diff --git a/library/ceph_key.py b/library/ceph_key.py index b566ee63f..60df45edd 100644 --- a/library/ceph_key.py +++ b/library/ceph_key.py @@ -138,7 +138,7 @@ caps: secret: AQAin8tUMICVFBAALRHNrV0Z4MXupRw4v9JQ6Q== caps: mon: allow * - dest: "/var/lib/ceph/tmp/keyring.mon" + dest: "/var/lib/ceph/tmp/" import_key: False - name: create cephx key @@ -268,13 +268,10 @@ def generate_ceph_authtool_cmd(cluster, name, secret, caps, auid, dest, containe Generate 'ceph-authtool' command line to execute ''' - file_destination = os.path.join( - dest + "/" + cluster + "." + name + ".keyring") - cmd = [ 'ceph-authtool', '--create-keyring', - file_destination, + dest, '--name', name, '--add-key', @@ -297,12 +294,10 @@ def create_key(module, result, cluster, name, secret, caps, import_key, auid, de Create a CephX key ''' - file_path = os.path.join(dest + "/" + cluster + "." + name + ".keyring") - args = [ 'import', '-i', - file_path, + dest, ] cmd_list = [] @@ -366,6 +361,29 @@ def delete_key(cluster, name, containerized=None): return cmd_list +def get_key(cluster, name, dest, containerized=None): + ''' + Get a CephX key (write on the filesystem) + ''' + + cmd_list = [] + + args = [ + 'get', + name, + '-o', + dest, + ] + + user = "client.admin" + user_key = os.path.join( + "/etc/ceph/" + cluster + ".client.admin.keyring") + cmd_list.append(generate_ceph_cmd( + cluster, args, user, user_key, containerized)) + + return cmd_list + + def info_key(cluster, name, user, user_key, output_format, containerized=None): ''' Get information about a CephX key @@ -478,7 +496,7 @@ def run_module(): secret=dict(type='str', required=False, default=None), import_key=dict(type='bool', required=False, default=True), auid=dict(type='str', required=False, default=None), - dest=dict(type='str', required=False, default='/etc/ceph/'), + dest=dict(type='str', required=False, default='/etc/ceph'), ) module = AnsibleModule( @@ -528,21 +546,30 @@ def run_module(): if not caps: fatal("Capabilities must be provided when state is 'present'", module) # noqa E501 + # Build a different path for bootstrap keys as there are stored as + # /var/lib/ceph/bootstrap-rbd/ceph.keyring + if 'bootstrap' in dest: + file_path = os.path.join(dest + "/" + cluster + ".keyring") + else: + file_path = os.path.join(dest + "/" + cluster + + "." + name + ".keyring") + # We allow 'present' to override any existing key # ONLY if a secret is provided # if not we skip the creation if import_key: if rc == 0 and not secret: - result["stdout"] = "skipped, since {0} already exists, if you want to update a key use 'state: update'".format( # noqa E501 - name) + # If the key exists in Ceph we must fetch it on the system + # because nothing tells us it exists on the fs or not + rc, cmd, out, err = exec_commands(module, get_key(cluster, name, file_path, containerized)) # noqa E501 + result["stdout"] = "skipped, since {0} already exists, we only fetched the key at {1}. If you want to update a key use 'state: update'".format( # noqa E501 + name, file_path) result['rc'] = rc module.exit_json(**result) rc, cmd, out, err = exec_commands(module, create_key( - module, result, cluster, name, secret, caps, import_key, auid, dest, containerized)) # noqa E501 + module, result, cluster, name, secret, caps, import_key, auid, file_path, containerized)) # noqa E501 - file_path = os.path.join( - dest + "/" + cluster + "." + name + ".keyring") file_args = module.load_file_common_arguments(module.params) file_args['path'] = file_path module.set_fs_attributes_if_different(file_args, False) @@ -557,6 +584,8 @@ def run_module(): rc, cmd, out, err = exec_commands( module, update_key(cluster, name, caps, containerized)) + # After the update we don't need to overwrite the key on the filesystem + # since the secret has not changed elif state == "absent": rc, cmd, out, err = exec_commands( @@ -625,6 +654,10 @@ def run_module(): module, info_cmd) # noqa E501 # apply ceph:ceph ownership and mode 0400 on keys + # FIXME by using + # file_args = module.load_file_common_arguments(module.params) + # file_args['path'] = dest + # module.set_fs_attributes_if_different(file_args, False) try: os.chown(key_path, ceph_uid, ceph_grp) os.chmod(key_path, stat.S_IRUSR) diff --git a/library/test_ceph_key.py b/library/test_ceph_key.py index 113c1d5d4..b8761fac3 100644 --- a/library/test_ceph_key.py +++ b/library/test_ceph_key.py @@ -120,7 +120,7 @@ class TestCephKeyModule(object): 'allow rwx', ] result = ceph_key.generate_ceph_authtool_cmd( - fake_cluster, fake_name, fake_secret, fake_caps, fake_auid, fake_dest) # noqa E501 + fake_cluster, fake_name, fake_secret, fake_caps, fake_auid, fake_file_destination) # noqa E501 assert result == expected_command_list def test_generate_ceph_authtool_cmd_non_container_auid(self): @@ -153,7 +153,7 @@ class TestCephKeyModule(object): 'allow rwx', ] result = ceph_key.generate_ceph_authtool_cmd( - fake_cluster, fake_name, fake_secret, fake_caps, fake_auid, fake_dest) # noqa E501 + fake_cluster, fake_name, fake_secret, fake_caps, fake_auid, fake_file_destination) # noqa E501 assert result == expected_command_list def test_generate_ceph_authtool_cmd_container(self): @@ -189,7 +189,7 @@ class TestCephKeyModule(object): 'allow rwx' ] result = ceph_key.generate_ceph_authtool_cmd( - fake_cluster, fake_name, fake_secret, fake_caps, fake_auid, fake_dest, fake_containerized) # noqa E501 + fake_cluster, fake_name, fake_secret, fake_caps, fake_auid, fake_file_destination, fake_containerized) # noqa E501 assert result == expected_command_list def test_create_key_non_container(self): @@ -214,7 +214,7 @@ class TestCephKeyModule(object): 'import', '-i', fake_file_destination], ] result = ceph_key.create_key(fake_module, fake_result, fake_cluster, - fake_name, fake_secret, fake_caps, fake_import_key, fake_auid, fake_dest) # noqa E501 + fake_name, fake_secret, fake_caps, fake_import_key, fake_auid, fake_file_destination) # noqa E501 assert result == expected_command_list def test_create_key_container(self): @@ -240,7 +240,7 @@ class TestCephKeyModule(object): fake_cluster, 'auth', 'import', '-i', fake_file_destination], ] result = ceph_key.create_key(fake_module, fake_result, fake_cluster, fake_name, # noqa E501 - fake_secret, fake_caps, fake_import_key, fake_auid, fake_dest, fake_containerized) # noqa E501 + fake_secret, fake_caps, fake_import_key, fake_auid, fake_file_destination, fake_containerized) # noqa E501 assert result == expected_command_list def test_create_key_non_container_no_import(self): @@ -275,7 +275,7 @@ class TestCephKeyModule(object): 'allow rwx', ] ] result = ceph_key.create_key(fake_module, fake_result, fake_cluster, - fake_name, fake_secret, fake_caps, fake_import_key, fake_auid, fake_dest) # noqa E501 + fake_name, fake_secret, fake_caps, fake_import_key, fake_auid, fake_file_destination) # noqa E501 assert result == expected_command_list def test_create_key_container_no_import(self): @@ -315,7 +315,7 @@ class TestCephKeyModule(object): 'allow rwx', ] ] result = ceph_key.create_key(fake_module, fake_result, fake_cluster, fake_name, # noqa E501 - fake_secret, fake_caps, fake_import_key, fake_auid, fake_dest, fake_containerized) # noqa E501 + fake_secret, fake_caps, fake_import_key, fake_auid, fake_file_destination, fake_containerized) # noqa E501 assert result == expected_command_list def test_update_key_non_container(self): @@ -410,6 +410,35 @@ class TestCephKeyModule(object): result = ceph_key.list_keys(fake_cluster, fake_user, fake_key) assert result == expected_command_list + def test_get_key_container(self): + fake_cluster = "fake" + fake_name = "client.fake" + fake_containerized = "docker exec -ti ceph-mon" + fake_dest = "/fake/ceph" + fake_file_destination = os.path.join( + fake_dest + "/" + fake_cluster + "." + fake_name + ".keyring") + expected_command_list = [ + ['docker', 'exec', '-ti', 'ceph-mon', 'ceph', '-n', "client.admin", '-k', "/etc/ceph/fake.client.admin.keyring", '--cluster', # noqa E501 + fake_cluster, 'auth', 'get', fake_name, '-o', fake_file_destination], # noqa E501 + ] + result = ceph_key.get_key( + fake_cluster, fake_name, fake_file_destination, fake_containerized) # noqa E501 + assert result == expected_command_list + + def test_get_key_non_container(self): + fake_cluster = "fake" + fake_dest = "/fake/ceph" + fake_name = "client.fake" + fake_file_destination = os.path.join( + fake_dest + "/" + fake_cluster + "." + fake_name + ".keyring") + expected_command_list = [ + ['ceph', '-n', "client.admin", '-k', "/etc/ceph/fake.client.admin.keyring", # noqa E501 + '--cluster', fake_cluster, 'auth', 'get', fake_name, '-o', fake_file_destination], # noqa E501 + ] + result = ceph_key.get_key( + fake_cluster, fake_name, fake_file_destination) # noqa E501 + assert result == expected_command_list + def test_list_key_non_container_with_mon_key(self): fake_hostname = "mon01" fake_cluster = "fake"