Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / mds / TestMDSAuthCaps.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 "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);
119   ASSERT_TRUE(cap.parse(g_ceph_context, "allow * uid=10 gids=10,11,12; allow * uid=12 gids=12,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_FALSE(cap.is_capable("foo", 0, 0, 0777, 10, 0, NULL, MAY_READ, 0, 0));
125   ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 9, 10, NULL, MAY_READ, 0, 0));
126   ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 10, 10, NULL, MAY_READ, 0, 0));
127   ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 12, 12, NULL, MAY_READ, 0, 0));
128   ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 10, 13, NULL, MAY_READ, 0, 0));
129
130   // user
131   ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0500, 10, 11, NULL, MAY_READ, 0, 0));
132   ASSERT_FALSE(cap.is_capable("foo", 10, 10, 0500, 10, 11, NULL, MAY_WRITE, 0, 0));
133   ASSERT_FALSE(cap.is_capable("foo", 10, 10, 0500, 10, 11, NULL, MAY_READ | MAY_WRITE, 0, 0));
134   ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0700, 10, 11, NULL, MAY_READ, 0, 0));
135   ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0700, 10, 11, NULL, MAY_WRITE, 0, 0));
136   ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0700, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0));
137   ASSERT_TRUE(cap.is_capable("foo", 10, 0, 0700, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0));
138   ASSERT_FALSE(cap.is_capable("foo", 12, 0, 0700, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0));
139   ASSERT_TRUE(cap.is_capable("foo", 12, 0, 0700, 12, 12, NULL, MAY_READ | MAY_WRITE, 0, 0));
140   ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0700, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0));
141
142   // group
143   vector<uint64_t> glist10;
144   glist10.push_back(10);
145   vector<uint64_t> dglist10;
146   dglist10.push_back(8);
147   dglist10.push_back(10);
148   vector<uint64_t> glist11;
149   glist11.push_back(11);
150   vector<uint64_t> glist12;
151   glist12.push_back(12);
152   ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0750, 10, 10, NULL, MAY_READ, 0, 0));
153   ASSERT_FALSE(cap.is_capable("foo", 0, 10, 0750, 10, 10, NULL, MAY_WRITE, 0, 0));
154   ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0770, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0));
155   ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0770, 10, 11, &glist10, MAY_READ | MAY_WRITE, 0, 0));
156   ASSERT_TRUE(cap.is_capable("foo", 0, 11, 0770, 10, 10, &glist11, MAY_READ | MAY_WRITE, 0, 0));
157   ASSERT_TRUE(cap.is_capable("foo", 0, 11, 0770, 10, 11, NULL, MAY_READ | MAY_WRITE, 0, 0));
158   ASSERT_TRUE(cap.is_capable("foo", 0, 12, 0770, 12, 12, NULL, MAY_READ | MAY_WRITE, 0, 0));
159   ASSERT_FALSE(cap.is_capable("foo", 0, 10, 0770, 12, 12, NULL, MAY_READ | MAY_WRITE, 0, 0));
160   ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0770, 12, 12, &glist10, MAY_READ | MAY_WRITE, 0, 0));
161   ASSERT_TRUE(cap.is_capable("foo", 0, 10, 0770, 12, 12, &dglist10, MAY_READ | MAY_WRITE, 0, 0));
162   ASSERT_FALSE(cap.is_capable("foo", 0, 11, 0770, 12, 12, &glist11, MAY_READ | MAY_WRITE, 0, 0));
163   ASSERT_FALSE(cap.is_capable("foo", 0, 12, 0770, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0));
164   ASSERT_TRUE(cap.is_capable("foo", 0, 12, 0770, 10, 10, &glist12, MAY_READ | MAY_WRITE, 0, 0));
165
166   // user > group
167   ASSERT_TRUE(cap.is_capable("foo", 10, 10, 0570, 10, 10, NULL, MAY_READ, 0, 0));
168   ASSERT_FALSE(cap.is_capable("foo", 10, 10, 0570, 10, 10, NULL, MAY_WRITE, 0, 0));
169
170   // other
171   ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0775, 10, 10, NULL, MAY_READ, 0, 0));
172   ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0770, 10, 10, NULL, MAY_READ, 0, 0));
173   ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0775, 10, 10, NULL, MAY_WRITE, 0, 0));
174   ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0775, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0));
175   ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 10, 10, NULL, MAY_READ | MAY_WRITE, 0, 0));
176   ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0773, 10, 10, NULL, MAY_READ, 0, 0));
177
178   // group > other
179   ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0557, 10, 10, NULL, MAY_READ, 0, 0));
180   ASSERT_FALSE(cap.is_capable("foo", 0, 10, 0557, 10, 10, NULL, MAY_WRITE, 0, 0));
181
182   // user > other
183   ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0557, 10, 10, NULL, MAY_READ, 0, 0));
184   ASSERT_FALSE(cap.is_capable("foo", 10, 0, 0557, 10, 10, NULL, MAY_WRITE, 0, 0));
185 }
186
187 TEST(MDSAuthCaps, AllowPath) {
188   MDSAuthCaps cap;
189   ASSERT_TRUE(cap.parse(g_ceph_context, "allow * path=/sandbox", NULL));
190   ASSERT_FALSE(cap.allow_all());
191   ASSERT_TRUE(cap.is_capable("sandbox/foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
192   ASSERT_TRUE(cap.is_capable("sandbox", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
193   ASSERT_FALSE(cap.is_capable("sandboxed", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
194   ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
195 }
196
197 TEST(MDSAuthCaps, AllowPathChars) {
198   MDSAuthCaps unquo_cap;
199   ASSERT_TRUE(unquo_cap.parse(g_ceph_context, "allow * path=/sandbox-._foo", NULL));
200   ASSERT_FALSE(unquo_cap.allow_all());
201   ASSERT_TRUE(unquo_cap.is_capable("sandbox-._foo/foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
202   ASSERT_FALSE(unquo_cap.is_capable("sandbox", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
203   ASSERT_FALSE(unquo_cap.is_capable("sandbox-._food", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
204   ASSERT_FALSE(unquo_cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
205 }
206
207
208 TEST(MDSAuthCaps, AllowPathCharsQuoted) {
209   MDSAuthCaps quo_cap;
210   ASSERT_TRUE(quo_cap.parse(g_ceph_context, "allow * path=\"/sandbox-._foo\"", NULL));
211   ASSERT_FALSE(quo_cap.allow_all());
212   ASSERT_TRUE(quo_cap.is_capable("sandbox-._foo/foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
213   ASSERT_FALSE(quo_cap.is_capable("sandbox", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
214   ASSERT_FALSE(quo_cap.is_capable("sandbox-._food", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
215   ASSERT_FALSE(quo_cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ | MAY_WRITE, 0, 0));
216 }
217
218 TEST(MDSAuthCaps, OutputParsed) {
219   struct CapsTest {
220     const char *input;
221     const char *output;
222   };
223   CapsTest test_values[] = {
224     {"allow",
225      "MDSAuthCaps[allow rw]"},
226     {"allow *",
227      "MDSAuthCaps[allow *]"},
228     {"allow r",
229      "MDSAuthCaps[allow r]"},
230     {"allow rw",
231      "MDSAuthCaps[allow rw]"},
232     {"allow * uid=1",
233      "MDSAuthCaps[allow * uid=1]"},
234     {"allow * uid=1 gids=1",
235      "MDSAuthCaps[allow * uid=1 gids=1]"},
236     {"allow * uid=1 gids=1,2,3",
237      "MDSAuthCaps[allow * uid=1 gids=1,2,3]"},
238     {"allow * path=/foo",
239      "MDSAuthCaps[allow * path=\"/foo\"]"},
240     {"allow * path=\"/foo\"",
241      "MDSAuthCaps[allow * path=\"/foo\"]"},
242     {"allow * path=\"/foo\" uid=1",
243      "MDSAuthCaps[allow * path=\"/foo\" uid=1]"},
244     {"allow * path=\"/foo\" uid=1 gids=1,2,3",
245      "MDSAuthCaps[allow * path=\"/foo\" uid=1 gids=1,2,3]"},
246     {"allow r uid=1 gids=1,2,3, allow * uid=2",
247      "MDSAuthCaps[allow r uid=1 gids=1,2,3, allow * uid=2]"},
248   };
249   size_t num_tests = sizeof(test_values) / sizeof(*test_values);
250   for (size_t i = 0; i < num_tests; ++i) {
251     MDSAuthCaps cap;
252     std::cout << "Testing input '" << test_values[i].input << "'" << std::endl;
253     ASSERT_TRUE(cap.parse(g_ceph_context, test_values[i].input, &cout));
254     ASSERT_EQ(test_values[i].output, stringify(cap));
255   }
256 }