ceph_key: add a get_key function

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>
pull/3348/head
Sébastien Han 2018-11-21 16:17:04 +01:00 committed by Guillaume Abrioux
parent c14f9b78ff
commit 691f373543
2 changed files with 83 additions and 21 deletions

View 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)

View 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"