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_management/src/**'
|
||||
- 'deps/rabbitmq_management/priv/**'
|
||||
- 'deps/rabbitmq_management/selenium/**'
|
||||
- 'selenium/**'
|
||||
- 'scripts/**'
|
||||
- .bazelrc
|
||||
- .bazelversion
|
||||
- BUILD.*
|
||||
- '*.bzl'
|
||||
- '*.bazel'
|
||||
- .github/workflows/test-authnz.yaml
|
||||
pull_request:
|
||||
paths:
|
||||
|
|
|
@ -12,11 +12,6 @@ on:
|
|||
- 'deps/rabbitmq_management/priv/**'
|
||||
- 'deps/rabbitmq_web_dispatch/src/**'
|
||||
- 'scripts/**'
|
||||
- .bazelrc
|
||||
- .bazelversion
|
||||
- BUILD.*
|
||||
- '*.bzl'
|
||||
- '*.bazel'
|
||||
- 'selenium/**'
|
||||
- .github/workflows/test-management-ui.yaml
|
||||
|
||||
|
|
|
@ -20,6 +20,14 @@
|
|||
}).
|
||||
-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, {
|
||||
id :: oauth_provider_id(),
|
||||
issuer :: option(uri_string:uri_string()),
|
||||
|
@ -28,7 +36,8 @@
|
|||
authorization_endpoint :: option(uri_string:uri_string()),
|
||||
end_session_endpoint :: 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}].
|
||||
|
|
|
@ -7,12 +7,17 @@
|
|||
-module(oauth2_client).
|
||||
-export([get_access_token/2, get_expiration_time/1,
|
||||
refresh_access_token/2,
|
||||
get_jwks/1,
|
||||
get_oauth_provider/1, get_oauth_provider/2,
|
||||
get_openid_configuration/2,
|
||||
get_openid_configuration/1,
|
||||
build_openid_discovery_endpoint/3,
|
||||
merge_openid_configuration/2,
|
||||
merge_oauth_provider/2,
|
||||
extract_ssl_options_as_list/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
|
||||
]).
|
||||
|
||||
|
@ -25,29 +30,82 @@ get_access_token(OAuthProvider, Request) ->
|
|||
rabbit_log:debug("get_access_token using OAuthProvider:~p and client_id:~p",
|
||||
[OAuthProvider, Request#access_token_request.client_id]),
|
||||
URL = OAuthProvider#oauth_provider.token_endpoint,
|
||||
Id = OAuthProvider#oauth_provider.id,
|
||||
Header = [],
|
||||
Type = ?CONTENT_URLENCODED,
|
||||
Body = build_access_token_request_body(Request),
|
||||
HTTPOptions = get_ssl_options_if_any(OAuthProvider) ++
|
||||
get_timeout_of_default(Request#access_token_request.timeout),
|
||||
Options = [],
|
||||
Response = httpc:request(post, {URL, Header, Type, Body}, HTTPOptions, Options),
|
||||
HTTPOptions =
|
||||
map_ssl_options_to_httpc_option(OAuthProvider#oauth_provider.ssl_options) ++
|
||||
map_timeout_to_httpc_option(Request#access_token_request.timeout),
|
||||
Response = http_post(Id, URL, Header, Type, Body, HTTPOptions,
|
||||
OAuthProvider#oauth_provider.proxy_options),
|
||||
parse_access_token_response(Response).
|
||||
|
||||
-spec refresh_access_token(oauth_provider(), refresh_token_request()) ->
|
||||
{ok, successful_access_token_response()} |
|
||||
{error, unsuccessful_access_token_response() | any()}.
|
||||
refresh_access_token(OAuthProvider, Request) ->
|
||||
Id = OAuthProvider#oauth_provider.id,
|
||||
URL = OAuthProvider#oauth_provider.token_endpoint,
|
||||
Header = [],
|
||||
Type = ?CONTENT_URLENCODED,
|
||||
Body = build_refresh_token_request_body(Request),
|
||||
HTTPOptions = get_ssl_options_if_any(OAuthProvider) ++
|
||||
get_timeout_of_default(Request#refresh_token_request.timeout),
|
||||
Options = [],
|
||||
Response = httpc:request(post, {URL, Header, Type, Body}, HTTPOptions, Options),
|
||||
HTTPOptions =
|
||||
map_ssl_options_to_httpc_option(OAuthProvider#oauth_provider.ssl_options) ++
|
||||
map_timeout_to_httpc_option(Request#refresh_token_request.timeout),
|
||||
Response = http_post(Id, URL, Header, Type, Body, HTTPOptions,
|
||||
OAuthProvider#oauth_provider.proxy_options),
|
||||
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) ->
|
||||
erlang:iolist_to_binary([Path1, Path2]).
|
||||
|
||||
|
@ -93,15 +151,28 @@ drop_trailing_path_separator(Path) when is_list(Path) ->
|
|||
_ -> Path
|
||||
end.
|
||||
|
||||
-spec get_openid_configuration(DiscoveryEndpoint :: uri_string:uri_string(),
|
||||
ssl:tls_option() | []) -> {ok, openid_configuration()} | {error, term()}.
|
||||
get_openid_configuration(DiscoverEndpoint, TLSOptions) ->
|
||||
rabbit_log:debug("get_openid_configuration from ~p (~p)", [DiscoverEndpoint,
|
||||
format_ssl_options(TLSOptions)]),
|
||||
Options = [],
|
||||
Response = httpc:request(get, {DiscoverEndpoint, []}, TLSOptions, Options),
|
||||
-spec get_openid_configuration(oauth_provider()) -> {ok, openid_configuration()} | {error, term()}.
|
||||
get_openid_configuration(#oauth_provider{id = Id, discovery_endpoint = Endpoint,
|
||||
ssl_options = SslOptions, proxy_options = ProxyOptions}) ->
|
||||
rabbit_log:debug("get_openid_configuration from ~p (~p) [~p]", [Endpoint,
|
||||
format_ssl_options(SslOptions), format_proxy_options(ProxyOptions)]),
|
||||
HTTPOptions =
|
||||
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).
|
||||
|
||||
-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()) ->
|
||||
oauth_provider().
|
||||
merge_openid_configuration(OpenId, OAuthProvider0) ->
|
||||
|
@ -283,7 +354,7 @@ download_oauth_provider(OAuthProvider) ->
|
|||
undefined -> {error, {missing_oauth_provider_attributes, [issuer]}};
|
||||
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, update_oauth_provider_endpoints_configuration(
|
||||
merge_openid_configuration(OpenIdConfiguration, OAuthProvider))};
|
||||
|
@ -341,7 +412,6 @@ get_oauth_provider(OAuthProviderId, ListOfRequiredAttributes)
|
|||
[OAuthProviderId, Error0]),
|
||||
Error0;
|
||||
Config ->
|
||||
rabbit_log:debug("Found oauth_provider configuration ~p", [Config]),
|
||||
OAuthProvider = map_to_oauth_provider(Config),
|
||||
rabbit_log:debug("Resolved oauth_provider ~p", [format_oauth_provider(OAuthProvider)]),
|
||||
case find_missing_attributes(OAuthProvider, ListOfRequiredAttributes) of
|
||||
|
@ -395,9 +465,37 @@ lookup_root_oauth_provider() ->
|
|||
token_endpoint = get_env(token_endpoint),
|
||||
authorization_endpoint = get_env(authorization_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().
|
||||
extract_ssl_options_as_list(Map) ->
|
||||
{Verify, CaCerts, CaCertFile} = case get_verify_or_peer_verification(Map, verify_peer) of
|
||||
|
@ -522,17 +620,38 @@ append_extra_parameters(Request, QueryList) ->
|
|||
Params -> Params ++ QueryList
|
||||
end.
|
||||
|
||||
get_ssl_options_if_any(OAuthProvider) ->
|
||||
case OAuthProvider#oauth_provider.ssl_options of
|
||||
map_ssl_options_to_httpc_option(SslOptions) ->
|
||||
case SslOptions of
|
||||
undefined -> [];
|
||||
Options -> [{ssl, Options}]
|
||||
end.
|
||||
get_timeout_of_default(Timeout) ->
|
||||
|
||||
map_timeout_to_httpc_option(Timeout) ->
|
||||
case Timeout of
|
||||
undefined -> [{timeout, ?DEFAULT_HTTP_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.
|
||||
|
||||
is_json(?CONTENT_JSON) -> true;
|
||||
is_json(_) -> false.
|
||||
|
||||
|
@ -543,10 +662,8 @@ is_json(_) -> false.
|
|||
decode_body(_, []) -> [];
|
||||
decode_body(?CONTENT_JSON, Body) ->
|
||||
case rabbit_json:try_decode(rabbit_data_coercion:to_binary(Body)) of
|
||||
{ok, Value} ->
|
||||
Value;
|
||||
{error, _} = Error ->
|
||||
Error
|
||||
{ok, Value} -> Value;
|
||||
{error, _} = Error -> Error
|
||||
end;
|
||||
decode_body(MimeType, Body) ->
|
||||
Items = string:split(MimeType, ";"),
|
||||
|
@ -588,14 +705,14 @@ map_to_oauth_provider(PropList) when is_list(PropList) ->
|
|||
proplists:get_value(jwks_uri, PropList, undefined),
|
||||
ssl_options =
|
||||
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) ->
|
||||
case decode_body(proplists:get_value("content-type", Headers, ?CONTENT_JSON), Body) of
|
||||
{error, {error, InternalError}} ->
|
||||
{error, InternalError};
|
||||
{error, _} = Error ->
|
||||
Error;
|
||||
{error, {error, InternalError}} -> {error, InternalError};
|
||||
{error, _} = Error -> Error;
|
||||
Value ->
|
||||
case Code of
|
||||
200 -> {ok, map_to_successful_access_token_response(Value)};
|
||||
|
@ -626,6 +743,18 @@ format_ssl_options(TlsOptions) ->
|
|||
proplists:get_value(cacertfile, TlsOptions),
|
||||
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(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, " ++
|
||||
" token_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),
|
||||
OAuthProvider#oauth_provider.issuer,
|
||||
OAuthProvider#oauth_provider.discovery_endpoint,
|
||||
|
@ -642,7 +771,8 @@ format_oauth_provider(OAuthProvider) ->
|
|||
OAuthProvider#oauth_provider.authorization_endpoint,
|
||||
OAuthProvider#oauth_provider.end_session_endpoint,
|
||||
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) ->
|
||||
application:get_env(rabbitmq_auth_backend_oauth2, Par, undefined).
|
||||
|
|
|
@ -322,13 +322,25 @@ build_openid_discovery_endpoint(Issuer, Path) ->
|
|||
|
||||
get_openid_configuration(Config) ->
|
||||
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
||||
SslOptions = [{ssl, ExpectedOAuthProvider#oauth_provider.ssl_options}],
|
||||
{ok, ActualOpenId} = oauth2_client:get_openid_configuration(
|
||||
build_openid_discovery_endpoint(build_issuer("https")),
|
||||
SslOptions),
|
||||
ensure_discovery_endpoint(ExpectedOAuthProvider)),
|
||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||
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) ->
|
||||
#openid_configuration{
|
||||
issuer = OAuthProvider#oauth_provider.issuer,
|
||||
|
@ -344,35 +356,30 @@ get_openid_configuration_returns_partial_payload(Config) ->
|
|||
token_endpoint = ExpectedOAuthProvider0#oauth_provider.token_endpoint,
|
||||
jwks_uri = ExpectedOAuthProvider0#oauth_provider.jwks_uri},
|
||||
|
||||
SslOptions = [{ssl, ExpectedOAuthProvider0#oauth_provider.ssl_options}],
|
||||
{ok, Actual} = oauth2_client:get_openid_configuration(
|
||||
build_openid_discovery_endpoint(build_issuer("https")),
|
||||
SslOptions),
|
||||
ensure_discovery_endpoint(ExpectedOAuthProvider0)),
|
||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||
assertOpenIdConfiguration(ExpectedOpenId, Actual).
|
||||
|
||||
get_openid_configuration_using_path(Config) ->
|
||||
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
||||
SslOptions = [{ssl, ExpectedOAuthProvider#oauth_provider.ssl_options}],
|
||||
{ok, Actual} = oauth2_client:get_openid_configuration(
|
||||
build_openid_discovery_endpoint(build_issuer("https", ?ISSUER_PATH)),
|
||||
SslOptions),
|
||||
ensure_discovery_endpoint(
|
||||
ensure_issuer(ExpectedOAuthProvider, build_issuer("https", ?ISSUER_PATH)))),
|
||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||
assertOpenIdConfiguration(ExpectedOpenId,Actual).
|
||||
get_openid_configuration_using_path_and_custom_endpoint(Config) ->
|
||||
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
||||
SslOptions = [{ssl, ExpectedOAuthProvider#oauth_provider.ssl_options}],
|
||||
{ok, Actual} = oauth2_client:get_openid_configuration(
|
||||
build_openid_discovery_endpoint(build_issuer("https", ?ISSUER_PATH),
|
||||
?CUSTOM_OPENID_CONFIGURATION_ENDPOINT), SslOptions),
|
||||
ensure_discovery_endpoint(
|
||||
ensure_issuer(ExpectedOAuthProvider, build_issuer("https", ?ISSUER_PATH)),
|
||||
?CUSTOM_OPENID_CONFIGURATION_ENDPOINT)),
|
||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||
assertOpenIdConfiguration(ExpectedOpenId, Actual).
|
||||
get_openid_configuration_using_custom_endpoint(Config) ->
|
||||
ExpectedOAuthProvider = ?config(oauth_provider, Config),
|
||||
SslOptions = [{ssl, ExpectedOAuthProvider#oauth_provider.ssl_options}],
|
||||
{ok, Actual} = oauth2_client:get_openid_configuration(
|
||||
build_openid_discovery_endpoint(build_issuer("https"),
|
||||
?CUSTOM_OPENID_CONFIGURATION_ENDPOINT), SslOptions),
|
||||
ensure_discovery_endpoint(ExpectedOAuthProvider, ?CUSTOM_OPENID_CONFIGURATION_ENDPOINT)),
|
||||
ExpectedOpenId = map_oauth_provider_to_openid_configuration(ExpectedOAuthProvider),
|
||||
assertOpenIdConfiguration(ExpectedOpenId, Actual).
|
||||
|
||||
|
|
|
@ -220,6 +220,26 @@
|
|||
rabbit_oauth2_schema:translate_oauth_providers(Conf)
|
||||
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,
|
||||
"auth_oauth2.https.peer_verification",
|
||||
"rabbitmq_auth_backend_oauth2.key_config.peer_verification",
|
||||
|
@ -322,6 +342,26 @@
|
|||
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
||||
[{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,
|
||||
"auth_oauth2.oauth_providers.$name.https.hostname_verification",
|
||||
"rabbitmq_auth_backend_oauth2.oauth_providers",
|
||||
|
|
|
@ -158,6 +158,7 @@ translate_oauth_providers(Conf) ->
|
|||
Settings),
|
||||
extract_oauth_providers_algorithm(Settings),
|
||||
extract_oauth_providers_https(Settings),
|
||||
extract_oauth_providers_proxy(Settings),
|
||||
extract_oauth_providers_signing_keys(Settings)
|
||||
]).
|
||||
|
||||
|
@ -264,6 +265,15 @@ mapOauthProviderProperty({Key, Value}) ->
|
|||
_ -> Value
|
||||
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) ->
|
||||
ExtractProviderNameFun = fun extract_key_as_binary/1,
|
||||
|
||||
|
@ -280,6 +290,9 @@ mapHttpProperty({Key, Value}) ->
|
|||
_ -> Value
|
||||
end}.
|
||||
|
||||
mapProxyProperty({Key, Value}) ->
|
||||
{Key, Value}.
|
||||
|
||||
extract_oauth_providers_algorithm(Settings) ->
|
||||
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.
|
||||
|
||||
-spec update_jwks_signing_keys(oauth_provider()) -> ok | {error, term()}.
|
||||
update_jwks_signing_keys(#oauth_provider{id = Id, jwks_uri = JwksUrl,
|
||||
ssl_options = SslOptions}) ->
|
||||
rabbit_log:debug("Downloading signing keys from ~tp (TLS options: ~p)",
|
||||
[JwksUrl, format_ssl_options(SslOptions)]),
|
||||
case uaa_jwks:get(JwksUrl, SslOptions) of
|
||||
update_jwks_signing_keys(#oauth_provider{id = Id} = OAuthProvider) ->
|
||||
rabbit_log:debug("Downloading signing keys from OauthProvider: ~tp",
|
||||
[Id]),
|
||||
case oauth2_client:get_jwks(OAuthProvider) of
|
||||
{ok, {_, _, JwksBody}} ->
|
||||
KeyList = maps:get(<<"keys">>,
|
||||
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"}
|
||||
]}
|
||||
]
|
||||
}
|
||||
}
|
||||
]}
|
||||
], []
|
||||
}
|
||||
].
|
||||
|
|
|
@ -66,6 +66,9 @@ verify_provider() -> [
|
|||
{oauth_provider_with_issuer, [], [
|
||||
get_oauth_provider_has_jwks_uri
|
||||
]}
|
||||
,{oauth_provider_with_proxy, [], [
|
||||
get_oauth_provider_has_proxy
|
||||
]}
|
||||
].
|
||||
|
||||
init_per_suite(Config) ->
|
||||
|
@ -149,6 +152,27 @@ init_per_group(with_resource_server_id, Config) ->
|
|||
set_env(resource_server_id, ?RABBITMQ),
|
||||
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) ->
|
||||
KeyConfig = get_env(key_config, []),
|
||||
set_env(key_config, KeyConfig ++ [{algorithms, [<<"HS256">>, <<"RS256">>]}]),
|
||||
|
@ -190,6 +214,16 @@ init_per_group(_any, Config) ->
|
|||
end_per_group(with_rabbitmq_node, Config) ->
|
||||
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) ->
|
||||
KeyConfig = call_get_env(Config, key_config, []),
|
||||
call_set_env(Config, key_config, KeyConfig),
|
||||
|
@ -408,9 +442,21 @@ get_oauth_provider_with_jwks_uri_returns_error(Config) ->
|
|||
get_oauth_provider_has_jwks_uri(Config) ->
|
||||
{ok, OAuthProvider} = get_oauth_provider(
|
||||
?config(oauth_provider_id, Config), [jwks_uri]),
|
||||
ct:log("OAuthProvider: ~p", [OAuthProvider]),
|
||||
?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
|
||||
|
||||
|
|
|
@ -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,7 +12,6 @@ ensure_keycloak() {
|
|||
init_keycloak() {
|
||||
KEYCLOAK_CONFIG_PATH=${KEYCLOAK_CONFIG_PATH:-oauth/keycloak}
|
||||
KEYCLOAK_CONFIG_DIR=$(realpath ${TEST_DIR}/${KEYCLOAK_CONFIG_PATH})
|
||||
KEYCLOAK_URL=${OAUTH_PROVIDER_URL}
|
||||
|
||||
print "> KEYCLOAK_CONFIG_DIR: ${KEYCLOAK_CONFIG_DIR}"
|
||||
print "> KEYCLOAK_URL: ${KEYCLOAK_URL}"
|
||||
|
@ -42,8 +41,9 @@ start_keycloak() {
|
|||
--publish 8443:8443 \
|
||||
--env KEYCLOAK_ADMIN=admin \
|
||||
--env KEYCLOAK_ADMIN_PASSWORD=admin \
|
||||
--env QUARKUS_HTTP_ACCESS_LOG_ENABLED=true \
|
||||
-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-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() {
|
||||
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() {
|
||||
BASE_URL=$1
|
||||
if [[ $BASE_URL == *"localhost"** ]]; then
|
||||
wait_for_url_local $BASE_URL
|
||||
wait_for_url_local $@
|
||||
else
|
||||
wait_for_url_docker $BASE_URL
|
||||
wait_for_url_docker $@
|
||||
fi
|
||||
}
|
||||
wait_for_url_local() {
|
||||
url=$1
|
||||
proxy=${2:-none}
|
||||
proxy_user=${3:-none}
|
||||
proxy_pass=$4
|
||||
curl_args="-L -f -v"
|
||||
max_retry=10
|
||||
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
|
||||
print "Waiting for $url to start (local)"
|
||||
sleep 5
|
||||
|
@ -240,7 +257,14 @@ wait_for_url_docker() {
|
|||
url=$1
|
||||
max_retry=10
|
||||
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
|
||||
print "Waiting for $url to start (docker)"
|
||||
sleep 5
|
||||
|
@ -373,7 +397,8 @@ profiles_with_local_or_docker() {
|
|||
generate_env_file() {
|
||||
begin "Generating env file ..."
|
||||
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
|
||||
end "Finished generating env file."
|
||||
}
|
||||
|
@ -541,7 +566,7 @@ run_on_docker_with() {
|
|||
build_mocha_image
|
||||
start_selenium
|
||||
|
||||
trap teardown_components EXIT
|
||||
trap "teardown_components" EXIT
|
||||
|
||||
start_components
|
||||
test
|
||||
|
@ -622,7 +647,6 @@ start_components() {
|
|||
$start
|
||||
done
|
||||
}
|
||||
|
||||
teardown_components() {
|
||||
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-without-basic-auth-and-resource-label-and-scopes.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-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-via-proxy.sh
|
||||
authnz-mgt/oauth-idp-initiated-with-uaa.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-uaa-down-but-with-basic-auth.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 { open: openAmqp, once: onceAmqp, on: onAmqp, close: closeAmqp } = require('../amqp')
|
||||
|
||||
var receivedAmqpMessageCount = 0
|
||||
var untilConnectionEstablished = new Promise((resolve, reject) => {
|
||||
onAmqp('connection_open', function(context) {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
onAmqp('message', function (context) {
|
||||
receivedAmqpMessageCount++
|
||||
})
|
||||
onceAmqp('sendable', function (context) {
|
||||
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 () {
|
||||
var untilFirstMessageReceived = new Promise((resolve, reject) => {
|
||||
onAmqp('message', function(context) {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
amqp = openAmqp()
|
||||
await untilConnectionEstablished
|
||||
var untilMessageReceived = new Promise((resolve, reject) => {
|
||||
await untilFirstMessageReceived
|
||||
var untilSecondMessageReceived = new Promise((resolve, reject) => {
|
||||
onAmqp('message', function(context) {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
amqp.sender.send({body:'second message'})
|
||||
await untilMessageReceived
|
||||
assert.equal(2, receivedAmqpMessageCount)
|
||||
await untilSecondMessageReceived
|
||||
})
|
||||
|
||||
after(function () {
|
||||
|
|
|
@ -27,35 +27,32 @@ describe('management user with vhosts permissions', function () {
|
|||
it('can access overview tab', async function () {
|
||||
await overview.clickOnOverviewTab()
|
||||
await overview.waitForOverviewTab()
|
||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
||||
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||
})
|
||||
it('can access connections tab', async function () {
|
||||
await overview.clickOnConnectionsTab()
|
||||
await overview.waitForConnectionsTab()
|
||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
||||
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||
})
|
||||
it('can access channels tab', async function () {
|
||||
await overview.clickOnChannelsTab()
|
||||
await overview.waitForChannelsTab()
|
||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
||||
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||
})
|
||||
it('can access exchanges tab', async function () {
|
||||
await overview.clickOnExchangesTab()
|
||||
await overview.waitForExchangesTab()
|
||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
||||
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||
})
|
||||
it('can access queues and streams tab', async function () {
|
||||
await overview.clickOnQueuesTab()
|
||||
await overview.waitForQueuesTab()
|
||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
||||
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||
})
|
||||
it('can access limited options in admin tab', async function () {
|
||||
console.log("before clickOnAdminTab")
|
||||
await overview.clickOnAdminTab()
|
||||
console.log("before waitForAdminTab")
|
||||
await overview.waitForAdminTab()
|
||||
console.log("after waitForAdminTab")
|
||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
||||
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||
})
|
||||
|
||||
it('cannot add/update user limits', async function () {
|
||||
|
|
|
@ -19,7 +19,6 @@ describe('An user without management tag', function () {
|
|||
overview = new OverviewPage(driver)
|
||||
captureScreen = captureScreensFor(driver, __filename)
|
||||
|
||||
//assert.ok(!await login.isPopupWarningDisplayed())
|
||||
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(){
|
||||
await delay(1000)
|
||||
const visible = await login.isPopupWarningDisplayed()
|
||||
assert.ok(!visible)
|
||||
const 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 () {
|
||||
await homePage.isLoaded()
|
||||
if (await homePage.isOAuth2SectionVisible()) {
|
||||
throw new Error('OAuth2 section should not be present')
|
||||
}
|
||||
assert.ok(await homePage.isOAuth2SectionNotVisible())
|
||||
})
|
||||
|
||||
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 () {
|
||||
const visible = await homePage.isWarningVisible()
|
||||
assert.ok(!visible)
|
||||
assert.ok(await homePage.isWarningNotVisible())
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ describe('Given there are three oauth resources but two enabled', function () {
|
|||
if (!await overview.isLoaded()) {
|
||||
throw new Error('Failed to login')
|
||||
}
|
||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
||||
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||
await overview.logout()
|
||||
})
|
||||
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()) {
|
||||
throw new Error('Failed to login')
|
||||
}
|
||||
assert.ok(!await overview.isPopupWarningDisplayed())
|
||||
assert.ok(await overview.isPopupWarningNotDisplayed())
|
||||
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 () {
|
||||
assert.ok(!await homePage.isBasicAuthSectionVisible())
|
||||
assert.ok(await homePage.isBasicAuthSectionNotVisible())
|
||||
})
|
||||
|
||||
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 OAUTH_PROVIDER_URL=https://keycloak:8443/realms/test
|
||||
export OAUTH_PROVIDER_CA_CERT=/config/oauth/keycloak/ca_keycloak_certificate.pem
|
||||
export KEYCLOAK_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 OAUTH_PROVIDER_URL=https://localhost:8443/realms/test
|
||||
export OAUTH_PROVIDER_CA_CERT=selenium/test/oauth/keycloak/ca_keycloak_certificate.pem
|
||||
export KEYCLOAK_URL=https://keycloak:8443/realms/test
|
||||
export KEYCLOAK_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": [
|
||||
{
|
||||
"name": "/"
|
||||
},
|
||||
{
|
||||
"name": "other"
|
||||
}
|
||||
],
|
||||
"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
|
||||
management.oauth_provider_url = ${KEYCLOAK_URL}
|
||||
#management.oauth_provider_url = ${KEYCLOAK_URL}
|
||||
management.oauth_authorization_endpoint_params.resource = rabbitmq
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
auth_oauth2.issuer = ${OAUTH_PROVIDER_URL}
|
||||
auth_oauth2.https.cacertfile = ${OAUTH_PROVIDER_CA_CERT}
|
||||
auth_oauth2.issuer = ${KEYCLOAK_URL}
|
||||
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
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
# uaa requires a secret in order to renew tokens
|
||||
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
|
||||
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 () {
|
||||
await homePage.toggleBasicAuthSection()
|
||||
assert.ok(await homePage.isLoginButtonVisible)
|
||||
assert.ok(await homePage.getBasicAuthLoginButton())
|
||||
await homePage.basicAuthLogin('guest', 'guest')
|
||||
await overview.isLoaded()
|
||||
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 () {
|
||||
await homePage.isLoaded()
|
||||
const message = await homePage.getWarning()
|
||||
assert.equal(true, message.startsWith('OAuth resource [rabbitmq] not available'))
|
||||
assert.equal(true, message.endsWith(' not reachable'))
|
||||
assert.ok(message.startsWith('OAuth resource [rabbitmq] not available'))
|
||||
assert.ok(message.endsWith(' not reachable'))
|
||||
})
|
||||
|
||||
it('should not be presented oauth2 section', async function () {
|
||||
await homePage.isLoaded()
|
||||
if (await homePage.isOAuth2SectionVisible()) {
|
||||
throw new Error('OAuth2 section should not be present')
|
||||
}
|
||||
assert.ok(await homePage.isOAuth2SectionNotVisible())
|
||||
})
|
||||
|
||||
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 () {
|
||||
const visible = await homePage.isWarningVisible()
|
||||
assert.ok(!visible)
|
||||
assert.ok(await homePage.isWarningNotVisible())
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -28,15 +28,14 @@ describe('An user without management tag', function () {
|
|||
})
|
||||
|
||||
it('cannot log in into the management ui', async function () {
|
||||
const visible = await homePage.isWarningVisible()
|
||||
assert.ok(visible)
|
||||
assert.ok(await homePage.isWarningVisible())
|
||||
})
|
||||
|
||||
it('should get "Not authorized" warning message', async function(){
|
||||
assert.equal('Not authorized', await homePage.getWarning())
|
||||
assert.equal('Click here to logout', await homePage.getLogoutButton())
|
||||
assert.ok(!await homePage.isBasicAuthSectionVisible())
|
||||
assert.ok(!await homePage.isOAuth2SectionVisible())
|
||||
assert.ok(await homePage.isBasicAuthSectionNotVisible())
|
||||
assert.ok(await homePage.isOAuth2SectionNotVisible())
|
||||
})
|
||||
|
||||
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(){
|
||||
const visible = await homePage.isWarningVisible()
|
||||
assert.ok(!visible)
|
||||
assert.ok(await homePage.isWarningNotVisible())
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
@ -20,13 +20,13 @@ describe('When UAA is down', function () {
|
|||
it('should display warning message that UAA is down', async function () {
|
||||
await homePage.isLoaded()
|
||||
const message = await homePage.getWarning()
|
||||
assert.equal(true, message.startsWith('OAuth resource [rabbitmq] not available'))
|
||||
assert.equal(true, message.endsWith(' not reachable'))
|
||||
assert.ok(message.startsWith('OAuth resource [rabbitmq] not available'))
|
||||
assert.ok(message.endsWith(' not reachable'))
|
||||
})
|
||||
|
||||
it('should not be presented with a login button to log in', async function () {
|
||||
await homePage.isLoaded()
|
||||
assert.equal(false, await homePage.isLoginButtonVisible())
|
||||
assert.ok(await homePage.isLoginButtonNotVisible())
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
const { By, Key, until, Builder } = require('selenium-webdriver')
|
||||
require('chromedriver')
|
||||
const assert = require('assert')
|
||||
const { buildDriver, goToLogin, goToHome, captureScreensFor, teardown } = require('../../utils')
|
||||
const { buildDriver, goToHome, captureScreensFor, teardown } = require('../../utils')
|
||||
|
||||
const OverviewPage = require('../../pageobjects/OverviewPage')
|
||||
|
||||
describe('A user with a JWT token', function () {
|
||||
let overview
|
||||
let captureScreen
|
||||
let token
|
||||
let fakePortal
|
||||
|
||||
before(async function () {
|
||||
driver = buildDriver()
|
||||
|
|
|
@ -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 () {
|
||||
await homePage.isLoaded()
|
||||
const value = await homePage.getLoginButton()
|
||||
assert.equal(value, 'Click here to log in')
|
||||
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||
})
|
||||
|
||||
it('should not have a warning message', async function () {
|
||||
await homePage.isLoaded()
|
||||
const visible = await homePage.isWarningVisible()
|
||||
assert.ok(!visible)
|
||||
assert.ok(await homePage.isWarningNotVisible())
|
||||
})
|
||||
|
||||
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 () {
|
||||
await homePage.isLoaded()
|
||||
const value = await homePage.getLoginButton()
|
||||
assert.equal(value, 'Click here to log in')
|
||||
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||
})
|
||||
|
||||
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 () {
|
||||
const message = await homePage.getWarning()
|
||||
assert.equal('Not_Authorized', message)
|
||||
assert.equal(await homePage.getWarning(), 'Not_Authorized')
|
||||
})
|
||||
it('should be presented with a login button to log in', async function () {
|
||||
const value = await homePage.getLoginButton()
|
||||
assert.equal(value, 'Click here to log in')
|
||||
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||
})
|
||||
|
||||
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("RabbitMQ X_Idp", resources[2].text)
|
||||
|
||||
const value = await homePage.getLoginButton()
|
||||
assert.equal(value, 'Click here to log in')
|
||||
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||
})
|
||||
|
||||
it('should not have a warning message', async function () {
|
||||
await homePage.isLoaded()
|
||||
const visible = await homePage.isWarningVisible()
|
||||
assert.ok(!visible)
|
||||
assert.ok(await homePage.isWarningNotVisible())
|
||||
})
|
||||
|
||||
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 () {
|
||||
await homePage.isLoaded()
|
||||
const value = await homePage.getLoginButton()
|
||||
assert.equal(value, 'Click here to log in')
|
||||
assert.equal(await homePage.getLoginButton(), 'Click here to log in')
|
||||
})
|
||||
|
||||
it('should not have a warning message', async function () {
|
||||
await homePage.isLoaded()
|
||||
const visible = await homePage.isWarningVisible()
|
||||
assert.ok(!visible)
|
||||
assert.ok(await homePage.isWarningNotVisible())
|
||||
})
|
||||
|
||||
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 () {
|
||||
await homePage.clickToLogin()
|
||||
|
||||
await idpLogin.login('rabbit_admin', 'rabbit_admin')
|
||||
|
||||
if (!await exchanges.isLoaded()) {
|
||||
throw new Error('Failed to login')
|
||||
}
|
||||
|
||||
assert.equal("All exchanges (8)", await exchanges.getPagingSectionHeaderText())
|
||||
await exchanges.getPagingSectionHeaderText()
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -29,15 +29,14 @@ describe('An user without management tag', function () {
|
|||
if (!await homePage.isLoaded()) {
|
||||
throw new Error('Failed to login')
|
||||
}
|
||||
const visible = await homePage.isWarningVisible()
|
||||
assert.ok(visible)
|
||||
assert.ok(await homePage.isWarningVisible())
|
||||
})
|
||||
|
||||
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('Click here to logout', await homePage.getLogoutButton())
|
||||
assert.ok(!await homePage.isBasicAuthSectionVisible())
|
||||
assert.ok(!await homePage.isOAuth2SectionVisible())
|
||||
assert.ok(await homePage.isBasicAuthSectionNotVisible())
|
||||
assert.ok(await homePage.isOAuth2SectionNotVisible())
|
||||
})
|
||||
|
||||
describe("After clicking on logout button", function() {
|
||||
|
@ -48,8 +47,7 @@ describe('An user without management tag', function () {
|
|||
|
||||
it('should get redirected to home page again without error message', async function(){
|
||||
await driver.sleep(250)
|
||||
const visible = await homePage.isWarningVisible()
|
||||
assert.ok(!visible)
|
||||
assert.ok(await homePage.isWarningNotVisible())
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
@ -147,17 +147,11 @@ module.exports = class BasePage {
|
|||
} catch(e) {
|
||||
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() {
|
||||
let element = await driver.findElement(FORM_POPUP)
|
||||
return this.driver.wait(until.elementIsVisible(element), this.timeout,
|
||||
|
@ -208,15 +202,38 @@ module.exports = class BasePage {
|
|||
|
||||
async waitForDisplayed (locator) {
|
||||
if (this.interactionDelay && this.interactionDelay > 0) await this.driver.sleep(this.interactionDelay)
|
||||
let times = 1
|
||||
do {
|
||||
try {
|
||||
return this.waitForVisible(await this.waitForLocated(locator))
|
||||
}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
|
||||
}
|
||||
}
|
||||
} 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) {
|
||||
const element = await this.waitForDisplayed(locator)
|
||||
|
|
|
@ -51,6 +51,9 @@ module.exports = class SSOHomePage extends BasePage {
|
|||
async getOAuthResourceOptions () {
|
||||
return this.getSelectableOptions(SELECT_RESOURCES)
|
||||
}
|
||||
async isLoginButtonNotVisible() {
|
||||
return this.waitForNotDisplayed(OAUTH2_LOGIN_BUTTON)
|
||||
}
|
||||
async isLoginButtonVisible() {
|
||||
try {
|
||||
await this.waitForDisplayed(OAUTH2_LOGIN_BUTTON)
|
||||
|
@ -71,12 +74,18 @@ module.exports = class SSOHomePage extends BasePage {
|
|||
async isOAuth2SectionVisible() {
|
||||
return this.isDisplayed(SECTION_LOGIN_WITH_OAUTH)
|
||||
}
|
||||
async isOAuth2SectionNotVisible() {
|
||||
return this.waitForNotDisplayed(SECTION_LOGIN_WITH_OAUTH)
|
||||
}
|
||||
async getOAuth2Section() {
|
||||
return this.waitForDisplayed(SECTION_LOGIN_WITH_OAUTH)
|
||||
}
|
||||
async isBasicAuthSectionVisible() {
|
||||
return this.isDisplayed(SECTION_LOGIN_WITH_BASIC_AUTH)
|
||||
}
|
||||
async isBasicAuthSectionNotVisible() {
|
||||
return this.waitForNotDisplayed(SECTION_LOGIN_WITH_BASIC_AUTH)
|
||||
}
|
||||
async getBasicAuthSection() {
|
||||
return this.waitForDisplayed(SECTION_LOGIN_WITH_BASIC_AUTH)
|
||||
}
|
||||
|
@ -104,6 +113,9 @@ module.exports = class SSOHomePage extends BasePage {
|
|||
return Promise.resolve(false)
|
||||
}
|
||||
}
|
||||
async isWarningNotVisible () {
|
||||
return this.waitForNotDisplayed(WARNING)
|
||||
}
|
||||
async getWarnings() {
|
||||
try
|
||||
{
|
||||
|
|
|
@ -3,15 +3,17 @@ const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
|
|||
const fsp = fs.promises
|
||||
const path = require('path')
|
||||
const { By, Key, until, Builder, logging, Capabilities } = require('selenium-webdriver')
|
||||
const proxy = require('selenium-webdriver/proxy')
|
||||
require('chromedriver')
|
||||
const UAALoginPage = require('./pageobjects/UAALoginPage')
|
||||
const KeycloakLoginPage = require('./pageobjects/KeycloakLoginPage')
|
||||
const assert = require('assert')
|
||||
|
||||
const runLocal = String(process.env.RUN_LOCAL).toLowerCase() != 'false'
|
||||
const uaaUrl = process.env.UAA_URL || 'http://localhost:8080'
|
||||
const baseUrl = randomly_pick_baseurl(process.env.RABBITMQ_URL) || 'http://localhost:15672/'
|
||||
//const proxyUrl = calculateProxyUrl(baseUrl)
|
||||
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 screenshotsDir = process.env.SCREENSHOTS_DIR || '/screens'
|
||||
const profiles = process.env.PROFILES || ''
|
||||
|
@ -23,6 +25,19 @@ function randomly_pick_baseurl(baseUrl) {
|
|||
function getRandomInt(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 {
|
||||
driver
|
||||
test
|
||||
|
@ -64,10 +79,19 @@ module.exports = {
|
|||
"--disable-search-engine-choice-screen"
|
||||
]
|
||||
});
|
||||
driver = builder
|
||||
|
||||
builder = builder
|
||||
.forBrowser('chrome')
|
||||
.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 } )
|
||||
return driver
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue