]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/libcephfs/access.cc
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) 2011 New Dream Network
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.
15 #include "gtest/gtest.h"
16 #include "common/ceph_argparse.h"
17 #include "include/buffer.h"
18 #include "include/stringify.h"
19 #include "include/cephfs/libcephfs.h"
20 #include "include/rados/librados.h"
24 #include <sys/types.h>
30 #include "json_spirit/json_spirit.h"
34 #include <sys/xattr.h>
43 int do_mon_command(string s
, string
*key
)
46 size_t outs_len
, outbuf_len
;
47 const char *ss
= s
.c_str();
48 int r
= rados_mon_command(cluster
, (const char **)&ss
, 1,
53 string
s(outbuf
, outbuf_len
);
54 std::cout
<< "out: " << s
<< std::endl
;
57 json_spirit::mValue v
, k
;
58 json_spirit::read_or_throw(s
, v
);
59 k
= v
.get_array()[0].get_obj().find("key")->second
;
61 std::cout
<< "key: " << *key
<< std::endl
;
67 string
s(outs
, outs_len
);
68 std::cout
<< "outs: " << s
<< std::endl
;
74 string
get_unique_dir()
76 return string("/ceph_test_libcephfs_access.") + stringify(rand());
79 TEST(AccessTest
, Foo
) {
80 string dir
= get_unique_dir();
81 string user
= "libcephfs_foo_test." + stringify(rand());
82 // admin mount to set up test
83 struct ceph_mount_info
*admin
;
84 ASSERT_EQ(0, ceph_create(&admin
, NULL
));
85 ASSERT_EQ(0, ceph_conf_read_file(admin
, NULL
));
86 ASSERT_EQ(0, ceph_conf_parse_env(admin
, NULL
));
87 ASSERT_EQ(0, ceph_mount(admin
, "/"));
88 ASSERT_EQ(0, ceph_mkdir(admin
, dir
.c_str(), 0755));
92 ASSERT_EQ(0, do_mon_command(
93 "{\"prefix\": \"auth get-or-create\", \"entity\": \"client." + user
+ "\", "
94 "\"caps\": [\"mon\", \"allow *\", \"osd\", \"allow rw\", "
95 "\"mds\", \"allow rw\""
96 "], \"format\": \"json\"}", &key
));
98 struct ceph_mount_info
*cmount
;
99 ASSERT_EQ(0, ceph_create(&cmount
, user
.c_str()));
100 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
101 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
102 ASSERT_EQ(0, ceph_conf_set(cmount
, "key", key
.c_str()));
103 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
105 ceph_shutdown(cmount
);
108 ASSERT_EQ(0, ceph_rmdir(admin
, dir
.c_str()));
109 ceph_shutdown(admin
);
112 TEST(AccessTest
, Path
) {
113 string good
= get_unique_dir();
114 string bad
= get_unique_dir();
115 string user
= "libcephfs_path_test." + stringify(rand());
116 struct ceph_mount_info
*admin
;
117 ASSERT_EQ(0, ceph_create(&admin
, NULL
));
118 ASSERT_EQ(0, ceph_conf_read_file(admin
, NULL
));
119 ASSERT_EQ(0, ceph_conf_parse_env(admin
, NULL
));
120 ASSERT_EQ(0, ceph_mount(admin
, "/"));
121 ASSERT_EQ(0, ceph_mkdir(admin
, good
.c_str(), 0755));
122 ASSERT_EQ(0, ceph_mkdir(admin
, string(good
+ "/p").c_str(), 0755));
123 ASSERT_EQ(0, ceph_mkdir(admin
, bad
.c_str(), 0755));
124 ASSERT_EQ(0, ceph_mkdir(admin
, string(bad
+ "/p").c_str(), 0755));
125 int fd
= ceph_open(admin
, string(good
+ "/q").c_str(), O_CREAT
|O_WRONLY
, 0755);
126 ceph_close(admin
, fd
);
127 fd
= ceph_open(admin
, string(bad
+ "/q").c_str(), O_CREAT
|O_WRONLY
, 0755);
128 ceph_close(admin
, fd
);
129 fd
= ceph_open(admin
, string(bad
+ "/z").c_str(), O_CREAT
|O_WRONLY
, 0755);
130 ceph_write(admin
, fd
, "TEST FAILED", 11, 0);
131 ceph_close(admin
, fd
);
134 ASSERT_EQ(0, do_mon_command(
135 "{\"prefix\": \"auth get-or-create\", \"entity\": \"client." + user
+ "\", "
136 "\"caps\": [\"mon\", \"allow r\", \"osd\", \"allow rwx\", "
137 "\"mds\", \"allow r, allow rw path=" + good
+ "\""
138 "], \"format\": \"json\"}", &key
));
140 struct ceph_mount_info
*cmount
;
141 ASSERT_EQ(0, ceph_create(&cmount
, user
.c_str()));
142 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
143 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
144 ASSERT_EQ(0, ceph_conf_set(cmount
, "key", key
.c_str()));
145 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
148 ASSERT_GE(ceph_mkdir(cmount
, string(good
+ "/x").c_str(), 0755), 0);
149 ASSERT_GE(ceph_rmdir(cmount
, string(good
+ "/p").c_str()), 0);
150 ASSERT_GE(ceph_unlink(cmount
, string(good
+ "/q").c_str()), 0);
151 fd
= ceph_open(cmount
, string(good
+ "/y").c_str(), O_CREAT
|O_WRONLY
, 0755);
153 ceph_write(cmount
, fd
, "bar", 3, 0);
154 ceph_close(cmount
, fd
);
155 ASSERT_GE(ceph_unlink(cmount
, string(good
+ "/y").c_str()), 0);
156 ASSERT_GE(ceph_rmdir(cmount
, string(good
+ "/x").c_str()), 0);
158 fd
= ceph_open(cmount
, string(bad
+ "/z").c_str(), O_RDONLY
, 0644);
160 ceph_close(cmount
, fd
);
163 ASSERT_LT(ceph_mkdir(cmount
, string(bad
+ "/x").c_str(), 0755), 0);
164 ASSERT_LT(ceph_rmdir(cmount
, string(bad
+ "/p").c_str()), 0);
165 ASSERT_LT(ceph_unlink(cmount
, string(bad
+ "/q").c_str()), 0);
166 fd
= ceph_open(cmount
, string(bad
+ "/y").c_str(), O_CREAT
|O_WRONLY
, 0755);
170 fd
= ceph_open(cmount
, string(good
+ "/unlinkme").c_str(), O_CREAT
|O_WRONLY
, 0755);
171 ceph_unlink(cmount
, string(good
+ "/unlinkme").c_str());
172 ASSERT_GE(ceph_write(cmount
, fd
, "foo", 3, 0), 0);
173 ASSERT_GE(ceph_fchmod(cmount
, fd
, 0777), 0);
174 ASSERT_GE(ceph_ftruncate(cmount
, fd
, 0), 0);
175 ASSERT_GE(ceph_fsetxattr(cmount
, fd
, "user.any", "bar", 3, 0), 0);
176 ceph_close(cmount
, fd
);
179 fd
= ceph_open(cmount
, string(good
+ "/renameme").c_str(), O_CREAT
|O_WRONLY
, 0755);
180 ASSERT_EQ(ceph_rename(admin
, string(good
+ "/renameme").c_str(),
181 string(bad
+ "/asdf").c_str()), 0);
182 ASSERT_GE(ceph_write(cmount
, fd
, "foo", 3, 0), 0);
183 ASSERT_GE(ceph_fchmod(cmount
, fd
, 0777), -EACCES
);
184 ASSERT_GE(ceph_ftruncate(cmount
, fd
, 0), -EACCES
);
185 ASSERT_GE(ceph_fsetxattr(cmount
, fd
, "user.any", "bar", 3, 0), -EACCES
);
186 ceph_close(cmount
, fd
);
188 ceph_shutdown(cmount
);
189 ASSERT_EQ(0, ceph_unlink(admin
, string(bad
+ "/q").c_str()));
190 ASSERT_EQ(0, ceph_unlink(admin
, string(bad
+ "/z").c_str()));
191 ASSERT_EQ(0, ceph_rmdir(admin
, string(bad
+ "/p").c_str()));
192 ASSERT_EQ(0, ceph_unlink(admin
, string(bad
+ "/asdf").c_str()));
193 ASSERT_EQ(0, ceph_rmdir(admin
, good
.c_str()));
194 ASSERT_EQ(0, ceph_rmdir(admin
, bad
.c_str()));
195 ceph_shutdown(admin
);
198 TEST(AccessTest
, ReadOnly
) {
199 string dir
= get_unique_dir();
200 string dir2
= get_unique_dir();
201 string user
= "libcephfs_readonly_test." + stringify(rand());
202 struct ceph_mount_info
*admin
;
203 ASSERT_EQ(0, ceph_create(&admin
, NULL
));
204 ASSERT_EQ(0, ceph_conf_read_file(admin
, NULL
));
205 ASSERT_EQ(0, ceph_conf_parse_env(admin
, NULL
));
206 ASSERT_EQ(0, ceph_mount(admin
, "/"));
207 ASSERT_EQ(0, ceph_mkdir(admin
, dir
.c_str(), 0755));
208 int fd
= ceph_open(admin
, string(dir
+ "/out").c_str(), O_CREAT
|O_WRONLY
, 0755);
209 ceph_write(admin
, fd
, "foo", 3, 0);
210 ceph_close(admin
,fd
);
213 ASSERT_EQ(0, do_mon_command(
214 "{\"prefix\": \"auth get-or-create\", \"entity\": \"client." + user
+ "\", "
215 "\"caps\": [\"mon\", \"allow r\", \"osd\", \"allow rw\", "
216 "\"mds\", \"allow r\""
217 "], \"format\": \"json\"}", &key
));
219 struct ceph_mount_info
*cmount
;
220 ASSERT_EQ(0, ceph_create(&cmount
, user
.c_str()));
221 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
222 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
223 ASSERT_EQ(0, ceph_conf_set(cmount
, "key", key
.c_str()));
224 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
227 fd
= ceph_open(cmount
, string(dir
+ "/out").c_str(), O_RDONLY
, 0644);
229 ceph_close(cmount
,fd
);
232 fd
= ceph_open(cmount
, string(dir
+ "/bar").c_str(), O_CREAT
|O_WRONLY
, 0755);
234 ASSERT_LT(ceph_mkdir(cmount
, dir2
.c_str(), 0755), 0);
236 ceph_shutdown(cmount
);
237 ASSERT_EQ(0, ceph_unlink(admin
, string(dir
+ "/out").c_str()));
238 ASSERT_EQ(0, ceph_rmdir(admin
, dir
.c_str()));
239 ceph_shutdown(admin
);
242 TEST(AccessTest
, User
) {
243 string dir
= get_unique_dir();
244 string user
= "libcephfs_user_test." + stringify(rand());
246 // admin mount to set up test
247 struct ceph_mount_info
*admin
;
248 ASSERT_EQ(0, ceph_create(&admin
, NULL
));
249 ASSERT_EQ(0, ceph_conf_read_file(admin
, NULL
));
250 ASSERT_EQ(0, ceph_conf_parse_env(admin
, NULL
));
251 ASSERT_EQ(0, ceph_conf_set(admin
, "client_permissions", "0"));
252 ASSERT_EQ(0, ceph_mount(admin
, "/"));
253 ASSERT_EQ(0, ceph_mkdir(admin
, dir
.c_str(), 0755));
257 ASSERT_EQ(0, do_mon_command(
258 "{\"prefix\": \"auth get-or-create\", \"entity\": \"client." + user
+ "\", "
259 "\"caps\": [\"mon\", \"allow *\", \"osd\", \"allow rw\", "
260 "\"mds\", \"allow rw uid=123 gids=456,789\""
261 "], \"format\": \"json\"}", &key
));
263 struct ceph_mount_info
*cmount
;
264 ASSERT_EQ(0, ceph_create(&cmount
, user
.c_str()));
265 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
266 ASSERT_EQ(0, ceph_conf_parse_env(cmount
, NULL
));
267 ASSERT_EQ(0, ceph_conf_set(cmount
, "key", key
.c_str()));
268 ASSERT_EQ(-EACCES
, ceph_mount(cmount
, "/"));
269 ASSERT_EQ(0, ceph_init(cmount
));
271 UserPerm
*perms
= ceph_userperm_new(123, 456, 0, NULL
);
272 ASSERT_NE(nullptr, perms
);
273 ASSERT_EQ(0, ceph_mount_perms_set(cmount
, perms
));
274 ceph_userperm_destroy(perms
);
276 ASSERT_EQ(0, ceph_conf_set(cmount
, "client_permissions", "0"));
277 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
280 ASSERT_EQ(0, ceph_chmod(admin
, dir
.c_str(), 0700));
281 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 123, 456));
282 ASSERT_EQ(0, ceph_mkdir(cmount
, string(dir
+ "/u1").c_str(), 0755));
283 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 1, 456));
284 ASSERT_EQ(-EACCES
, ceph_mkdir(cmount
, string(dir
+ "/no").c_str(), 0755));
287 ASSERT_EQ(0, ceph_chmod(admin
, dir
.c_str(), 0770));
288 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 1, 456));
289 ASSERT_EQ(0, ceph_mkdir(cmount
, string(dir
+ "/u2").c_str(), 0755));
290 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 1, 2));
291 ASSERT_EQ(-EACCES
, ceph_mkdir(cmount
, string(dir
+ "/no").c_str(), 0755));
293 // user overrides group
294 ASSERT_EQ(0, ceph_chmod(admin
, dir
.c_str(), 0470));
295 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 123, 456));
296 ASSERT_EQ(-EACCES
, ceph_mkdir(cmount
, string(dir
+ "/no").c_str(), 0755));
299 ASSERT_EQ(0, ceph_chmod(admin
, dir
.c_str(), 0777));
300 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 1, 1));
301 ASSERT_EQ(0, ceph_mkdir(cmount
, string(dir
+ "/u3").c_str(), 0755));
302 ASSERT_EQ(0, ceph_chmod(admin
, dir
.c_str(), 0770));
303 ASSERT_EQ(-EACCES
, ceph_mkdir(cmount
, string(dir
+ "/no").c_str(), 0755));
305 // user and group overrides other
306 ASSERT_EQ(0, ceph_chmod(admin
, dir
.c_str(), 07));
307 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 1, 456));
308 ASSERT_EQ(-EACCES
, ceph_mkdir(cmount
, string(dir
+ "/no").c_str(), 0755));
309 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 123, 1));
310 ASSERT_EQ(-EACCES
, ceph_mkdir(cmount
, string(dir
+ "/no").c_str(), 0755));
311 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 123, 456));
312 ASSERT_EQ(-EACCES
, ceph_mkdir(cmount
, string(dir
+ "/no").c_str(), 0755));
315 ASSERT_EQ(0, ceph_chmod(admin
, dir
.c_str(), 0700));
316 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 123, 456));
317 // FIXME: Re-enable these 789 tests once we can set multiple GIDs via libcephfs/config
318 // ASSERT_EQ(0, ceph_chown(cmount, dir.c_str(), 123, 789));
319 ASSERT_EQ(0, ceph_chown(cmount
, dir
.c_str(), 123, 456));
320 // ASSERT_EQ(0, ceph_chown(cmount, dir.c_str(), -1, 789));
321 ASSERT_EQ(0, ceph_chown(cmount
, dir
.c_str(), -1, 456));
322 ASSERT_EQ(-EACCES
, ceph_chown(cmount
, dir
.c_str(), 123, 1));
323 ASSERT_EQ(-EACCES
, ceph_chown(cmount
, dir
.c_str(), 1, 456));
325 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 1, 1));
326 ASSERT_EQ(-EACCES
, ceph_chown(cmount
, dir
.c_str(), 123, 456));
327 ASSERT_EQ(-EACCES
, ceph_chown(cmount
, dir
.c_str(), 123, -1));
328 ASSERT_EQ(-EACCES
, ceph_chown(cmount
, dir
.c_str(), -1, 456));
330 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 1, 456));
331 ASSERT_EQ(-EACCES
, ceph_chown(cmount
, dir
.c_str(), 123, 456));
332 ASSERT_EQ(-EACCES
, ceph_chown(cmount
, dir
.c_str(), 123, -1));
333 ASSERT_EQ(-EACCES
, ceph_chown(cmount
, dir
.c_str(), -1, 456));
335 ASSERT_EQ(0, ceph_chown(admin
, dir
.c_str(), 123, 1));
336 ASSERT_EQ(0, ceph_chown(cmount
, dir
.c_str(), -1, 456));
337 // ASSERT_EQ(0, ceph_chown(cmount, dir.c_str(), 123, 789));
339 ceph_shutdown(cmount
);
342 ASSERT_EQ(0, ceph_rmdir(admin
, string(dir
+ "/u1").c_str()));
343 ASSERT_EQ(0, ceph_rmdir(admin
, string(dir
+ "/u2").c_str()));
344 ASSERT_EQ(0, ceph_rmdir(admin
, string(dir
+ "/u3").c_str()));
345 ASSERT_EQ(0, ceph_rmdir(admin
, dir
.c_str()));
346 ceph_shutdown(admin
);
349 static int update_root_mode()
351 struct ceph_mount_info
*admin
;
352 int r
= ceph_create(&admin
, NULL
);
355 ceph_conf_read_file(admin
, NULL
);
356 ceph_conf_parse_env(admin
, NULL
);
357 ceph_conf_set(admin
, "client_permissions", "false");
358 r
= ceph_mount(admin
, "/");
361 r
= ceph_chmod(admin
, "/", 0777);
363 ceph_shutdown(admin
);
368 int main(int argc
, char **argv
)
370 int r
= update_root_mode();
374 ::testing::InitGoogleTest(&argc
, argv
);
378 r
= rados_create(&cluster
, NULL
);
382 r
= rados_conf_read_file(cluster
, NULL
);
386 rados_conf_parse_env(cluster
, NULL
);
387 r
= rados_connect(cluster
);
393 rados_shutdown(cluster
);