]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/mon/moncap.cc
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / test / mon / moncap.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2012 Inktank
7 *
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.
12 *
13 */
14
15 #include <iostream>
16
17 #include "include/stringify.h"
18 #include "mon/MonCap.h"
19
20 #include "gtest/gtest.h"
21
22 using namespace std;
23
24 const char *parse_good[] = {
25
26 // MonCapMatch
27 "allow *",
28 "allow r",
29 "allow rwx",
30 "allow r",
31 " allow rwx",
32 "allow rwx ",
33 " allow rwx ",
34 " allow\t rwx ",
35 "\tallow\nrwx\t",
36 "allow service=foo x",
37 "allow service=\"froo\" x",
38 "allow profile osd",
39 "allow profile osd-bootstrap",
40 "allow profile \"mds-bootstrap\", allow *",
41 "allow command \"a b c\"",
42 "allow command abc",
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\"",
62 "profile osd",
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",
71 0
72 };
73
74 TEST(MonCap, ParseGood) {
75 for (int i=0; parse_good[i]; ++i) {
76 string str = parse_good[i];
77 MonCap cap;
78 std::cout << "Testing good input: '" << str << "'" << std::endl;
79 ASSERT_TRUE(cap.parse(str, &cout));
80 std::cout << " -> " << cap << std::endl;
81 }
82 }
83
84 // these should stringify to the input value
85 const char *parse_identity[] = {
86 "allow *",
87 "allow r",
88 "allow rwx",
89 "allow service foo x",
90 "allow profile osd",
91 "allow profile osd-bootstrap",
92 "allow profile mds-bootstrap, allow *",
93 "allow profile \"foo bar\", allow *",
94 "allow command abc",
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",
109 0
110 };
111
112 TEST(MonCap, ParseIdentity)
113 {
114 for (int i=0; parse_identity[i]; ++i) {
115 string str = parse_identity[i];
116 MonCap cap;
117 std::cout << "Testing good input: '" << str << "'" << std::endl;
118 ASSERT_TRUE(cap.parse(str, &cout));
119 string out = stringify(cap);
120 ASSERT_EQ(out, str);
121 }
122 }
123
124 const char *parse_bad[] = {
125 "allow r foo",
126 "allow*",
127 "foo allow *",
128 "allow profile foo rwx",
129 "allow profile",
130 "allow profile foo bar rwx",
131 "allow service bar",
132 "allow command baz x",
133 "allow r w",
134 "ALLOW r",
135 "allow rwx,",
136 "allow rwx 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",
147 0
148 };
149
150 TEST(MonCap, ParseBad) {
151 for (int i=0; parse_bad[i]; ++i) {
152 string str = parse_bad[i];
153 MonCap cap;
154 std::cout << "Testing bad input: '" << str << "'" << std::endl;
155 ASSERT_FALSE(cap.parse(str, &cout));
156 }
157 }
158
159 TEST(MonCap, AllowAll) {
160 MonCap cap;
161 ASSERT_FALSE(cap.is_allow_all());
162
163 ASSERT_TRUE(cap.parse("allow r", NULL));
164 ASSERT_FALSE(cap.is_allow_all());
165 cap.grants.clear();
166
167 ASSERT_TRUE(cap.parse("allow w", NULL));
168 ASSERT_FALSE(cap.is_allow_all());
169 cap.grants.clear();
170
171 ASSERT_TRUE(cap.parse("allow x", NULL));
172 ASSERT_FALSE(cap.is_allow_all());
173 cap.grants.clear();
174
175 ASSERT_TRUE(cap.parse("allow rwx", NULL));
176 ASSERT_FALSE(cap.is_allow_all());
177 cap.grants.clear();
178
179 ASSERT_TRUE(cap.parse("allow rw", NULL));
180 ASSERT_FALSE(cap.is_allow_all());
181 cap.grants.clear();
182
183 ASSERT_TRUE(cap.parse("allow rx", NULL));
184 ASSERT_FALSE(cap.is_allow_all());
185 cap.grants.clear();
186
187 ASSERT_TRUE(cap.parse("allow wx", NULL));
188 ASSERT_FALSE(cap.is_allow_all());
189 cap.grants.clear();
190
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,
194 {}));
195
196 MonCap cap2;
197 ASSERT_FALSE(cap2.is_allow_all());
198 cap2.set_allow_all();
199 ASSERT_TRUE(cap2.is_allow_all());
200 }
201
202 TEST(MonCap, Network) {
203 MonCap cap;
204 bool r = cap.parse("allow * network 192.168.0.0/16, allow * network 10.0.0.0/8", NULL);
205 ASSERT_TRUE(r);
206
207 entity_addr_t a, b, c;
208 a.parse("10.1.2.3");
209 b.parse("192.168.2.3");
210 c.parse("192.167.2.3");
211
212 ASSERT_TRUE(cap.is_capable(NULL, {}, "foo", "asdf", {}, true, true, true,
213 a));
214 ASSERT_TRUE(cap.is_capable(NULL, {}, "foo", "asdf", {}, true, true, true,
215 b));
216 ASSERT_FALSE(cap.is_capable(NULL, {}, "foo", "asdf", {}, true, true, true,
217 c));
218 }
219
220 TEST(MonCap, ProfileOSD) {
221 MonCap cap;
222 bool r = cap.parse("allow profile osd", NULL);
223 ASSERT_TRUE(r);
224
225 EntityName name;
226 name.from_str("osd.123");
227 map<string,string> ca;
228
229 ASSERT_TRUE(cap.is_capable(NULL, name, "osd", "", ca, true, false, false,
230 {}));
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,
235 {}));
236
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, {}));
239
240 ca.clear();
241 ASSERT_FALSE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true,
242 true, {}));
243 ca["key"] = "daemon-private/osd.123";
244 ASSERT_FALSE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true,
245 true, {}));
246 ca["key"] = "daemon-private/osd.12/asdf";
247 ASSERT_FALSE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true,
248 true, {}));
249 ca["key"] = "daemon-private/osd.123/";
250 ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true,
251 true, {}));
252 ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true,
253 true, {}));
254 ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true,
255 true, {}));
256 ca["key"] = "daemon-private/osd.123/foo";
257 ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true,
258 true, {}));
259 ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key put", ca, true, true,
260 true, {}));
261 ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key set", ca, true, true,
262 true, {}));
263 ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key exists", ca, true,
264 true, true, {}));
265 ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key delete", ca, true,
266 true, true, {}));
267 }
268
269 TEST(MonCap, CommandRegEx) {
270 MonCap cap;
271 ASSERT_FALSE(cap.is_allow_all());
272 ASSERT_TRUE(cap.parse("allow command abc with arg regex \"^[0-9a-z.]*$\"",
273 NULL));
274
275 EntityName name;
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, {}));
281
282 ASSERT_TRUE(cap.parse("allow command abc with arg regex \"[*\"", NULL));
283 ASSERT_FALSE(cap.is_capable(nullptr, name, "", "abc", {{"arg", ""}}, true,
284 true, true, {}));
285 }
286
287 TEST(MonCap, ProfileBootstrapRBD) {
288 MonCap cap;
289 ASSERT_FALSE(cap.is_allow_all());
290 ASSERT_TRUE(cap.parse("profile bootstrap-rbd", NULL));
291
292 EntityName name;
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"},
299 }, true, true, true,
300 {}));
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"},
306 }, true, true, true,
307 {}));
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"},
313 }, true, true, true,
314 {}));
315 }
316
317 TEST(MonCap, ProfileBootstrapRBDMirror) {
318 MonCap cap;
319 ASSERT_FALSE(cap.is_allow_all());
320 ASSERT_TRUE(cap.parse("profile bootstrap-rbd-mirror", NULL));
321
322 EntityName name;
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"},
329 }, true, true, true,
330 {}));
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"},
336 }, true, true, true,
337 {}));
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"},
343 }, true, true, true,
344 {}));
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"},
350 }, true, true, true,
351 {}));
352 }
353
354 TEST(MonCap, ProfileRBD) {
355 MonCap cap;
356 ASSERT_FALSE(cap.is_allow_all());
357 ASSERT_TRUE(cap.parse("profile rbd", NULL));
358
359 EntityName name;
360 name.from_str("mon.a");
361 ASSERT_FALSE(cap.is_capable(nullptr, name, "config-key",
362 "config-key get", {
363 {"key", "rbd/mirror/peer/1/1234"},
364 }, true, false, false, {}));
365 }
366
367 TEST(MonCap, ProfileRBDMirror) {
368 MonCap cap;
369 ASSERT_FALSE(cap.is_allow_all());
370 ASSERT_TRUE(cap.parse("profile rbd-mirror", NULL));
371
372 EntityName name;
373 name.from_str("mon.a");
374 ASSERT_TRUE(cap.is_capable(nullptr, name, "config-key",
375 "config-key get", {
376 {"key", "rbd/mirror/peer/1/1234"},
377 }, true, false, false, {}));
378 }