Skip to content

Commit 7910084

Browse files
committed
Add support for multiline cuttlefish values in LDAP plugin
The cuttlefish project recently added support for multiline values. The primary motivation for this is so that LDAP settings like `vhost_access_query` could now be expressed in `rabbitmq.conf`, rather than requiring `advanced.config`. These changes require cuttlefish version `3.6.0` or later. References: * Kyorai/cuttlefish#60 * Kyorai/cuttlefish#63
1 parent 6154afc commit 7910084

File tree

5 files changed

+209
-26
lines changed

5 files changed

+209
-26
lines changed

deps/rabbitmq_auth_backend_ldap/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ define PROJECT_APP_EXTRA_KEYS
3535
endef
3636

3737
LOCAL_DEPS = eldap public_key
38-
DEPS = rabbit_common rabbit
38+
DEPS = rabbit_common rabbit cuttlefish
3939
TEST_DEPS = ct_helper rabbitmq_ct_helpers rabbitmq_ct_client_helpers amqp_client
4040
dep_ct_helper = git https://github.com/extend/ct_helper.git master
4141

deps/rabbitmq_auth_backend_ldap/priv/schema/rabbitmq_auth_backend_ldap.schema

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
%% vim:ft=erlang:
2+
%% -*- mode: erlang; -*-
13
%% ----------------------------------------------------------------------------
24
%% RabbitMQ LDAP Plugin
35
%%
46
%% See https://www.rabbitmq.com/ldap.html for details.
57
%%
68
%% ----------------------------------------------------------------------------
79

8-
% {rabbitmq_auth_backend_ldap,
9-
% [
1010
%%
1111
%% Connecting to the LDAP server(s)
1212
%% ================================
@@ -191,25 +191,6 @@ end}.
191191
{mapping, "auth_ldap.group_lookup_base", "rabbitmq_auth_backend_ldap.group_lookup_base",
192192
[{datatype, [{enum, [none]}, string]}]}.
193193

194-
%% The LDAP plugin can perform a variety of queries against your
195-
%% LDAP server to determine questions of authorisation. See
196-
%% https://www.rabbitmq.com/ldap.html#authorisation for more
197-
%% information.
198-
199-
%% Set the query to use when determining vhost access
200-
%%
201-
%% {vhost_access_query, {in_group,
202-
%% "ou=${vhost}-users,ou=vhosts,dc=example,dc=com"}},
203-
204-
%% Set the query to use when determining resource (e.g., queue) access
205-
%%
206-
%% {resource_access_query, {constant, true}},
207-
208-
%% Set queries to determine which tags a user has
209-
%%
210-
%% {tag_queries, []}
211-
% ]},
212-
213194
%% Connect to the LDAP server using TLS
214195
%%
215196
%% {use_ssl, false},
@@ -341,6 +322,62 @@ fun(Conf) ->
341322
end
342323
end}.
343324

344-
345325
{mapping, "auth_ldap.ssl_options.hostname_verification", "rabbitmq_auth_backend_ldap.ssl_hostname_verification", [
346326
{datatype, {enum, [wildcard, none]}}]}.
327+
328+
%% The LDAP plugin can perform a variety of queries against your
329+
%% LDAP server to determine questions of authorisation. See
330+
%% https://rabbitmq.com/docs/ldap#authorisation for more
331+
%% information.
332+
333+
{mapping, "auth_ldap.queries.vhost_access", "rabbitmq_auth_backend_ldap.vhost_access_query",
334+
[{datatype, string}]}.
335+
336+
{translation, "rabbitmq_auth_backend_ldap.vhost_access_query",
337+
fun(Conf) ->
338+
case cuttlefish:conf_get("auth_ldap.queries.vhost_access", Conf, undefined) of
339+
undefined ->
340+
cuttlefish:unset();
341+
Query ->
342+
rabbit_auth_backend_ldap_util:parse_query(Query)
343+
end
344+
end}.
345+
346+
{mapping, "auth_ldap.queries.resource_access", "rabbitmq_auth_backend_ldap.resource_access_query",
347+
[{datatype, string}]}.
348+
349+
{translation, "rabbitmq_auth_backend_ldap.resource_access_query",
350+
fun(Conf) ->
351+
case cuttlefish:conf_get("auth_ldap.queries.resource_access", Conf, undefined) of
352+
undefined ->
353+
cuttlefish:unset();
354+
Query ->
355+
rabbit_auth_backend_ldap_util:parse_query(Query)
356+
end
357+
end}.
358+
359+
{mapping, "auth_ldap.queries.topic_access", "rabbitmq_auth_backend_ldap.topic_access_query",
360+
[{datatype, string}]}.
361+
362+
{translation, "rabbitmq_auth_backend_ldap.topic_access_query",
363+
fun(Conf) ->
364+
case cuttlefish:conf_get("auth_ldap.queries.topic_access", Conf, undefined) of
365+
undefined ->
366+
cuttlefish:unset();
367+
Query ->
368+
rabbit_auth_backend_ldap_util:parse_query(Query)
369+
end
370+
end}.
371+
372+
{mapping, "auth_ldap.queries.tags", "rabbitmq_auth_backend_ldap.tag_queries",
373+
[{datatype, string}]}.
374+
375+
{translation, "rabbitmq_auth_backend_ldap.tag_queries",
376+
fun(Conf) ->
377+
case cuttlefish:conf_get("auth_ldap.queries.tags", Conf, undefined) of
378+
undefined ->
379+
cuttlefish:unset();
380+
Query ->
381+
rabbit_auth_backend_ldap_util:parse_query(Query)
382+
end
383+
end}.

