Skip to content

Commit 096015b

Browse files
Merge pull request #11344 from rabbitmq/fix-10281
Add ssl_options to rabbitmq_auth_backend_http's schema
2 parents bd847b8 + 067964b commit 096015b

File tree

9 files changed

+434
-79
lines changed

9 files changed

+434
-79
lines changed

deps/rabbitmq_auth_backend_http/BUILD.bazel

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ all_srcs(name = "all_srcs")
4444
test_suite_beam_files(name = "test_suite_beam_files")
4545

4646
# gazelle:erlang_app_extra_app inets
47-
47+
# gazelle:erlang_app_extra_app public_key
4848
# gazelle:erlang_app_dep rabbit
4949

5050
rabbitmq_app(
@@ -57,7 +57,12 @@ rabbitmq_app(
5757
app_module = APP_MODULE,
5858
app_name = APP_NAME,
5959
beam_files = [":beam_files"],
60-
extra_apps = ["inets"],
60+
extra_apps = [
61+
"crypto",
62+
"inets",
63+
"ssl",
64+
"public_key",
65+
],
6166
license_files = [":license_files"],
6267
priv = [":priv"],
6368
deps = [
@@ -94,15 +99,14 @@ eunit(
9499

95100
broker_for_integration_suites()
96101

97-
rabbitmq_suite(
102+
rabbitmq_integration_suite(
98103
name = "auth_SUITE",
99104
size = "small",
100105
additional_beam = [
101106
"test/auth_http_mock.beam",
102107
],
103108
deps = [
104-
"//deps/rabbit_common:erlang_app",
105-
"@cowboy//:erlang_app",
109+
"@cowboy//:erlang_app"
106110
],
107111
)
108112

deps/rabbitmq_auth_backend_http/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ define PROJECT_APP_EXTRA_KEYS
1818
{broker_version_requirements, []}
1919
endef
2020

21-
LOCAL_DEPS = inets
21+
LOCAL_DEPS = ssl inets crypto public_key
2222
DEPS = rabbit_common rabbit amqp_client
2323
TEST_DEPS = rabbitmq_ct_helpers rabbitmq_ct_client_helpers cowboy
2424

deps/rabbitmq_auth_backend_http/priv/schema/rabbitmq_auth_backend_http.schema

Lines changed: 128 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
2-
%% ==========================================================================
31
%% ----------------------------------------------------------------------------
42
%% RabbitMQ HTTP Authorization
5-
%%
63
%% ----------------------------------------------------------------------------
74

85
{mapping, "auth_http.http_method", "rabbitmq_auth_backend_http.http_method",
@@ -25,3 +22,131 @@
2522

2623
{mapping, "auth_http.connection_timeout", "rabbitmq_auth_backend_http.connection_timeout",
2724
[{datatype, integer}]}.
25+
26+
%% TLS options
27+
28+
{mapping, "auth_http.ssl_options", "rabbitmq_auth_backend_http.ssl_options", [
29+
{datatype, {enum, [none]}}
30+
]}.
31+
32+
{translation, "rabbitmq_auth_backend_http.ssl_options",
33+
fun(Conf) ->
34+
case cuttlefish:conf_get("auth_http.ssl_options", Conf, undefined) of
35+
none -> [];
36+
_ -> cuttlefish:invalid("Invalid auth_http.ssl_options")
37+
end
38+
end}.
39+
40+
{mapping, "auth_http.ssl_options.verify", "rabbitmq_auth_backend_http.ssl_options.verify", [
41+
{datatype, {enum, [verify_peer, verify_none]}}]}.
42+
43+
{mapping, "auth_http.ssl_options.fail_if_no_peer_cert", "rabbitmq_auth_backend_http.ssl_options.fail_if_no_peer_cert", [
44+
{datatype, {enum, [true, false]}}]}.
45+
46+
{mapping, "auth_http.ssl_options.cacertfile", "rabbitmq_auth_backend_http.ssl_options.cacertfile",
47+
[{datatype, string}, {validators, ["file_accessible"]}]}.
48+
49+
{mapping, "auth_http.ssl_options.certfile", "rabbitmq_auth_backend_http.ssl_options.certfile",
50+
[{datatype, string}, {validators, ["file_accessible"]}]}.
51+
52+
{mapping, "auth_http.ssl_options.cacerts.$name", "rabbitmq_auth_backend_http.ssl_options.cacerts",
53+
[{datatype, string}]}.
54+
55+
{translation, "rabbitmq_auth_backend_http.ssl_options.cacerts",
56+
fun(Conf) ->
57+
Settings = cuttlefish_variable:filter_by_prefix("auth_http.ssl_options.cacerts", Conf),
58+
[ list_to_binary(V) || {_, V} <- Settings ]
59+
end}.
60+
61+
{mapping, "auth_http.ssl_options.cert", "rabbitmq_auth_backend_http.ssl_options.cert",
62+
[{datatype, string}]}.
63+
64+
{translation, "rabbitmq_auth_backend_http.ssl_options.cert",
65+
fun(Conf) ->
66+
list_to_binary(cuttlefish:conf_get("auth_http.ssl_options.cert", Conf))
67+
end}.
68+
69+
{mapping, "auth_http.ssl_options.client_renegotiation", "rabbitmq_auth_backend_http.ssl_options.client_renegotiation",
70+
[{datatype, {enum, [true, false]}}]}.
71+
72+
{mapping, "auth_http.ssl_options.crl_check", "rabbitmq_auth_backend_http.ssl_options.crl_check",
73+
[{datatype, [{enum, [true, false, peer, best_effort]}]}]}.
74+
75+
{mapping, "auth_http.ssl_options.depth", "rabbitmq_auth_backend_http.ssl_options.depth",
76+
[{datatype, integer}, {validators, ["byte"]}]}.
77+
78+
{mapping, "auth_http.ssl_options.dh", "rabbitmq_auth_backend_http.ssl_options.dh",
79+
[{datatype, string}]}.
80+
81+
{translation, "rabbitmq_auth_backend_http.ssl_options.dh",
82+
fun(Conf) ->
83+
list_to_binary(cuttlefish:conf_get("auth_http.ssl_options.dh", Conf))
84+
end}.
85+
86+
{mapping, "auth_http.ssl_options.dhfile", "rabbitmq_auth_backend_http.ssl_options.dhfile",
87+
[{datatype, string}, {validators, ["file_accessible"]}]}.
88+
89+
{mapping, "auth_http.ssl_options.honor_cipher_order", "rabbitmq_auth_backend_http.ssl_options.honor_cipher_order",
90+
[{datatype, {enum, [true, false]}}]}.
91+
92+
{mapping, "auth_http.ssl_options.honor_ecc_order", "rabbitmq_auth_backend_http.ssl_options.honor_ecc_order",
93+
[{datatype, {enum, [true, false]}}]}.
94+
95+
{mapping, "auth_http.ssl_options.key.RSAPrivateKey", "rabbitmq_auth_backend_http.ssl_options.key",
96+
[{datatype, string}]}.
97+
98+
{mapping, "auth_http.ssl_options.key.DSAPrivateKey", "rabbitmq_auth_backend_http.ssl_options.key",
99+
[{datatype, string}]}.
100+
101+
{mapping, "auth_http.ssl_options.key.PrivateKeyInfo", "rabbitmq_auth_backend_http.ssl_options.key",
102+
[{datatype, string}]}.
103+
104+
{translation, "rabbitmq_auth_backend_http.ssl_options.key",
105+
fun(Conf) ->
106+
case cuttlefish_variable:filter_by_prefix("auth_http.ssl_options.key", Conf) of
107+
[{[_,_,Key], Val}|_] -> {list_to_atom(Key), list_to_binary(Val)};
108+
_ -> undefined
109+
end
110+
end}.
111+
112+
{mapping, "auth_http.ssl_options.keyfile", "rabbitmq_auth_backend_http.ssl_options.keyfile",
113+
[{datatype, string}, {validators, ["file_accessible"]}]}.
114+
115+
{mapping, "auth_http.ssl_options.log_alert", "rabbitmq_auth_backend_http.ssl_options.log_alert",
116+
[{datatype, {enum, [true, false]}}]}.
117+
118+
{mapping, "auth_http.ssl_options.password", "rabbitmq_auth_backend_http.ssl_options.password",
119+
[{datatype, string}]}.
120+
121+
{mapping, "auth_http.ssl_options.psk_identity", "rabbitmq_auth_backend_http.ssl_options.psk_identity",
122+
[{datatype, string}]}.
123+
124+
{mapping, "auth_http.ssl_options.reuse_sessions", "rabbitmq_auth_backend_http.ssl_options.reuse_sessions",
125+
[{datatype, {enum, [true, false]}}]}.
126+
127+
{mapping, "auth_http.ssl_options.secure_renegotiate", "rabbitmq_auth_backend_http.ssl_options.secure_renegotiate",
128+
[{datatype, {enum, [true, false]}}]}.
129+
130+
{mapping, "auth_http.ssl_options.versions.$version", "rabbitmq_auth_backend_http.ssl_options.versions",
131+
[{datatype, atom}]}.
132+
133+
{translation, "rabbitmq_auth_backend_http.ssl_options.versions",
134+
fun(Conf) ->
135+
Settings = cuttlefish_variable:filter_by_prefix("auth_http.ssl_options.versions", Conf),
136+
[ V || {_, V} <- Settings ]
137+
end}.
138+
139+
{mapping, "auth_http.ssl_options.sni", "rabbitmq_auth_backend_http.ssl_options.server_name_indication",
140+
[{datatype, [{enum, [none]}, string]}]}.
141+
142+
{translation, "rabbitmq_auth_backend_http.ssl_options.server_name_indication",
143+
fun(Conf) ->
144+
case cuttlefish:conf_get("auth_http.ssl_options.sni", Conf, undefined) of
145+
undefined -> cuttlefish:unset();
146+
none -> cuttlefish:unset();
147+
Hostname -> Hostname
148+
end
149+
end}.
150+
151+
{mapping, "auth_http.ssl_options.hostname_verification", "rabbitmq_auth_backend_http.ssl_hostname_verification", [
152+
{datatype, {enum, [wildcard, none]}}]}.

deps/rabbitmq_auth_backend_http/src/rabbit_auth_backend_http.erl

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ http_req(Path, Query, Retry) ->
163163
Other -> Other
164164
end.
165165

166-
167166
do_http_req(Path0, Query) ->
168167
URI = uri_parser:parse(Path0, [{port, 80}]),
169168
{host, Host} = lists:keyfind(host, 1, URI),
@@ -190,19 +189,8 @@ do_http_req(Path0, Query) ->
190189
_ -> RequestTimeout
191190
end,
192191
rabbit_log:debug("auth_backend_http: request timeout: ~tp, connection timeout: ~tp", [RequestTimeout, ConnectionTimeout]),
193-
HttpOpts = case application:get_env(rabbitmq_auth_backend_http, ssl_options) of
194-
{ok, Opts} when is_list(Opts) ->
195-
[
196-
{ssl, Opts},
197-
{timeout, RequestTimeout},
198-
{connect_timeout, ConnectionTimeout}];
199-
_ ->
200-
[
201-
{timeout, RequestTimeout},
202-
{connect_timeout, ConnectionTimeout}
203-
]
204-
end,
205-
192+
HttpOpts = [{timeout, RequestTimeout},
193+
{connect_timeout, ConnectionTimeout}] ++ ssl_options(),
206194
case httpc:request(Method, Request, HttpOpts, []) of
207195
{ok, {{_HTTP, Code, _}, _Headers, Body}} ->
208196
rabbit_log:debug("auth_backend_http: response code is ~tp, body: ~tp", [Code, Body]),
@@ -214,6 +202,22 @@ do_http_req(Path0, Query) ->
214202
E
215203
end.
216204

205+
ssl_options() ->
206+
case application:get_env(rabbitmq_auth_backend_http, ssl_options) of
207+
{ok, Opts0} when is_list(Opts0) ->
208+
Opts1 = [{ssl, rabbit_networking:fix_ssl_options(Opts0)}],
209+
case application:get_env(rabbitmq_auth_backend_http, ssl_hostname_verification) of
210+
{ok, wildcard} ->
211+
rabbit_log:debug("Enabling wildcard-aware hostname verification for HTTP client connections"),
212+
%% Needed for HTTPS connections that connect to servers that use wildcard certificates.
213+
%% See https://erlang.org/doc/man/public_key.html#pkix_verify_hostname_match_fun-1.
214+
[{customize_hostname_check, [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]} | Opts1];
215+
_ ->
216+
Opts1
217+
end;
218+
_ -> []
219+
end.
220+
217221
p(PathName) ->
218222
{ok, Path} = application:get_env(rabbitmq_auth_backend_http, PathName),
219223
Path.

0 commit comments

Comments
 (0)