]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | const char *parse_good[] = { | |
23 | ||
24 | // MonCapMatch | |
25 | "allow *", | |
26 | "allow r", | |
27 | "allow rwx", | |
28 | "allow r", | |
29 | " allow rwx", | |
30 | "allow rwx ", | |
31 | " allow rwx ", | |
32 | " allow\t rwx ", | |
33 | "\tallow\nrwx\t", | |
34 | "allow service=foo x", | |
35 | "allow service=\"froo\" x", | |
36 | "allow profile osd", | |
37 | "allow profile osd-bootstrap", | |
38 | "allow profile \"mds-bootstrap\", allow *", | |
39 | "allow command \"a b c\"", | |
40 | "allow command abc", | |
41 | "allow command abc with arg=foo", | |
42 | "allow command abc with arg=foo arg2=bar", | |
43 | "allow command abc with arg=foo arg2=bar", | |
44 | "allow command abc with arg=foo arg2 prefix bar arg3 prefix baz", | |
45 | "allow command abc with arg=foo arg2 prefix \"bar bingo\" arg3 prefix baz", | |
c07f9fc5 FG |
46 | "allow command abc with arg regex \"^[0-9a-z.]*$\"", |
47 | "allow command abc with arg regex \"\(invaluid regex\"", | |
7c673cae FG |
48 | "allow service foo x", |
49 | "allow service foo x; allow service bar x", | |
50 | "allow service foo w ;allow service bar x", | |
51 | "allow service foo w , allow service bar x", | |
52 | "allow service foo r , allow service bar x", | |
53 | "allow service foo_foo r, allow service bar r", | |
54 | "allow service foo-foo r, allow service bar r", | |
55 | "allow service \" foo \" w, allow service bar r", | |
56 | "allow command abc with arg=foo arg2=bar, allow service foo r", | |
57 | "allow command abc.def with arg=foo arg2=bar, allow service foo r", | |
58 | "allow command \"foo bar\" with arg=\"baz\"", | |
59 | "allow command \"foo bar\" with arg=\"baz.xx\"", | |
c07f9fc5 FG |
60 | "profile osd", |
61 | "profile \"mds-bootstrap\", profile foo", | |
7c673cae FG |
62 | 0 |
63 | }; | |
64 | ||
65 | TEST(MonCap, ParseGood) { | |
66 | for (int i=0; parse_good[i]; ++i) { | |
67 | string str = parse_good[i]; | |
68 | MonCap cap; | |
69 | std::cout << "Testing good input: '" << str << "'" << std::endl; | |
70 | ASSERT_TRUE(cap.parse(str, &cout)); | |
71 | std::cout << " -> " << cap << std::endl; | |
72 | } | |
73 | } | |
74 | ||
75 | // these should stringify to the input value | |
76 | const char *parse_identity[] = { | |
77 | "allow *", | |
78 | "allow r", | |
79 | "allow rwx", | |
80 | "allow service foo x", | |
81 | "allow profile osd", | |
82 | "allow profile osd-bootstrap", | |
83 | "allow profile mds-bootstrap, allow *", | |
84 | "allow profile \"foo bar\", allow *", | |
85 | "allow command abc", | |
86 | "allow command \"a b c\"", | |
87 | "allow command abc with arg=foo", | |
88 | "allow command abc with arg=foo arg2=bar", | |
89 | "allow command abc with arg=foo arg2=bar", | |
90 | "allow command abc with arg=foo arg2 prefix bar arg3 prefix baz", | |
91 | "allow command abc with arg=foo arg2 prefix \"bar bingo\" arg3 prefix baz", | |
92 | "allow service foo x", | |
93 | "allow service foo x, allow service bar x", | |
94 | "allow service foo w, allow service bar x", | |
95 | "allow service foo r, allow service bar x", | |
96 | "allow service foo_foo r, allow service bar r", | |
97 | "allow service foo-foo r, allow service bar r", | |
98 | "allow service \" foo \" w, allow service bar r", | |
99 | "allow command abc with arg=foo arg2=bar, allow service foo r", | |
100 | 0 | |
101 | }; | |
102 | ||
103 | TEST(MonCap, ParseIdentity) | |
104 | { | |
105 | for (int i=0; parse_identity[i]; ++i) { | |
106 | string str = parse_identity[i]; | |
107 | MonCap cap; | |
108 | std::cout << "Testing good input: '" << str << "'" << std::endl; | |
109 | ASSERT_TRUE(cap.parse(str, &cout)); | |
110 | string out = stringify(cap); | |
111 | ASSERT_EQ(out, str); | |
112 | } | |
113 | } | |
114 | ||
115 | const char *parse_bad[] = { | |
116 | "allow r foo", | |
117 | "allow*", | |
118 | "foo allow *", | |
119 | "allow profile foo rwx", | |
120 | "allow profile", | |
121 | "allow profile foo bar rwx", | |
122 | "allow service bar", | |
123 | "allow command baz x", | |
124 | "allow r w", | |
125 | "ALLOW r", | |
126 | "allow rwx,", | |
127 | "allow rwx x", | |
128 | "allow r pool foo r", | |
129 | "allow wwx pool taco", | |
130 | "allow wwx pool taco^funny&chars", | |
131 | "allow rwx pool 'weird name''", | |
132 | "allow rwx object_prefix \"beforepool\" pool weird", | |
133 | "allow rwx auid 123 pool asdf", | |
134 | "allow command foo a prefix b", | |
135 | "allow command foo with a prefixb", | |
136 | "allow command foo with a = prefix b", | |
137 | "allow command foo with a prefix b c", | |
138 | 0 | |
139 | }; | |
140 | ||
141 | TEST(MonCap, ParseBad) { | |
142 | for (int i=0; parse_bad[i]; ++i) { | |
143 | string str = parse_bad[i]; | |
144 | MonCap cap; | |
145 | std::cout << "Testing bad input: '" << str << "'" << std::endl; | |
146 | ASSERT_FALSE(cap.parse(str, &cout)); | |
147 | } | |
148 | } | |
149 | ||
150 | TEST(MonCap, AllowAll) { | |
151 | MonCap cap; | |
152 | ASSERT_FALSE(cap.is_allow_all()); | |
153 | ||
154 | ASSERT_TRUE(cap.parse("allow r", NULL)); | |
155 | ASSERT_FALSE(cap.is_allow_all()); | |
156 | cap.grants.clear(); | |
157 | ||
158 | ASSERT_TRUE(cap.parse("allow w", NULL)); | |
159 | ASSERT_FALSE(cap.is_allow_all()); | |
160 | cap.grants.clear(); | |
161 | ||
162 | ASSERT_TRUE(cap.parse("allow x", NULL)); | |
163 | ASSERT_FALSE(cap.is_allow_all()); | |
164 | cap.grants.clear(); | |
165 | ||
166 | ASSERT_TRUE(cap.parse("allow rwx", NULL)); | |
167 | ASSERT_FALSE(cap.is_allow_all()); | |
168 | cap.grants.clear(); | |
169 | ||
170 | ASSERT_TRUE(cap.parse("allow rw", NULL)); | |
171 | ASSERT_FALSE(cap.is_allow_all()); | |
172 | cap.grants.clear(); | |
173 | ||
174 | ASSERT_TRUE(cap.parse("allow rx", NULL)); | |
175 | ASSERT_FALSE(cap.is_allow_all()); | |
176 | cap.grants.clear(); | |
177 | ||
178 | ASSERT_TRUE(cap.parse("allow wx", NULL)); | |
179 | ASSERT_FALSE(cap.is_allow_all()); | |
180 | cap.grants.clear(); | |
181 | ||
182 | ASSERT_TRUE(cap.parse("allow *", NULL)); | |
183 | ASSERT_TRUE(cap.is_allow_all()); | |
184 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, EntityName(), | |
185 | "foo", "asdf", map<string,string>(), true, true, true)); | |
186 | ||
187 | MonCap cap2; | |
188 | ASSERT_FALSE(cap2.is_allow_all()); | |
189 | cap2.set_allow_all(); | |
190 | ASSERT_TRUE(cap2.is_allow_all()); | |
191 | } | |
192 | ||
193 | TEST(MonCap, ProfileOSD) { | |
194 | MonCap cap; | |
195 | bool r = cap.parse("allow profile osd", NULL); | |
196 | ASSERT_TRUE(r); | |
197 | ||
198 | EntityName name; | |
199 | name.from_str("osd.123"); | |
200 | map<string,string> ca; | |
201 | ||
202 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
203 | name, "osd", "", ca, true, false, false)); | |
204 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
205 | name, "osd", "", ca, true, true, false)); | |
206 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
207 | name, "osd", "", ca, true, true, true)); | |
208 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
209 | name, "osd", "", ca, true, true, true)); | |
210 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
211 | name, "mon", "", ca, true, false,false)); | |
212 | ||
213 | ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
214 | name, "mds", "", ca, true, true, true)); | |
215 | ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
216 | name, "mon", "", ca, true, true, true)); | |
217 | ||
218 | ca.clear(); | |
219 | ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
220 | name, "", "config-key get", ca, true, true, true)); | |
221 | ca["key"] = "daemon-private/osd.123"; | |
222 | ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
223 | name, "", "config-key get", ca, true, true, true)); | |
224 | ca["key"] = "daemon-private/osd.12/asdf"; | |
225 | ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
226 | name, "", "config-key get", ca, true, true, true)); | |
227 | ca["key"] = "daemon-private/osd.123/"; | |
228 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
229 | name, "", "config-key get", ca, true, true, true)); | |
230 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
231 | name, "", "config-key get", ca, true, true, true)); | |
232 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
233 | name, "", "config-key get", ca, true, true, true)); | |
234 | ca["key"] = "daemon-private/osd.123/foo"; | |
235 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
236 | name, "", "config-key get", ca, true, true, true)); | |
237 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
238 | name, "", "config-key put", ca, true, true, true)); | |
c07f9fc5 FG |
239 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, |
240 | name, "", "config-key set", ca, true, true, true)); | |
7c673cae FG |
241 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, |
242 | name, "", "config-key exists", ca, true, true, true)); | |
243 | ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, | |
244 | name, "", "config-key delete", ca, true, true, true)); | |
245 | } | |
246 | ||
c07f9fc5 FG |
247 | TEST(MonCap, CommandRegEx) { |
248 | MonCap cap; | |
249 | ASSERT_FALSE(cap.is_allow_all()); | |
250 | ASSERT_TRUE(cap.parse("allow command abc with arg regex \"^[0-9a-z.]*$\"", NULL)); | |
251 | ||
252 | EntityName name; | |
253 | name.from_str("osd.123"); | |
254 | ASSERT_TRUE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_OSD, name, "", | |
255 | "abc", {{"arg", "12345abcde"}}, true, true, true)); | |
256 | ASSERT_FALSE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_OSD, name, "", | |
257 | "abc", {{"arg", "~!@#$"}}, true, true, true)); | |
258 | ||
259 | ASSERT_TRUE(cap.parse("allow command abc with arg regex \"[*\"", NULL)); | |
260 | ASSERT_FALSE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_OSD, name, "", | |
261 | "abc", {{"arg", ""}}, true, true, true)); | |
262 | } | |
d2e6a577 FG |
263 | |
264 | TEST(MonCap, ProfileBootstrapRBD) { | |
265 | MonCap cap; | |
266 | ASSERT_FALSE(cap.is_allow_all()); | |
267 | ASSERT_TRUE(cap.parse("profile bootstrap-rbd", NULL)); | |
268 | ||
269 | EntityName name; | |
270 | name.from_str("mon.a"); | |
271 | ASSERT_TRUE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_MON, name, "", | |
272 | "auth get-or-create", { | |
273 | {"entity", "client.rbd"}, | |
274 | {"caps_mon", "profile rbd"}, | |
275 | {"caps_osd", "profile rbd pool=foo, profile rbd-read-only"}, | |
276 | }, true, true, true)); | |
277 | ASSERT_FALSE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_MON, name, "", | |
278 | "auth get-or-create", { | |
279 | {"entity", "client.rbd"}, | |
280 | {"caps_mon", "allow *"}, | |
281 | {"caps_osd", "profile rbd"}, | |
282 | }, true, true, true)); | |
283 | ASSERT_FALSE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_MON, name, "", | |
284 | "auth get-or-create", { | |
285 | {"entity", "client.rbd"}, | |
286 | {"caps_mon", "profile rbd"}, | |
287 | {"caps_osd", "profile rbd pool=foo, allow *, profile rbd-read-only"}, | |
288 | }, true, true, true)); | |
289 | } |