deps/rabbitmq_auth_backend_ldap/src/rabbit_auth_backend_ldap_util.erl

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
-module(rabbit_auth_backend_ldap_util).
99

10-
-export([fill/2, get_active_directory_args/1]).
10+
-export([fill/2, get_active_directory_args/1, parse_query/1]).
1111

1212
fill(Fmt, []) ->
1313
binary_to_list(iolist_to_binary(Fmt));
@@ -32,3 +32,57 @@ get_active_directory_args(Username) when is_binary(Username) ->
3232
% If Username is in Domain\User format, provide additional fill
3333
% template arguments
3434
get_active_directory_args(binary:split(Username, <<"\\">>, [trim_all])).
35+
36+
parse_query(Query) when is_binary(Query) ->
37+
parse_query(rabbit_data_coercion:to_unicode_charlist(Query));
38+
parse_query(Query0) when is_list(Query0) ->
39+
Query1 = fixup_query(Query0),
40+
parse_query_handle_erl_scan(erl_scan:string(Query1)).
41+
42+
fixup_query(Query0) ->
43+
Query1 = string:trim(Query0, both),
44+
fixup_query(lists:last(Query1) =:= $., Query1).
45+
46+
fixup_query(true, Query) ->
47+
Query;
48+
fixup_query(false, Query) ->
49+
Query ++ ".".
50+
51+
parse_query_handle_erl_scan({ok, Tokens, _EndLine}) ->
52+
parse_query_handle_exprs(erl_parse:parse_exprs(Tokens));
53+
parse_query_handle_erl_scan(Error) ->
54+
cuttlefish:invalid(fmt("invalid query: ~tp", [Error])).
55+
56+
parse_query_handle_exprs({ok, AbsForm}) ->
57+
parse_query_handle_eval(erl_eval:exprs(AbsForm, erl_eval:new_bindings()));
58+
parse_query_handle_exprs(Error) ->
59+
cuttlefish:invalid(fmt("invalid query: ~tp", [Error])).
60+
61+
parse_query_handle_eval({value, {constant, true}=T, _}) ->
62+
T;
63+
parse_query_handle_eval({value, {constant, false}=T, _}) ->
64+
T;
65+
parse_query_handle_eval({value, {in_group, _}=T, _}) ->
66+
T;
67+
parse_query_handle_eval({value, {in_group_nested, _, _}=T, _}) ->
68+
T;
69+
parse_query_handle_eval({value, {for, Q}=T, _}) when is_list(Q) ->
70+
T;
71+
parse_query_handle_eval({value, {'not', _}=T, _}) ->
72+
T;
73+
parse_query_handle_eval({value, {'and', Q}=T, _}) when is_list(Q) ->
74+
T;
75+
parse_query_handle_eval({value, {'or', Q}=T, _}) when is_list(Q) ->
76+
T;
77+
parse_query_handle_eval({value, {equals, _, _}=T, _}) ->
78+
T;
79+
parse_query_handle_eval({value, {match, _, _}=T, _}) ->
80+
T;
81+
parse_query_handle_eval({value, T, _}) when is_list(T) ->
82+
%% NB: tag_queries uses this form
83+
T;
84+
parse_query_handle_eval({value, Unexpected, _}) ->
85+
cuttlefish:invalid(fmt("invalid query: ~tp", [Unexpected])).
86+
87+
fmt(Fmt, Args) ->
88+
rabbit_data_coercion:to_unicode_charlist(io_lib:format(Fmt, Args)).

