1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2012 Inktank
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
17 #include "include/stringify.h"
18 #include "mon/MonCap.h"
20 #include "gtest/gtest.h"
24 const char *parse_good
[] = {
36 "allow service=foo x",
37 "allow service=\"froo\" x",
39 "allow profile osd-bootstrap",
40 "allow profile \"mds-bootstrap\", allow *",
41 "allow command \"a b c\"",
43 "allow command abc with arg=foo",
44 "allow command abc with arg=foo arg2=bar",
45 "allow command abc with arg=foo arg2=bar",
46 "allow command abc with arg=foo arg2 prefix bar arg3 prefix baz",
47 "allow command abc with arg=foo arg2 prefix \"bar bingo\" arg3 prefix baz",
48 "allow command abc with arg regex \"^[0-9a-z.]*$\"",
49 "allow command abc with arg regex \"\(invaluid regex\"",
50 "allow service foo x",
51 "allow service foo x; allow service bar x",
52 "allow service foo w ;allow service bar x",
53 "allow service foo w , allow service bar x",
54 "allow service foo r , allow service bar x",
55 "allow service foo_foo r, allow service bar r",
56 "allow service foo-foo r, allow service bar r",
57 "allow service \" foo \" w, allow service bar r",
58 "allow command abc with arg=foo arg2=bar, allow service foo r",
59 "allow command abc.def with arg=foo arg2=bar, allow service foo r",
60 "allow command \"foo bar\" with arg=\"baz\"",
61 "allow command \"foo bar\" with arg=\"baz.xx\"",
63 "profile \"mds-bootstrap\", profile foo",
64 "allow * network 1.2.3.4/24",
65 "allow * network ::1/128",
66 "allow * network [aa:bb::1]/128",
67 "allow service=foo x network 1.2.3.4/16",
68 "allow command abc network 1.2.3.4/8",
69 "profile osd network 1.2.3.4/32",
70 "allow profile mon network 1.2.3.4/32",
74 TEST(MonCap
, ParseGood
) {
75 for (int i
=0; parse_good
[i
]; ++i
) {
76 string str
= parse_good
[i
];
78 std::cout
<< "Testing good input: '" << str
<< "'" << std::endl
;
79 ASSERT_TRUE(cap
.parse(str
, &cout
));
80 std::cout
<< " -> " << cap
<< std::endl
;
84 // these should stringify to the input value
85 const char *parse_identity
[] = {
89 "allow service foo x",
91 "allow profile osd-bootstrap",
92 "allow profile mds-bootstrap, allow *",
93 "allow profile \"foo bar\", allow *",
95 "allow command \"a b c\"",
96 "allow command abc with arg=foo",
97 "allow command abc with arg=foo arg2=bar",
98 "allow command abc with arg=foo arg2=bar",
99 "allow command abc with arg=foo arg2 prefix bar arg3 prefix baz",
100 "allow command abc with arg=foo arg2 prefix \"bar bingo\" arg3 prefix baz",
101 "allow service foo x",
102 "allow service foo x, allow service bar x",
103 "allow service foo w, allow service bar x",
104 "allow service foo r, allow service bar x",
105 "allow service foo_foo r, allow service bar r",
106 "allow service foo-foo r, allow service bar r",
107 "allow service \" foo \" w, allow service bar r",
108 "allow command abc with arg=foo arg2=bar, allow service foo r",
112 TEST(MonCap
, ParseIdentity
)
114 for (int i
=0; parse_identity
[i
]; ++i
) {
115 string str
= parse_identity
[i
];
117 std::cout
<< "Testing good input: '" << str
<< "'" << std::endl
;
118 ASSERT_TRUE(cap
.parse(str
, &cout
));
119 string out
= stringify(cap
);
124 const char *parse_bad
[] = {
128 "allow profile foo rwx",
130 "allow profile foo bar rwx",
132 "allow command baz x",
137 "allow r pool foo r",
138 "allow wwx pool taco",
139 "allow wwx pool taco^funny&chars",
140 "allow rwx pool 'weird name''",
141 "allow rwx object_prefix \"beforepool\" pool weird",
142 "allow rwx auid 123 pool asdf",
143 "allow command foo a prefix b",
144 "allow command foo with a prefixb",
145 "allow command foo with a = prefix b",
146 "allow command foo with a prefix b c",
150 TEST(MonCap
, ParseBad
) {
151 for (int i
=0; parse_bad
[i
]; ++i
) {
152 string str
= parse_bad
[i
];
154 std::cout
<< "Testing bad input: '" << str
<< "'" << std::endl
;
155 ASSERT_FALSE(cap
.parse(str
, &cout
));
159 TEST(MonCap
, AllowAll
) {
161 ASSERT_FALSE(cap
.is_allow_all());
163 ASSERT_TRUE(cap
.parse("allow r", NULL
));
164 ASSERT_FALSE(cap
.is_allow_all());
167 ASSERT_TRUE(cap
.parse("allow w", NULL
));
168 ASSERT_FALSE(cap
.is_allow_all());
171 ASSERT_TRUE(cap
.parse("allow x", NULL
));
172 ASSERT_FALSE(cap
.is_allow_all());
175 ASSERT_TRUE(cap
.parse("allow rwx", NULL
));
176 ASSERT_FALSE(cap
.is_allow_all());
179 ASSERT_TRUE(cap
.parse("allow rw", NULL
));
180 ASSERT_FALSE(cap
.is_allow_all());
183 ASSERT_TRUE(cap
.parse("allow rx", NULL
));
184 ASSERT_FALSE(cap
.is_allow_all());
187 ASSERT_TRUE(cap
.parse("allow wx", NULL
));
188 ASSERT_FALSE(cap
.is_allow_all());
191 ASSERT_TRUE(cap
.parse("allow *", NULL
));
192 ASSERT_TRUE(cap
.is_allow_all());
193 ASSERT_TRUE(cap
.is_capable(NULL
, {}, "foo", "asdf", {}, true, true, true,
197 ASSERT_FALSE(cap2
.is_allow_all());
198 cap2
.set_allow_all();
199 ASSERT_TRUE(cap2
.is_allow_all());
202 TEST(MonCap
, Network
) {
204 bool r
= cap
.parse("allow * network 192.168.0.0/16, allow * network 10.0.0.0/8", NULL
);
207 entity_addr_t a
, b
, c
;
209 b
.parse("192.168.2.3");
210 c
.parse("192.167.2.3");
212 ASSERT_TRUE(cap
.is_capable(NULL
, {}, "foo", "asdf", {}, true, true, true,
214 ASSERT_TRUE(cap
.is_capable(NULL
, {}, "foo", "asdf", {}, true, true, true,
216 ASSERT_FALSE(cap
.is_capable(NULL
, {}, "foo", "asdf", {}, true, true, true,
220 TEST(MonCap
, ProfileOSD
) {
222 bool r
= cap
.parse("allow profile osd", NULL
);
226 name
.from_str("osd.123");
227 map
<string
,string
> ca
;
229 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "osd", "", ca
, true, false, false,
231 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "osd", "", ca
, true, true, false, {}));
232 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "osd", "", ca
, true, true, true, {}));
233 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "osd", "", ca
, true, true, true, {}));
234 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "mon", "", ca
, true, false, false,
237 ASSERT_FALSE(cap
.is_capable(NULL
, name
, "mds", "", ca
, true, true, true, {}));
238 ASSERT_FALSE(cap
.is_capable(NULL
, name
, "mon", "", ca
, true, true, true, {}));
241 ASSERT_FALSE(cap
.is_capable(NULL
, name
, "", "config-key get", ca
, true, true,
243 ca
["key"] = "daemon-private/osd.123";
244 ASSERT_FALSE(cap
.is_capable(NULL
, name
, "", "config-key get", ca
, true, true,
246 ca
["key"] = "daemon-private/osd.12/asdf";
247 ASSERT_FALSE(cap
.is_capable(NULL
, name
, "", "config-key get", ca
, true, true,
249 ca
["key"] = "daemon-private/osd.123/";
250 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "", "config-key get", ca
, true, true,
252 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "", "config-key get", ca
, true, true,
254 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "", "config-key get", ca
, true, true,
256 ca
["key"] = "daemon-private/osd.123/foo";
257 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "", "config-key get", ca
, true, true,
259 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "", "config-key put", ca
, true, true,
261 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "", "config-key set", ca
, true, true,
263 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "", "config-key exists", ca
, true,
265 ASSERT_TRUE(cap
.is_capable(NULL
, name
, "", "config-key delete", ca
, true,
269 TEST(MonCap
, CommandRegEx
) {
271 ASSERT_FALSE(cap
.is_allow_all());
272 ASSERT_TRUE(cap
.parse("allow command abc with arg regex \"^[0-9a-z.]*$\"",
276 name
.from_str("osd.123");
277 ASSERT_TRUE(cap
.is_capable(nullptr, name
, "", "abc", {{"arg", "12345abcde"}},
278 true, true, true, {}));
279 ASSERT_FALSE(cap
.is_capable(nullptr, name
, "", "abc", {{"arg", "~!@#$"}},
280 true, true, true, {}));
282 ASSERT_TRUE(cap
.parse("allow command abc with arg regex \"[*\"", NULL
));
283 ASSERT_FALSE(cap
.is_capable(nullptr, name
, "", "abc", {{"arg", ""}}, true,
287 TEST(MonCap
, ProfileBootstrapRBD
) {
289 ASSERT_FALSE(cap
.is_allow_all());
290 ASSERT_TRUE(cap
.parse("profile bootstrap-rbd", NULL
));
293 name
.from_str("mon.a");
294 ASSERT_TRUE(cap
.is_capable(nullptr, name
, "",
295 "auth get-or-create", {
296 {"entity", "client.rbd"},
297 {"caps_mon", "profile rbd"},
298 {"caps_osd", "profile rbd pool=foo, profile rbd-read-only"},
301 ASSERT_FALSE(cap
.is_capable(nullptr, name
, "",
302 "auth get-or-create", {
303 {"entity", "client.rbd"},
304 {"caps_mon", "allow *"},
305 {"caps_osd", "profile rbd"},
308 ASSERT_FALSE(cap
.is_capable(nullptr, name
, "",
309 "auth get-or-create", {
310 {"entity", "client.rbd"},
311 {"caps_mon", "profile rbd"},
312 {"caps_osd", "profile rbd pool=foo, allow *, profile rbd-read-only"},
317 TEST(MonCap
, ProfileBootstrapRBDMirror
) {
319 ASSERT_FALSE(cap
.is_allow_all());
320 ASSERT_TRUE(cap
.parse("profile bootstrap-rbd-mirror", NULL
));
323 name
.from_str("mon.a");
324 ASSERT_TRUE(cap
.is_capable(nullptr, name
, "",
325 "auth get-or-create", {
326 {"entity", "client.rbd"},
327 {"caps_mon", "profile rbd-mirror"},
328 {"caps_osd", "profile rbd pool=foo, profile rbd-read-only"},
331 ASSERT_FALSE(cap
.is_capable(nullptr, name
, "",
332 "auth get-or-create", {
333 {"entity", "client.rbd"},
334 {"caps_mon", "profile rbd"},
335 {"caps_osd", "profile rbd pool=foo, profile rbd-read-only"},
338 ASSERT_FALSE(cap
.is_capable(nullptr, name
, "",
339 "auth get-or-create", {
340 {"entity", "client.rbd"},
341 {"caps_mon", "allow *"},
342 {"caps_osd", "profile rbd"},
345 ASSERT_FALSE(cap
.is_capable(nullptr, name
, "",
346 "auth get-or-create", {
347 {"entity", "client.rbd"},
348 {"caps_mon", "profile rbd-mirror"},
349 {"caps_osd", "profile rbd pool=foo, allow *, profile rbd-read-only"},
354 TEST(MonCap
, ProfileRBD
) {
356 ASSERT_FALSE(cap
.is_allow_all());
357 ASSERT_TRUE(cap
.parse("profile rbd", NULL
));
360 name
.from_str("mon.a");
361 ASSERT_FALSE(cap
.is_capable(nullptr, name
, "config-key",
363 {"key", "rbd/mirror/peer/1/1234"},
364 }, true, false, false, {}));
367 TEST(MonCap
, ProfileRBDMirror
) {
369 ASSERT_FALSE(cap
.is_allow_all());
370 ASSERT_TRUE(cap
.parse("profile rbd-mirror", NULL
));
373 name
.from_str("mon.a");
374 ASSERT_TRUE(cap
.is_capable(nullptr, name
, "config-key",
376 {"key", "rbd/mirror/peer/1/1234"},
377 }, true, false, false, {}));