From c2d11da93cc0a75caff50fbb4508eea8f3812167 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Mon, 10 Feb 2025 08:19:20 +0100 Subject: [PATCH 1/6] Support keycloak custom format via configuration (cherry picked from commit 1179d3a3ecc7e252510ee10b66f7fc3e4ba8c37b) --- deps/rabbitmq_auth_backend_oauth2/app.bzl | 3 - .../src/rabbit_auth_backend_oauth2.erl | 192 ++++++++++++------ .../src/rabbit_oauth2_keycloak.erl | 41 ---- .../src/rabbit_oauth2_rar.erl | 12 +- .../src/rabbit_oauth2_scope.erl | 1 + .../rabbitmq_auth_backend_oauth2.snippets | 10 + .../test/unit_SUITE.erl | 150 +++++++++++++- 7 files changed, 291 insertions(+), 118 deletions(-) delete mode 100644 deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_keycloak.erl diff --git a/deps/rabbitmq_auth_backend_oauth2/app.bzl b/deps/rabbitmq_auth_backend_oauth2/app.bzl index 5d18fb9ae2e4..a503e4b3544f 100644 --- a/deps/rabbitmq_auth_backend_oauth2/app.bzl +++ b/deps/rabbitmq_auth_backend_oauth2/app.bzl @@ -13,7 +13,6 @@ def all_beam_files(name = "all_beam_files"): "src/Elixir.RabbitMQ.CLI.Ctl.Commands.AddUaaKeyCommand.erl", "src/rabbit_auth_backend_oauth2.erl", "src/rabbit_auth_backend_oauth2_app.erl", - "src/rabbit_oauth2_keycloak.erl", "src/rabbit_oauth2_provider.erl", "src/rabbit_oauth2_rar.erl", "src/rabbit_oauth2_resource_server.erl", @@ -51,7 +50,6 @@ def all_test_beam_files(name = "all_test_beam_files"): "src/Elixir.RabbitMQ.CLI.Ctl.Commands.AddUaaKeyCommand.erl", "src/rabbit_auth_backend_oauth2.erl", "src/rabbit_auth_backend_oauth2_app.erl", - "src/rabbit_oauth2_keycloak.erl", "src/rabbit_oauth2_provider.erl", "src/rabbit_oauth2_rar.erl", "src/rabbit_oauth2_resource_server.erl", @@ -101,7 +99,6 @@ def all_srcs(name = "all_srcs"): "src/Elixir.RabbitMQ.CLI.Ctl.Commands.AddUaaKeyCommand.erl", "src/rabbit_auth_backend_oauth2.erl", "src/rabbit_auth_backend_oauth2_app.erl", - "src/rabbit_oauth2_keycloak.erl", "src/rabbit_oauth2_provider.erl", "src/rabbit_oauth2_rar.erl", "src/rabbit_oauth2_resource_server.erl", diff --git a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl index df5ea8548d04..844224f6a311 100644 --- a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl +++ b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl @@ -28,8 +28,7 @@ get_scope/1, set_scope/2, resolve_resource_server/1]). --import(rabbit_oauth2_keycloak, [has_keycloak_scopes/1, extract_scopes_from_keycloak_format/1]). --import(rabbit_oauth2_rar, [extract_scopes_from_rich_auth_request/2, has_rich_auth_request_scopes/1]). +-import(rabbit_oauth2_rar, [extract_scopes_from_rich_auth_request/2]). -import(rabbit_oauth2_scope, [filter_matching_scope_prefix_and_drop_it/2]). @@ -229,79 +228,142 @@ check_token(Token, {ResourceServer, InternalOAuthProvider}) -> {false, _} -> {refused, signature_invalid} end. +extract_scopes_from_scope_claim(Payload) -> + case maps:find(?SCOPE_JWT_FIELD, Payload) of + {ok, Bin} when is_binary(Bin) -> + maps:put(?SCOPE_JWT_FIELD, + binary:split(Bin, <<" ">>, [global, trim_all]), + Payload); + _ -> Payload + end. + -spec normalize_token_scope( ResourceServer :: resource_server(), DecodedToken :: decoded_jwt_token()) -> map(). normalize_token_scope(ResourceServer, Payload) -> - Payload0 = maps:map(fun(K, V) -> - case K of - ?SCOPE_JWT_FIELD when is_binary(V) -> - binary:split(V, <<" ">>, [global, trim_all]); - _ -> V - end - end, Payload), - - Payload1 = case has_additional_scopes_key(ResourceServer, Payload0) of - true -> extract_scopes_from_additional_scopes_key(ResourceServer, Payload0); - false -> Payload0 - end, - - Payload2 = case has_keycloak_scopes(Payload1) of - true -> extract_scopes_from_keycloak_format(Payload1); - false -> Payload1 - end, - - Payload3 = case ResourceServer#resource_server.scope_aliases of - undefined -> Payload2; - ScopeAliases -> extract_scopes_using_scope_aliases(ScopeAliases, Payload2) - end, - - Payload4 = case has_rich_auth_request_scopes(Payload3) of - true -> extract_scopes_from_rich_auth_request(ResourceServer, Payload3); - false -> Payload3 - end, + + Payload1 = extract_scopes_from_rich_auth_request(ResourceServer, + extract_scopes_using_scope_aliases(ResourceServer, + extract_scopes_from_additional_scopes_key(ResourceServer, + extract_scopes_from_scope_claim(Payload)))), FilteredScopes = filter_matching_scope_prefix_and_drop_it( - get_scope(Payload4), ResourceServer#resource_server.scope_prefix), - set_scope(FilteredScopes, Payload4). - + get_scope(Payload1), ResourceServer#resource_server.scope_prefix), + set_scope(FilteredScopes, Payload1). -spec extract_scopes_using_scope_aliases( - ScopeAliasMapping :: map(), Payload :: map()) -> map(). -extract_scopes_using_scope_aliases(ScopeAliasMapping, Payload) -> - Scopes0 = get_scope(Payload), - Scopes = rabbit_data_coercion:to_list_of_binaries(Scopes0), - %% for all scopes, look them up in the scope alias map, and if they are - %% present, add the alias to the final scope list. Note that we also preserve - %% the original scopes, it should not hurt. - ExpandedScopes = - lists:foldl(fun(ScopeListItem, Acc) -> - case maps:get(ScopeListItem, ScopeAliasMapping, undefined) of - undefined -> - Acc; - MappedList when is_list(MappedList) -> - Binaries = rabbit_data_coercion:to_list_of_binaries(MappedList), - Acc ++ Binaries; - Value -> - Binaries = rabbit_data_coercion:to_list_of_binaries(Value), - Acc ++ Binaries - end - end, Scopes, Scopes), - set_scope(ExpandedScopes, Payload). - --spec has_additional_scopes_key( - ResourceServer :: resource_server(), Payload :: map()) -> boolean(). -has_additional_scopes_key(ResourceServer, Payload) when is_map(Payload) -> - case ResourceServer#resource_server.additional_scopes_key of - undefined -> false; - ScopeKey -> maps:is_key(ScopeKey, Payload) - end. + ResourceServer :: resource_server(), Payload :: map()) -> map(). +extract_scopes_using_scope_aliases( + #resource_server{scope_aliases = ScopeAliasMapping}, Payload) + when is_map(ScopeAliasMapping) -> + Scopes0 = get_scope(Payload), + Scopes = rabbit_data_coercion:to_list_of_binaries(Scopes0), + %% for all scopes, look them up in the scope alias map, and if they are + %% present, add the alias to the final scope list. Note that we also preserve + %% the original scopes, it should not hurt. + ExpandedScopes = + lists:foldl(fun(ScopeListItem, Acc) -> + case maps:get(ScopeListItem, ScopeAliasMapping, undefined) of + undefined -> + Acc; + MappedList when is_list(MappedList) -> + Binaries = rabbit_data_coercion:to_list_of_binaries(MappedList), + Acc ++ Binaries; + Value -> + Binaries = rabbit_data_coercion:to_list_of_binaries(Value), + Acc ++ Binaries + end + end, Scopes, Scopes), + set_scope(ExpandedScopes, Payload); +extract_scopes_using_scope_aliases(_, Payload) -> Payload. + +%% Path is a binary expression which is a plain word like <<"roles">> +%% or +1 word separated by . like <<"authorization.permissions.scopes">> +%% The Payload is a map. +%% Using the path <<"authorization.permissions.scopes">> as an example +%% 1. lookup the key <<"authorization">> in the Payload +%% 2. if it is found, the next map to use as payload is the value found from the key <<"authorization">> +%% 3. lookup the key <<"permissions">> in the previous map +%% 4. if it is found, it may be a map or a list of maps. +%% 5. if it is a list of maps, iterate each element in the list +%% 6. for each element in the list, which should be a map, find the key <<"scopes">> +%% 7. because there are no more words/keys, return a list of all the values found +%% associated to the word <<"scopes">> +extract_token_value(R, Payload, Path, ValueMapperFun) + when is_map(Payload), is_binary(Path), is_function(ValueMapperFun) -> + extract_token_value_from_map(R, Payload, [], split_path(Path), ValueMapperFun); +extract_token_value(_, _, _, _) -> + []. + +extract_scope_list_from_token_value(_R, List) when is_list(List) -> List; +extract_scope_list_from_token_value(_R, Binary) when is_binary(Binary) -> + binary:split(Binary, <<" ">>, [global, trim_all]); +extract_scope_list_from_token_value(#resource_server{id = ResourceServerId}, Map) when is_map(Map) -> + case maps:get(ResourceServerId, Map, undefined) of + undefined -> []; + Ks when is_list(Ks) -> + [erlang:iolist_to_binary([ResourceServerId, <<".">>, K]) || K <- Ks]; + ClaimBin when is_binary(ClaimBin) -> + UnprefixedClaims = binary:split(ClaimBin, <<" ">>, [global, trim_all]), + [erlang:iolist_to_binary([ResourceServerId, <<".">>, K]) || K <- UnprefixedClaims]; + _ -> [] + end; +extract_scope_list_from_token_value(_, _) -> []. + +extract_token_value_from_map(_, _Map, Acc, [], _Mapper) -> + Acc; +extract_token_value_from_map(R, Map, Acc, [KeyStr], Mapper) when is_map(Map) -> + case maps:find(KeyStr, Map) of + {ok, Value} -> Acc ++ Mapper(R, Value); + error -> Acc + end; +extract_token_value_from_map(R, Map, Acc, [KeyStr | Rest], Mapper) when is_map(Map) -> + case maps:find(KeyStr, Map) of + {ok, M} when is_map(M) -> extract_token_value_from_map(R, M, Acc, Rest, Mapper); + {ok, L} when is_list(L) -> extract_token_value_from_list(R, L, Acc, Rest, Mapper); + {ok, Value} when Rest =:= [] -> Acc ++ Mapper(R, Value); + _ -> Acc + end; +extract_token_value_from_map(_, _, Acc, _, _Mapper) -> + Acc. + +extract_token_value_from_list(_, [], Acc, [], _Mapper) -> + Acc; +extract_token_value_from_list(_, [], Acc, [_KeyStr | _Rest], _Mapper) -> + Acc; +extract_token_value_from_list(R, [H | T], Acc, [KeyStr | Rest] = KeyList, Mapper) when is_map(H) -> + NewAcc = case maps:find(KeyStr, H) of + {ok, Map} when is_map(Map) -> extract_token_value_from_map(R, Map, Acc, Rest, Mapper); + {ok, List} when is_list(List) -> extract_token_value_from_list(R, List, Acc, Rest, Mapper); + {ok, Value} -> Acc++Mapper(R, Value); + _ -> Acc + end, + extract_token_value_from_list(R, T, NewAcc, KeyList, Mapper); + +extract_token_value_from_list(R, [E | T], Acc, [], Mapper) -> + extract_token_value_from_list(R, T, Acc++Mapper(R, E), [], Mapper); +extract_token_value_from_list(R, [E | _T] = L, Acc, KeyList, Mapper) when is_map(E) -> + extract_token_value_from_list(R, L, Acc, KeyList, Mapper); +extract_token_value_from_list(R, [_ | T], Acc, KeyList, Mapper) -> + extract_token_value_from_list(R, T, Acc, KeyList, Mapper). + + +split_path(Path) when is_binary(Path) -> + binary:split(Path, <<".">>, [global, trim_all]). + -spec extract_scopes_from_additional_scopes_key( ResourceServer :: resource_server(), Payload :: map()) -> map(). -extract_scopes_from_additional_scopes_key(ResourceServer, Payload) -> - Claim = maps:get(ResourceServer#resource_server.additional_scopes_key, Payload), - AdditionalScopes = extract_additional_scopes(ResourceServer, Claim), - set_scope(AdditionalScopes ++ get_scope(Payload), Payload). +extract_scopes_from_additional_scopes_key( + #resource_server{additional_scopes_key = Key} = ResourceServer, Payload) + when is_list(Key) or is_binary(Key) -> + Paths = case Key of + B when is_binary(B) -> binary:split(B, <<" ">>, [global, trim_all]); + L when is_list(L) -> L + end, + AdditionalScopes = [ extract_token_value(ResourceServer, + Payload, Path, fun extract_scope_list_from_token_value/2) || Path <- Paths], + set_scope(lists:flatten(AdditionalScopes) ++ get_scope(Payload), Payload); +extract_scopes_from_additional_scopes_key(_, Payload) -> Payload. extract_additional_scopes(ResourceServer, ComplexClaim) -> ResourceServerId = ResourceServer#resource_server.id, diff --git a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_keycloak.erl b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_keycloak.erl deleted file mode 100644 index e75910e48055..000000000000 --- a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_keycloak.erl +++ /dev/null @@ -1,41 +0,0 @@ -%% This Source Code Form is subject to the terms of the Mozilla Public -%% License, v. 2.0. If a copy of the MPL was not distributed with this -%% file, You can obtain one at https://mozilla.org/MPL/2.0/. -%% -%% Copyright (c) 2007-2025 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved. -%% - --module(rabbit_oauth2_keycloak). - --include("oauth2.hrl"). - --export([extract_scopes_from_keycloak_format/1, has_keycloak_scopes/1]). --import(uaa_jwt, [get_scope/1, set_scope/2]). - --define(AUTHORIZATION_CLAIM, <<"authorization">>). --define(PERMISSIONS_CLAIM, <<"permissions">>). --define(SCOPES_CLAIM, <<"scopes">>). - --spec has_keycloak_scopes(Payload::map()) -> boolean(). -has_keycloak_scopes(Payload) -> - maps:is_key(?AUTHORIZATION_CLAIM, Payload). - --spec extract_scopes_from_keycloak_format(Payload :: map()) -> map(). -%% keycloak token format: https://github.com/rabbitmq/rabbitmq-auth-backend-oauth2/issues/36 -extract_scopes_from_keycloak_format(#{?AUTHORIZATION_CLAIM := Authorization} = Payload) -> - AdditionalScopes = extract_scopes_from_keycloak_permissions([], - maps:get(?PERMISSIONS_CLAIM, Authorization, [])), - set_scope(AdditionalScopes ++ get_scope(Payload), Payload). - -extract_scopes_from_keycloak_permissions(Acc, []) -> - Acc; -extract_scopes_from_keycloak_permissions(Acc, [H | T]) when is_map(H) -> - Scopes = case maps:get(?SCOPES_CLAIM, H, []) of - ScopesAsList when is_list(ScopesAsList) -> - ScopesAsList; - ScopesAsBinary when is_binary(ScopesAsBinary) -> - [ScopesAsBinary] - end, - extract_scopes_from_keycloak_permissions(Acc ++ Scopes, T); -extract_scopes_from_keycloak_permissions(Acc, [_ | T]) -> - extract_scopes_from_keycloak_permissions(Acc, T). diff --git a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_rar.erl b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_rar.erl index 9d7a583fa4c1..5e71c81dd7d8 100644 --- a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_rar.erl +++ b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_rar.erl @@ -11,7 +11,7 @@ -include("oauth2.hrl"). -import(uaa_jwt, [get_scope/1, set_scope/2]). --export([extract_scopes_from_rich_auth_request/2, has_rich_auth_request_scopes/1]). +-export([extract_scopes_from_rich_auth_request/2]). -define(AUTHORIZATION_DETAILS_CLAIM, <<"authorization_details">>). -define(RAR_ACTIONS_FIELD, <<"actions">>). @@ -44,15 +44,12 @@ <<"management">>, <<"policymaker">> ]). --spec has_rich_auth_request_scopes(Payload::map()) -> boolean(). -has_rich_auth_request_scopes(Payload) -> - maps:is_key(?AUTHORIZATION_DETAILS_CLAIM, Payload). - -spec extract_scopes_from_rich_auth_request(ResourceServer :: resource_server(), Payload :: map()) -> map(). %% https://oauth.net/2/rich-authorization-requests/ extract_scopes_from_rich_auth_request(ResourceServer, - #{?AUTHORIZATION_DETAILS_CLAIM := Permissions} = Payload) -> + #{?AUTHORIZATION_DETAILS_CLAIM := Permissions} = Payload) + when is_list(Permissions) -> ResourceServerType = ResourceServer#resource_server.resource_server_type, FilteredPermissionsByType = lists:filter(fun(P) -> @@ -61,7 +58,8 @@ extract_scopes_from_rich_auth_request(ResourceServer, ResourceServer#resource_server.id, FilteredPermissionsByType), ExistingScopes = get_scope(Payload), - set_scope(AdditionalScopes ++ ExistingScopes, Payload). + set_scope(AdditionalScopes ++ ExistingScopes, Payload); +extract_scopes_from_rich_auth_request(_, Payload) -> Payload. put_location_attribute(Attribute, Map) -> put_attribute(binary:split(Attribute, <<":">>, [global, trim_all]), Map). diff --git a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl index 7391c9e3857b..2f4425dc59d8 100644 --- a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl +++ b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl @@ -96,6 +96,7 @@ parse_resource_pattern(Pattern, Permission) -> -spec filter_matching_scope_prefix_and_drop_it(list(), binary()|list()) -> list(). filter_matching_scope_prefix_and_drop_it(Scopes, <<"">>) -> Scopes; filter_matching_scope_prefix_and_drop_it(Scopes, PrefixPattern) -> + PatternLength = byte_size(PrefixPattern), lists:filtermap( fun(ScopeEl) -> diff --git a/deps/rabbitmq_auth_backend_oauth2/test/config_schema_SUITE_data/rabbitmq_auth_backend_oauth2.snippets b/deps/rabbitmq_auth_backend_oauth2/test/config_schema_SUITE_data/rabbitmq_auth_backend_oauth2.snippets index 7b6b148b5944..4db415c113a3 100644 --- a/deps/rabbitmq_auth_backend_oauth2/test/config_schema_SUITE_data/rabbitmq_auth_backend_oauth2.snippets +++ b/deps/rabbitmq_auth_backend_oauth2/test/config_schema_SUITE_data/rabbitmq_auth_backend_oauth2.snippets @@ -316,5 +316,15 @@ } ]} ], [] + }, + {additional_scopes_key, + "auth_oauth2.resource_server_id = new_resource_server_id + auth_oauth2.additional_scopes_key = roles realm.roles", + [ + {rabbitmq_auth_backend_oauth2, [ + {resource_server_id,<<"new_resource_server_id">>}, + {extra_scopes_source, <<"roles realm.roles">> } + ]} + ], [] } ]. diff --git a/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl b/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl index 5dedc8cefc85..3d6ac45799da 100644 --- a/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl +++ b/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl @@ -17,13 +17,16 @@ user_login_authentication/2, user_login_authorization/2, normalize_token_scope/2, - check_vhost_access/3]). + check_vhost_access/3, + extract_token_value/4, + extract_scope_list_from_token_value/2]). -import(rabbit_oauth2_resource_server, [ new_resource_server/1 ]). all() -> [ + test_extract_scope_from_path_expression, filter_matching_scope_prefix_and_drop_it, normalize_token_scopes_with_scope_prefix, normalize_token_scope_from_space_separated_list_in_scope_claim, @@ -39,6 +42,7 @@ all() -> test_token_expiration, test_invalid_signature, test_incorrect_kid, + normalize_token_scope_using_multiple_scopes_key, normalize_token_scope_with_keycloak_scopes, normalize_token_scope_with_rich_auth_request, normalize_token_scope_with_rich_auth_request_using_regular_expression_with_cluster, @@ -46,6 +50,7 @@ all() -> test_unsuccessful_access_with_a_token_that_uses_missing_scope_alias_in_extra_scope_source_field, test_username_from, {group, with_rabbitmq_node} + ]. groups() -> [ @@ -116,6 +121,73 @@ end_per_group(_, Config) -> -define(RESOURCE_SERVER_TYPE, <<"rabbitmq-type">>). -define(DEFAULT_SCOPE_PREFIX, <<"rabbitmq.">>). +normalize_token_scope_using_multiple_scopes_key(_) -> + Pairs = [ + %% common case + { + "keycloak format 1", + #{<<"authorization">> => + #{<<"permissions">> => + [#{<<"rsid">> => <<"2c390fe4-02ad-41c7-98a2-cebb8c60ccf1">>, + <<"rsname">> => <<"allvhost">>, + <<"scopes">> => [<<"rabbitmq-resource.read:*/*">>]}, + #{<<"rsid">> => <<"e7f12e94-4c34-43d8-b2b1-c516af644cee">>, + <<"rsname">> => <<"vhost1">>, + <<"scopes">> => [<<"rabbitmq-resource.write:vhost1/*">>]}, + #{<<"rsid">> => <<"12ac3d1c-28c2-4521-8e33-0952eff10bd9">>, + <<"rsname">> => <<"Default Resource">>, + <<"scopes">> => [<<"unknown-resource.write:vhost1/*">>]} + ] + } + }, + [<<"read:*/*">>, <<"write:vhost1/*">>] + }, + { + "keycloak format 2 using realm_access", + #{<<"realm_access">> => + #{<<"roles">> => [<<"rabbitmq-resource.read:format2/*">>]} + }, + [<<"read:format2/*">>] + }, + { + "keycloak format 2 using resource_access", + #{<<"resource_access">> => + #{<<"account">> => #{<<"roles">> => [<<"rabbitmq-resource.read:format2bis/*">>]} } + }, + [<<"read:format2bis/*">>] + }, + { + "both formats", + #{<<"authorization">> => + #{<<"permissions">> => + [#{<<"rsid">> => <<"2c390fe4-02ad-41c7-98a2-cebb8c60ccf1">>, + <<"rsname">> => <<"allvhost">>, + <<"scopes">> => [<<"rabbitmq-resource.read:*/*">>]}, + #{<<"rsid">> => <<"e7f12e94-4c34-43d8-b2b1-c516af644cee">>, + <<"rsname">> => <<"vhost1">>, + <<"scopes">> => [<<"rabbitmq-resource.write:vhost1/*">>]}, + #{<<"rsid">> => <<"12ac3d1c-28c2-4521-8e33-0952eff10bd9">>, + <<"rsname">> => <<"Default Resource">>, + <<"scopes">> => [<<"unknown-resource.write:vhost1/*">>]} + ] + }, + <<"realm_access">> => + #{<<"roles">> => [<<"rabbitmq-resource.read:format2/*">>]}, + <<"resource_access">> => + #{<<"account">> => #{<<"roles">> => [<<"rabbitmq-resource.read:format2bis/*">>]} } + }, + [<<"read:*/*">>, <<"write:vhost1/*">>, <<"read:format2/*">>, <<"read:format2bis/*">>] + } + ], + + lists:foreach(fun({Case, Token0, ExpectedScope}) -> + ResourceServer0 = new_resource_server(<<"rabbitmq-resource">>), + ResourceServer = ResourceServer0#resource_server{ + additional_scopes_key = <<"authorization.permissions.scopes realm_access.roles resource_access.account.roles">> + }, + Token = normalize_token_scope(ResourceServer, Token0), + ?assertEqual(ExpectedScope, uaa_jwt:get_scope(Token), Case) + end, Pairs). normalize_token_scope_with_keycloak_scopes(_) -> Pairs = [ @@ -169,7 +241,10 @@ normalize_token_scope_with_keycloak_scopes(_) -> ], lists:foreach(fun({Case, Authorization, ExpectedScope}) -> - ResourceServer = new_resource_server(<<"rabbitmq-resource">>), + ResourceServer0 = new_resource_server(<<"rabbitmq-resource">>), + ResourceServer = ResourceServer0#resource_server{ + additional_scopes_key = <<"authorization.permissions.scopes">> + }, Token0 = #{<<"authorization">> => Authorization}, Token = normalize_token_scope(ResourceServer, Token0), ?assertEqual(ExpectedScope, uaa_jwt:get_scope(Token), Case) @@ -1286,6 +1361,77 @@ normalize_token_scope_without_scope_claim(_) -> Token0 = #{ }, ?assertEqual([], uaa_jwt:get_scope(normalize_token_scope(ResourceServer, Token0))). + +test_extract_scope_from_path_expression(_) -> + M = fun rabbit_auth_backend_oauth2:extract_scope_list_from_token_value/2, + R = #resource_server{id = <<"rabbitmq">>}, + + [<<"role1">>] = extract_token_value(R, + #{ <<"auth">> => #{ <<"permission">> => <<"role1">> }}, + <<"auth.permission">>, M), + [<<"role1">>,<<"role2">>] = extract_token_value(R, + #{ <<"auth">> => #{ <<"permission">> => [<<"role1">>,<<"role2">>] }}, + <<"auth.permission">>, M), + [<<"role1">>,<<"role2">>] = extract_token_value(R, + #{ <<"auth">> => #{ <<"permission">> => <<"role1 role2">> }}, + <<"auth.permission">>, M), + [<<"rabbitmq.role1">>,<<"rabbitmq.role2">>] = extract_token_value(R, + #{ <<"auth">> => #{ + <<"rabbitmq">> => [<<"role1">>,<<"role2">>] + }}, + <<"auth">>, M), + [<<"rabbitmq.role1">>,<<"rabbitmq.role2">>] = extract_token_value(R, + #{ <<"auth">> => #{ + <<"rabbitmq">> => <<"role1 role2">> + }}, + <<"auth">>, M), + %% this is the old keycloak format + [<<"role1">>,<<"role2">>] = extract_token_value(R, + #{ <<"auth">> => #{ + <<"permission">> => [ + #{ <<"scopes">> => <<"role1">>}, + #{ <<"scopes">> => <<"role2">>} + ] + }}, + <<"auth.permission.scopes">>, M), + + [<<"role1">>,<<"role2">>] = extract_token_value(R, + #{ <<"auth">> => #{ + <<"permission">> => [ + #{ <<"scopes">> => [<<"role1">>]}, + #{ <<"scopes">> => [<<"role2">>]} + ] + }}, + <<"auth.permission.scopes">>, M), + + [<<"role1">>,<<"role2">>] = extract_token_value(R, + #{ <<"auth">> => [ + #{ <<"permission">> => [ + #{ <<"scopes">> => [<<"role1">>]} + ]}, + #{ <<"permission">> => [ + #{ <<"scopes">> => [<<"role2">>]} + ]} + ]}, + <<"auth.permission.scopes">>, M), + + [<<"role1">>] = extract_token_value(R, + #{ <<"auth">> => #{ <<"permission">> => [<<"role1">>] }}, + <<"auth.permission">>, M), + + [] = extract_token_value(R, + #{ <<"auth">> => #{ <<"permission">> => [<<"role1">>] }}, + <<"auth.permission2">>, M), + + [] = extract_token_value(R, + #{ <<"auth">> => #{ <<"permission">> => [<<"role1">>] }}, + <<"auth2.permission">>, M), + + [] = extract_token_value(R, + #{ <<"auth">> => #{ <<"permission">> => [<<"role1">>] }}, + <<"auth.permission2">>, M). + + %% %% Helpers %% From 467ddcde67fbf380338ebf91a85d291accba473c Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Mon, 10 Feb 2025 13:44:48 +0100 Subject: [PATCH 2/6] Support in code the old keycloak format That was not keycloak format it was an extension to the oauth spec introuduced a few years ago. To get a token from keycloak using this format, a.k.a. requesting party token, one has to specify a different claim type called urn:ietf:params:oauth:grant-type:uma-ticket (cherry picked from commit 3041d6c25376f9a9bc3802f414a97199e87fbedf) --- .../include/oauth2.hrl | 8 +++ .../src/rabbit_auth_backend_oauth2.erl | 67 +++++++++---------- .../src/rabbit_oauth2_scope.erl | 17 ++++- .../test/unit_SUITE.erl | 17 ++--- 4 files changed, 60 insertions(+), 49 deletions(-) diff --git a/deps/rabbitmq_auth_backend_oauth2/include/oauth2.hrl b/deps/rabbitmq_auth_backend_oauth2/include/oauth2.hrl index 4652c16ddcd1..e7792e49298b 100644 --- a/deps/rabbitmq_auth_backend_oauth2/include/oauth2.hrl +++ b/deps/rabbitmq_auth_backend_oauth2/include/oauth2.hrl @@ -22,6 +22,14 @@ %% End of Key JWT fields +%% UMA claim-type returns a RPT which is a token +%% where scopes are located under a map of list of objects which have +%% the scopes in the "scopes" attribute +%% Used by Keycloak, WSO2 and others. +%% https://en.wikipedia.org/wiki/User-Managed_Access#cite_note-docs.wso2.com-19 +-define(SCOPES_LOCATION_IN_REQUESTING_PARTY_TOKEN, <<"authorization.permissions.scopes">>). + + -type raw_jwt_token() :: binary() | #{binary() => any()}. -type decoded_jwt_token() :: #{binary() => any()}. diff --git a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl index 844224f6a311..1b9743848fd1 100644 --- a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl +++ b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl @@ -30,7 +30,9 @@ -import(rabbit_oauth2_rar, [extract_scopes_from_rich_auth_request/2]). --import(rabbit_oauth2_scope, [filter_matching_scope_prefix_and_drop_it/2]). +-import(rabbit_oauth2_scope, [ + filter_matching_scope_prefix/2, + filter_matching_scope_prefix_and_drop_it/2]). -ifdef(TEST). -compile(export_all). @@ -240,15 +242,30 @@ extract_scopes_from_scope_claim(Payload) -> -spec normalize_token_scope( ResourceServer :: resource_server(), DecodedToken :: decoded_jwt_token()) -> map(). normalize_token_scope(ResourceServer, Payload) -> - - Payload1 = extract_scopes_from_rich_auth_request(ResourceServer, - extract_scopes_using_scope_aliases(ResourceServer, - extract_scopes_from_additional_scopes_key(ResourceServer, - extract_scopes_from_scope_claim(Payload)))), - FilteredScopes = filter_matching_scope_prefix_and_drop_it( - get_scope(Payload1), ResourceServer#resource_server.scope_prefix), - set_scope(FilteredScopes, Payload1). + filter_duplicates( + filter_matching_scope_prefix(ResourceServer, + extract_scopes_from_rich_auth_request(ResourceServer, + extract_scopes_using_scope_aliases(ResourceServer, + extract_scopes_from_additional_scopes_key(ResourceServer, + extract_scopes_from_requesting_party_token(ResourceServer, + extract_scopes_from_scope_claim(Payload))))))). + +filter_duplicates(#{?SCOPE_JWT_FIELD := Scopes} = Payload) -> + set_scope(lists:usort(Scopes), Payload); +filter_duplicates(Payload) -> Payload. + +-spec extract_scopes_from_requesting_party_token( + ResourceServer :: resource_server(), DecodedToken :: decoded_jwt_token()) -> map(). +extract_scopes_from_requesting_party_token(ResourceServer, Payload) -> + Path = ?SCOPES_LOCATION_IN_REQUESTING_PARTY_TOKEN, + case extract_token_value(ResourceServer, Payload, Path, + fun extract_scope_list_from_token_value/2) of + [] -> + Payload; + AdditionalScopes -> + set_scope(lists:flatten(AdditionalScopes) ++ get_scope(Payload), Payload) + end. -spec extract_scopes_using_scope_aliases( ResourceServer :: resource_server(), Payload :: map()) -> map(). @@ -322,9 +339,9 @@ extract_token_value_from_map(R, Map, Acc, [KeyStr | Rest], Mapper) when is_map(M {ok, L} when is_list(L) -> extract_token_value_from_list(R, L, Acc, Rest, Mapper); {ok, Value} when Rest =:= [] -> Acc ++ Mapper(R, Value); _ -> Acc - end; -extract_token_value_from_map(_, _, Acc, _, _Mapper) -> - Acc. + end. +%extract_token_value_from_map(_, _, Acc, _, _Mapper) -> +% Acc. extract_token_value_from_list(_, [], Acc, [], _Mapper) -> Acc; @@ -355,35 +372,13 @@ split_path(Path) when is_binary(Path) -> ResourceServer :: resource_server(), Payload :: map()) -> map(). extract_scopes_from_additional_scopes_key( #resource_server{additional_scopes_key = Key} = ResourceServer, Payload) - when is_list(Key) or is_binary(Key) -> - Paths = case Key of - B when is_binary(B) -> binary:split(B, <<" ">>, [global, trim_all]); - L when is_list(L) -> L - end, + when is_binary(Key) -> + Paths = binary:split(Key, <<" ">>, [global, trim_all]), AdditionalScopes = [ extract_token_value(ResourceServer, Payload, Path, fun extract_scope_list_from_token_value/2) || Path <- Paths], set_scope(lists:flatten(AdditionalScopes) ++ get_scope(Payload), Payload); extract_scopes_from_additional_scopes_key(_, Payload) -> Payload. -extract_additional_scopes(ResourceServer, ComplexClaim) -> - ResourceServerId = ResourceServer#resource_server.id, - case ComplexClaim of - L when is_list(L) -> L; - M when is_map(M) -> - case maps:get(ResourceServerId, M, undefined) of - undefined -> []; - Ks when is_list(Ks) -> - [erlang:iolist_to_binary([ResourceServerId, <<".">>, K]) || K <- Ks]; - ClaimBin when is_binary(ClaimBin) -> - UnprefixedClaims = binary:split(ClaimBin, <<" ">>, [global, trim_all]), - [erlang:iolist_to_binary([ResourceServerId, <<".">>, K]) || K <- UnprefixedClaims]; - _ -> [] - end; - Bin when is_binary(Bin) -> - binary:split(Bin, <<" ">>, [global, trim_all]); - _ -> [] - end. - %% A token may be present in the password credential or in the rabbit_auth_backend_oauth2 %% credential. The former is the most common scenario for the first time authentication. diff --git a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl index 2f4425dc59d8..93bbc32dfa04 100644 --- a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl +++ b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl @@ -7,10 +7,13 @@ -module(rabbit_oauth2_scope). +-include("oauth2.hrl"). + -export([vhost_access/2, resource_access/3, topic_access/4, concat_scopes/2, + filter_matching_scope_prefix/2, filter_matching_scope_prefix_and_drop_it/2]). -include_lib("rabbit_common/include/rabbit.hrl"). @@ -93,10 +96,18 @@ parse_resource_pattern(Pattern, Permission) -> _Other -> ignore end. +-spec filter_matching_scope_prefix(ResourceServer :: resource_server(), + Payload :: map()) -> map(). +filter_matching_scope_prefix( + #resource_server{scope_prefix = ScopePrefix}, + #{?SCOPE_JWT_FIELD := Scopes} = Payload) -> + Payload#{?SCOPE_JWT_FIELD := + filter_matching_scope_prefix_and_drop_it(Scopes, ScopePrefix)}; +filter_matching_scope_prefix(_, Payload) -> Payload. + -spec filter_matching_scope_prefix_and_drop_it(list(), binary()|list()) -> list(). -filter_matching_scope_prefix_and_drop_it(Scopes, <<"">>) -> Scopes; -filter_matching_scope_prefix_and_drop_it(Scopes, PrefixPattern) -> - +filter_matching_scope_prefix_and_drop_it(Scopes, <<>>) -> Scopes; +filter_matching_scope_prefix_and_drop_it(Scopes, PrefixPattern) -> PatternLength = byte_size(PrefixPattern), lists:filtermap( fun(ScopeEl) -> diff --git a/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl b/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl index 3d6ac45799da..d920db3ec05e 100644 --- a/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl +++ b/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl @@ -43,7 +43,7 @@ all() -> test_invalid_signature, test_incorrect_kid, normalize_token_scope_using_multiple_scopes_key, - normalize_token_scope_with_keycloak_scopes, + normalize_token_scope_with_requesting_party_token_scopes, normalize_token_scope_with_rich_auth_request, normalize_token_scope_with_rich_auth_request_using_regular_expression_with_cluster, test_unsuccessful_access_with_a_token_that_uses_missing_scope_alias_in_scope_field, @@ -125,7 +125,7 @@ normalize_token_scope_using_multiple_scopes_key(_) -> Pairs = [ %% common case { - "keycloak format 1", + "keycloak format 1, i.e. requesting party token", #{<<"authorization">> => #{<<"permissions">> => [#{<<"rsid">> => <<"2c390fe4-02ad-41c7-98a2-cebb8c60ccf1">>, @@ -186,10 +186,10 @@ normalize_token_scope_using_multiple_scopes_key(_) -> additional_scopes_key = <<"authorization.permissions.scopes realm_access.roles resource_access.account.roles">> }, Token = normalize_token_scope(ResourceServer, Token0), - ?assertEqual(ExpectedScope, uaa_jwt:get_scope(Token), Case) + ?assertEqual(lists:sort(ExpectedScope), lists:sort(uaa_jwt:get_scope(Token)), Case) end, Pairs). -normalize_token_scope_with_keycloak_scopes(_) -> +normalize_token_scope_with_requesting_party_token_scopes(_) -> Pairs = [ %% common case { @@ -241,12 +241,9 @@ normalize_token_scope_with_keycloak_scopes(_) -> ], lists:foreach(fun({Case, Authorization, ExpectedScope}) -> - ResourceServer0 = new_resource_server(<<"rabbitmq-resource">>), - ResourceServer = ResourceServer0#resource_server{ - additional_scopes_key = <<"authorization.permissions.scopes">> - }, + ResourceServer0 = new_resource_server(<<"rabbitmq-resource">>), Token0 = #{<<"authorization">> => Authorization}, - Token = normalize_token_scope(ResourceServer, Token0), + Token = normalize_token_scope(ResourceServer0, Token0), ?assertEqual(ExpectedScope, uaa_jwt:get_scope(Token), Case) end, Pairs). @@ -431,7 +428,7 @@ normalize_token_scope_with_rich_auth_request(_) -> } ], [<<"tag:management">>, <<"tag:policymaker">>, - <<"tag:management">>, <<"tag:monitoring">> ] + <<"tag:monitoring">> ] }, { "should produce a scope for every user tag action but only for the clusters that match {resource_server_id}", [ #{<<"type">> => ?RESOURCE_SERVER_TYPE, From dbf2dfa66bf3e388ab3fb0662a8803e4f838f4d3 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Tue, 11 Feb 2025 12:25:48 +0100 Subject: [PATCH 3/6] Clean up (cherry picked from commit ecacf0f19cf2b2f9d2a151243d1a1c428e092bde) --- .../src/rabbit_auth_backend_oauth2.erl | 2 -- deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl index 1b9743848fd1..133a566f177c 100644 --- a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl +++ b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl @@ -340,8 +340,6 @@ extract_token_value_from_map(R, Map, Acc, [KeyStr | Rest], Mapper) when is_map(M {ok, Value} when Rest =:= [] -> Acc ++ Mapper(R, Value); _ -> Acc end. -%extract_token_value_from_map(_, _, Acc, _, _Mapper) -> -% Acc. extract_token_value_from_list(_, [], Acc, [], _Mapper) -> Acc; diff --git a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl index 93bbc32dfa04..7e1efd24706f 100644 --- a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl +++ b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_oauth2_scope.erl @@ -106,8 +106,8 @@ filter_matching_scope_prefix( filter_matching_scope_prefix(_, Payload) -> Payload. -spec filter_matching_scope_prefix_and_drop_it(list(), binary()|list()) -> list(). -filter_matching_scope_prefix_and_drop_it(Scopes, <<>>) -> Scopes; -filter_matching_scope_prefix_and_drop_it(Scopes, PrefixPattern) -> +filter_matching_scope_prefix_and_drop_it(Scopes, <<>>) -> Scopes; +filter_matching_scope_prefix_and_drop_it(Scopes, PrefixPattern) -> PatternLength = byte_size(PrefixPattern), lists:filtermap( fun(ScopeEl) -> From cb3181cb4d29bd903e5ae65d8a7d3193e45cdddc Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Wed, 12 Feb 2025 09:52:34 +0100 Subject: [PATCH 4/6] Apply fix from PR #13180 (cherry picked from commit bf7de92aa4c8507fddb0c25cc5bffe09a923d9d3) # Conflicts: # deps/rabbitmq_mqtt/test/auth_SUITE.erl --- deps/rabbitmq_mqtt/test/auth_SUITE.erl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/deps/rabbitmq_mqtt/test/auth_SUITE.erl b/deps/rabbitmq_mqtt/test/auth_SUITE.erl index a7a4ea78f1d8..95479c71ae40 100644 --- a/deps/rabbitmq_mqtt/test/auth_SUITE.erl +++ b/deps/rabbitmq_mqtt/test/auth_SUITE.erl @@ -69,10 +69,17 @@ sub_groups() -> ssl_user_cert_vhost_mapping_takes_precedence_over_port_vhost_mapping ]}, {ssl_user_with_invalid_client_id_in_cert_san_dns, [], +<<<<<<< HEAD [invalid_client_id_from_cert_san_dns ]}, {ssl_user_with_client_id_in_cert_san_dns, [], [client_id_from_cert_san_dns +======= + [client_id_from_cert_san_dns + ]}, + {ssl_user_with_client_id_in_cert_san_dns, [], + [client_id_from_cert_san_dns +>>>>>>> bf7de92aa (Apply fix from PR #13180) ]}, {ssl_user_with_client_id_in_cert_san_dns_1, [], [client_id_from_cert_san_dns_1 @@ -209,8 +216,13 @@ mqtt_config(no_ssl_user) -> mqtt_config(client_id_propagation) -> {rabbitmq_mqtt, [{ssl_cert_login, true}, {allow_anonymous, true}]}; +<<<<<<< HEAD mqtt_config(T) when T == ssl_user_with_client_id_in_cert_san_dns; T == ssl_user_with_invalid_client_id_in_cert_san_dns -> +======= +mqtt_config(T) when T == ssl_user_with_invalid_client_id_in_cert_san_dns; + ssl_user_with_client_id_in_cert_san_dns -> +>>>>>>> bf7de92aa (Apply fix from PR #13180) {rabbitmq_mqtt, [{ssl_cert_login, true}, {allow_anonymous, false}, {ssl_cert_client_id_from, subject_alternative_name}, @@ -591,8 +603,13 @@ client_id_from_cert_dn(Config) -> invalid_client_id_from_cert_san_dns(Config) -> MqttClientId = <<"other_client_id">>, {ok, C} = connect_ssl(MqttClientId, Config), +<<<<<<< HEAD unlink(C), {error, {client_identifier_not_valid, _}} = emqtt:connect(C). +======= + {error, {client_identifier_not_valid, _}} = emqtt:connect(C), + unlink(C). +>>>>>>> bf7de92aa (Apply fix from PR #13180) ssl_user_vhost_parameter_mapping_success(Config) -> expect_successful_connection(fun connect_ssl/1, Config). From 3294f2e77354148518e94c211e29a550020fc0b6 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Wed, 12 Feb 2025 10:11:04 +0100 Subject: [PATCH 5/6] Fix test case name Fix test case nam# Por favor ingresa el mensaje del commit para tus cambios. Las (cherry picked from commit aeda3cada2454ffcd99389e7ef92aceff8fe794c) # Conflicts: # deps/rabbitmq_mqtt/test/auth_SUITE.erl --- deps/rabbitmq_mqtt/test/auth_SUITE.erl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deps/rabbitmq_mqtt/test/auth_SUITE.erl b/deps/rabbitmq_mqtt/test/auth_SUITE.erl index 95479c71ae40..fe160d83dfe9 100644 --- a/deps/rabbitmq_mqtt/test/auth_SUITE.erl +++ b/deps/rabbitmq_mqtt/test/auth_SUITE.erl @@ -69,6 +69,7 @@ sub_groups() -> ssl_user_cert_vhost_mapping_takes_precedence_over_port_vhost_mapping ]}, {ssl_user_with_invalid_client_id_in_cert_san_dns, [], +<<<<<<< HEAD <<<<<<< HEAD [invalid_client_id_from_cert_san_dns ]}, @@ -76,6 +77,9 @@ sub_groups() -> [client_id_from_cert_san_dns ======= [client_id_from_cert_san_dns +======= + [invalid_client_id_from_cert_san_dns +>>>>>>> aeda3cada (Fix test case name) ]}, {ssl_user_with_client_id_in_cert_san_dns, [], [client_id_from_cert_san_dns From e08aa4bd77b95ff674f3ea055398366329bb747b Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Wed, 12 Feb 2025 20:34:04 -0500 Subject: [PATCH 6/6] Resolve a conflict #13216 #12324 #13180 --- deps/rabbitmq_mqtt/test/auth_SUITE.erl | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/deps/rabbitmq_mqtt/test/auth_SUITE.erl b/deps/rabbitmq_mqtt/test/auth_SUITE.erl index fe160d83dfe9..f69d80a14c03 100644 --- a/deps/rabbitmq_mqtt/test/auth_SUITE.erl +++ b/deps/rabbitmq_mqtt/test/auth_SUITE.erl @@ -49,7 +49,7 @@ sub_groups() -> ssl_user_vhost_parameter_mapping_vhost_does_not_exist, ssl_user_cert_vhost_mapping_takes_precedence_over_port_vhost_mapping ]}, - {anonymous_no_ssl_user, [shuffle], + {anonymous_no_ssl_user, [shuffle], [anonymous_auth_success, user_credentials_auth, port_vhost_mapping_success, @@ -69,21 +69,10 @@ sub_groups() -> ssl_user_cert_vhost_mapping_takes_precedence_over_port_vhost_mapping ]}, {ssl_user_with_invalid_client_id_in_cert_san_dns, [], -<<<<<<< HEAD -<<<<<<< HEAD [invalid_client_id_from_cert_san_dns ]}, {ssl_user_with_client_id_in_cert_san_dns, [], - [client_id_from_cert_san_dns -======= [client_id_from_cert_san_dns -======= - [invalid_client_id_from_cert_san_dns ->>>>>>> aeda3cada (Fix test case name) - ]}, - {ssl_user_with_client_id_in_cert_san_dns, [], - [client_id_from_cert_san_dns ->>>>>>> bf7de92aa (Apply fix from PR #13180) ]}, {ssl_user_with_client_id_in_cert_san_dns_1, [], [client_id_from_cert_san_dns_1 @@ -220,13 +209,8 @@ mqtt_config(no_ssl_user) -> mqtt_config(client_id_propagation) -> {rabbitmq_mqtt, [{ssl_cert_login, true}, {allow_anonymous, true}]}; -<<<<<<< HEAD -mqtt_config(T) when T == ssl_user_with_client_id_in_cert_san_dns; - T == ssl_user_with_invalid_client_id_in_cert_san_dns -> -======= mqtt_config(T) when T == ssl_user_with_invalid_client_id_in_cert_san_dns; ssl_user_with_client_id_in_cert_san_dns -> ->>>>>>> bf7de92aa (Apply fix from PR #13180) {rabbitmq_mqtt, [{ssl_cert_login, true}, {allow_anonymous, false}, {ssl_cert_client_id_from, subject_alternative_name}, @@ -607,13 +591,8 @@ client_id_from_cert_dn(Config) -> invalid_client_id_from_cert_san_dns(Config) -> MqttClientId = <<"other_client_id">>, {ok, C} = connect_ssl(MqttClientId, Config), -<<<<<<< HEAD - unlink(C), - {error, {client_identifier_not_valid, _}} = emqtt:connect(C). -======= {error, {client_identifier_not_valid, _}} = emqtt:connect(C), unlink(C). ->>>>>>> bf7de92aa (Apply fix from PR #13180) ssl_user_vhost_parameter_mapping_success(Config) -> expect_successful_connection(fun connect_ssl/1, Config).