]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/mgr/test_mgrcap.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / mgr / test_mgrcap.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 "mgr/MgrCap.h"
19
20 #include "gtest/gtest.h"
21
22 using namespace std;
23
24 const char *parse_good[] = {
25
26 // MgrCapMatch
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 read-only",
39 "allow profile read-write",
40 "allow profile \"rbd-read-only\", 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 module foo x",
59 "allow module=foo x",
60 "allow module foo_foo r",
61 "allow module \" foo \" w",
62 "allow module foo with arg1=value1 x",
63 "allow command abc with arg=foo arg2=bar, allow service foo r",
64 "allow command abc.def with arg=foo arg2=bar, allow service foo r",
65 "allow command \"foo bar\" with arg=\"baz\"",
66 "allow command \"foo bar\" with arg=\"baz.xx\"",
67 "allow command \"foo bar\" with arg = \"baz.xx\"",
68 "profile crash",
69 "profile osd",
70 "profile mds",
71 "profile rbd pool=ABC namespace=NS",
72 "profile \"rbd-read-only\", profile crash",
73 "allow * network 1.2.3.4/24",
74 "allow * network ::1/128",
75 "allow * network [aa:bb::1]/128",
76 "allow service=foo x network 1.2.3.4/16",
77 "allow command abc network 1.2.3.4/8",
78 "profile crash network 1.2.3.4/32",
79 "allow profile crash network 1.2.3.4/32",
80 0
81 };
82
83 TEST(MgrCap, ParseGood) {
84 for (int i=0; parse_good[i]; ++i) {
85 string str = parse_good[i];
86 MgrCap cap;
87 std::cout << "Testing good input: '" << str << "'" << std::endl;
88 ASSERT_TRUE(cap.parse(str, &cout));
89 std::cout << " -> " << cap
90 << std::endl;
91 }
92 }
93
94 // these should stringify to the input value
95 const char *parse_identity[] = {
96 "allow *",
97 "allow r",
98 "allow rwx",
99 "allow service foo x",
100 "profile crash",
101 "profile rbd-read-only, allow *",
102 "profile rbd namespace=NS pool=ABC",
103 "allow command abc",
104 "allow command \"a b c\"",
105 "allow command abc with arg=foo",
106 "allow command abc with arg=foo arg2=bar",
107 "allow command abc with arg=foo arg2=bar",
108 "allow command abc with arg=foo arg2 prefix bar arg3 prefix baz",
109 "allow command abc with arg=foo arg2 prefix \"bar bingo\" arg3 prefix baz",
110 "allow service foo x",
111 "allow service foo x, allow service bar x",
112 "allow service foo w, allow service bar x",
113 "allow service foo r, allow service bar x",
114 "allow service foo_foo r, allow service bar r",
115 "allow service foo-foo r, allow service bar r",
116 "allow service \" foo \" w, allow service bar r",
117 "allow module foo x",
118 "allow module \" foo_foo \" r",
119 "allow module foo with arg1=value1 x",
120 "allow command abc with arg=foo arg2=bar, allow service foo r",
121 0
122 };
123
124 TEST(MgrCap, ParseIdentity)
125 {
126 for (int i=0; parse_identity[i]; ++i) {
127 string str = parse_identity[i];
128 MgrCap cap;
129 std::cout << "Testing good input: '" << str << "'" << std::endl;
130 ASSERT_TRUE(cap.parse(str, &cout));
131 string out = stringify(cap);
132 ASSERT_EQ(out, str);
133 }
134 }
135
136 const char *parse_bad[] = {
137 "allow r foo",
138 "allow*",
139 "foo allow *",
140 "profile foo rwx",
141 "profile",
142 "profile foo bar rwx",
143 "allow profile foo rwx",
144 "allow profile",
145 "allow profile foo bar rwx",
146 "allow service bar",
147 "allow command baz x",
148 "allow r w",
149 "ALLOW r",
150 "allow rwx,",
151 "allow rwx x",
152 "allow r pool foo r",
153 "allow wwx pool taco",
154 "allow wwx pool taco^funny&chars",
155 "allow rwx pool 'weird name''",
156 "allow rwx object_prefix \"beforepool\" pool weird",
157 "allow rwx auid 123 pool asdf",
158 "allow command foo a prefix b",
159 "allow command foo with a prefixb",
160 "allow command foo with a = prefix b",
161 "allow command foo with a prefix b c",
162 0
163 };
164
165 TEST(MgrCap, ParseBad) {
166 for (int i=0; parse_bad[i]; ++i) {
167 string str = parse_bad[i];
168 MgrCap cap;
169 std::cout << "Testing bad input: '" << str << "'" << std::endl;
170 ASSERT_FALSE(cap.parse(str, &cout));
171 }
172 }
173
174 TEST(MgrCap, AllowAll) {
175 MgrCap cap;
176 ASSERT_FALSE(cap.is_allow_all());
177
178 ASSERT_TRUE(cap.parse("allow r", nullptr));
179 ASSERT_FALSE(cap.is_allow_all());
180 cap.grants.clear();
181
182 ASSERT_TRUE(cap.parse("allow w", nullptr));
183 ASSERT_FALSE(cap.is_allow_all());
184 cap.grants.clear();
185
186 ASSERT_TRUE(cap.parse("allow x", nullptr));
187 ASSERT_FALSE(cap.is_allow_all());
188 cap.grants.clear();
189
190 ASSERT_TRUE(cap.parse("allow rwx", nullptr));
191 ASSERT_FALSE(cap.is_allow_all());
192 cap.grants.clear();
193
194 ASSERT_TRUE(cap.parse("allow rw", nullptr));
195 ASSERT_FALSE(cap.is_allow_all());
196 cap.grants.clear();
197
198 ASSERT_TRUE(cap.parse("allow rx", nullptr));
199 ASSERT_FALSE(cap.is_allow_all());
200 cap.grants.clear();
201
202 ASSERT_TRUE(cap.parse("allow wx", nullptr));
203 ASSERT_FALSE(cap.is_allow_all());
204 cap.grants.clear();
205
206 ASSERT_TRUE(cap.parse("allow *", nullptr));
207 ASSERT_TRUE(cap.is_allow_all());
208 ASSERT_TRUE(cap.is_capable(nullptr, {}, "foo", "", "asdf", {}, true, true,
209 true, {}));
210
211 MgrCap cap2;
212 ASSERT_FALSE(cap2.is_allow_all());
213 cap2.set_allow_all();
214 ASSERT_TRUE(cap2.is_allow_all());
215 }
216
217 TEST(MgrCap, Network) {
218 MgrCap cap;
219 bool r = cap.parse("allow * network 192.168.0.0/16, allow * network 10.0.0.0/8", nullptr);
220 ASSERT_TRUE(r);
221
222 entity_addr_t a, b, c;
223 a.parse("10.1.2.3");
224 b.parse("192.168.2.3");
225 c.parse("192.167.2.3");
226
227 ASSERT_TRUE(cap.is_capable(nullptr, {}, "foo", "", "asdf", {}, true, true,
228 true, a));
229 ASSERT_TRUE(cap.is_capable(nullptr, {}, "foo", "", "asdf", {}, true, true,
230 true, b));
231 ASSERT_FALSE(cap.is_capable(nullptr, {}, "foo", "", "asdf", {}, true, true,
232 true, c));
233 }
234
235 TEST(MgrCap, CommandRegEx) {
236 MgrCap cap;
237 ASSERT_FALSE(cap.is_allow_all());
238 ASSERT_TRUE(cap.parse("allow command abc with arg regex \"^[0-9a-z.]*$\"",
239 nullptr));
240
241 EntityName name;
242 name.from_str("osd.123");
243 ASSERT_TRUE(cap.is_capable(nullptr, name, "", "", "abc",
244 {{"arg", "12345abcde"}}, true, true, true, {}));
245 ASSERT_FALSE(cap.is_capable(nullptr, name, "", "", "abc", {{"arg", "~!@#$"}},
246 true, true, true, {}));
247
248 ASSERT_TRUE(cap.parse("allow command abc with arg regex \"[*\"", nullptr));
249 ASSERT_FALSE(cap.is_capable(nullptr, name, "", "", "abc", {{"arg", ""}}, true,
250 true, true, {}));
251 }
252
253 TEST(MgrCap, Module) {
254 MgrCap cap;
255 ASSERT_FALSE(cap.is_allow_all());
256 ASSERT_TRUE(cap.parse("allow module abc r, allow module bcd w", nullptr));
257
258 ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, true, false,
259 {}));
260 ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, false, false,
261 {}));
262 ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "bcd", "", {}, true, true, false,
263 {}));
264 ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "bcd", "", {}, false, true, false,
265 {}));
266 }
267
268 TEST(MgrCap, Profile) {
269 MgrCap cap;
270 ASSERT_FALSE(cap.is_allow_all());
271
272 ASSERT_FALSE(cap.parse("profile unknown"));
273 ASSERT_FALSE(cap.parse("profile rbd invalid-key=value"));
274
275 ASSERT_TRUE(cap.parse("profile rbd", nullptr));
276 ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, false,
277 false, {}));
278 ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true,
279 true, false, {}));
280 ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true,
281 false, false, {}));
282
283 ASSERT_TRUE(cap.parse("profile rbd pool=abc namespace prefix def", nullptr));
284 ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {},
285 true, true, false, {}));
286 ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "rbd_support", "",
287 {{"pool", "abc"}},
288 true, true, false, {}));
289 ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "",
290 {{"pool", "abc"}, {"namespace", "defghi"}},
291 true, true, false, {}));
292
293 ASSERT_TRUE(cap.parse("profile rbd-read-only", nullptr));
294 ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, false,
295 false, {}));
296 ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true,
297 true, false, {}));
298 ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true,
299 false, false, {}));
300 }