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"
22 const char *parse_good[] = {
34 "allow service=foo x",
35 "allow service=\"froo\" x",
37 "allow profile osd-bootstrap",
38 "allow profile \"mds-bootstrap\", allow *",
39 "allow command \"a b c\"",
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",
46 "allow command abc with arg regex \"^[0-9a-z.]*$\"",
47 "allow command abc with arg regex \"\(invaluid regex\"",
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\"",
61 "profile \"mds-bootstrap\", profile foo",
65 TEST(MonCap, ParseGood) {
66 for (int i=0; parse_good[i]; ++i) {
67 string str = parse_good[i];
69 std::cout << "Testing good input: '" << str << "'" << std::endl;
70 ASSERT_TRUE(cap.parse(str, &cout));
71 std::cout << " -> " << cap << std::endl;
75 // these should stringify to the input value
76 const char *parse_identity[] = {
80 "allow service foo x",
82 "allow profile osd-bootstrap",
83 "allow profile mds-bootstrap, allow *",
84 "allow profile \"foo bar\", allow *",
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",
103 TEST(MonCap, ParseIdentity)
105 for (int i=0; parse_identity[i]; ++i) {
106 string str = parse_identity[i];
108 std::cout << "Testing good input: '" << str << "'" << std::endl;
109 ASSERT_TRUE(cap.parse(str, &cout));
110 string out = stringify(cap);
115 const char *parse_bad[] = {
119 "allow profile foo rwx",
121 "allow profile foo bar rwx",
123 "allow command baz 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",
141 TEST(MonCap, ParseBad) {
142 for (int i=0; parse_bad[i]; ++i) {
143 string str = parse_bad[i];
145 std::cout << "Testing bad input: '" << str << "'" << std::endl;
146 ASSERT_FALSE(cap.parse(str, &cout));
150 TEST(MonCap, AllowAll) {
152 ASSERT_FALSE(cap.is_allow_all());
154 ASSERT_TRUE(cap.parse("allow r", NULL));
155 ASSERT_FALSE(cap.is_allow_all());
158 ASSERT_TRUE(cap.parse("allow w", NULL));
159 ASSERT_FALSE(cap.is_allow_all());
162 ASSERT_TRUE(cap.parse("allow x", NULL));
163 ASSERT_FALSE(cap.is_allow_all());
166 ASSERT_TRUE(cap.parse("allow rwx", NULL));
167 ASSERT_FALSE(cap.is_allow_all());
170 ASSERT_TRUE(cap.parse("allow rw", NULL));
171 ASSERT_FALSE(cap.is_allow_all());
174 ASSERT_TRUE(cap.parse("allow rx", NULL));
175 ASSERT_FALSE(cap.is_allow_all());
178 ASSERT_TRUE(cap.parse("allow wx", NULL));
179 ASSERT_FALSE(cap.is_allow_all());
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));
188 ASSERT_FALSE(cap2.is_allow_all());
189 cap2.set_allow_all();
190 ASSERT_TRUE(cap2.is_allow_all());
193 TEST(MonCap, ProfileOSD) {
195 bool r = cap.parse("allow profile osd", NULL);
199 name.from_str("osd.123");
200 map<string,string> ca;
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));
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));
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));
239 ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON,
240 name, "", "config-key set", ca, true, true, true));
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));
247 TEST(MonCap, CommandRegEx) {
249 ASSERT_FALSE(cap.is_allow_all());
250 ASSERT_TRUE(cap.parse("allow command abc with arg regex \"^[0-9a-z.]*$\"", NULL));
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));
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));
264 TEST(MonCap, ProfileBootstrapRBD) {
266 ASSERT_FALSE(cap.is_allow_all());
267 ASSERT_TRUE(cap.parse("profile bootstrap-rbd", NULL));
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));