Support explicit foward proxy from oauth2 plugin
This commit is contained in:
parent
68de3fdb77
commit
b5be85ffab
|
@ -10,13 +10,8 @@ on:
|
||||||
- 'deps/rabbitmq_auth_**'
|
- 'deps/rabbitmq_auth_**'
|
||||||
- 'deps/rabbitmq_management/src/**'
|
- 'deps/rabbitmq_management/src/**'
|
||||||
- 'deps/rabbitmq_management/priv/**'
|
- 'deps/rabbitmq_management/priv/**'
|
||||||
- 'deps/rabbitmq_management/selenium/**'
|
- 'selenium/**'
|
||||||
- 'scripts/**'
|
- 'scripts/**'
|
||||||
- .bazelrc
|
|
||||||
- .bazelversion
|
|
||||||
- BUILD.*
|
|
||||||
- '*.bzl'
|
|
||||||
- '*.bazel'
|
|
||||||
- .github/workflows/test-authnz.yaml
|
- .github/workflows/test-authnz.yaml
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
|
|
|
@ -12,11 +12,6 @@ on:
|
||||||
- 'deps/rabbitmq_management/priv/**'
|
- 'deps/rabbitmq_management/priv/**'
|
||||||
- 'deps/rabbitmq_web_dispatch/src/**'
|
- 'deps/rabbitmq_web_dispatch/src/**'
|
||||||
- 'scripts/**'
|
- 'scripts/**'
|
||||||
- .bazelrc
|
|
||||||
- .bazelversion
|
|
||||||
- BUILD.*
|
|
||||||
- '*.bzl'
|
|
||||||
- '*.bazel'
|
|
||||||
- 'selenium/**'
|
- 'selenium/**'
|
||||||
- .github/workflows/test-management-ui.yaml
|
- .github/workflows/test-management-ui.yaml
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,14 @@
|
||||||
}).
|
}).
|
||||||
-type openid_configuration() :: #openid_configuration{}.
|
-type openid_configuration() :: #openid_configuration{}.
|
||||||
|
|
||||||
|
-record(proxy_options, {
|
||||||
|
host :: string(),
|
||||||
|
port :: integer(),
|
||||||
|
username :: option(string() | binary()),
|
||||||
|
password :: option(string() | binary())
|
||||||
|
}).
|
||||||
|
-type proxy_options() :: #proxy_options{}.
|
||||||
|
|
||||||
-record(oauth_provider, {
|
-record(oauth_provider, {
|
||||||
id :: oauth_provider_id(),
|
id :: oauth_provider_id(),
|
||||||
issuer :: option(uri_string:uri_string()),
|
issuer :: option(uri_string:uri_string()),
|
||||||
|
@ -28,7 +36,8 @@
|
||||||
authorization_endpoint :: option(uri_string:uri_string()),
|
authorization_endpoint :: option(uri_string:uri_string()),
|
||||||
end_session_endpoint :: option(uri_string:uri_string()),
|
end_session_endpoint :: option(uri_string:uri_string()),
|
||||||
jwks_uri :: option(uri_string:uri_string()),
|
jwks_uri :: option(uri_string:uri_string()),
|
||||||
ssl_options :: option(list())
|
ssl_options :: option(list()),
|
||||||
|
proxy_options :: option(proxy_options())
|
||||||
}).
|
}).
|
||||||
|
|
||||||
-type query_list() :: [{unicode:chardata(), unicode:chardata() | true}].
|
-type query_list() :: [{unicode:chardata(), unicode:chardata() | true}].
|
||||||
|
|
|
@ -7,13 +7,18 @@
|
||||||
-module(oauth2_client).
|
-module(oauth2_client).
|
||||||
-export([get_access_token/2, get_expiration_time/1,
|
-export([get_access_token/2, get_expiration_time/1,
|
||||||
refresh_access_token/2,
|
refresh_access_token/2,
|
||||||
|
get_jwks/1,
|
||||||
get_oauth_provider/1, get_oauth_provider/2,
|
get_oauth_provider/1, get_oauth_provider/2,
|
||||||
get_openid_configuration/2,
|
get_openid_configuration/1,
|
||||||
build_openid_discovery_endpoint/3,
|
build_openid_discovery_endpoint/3,
|
||||||
merge_openid_configuration/2,
|
merge_openid_configuration/2,
|
||||||
merge_oauth_provider/2,
|
merge_oauth_provider/2,
|
||||||
extract_ssl_options_as_list/1,
|
extract_ssl_options_as_list/1,
|
||||||
format_ssl_options/1, format_oauth_provider/1, format_oauth_provider_id/1
|
map_proxy_auth_to_httpc_option/1,
|
||||||
|
map_proxy_to_httpc_option/1,
|
||||||
|
map_ssl_options_to_httpc_option/1,
|
||||||
|
map_timeout_to_httpc_option/1,
|
||||||
|
format_ssl_options/1, format_oauth_provider/1, format_oauth_provider_id/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("oauth2_client.hrl").
|
-include("oauth2_client.hrl").
|
||||||
|
@ -25,29 +30,82 @@ get_access_token(OAuthProvider, Request) ->
|
||||||
rabbit_log:debug("get_access_token using OAuthProvider:~p and client_id:~p",
|
rabbit_log:debug("get_access_token using OAuthProvider:~p and client_id:~p",
|
||||||
[OAuthProvider, Request#access_token_request.client_id]),
|
[OAuthProvider, Request#access_token_request.client_id]),
|
||||||
URL = OAuthProvider#oauth_provider.token_endpoint,
|
URL = OAuthProvider#oauth_provider.token_endpoint,
|
||||||
|
Id = OAuthProvider#oauth_provider.id,
|
||||||
Header = [],
|
Header = [],
|
||||||
Type = ?CONTENT_URLENCODED,
|
Type = ?CONTENT_URLENCODED,
|
||||||
Body = build_access_token_request_body(Request),
|
Body = build_access_token_request_body(Request),
|
||||||
HTTPOptions = get_ssl_options_if_any(OAuthProvider) ++
|
HTTPOptions =
|
||||||
get_timeout_of_default(Request#access_token_request.timeout),
|
map_ssl_options_to_httpc_option(OAuthProvider#oauth_provider.ssl_options) ++
|
||||||
Options = [],
|
map_timeout_to_httpc_option(Request#access_token_request.timeout),
|
||||||
Response = httpc:request(post, {URL, Header, Type, Body}, HTTPOptions, Options),
|
Response = http_post(Id, URL, Header, Type, Body, HTTPOptions,
|
||||||
|
OAuthProvider#oauth_provider.proxy_options),
|
||||||
parse_access_token_response(Response).
|
parse_access_token_response(Response).
|
||||||
|
|
||||||
-spec refresh_access_token(oauth_provider(), refresh_token_request()) ->
|
-spec refresh_access_token(oauth_provider(), refresh_token_request()) ->
|
||||||
{ok, successful_access_token_response()} |
|
{ok, successful_access_token_response()} |
|
||||||
{error, unsuccessful_access_token_response() | any()}.
|
{error, unsuccessful_access_token_response() | any()}.
|
||||||
refresh_access_token(OAuthProvider, Request) ->
|
refresh_access_token(OAuthProvider, Request) ->
|
||||||
|
Id = OAuthProvider#oauth_provider.id,
|
||||||
URL = OAuthProvider#oauth_provider.token_endpoint,
|
URL = OAuthProvider#oauth_provider.token_endpoint,
|
||||||
Header = [],
|
Header = [],
|
||||||
Type = ?CONTENT_URLENCODED,
|
Type = ?CONTENT_URLENCODED,
|
||||||
Body = build_refresh_token_request_body(Request),
|
Body = build_refresh_token_request_body(Request),
|
||||||
HTTPOptions = get_ssl_options_if_any(OAuthProvider) ++
|
HTTPOptions =
|
||||||
get_timeout_of_default(Request#refresh_token_request.timeout),
|
map_ssl_options_to_httpc_option(OAuthProvider#oauth_provider.ssl_options) ++
|
||||||
Options = [],
|
map_timeout_to_httpc_option(Request#refresh_token_request.timeout),
|
||||||
Response = httpc:request(post, {URL, Header, Type, Body}, HTTPOptions, Options),
|
Response = http_post(Id, URL, Header, Type, Body, HTTPOptions,
|
||||||
|
OAuthProvider#oauth_provider.proxy_options),
|
||||||
parse_access_token_response(Response).
|
parse_access_token_response(Response).
|
||||||
|
|
||||||
|
ensure_http_client_started(Id, ProxyOptions) ->
|
||||||
|
Profile = case Id of
|
||||||
|
root -> root;
|
||||||
|
_ -> binary_to_atom(Id)
|
||||||
|
end,
|
||||||
|
rabbit_log:debug("Starting http client ~p ...", [Profile]),
|
||||||
|
case inets:start(httpc, [{profile, Profile}]) of
|
||||||
|
{ok, _} ->
|
||||||
|
HttpProxyOptions = map_proxy_to_httpc_option(ProxyOptions),
|
||||||
|
case ensure_http_proxy_options_if_any(Profile, HttpProxyOptions) of
|
||||||
|
ok -> {ok, Profile};
|
||||||
|
{error, _} = Error -> Error
|
||||||
|
end;
|
||||||
|
{error, {already_started, _}} ->
|
||||||
|
{ok, Profile};
|
||||||
|
Error ->
|
||||||
|
rabbit_log:error("Failed to start httpc client: ~p", [Error]),
|
||||||
|
Error
|
||||||
|
end.
|
||||||
|
ensure_http_proxy_options_if_any(_Profile, []) ->
|
||||||
|
ok;
|
||||||
|
ensure_http_proxy_options_if_any(Profile, HttpProxyOptions) ->
|
||||||
|
case httpc:set_options(HttpProxyOptions, Profile) of
|
||||||
|
ok ->
|
||||||
|
rabbit_log:debug("Successfully set_options ~p on http client ~p",
|
||||||
|
[HttpProxyOptions, Profile]),
|
||||||
|
ok;
|
||||||
|
{error, _} = Error -> Error
|
||||||
|
end.
|
||||||
|
|
||||||
|
http_post(Id, URL, Header, Type, Body, HTTPOptions, ProxyOptions) ->
|
||||||
|
http_request(Id, post, {URL, Header, Type, Body}, HTTPOptions, ProxyOptions).
|
||||||
|
http_get(Id, URL, HTTPOptions, ProxyOptions) ->
|
||||||
|
http_request(Id, get, {URL, []}, HTTPOptions, ProxyOptions).
|
||||||
|
http_request(Id, Method, Payload, HTTPOptions, ProxyOptions) ->
|
||||||
|
case ensure_http_client_started(Id, ProxyOptions) of
|
||||||
|
{ok, Profile} ->
|
||||||
|
case ProxyOptions of
|
||||||
|
undefined ->
|
||||||
|
httpc:request(Method, Payload, HTTPOptions, [], Profile);
|
||||||
|
_ ->
|
||||||
|
httpc:request(Method, Payload,
|
||||||
|
HTTPOptions ++ map_proxy_auth_to_httpc_option(ProxyOptions),
|
||||||
|
[],
|
||||||
|
Profile)
|
||||||
|
end;
|
||||||
|
{error, _} = Error -> Error
|
||||||
|
end.
|
||||||
|
|
||||||
append_paths(Path1, Path2) ->
|
append_paths(Path1, Path2) ->
|
||||||
erlang:iolist_to_binary([Path1, Path2]).
|
erlang:iolist_to_binary([Path1, Path2]).
|
||||||
|
|
||||||
|
@ -93,14 +151,27 @@ drop_trailing_path_separator(Path) when is_list(Path) ->
|
||||||
_ -> Path
|
_ -> Path
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec get_openid_configuration(DiscoveryEndpoint :: uri_string:uri_string(),
|
-spec get_openid_configuration(oauth_provider()) -> {ok, openid_configuration()} | {error, term()}.
|
||||||
ssl:tls_option() | []) -> {ok, openid_configuration()} | {error, term()}.
|
get_openid_configuration(#oauth_provider{id = Id, discovery_endpoint = Endpoint,
|
||||||
get_openid_configuration(DiscoverEndpoint, TLSOptions) ->
|
ssl_options = SslOptions, proxy_options = ProxyOptions}) ->
|
||||||
rabbit_log:debug("get_openid_configuration from ~p (~p)", [DiscoverEndpoint,
|
rabbit_log:debug("get_openid_configuration from ~p (~p) [~p]", [Endpoint,
|
||||||
format_ssl_options(TLSOptions)]),
|
format_ssl_options(SslOptions), format_proxy_options(ProxyOptions)]),
|
||||||
Options = [],
|
HTTPOptions =
|
||||||
Response = httpc:request(get, {DiscoverEndpoint, []}, TLSOptions, Options),
|
map_ssl_options_to_httpc_option(SslOptions) ++
|
||||||
|
map_timeout_to_httpc_option(?DEFAULT_HTTP_TIMEOUT),
|
||||||
|
|
||||||
|
Response = http_get(Id, Endpoint, HTTPOptions, ProxyOptions),
|
||||||
parse_openid_configuration_response(Response).
|
parse_openid_configuration_response(Response).
|
||||||
|
|
||||||
|
-spec get_jwks(oauth_provider()) -> {ok, term()} | {error, term()}.
|
||||||
|
get_jwks(#oauth_provider{id = Id, jwks_uri = JwksUrl,
|
||||||
|
ssl_options = SslOptions, proxy_options = ProxyOptions}) ->
|
||||||
|
rabbit_log:debug("get_jwks from ~p (~p) [~p]", [JwksUrl,
|
||||||
|
format_ssl_options(SslOptions), format_proxy_options(ProxyOptions)]),
|
||||||
|
HTTPOptions =
|
||||||
|
map_ssl_options_to_httpc_option(SslOptions) ++
|
||||||
|
map_timeout_to_httpc_option(?DEFAULT_HTTP_TIMEOUT),
|
||||||
|
http_get(Id, JwksUrl, HTTPOptions, ProxyOptions).
|
||||||
|
|
||||||
-spec merge_openid_configuration(openid_configuration(), oauth_provider()) ->
|
-spec merge_openid_configuration(openid_configuration(), oauth_provider()) ->
|
||||||
oauth_provider().
|
oauth_provider().
|
||||||
|
@ -283,7 +354,7 @@ download_oauth_provider(OAuthProvider) ->
|
||||||
undefined -> {error, {missing_oauth_provider_attributes, [issuer]}};
|
undefined -> {error, {missing_oauth_provider_attributes, [issuer]}};
|
||||||
URL ->
|
URL ->
|
||||||
rabbit_log:debug("Downloading oauth_provider using ~p ", [URL]),
|
rabbit_log:debug("Downloading oauth_provider using ~p ", [URL]),
|
||||||
case get_openid_configuration(URL, get_ssl_options_if_any(OAuthProvider)) of
|
case get_openid_configuration(OAuthProvider) of
|
||||||
{ok, OpenIdConfiguration} ->
|
{ok, OpenIdConfiguration} ->
|
||||||
{ok, update_oauth_provider_endpoints_configuration(
|
{ok, update_oauth_provider_endpoints_configuration(
|
||||||
merge_openid_configuration(OpenIdConfiguration, OAuthProvider))};
|
merge_openid_configuration(OpenIdConfiguration, OAuthProvider))};
|
||||||
|
@ -341,7 +412,6 @@ get_oauth_provider(OAuthProviderId, ListOfRequiredAttributes)
|
||||||
[OAuthProviderId, Error0]),
|
[OAuthProviderId, Error0]),
|
||||||
Error0;
|
Error0;
|
||||||
Config ->
|
Config ->
|
||||||
rabbit_log:debug("Found oauth_provider configuration ~p", [Config]),
|
|
||||||
OAuthProvider = map_to_oauth_provider(Config),
|
OAuthProvider = map_to_oauth_provider(Config),
|
||||||
rabbit_log:debug("Resolved oauth_provider ~p", [format_oauth_provider(OAuthProvider)]),
|
rabbit_log:debug("Resolved oauth_provider ~p", [format_oauth_provider(OAuthProvider)]),
|
||||||
case find_missing_attributes(OAuthProvider, ListOfRequiredAttributes) of
|
case find_missing_attributes(OAuthProvider, ListOfRequiredAttributes) of
|
||||||
|
@ -395,8 +465,36 @@ lookup_root_oauth_provider() ->
|
||||||
token_endpoint = get_env(token_endpoint),
|
token_endpoint = get_env(token_endpoint),
|
||||||
authorization_endpoint = get_env(authorization_endpoint),
|
authorization_endpoint = get_env(authorization_endpoint),
|
||||||
end_session_endpoint = get_env(end_session_endpoint),
|
end_session_endpoint = get_env(end_session_endpoint),
|
||||||
ssl_options = extract_ssl_options_as_list(Map)
|
ssl_options = extract_ssl_options_as_list(Map),
|
||||||
|
proxy_options = extract_proxy_options(get_env(proxy, []))
|
||||||
}.
|
}.
|
||||||
|
|
||||||
|
-spec extract_proxy_options(#{atom() => any()}|list()) -> proxy_options() | undefined.
|
||||||
|
extract_proxy_options(List) when is_list(List) ->
|
||||||
|
case {proplists:get_value(host, List, undefined),
|
||||||
|
proplists:get_value(port, List, 0)} of
|
||||||
|
{undefined, _} -> undefined;
|
||||||
|
{_, 0} -> undefined;
|
||||||
|
{H, P} ->
|
||||||
|
#proxy_options{
|
||||||
|
host = H,
|
||||||
|
port = P,
|
||||||
|
username = proplists:get_value(username, List, undefined),
|
||||||
|
password = proplists:get_value(password, List, undefined)
|
||||||
|
}
|
||||||
|
end;
|
||||||
|
extract_proxy_options(Map) ->
|
||||||
|
case {maps:get(host, Map, undefined), maps:get(port, Map, 0)} of
|
||||||
|
{undefined, _} -> undefined;
|
||||||
|
{_, 0} -> undefined;
|
||||||
|
{H, P} ->
|
||||||
|
#proxy_options{
|
||||||
|
host = H,
|
||||||
|
port = P,
|
||||||
|
username = maps:get(username, Map, undefined),
|
||||||
|
password = maps:get(password, Map, undefined)
|
||||||
|
}
|
||||||
|
end.
|
||||||
|
|
||||||
-spec extract_ssl_options_as_list(#{atom() => any()}) -> proplists:proplist().
|
-spec extract_ssl_options_as_list(#{atom() => any()}) -> proplists:proplist().
|
||||||
extract_ssl_options_as_list(Map) ->
|
extract_ssl_options_as_list(Map) ->
|
||||||
|
@ -522,15 +620,36 @@ append_extra_parameters(Request, QueryList) ->
|
||||||
Params -> Params ++ QueryList
|
Params -> Params ++ QueryList
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_ssl_options_if_any(OAuthProvider) ->
|
map_ssl_options_to_httpc_option(SslOptions) ->
|
||||||
case OAuthProvider#oauth_provider.ssl_options of
|
case SslOptions of
|
||||||
undefined -> [];
|
undefined -> [];
|
||||||
Options -> [{ssl, Options}]
|
Options -> [{ssl, Options}]
|
||||||
end.
|
end.
|
||||||
get_timeout_of_default(Timeout) ->
|
|
||||||
|
map_timeout_to_httpc_option(Timeout) ->
|
||||||
case Timeout of
|
case Timeout of
|
||||||
undefined -> [{timeout, ?DEFAULT_HTTP_TIMEOUT}];
|
undefined -> [{timeout, ?DEFAULT_HTTP_TIMEOUT}];
|
||||||
Timeout -> [{timeout, Timeout}]
|
Timeout -> [{timeout, Timeout}]
|
||||||
|
end.
|
||||||
|
|
||||||
|
map_proxy_to_httpc_option(ProxyOptions) ->
|
||||||
|
case ProxyOptions of
|
||||||
|
undefined -> [];
|
||||||
|
Proxy -> case {Proxy#proxy_options.host, Proxy#proxy_options.port} of
|
||||||
|
{_, 0} -> [];
|
||||||
|
{Host, Port} -> P = {{Host, Port},[]},
|
||||||
|
[{proxy, P}]
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
|
map_proxy_auth_to_httpc_option(ProxyOptions) ->
|
||||||
|
case ProxyOptions of
|
||||||
|
undefined -> [];
|
||||||
|
Proxy -> case {Proxy#proxy_options.username, Proxy#proxy_options.password} of
|
||||||
|
{undefined, _} -> [];
|
||||||
|
{_, undefined} -> [];
|
||||||
|
{_, _} = Auth -> [{proxy_auth, Auth}]
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
is_json(?CONTENT_JSON) -> true;
|
is_json(?CONTENT_JSON) -> true;
|
||||||
|
@ -543,10 +662,8 @@ is_json(_) -> false.
|
||||||
decode_body(_, []) -> [];
|
decode_body(_, []) -> [];
|
||||||
decode_body(?CONTENT_JSON, Body) ->
|
decode_body(?CONTENT_JSON, Body) ->
|
||||||
case rabbit_json:try_decode(rabbit_data_coercion:to_binary(Body)) of
|
case rabbit_json:try_decode(rabbit_data_coercion:to_binary(Body)) of
|
||||||
{ok, Value} ->
|
{ok, Value} -> Value;
|
||||||
Value;
|
{error, _} = Error -> Error
|
||||||
{error, _} = Error ->
|
|
||||||
Error
|
|
||||||
end;
|
end;
|
||||||
decode_body(MimeType, Body) ->
|
decode_body(MimeType, Body) ->
|
||||||
Items = string:split(MimeType, ";"),
|
Items = string:split(MimeType, ";"),
|
||||||
|
@ -588,14 +705,14 @@ map_to_oauth_provider(PropList) when is_list(PropList) ->
|
||||||
proplists:get_value(jwks_uri, PropList, undefined),
|
proplists:get_value(jwks_uri, PropList, undefined),
|
||||||
ssl_options =
|
ssl_options =
|
||||||
extract_ssl_options_as_list(maps:from_list(
|
extract_ssl_options_as_list(maps:from_list(
|
||||||
proplists:get_value(https, PropList, [])))
|
proplists:get_value(https, PropList, []))),
|
||||||
|
proxy_options =
|
||||||
|
extract_proxy_options(proplists:get_value(proxy, PropList, []))
|
||||||
}.
|
}.
|
||||||
map_to_access_token_response(Code, Reason, Headers, Body) ->
|
map_to_access_token_response(Code, Reason, Headers, Body) ->
|
||||||
case decode_body(proplists:get_value("content-type", Headers, ?CONTENT_JSON), Body) of
|
case decode_body(proplists:get_value("content-type", Headers, ?CONTENT_JSON), Body) of
|
||||||
{error, {error, InternalError}} ->
|
{error, {error, InternalError}} -> {error, InternalError};
|
||||||
{error, InternalError};
|
{error, _} = Error -> Error;
|
||||||
{error, _} = Error ->
|
|
||||||
Error;
|
|
||||||
Value ->
|
Value ->
|
||||||
case Code of
|
case Code of
|
||||||
200 -> {ok, map_to_successful_access_token_response(Value)};
|
200 -> {ok, map_to_successful_access_token_response(Value)};
|
||||||
|
@ -626,6 +743,18 @@ format_ssl_options(TlsOptions) ->
|
||||||
proplists:get_value(cacertfile, TlsOptions),
|
proplists:get_value(cacertfile, TlsOptions),
|
||||||
CaCertsCount])).
|
CaCertsCount])).
|
||||||
|
|
||||||
|
-spec format_proxy_options(proxy_options()|undefined) -> string().
|
||||||
|
format_proxy_options(undefined) ->
|
||||||
|
lists:flatten(io_lib:format("{no proxy}", []));
|
||||||
|
|
||||||
|
format_proxy_options(ProxyOptions) ->
|
||||||
|
lists:flatten(io_lib:format("{host: ~p, port: ~p, username: ~p, " ++
|
||||||
|
"password: ~p }", [
|
||||||
|
ProxyOptions#proxy_options.host,
|
||||||
|
ProxyOptions#proxy_options.port,
|
||||||
|
ProxyOptions#proxy_options.username,
|
||||||
|
ProxyOptions#proxy_options.password])).
|
||||||
|
|
||||||
format_oauth_provider_id(root) -> "<from keyconfig>";
|
format_oauth_provider_id(root) -> "<from keyconfig>";
|
||||||
format_oauth_provider_id(Id) -> binary_to_list(Id).
|
format_oauth_provider_id(Id) -> binary_to_list(Id).
|
||||||
|
|
||||||
|
@ -634,7 +763,7 @@ format_oauth_provider(OAuthProvider) ->
|
||||||
lists:flatten(io_lib:format("{id: ~p, issuer: ~p, discovery_endpoint: ~p, " ++
|
lists:flatten(io_lib:format("{id: ~p, issuer: ~p, discovery_endpoint: ~p, " ++
|
||||||
" token_endpoint: ~p, " ++
|
" token_endpoint: ~p, " ++
|
||||||
"authorization_endpoint: ~p, end_session_endpoint: ~p, " ++
|
"authorization_endpoint: ~p, end_session_endpoint: ~p, " ++
|
||||||
"jwks_uri: ~p, ssl_options: ~p }", [
|
"jwks_uri: ~p, ssl_options: ~p, proxy_options: ~p}", [
|
||||||
format_oauth_provider_id(OAuthProvider#oauth_provider.id),
|
format_oauth_provider_id(OAuthProvider#oauth_provider.id),
|
||||||
OAuthProvider#oauth_provider.issuer,
|
OAuthProvider#oauth_provider.issuer,
|
||||||
OAuthProvider#oauth_provider.discovery_endpoint,
|
OAuthProvider#oauth_provider.discovery_endpoint,
|
||||||
|
@ -642,7 +771,8 @@ format_oauth_provider(OAuthProvider) ->
|
||||||
OAuthProvider#oauth_provider.authorization_endpoint,
|
OAuthProvider#oauth_provider.authorization_endpoint,
|
||||||
OAuthProvider#oauth_provider.end_session_endpoint,
|
OAuthProvider#oauth_provider.end_session_endpoint,
|
||||||
OAuthProvider#oauth_provider.jwks_uri,
|
OAuthProvider#oauth_provider.jwks_uri,
|
||||||
format_ssl_options(OAuthProvider#oauth_provider.ssl_options)])).
|
format_ssl_options(OAuthProvider#oauth_provider.ssl_options),
|
||||||
|
format_proxy_options(OAuthProvider#oauth_provider.proxy_options)])).
|
||||||
|
|
||||||
get_env(Par) ->
|
get_env(Par) ->
|
||||||
application:get_env(rabbitmq_auth_backend_oauth2, Par, undefined).
|
application:get_env(rabbitmq_auth_backend_oauth2, Par, undefined).
|
||||||
|
|
|
@ -322,13 +322,25 @@ build_openid_discovery_endpoint(Issuer, Path) ->
|
||||||
|
|
||||||
get_openid_configuration(Config) ->
|
get_openid_configuration(Config) ->
|
||||||
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
||||||
SslOptions = [{ssl, ExpectedOAuthProvider#oauth_provider.ssl_options}],
|
|
||||||
{ok, ActualOpenId} = oauth2_client:get_openid_configuration(
|
{ok, ActualOpenId} = oauth2_client:get_openid_configuration(
|
||||||
build_openid_discovery_endpoint(build_issuer("https")),
|
ensure_discovery_endpoint(ExpectedOAuthProvider)),
|
||||||
SslOptions),
|
|
||||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||||
assertOpenIdConfiguration(ExpectedOpenId, ActualOpenId).
|
assertOpenIdConfiguration(ExpectedOpenId, ActualOpenId).
|
||||||
|
|
||||||
|
ensure_issuer(OAuthProvider, IssuerURL) ->
|
||||||
|
OAuthProvider#oauth_provider{
|
||||||
|
issuer = IssuerURL
|
||||||
|
}.
|
||||||
|
ensure_discovery_endpoint(OAuthProvider) ->
|
||||||
|
OAuthProvider#oauth_provider{
|
||||||
|
discovery_endpoint = build_openid_discovery_endpoint(OAuthProvider#oauth_provider.issuer)
|
||||||
|
}.
|
||||||
|
ensure_discovery_endpoint(OAuthProvider, DiscoveryEndpointPath) ->
|
||||||
|
OAuthProvider#oauth_provider{
|
||||||
|
discovery_endpoint = build_openid_discovery_endpoint(
|
||||||
|
OAuthProvider#oauth_provider.issuer,
|
||||||
|
DiscoveryEndpointPath)
|
||||||
|
}.
|
||||||
map_oauth_provider_to_openid_configuration(OAuthProvider) ->
|
map_oauth_provider_to_openid_configuration(OAuthProvider) ->
|
||||||
#openid_configuration{
|
#openid_configuration{
|
||||||
issuer = OAuthProvider#oauth_provider.issuer,
|
issuer = OAuthProvider#oauth_provider.issuer,
|
||||||
|
@ -344,35 +356,30 @@ get_openid_configuration_returns_partial_payload(Config) ->
|
||||||
token_endpoint = ExpectedOAuthProvider0#oauth_provider.token_endpoint,
|
token_endpoint = ExpectedOAuthProvider0#oauth_provider.token_endpoint,
|
||||||
jwks_uri = ExpectedOAuthProvider0#oauth_provider.jwks_uri},
|
jwks_uri = ExpectedOAuthProvider0#oauth_provider.jwks_uri},
|
||||||
|
|
||||||
SslOptions = [{ssl, ExpectedOAuthProvider0#oauth_provider.ssl_options}],
|
|
||||||
{ok, Actual} = oauth2_client:get_openid_configuration(
|
{ok, Actual} = oauth2_client:get_openid_configuration(
|
||||||
build_openid_discovery_endpoint(build_issuer("https")),
|
ensure_discovery_endpoint(ExpectedOAuthProvider0)),
|
||||||
SslOptions),
|
|
||||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||||
assertOpenIdConfiguration(ExpectedOpenId, Actual).
|
assertOpenIdConfiguration(ExpectedOpenId, Actual).
|
||||||
|
|
||||||
get_openid_configuration_using_path(Config) ->
|
get_openid_configuration_using_path(Config) ->
|
||||||
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
||||||
SslOptions = [{ssl, ExpectedOAuthProvider#oauth_provider.ssl_options}],
|
{ok, Actual} = oauth2_client:get_openid_configuration(
|
||||||
{ok, Actual} = oauth2_client:get_openid_configuration(
|
ensure_discovery_endpoint(
|
||||||
build_openid_discovery_endpoint(build_issuer("https", ?ISSUER_PATH)),
|
ensure_issuer(ExpectedOAuthProvider, build_issuer("https", ?ISSUER_PATH)))),
|
||||||
SslOptions),
|
|
||||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||||
assertOpenIdConfiguration(ExpectedOpenId,Actual).
|
assertOpenIdConfiguration(ExpectedOpenId,Actual).
|
||||||
get_openid_configuration_using_path_and_custom_endpoint(Config) ->
|
get_openid_configuration_using_path_and_custom_endpoint(Config) ->
|
||||||
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
||||||
SslOptions = [{ssl, ExpectedOAuthProvider#oauth_provider.ssl_options}],
|
|
||||||
{ok, Actual} = oauth2_client:get_openid_configuration(
|
{ok, Actual} = oauth2_client:get_openid_configuration(
|
||||||
build_openid_discovery_endpoint(build_issuer("https", ?ISSUER_PATH),
|
ensure_discovery_endpoint(
|
||||||
?CUSTOM_OPENID_CONFIGURATION_ENDPOINT), SslOptions),
|
ensure_issuer(ExpectedOAuthProvider, build_issuer("https", ?ISSUER_PATH)),
|
||||||
|
?CUSTOM_OPENID_CONFIGURATION_ENDPOINT)),
|
||||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||||
assertOpenIdConfiguration(ExpectedOpenId, Actual).
|
assertOpenIdConfiguration(ExpectedOpenId, Actual).
|
||||||
get_openid_configuration_using_custom_endpoint(Config) ->
|
get_openid_configuration_using_custom_endpoint(Config) ->
|
||||||
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
||||||
SslOptions = [{ssl, ExpectedOAuthProvider#oauth_provider.ssl_options}],
|
|
||||||
{ok, Actual} = oauth2_client:get_openid_configuration(
|
{ok, Actual} = oauth2_client:get_openid_configuration(
|
||||||
build_openid_discovery_endpoint(build_issuer("https"),
|
ensure_discovery_endpoint(ExpectedOAuthProvider, ?CUSTOM_OPENID_CONFIGURATION_ENDPOINT)),
|
||||||
?CUSTOM_OPENID_CONFIGURATION_ENDPOINT), SslOptions),
|
|
||||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||||
assertOpenIdConfiguration(ExpectedOpenId, Actual).
|
assertOpenIdConfiguration(ExpectedOpenId, Actual).
|
||||||
|
|
||||||
|
|
|
@ -220,6 +220,26 @@
|
||||||
rabbit_oauth2_schema:translate_oauth_providers(Conf)
|
rabbit_oauth2_schema:translate_oauth_providers(Conf)
|
||||||
end}.
|
end}.
|
||||||
|
|
||||||
|
{mapping,
|
||||||
|
"auth_oauth2.proxy.host",
|
||||||
|
"rabbitmq_auth_backend_oauth2.proxy.host",
|
||||||
|
[{datatype, string}]}.
|
||||||
|
|
||||||
|
{mapping,
|
||||||
|
"auth_oauth2.proxy.port",
|
||||||
|
"rabbitmq_auth_backend_oauth2.proxy.port",
|
||||||
|
[{datatype, integer}]}.
|
||||||
|
|
||||||
|
{mapping,
|
||||||
|
"auth_oauth2.proxy.username",
|
||||||
|
"rabbitmq_auth_backend_oauth2.proxy.username",
|
||||||
|
[{datatype, string}]}.
|
||||||
|
|
||||||
|
{mapping,
|
||||||
|
"auth_oauth2.proxy.password",
|
||||||
|
"rabbitmq_auth_backend_oauth2.proxy.password",
|
||||||
|
[{datatype, string}]}.
|
||||||
|
|
||||||
{mapping,
|
{mapping,
|
||||||
"auth_oauth2.https.peer_verification",
|
"auth_oauth2.https.peer_verification",
|
||||||
"rabbitmq_auth_backend_oauth2.key_config.peer_verification",
|
"rabbitmq_auth_backend_oauth2.key_config.peer_verification",
|
||||||
|
@ -322,6 +342,26 @@
|
||||||
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
||||||
[{datatype, integer}]}.
|
[{datatype, integer}]}.
|
||||||
|
|
||||||
|
{mapping,
|
||||||
|
"auth_oauth2.oauth_providers.$name.proxy.host",
|
||||||
|
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
||||||
|
[{datatype, string}]}.
|
||||||
|
|
||||||
|
{mapping,
|
||||||
|
"auth_oauth2.oauth_providers.$name.proxy.port",
|
||||||
|
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
||||||
|
[{datatype, integer}]}.
|
||||||
|
|
||||||
|
{mapping,
|
||||||
|
"auth_oauth2.oauth_providers.$name.proxy.username",
|
||||||
|
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
||||||
|
[{datatype, string}]}.
|
||||||
|
|
||||||
|
{mapping,
|
||||||
|
"auth_oauth2.oauth_providers.$name.proxy.password",
|
||||||
|
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
||||||
|
[{datatype, string}]}.
|
||||||
|
|
||||||
{mapping,
|
{mapping,
|
||||||
"auth_oauth2.oauth_providers.$name.https.hostname_verification",
|
"auth_oauth2.oauth_providers.$name.https.hostname_verification",
|
||||||
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
||||||
|
|
|
@ -158,6 +158,7 @@ translate_oauth_providers(Conf) ->
|
||||||
Settings),
|
Settings),
|
||||||
extract_oauth_providers_algorithm(Settings),
|
extract_oauth_providers_algorithm(Settings),
|
||||||
extract_oauth_providers_https(Settings),
|
extract_oauth_providers_https(Settings),
|
||||||
|
extract_oauth_providers_proxy(Settings),
|
||||||
extract_oauth_providers_signing_keys(Settings)
|
extract_oauth_providers_signing_keys(Settings)
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
@ -264,6 +265,15 @@ mapOauthProviderProperty({Key, Value}) ->
|
||||||
_ -> Value
|
_ -> Value
|
||||||
end}.
|
end}.
|
||||||
|
|
||||||
|
extract_oauth_providers_proxy(Settings) ->
|
||||||
|
ExtractProviderNameFun = fun extract_key_as_binary/1,
|
||||||
|
AttributesPerProvider = [{Name, mapProxyProperty({list_to_atom(Key), V})} ||
|
||||||
|
{[?AUTH_OAUTH2, ?OAUTH_PROVIDERS, Name, "proxy", Key], V} <- Settings ],
|
||||||
|
|
||||||
|
maps:map(fun(_K,V)-> [{proxy, V}] end,
|
||||||
|
maps:groups_from_list(ExtractProviderNameFun, fun({_, V}) -> V end,
|
||||||
|
AttributesPerProvider)).
|
||||||
|
|
||||||
extract_oauth_providers_https(Settings) ->
|
extract_oauth_providers_https(Settings) ->
|
||||||
ExtractProviderNameFun = fun extract_key_as_binary/1,
|
ExtractProviderNameFun = fun extract_key_as_binary/1,
|
||||||
|
|
||||||
|
@ -280,6 +290,9 @@ mapHttpProperty({Key, Value}) ->
|
||||||
_ -> Value
|
_ -> Value
|
||||||
end}.
|
end}.
|
||||||
|
|
||||||
|
mapProxyProperty({Key, Value}) ->
|
||||||
|
{Key, Value}.
|
||||||
|
|
||||||
extract_oauth_providers_algorithm(Settings) ->
|
extract_oauth_providers_algorithm(Settings) ->
|
||||||
KeyFun = fun extract_key_as_binary/1,
|
KeyFun = fun extract_key_as_binary/1,
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
-module(uaa_jwks).
|
|
||||||
-export([get/2]).
|
|
||||||
|
|
||||||
-spec get(uri_string:uri_string(), list()) -> {ok, term()} | {error, term()}.
|
|
||||||
get(JwksUrl, SslOptions) ->
|
|
||||||
Options = [{timeout, 60000}] ++ [{ssl, SslOptions}],
|
|
||||||
httpc:request(get, {JwksUrl, []}, Options, []).
|
|
|
@ -42,11 +42,10 @@ add_signing_key(KeyId, Type, Value) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec update_jwks_signing_keys(oauth_provider()) -> ok | {error, term()}.
|
-spec update_jwks_signing_keys(oauth_provider()) -> ok | {error, term()}.
|
||||||
update_jwks_signing_keys(#oauth_provider{id = Id, jwks_uri = JwksUrl,
|
update_jwks_signing_keys(#oauth_provider{id = Id} = OAuthProvider) ->
|
||||||
ssl_options = SslOptions}) ->
|
rabbit_log:debug("Downloading signing keys from OauthProvider: ~tp",
|
||||||
rabbit_log:debug("Downloading signing keys from ~tp (TLS options: ~p)",
|
[Id]),
|
||||||
[JwksUrl, format_ssl_options(SslOptions)]),
|
case oauth2_client:get_jwks(OAuthProvider) of
|
||||||
case uaa_jwks:get(JwksUrl, SslOptions) of
|
|
||||||
{ok, {_, _, JwksBody}} ->
|
{ok, {_, _, JwksBody}} ->
|
||||||
KeyList = maps:get(<<"keys">>,
|
KeyList = maps:get(<<"keys">>,
|
||||||
jose:decode(erlang:iolist_to_binary(JwksBody)), []),
|
jose:decode(erlang:iolist_to_binary(JwksBody)), []),
|
||||||
|
|
|
@ -316,5 +316,37 @@
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
], []
|
], []
|
||||||
|
},
|
||||||
|
{proxy,
|
||||||
|
"auth_oauth2.proxy.host = localproxy
|
||||||
|
auth_oauth2.proxy.port = 8080
|
||||||
|
auth_oauth2.proxy.username = proxyuser
|
||||||
|
auth_oauth2.proxy.password = proxypwd
|
||||||
|
auth_oauth2.oauth_providers.keycloak.proxy.host = localproxy2
|
||||||
|
auth_oauth2.oauth_providers.keycloak.proxy.port = 8080
|
||||||
|
auth_oauth2.oauth_providers.keycloak.proxy.username = proxyuser2
|
||||||
|
auth_oauth2.oauth_providers.keycloak.proxy.password = proxypwd2",
|
||||||
|
[
|
||||||
|
{rabbitmq_auth_backend_oauth2, [
|
||||||
|
{proxy, [
|
||||||
|
{host, "localproxy"},
|
||||||
|
{password, "proxypwd"},
|
||||||
|
{port, 8080},
|
||||||
|
{username, "proxyuser"}
|
||||||
|
]},
|
||||||
|
{oauth_providers,
|
||||||
|
#{
|
||||||
|
<<"keycloak">> => [
|
||||||
|
{proxy, [
|
||||||
|
{password, "proxypwd2"},
|
||||||
|
{username, "proxyuser2"},
|
||||||
|
{port, 8080},
|
||||||
|
{host, "localproxy2"}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
], []
|
||||||
}
|
}
|
||||||
].
|
].
|
||||||
|
|
|
@ -65,6 +65,9 @@ verify_provider() -> [
|
||||||
]},
|
]},
|
||||||
{oauth_provider_with_issuer, [], [
|
{oauth_provider_with_issuer, [], [
|
||||||
get_oauth_provider_has_jwks_uri
|
get_oauth_provider_has_jwks_uri
|
||||||
|
]}
|
||||||
|
,{oauth_provider_with_proxy, [], [
|
||||||
|
get_oauth_provider_has_proxy
|
||||||
]}
|
]}
|
||||||
].
|
].
|
||||||
|
|
||||||
|
@ -149,6 +152,27 @@ init_per_group(with_resource_server_id, Config) ->
|
||||||
set_env(resource_server_id, ?RABBITMQ),
|
set_env(resource_server_id, ?RABBITMQ),
|
||||||
Config;
|
Config;
|
||||||
|
|
||||||
|
init_per_group(oauth_provider_with_proxy, Config) ->
|
||||||
|
Proxy = [
|
||||||
|
{host, "idp"},
|
||||||
|
{port, 8080},
|
||||||
|
{username, <<"user1">>},
|
||||||
|
{password, <<"pwd1">>}
|
||||||
|
],
|
||||||
|
case ?config(oauth_provider_id, Config) of
|
||||||
|
root ->
|
||||||
|
set_env(proxy, Proxy);
|
||||||
|
Id ->
|
||||||
|
OAuthProviders = get_env(oauth_providers, #{}),
|
||||||
|
OAuthProvider = maps:get(Id, OAuthProviders, []),
|
||||||
|
set_env(oauth_providers, maps:put(Id,
|
||||||
|
[{proxy, Proxy}] ++ OAuthProvider, OAuthProviders))
|
||||||
|
end,
|
||||||
|
[{proxy_hostname, "idp"},
|
||||||
|
{proxy_port, 8080},
|
||||||
|
{proxy_username, <<"user1">>},
|
||||||
|
{proxy_password, <<"pwd1">>}] ++ Config;
|
||||||
|
|
||||||
init_per_group(with_algorithms, Config) ->
|
init_per_group(with_algorithms, Config) ->
|
||||||
KeyConfig = get_env(key_config, []),
|
KeyConfig = get_env(key_config, []),
|
||||||
set_env(key_config, KeyConfig ++ [{algorithms, [<<"HS256">>, <<"RS256">>]}]),
|
set_env(key_config, KeyConfig ++ [{algorithms, [<<"HS256">>, <<"RS256">>]}]),
|
||||||
|
@ -190,6 +214,16 @@ init_per_group(_any, Config) ->
|
||||||
end_per_group(with_rabbitmq_node, Config) ->
|
end_per_group(with_rabbitmq_node, Config) ->
|
||||||
rabbit_ct_helpers:run_steps(Config, rabbit_ct_broker_helpers:teardown_steps());
|
rabbit_ct_helpers:run_steps(Config, rabbit_ct_broker_helpers:teardown_steps());
|
||||||
|
|
||||||
|
end_per_group(oauth_provider_with_proxy, Config) ->
|
||||||
|
case ?config(oauth_provider_id, Config) of
|
||||||
|
root ->
|
||||||
|
unset_env(proxy);
|
||||||
|
Id ->
|
||||||
|
unset_oauth_provider_properties(Id,
|
||||||
|
[host, port, username, password])
|
||||||
|
end,
|
||||||
|
Config;
|
||||||
|
|
||||||
end_per_group(with_root_static_signing_keys, Config) ->
|
end_per_group(with_root_static_signing_keys, Config) ->
|
||||||
KeyConfig = call_get_env(Config, key_config, []),
|
KeyConfig = call_get_env(Config, key_config, []),
|
||||||
call_set_env(Config, key_config, KeyConfig),
|
call_set_env(Config, key_config, KeyConfig),
|
||||||
|
@ -407,10 +441,22 @@ get_oauth_provider_with_jwks_uri_returns_error(Config) ->
|
||||||
|
|
||||||
get_oauth_provider_has_jwks_uri(Config) ->
|
get_oauth_provider_has_jwks_uri(Config) ->
|
||||||
{ok, OAuthProvider} = get_oauth_provider(
|
{ok, OAuthProvider} = get_oauth_provider(
|
||||||
?config(oauth_provider_id, Config), [jwks_uri]),
|
?config(oauth_provider_id, Config), [jwks_uri]),
|
||||||
ct:log("OAuthProvider: ~p", [OAuthProvider]),
|
|
||||||
?assertEqual(?config(jwks_uri, Config), OAuthProvider#oauth_provider.jwks_uri).
|
?assertEqual(?config(jwks_uri, Config), OAuthProvider#oauth_provider.jwks_uri).
|
||||||
|
|
||||||
|
get_oauth_provider_has_proxy(Config) ->
|
||||||
|
{ok, OAuthProvider} = get_oauth_provider(
|
||||||
|
?config(oauth_provider_id, Config), [jwks_uri]),
|
||||||
|
|
||||||
|
?assertEqual(?config(proxy_port, Config),
|
||||||
|
OAuthProvider#oauth_provider.proxy_options#proxy_options.port),
|
||||||
|
?assertEqual(?config(proxy_hostname, Config),
|
||||||
|
OAuthProvider#oauth_provider.proxy_options#proxy_options.host),
|
||||||
|
?assertEqual(?config(proxy_username, Config),
|
||||||
|
OAuthProvider#oauth_provider.proxy_options#proxy_options.username),
|
||||||
|
?assertEqual(?config(proxy_password, Config),
|
||||||
|
OAuthProvider#oauth_provider.proxy_options#proxy_options.password).
|
||||||
|
|
||||||
|
|
||||||
%% ---- Utility functions
|
%% ---- Utility functions
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
HTTPD_DOCKER_IMAGE=httpd:latest
|
||||||
|
|
||||||
|
ensure_devkeycloak-proxy() {
|
||||||
|
if docker ps | grep devkeycloak-proxy &> /dev/null; then
|
||||||
|
print "devkeycloak-proxy already running ..."
|
||||||
|
else
|
||||||
|
start_devkeycloak-proxy
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
init_devkeycloak-proxy() {
|
||||||
|
HTTPD_CONFIG_DIR=${TEST_CONFIG_DIR}/devkeycloak-proxy
|
||||||
|
PROXY_HOSTNAME=devkeycloak-proxy
|
||||||
|
PROXY_PORT=9092
|
||||||
|
|
||||||
|
print "> HTTPD_CONFIG: ${HTTPD_CONFIG_DIR}"
|
||||||
|
print "> PROXY_HOSTNAME: ${PROXY_HOSTNAME}"
|
||||||
|
print "> PROXY_PORT: ${PROXY_PORT}"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
start_devkeycloak-proxy() {
|
||||||
|
begin "Starting devkeycloak-proxy ..."
|
||||||
|
|
||||||
|
init_devkeycloak-proxy
|
||||||
|
kill_container_if_exist devkeycloak-proxy
|
||||||
|
|
||||||
|
MOUNT_HTTPD_CONFIG_DIR=$CONF_DIR/httpd
|
||||||
|
|
||||||
|
mkdir -p $MOUNT_HTTPD_CONFIG_DIR
|
||||||
|
${BIN_DIR}/gen-httpd-conf ${HTTPD_CONFIG_DIR} $ENV_FILE $MOUNT_HTTPD_CONFIG_DIR/httpd.conf
|
||||||
|
print "> EFFECTIVE HTTPD_CONFIG_FILE: $MOUNT_HTTPD_CONFIG_DIR/httpd.conf"
|
||||||
|
cp ${HTTPD_CONFIG_DIR}/.htpasswd $MOUNT_HTTPD_CONFIG_DIR
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--detach \
|
||||||
|
--name devkeycloak-proxy \
|
||||||
|
--net ${DOCKER_NETWORK} \
|
||||||
|
--publish 9092:9092 \
|
||||||
|
--mount "type=bind,source=${MOUNT_HTTPD_CONFIG_DIR},target=/usr/local/apache2/conf" \
|
||||||
|
${HTTPD_DOCKER_IMAGE}
|
||||||
|
|
||||||
|
#wait_for_url $OAUTH_PROVIDER_URL ${FORWARD_PROXY_URL}
|
||||||
|
wait_for_message devkeycloak-proxy "initializing worker proxy:forward local"
|
||||||
|
end "devkeycloak-proxy is ready"
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
|
||||||
|
HTTPD_DOCKER_IMAGE=httpd:latest
|
||||||
|
|
||||||
|
ensure_forward-proxy() {
|
||||||
|
if docker ps | grep forward-proxy &> /dev/null; then
|
||||||
|
print "forward-proxy already running ..."
|
||||||
|
else
|
||||||
|
start_forward-proxy
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
init_forward-proxy() {
|
||||||
|
HTTPD_CONFIG_DIR=${TEST_CONFIG_DIR}/forward-proxy
|
||||||
|
PROXY_HOSTNAME=forward-proxy
|
||||||
|
PROXY_PORT=9092
|
||||||
|
|
||||||
|
print "> HTTPD_CONFIG: ${HTTPD_CONFIG_DIR}"
|
||||||
|
print "> OAUTH_PROVIDER_URL: ${OAUTH_PROVIDER_URL}"
|
||||||
|
print "> PROXY_HOSTNAME: ${PROXY_HOSTNAME}"
|
||||||
|
print "> PROXY_PORT: ${PROXY_PORT}"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
start_forward-proxy() {
|
||||||
|
begin "Starting forward-proxy ..."
|
||||||
|
|
||||||
|
init_forward-proxy
|
||||||
|
kill_container_if_exist forward-proxy
|
||||||
|
|
||||||
|
MOUNT_HTTPD_CONFIG_DIR=$CONF_DIR/httpd
|
||||||
|
|
||||||
|
mkdir -p $MOUNT_HTTPD_CONFIG_DIR
|
||||||
|
${BIN_DIR}/gen-httpd-conf ${HTTPD_CONFIG_DIR} $ENV_FILE $MOUNT_HTTPD_CONFIG_DIR/httpd.conf
|
||||||
|
print "> EFFECTIVE HTTPD_CONFIG_FILE: $MOUNT_HTTPD_CONFIG_DIR/httpd.conf"
|
||||||
|
cp ${HTTPD_CONFIG_DIR}/.htpasswd $MOUNT_HTTPD_CONFIG_DIR
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--detach \
|
||||||
|
--name forward-proxy \
|
||||||
|
--net ${DOCKER_NETWORK} \
|
||||||
|
--publish 9092:9092 \
|
||||||
|
--mount "type=bind,source=${MOUNT_HTTPD_CONFIG_DIR},target=/usr/local/apache2/conf" \
|
||||||
|
${HTTPD_DOCKER_IMAGE}
|
||||||
|
|
||||||
|
#wait_for_url $OAUTH_PROVIDER_URL ${FORWARD_PROXY_URL}
|
||||||
|
wait_for_message forward-proxy "initializing worker proxy:forward local"
|
||||||
|
end "forward-proxy is ready"
|
||||||
|
}
|
|
@ -12,8 +12,7 @@ ensure_keycloak() {
|
||||||
init_keycloak() {
|
init_keycloak() {
|
||||||
KEYCLOAK_CONFIG_PATH=${KEYCLOAK_CONFIG_PATH:-oauth/keycloak}
|
KEYCLOAK_CONFIG_PATH=${KEYCLOAK_CONFIG_PATH:-oauth/keycloak}
|
||||||
KEYCLOAK_CONFIG_DIR=$(realpath ${TEST_DIR}/${KEYCLOAK_CONFIG_PATH})
|
KEYCLOAK_CONFIG_DIR=$(realpath ${TEST_DIR}/${KEYCLOAK_CONFIG_PATH})
|
||||||
KEYCLOAK_URL=${OAUTH_PROVIDER_URL}
|
|
||||||
|
|
||||||
print "> KEYCLOAK_CONFIG_DIR: ${KEYCLOAK_CONFIG_DIR}"
|
print "> KEYCLOAK_CONFIG_DIR: ${KEYCLOAK_CONFIG_DIR}"
|
||||||
print "> KEYCLOAK_URL: ${KEYCLOAK_URL}"
|
print "> KEYCLOAK_URL: ${KEYCLOAK_URL}"
|
||||||
print "> KEYCLOAK_DOCKER_IMAGE: ${KEYCLOAK_DOCKER_IMAGE}"
|
print "> KEYCLOAK_DOCKER_IMAGE: ${KEYCLOAK_DOCKER_IMAGE}"
|
||||||
|
@ -42,8 +41,9 @@ start_keycloak() {
|
||||||
--publish 8443:8443 \
|
--publish 8443:8443 \
|
||||||
--env KEYCLOAK_ADMIN=admin \
|
--env KEYCLOAK_ADMIN=admin \
|
||||||
--env KEYCLOAK_ADMIN_PASSWORD=admin \
|
--env KEYCLOAK_ADMIN_PASSWORD=admin \
|
||||||
|
--env QUARKUS_HTTP_ACCESS_LOG_ENABLED=true \
|
||||||
-v ${MOUNT_KEYCLOAK_CONF_DIR}:/opt/keycloak/data/import/ \
|
-v ${MOUNT_KEYCLOAK_CONF_DIR}:/opt/keycloak/data/import/ \
|
||||||
${KEYCLOAK_DOCKER_IMAGE} start-dev --import-realm \
|
${KEYCLOAK_DOCKER_IMAGE} start-dev --import-realm --log-level=INFO \
|
||||||
--https-certificate-file=/opt/keycloak/data/import/server_keycloak_certificate.pem \
|
--https-certificate-file=/opt/keycloak/data/import/server_keycloak_certificate.pem \
|
||||||
--https-certificate-key-file=/opt/keycloak/data/import/server_keycloak_key.pem
|
--https-certificate-key-file=/opt/keycloak/data/import/server_keycloak_key.pem
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
HTTPD_DOCKER_IMAGE=httpd:latest
|
||||||
|
|
||||||
|
ensure_prodkeycloak-proxy() {
|
||||||
|
if docker ps | grep prodkeycloak-proxy &> /dev/null; then
|
||||||
|
print "prodkeycloak-proxy already running ..."
|
||||||
|
else
|
||||||
|
start_prodkeycloak-proxy
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
init_prodkeycloak-proxy() {
|
||||||
|
HTTPD_CONFIG_DIR=${TEST_CONFIG_DIR}/prodkeycloak-proxy
|
||||||
|
PROXY_HOSTNAME=prodkeycloak-proxy
|
||||||
|
PROXY_PORT=9091
|
||||||
|
|
||||||
|
print "> HTTPD_CONFIG: ${HTTPD_CONFIG_DIR}"
|
||||||
|
print "> PROXY_HOSTNAME: ${PROXY_HOSTNAME}"
|
||||||
|
print "> PROXY_PORT: ${PROXY_PORT}"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
start_prodkeycloak-proxy() {
|
||||||
|
begin "Starting prodkeycloak-proxy ..."
|
||||||
|
|
||||||
|
init_prodkeycloak-proxy
|
||||||
|
kill_container_if_exist prodkeycloak-proxy
|
||||||
|
|
||||||
|
MOUNT_HTTPD_CONFIG_DIR=$CONF_DIR/httpd
|
||||||
|
|
||||||
|
mkdir -p $MOUNT_HTTPD_CONFIG_DIR
|
||||||
|
${BIN_DIR}/gen-httpd-conf ${HTTPD_CONFIG_DIR} $ENV_FILE $MOUNT_HTTPD_CONFIG_DIR/httpd.conf
|
||||||
|
print "> EFFECTIVE HTTPD_CONFIG_FILE: $MOUNT_HTTPD_CONFIG_DIR/httpd.conf"
|
||||||
|
cp ${HTTPD_CONFIG_DIR}/.htpasswd $MOUNT_HTTPD_CONFIG_DIR
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--detach \
|
||||||
|
--name prodkeycloak-proxy \
|
||||||
|
--net ${DOCKER_NETWORK} \
|
||||||
|
--publish 9091:9091 \
|
||||||
|
--mount "type=bind,source=${MOUNT_HTTPD_CONFIG_DIR},target=/usr/local/apache2/conf" \
|
||||||
|
${HTTPD_DOCKER_IMAGE}
|
||||||
|
|
||||||
|
wait_for_message prodkeycloak-proxy "initializing worker proxy:forward local"
|
||||||
|
end "prodkeycloak-proxy is ready"
|
||||||
|
}
|
|
@ -214,20 +214,37 @@ wait_for_oidc_endpoint_docker() {
|
||||||
calculate_rabbitmq_url() {
|
calculate_rabbitmq_url() {
|
||||||
echo "${RABBITMQ_SCHEME:-http}://$1${PUBLIC_RABBITMQ_PATH:-$RABBITMQ_PATH}"
|
echo "${RABBITMQ_SCHEME:-http}://$1${PUBLIC_RABBITMQ_PATH:-$RABBITMQ_PATH}"
|
||||||
}
|
}
|
||||||
|
calculate_forward_proxy_url() {
|
||||||
|
PROXIED_URL=$1
|
||||||
|
PROXY_HOSTNAME=$2
|
||||||
|
PROXY_PORT=$3
|
||||||
|
SCHEME=$(echo "$PROXIED_URL" | cut -d: -f1)
|
||||||
|
PATH=$(echo "$PROXIED_URL" | cut -d/ -f4-)
|
||||||
|
echo "$SCHEME://$PROXY_HOSTNAME:$PROXY_PORT/$PATH"
|
||||||
|
}
|
||||||
wait_for_url() {
|
wait_for_url() {
|
||||||
BASE_URL=$1
|
BASE_URL=$1
|
||||||
if [[ $BASE_URL == *"localhost"** ]]; then
|
if [[ $BASE_URL == *"localhost"** ]]; then
|
||||||
wait_for_url_local $BASE_URL
|
wait_for_url_local $@
|
||||||
else
|
else
|
||||||
wait_for_url_docker $BASE_URL
|
wait_for_url_docker $@
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
wait_for_url_local() {
|
wait_for_url_local() {
|
||||||
url=$1
|
url=$1
|
||||||
|
proxy=${2:-none}
|
||||||
|
proxy_user=${3:-none}
|
||||||
|
proxy_pass=$4
|
||||||
|
curl_args="-L -f -v"
|
||||||
max_retry=10
|
max_retry=10
|
||||||
counter=0
|
counter=0
|
||||||
until (curl -L -f -v $url >/dev/null 2>&1)
|
if [[ "$proxy" != "none" && "$proxy" != "" ]]; then
|
||||||
|
curl_args="--proxy ${proxy} ${curl_args}"
|
||||||
|
fi
|
||||||
|
if [[ "$proxy_user" != "none" && "$proxy_user" != "" ]]; then
|
||||||
|
curl_args="--proxy-user ${proxy_user}:${proxy_pass} ${curl_args}"
|
||||||
|
fi
|
||||||
|
until (curl $curl_args $url >/dev/null 2>&1)
|
||||||
do
|
do
|
||||||
print "Waiting for $url to start (local)"
|
print "Waiting for $url to start (local)"
|
||||||
sleep 5
|
sleep 5
|
||||||
|
@ -240,7 +257,14 @@ wait_for_url_docker() {
|
||||||
url=$1
|
url=$1
|
||||||
max_retry=10
|
max_retry=10
|
||||||
counter=0
|
counter=0
|
||||||
until (docker run --net ${DOCKER_NETWORK} --rm curlimages/curl:7.85.0 -L -f -v $url >/dev/null 2>&1)
|
curl_args="-L -f -v"
|
||||||
|
if [[ "$proxy" != "none" && "$proxy" != "" ]]; then
|
||||||
|
curl_args="--proxy ${proxy} ${curl_args}"
|
||||||
|
fi
|
||||||
|
if [[ "$proxy_user" != "none" && "$proxy_user" != "" ]]; then
|
||||||
|
curl_args="--proxy-user ${proxy_user}:${proxy_pass} ${curl_args}"
|
||||||
|
fi
|
||||||
|
until (docker run --net ${DOCKER_NETWORK} --rm curlimages/curl:7.85.0 $curl_args $url >/dev/null 2>&1)
|
||||||
do
|
do
|
||||||
print "Waiting for $url to start (docker)"
|
print "Waiting for $url to start (docker)"
|
||||||
sleep 5
|
sleep 5
|
||||||
|
@ -373,7 +397,8 @@ profiles_with_local_or_docker() {
|
||||||
generate_env_file() {
|
generate_env_file() {
|
||||||
begin "Generating env file ..."
|
begin "Generating env file ..."
|
||||||
mkdir -p $CONF_DIR
|
mkdir -p $CONF_DIR
|
||||||
${BIN_DIR}/gen-env-file $TEST_CONFIG_DIR $ENV_FILE
|
${BIN_DIR}/gen-env-file $TEST_CONFIG_DIR ${ENV_FILE}.tmp
|
||||||
|
grep -v '^#' ${ENV_FILE}.tmp > $ENV_FILE
|
||||||
source $ENV_FILE
|
source $ENV_FILE
|
||||||
end "Finished generating env file."
|
end "Finished generating env file."
|
||||||
}
|
}
|
||||||
|
@ -541,7 +566,7 @@ run_on_docker_with() {
|
||||||
build_mocha_image
|
build_mocha_image
|
||||||
start_selenium
|
start_selenium
|
||||||
|
|
||||||
trap teardown_components EXIT
|
trap "teardown_components" EXIT
|
||||||
|
|
||||||
start_components
|
start_components
|
||||||
test
|
test
|
||||||
|
@ -622,7 +647,6 @@ start_components() {
|
||||||
$start
|
$start
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
teardown_components() {
|
teardown_components() {
|
||||||
skip_rabbitmq=${1:-false}
|
skip_rabbitmq=${1:-false}
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,14 @@ authnz-mgt/multi-oauth-with-basic-auth-when-idps-down.sh
|
||||||
authnz-mgt/multi-oauth-with-basic-auth.sh
|
authnz-mgt/multi-oauth-with-basic-auth.sh
|
||||||
authnz-mgt/multi-oauth-without-basic-auth-and-resource-label-and-scopes.sh
|
authnz-mgt/multi-oauth-without-basic-auth-and-resource-label-and-scopes.sh
|
||||||
authnz-mgt/multi-oauth-without-basic-auth.sh
|
authnz-mgt/multi-oauth-without-basic-auth.sh
|
||||||
|
authnz-mgt/multi-oauth-via-proxies.sh
|
||||||
authnz-mgt/oauth-and-basic-auth.sh
|
authnz-mgt/oauth-and-basic-auth.sh
|
||||||
authnz-mgt/oauth-idp-initiated-with-uaa-and-prefix-via-proxy.sh
|
authnz-mgt/oauth-idp-initiated-with-uaa-and-prefix-via-proxy.sh
|
||||||
authnz-mgt/oauth-idp-initiated-with-uaa-and-prefix.sh
|
authnz-mgt/oauth-idp-initiated-with-uaa-and-prefix.sh
|
||||||
authnz-mgt/oauth-idp-initiated-with-uaa-via-proxy.sh
|
authnz-mgt/oauth-idp-initiated-with-uaa-via-proxy.sh
|
||||||
authnz-mgt/oauth-idp-initiated-with-uaa.sh
|
authnz-mgt/oauth-idp-initiated-with-uaa.sh
|
||||||
authnz-mgt/oauth-with-keycloak.sh
|
authnz-mgt/oauth-with-keycloak.sh
|
||||||
|
authnz-mgt/oauth-with-keycloak-via-forward-proxy.sh
|
||||||
authnz-mgt/oauth-with-keycloak-with-verify-none.sh
|
authnz-mgt/oauth-with-keycloak-with-verify-none.sh
|
||||||
authnz-mgt/oauth-with-uaa-down-but-with-basic-auth.sh
|
authnz-mgt/oauth-with-uaa-down-but-with-basic-auth.sh
|
||||||
authnz-mgt/oauth-with-uaa-down.sh
|
authnz-mgt/oauth-with-uaa-down.sh
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
TEST_CASES_PATH=/multi-oauth/without-basic-auth
|
||||||
|
TEST_CONFIG_PATH=/multi-oauth
|
||||||
|
PROFILES="devkeycloak prodkeycloak with-resource-label with-resource-scopes tls devkeycloak-proxy prodkeycloak-proxy"
|
||||||
|
|
||||||
|
source $SCRIPT/../../bin/suite_template $@
|
||||||
|
runWith devkeycloak prodkeycloak devkeycloak-proxy prodkeycloak-proxy
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
TEST_CASES_PATH=/oauth/with-sp-initiated
|
||||||
|
TEST_CONFIG_PATH=/oauth
|
||||||
|
PROFILES="forward-proxy keycloak forward-proxy-oauth-provider keycloak-mgt-oauth-provider tls"
|
||||||
|
|
||||||
|
source $SCRIPT/../../bin/suite_template $@
|
||||||
|
runWith keycloak forward-proxy
|
|
@ -3,16 +3,12 @@ const { tokenFor, openIdConfiguration } = require('../utils')
|
||||||
const { reset, expectUser, expectVhost, expectResource, allow, verifyAll } = require('../mock_http_backend')
|
const { reset, expectUser, expectVhost, expectResource, allow, verifyAll } = require('../mock_http_backend')
|
||||||
const { open: openAmqp, once: onceAmqp, on: onAmqp, close: closeAmqp } = require('../amqp')
|
const { open: openAmqp, once: onceAmqp, on: onAmqp, close: closeAmqp } = require('../amqp')
|
||||||
|
|
||||||
var receivedAmqpMessageCount = 0
|
|
||||||
var untilConnectionEstablished = new Promise((resolve, reject) => {
|
var untilConnectionEstablished = new Promise((resolve, reject) => {
|
||||||
onAmqp('connection_open', function(context) {
|
onAmqp('connection_open', function(context) {
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
onAmqp('message', function (context) {
|
|
||||||
receivedAmqpMessageCount++
|
|
||||||
})
|
|
||||||
onceAmqp('sendable', function (context) {
|
onceAmqp('sendable', function (context) {
|
||||||
context.sender.send({body:'first message'})
|
context.sender.send({body:'first message'})
|
||||||
})
|
})
|
||||||
|
@ -52,16 +48,21 @@ describe('Having AMQP 1.0 protocol enabled and the following auth_backends: ' +
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can open an AMQP 1.0 connection', async function () {
|
it('can open an AMQP 1.0 connection', async function () {
|
||||||
|
var untilFirstMessageReceived = new Promise((resolve, reject) => {
|
||||||
|
onAmqp('message', function(context) {
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
amqp = openAmqp()
|
amqp = openAmqp()
|
||||||
await untilConnectionEstablished
|
await untilConnectionEstablished
|
||||||
var untilMessageReceived = new Promise((resolve, reject) => {
|
await untilFirstMessageReceived
|
||||||
|
var untilSecondMessageReceived = new Promise((resolve, reject) => {
|
||||||
onAmqp('message', function(context) {
|
onAmqp('message', function(context) {
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
amqp.sender.send({body:'second message'})
|
amqp.sender.send({body:'second message'})
|
||||||
await untilMessageReceived
|
await untilSecondMessageReceived
|
||||||
assert.equal(2, receivedAmqpMessageCount)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
after(function () {
|
after(function () {
|
||||||
|
|
|
@ -27,35 +27,32 @@ describe('management user with vhosts permissions', function () {
|
||||||
it('can access overview tab', async function () {
|
it('can access overview tab', async function () {
|
||||||
await overview.clickOnOverviewTab()
|
await overview.clickOnOverviewTab()
|
||||||
await overview.waitForOverviewTab()
|
await overview.waitForOverviewTab()
|
||||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||||
})
|
})
|
||||||
it('can access connections tab', async function () {
|
it('can access connections tab', async function () {
|
||||||
await overview.clickOnConnectionsTab()
|
await overview.clickOnConnectionsTab()
|
||||||
await overview.waitForConnectionsTab()
|
await overview.waitForConnectionsTab()
|
||||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||||
})
|
})
|
||||||
it('can access channels tab', async function () {
|
it('can access channels tab', async function () {
|
||||||
await overview.clickOnChannelsTab()
|
await overview.clickOnChannelsTab()
|
||||||
await overview.waitForChannelsTab()
|
await overview.waitForChannelsTab()
|
||||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||||
})
|
})
|
||||||
it('can access exchanges tab', async function () {
|
it('can access exchanges tab', async function () {
|
||||||
await overview.clickOnExchangesTab()
|
await overview.clickOnExchangesTab()
|
||||||
await overview.waitForExchangesTab()
|
await overview.waitForExchangesTab()
|
||||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||||
})
|
})
|
||||||
it('can access queues and streams tab', async function () {
|
it('can access queues and streams tab', async function () {
|
||||||
await overview.clickOnQueuesTab()
|
await overview.clickOnQueuesTab()
|
||||||
await overview.waitForQueuesTab()
|
await overview.waitForQueuesTab()
|
||||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||||
})
|
})
|
||||||
it('can access limited options in admin tab', async function () {
|
it('can access limited options in admin tab', async function () {
|
||||||
console.log("before clickOnAdminTab")
|
|
||||||
await overview.clickOnAdminTab()
|
await overview.clickOnAdminTab()
|
||||||
console.log("before waitForAdminTab")
|
|
||||||
await overview.waitForAdminTab()
|
await overview.waitForAdminTab()
|
||||||
console.log("after waitForAdminTab")
|
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('cannot add/update user limits', async function () {
|
it('cannot add/update user limits', async function () {
|
||||||
|
|
|
@ -19,7 +19,6 @@ describe('An user without management tag', function () {
|
||||||
overview = new OverviewPage(driver)
|
overview = new OverviewPage(driver)
|
||||||
captureScreen = captureScreensFor(driver, __filename)
|
captureScreen = captureScreensFor(driver, __filename)
|
||||||
|
|
||||||
//assert.ok(!await login.isPopupWarningDisplayed())
|
|
||||||
await login.login('rabbit_no_management', 'guest')
|
await login.login('rabbit_no_management', 'guest')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -45,8 +44,8 @@ describe('An user without management tag', function () {
|
||||||
|
|
||||||
it('should close popup warning', async function(){
|
it('should close popup warning', async function(){
|
||||||
await delay(1000)
|
await delay(1000)
|
||||||
const visible = await login.isPopupWarningDisplayed()
|
const visible =
|
||||||
assert.ok(!visible)
|
assert.ok(await login.isPopupWarningNotDisplayed())
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
guest:{SHA}NWdeaPS1r3uZXZIFrQ/EOELxZFA=
|
|
@ -0,0 +1,147 @@
|
||||||
|
#
|
||||||
|
# This is the main Apache HTTP server configuration file. It contains the
|
||||||
|
# configuration directives that give the server its instructions.
|
||||||
|
# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
|
||||||
|
# In particular, see
|
||||||
|
# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
|
||||||
|
# for a discussion of each configuration directive.
|
||||||
|
#
|
||||||
|
# Do NOT simply read the instructions in here without understanding
|
||||||
|
# what they do. They're here only as hints or reminders. If you are unsure
|
||||||
|
# consult the online docs. You have been warned.
|
||||||
|
#
|
||||||
|
# Configuration and logfile names: If the filenames you specify for many
|
||||||
|
# of the server's control files begin with "/" (or "drive:/" for Win32), the
|
||||||
|
# server will use that explicit path. If the filenames do *not* begin
|
||||||
|
# with "/", the value of ServerRoot is prepended -- so "logs/access_log"
|
||||||
|
# with ServerRoot set to "/usr/local/apache2" will be interpreted by the
|
||||||
|
# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
|
||||||
|
# will be interpreted as '/logs/access_log'.
|
||||||
|
|
||||||
|
#
|
||||||
|
# ServerRoot: The top of the directory tree under which the server's
|
||||||
|
# configuration, error, and log files are kept.
|
||||||
|
#
|
||||||
|
# Do not add a slash at the end of the directory path. If you point
|
||||||
|
# ServerRoot at a non-local disk, be sure to specify a local disk on the
|
||||||
|
# Mutex directive, if file-based mutexes are used. If you wish to share the
|
||||||
|
# same ServerRoot for multiple httpd daemons, you will need to change at
|
||||||
|
# least PidFile.
|
||||||
|
#
|
||||||
|
ServerRoot "/usr/local/apache2"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Mutex: Allows you to set the mutex mechanism and mutex file directory
|
||||||
|
# for individual mutexes, or change the global defaults
|
||||||
|
#
|
||||||
|
# Uncomment and change the directory if mutexes are file-based and the default
|
||||||
|
# mutex file directory is not on a local disk or is not appropriate for some
|
||||||
|
# other reason.
|
||||||
|
#
|
||||||
|
# Mutex default:logs
|
||||||
|
|
||||||
|
#
|
||||||
|
# Listen: Allows you to bind Apache to specific IP addresses and/or
|
||||||
|
# ports, instead of the default. See also the <VirtualHost>
|
||||||
|
# directive.
|
||||||
|
#
|
||||||
|
# Change this to Listen on specific IP addresses as shown below to
|
||||||
|
# prevent Apache from glomming onto all bound IP addresses.
|
||||||
|
#
|
||||||
|
#Listen 12.34.56.78:80
|
||||||
|
Listen 9092
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dynamic Shared Object (DSO) Support
|
||||||
|
#
|
||||||
|
# To be able to use the functionality of a module which was built as a DSO you
|
||||||
|
# have to place corresponding `LoadModule' lines at this location so the
|
||||||
|
# directives contained in it are actually available _before_ they are used.
|
||||||
|
# Statically compiled modules (those listed by `httpd -l') do not need
|
||||||
|
# to be loaded here.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# LoadModule foo_module modules/mod_foo.so
|
||||||
|
#
|
||||||
|
|
||||||
|
LoadModule mpm_event_module modules/mod_mpm_event.so
|
||||||
|
LoadModule access_compat_module modules/mod_access_compat.so
|
||||||
|
LoadModule log_config_module modules/mod_log_config.so
|
||||||
|
LoadModule auth_basic_module modules/mod_auth_basic.so
|
||||||
|
LoadModule authn_core_module modules/mod_authn_core.so
|
||||||
|
LoadModule authz_core_module modules/mod_authz_core.so
|
||||||
|
LoadModule authn_file_module modules/mod_authn_file.so
|
||||||
|
LoadModule authz_user_module modules/mod_authz_user.so
|
||||||
|
LoadModule proxy_module modules/mod_proxy.so
|
||||||
|
LoadModule proxy_connect_module modules/mod_proxy_connect.so
|
||||||
|
LoadModule proxy_http_module modules/mod_proxy_http.so
|
||||||
|
LoadModule ssl_module modules/mod_ssl.so
|
||||||
|
LoadModule unixd_module modules/mod_unixd.so
|
||||||
|
|
||||||
|
<IfModule unixd_module>
|
||||||
|
User www-data
|
||||||
|
Group www-data
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
|
||||||
|
ServerAdmin you@example.com
|
||||||
|
|
||||||
|
ServerName devkeycloak-proxy
|
||||||
|
|
||||||
|
ErrorLog /proc/self/fd/2
|
||||||
|
|
||||||
|
LogLevel warn
|
||||||
|
|
||||||
|
<IfModule log_config_module>
|
||||||
|
#
|
||||||
|
# The following directives define some format nicknames for use with
|
||||||
|
# a CustomLog directive (see below).
|
||||||
|
#
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||||
|
|
||||||
|
<IfModule logio_module>
|
||||||
|
# You need to enable mod_logio.c to use %I and %O
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
#
|
||||||
|
# The location and format of the access logfile (Common Logfile Format).
|
||||||
|
# If you do not define any access logfiles within a <VirtualHost>
|
||||||
|
# container, they will be logged here. Contrariwise, if you *do*
|
||||||
|
# define per-<VirtualHost> access logfiles, transactions will be
|
||||||
|
# logged therein and *not* in this file.
|
||||||
|
#
|
||||||
|
CustomLog logs/access_log common
|
||||||
|
|
||||||
|
#
|
||||||
|
# If you prefer a logfile with access, agent, and referer information
|
||||||
|
# (Combined Logfile Format) you can use the following directive.
|
||||||
|
#
|
||||||
|
#CustomLog "logs/access_log" combined
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule proxy_module>
|
||||||
|
ProxyRequests On
|
||||||
|
ProxyVia On
|
||||||
|
<Proxy *>
|
||||||
|
Allow from all
|
||||||
|
</Proxy>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
|
||||||
|
<VirtualHost *:9092>
|
||||||
|
AllowCONNECT 8442
|
||||||
|
|
||||||
|
ProxyRequests On
|
||||||
|
ProxyVia On
|
||||||
|
LogLevel debug
|
||||||
|
ErrorLog /dev/stderr
|
||||||
|
CustomLog /dev/stdout combined
|
||||||
|
|
||||||
|
<Proxy "*">
|
||||||
|
Allow from all
|
||||||
|
|
||||||
|
|
||||||
|
</Proxy>
|
||||||
|
</VirtualHost>
|
|
@ -0,0 +1,2 @@
|
||||||
|
export DEVKEYCLOAK_PROXY_HOST=devkeycloak-proxy
|
||||||
|
export DEVKEYCLOAK_PROXY_PORT=9092
|
|
@ -0,0 +1,4 @@
|
||||||
|
export PRODKEYCLOAK_PROXY_HOST=prodkeycloak-proxy
|
||||||
|
export PRODKEYCLOAK_PROXY_PORT=9091
|
||||||
|
export PRODKEYCLOAK_PROXY_USERNAME=guest
|
||||||
|
export PRODKEYCLOAK_PROXY_PASSWORD=guest
|
|
@ -0,0 +1,2 @@
|
||||||
|
export DEVKEYCLOAK_PROXY_HOST=devkeycloak-proxy
|
||||||
|
export DEVKEYCLOAK_PROXY_PORT=9092
|
|
@ -0,0 +1,4 @@
|
||||||
|
export PRODKEYCLOAK_PROXY_HOST=prodkeycloak-proxy
|
||||||
|
export PRODKEYCLOAK_PROXY_PORT=9091
|
||||||
|
export PRODKEYCLOAK_PROXY_USERNAME=guest
|
||||||
|
export PRODKEYCLOAK_PROXY_PASSWORD=guest
|
|
@ -0,0 +1 @@
|
||||||
|
guest:{SHA}NWdeaPS1r3uZXZIFrQ/EOELxZFA=
|
|
@ -0,0 +1,151 @@
|
||||||
|
#
|
||||||
|
# This is the main Apache HTTP server configuration file. It contains the
|
||||||
|
# configuration directives that give the server its instructions.
|
||||||
|
# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
|
||||||
|
# In particular, see
|
||||||
|
# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
|
||||||
|
# for a discussion of each configuration directive.
|
||||||
|
#
|
||||||
|
# Do NOT simply read the instructions in here without understanding
|
||||||
|
# what they do. They're here only as hints or reminders. If you are unsure
|
||||||
|
# consult the online docs. You have been warned.
|
||||||
|
#
|
||||||
|
# Configuration and logfile names: If the filenames you specify for many
|
||||||
|
# of the server's control files begin with "/" (or "drive:/" for Win32), the
|
||||||
|
# server will use that explicit path. If the filenames do *not* begin
|
||||||
|
# with "/", the value of ServerRoot is prepended -- so "logs/access_log"
|
||||||
|
# with ServerRoot set to "/usr/local/apache2" will be interpreted by the
|
||||||
|
# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
|
||||||
|
# will be interpreted as '/logs/access_log'.
|
||||||
|
|
||||||
|
#
|
||||||
|
# ServerRoot: The top of the directory tree under which the server's
|
||||||
|
# configuration, error, and log files are kept.
|
||||||
|
#
|
||||||
|
# Do not add a slash at the end of the directory path. If you point
|
||||||
|
# ServerRoot at a non-local disk, be sure to specify a local disk on the
|
||||||
|
# Mutex directive, if file-based mutexes are used. If you wish to share the
|
||||||
|
# same ServerRoot for multiple httpd daemons, you will need to change at
|
||||||
|
# least PidFile.
|
||||||
|
#
|
||||||
|
ServerRoot "/usr/local/apache2"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Mutex: Allows you to set the mutex mechanism and mutex file directory
|
||||||
|
# for individual mutexes, or change the global defaults
|
||||||
|
#
|
||||||
|
# Uncomment and change the directory if mutexes are file-based and the default
|
||||||
|
# mutex file directory is not on a local disk or is not appropriate for some
|
||||||
|
# other reason.
|
||||||
|
#
|
||||||
|
# Mutex default:logs
|
||||||
|
|
||||||
|
#
|
||||||
|
# Listen: Allows you to bind Apache to specific IP addresses and/or
|
||||||
|
# ports, instead of the default. See also the <VirtualHost>
|
||||||
|
# directive.
|
||||||
|
#
|
||||||
|
# Change this to Listen on specific IP addresses as shown below to
|
||||||
|
# prevent Apache from glomming onto all bound IP addresses.
|
||||||
|
#
|
||||||
|
#Listen 12.34.56.78:80
|
||||||
|
Listen 9091
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dynamic Shared Object (DSO) Support
|
||||||
|
#
|
||||||
|
# To be able to use the functionality of a module which was built as a DSO you
|
||||||
|
# have to place corresponding `LoadModule' lines at this location so the
|
||||||
|
# directives contained in it are actually available _before_ they are used.
|
||||||
|
# Statically compiled modules (those listed by `httpd -l') do not need
|
||||||
|
# to be loaded here.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# LoadModule foo_module modules/mod_foo.so
|
||||||
|
#
|
||||||
|
|
||||||
|
LoadModule mpm_event_module modules/mod_mpm_event.so
|
||||||
|
LoadModule access_compat_module modules/mod_access_compat.so
|
||||||
|
LoadModule log_config_module modules/mod_log_config.so
|
||||||
|
LoadModule auth_basic_module modules/mod_auth_basic.so
|
||||||
|
LoadModule authn_core_module modules/mod_authn_core.so
|
||||||
|
LoadModule authz_core_module modules/mod_authz_core.so
|
||||||
|
LoadModule authn_file_module modules/mod_authn_file.so
|
||||||
|
LoadModule authz_user_module modules/mod_authz_user.so
|
||||||
|
LoadModule proxy_module modules/mod_proxy.so
|
||||||
|
LoadModule proxy_connect_module modules/mod_proxy_connect.so
|
||||||
|
LoadModule proxy_http_module modules/mod_proxy_http.so
|
||||||
|
LoadModule ssl_module modules/mod_ssl.so
|
||||||
|
LoadModule unixd_module modules/mod_unixd.so
|
||||||
|
|
||||||
|
<IfModule unixd_module>
|
||||||
|
User www-data
|
||||||
|
Group www-data
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
|
||||||
|
ServerAdmin you@example.com
|
||||||
|
|
||||||
|
ServerName prodkeycloak-proxy
|
||||||
|
|
||||||
|
ErrorLog /proc/self/fd/2
|
||||||
|
|
||||||
|
LogLevel warn
|
||||||
|
|
||||||
|
<IfModule log_config_module>
|
||||||
|
#
|
||||||
|
# The following directives define some format nicknames for use with
|
||||||
|
# a CustomLog directive (see below).
|
||||||
|
#
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||||
|
|
||||||
|
<IfModule logio_module>
|
||||||
|
# You need to enable mod_logio.c to use %I and %O
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
#
|
||||||
|
# The location and format of the access logfile (Common Logfile Format).
|
||||||
|
# If you do not define any access logfiles within a <VirtualHost>
|
||||||
|
# container, they will be logged here. Contrariwise, if you *do*
|
||||||
|
# define per-<VirtualHost> access logfiles, transactions will be
|
||||||
|
# logged therein and *not* in this file.
|
||||||
|
#
|
||||||
|
CustomLog logs/access_log common
|
||||||
|
|
||||||
|
#
|
||||||
|
# If you prefer a logfile with access, agent, and referer information
|
||||||
|
# (Combined Logfile Format) you can use the following directive.
|
||||||
|
#
|
||||||
|
#CustomLog "logs/access_log" combined
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule proxy_module>
|
||||||
|
ProxyRequests On
|
||||||
|
ProxyVia On
|
||||||
|
<Proxy *>
|
||||||
|
Allow from all
|
||||||
|
</Proxy>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
|
||||||
|
<VirtualHost *:9091>
|
||||||
|
AllowCONNECT 8443
|
||||||
|
|
||||||
|
ProxyRequests On
|
||||||
|
ProxyVia On
|
||||||
|
LogLevel debug
|
||||||
|
ErrorLog /dev/stderr
|
||||||
|
CustomLog /dev/stdout combined
|
||||||
|
|
||||||
|
<Proxy "*">
|
||||||
|
Allow from all
|
||||||
|
AuthType Basic
|
||||||
|
AuthName "Restricted Site"
|
||||||
|
AuthBasicProvider file
|
||||||
|
AuthUserFile /usr/local/apache2/conf/.htpasswd
|
||||||
|
Require valid-user
|
||||||
|
|
||||||
|
</Proxy>
|
||||||
|
</VirtualHost>
|
|
@ -0,0 +1,2 @@
|
||||||
|
auth_oauth2.oauth_providers.devkeycloak.proxy.host = ${DEVKEYCLOAK_PROXY_HOST}
|
||||||
|
auth_oauth2.oauth_providers.devkeycloak.proxy.port = ${DEVKEYCLOAK_PROXY_PORT}
|
|
@ -0,0 +1,4 @@
|
||||||
|
auth_oauth2.oauth_providers.prodkeycloak.proxy.host = ${PRODKEYCLOAK_PROXY_HOST}
|
||||||
|
auth_oauth2.oauth_providers.prodkeycloak.proxy.port = ${PRODKEYCLOAK_PROXY_PORT}
|
||||||
|
auth_oauth2.oauth_providers.prodkeycloak.proxy.username = ${PRODKEYCLOAK_PROXY_USERNAME}
|
||||||
|
auth_oauth2.oauth_providers.prodkeycloak.proxy.password = ${PRODKEYCLOAK_PROXY_PASSWORD}
|
|
@ -33,9 +33,7 @@ describe('When basic authentication is enabled but both Idps are down', function
|
||||||
|
|
||||||
it('should not be presented oauth2 section', async function () {
|
it('should not be presented oauth2 section', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
if (await homePage.isOAuth2SectionVisible()) {
|
assert.ok(await homePage.isOAuth2SectionNotVisible())
|
||||||
throw new Error('OAuth2 section should not be present')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -45,8 +45,7 @@ describe('Given two oauth resources and basic auth enabled, an unauthenticated u
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not have a warning message', async function () {
|
it('should not have a warning message', async function () {
|
||||||
const visible = await homePage.isWarningVisible()
|
assert.ok(await homePage.isWarningNotVisible())
|
||||||
assert.ok(!visible)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ describe('Given there are three oauth resources but two enabled', function () {
|
||||||
if (!await overview.isLoaded()) {
|
if (!await overview.isLoaded()) {
|
||||||
throw new Error('Failed to login')
|
throw new Error('Failed to login')
|
||||||
}
|
}
|
||||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||||
await overview.logout()
|
await overview.logout()
|
||||||
})
|
})
|
||||||
it('prod_user registered in prodkeycloak can log in using RabbitMQ Development OAuth 2.0 resource', async function () {
|
it('prod_user registered in prodkeycloak can log in using RabbitMQ Development OAuth 2.0 resource', async function () {
|
||||||
|
@ -46,7 +46,7 @@ describe('Given there are three oauth resources but two enabled', function () {
|
||||||
if (!await overview.isLoaded()) {
|
if (!await overview.isLoaded()) {
|
||||||
throw new Error('Failed to login')
|
throw new Error('Failed to login')
|
||||||
}
|
}
|
||||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||||
await overview.logout()
|
await overview.logout()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,11 @@ describe('Given three oauth resources but only two enabled, an unauthenticated u
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not be presented with a login button to log in using Basic Auth', async function () {
|
it('should not be presented with a login button to log in using Basic Auth', async function () {
|
||||||
assert.ok(!await homePage.isBasicAuthSectionVisible())
|
assert.ok(await homePage.isBasicAuthSectionNotVisible())
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not have a warning message', async function () {
|
it('should not have a warning message', async function () {
|
||||||
assert.ok(!await homePage.isWarningVisible())
|
assert.ok(await homePage.isWarningNotVisible())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export FORWARD_PROXY_HOST=forward-proxy
|
||||||
|
export FORWARD_PROXY_PORT=9092
|
||||||
|
export FORWARD_PROXY_USERNAME=guest
|
||||||
|
export FORWARD_PROXY_PASSWORD=guest
|
||||||
|
export OAUTH_PROVIDER_URL=${KEYCLOAK_URL}
|
||||||
|
export OAUTH_PROVIDER_CA_CERT=${KEYCLOAK_CA_CERT}
|
|
@ -1,3 +1,2 @@
|
||||||
export KEYCLOAK_URL=https://keycloak:8443/realms/test
|
export KEYCLOAK_URL=https://keycloak:8443/realms/test
|
||||||
export OAUTH_PROVIDER_URL=https://keycloak:8443/realms/test
|
export KEYCLOAK_CA_CERT=/config/oauth/keycloak/ca_keycloak_certificate.pem
|
||||||
export OAUTH_PROVIDER_CA_CERT=/config/oauth/keycloak/ca_keycloak_certificate.pem
|
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
# export OAUTH_PROVIDER_URL=${KEYCLOAK_URL}
|
export OAUTH_PROVIDER_URL=${KEYCLOAK_URL}
|
||||||
|
export OAUTH_PROVIDER_CA_CERT=${OAUTH_SERVER_CONFIG_DIR}/ca_keycloak_certificate.pem
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export FORWARD_PROXY_HOST=forward-proxy
|
||||||
|
export FORWARD_PROXY_PORT=9092
|
||||||
|
export FORWARD_PROXY_USERNAME=guest
|
||||||
|
export FORWARD_PROXY_PASSWORD=guest
|
||||||
|
export OAUTH_PROVIDER_URL=${KEYCLOAK_URL}
|
||||||
|
export OAUTH_PROVIDER_CA_CERT=${KEYCLOAK_CA_CERT}
|
|
@ -1,3 +1,2 @@
|
||||||
export KEYCLOAK_URL=https://localhost:8443/realms/test
|
export KEYCLOAK_URL=https://keycloak:8443/realms/test
|
||||||
export OAUTH_PROVIDER_URL=https://localhost:8443/realms/test
|
export KEYCLOAK_CA_CERT=selenium/test/oauth/keycloak/ca_keycloak_certificate.pem
|
||||||
export OAUTH_PROVIDER_CA_CERT=selenium/test/oauth/keycloak/ca_keycloak_certificate.pem
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
guest:{SHA}NWdeaPS1r3uZXZIFrQ/EOELxZFA=
|
|
@ -0,0 +1,165 @@
|
||||||
|
#
|
||||||
|
# This is the main Apache HTTP server configuration file. It contains the
|
||||||
|
# configuration directives that give the server its instructions.
|
||||||
|
# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
|
||||||
|
# In particular, see
|
||||||
|
# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
|
||||||
|
# for a discussion of each configuration directive.
|
||||||
|
#
|
||||||
|
# Do NOT simply read the instructions in here without understanding
|
||||||
|
# what they do. They're here only as hints or reminders. If you are unsure
|
||||||
|
# consult the online docs. You have been warned.
|
||||||
|
#
|
||||||
|
# Configuration and logfile names: If the filenames you specify for many
|
||||||
|
# of the server's control files begin with "/" (or "drive:/" for Win32), the
|
||||||
|
# server will use that explicit path. If the filenames do *not* begin
|
||||||
|
# with "/", the value of ServerRoot is prepended -- so "logs/access_log"
|
||||||
|
# with ServerRoot set to "/usr/local/apache2" will be interpreted by the
|
||||||
|
# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
|
||||||
|
# will be interpreted as '/logs/access_log'.
|
||||||
|
|
||||||
|
#
|
||||||
|
# ServerRoot: The top of the directory tree under which the server's
|
||||||
|
# configuration, error, and log files are kept.
|
||||||
|
#
|
||||||
|
# Do not add a slash at the end of the directory path. If you point
|
||||||
|
# ServerRoot at a non-local disk, be sure to specify a local disk on the
|
||||||
|
# Mutex directive, if file-based mutexes are used. If you wish to share the
|
||||||
|
# same ServerRoot for multiple httpd daemons, you will need to change at
|
||||||
|
# least PidFile.
|
||||||
|
#
|
||||||
|
ServerRoot "/usr/local/apache2"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Mutex: Allows you to set the mutex mechanism and mutex file directory
|
||||||
|
# for individual mutexes, or change the global defaults
|
||||||
|
#
|
||||||
|
# Uncomment and change the directory if mutexes are file-based and the default
|
||||||
|
# mutex file directory is not on a local disk or is not appropriate for some
|
||||||
|
# other reason.
|
||||||
|
#
|
||||||
|
# Mutex default:logs
|
||||||
|
|
||||||
|
#
|
||||||
|
# Listen: Allows you to bind Apache to specific IP addresses and/or
|
||||||
|
# ports, instead of the default. See also the <VirtualHost>
|
||||||
|
# directive.
|
||||||
|
#
|
||||||
|
# Change this to Listen on specific IP addresses as shown below to
|
||||||
|
# prevent Apache from glomming onto all bound IP addresses.
|
||||||
|
#
|
||||||
|
#Listen 12.34.56.78:80
|
||||||
|
Listen 9092
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dynamic Shared Object (DSO) Support
|
||||||
|
#
|
||||||
|
# To be able to use the functionality of a module which was built as a DSO you
|
||||||
|
# have to place corresponding `LoadModule' lines at this location so the
|
||||||
|
# directives contained in it are actually available _before_ they are used.
|
||||||
|
# Statically compiled modules (those listed by `httpd -l') do not need
|
||||||
|
# to be loaded here.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# LoadModule foo_module modules/mod_foo.so
|
||||||
|
#
|
||||||
|
|
||||||
|
LoadModule mpm_event_module modules/mod_mpm_event.so
|
||||||
|
LoadModule access_compat_module modules/mod_access_compat.so
|
||||||
|
LoadModule log_config_module modules/mod_log_config.so
|
||||||
|
LoadModule auth_basic_module modules/mod_auth_basic.so
|
||||||
|
LoadModule authn_core_module modules/mod_authn_core.so
|
||||||
|
LoadModule authz_core_module modules/mod_authz_core.so
|
||||||
|
LoadModule authn_file_module modules/mod_authn_file.so
|
||||||
|
LoadModule authz_user_module modules/mod_authz_user.so
|
||||||
|
LoadModule proxy_module modules/mod_proxy.so
|
||||||
|
LoadModule proxy_connect_module modules/mod_proxy_connect.so
|
||||||
|
LoadModule proxy_http_module modules/mod_proxy_http.so
|
||||||
|
LoadModule ssl_module modules/mod_ssl.so
|
||||||
|
LoadModule unixd_module modules/mod_unixd.so
|
||||||
|
|
||||||
|
<IfModule unixd_module>
|
||||||
|
User www-data
|
||||||
|
Group www-data
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
|
||||||
|
ServerAdmin you@example.com
|
||||||
|
|
||||||
|
ServerName forward-proxy
|
||||||
|
|
||||||
|
ErrorLog /proc/self/fd/2
|
||||||
|
|
||||||
|
LogLevel warn
|
||||||
|
|
||||||
|
<IfModule log_config_module>
|
||||||
|
#
|
||||||
|
# The following directives define some format nicknames for use with
|
||||||
|
# a CustomLog directive (see below).
|
||||||
|
#
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||||
|
|
||||||
|
<IfModule logio_module>
|
||||||
|
# You need to enable mod_logio.c to use %I and %O
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
#
|
||||||
|
# The location and format of the access logfile (Common Logfile Format).
|
||||||
|
# If you do not define any access logfiles within a <VirtualHost>
|
||||||
|
# container, they will be logged here. Contrariwise, if you *do*
|
||||||
|
# define per-<VirtualHost> access logfiles, transactions will be
|
||||||
|
# logged therein and *not* in this file.
|
||||||
|
#
|
||||||
|
CustomLog logs/access_log common
|
||||||
|
|
||||||
|
#
|
||||||
|
# If you prefer a logfile with access, agent, and referer information
|
||||||
|
# (Combined Logfile Format) you can use the following directive.
|
||||||
|
#
|
||||||
|
#CustomLog "logs/access_log" combined
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule proxy_module>
|
||||||
|
ProxyRequests On
|
||||||
|
ProxyVia On
|
||||||
|
<Proxy *>
|
||||||
|
Allow from all
|
||||||
|
</Proxy>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
|
||||||
|
<VirtualHost *:9092>
|
||||||
|
# SSLEngine on
|
||||||
|
# SSLCertificateKeyFile /usr/local/apache2/conf/server_forward-proxy_key.pem
|
||||||
|
# SSLCertificateFile /usr/local/apache2/conf/server_forward-proxy_certificate.pem
|
||||||
|
# SSLCertificateChainFile /usr/local/apache2/conf/ca_keycloak_certificate.pem
|
||||||
|
# SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
|
||||||
|
# SSLProxyVerify none
|
||||||
|
AllowCONNECT 8443
|
||||||
|
|
||||||
|
# SSLProxyEngine On
|
||||||
|
|
||||||
|
# SSLProxyVerify none
|
||||||
|
# SSLProxyCheckPeerCN off
|
||||||
|
# SSLProxyCheckPeerName off
|
||||||
|
# SSLProxyCheckPeerExpire off
|
||||||
|
# SSLProxyProtocol +TLSv1.2
|
||||||
|
|
||||||
|
ProxyRequests On
|
||||||
|
ProxyVia On
|
||||||
|
LogLevel debug
|
||||||
|
ErrorLog /dev/stderr
|
||||||
|
CustomLog /dev/stdout combined
|
||||||
|
|
||||||
|
<Proxy "*">
|
||||||
|
Allow from all
|
||||||
|
AuthType Basic
|
||||||
|
AuthName "Restricted Site"
|
||||||
|
AuthBasicProvider file
|
||||||
|
AuthUserFile /usr/local/apache2/conf/.htpasswd
|
||||||
|
Require valid-user
|
||||||
|
|
||||||
|
</Proxy>
|
||||||
|
</VirtualHost>
|
|
@ -56,6 +56,9 @@
|
||||||
"vhosts": [
|
"vhosts": [
|
||||||
{
|
{
|
||||||
"name": "/"
|
"name": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "other"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
auth_oauth2.issuer = ${OAUTH_PROVIDER_URL}
|
||||||
|
auth_oauth2.https.cacertfile = ${KEYCLOAK_CA_CERT}
|
||||||
|
auth_oauth2.proxy.host = ${FORWARD_PROXY_HOST}
|
||||||
|
auth_oauth2.proxy.port = ${FORWARD_PROXY_PORT}
|
||||||
|
auth_oauth2.proxy.username = ${FORWARD_PROXY_USERNAME}
|
||||||
|
auth_oauth2.proxy.password = ${FORWARD_PROXY_PASSWORD}
|
|
@ -1,3 +1,3 @@
|
||||||
# uaa requires a secret in order to renew tokens
|
# uaa requires a secret in order to renew tokens
|
||||||
management.oauth_provider_url = ${KEYCLOAK_URL}
|
#management.oauth_provider_url = ${KEYCLOAK_URL}
|
||||||
management.oauth_authorization_endpoint_params.resource = rabbitmq
|
management.oauth_authorization_endpoint_params.resource = rabbitmq
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
auth_oauth2.issuer = ${OAUTH_PROVIDER_URL}
|
auth_oauth2.issuer = ${KEYCLOAK_URL}
|
||||||
auth_oauth2.https.cacertfile = ${OAUTH_PROVIDER_CA_CERT}
|
auth_oauth2.https.cacertfile = ${KEYCLOAK_CA_CERT}
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
auth_oauth2.issuer = ${OAUTH_PROVIDER_URL}
|
auth_oauth2.issuer = ${KEYCLOAK_URL}
|
||||||
auth_oauth2.https.peer_verification = verify_none
|
auth_oauth2.https.peer_verification = verify_none
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
# uaa requires a secret in order to renew tokens
|
# uaa requires a secret in order to renew tokens
|
||||||
management.oauth_provider_url = ${UAA_URL}
|
management.oauth_provider_url = ${UAA_URL}
|
||||||
|
# uaa requires a secret in order to renew tokens
|
||||||
|
management.oauth_client_secret = ${OAUTH_CLIENT_SECRET}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
# uaa requires a secret in order to renew tokens
|
|
||||||
management.oauth_client_secret = ${OAUTH_CLIENT_SECRET}
|
|
||||||
|
|
||||||
# configure static signing keys and the oauth provider used by the plugin
|
# configure static signing keys and the oauth provider used by the plugin
|
||||||
auth_oauth2.default_key = ${OAUTH_SIGNING_KEY_ID}
|
auth_oauth2.default_key = ${OAUTH_SIGNING_KEY_ID}
|
||||||
|
|
|
@ -21,7 +21,7 @@ describe('When basic authentication is enabled but UAA is down', function () {
|
||||||
|
|
||||||
it('can log in with Basic Auth', async function () {
|
it('can log in with Basic Auth', async function () {
|
||||||
await homePage.toggleBasicAuthSection()
|
await homePage.toggleBasicAuthSection()
|
||||||
assert.ok(await homePage.isLoginButtonVisible)
|
assert.ok(await homePage.getBasicAuthLoginButton())
|
||||||
await homePage.basicAuthLogin('guest', 'guest')
|
await homePage.basicAuthLogin('guest', 'guest')
|
||||||
await overview.isLoaded()
|
await overview.isLoaded()
|
||||||
assert.equal(await overview.getUser(), 'User guest')
|
assert.equal(await overview.getUser(), 'User guest')
|
||||||
|
|
|
@ -20,15 +20,13 @@ describe('When basic authentication is enabled but UAA is down', function () {
|
||||||
it('should display warning message that UAA is down', async function () {
|
it('should display warning message that UAA is down', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
const message = await homePage.getWarning()
|
const message = await homePage.getWarning()
|
||||||
assert.equal(true, message.startsWith('OAuth resource [rabbitmq] not available'))
|
assert.ok(message.startsWith('OAuth resource [rabbitmq] not available'))
|
||||||
assert.equal(true, message.endsWith(' not reachable'))
|
assert.ok(message.endsWith(' not reachable'))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not be presented oauth2 section', async function () {
|
it('should not be presented oauth2 section', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
if (await homePage.isOAuth2SectionVisible()) {
|
assert.ok(await homePage.isOAuth2SectionNotVisible())
|
||||||
throw new Error('OAuth2 section should not be present')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -30,8 +30,7 @@ describe('A user which accesses any protected URL without a session where basic
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not have a warning message', async function () {
|
it('should not have a warning message', async function () {
|
||||||
const visible = await homePage.isWarningVisible()
|
assert.ok(await homePage.isWarningNotVisible())
|
||||||
assert.ok(!visible)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,15 +28,14 @@ describe('An user without management tag', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('cannot log in into the management ui', async function () {
|
it('cannot log in into the management ui', async function () {
|
||||||
const visible = await homePage.isWarningVisible()
|
assert.ok(await homePage.isWarningVisible())
|
||||||
assert.ok(visible)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should get "Not authorized" warning message', async function(){
|
it('should get "Not authorized" warning message', async function(){
|
||||||
assert.equal('Not authorized', await homePage.getWarning())
|
assert.equal('Not authorized', await homePage.getWarning())
|
||||||
assert.equal('Click here to logout', await homePage.getLogoutButton())
|
assert.equal('Click here to logout', await homePage.getLogoutButton())
|
||||||
assert.ok(!await homePage.isBasicAuthSectionVisible())
|
assert.ok(await homePage.isBasicAuthSectionNotVisible())
|
||||||
assert.ok(!await homePage.isOAuth2SectionVisible())
|
assert.ok(await homePage.isOAuth2SectionNotVisible())
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("After clicking on logout button", function() {
|
describe("After clicking on logout button", function() {
|
||||||
|
@ -46,8 +45,7 @@ describe('An user without management tag', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should get redirected to home page again without error message', async function(){
|
it('should get redirected to home page again without error message', async function(){
|
||||||
const visible = await homePage.isWarningVisible()
|
assert.ok(await homePage.isWarningNotVisible())
|
||||||
assert.ok(!visible)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -20,13 +20,13 @@ describe('When UAA is down', function () {
|
||||||
it('should display warning message that UAA is down', async function () {
|
it('should display warning message that UAA is down', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
const message = await homePage.getWarning()
|
const message = await homePage.getWarning()
|
||||||
assert.equal(true, message.startsWith('OAuth resource [rabbitmq] not available'))
|
assert.ok(message.startsWith('OAuth resource [rabbitmq] not available'))
|
||||||
assert.equal(true, message.endsWith(' not reachable'))
|
assert.ok(message.endsWith(' not reachable'))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not be presented with a login button to log in', async function () {
|
it('should not be presented with a login button to log in', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
assert.equal(false, await homePage.isLoginButtonVisible())
|
assert.ok(await homePage.isLoginButtonNotVisible())
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
const { By, Key, until, Builder } = require('selenium-webdriver')
|
const { By, Key, until, Builder } = require('selenium-webdriver')
|
||||||
require('chromedriver')
|
require('chromedriver')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const { buildDriver, goToLogin, goToHome, captureScreensFor, teardown } = require('../../utils')
|
const { buildDriver, goToHome, captureScreensFor, teardown } = require('../../utils')
|
||||||
|
|
||||||
const OverviewPage = require('../../pageobjects/OverviewPage')
|
const OverviewPage = require('../../pageobjects/OverviewPage')
|
||||||
|
|
||||||
describe('A user with a JWT token', function () {
|
describe('A user with a JWT token', function () {
|
||||||
let overview
|
let overview
|
||||||
let captureScreen
|
let captureScreen
|
||||||
let token
|
|
||||||
let fakePortal
|
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
driver = buildDriver()
|
driver = buildDriver()
|
||||||
overview = new OverviewPage(driver)
|
overview = new OverviewPage(driver)
|
||||||
|
|
|
@ -21,14 +21,12 @@ describe('A user which accesses any protected URL without a session', function (
|
||||||
|
|
||||||
it('should be presented with a login button to log in', async function () {
|
it('should be presented with a login button to log in', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
const value = await homePage.getLoginButton()
|
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||||
assert.equal(value, 'Click here to log in')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not have a warning message', async function () {
|
it('should not have a warning message', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
const visible = await homePage.isWarningVisible()
|
assert.ok(await homePage.isWarningNotVisible())
|
||||||
assert.ok(!visible)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('login button should redirect to the configured oauth_provider_url', async function () {
|
it('login button should redirect to the configured oauth_provider_url', async function () {
|
||||||
|
|
|
@ -36,8 +36,7 @@ describe('Once user logs in with its own token', function () {
|
||||||
|
|
||||||
it('user should be presented with a login button to log in', async function () {
|
it('user should be presented with a login button to log in', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
const value = await homePage.getLoginButton()
|
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||||
assert.equal(value, 'Click here to log in')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -24,12 +24,10 @@ describe('A user who accesses the /login URL with a token without scopes for the
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should get a warning message', async function () {
|
it('should get a warning message', async function () {
|
||||||
const message = await homePage.getWarning()
|
assert.equal(await homePage.getWarning(), 'Not_Authorized')
|
||||||
assert.equal('Not_Authorized', message)
|
|
||||||
})
|
})
|
||||||
it('should be presented with a login button to log in', async function () {
|
it('should be presented with a login button to log in', async function () {
|
||||||
const value = await homePage.getLoginButton()
|
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||||
assert.equal(value, 'Click here to log in')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -29,14 +29,12 @@ describe('A user which accesses any protected URL without a session', function (
|
||||||
assert.equal("rabbit_x", resources[2].value)
|
assert.equal("rabbit_x", resources[2].value)
|
||||||
assert.equal("RabbitMQ X_Idp", resources[2].text)
|
assert.equal("RabbitMQ X_Idp", resources[2].text)
|
||||||
|
|
||||||
const value = await homePage.getLoginButton()
|
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||||
assert.equal(value, 'Click here to log in')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not have a warning message', async function () {
|
it('should not have a warning message', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
const visible = await homePage.isWarningVisible()
|
assert.ok(await homePage.isWarningNotVisible())
|
||||||
assert.ok(!visible)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -18,14 +18,12 @@ describe('A user which accesses any protected URL without a session', function (
|
||||||
|
|
||||||
it('should be presented with a login button to log in', async function () {
|
it('should be presented with a login button to log in', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
const value = await homePage.getLoginButton()
|
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||||
assert.equal(value, 'Click here to log in')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not have a warning message', async function () {
|
it('should not have a warning message', async function () {
|
||||||
await homePage.isLoaded()
|
await homePage.isLoaded()
|
||||||
const visible = await homePage.isWarningVisible()
|
assert.ok(await homePage.isWarningNotVisible())
|
||||||
assert.ok(!visible)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -26,14 +26,11 @@ describe('A user which accesses a protected URL without a session', function ()
|
||||||
|
|
||||||
it('redirect to previous accessed page after login ', async function () {
|
it('redirect to previous accessed page after login ', async function () {
|
||||||
await homePage.clickToLogin()
|
await homePage.clickToLogin()
|
||||||
|
|
||||||
await idpLogin.login('rabbit_admin', 'rabbit_admin')
|
await idpLogin.login('rabbit_admin', 'rabbit_admin')
|
||||||
|
|
||||||
if (!await exchanges.isLoaded()) {
|
if (!await exchanges.isLoaded()) {
|
||||||
throw new Error('Failed to login')
|
throw new Error('Failed to login')
|
||||||
}
|
}
|
||||||
|
await exchanges.getPagingSectionHeaderText()
|
||||||
assert.equal("All exchanges (8)", await exchanges.getPagingSectionHeaderText())
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,15 +29,14 @@ describe('An user without management tag', function () {
|
||||||
if (!await homePage.isLoaded()) {
|
if (!await homePage.isLoaded()) {
|
||||||
throw new Error('Failed to login')
|
throw new Error('Failed to login')
|
||||||
}
|
}
|
||||||
const visible = await homePage.isWarningVisible()
|
assert.ok(await homePage.isWarningVisible())
|
||||||
assert.ok(visible)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should get "Not authorized" warning message and logout button but no login button', async function(){
|
it('should get "Not authorized" warning message and logout button but no login button', async function(){
|
||||||
assert.equal('Not authorized', await homePage.getWarning())
|
assert.equal('Not authorized', await homePage.getWarning())
|
||||||
assert.equal('Click here to logout', await homePage.getLogoutButton())
|
assert.equal('Click here to logout', await homePage.getLogoutButton())
|
||||||
assert.ok(!await homePage.isBasicAuthSectionVisible())
|
assert.ok(await homePage.isBasicAuthSectionNotVisible())
|
||||||
assert.ok(!await homePage.isOAuth2SectionVisible())
|
assert.ok(await homePage.isOAuth2SectionNotVisible())
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("After clicking on logout button", function() {
|
describe("After clicking on logout button", function() {
|
||||||
|
@ -47,9 +46,8 @@ describe('An user without management tag', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should get redirected to home page again without error message', async function(){
|
it('should get redirected to home page again without error message', async function(){
|
||||||
await driver.sleep(250)
|
await driver.sleep(250)
|
||||||
const visible = await homePage.isWarningVisible()
|
assert.ok(await homePage.isWarningNotVisible())
|
||||||
assert.ok(!visible)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -146,18 +146,12 @@ module.exports = class BasePage {
|
||||||
return element.isDisplayed()
|
return element.isDisplayed()
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
return Promise.resolve(false)
|
return Promise.resolve(false)
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
let element = await driver.findElement(FORM_POPUP)
|
|
||||||
return this.driver.wait(until.elementIsVisible(element), this.timeout / 2,
|
|
||||||
'Timed out after [timeout=' + this.timeout + ';polling=' + this.polling + '] awaiting till visible ' + element,
|
|
||||||
this.polling / 2).then(function onWarningVisible(e) {
|
|
||||||
return Promise.resolve(true)
|
|
||||||
}, function onError(e) {
|
|
||||||
return Promise.resolve(false)
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
async isPopupWarningNotDisplayed() {
|
||||||
|
return this.waitForNotDisplayed(FORM_POPUP)
|
||||||
|
}
|
||||||
|
|
||||||
async getPopupWarning() {
|
async getPopupWarning() {
|
||||||
let element = await driver.findElement(FORM_POPUP)
|
let element = await driver.findElement(FORM_POPUP)
|
||||||
return this.driver.wait(until.elementIsVisible(element), this.timeout,
|
return this.driver.wait(until.elementIsVisible(element), this.timeout,
|
||||||
|
@ -208,14 +202,37 @@ module.exports = class BasePage {
|
||||||
|
|
||||||
async waitForDisplayed (locator) {
|
async waitForDisplayed (locator) {
|
||||||
if (this.interactionDelay && this.interactionDelay > 0) await this.driver.sleep(this.interactionDelay)
|
if (this.interactionDelay && this.interactionDelay > 0) await this.driver.sleep(this.interactionDelay)
|
||||||
try {
|
let times = 1
|
||||||
return this.waitForVisible(await this.waitForLocated(locator))
|
do {
|
||||||
}catch(error) {
|
try {
|
||||||
if (!error.name.includes("NoSuchSessionError")) {
|
return this.waitForVisible(await this.waitForLocated(locator))
|
||||||
console.error("Failed to waitForDisplayed " + locator + " due to " + error)
|
}catch(error) {
|
||||||
|
if (!error.name.includes("NoSuchSessionError")) {
|
||||||
|
console.error("Failed to waitForDisplayed " + locator + " due to " + error)
|
||||||
|
}
|
||||||
|
if (times > 0 && error.name.includes("StaleElementReference")) {
|
||||||
|
times--
|
||||||
|
this.driver.sleep(50)
|
||||||
|
} else {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw error
|
} while (true)
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async waitForNotDisplayed (locator) {
|
||||||
|
let times = 5
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
await driver.findElement(locator)
|
||||||
|
times--
|
||||||
|
this.driver.sleep(50)
|
||||||
|
}catch(error) {
|
||||||
|
return Promise.resolve(true)
|
||||||
|
}
|
||||||
|
} while(times > 0)
|
||||||
|
return Promise.resolve(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getText (locator) {
|
async getText (locator) {
|
||||||
|
|
|
@ -51,6 +51,9 @@ module.exports = class SSOHomePage extends BasePage {
|
||||||
async getOAuthResourceOptions () {
|
async getOAuthResourceOptions () {
|
||||||
return this.getSelectableOptions(SELECT_RESOURCES)
|
return this.getSelectableOptions(SELECT_RESOURCES)
|
||||||
}
|
}
|
||||||
|
async isLoginButtonNotVisible() {
|
||||||
|
return this.waitForNotDisplayed(OAUTH2_LOGIN_BUTTON)
|
||||||
|
}
|
||||||
async isLoginButtonVisible() {
|
async isLoginButtonVisible() {
|
||||||
try {
|
try {
|
||||||
await this.waitForDisplayed(OAUTH2_LOGIN_BUTTON)
|
await this.waitForDisplayed(OAUTH2_LOGIN_BUTTON)
|
||||||
|
@ -71,12 +74,18 @@ module.exports = class SSOHomePage extends BasePage {
|
||||||
async isOAuth2SectionVisible() {
|
async isOAuth2SectionVisible() {
|
||||||
return this.isDisplayed(SECTION_LOGIN_WITH_OAUTH)
|
return this.isDisplayed(SECTION_LOGIN_WITH_OAUTH)
|
||||||
}
|
}
|
||||||
|
async isOAuth2SectionNotVisible() {
|
||||||
|
return this.waitForNotDisplayed(SECTION_LOGIN_WITH_OAUTH)
|
||||||
|
}
|
||||||
async getOAuth2Section() {
|
async getOAuth2Section() {
|
||||||
return this.waitForDisplayed(SECTION_LOGIN_WITH_OAUTH)
|
return this.waitForDisplayed(SECTION_LOGIN_WITH_OAUTH)
|
||||||
}
|
}
|
||||||
async isBasicAuthSectionVisible() {
|
async isBasicAuthSectionVisible() {
|
||||||
return this.isDisplayed(SECTION_LOGIN_WITH_BASIC_AUTH)
|
return this.isDisplayed(SECTION_LOGIN_WITH_BASIC_AUTH)
|
||||||
}
|
}
|
||||||
|
async isBasicAuthSectionNotVisible() {
|
||||||
|
return this.waitForNotDisplayed(SECTION_LOGIN_WITH_BASIC_AUTH)
|
||||||
|
}
|
||||||
async getBasicAuthSection() {
|
async getBasicAuthSection() {
|
||||||
return this.waitForDisplayed(SECTION_LOGIN_WITH_BASIC_AUTH)
|
return this.waitForDisplayed(SECTION_LOGIN_WITH_BASIC_AUTH)
|
||||||
}
|
}
|
||||||
|
@ -104,6 +113,9 @@ module.exports = class SSOHomePage extends BasePage {
|
||||||
return Promise.resolve(false)
|
return Promise.resolve(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async isWarningNotVisible () {
|
||||||
|
return this.waitForNotDisplayed(WARNING)
|
||||||
|
}
|
||||||
async getWarnings() {
|
async getWarnings() {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,15 +3,17 @@ const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
|
||||||
const fsp = fs.promises
|
const fsp = fs.promises
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const { By, Key, until, Builder, logging, Capabilities } = require('selenium-webdriver')
|
const { By, Key, until, Builder, logging, Capabilities } = require('selenium-webdriver')
|
||||||
|
const proxy = require('selenium-webdriver/proxy')
|
||||||
require('chromedriver')
|
require('chromedriver')
|
||||||
const UAALoginPage = require('./pageobjects/UAALoginPage')
|
const UAALoginPage = require('./pageobjects/UAALoginPage')
|
||||||
const KeycloakLoginPage = require('./pageobjects/KeycloakLoginPage')
|
const KeycloakLoginPage = require('./pageobjects/KeycloakLoginPage')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
|
|
||||||
|
const runLocal = String(process.env.RUN_LOCAL).toLowerCase() != 'false'
|
||||||
const uaaUrl = process.env.UAA_URL || 'http://localhost:8080'
|
const uaaUrl = process.env.UAA_URL || 'http://localhost:8080'
|
||||||
const baseUrl = randomly_pick_baseurl(process.env.RABBITMQ_URL) || 'http://localhost:15672/'
|
const baseUrl = randomly_pick_baseurl(process.env.RABBITMQ_URL) || 'http://localhost:15672/'
|
||||||
|
//const proxyUrl = calculateProxyUrl(baseUrl)
|
||||||
const hostname = process.env.RABBITMQ_HOSTNAME || 'localhost'
|
const hostname = process.env.RABBITMQ_HOSTNAME || 'localhost'
|
||||||
const runLocal = String(process.env.RUN_LOCAL).toLowerCase() != 'false'
|
|
||||||
const seleniumUrl = process.env.SELENIUM_URL || 'http://selenium:4444'
|
const seleniumUrl = process.env.SELENIUM_URL || 'http://selenium:4444'
|
||||||
const screenshotsDir = process.env.SCREENSHOTS_DIR || '/screens'
|
const screenshotsDir = process.env.SCREENSHOTS_DIR || '/screens'
|
||||||
const profiles = process.env.PROFILES || ''
|
const profiles = process.env.PROFILES || ''
|
||||||
|
@ -23,6 +25,19 @@ function randomly_pick_baseurl(baseUrl) {
|
||||||
function getRandomInt(max) {
|
function getRandomInt(max) {
|
||||||
return Math.floor(Math.random() * max);
|
return Math.floor(Math.random() * max);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
function calculateProxyUrl(baseUrl) {
|
||||||
|
if (baseUrl.includes("localhost")) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
if (process.env.FORWARD_PROXY_HOST && process.env.FORWARD_PROXY_PORT) {
|
||||||
|
return 'http://' + process.env.FORWARD_PROXY_HOST + ':' + process.env.FORWARD_PROXY_PORT
|
||||||
|
}else {
|
||||||
|
console.log("There are no proxy setup : " + JSON.stringify(process.env))
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
class CaptureScreenshot {
|
class CaptureScreenshot {
|
||||||
driver
|
driver
|
||||||
test
|
test
|
||||||
|
@ -64,10 +79,19 @@ module.exports = {
|
||||||
"--disable-search-engine-choice-screen"
|
"--disable-search-engine-choice-screen"
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
driver = builder
|
|
||||||
|
builder = builder
|
||||||
.forBrowser('chrome')
|
.forBrowser('chrome')
|
||||||
.withCapabilities(chromeCapabilities)
|
.withCapabilities(chromeCapabilities)
|
||||||
.build()
|
/*
|
||||||
|
if (proxyUrl) {
|
||||||
|
console.log("Using proxy " + proxyUrl)
|
||||||
|
builder = builder.setProxy(proxy.manual({https: proxyUrl}))
|
||||||
|
}else {
|
||||||
|
console.log("Not Using proxy . runLocal: " + runLocal)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
driver = builder.build()
|
||||||
driver.manage().setTimeouts( { pageLoad: 35000 } )
|
driver.manage().setTimeouts( { pageLoad: 35000 } )
|
||||||
return driver
|
return driver
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue