]>
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 "mds/MDSAuthCaps.h" | |
19 | ||
20 | #include "gtest/gtest.h" | |
21 | ||
22 | using std::string; | |
23 | using std::cout; | |
24 | ||
25 | const char *parse_good[] = { | |
26 | "allow rw uid=1 gids=1", | |
27 | "allow * path=\"/foo\"", | |
28 | "allow * path=/foo", | |
29 | "allow * path=/foo-bar_baz", | |
30 | "allow * path=\"/foo bar/baz\"", | |
31 | "allow * uid=1", | |
32 | "allow * path=\"/foo\" uid=1", | |
33 | "allow *", | |
34 | "allow r", | |
35 | "allow rw", | |
36 | "allow rw uid=1 gids=1,2,3", | |
37 | "allow rw path=/foo uid=1 gids=1,2,3", | |
38 | "allow r, allow rw path=/foo", | |
39 | "allow r, allow * uid=1", | |
40 | "allow r ,allow * uid=1", | |
41 | "allow r ;allow * uid=1", | |
42 | "allow r ; allow * uid=1", | |
43 | "allow r ; allow * uid=1", | |
44 | "allow r uid=1 gids=1,2,3, allow * uid=2", | |
45 | 0 | |
46 | }; | |
47 | ||
48 | TEST(MDSAuthCaps, ParseGood) { | |
49 | for (int i=0; parse_good[i]; i++) { | |
50 | string str = parse_good[i]; | |
51 | MDSAuthCaps cap; | |
52 | std::cout << "Testing good input: '" << str << "'" << std::endl; | |
53 | ASSERT_TRUE(cap.parse(g_ceph_context, str, &cout)); | |
54 | } | |
55 | } | |
56 | ||
57 | const char *parse_bad[] = { | |
58 | "allow r poolfoo", | |
59 | "allow r w", | |
60 | "ALLOW r", | |
61 | "allow w", | |
62 | "allow rwx,", | |
63 | "allow rwx x", | |
64 | "allow r pool foo r", | |
65 | "allow wwx pool taco", | |
66 | "allow wwx pool taco^funny&chars", | |
67 | "allow rwx pool 'weird name''", | |
68 | "allow rwx object_prefix \"beforepool\" pool weird", | |
69 | "allow rwx auid 123 pool asdf", | |
70 | "allow xrwx pool foo,, allow r pool bar", | |
71 | ";allow rwx pool foo rwx ; allow r pool bar", | |
72 | "allow rwx pool foo ;allow r pool bar gibberish", | |
73 | "allow rwx auid 123 pool asdf namespace=foo", | |
74 | "allow rwx auid 123 namespace", | |
75 | "allow rwx namespace", | |
76 | "allow namespace", | |
77 | "allow namespace=foo", | |
78 | "allow rwx auid 123 namespace asdf", | |
79 | "allow wwx pool ''", | |
80 | "allow rw gids=1", | |
81 | "allow rw gids=1,2,3", | |
82 | "allow rw uid=123 gids=asdf", | |
83 | "allow rw uid=123 gids=1,2,asdf", | |
84 | 0 | |
85 | }; | |
86 | ||
87 | TEST(MDSAuthCaps, ParseBad) { | |
88 | for (int i=0; parse_bad[i]; i++) { | |
89 | string str = parse_bad[i]; | |
90 | MDSAuthCaps cap; | |
91 | std::cout << "Testing bad input: '" << str << "'" << std::endl; | |
92 | ASSERT_FALSE(cap.parse(g_ceph_context, str, &cout)); | |
93 | } | |
94 | } | |
95 | ||
96 | TEST(MDSAuthCaps, AllowAll) { | |
97 | MDSAuthCaps cap; | |
98 | ASSERT_FALSE(cap.allow_all()); | |
99 | ||
100 | ASSERT_TRUE(cap.parse(g_ceph_context, "allow r", NULL)); | |
101 | ASSERT_FALSE(cap.allow_all()); | |
102 | cap = MDSAuthCaps(); | |
103 | ||
104 | ASSERT_TRUE(cap.parse(g_ceph_context, "allow rw", NULL)); | |
105 | ASSERT_FALSE(cap.allow_all()); | |
106 | cap = MDSAuthCaps(); | |
107 | ||
108 | ASSERT_TRUE(cap.parse(g_ceph_context, "allow", NULL)); | |
109 | ASSERT_FALSE(cap.allow_all()); | |
110 | cap = MDSAuthCaps(); | |
111 | ||
112 | ASSERT_TRUE(cap.parse(g_ceph_context, "allow *", NULL)); | |
113 | ASSERT_TRUE(cap.allow_all()); | |
114 | ASSERT_TRUE(cap.is_capable("foo/bar", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
115 | } | |
116 | ||
117 | TEST(MDSAuthCaps, AllowUid) { | |
118 | MDSAuthCaps cap(g_ceph_context); | |
b32b8144 FG |
119 | ASSERT_TRUE(cap.parse(g_ceph_context, "allow * uid=10", NULL)); |
120 | ASSERT_FALSE(cap.allow_all()); | |
121 | ||
122 | // uid/gid must be valid | |
123 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ, 0, 0)); | |
124 | ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 10, 0, NULL, MAY_READ, 0, 0)); | |
125 | ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 10, 10, NULL, MAY_READ, 0, 0)); | |
126 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 12, 12, NULL, MAY_READ, 0, 0)); | |
127 | ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 10, 13, NULL, MAY_READ, 0, 0)); | |
128 | } | |
129 | ||
130 | TEST(MDSAuthCaps, AllowUidGid) { | |
131 | MDSAuthCaps cap(g_ceph_context); | |
7c673cae FG |
132 | ASSERT_TRUE(cap.parse(g_ceph_context, "allow * uid=10 gids=10,11,12; allow * uid=12 gids=12,10", NULL)); |
133 | ASSERT_FALSE(cap.allow_all()); | |
134 | ||
135 | // uid/gid must be valid | |
136 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ, 0, 0)); | |
137 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 10, 0, NULL, MAY_READ, 0, 0)); | |
138 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 9, 10, NULL, MAY_READ, 0, 0)); | |
139 | ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 10, 10, NULL, MAY_READ, 0, 0)); | |
140 | ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 12, 12, NULL, MAY_READ, 0, 0)); | |
141 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 10, 13, NULL, MAY_READ, 0, 0)); | |
142 | ||
143 | // user | |
144 | ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0500, 10, 11, NULL, MAY_READ, 0, 0)); | |
145 | ASSERT_FALSE(cap.is_capable("foo", 10, 10, 0500, 10, 11, NULL, MAY_WRITE, 0, 0)); | |
146 | ASSERT_FALSE(cap.is_capable("foo", 10, 10, 0500, 10, 11, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
147 | ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0700, 10, 11, NULL, MAY_READ, 0, 0)); | |
148 | ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0700, 10, 11, NULL, MAY_WRITE, 0, 0)); | |
149 | ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0700, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
150 | ASSERT_TRUE(cap.is_capable("foo", 10, 0, 0700, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
151 | ASSERT_FALSE(cap.is_capable("foo", 12, 0, 0700, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
152 | ASSERT_TRUE(cap.is_capable("foo", 12, 0, 0700, 12, 12, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
153 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0700, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
154 | ||
155 | // group | |
156 | vector<uint64_t> glist10; | |
157 | glist10.push_back(10); | |
158 | vector<uint64_t> dglist10; | |
159 | dglist10.push_back(8); | |
160 | dglist10.push_back(10); | |
161 | vector<uint64_t> glist11; | |
162 | glist11.push_back(11); | |
163 | vector<uint64_t> glist12; | |
164 | glist12.push_back(12); | |
165 | ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0750, 10, 10, NULL, MAY_READ, 0, 0)); | |
166 | ASSERT_FALSE(cap.is_capable("foo", 0, 10, 0750, 10, 10, NULL, MAY_WRITE, 0, 0)); | |
167 | ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0770, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
168 | ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0770, 10, 11, &glist10, MAY_READ | MAY_WRITE, 0, 0)); | |
169 | ASSERT_TRUE(cap.is_capable("foo", 0, 11, 0770, 10, 10, &glist11, MAY_READ | MAY_WRITE, 0, 0)); | |
170 | ASSERT_TRUE(cap.is_capable("foo", 0, 11, 0770, 10, 11, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
171 | ASSERT_TRUE(cap.is_capable("foo", 0, 12, 0770, 12, 12, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
172 | ASSERT_FALSE(cap.is_capable("foo", 0, 10, 0770, 12, 12, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
173 | ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0770, 12, 12, &glist10, MAY_READ | MAY_WRITE, 0, 0)); | |
174 | ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0770, 12, 12, &dglist10, MAY_READ | MAY_WRITE, 0, 0)); | |
175 | ASSERT_FALSE(cap.is_capable("foo", 0, 11, 0770, 12, 12, &glist11, MAY_READ | MAY_WRITE, 0, 0)); | |
176 | ASSERT_FALSE(cap.is_capable("foo", 0, 12, 0770, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
177 | ASSERT_TRUE(cap.is_capable("foo", 0, 12, 0770, 10, 10, &glist12, MAY_READ | MAY_WRITE, 0, 0)); | |
178 | ||
179 | // user > group | |
180 | ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0570, 10, 10, NULL, MAY_READ, 0, 0)); | |
181 | ASSERT_FALSE(cap.is_capable("foo", 10, 10, 0570, 10, 10, NULL, MAY_WRITE, 0, 0)); | |
182 | ||
183 | // other | |
184 | ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0775, 10, 10, NULL, MAY_READ, 0, 0)); | |
185 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0770, 10, 10, NULL, MAY_READ, 0, 0)); | |
186 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0775, 10, 10, NULL, MAY_WRITE, 0, 0)); | |
187 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0775, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
188 | ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
189 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0773, 10, 10, NULL, MAY_READ, 0, 0)); | |
190 | ||
191 | // group > other | |
192 | ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0557, 10, 10, NULL, MAY_READ, 0, 0)); | |
193 | ASSERT_FALSE(cap.is_capable("foo", 0, 10, 0557, 10, 10, NULL, MAY_WRITE, 0, 0)); | |
194 | ||
195 | // user > other | |
196 | ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0557, 10, 10, NULL, MAY_READ, 0, 0)); | |
197 | ASSERT_FALSE(cap.is_capable("foo", 10, 0, 0557, 10, 10, NULL, MAY_WRITE, 0, 0)); | |
198 | } | |
199 | ||
200 | TEST(MDSAuthCaps, AllowPath) { | |
201 | MDSAuthCaps cap; | |
202 | ASSERT_TRUE(cap.parse(g_ceph_context, "allow * path=/sandbox", NULL)); | |
203 | ASSERT_FALSE(cap.allow_all()); | |
204 | ASSERT_TRUE(cap.is_capable("sandbox/foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
205 | ASSERT_TRUE(cap.is_capable("sandbox", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
206 | ASSERT_FALSE(cap.is_capable("sandboxed", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
207 | ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
208 | } | |
209 | ||
210 | TEST(MDSAuthCaps, AllowPathChars) { | |
211 | MDSAuthCaps unquo_cap; | |
212 | ASSERT_TRUE(unquo_cap.parse(g_ceph_context, "allow * path=/sandbox-._foo", NULL)); | |
213 | ASSERT_FALSE(unquo_cap.allow_all()); | |
214 | ASSERT_TRUE(unquo_cap.is_capable("sandbox-._foo/foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
215 | ASSERT_FALSE(unquo_cap.is_capable("sandbox", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
216 | ASSERT_FALSE(unquo_cap.is_capable("sandbox-._food", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
217 | ASSERT_FALSE(unquo_cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
218 | } | |
219 | ||
220 | ||
221 | TEST(MDSAuthCaps, AllowPathCharsQuoted) { | |
222 | MDSAuthCaps quo_cap; | |
223 | ASSERT_TRUE(quo_cap.parse(g_ceph_context, "allow * path=\"/sandbox-._foo\"", NULL)); | |
224 | ASSERT_FALSE(quo_cap.allow_all()); | |
225 | ASSERT_TRUE(quo_cap.is_capable("sandbox-._foo/foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
226 | ASSERT_FALSE(quo_cap.is_capable("sandbox", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
227 | ASSERT_FALSE(quo_cap.is_capable("sandbox-._food", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
228 | ASSERT_FALSE(quo_cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0)); | |
229 | } | |
230 | ||
231 | TEST(MDSAuthCaps, OutputParsed) { | |
232 | struct CapsTest { | |
233 | const char *input; | |
234 | const char *output; | |
235 | }; | |
236 | CapsTest test_values[] = { | |
237 | {"allow", | |
238 | "MDSAuthCaps[allow rw]"}, | |
239 | {"allow *", | |
240 | "MDSAuthCaps[allow *]"}, | |
241 | {"allow r", | |
242 | "MDSAuthCaps[allow r]"}, | |
243 | {"allow rw", | |
244 | "MDSAuthCaps[allow rw]"}, | |
245 | {"allow * uid=1", | |
246 | "MDSAuthCaps[allow * uid=1]"}, | |
247 | {"allow * uid=1 gids=1", | |
248 | "MDSAuthCaps[allow * uid=1 gids=1]"}, | |
249 | {"allow * uid=1 gids=1,2,3", | |
250 | "MDSAuthCaps[allow * uid=1 gids=1,2,3]"}, | |
251 | {"allow * path=/foo", | |
252 | "MDSAuthCaps[allow * path=\"/foo\"]"}, | |
253 | {"allow * path=\"/foo\"", | |
254 | "MDSAuthCaps[allow * path=\"/foo\"]"}, | |
255 | {"allow * path=\"/foo\" uid=1", | |
256 | "MDSAuthCaps[allow * path=\"/foo\" uid=1]"}, | |
257 | {"allow * path=\"/foo\" uid=1 gids=1,2,3", | |
258 | "MDSAuthCaps[allow * path=\"/foo\" uid=1 gids=1,2,3]"}, | |
259 | {"allow r uid=1 gids=1,2,3, allow * uid=2", | |
260 | "MDSAuthCaps[allow r uid=1 gids=1,2,3, allow * uid=2]"}, | |
261 | }; | |
262 | size_t num_tests = sizeof(test_values) / sizeof(*test_values); | |
263 | for (size_t i = 0; i < num_tests; ++i) { | |
264 | MDSAuthCaps cap; | |
265 | std::cout << "Testing input '" << test_values[i].input << "'" << std::endl; | |
266 | ASSERT_TRUE(cap.parse(g_ceph_context, test_values[i].input, &cout)); | |
267 | ASSERT_EQ(test_values[i].output, stringify(cap)); | |
268 | } | |
269 | } |