]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/workunits/mon/caps.py
96dbf73ffd5464179925fac9e4994b38fe3c81b4
6 from StringIO
import StringIO
15 from ceph_argparse
import *
17 keyring_base
= '/tmp/cephtest-caps.keyring'
19 class UnexpectedReturn(Exception):
20 def __init__(self
, cmd
, ret
, expected
, msg
):
21 if isinstance(cmd
, list):
22 self
.cmd
= ' '.join(cmd
)
24 assert isinstance(cmd
, str) or isinstance(cmd
, unicode), \
25 'cmd needs to be either a list or a str'
27 self
.cmd
= str(self
.cmd
)
29 self
.expected
= int(expected
)
33 return repr('{c}: expected return {e}, got {r} ({o})'.format(
34 c
=self
.cmd
, e
=self
.expected
, r
=self
.ret
, o
=self
.msg
))
37 if isinstance(cmd
, list):
39 elif isinstance(cmd
, str) or isinstance(cmd
, unicode):
40 args
= shlex
.split(cmd
)
42 assert False, 'cmd is not a string/unicode nor a list!'
44 print 'call: {0}'.format(args
)
45 proc
= subprocess
.Popen(args
, stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
)
50 def expect(cmd
, expected_ret
):
54 except ValueError as e
:
55 print >> sys
.stderr
, \
56 'unable to run {c}: {err}'.format(c
=repr(cmd
), err
=e
.message
)
59 assert r
== p
.returncode
, \
60 'wth? r was supposed to match returncode!'
63 raise UnexpectedReturn(repr(cmd
), r
, expected_ret
, str(p
.stderr
.read()))
67 def expect_to_file(cmd
, expected_ret
, out_file
, mode
='a'):
69 # Let the exception be propagated to the caller
70 p
= expect(cmd
, expected_ret
)
71 assert p
.returncode
== expected_ret
, \
72 'expected result doesn\'t match and no exception was thrown!'
74 with io
.open(out_file
, mode
) as file:
75 file.write(unicode(p
.stdout
.read()))
80 def __init__(self
, cid
, j
):
82 self
.perms
= j
['perm']
83 self
.module
= j
['module']
88 if not isinstance(s
, dict):
89 assert isinstance(s
, str) or isinstance(s
,unicode), \
90 'malformatted signature cid {0}: {1}\n{2}'.format(cid
,s
,j
)
98 return repr('command {0}: {1} (requires \'{2}\')'.format(self
.cid
,\
99 self
.sig
, self
.perms
))
102 def destroy_keyring(path
):
103 if not os
.path
.exists(path
):
104 raise Exception('oops! cannot remove inexistent keyring {0}'.format(path
))
106 # grab all client entities from the keyring
107 entities
= [m
.group(1) for m
in [re
.match(r
'\[client\.(.*)\]', l
)
108 for l
in [str(line
.strip())
109 for line
in io
.open(path
,'r')]] if m
is not None]
111 # clean up and make sure each entity is gone
113 expect('ceph auth del client.{0}'.format(e
), 0)
114 expect('ceph auth get client.{0}'.format(e
), errno
.ENOENT
)
121 def test_basic_auth():
122 # make sure we can successfully add/del entities, change their caps
123 # and import/export keyrings.
125 expect('ceph auth add client.basicauth', 0)
126 expect('ceph auth caps client.basicauth mon \'allow *\'', 0)
127 # entity exists and caps do not match
128 expect('ceph auth add client.basicauth', errno
.EINVAL
)
129 # this command attempts to change an existing state and will fail
130 expect('ceph auth add client.basicauth mon \'allow w\'', errno
.EINVAL
)
131 expect('ceph auth get-or-create client.basicauth', 0)
132 expect('ceph auth get-key client.basicauth', 0)
133 expect('ceph auth get-or-create client.basicauth2', 0)
135 expect('ceph auth del client.basicauth', 0)
136 expect('ceph auth del client.basicauth2', 0)
140 def gen_module_keyring(module
):
142 ('all', '{t} \'allow service {s} rwx\'', 0),
143 ('none', '', errno
.EACCES
),
144 ('wrong', '{t} \'allow service foobar rwx\'', errno
.EACCES
),
145 ('right', '{t} \'allow service {s} {p}\'', 0),
146 ('no-execute', '{t} \'allow service {s} x\'', errno
.EACCES
)
149 keyring
= '{0}.service-{1}'.format(keyring_base
,module
)
150 for perms
in 'r rw x'.split():
151 for (n
,p
,r
) in module_caps
:
152 c
= p
.format(t
='mon', s
=module
, p
=perms
)
154 'ceph auth get-or-create client.{cn}-{cp} {caps}'.format(
155 cn
=n
,cp
=perms
,caps
=c
), 0, keyring
)
172 ('rwx', 'allow service {s} rwx'),
173 ('r', 'allow service {s} r'),
174 ('rw', 'allow service {s} rw'),
175 ('x', 'allow service {s} x'),
178 ('rwx', 'allow command "{c}"'),
181 ('rwx', 'allow command "{c}" with {kv}')
183 'command-with-prefix':[
184 ('rwx', 'allow command "{c}" with {key} prefix {val}')
192 ('none1', 'allow service foo rwx'),
193 ('none2', 'allow service foo r'),
194 ('none3', 'allow service foo rw'),
195 ('none4', 'allow service foo x'),
198 ('none', 'allow command foo'),
201 ('none', 'allow command "{c}" with foo=bar'),
203 'command-with-prefix':[
204 ('none', 'allow command "{c}" with foo prefix bar'),
212 'cmd':('status', '', 'r')
215 'pre':'heap start_profiler',
216 'cmd':('heap', 'heapcmd=stats', 'rw'),
217 'post':'heap stop_profiler'
223 'cmd':('auth list', '', 'r'),
227 'pre':'auth get-or-create client.foo mon \'allow *\'',
228 'cmd':('auth caps', 'entity="client.foo"', 'rw'),
229 'post':'auth del client.foo'
234 'cmd':('pg getmap', '', 'r'),
239 'cmd':('mds getmap', '', 'r'),
242 'cmd':('mds cluster_down', '', 'rw'),
243 'post':'mds cluster_up'
248 'cmd':('mon getmap', '', 'r')
251 'cmd':('mon remove', 'name=a', 'rw')
256 'cmd':('osd getmap', '', 'r'),
259 'cmd':('osd pause', '', 'rw'),
263 'cmd':('osd crush dump', '', 'r')
268 'pre':'config-key put foo bar',
269 'cmd':('config-key get', 'key=foo', 'r')
272 'pre':'config-key put foo bar',
273 'cmd':('config-key del', 'key=foo', 'rw')
278 for (module
,cmd_lst
) in cmds
.iteritems():
279 k
= keyring_base
+ '.' + module
282 (cmd_cmd
, cmd_args
, cmd_perm
) = cmd
['cmd']
285 if len(cmd_args
) > 0:
286 (cmd_args_key
, cmd_args_val
) = cmd_args
.split('=')
288 print 'generating keyring for {m}/{c}'.format(m
=module
,c
=cmd_cmd
)
290 for (good_or_bad
,kind_map
) in perms
.iteritems():
291 for (kind
,lst
) in kind_map
.iteritems():
292 for (perm
, cap
) in lst
:
293 cap_formatted
= cap
.format(
300 if len(cap_formatted
) == 0:
303 run_cap
= 'mon \'{fc}\''.format(fc
=cap_formatted
)
305 cname
= 'client.{gb}-{kind}-{p}'.format(
306 gb
=good_or_bad
,kind
=kind
,p
=perm
)
308 'ceph auth get-or-create {n} {c}'.format(
309 n
=cname
,c
=run_cap
), 0, k
)
311 print 'testing {m}/{c}'.format(m
=module
,c
=cmd_cmd
)
314 for good_bad
in perms
.iterkeys():
315 for (kind
,lst
) in perms
[good_bad
].iteritems():
317 cname
= 'client.{gb}-{k}-{p}'.format(gb
=good_bad
,k
=kind
,p
=perm
)
319 if good_bad
== 'good':
322 expect_ret
= errno
.EACCES
324 if ( cmd_perm
not in perm
):
325 expect_ret
= errno
.EACCES
326 if 'with' in kind
and len(cmd_args
) == 0:
327 expect_ret
= errno
.EACCES
328 if 'service' in kind
and len(module
) == 0:
329 expect_ret
= errno
.EACCES
331 if 'pre' in cmd
and len(cmd
['pre']) > 0:
332 expect('ceph {0}'.format(cmd
['pre']), 0)
333 expect('ceph -n {cn} -k {k} {c} {arg_val}'.format(
334 cn
=cname
,k
=k
,c
=cmd_cmd
,arg_val
=cmd_args_val
), expect_ret
)
335 if 'post' in cmd
and len(cmd
['post']) > 0:
336 expect('ceph {0}'.format(cmd
['post']), 0)
346 k
= keyring_base
+ '.misc'
348 'ceph auth get-or-create client.caps mon \'allow command "auth caps"' \
349 ' with entity="client.caps"\'', 0, k
)
350 expect('ceph -n client.caps -k {kf} mon_status'.format(kf
=k
), errno
.EACCES
)
351 expect('ceph -n client.caps -k {kf} auth caps client.caps mon \'allow *\''.format(kf
=k
), 0)
352 expect('ceph -n client.caps -k {kf} mon_status'.format(kf
=k
), 0)
365 if __name__
== '__main__':