Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions deps/rabbitmq_auth_backend_http/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ all_srcs(name = "all_srcs")
test_suite_beam_files(name = "test_suite_beam_files")

# gazelle:erlang_app_extra_app inets

# gazelle:erlang_app_extra_app public_key
# gazelle:erlang_app_dep rabbit

rabbitmq_app(
Expand All @@ -57,7 +57,12 @@ rabbitmq_app(
app_module = APP_MODULE,
app_name = APP_NAME,
beam_files = [":beam_files"],
extra_apps = ["inets"],
extra_apps = [
"crypto",
"inets",
"ssl",
"public_key",
],
license_files = [":license_files"],
priv = [":priv"],
deps = [
Expand Down Expand Up @@ -94,15 +99,14 @@ eunit(

broker_for_integration_suites()

rabbitmq_suite(
rabbitmq_integration_suite(
name = "auth_SUITE",
size = "small",
additional_beam = [
"test/auth_http_mock.beam",
],
deps = [
"//deps/rabbit_common:erlang_app",
"@cowboy//:erlang_app",
"@cowboy//:erlang_app"
],
)

Expand Down
2 changes: 1 addition & 1 deletion deps/rabbitmq_auth_backend_http/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ define PROJECT_APP_EXTRA_KEYS
{broker_version_requirements, []}
endef

LOCAL_DEPS = inets
LOCAL_DEPS = ssl inets crypto public_key
DEPS = rabbit_common rabbit amqp_client
TEST_DEPS = rabbitmq_ct_helpers rabbitmq_ct_client_helpers cowboy

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@

%% ==========================================================================
%% ----------------------------------------------------------------------------
%% RabbitMQ HTTP Authorization
%%
%% ----------------------------------------------------------------------------

{mapping, "auth_http.http_method", "rabbitmq_auth_backend_http.http_method",
Expand All @@ -25,3 +22,131 @@

{mapping, "auth_http.connection_timeout", "rabbitmq_auth_backend_http.connection_timeout",
[{datatype, integer}]}.

%% TLS options

{mapping, "auth_http.ssl_options", "rabbitmq_auth_backend_http.ssl_options", [
{datatype, {enum, [none]}}
]}.

{translation, "rabbitmq_auth_backend_http.ssl_options",
fun(Conf) ->
case cuttlefish:conf_get("auth_http.ssl_options", Conf, undefined) of
none -> [];
_ -> cuttlefish:invalid("Invalid auth_http.ssl_options")
end
end}.

{mapping, "auth_http.ssl_options.verify", "rabbitmq_auth_backend_http.ssl_options.verify", [
{datatype, {enum, [verify_peer, verify_none]}}]}.

{mapping, "auth_http.ssl_options.fail_if_no_peer_cert", "rabbitmq_auth_backend_http.ssl_options.fail_if_no_peer_cert", [
{datatype, {enum, [true, false]}}]}.

{mapping, "auth_http.ssl_options.cacertfile", "rabbitmq_auth_backend_http.ssl_options.cacertfile",
[{datatype, string}, {validators, ["file_accessible"]}]}.

{mapping, "auth_http.ssl_options.certfile", "rabbitmq_auth_backend_http.ssl_options.certfile",
[{datatype, string}, {validators, ["file_accessible"]}]}.

{mapping, "auth_http.ssl_options.cacerts.$name", "rabbitmq_auth_backend_http.ssl_options.cacerts",
[{datatype, string}]}.

{translation, "rabbitmq_auth_backend_http.ssl_options.cacerts",
fun(Conf) ->
Settings = cuttlefish_variable:filter_by_prefix("auth_http.ssl_options.cacerts", Conf),
[ list_to_binary(V) || {_, V} <- Settings ]
end}.

{mapping, "auth_http.ssl_options.cert", "rabbitmq_auth_backend_http.ssl_options.cert",
[{datatype, string}]}.

{translation, "rabbitmq_auth_backend_http.ssl_options.cert",
fun(Conf) ->
list_to_binary(cuttlefish:conf_get("auth_http.ssl_options.cert", Conf))
end}.

{mapping, "auth_http.ssl_options.client_renegotiation", "rabbitmq_auth_backend_http.ssl_options.client_renegotiation",
[{datatype, {enum, [true, false]}}]}.

{mapping, "auth_http.ssl_options.crl_check", "rabbitmq_auth_backend_http.ssl_options.crl_check",
[{datatype, [{enum, [true, false, peer, best_effort]}]}]}.

{mapping, "auth_http.ssl_options.depth", "rabbitmq_auth_backend_http.ssl_options.depth",
[{datatype, integer}, {validators, ["byte"]}]}.

{mapping, "auth_http.ssl_options.dh", "rabbitmq_auth_backend_http.ssl_options.dh",
[{datatype, string}]}.

{translation, "rabbitmq_auth_backend_http.ssl_options.dh",
fun(Conf) ->
list_to_binary(cuttlefish:conf_get("auth_http.ssl_options.dh", Conf))
end}.

{mapping, "auth_http.ssl_options.dhfile", "rabbitmq_auth_backend_http.ssl_options.dhfile",
[{datatype, string}, {validators, ["file_accessible"]}]}.

{mapping, "auth_http.ssl_options.honor_cipher_order", "rabbitmq_auth_backend_http.ssl_options.honor_cipher_order",
[{datatype, {enum, [true, false]}}]}.

{mapping, "auth_http.ssl_options.honor_ecc_order", "rabbitmq_auth_backend_http.ssl_options.honor_ecc_order",
[{datatype, {enum, [true, false]}}]}.

{mapping, "auth_http.ssl_options.key.RSAPrivateKey", "rabbitmq_auth_backend_http.ssl_options.key",
[{datatype, string}]}.

{mapping, "auth_http.ssl_options.key.DSAPrivateKey", "rabbitmq_auth_backend_http.ssl_options.key",
[{datatype, string}]}.

{mapping, "auth_http.ssl_options.key.PrivateKeyInfo", "rabbitmq_auth_backend_http.ssl_options.key",
[{datatype, string}]}.

{translation, "rabbitmq_auth_backend_http.ssl_options.key",
fun(Conf) ->
case cuttlefish_variable:filter_by_prefix("auth_http.ssl_options.key", Conf) of
[{[_,_,Key], Val}|_] -> {list_to_atom(Key), list_to_binary(Val)};
_ -> undefined
end
end}.

{mapping, "auth_http.ssl_options.keyfile", "rabbitmq_auth_backend_http.ssl_options.keyfile",
[{datatype, string}, {validators, ["file_accessible"]}]}.

{mapping, "auth_http.ssl_options.log_alert", "rabbitmq_auth_backend_http.ssl_options.log_alert",
[{datatype, {enum, [true, false]}}]}.

{mapping, "auth_http.ssl_options.password", "rabbitmq_auth_backend_http.ssl_options.password",
[{datatype, string}]}.

{mapping, "auth_http.ssl_options.psk_identity", "rabbitmq_auth_backend_http.ssl_options.psk_identity",
[{datatype, string}]}.

{mapping, "auth_http.ssl_options.reuse_sessions", "rabbitmq_auth_backend_http.ssl_options.reuse_sessions",
[{datatype, {enum, [true, false]}}]}.

{mapping, "auth_http.ssl_options.secure_renegotiate", "rabbitmq_auth_backend_http.ssl_options.secure_renegotiate",
[{datatype, {enum, [true, false]}}]}.

{mapping, "auth_http.ssl_options.versions.$version", "rabbitmq_auth_backend_http.ssl_options.versions",
[{datatype, atom}]}.

{translation, "rabbitmq_auth_backend_http.ssl_options.versions",
fun(Conf) ->
Settings = cuttlefish_variable:filter_by_prefix("auth_http.ssl_options.versions", Conf),
[ V || {_, V} <- Settings ]
end}.

{mapping, "auth_http.ssl_options.sni", "rabbitmq_auth_backend_http.ssl_options.server_name_indication",
[{datatype, [{enum, [none]}, string]}]}.

{translation, "rabbitmq_auth_backend_http.ssl_options.server_name_indication",
fun(Conf) ->
case cuttlefish:conf_get("auth_http.ssl_options.sni", Conf, undefined) of
undefined -> cuttlefish:unset();
none -> cuttlefish:unset();
Hostname -> Hostname
end
end}.

{mapping, "auth_http.ssl_options.hostname_verification", "rabbitmq_auth_backend_http.ssl_hostname_verification", [
{datatype, {enum, [wildcard, none]}}]}.
32 changes: 18 additions & 14 deletions deps/rabbitmq_auth_backend_http/src/rabbit_auth_backend_http.erl
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ http_req(Path, Query, Retry) ->
Other -> Other
end.


do_http_req(Path0, Query) ->
URI = uri_parser:parse(Path0, [{port, 80}]),
{host, Host} = lists:keyfind(host, 1, URI),
Expand All @@ -190,19 +189,8 @@ do_http_req(Path0, Query) ->
_ -> RequestTimeout
end,
rabbit_log:debug("auth_backend_http: request timeout: ~tp, connection timeout: ~tp", [RequestTimeout, ConnectionTimeout]),
HttpOpts = case application:get_env(rabbitmq_auth_backend_http, ssl_options) of
{ok, Opts} when is_list(Opts) ->
[
{ssl, Opts},
{timeout, RequestTimeout},
{connect_timeout, ConnectionTimeout}];
_ ->
[
{timeout, RequestTimeout},
{connect_timeout, ConnectionTimeout}
]
end,

HttpOpts = [{timeout, RequestTimeout},
{connect_timeout, ConnectionTimeout}] ++ ssl_options(),
case httpc:request(Method, Request, HttpOpts, []) of
{ok, {{_HTTP, Code, _}, _Headers, Body}} ->
rabbit_log:debug("auth_backend_http: response code is ~tp, body: ~tp", [Code, Body]),
Expand All @@ -214,6 +202,22 @@ do_http_req(Path0, Query) ->
E
end.

ssl_options() ->
case application:get_env(rabbitmq_auth_backend_http, ssl_options) of
{ok, Opts0} when is_list(Opts0) ->
Opts1 = [{ssl, rabbit_networking:fix_ssl_options(Opts0)}],
case application:get_env(rabbitmq_auth_backend_http, ssl_hostname_verification) of
{ok, wildcard} ->
rabbit_log:debug("Enabling wildcard-aware hostname verification for HTTP client connections"),
%% Needed for HTTPS connections that connect to servers that use wildcard certificates.
%% See https://erlang.org/doc/man/public_key.html#pkix_verify_hostname_match_fun-1.
[{customize_hostname_check, [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]} | Opts1];
_ ->
Opts1
end;
_ -> []
end.

p(PathName) ->
{ok, Path} = application:get_env(rabbitmq_auth_backend_http, PathName),
Path.
Expand Down
Loading