deps/rabbitmq_auth_backend_ldap/test/config_schema_SUITE_data/rabbitmq_auth_backend_ldap.snippets

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
%% vim:ft=erlang:
2+
%% -*- mode: erlang; -*-
3+
14
[{ldap_servers,
25
"auth_ldap.servers.1 = DC1.domain.com
36
auth_ldap.servers.2 = DC1.eng.domain.com",
@@ -334,5 +337,94 @@
334337
{versions,['tlsv1.2','tlsv1.1']}
335338
]},
336339
{use_ssl, true}]}],
337-
[]}
340+
[]},
341+
342+
{vhost_access_query,
343+
"auth_ldap.queries.vhost_access = '''
344+
{in_group,\"ou=${vhost}-users,ou=vhosts,dc=example,dc=com\"}
345+
'''",
346+
[
347+
{rabbitmq_auth_backend_ldap, [
348+
{vhost_access_query, {in_group,"ou=${vhost}-users,ou=vhosts,dc=example,dc=com"}}
349+
]}
350+
],
351+
[rabbitmq_auth_backend_ldap]},
352+
353+
{vhost_access_query_period_ending,
354+
"auth_ldap.queries.vhost_access = '''
355+
{in_group,\"ou=${vhost}-users,ou=vhosts,dc=example,dc=com\"}.
356+
'''",
357+
[
358+
{rabbitmq_auth_backend_ldap, [
359+
{vhost_access_query, {in_group,"ou=${vhost}-users,ou=vhosts,dc=example,dc=com"}}
360+
]}
361+
],
362+
[rabbitmq_auth_backend_ldap]},
363+
364+
{resource_access_query,
365+
"auth_ldap.queries.resource_access = '''
366+
{for, [
367+
{permission, configure, {in_group, \"cn=admin,dc=example,dc=com\"}},
368+
{permission, write, {for, [
369+
{resource, queue, {in_group, \"cn=admin,dc=example,dc=com\"}},
370+
{resource, exchange, {constant, true}}
371+
]}},
372+
{permission, read, {for, [
373+
{resource, exchange, {in_group, \"cn=admin,dc=example,dc=com\"}},
374+
{resource, queue, {constant, true}}
375+
]}}
376+
]}
377+
'''",
378+
[
379+
{rabbitmq_auth_backend_ldap, [
380+
{resource_access_query,
381+
{for, [
382+
{permission, configure, {in_group, "cn=admin,dc=example,dc=com"}},
383+
{permission, write, {for, [
384+
{resource, queue, {in_group, "cn=admin,dc=example,dc=com"}},
385+
{resource, exchange, {constant, true}}
386+
]}},
387+
{permission, read, {for, [
388+
{resource, exchange, {in_group, "cn=admin,dc=example,dc=com"}},
389+
{resource, queue, {constant, true}}
390+
]}}
391+
]}
392+
}
393+
]}
394+
],
395+
[rabbitmq_auth_backend_ldap]},
396+
397+
{topic_access_query,
398+
"auth_ldap.queries.topic_access = '''
399+
{for, [
400+
{permission, write, {match, {string, \"${routing_key}\"}, {string, \"^a\"}}},
401+
{permission, read, {constant, true}}
402+
]}
403+
'''",
404+
[
405+
{rabbitmq_auth_backend_ldap, [
406+
{topic_access_query,
407+
{for, [
408+
{permission, write, {match, {string, "${routing_key}"}, {string, "^a"}}},
409+
{permission, read, {constant, true}}
410+
]}
411+
}
412+
]}
413+
],
414+
[rabbitmq_auth_backend_ldap]},
415+
416+
{tag_queries,
417+
"auth_ldap.queries.tags = '''
418+
[{administrator, {constant, false}},
419+
{management, {constant, true}}]
420+
'''",
421+
[
422+
{rabbitmq_auth_backend_ldap, [
423+
{tag_queries, [
424+
{administrator, {constant, false}},
425+
{management, {constant, true}}
426+
]}
427+
]}
428+
],
429+
[rabbitmq_auth_backend_ldap]}
338430
].

rabbitmq-components.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ dep_accept = hex 0.3.5
4343
dep_cowboy = hex 2.14.1
4444
dep_cowlib = hex 2.16.0
4545
dep_credentials_obfuscation = hex 3.5.0
46-
dep_cuttlefish = hex 3.5.0
46+
dep_cuttlefish = hex 3.6.0
4747
dep_gen_batch_server = hex 0.8.8
4848
dep_jose = hex 1.11.10
4949
dep_khepri = hex 0.17.2

0 commit comments

Comments
 (0)