]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ansible.git/commitdiff
ceph_key: add a get_key function
authorSébastien Han <seb@redhat.com>
Wed, 21 Nov 2018 15:17:04 +0000 (16:17 +0100)
committerGuillaume Abrioux <gabrioux@redhat.com>
Mon, 26 Nov 2018 17:22:20 +0000 (18:22 +0100)
When checking if a key exists we also have to ensure that the key exists
on the filesystem, the key can change on Ceph but still have an outdated
version on the filesystem. This solves this issue.

Signed-off-by: Sébastien Han <seb@redhat.com>
library/ceph_key.py
library/test_ceph_key.py

index b566ee63f391d17cfc69e4da1037aba4bf0cefee..60df45edd6e6fcf99d4b0aef4b4d2895ea43d6ce 100644 (file)
@@ -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)
index 113c1d5d445568dd598aeada7c4c9d0c13a269c0..b8761fac3b3df5a394cf718d44a29e17e21af2ee 100644 (file)
@@ -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"