X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fqa%2Fworkunits%2Fmon%2Fcaps.py;fp=src%2Fceph%2Fqa%2Fworkunits%2Fmon%2Fcaps.py;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=65a695641c6b23685b9b7421128a317bf92559c0;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/qa/workunits/mon/caps.py b/src/ceph/qa/workunits/mon/caps.py deleted file mode 100644 index 65a6956..0000000 --- a/src/ceph/qa/workunits/mon/caps.py +++ /dev/null @@ -1,366 +0,0 @@ -#!/usr/bin/python - -import json -import subprocess -import shlex -from StringIO import StringIO -import errno -import sys -import os -import io -import re - - -import rados -from ceph_argparse import * - -keyring_base = '/tmp/cephtest-caps.keyring' - -class UnexpectedReturn(Exception): - def __init__(self, cmd, ret, expected, msg): - if isinstance(cmd, list): - self.cmd = ' '.join(cmd) - else: - assert isinstance(cmd, str) or isinstance(cmd, unicode), \ - 'cmd needs to be either a list or a str' - self.cmd = cmd - self.cmd = str(self.cmd) - self.ret = int(ret) - self.expected = int(expected) - self.msg = str(msg) - - def __str__(self): - return repr('{c}: expected return {e}, got {r} ({o})'.format( - c=self.cmd, e=self.expected, r=self.ret, o=self.msg)) - -def call(cmd): - if isinstance(cmd, list): - args = cmd - elif isinstance(cmd, str) or isinstance(cmd, unicode): - args = shlex.split(cmd) - else: - assert False, 'cmd is not a string/unicode nor a list!' - - print 'call: {0}'.format(args) - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - ret = proc.wait() - - return (ret, proc) - -def expect(cmd, expected_ret): - - try: - (r, p) = call(cmd) - except ValueError as e: - print >> sys.stderr, \ - 'unable to run {c}: {err}'.format(c=repr(cmd), err=e.message) - return errno.EINVAL - - assert r == p.returncode, \ - 'wth? r was supposed to match returncode!' - - if r != expected_ret: - raise UnexpectedReturn(repr(cmd), r, expected_ret, str(p.stderr.read())) - - return p - -def expect_to_file(cmd, expected_ret, out_file, mode='a'): - - # Let the exception be propagated to the caller - p = expect(cmd, expected_ret) - assert p.returncode == expected_ret, \ - 'expected result doesn\'t match and no exception was thrown!' - - with io.open(out_file, mode) as file: - file.write(unicode(p.stdout.read())) - - return p - -class Command: - def __init__(self, cid, j): - self.cid = cid[3:] - self.perms = j['perm'] - self.module = j['module'] - - self.sig = '' - self.args = [] - for s in j['sig']: - if not isinstance(s, dict): - assert isinstance(s, str) or isinstance(s,unicode), \ - 'malformatted signature cid {0}: {1}\n{2}'.format(cid,s,j) - if len(self.sig) > 0: - self.sig += ' ' - self.sig += s - else: - self.args.append(s) - - def __str__(self): - return repr('command {0}: {1} (requires \'{2}\')'.format(self.cid,\ - self.sig, self.perms)) - - -def destroy_keyring(path): - if not os.path.exists(path): - raise Exception('oops! cannot remove inexistent keyring {0}'.format(path)) - - # grab all client entities from the keyring - entities = [m.group(1) for m in [re.match(r'\[client\.(.*)\]', l) - for l in [str(line.strip()) - for line in io.open(path,'r')]] if m is not None] - - # clean up and make sure each entity is gone - for e in entities: - expect('ceph auth del client.{0}'.format(e), 0) - expect('ceph auth get client.{0}'.format(e), errno.ENOENT) - - # remove keyring - os.unlink(path) - - return True - -def test_basic_auth(): - # make sure we can successfully add/del entities, change their caps - # and import/export keyrings. - - expect('ceph auth add client.basicauth', 0) - expect('ceph auth caps client.basicauth mon \'allow *\'', 0) - # entity exists and caps do not match - expect('ceph auth add client.basicauth', errno.EINVAL) - # this command attempts to change an existing state and will fail - expect('ceph auth add client.basicauth mon \'allow w\'', errno.EINVAL) - expect('ceph auth get-or-create client.basicauth', 0) - expect('ceph auth get-key client.basicauth', 0) - expect('ceph auth get-or-create client.basicauth2', 0) - # cleanup - expect('ceph auth del client.basicauth', 0) - expect('ceph auth del client.basicauth2', 0) - - return True - -def gen_module_keyring(module): - module_caps = [ - ('all', '{t} \'allow service {s} rwx\'', 0), - ('none', '', errno.EACCES), - ('wrong', '{t} \'allow service foobar rwx\'', errno.EACCES), - ('right', '{t} \'allow service {s} {p}\'', 0), - ('no-execute', '{t} \'allow service {s} x\'', errno.EACCES) - ] - - keyring = '{0}.service-{1}'.format(keyring_base,module) - for perms in 'r rw x'.split(): - for (n,p,r) in module_caps: - c = p.format(t='mon', s=module, p=perms) - expect_to_file( - 'ceph auth get-or-create client.{cn}-{cp} {caps}'.format( - cn=n,cp=perms,caps=c), 0, keyring) - - return keyring - - -def test_all(): - - - perms = { - 'good': { - 'broad':[ - ('rwx', 'allow *'), - ('r', 'allow r'), - ('rw', 'allow rw'), - ('x', 'allow x'), - ], - 'service':[ - ('rwx', 'allow service {s} rwx'), - ('r', 'allow service {s} r'), - ('rw', 'allow service {s} rw'), - ('x', 'allow service {s} x'), - ], - 'command':[ - ('rwx', 'allow command "{c}"'), - ], - 'command-with':[ - ('rwx', 'allow command "{c}" with {kv}') - ], - 'command-with-prefix':[ - ('rwx', 'allow command "{c}" with {key} prefix {val}') - ] - }, - 'bad': { - 'broad':[ - ('none', ''), - ], - 'service':[ - ('none1', 'allow service foo rwx'), - ('none2', 'allow service foo r'), - ('none3', 'allow service foo rw'), - ('none4', 'allow service foo x'), - ], - 'command':[ - ('none', 'allow command foo'), - ], - 'command-with':[ - ('none', 'allow command "{c}" with foo=bar'), - ], - 'command-with-prefix':[ - ('none', 'allow command "{c}" with foo prefix bar'), - ], - } - } - - cmds = { - '':[ - { - 'cmd':('status', '', 'r') - }, - { - 'pre':'heap start_profiler', - 'cmd':('heap', 'heapcmd=stats', 'rw'), - 'post':'heap stop_profiler' - } - ], - 'auth':[ - { - 'pre':'', - 'cmd':('auth ls', '', 'r'), - 'post':'' - }, - { - 'pre':'auth get-or-create client.foo mon \'allow *\'', - 'cmd':('auth caps', 'entity="client.foo"', 'rw'), - 'post':'auth del client.foo' - } - ], - 'pg':[ - { - 'cmd':('pg getmap', '', 'r'), - }, - ], - 'mds':[ - { - 'cmd':('mds getmap', '', 'r'), - }, - { - 'cmd':('mds cluster_down', '', 'rw'), - 'post':'mds cluster_up' - }, - ], - 'mon':[ - { - 'cmd':('mon getmap', '', 'r') - }, - { - 'cmd':('mon remove', 'name=a', 'rw') - } - ], - 'osd':[ - { - 'cmd':('osd getmap', '', 'r'), - }, - { - 'cmd':('osd pause', '', 'rw'), - 'post':'osd unpause' - }, - { - 'cmd':('osd crush dump', '', 'r') - }, - ], - 'config-key':[ - { - 'pre':'config-key set foo bar', - 'cmd':('config-key get', 'key=foo', 'r') - }, - { - 'pre':'config-key set foo bar', - 'cmd':('config-key del', 'key=foo', 'rw') - } - ] - } - - for (module,cmd_lst) in cmds.iteritems(): - k = keyring_base + '.' + module - for cmd in cmd_lst: - - (cmd_cmd, cmd_args, cmd_perm) = cmd['cmd'] - cmd_args_key = '' - cmd_args_val = '' - if len(cmd_args) > 0: - (cmd_args_key, cmd_args_val) = cmd_args.split('=') - - print 'generating keyring for {m}/{c}'.format(m=module,c=cmd_cmd) - # gen keyring - for (good_or_bad,kind_map) in perms.iteritems(): - for (kind,lst) in kind_map.iteritems(): - for (perm, cap) in lst: - cap_formatted = cap.format( - s=module, - c=cmd_cmd, - kv=cmd_args, - key=cmd_args_key, - val=cmd_args_val) - - if len(cap_formatted) == 0: - run_cap = '' - else: - run_cap = 'mon \'{fc}\''.format(fc=cap_formatted) - - cname = 'client.{gb}-{kind}-{p}'.format( - gb=good_or_bad,kind=kind,p=perm) - expect_to_file( - 'ceph auth get-or-create {n} {c}'.format( - n=cname,c=run_cap), 0, k) - # keyring generated - print 'testing {m}/{c}'.format(m=module,c=cmd_cmd) - - # test - for good_bad in perms.iterkeys(): - for (kind,lst) in perms[good_bad].iteritems(): - for (perm,_) in lst: - cname = 'client.{gb}-{k}-{p}'.format(gb=good_bad,k=kind,p=perm) - - if good_bad == 'good': - expect_ret = 0 - else: - expect_ret = errno.EACCES - - if ( cmd_perm not in perm ): - expect_ret = errno.EACCES - if 'with' in kind and len(cmd_args) == 0: - expect_ret = errno.EACCES - if 'service' in kind and len(module) == 0: - expect_ret = errno.EACCES - - if 'pre' in cmd and len(cmd['pre']) > 0: - expect('ceph {0}'.format(cmd['pre']), 0) - expect('ceph -n {cn} -k {k} {c} {arg_val}'.format( - cn=cname,k=k,c=cmd_cmd,arg_val=cmd_args_val), expect_ret) - if 'post' in cmd and len(cmd['post']) > 0: - expect('ceph {0}'.format(cmd['post']), 0) - # finish testing - destroy_keyring(k) - - - return True - - -def test_misc(): - - k = keyring_base + '.misc' - expect_to_file( - 'ceph auth get-or-create client.caps mon \'allow command "auth caps"' \ - ' with entity="client.caps"\'', 0, k) - expect('ceph -n client.caps -k {kf} mon_status'.format(kf=k), errno.EACCES) - expect('ceph -n client.caps -k {kf} auth caps client.caps mon \'allow *\''.format(kf=k), 0) - expect('ceph -n client.caps -k {kf} mon_status'.format(kf=k), 0) - destroy_keyring(k) - -def main(): - - test_basic_auth() - test_all() - test_misc() - - print 'OK' - - return 0 - -if __name__ == '__main__': - main()