Skip to content

Commit

Permalink
ceph_key: support using different keyring
Browse files Browse the repository at this point in the history
Currently the `ceph_key` module doesn't support using a different
keyring than `client.admin`.
This commit adds the possibility to use a different keyring.

Usage:
```
      ceph_key:
        name: "client.rgw.myrgw-node.rgw123"
        cluster: "ceph"
        user: "client.bootstrap-rgw"
        user_key: /var/lib/ceph/bootstrap-rgw/ceph.keyring
        dest: "/var/lib/ceph/radosgw/ceph-rgw.myrgw-node.rgw123/keyring"
        caps:
          osd: 'allow rwx'
          mon: 'allow rw'
          import_key: False
        owner: "ceph"
        group: "ceph"
        mode: "0400"
```

Where:
`user` corresponds to `-n (--name)`
`user_key` corresponds to `-k (--keyring)`

Signed-off-by: Guillaume Abrioux <gabrioux@redhat.com>
(cherry picked from commit 12e6260)
  • Loading branch information
guits authored and dsavineau committed Dec 1, 2020
1 parent 63aa195 commit 18b34a5
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 74 deletions.
104 changes: 59 additions & 45 deletions library/ceph_key.py
Expand Up @@ -47,6 +47,16 @@
description:
- name of the CephX key
required: true
user:
description:
- entity used to perform operation.
It corresponds to the -n option (--name)
required: false
user_key:
description:
- the path to the keyring corresponding to the
user being used.
It corresponds to the -k option (--keyring)
state:
description:
- If 'present' is used, the module creates a keyring
Expand Down Expand Up @@ -131,6 +141,8 @@
- name: create cephx key
ceph_key:
name: "{{ keys_to_create }}"
user: client.bootstrap-rgw
user_key: /var/lib/ceph/bootstrap-rgw/ceph.keyring
state: present
caps: "{{ caps }}"
Expand Down Expand Up @@ -244,24 +256,26 @@ def generate_secret():
return secret


def generate_caps(cmd, _type, caps):
def generate_caps(_type, caps):
'''
Generate CephX capabilities list
'''

caps_cli = []

for k, v in caps.items():
# makes sure someone didn't pass an empty var,
# we don't want to add an empty cap
if len(k) == 0:
continue
if _type == "ceph-authtool":
cmd.extend(["--cap"])
cmd.extend([k, v])
caps_cli.extend(["--cap"])
caps_cli.extend([k, v])

return cmd
return caps_cli


def generate_ceph_cmd(cluster, args, user, user_key, container_image=None):
def generate_ceph_cmd(cluster, args, user, user_key_path, container_image=None):
'''
Generate 'ceph' command line to execute
'''
Expand All @@ -278,7 +292,7 @@ def generate_ceph_cmd(cluster, args, user, user_key, container_image=None):
'-n',
user,
'-k',
user_key,
user_key_path,
'--cluster',
cluster,
'auth',
Expand Down Expand Up @@ -312,40 +326,38 @@ def generate_ceph_authtool_cmd(cluster, name, secret, caps, dest, container_imag
]

cmd.extend(base_cmd)
cmd = generate_caps(cmd, "ceph-authtool", caps)
cmd.extend(generate_caps("ceph-authtool", caps))

return cmd


def create_key(module, result, cluster, name, secret, caps, import_key, dest, container_image=None): # noqa E501
def create_key(module, result, cluster, user, user_key_path, name, secret, caps, import_key, dest, container_image=None): # noqa E501
'''
Create a CephX key
'''

args = [
'import',
'-i',
dest,
]
cmd_list = []

if not secret:
secret = generate_secret()

if user == 'client.admin':
args = ['import', '-i', dest]
else:
args = ['get-or-create', name]
args.extend(generate_caps(None, caps))
args.extend(['-o', dest])

cmd_list.append(generate_ceph_authtool_cmd(
cluster, name, secret, caps, dest, container_image))

if import_key:
user = "client.admin"
keyring_filename = cluster + "." + user + ".keyring"
user_key = os.path.join("/etc/ceph/", keyring_filename)
if import_key or user != 'client.admin':
cmd_list.append(generate_ceph_cmd(
cluster, args, user, user_key, container_image))
cluster, args, user, user_key_path, container_image))

return cmd_list


def delete_key(cluster, name, container_image=None):
def delete_key(cluster, user, user_key_path, name, container_image=None):
'''
Delete a CephX key
'''
Expand All @@ -357,16 +369,13 @@ def delete_key(cluster, name, container_image=None):
name,
]

user = "client.admin"
keyring_filename = cluster + "." + user + ".keyring"
user_key = os.path.join("/etc/ceph/", keyring_filename)
cmd_list.append(generate_ceph_cmd(
cluster, args, user, user_key, container_image))
cluster, args, user, user_key_path, container_image))

return cmd_list


def get_key(cluster, name, dest, container_image=None):
def get_key(cluster, user, user_key_path, name, dest, container_image=None):
'''
Get a CephX key (write on the filesystem)
'''
Expand All @@ -380,16 +389,13 @@ def get_key(cluster, name, dest, container_image=None):
dest,
]

user = "client.admin"
keyring_filename = cluster + "." + user + ".keyring"
user_key = os.path.join("/etc/ceph/", keyring_filename)
cmd_list.append(generate_ceph_cmd(
cluster, args, user, user_key, container_image))
cluster, args, user, user_key_path, container_image))

return cmd_list


def info_key(cluster, name, user, user_key, output_format, container_image=None): # noqa E501
def info_key(cluster, name, user, user_key_path, output_format, container_image=None): # noqa E501
'''
Get information about a CephX key
'''
Expand All @@ -404,12 +410,12 @@ def info_key(cluster, name, user, user_key, output_format, container_image=None)
]

cmd_list.append(generate_ceph_cmd(
cluster, args, user, user_key, container_image))
cluster, args, user, user_key_path, container_image))

return cmd_list


def list_keys(cluster, user, user_key, container_image=None):
def list_keys(cluster, user, user_key_path, container_image=None):
'''
List all CephX keys
'''
Expand All @@ -423,7 +429,7 @@ def list_keys(cluster, user, user_key, container_image=None):
]

cmd_list.append(generate_ceph_cmd(
cluster, args, user, user_key, container_image))
cluster, args, user, user_key_path, container_image))

return cmd_list

Expand Down Expand Up @@ -505,6 +511,8 @@ def run_module():
secret=dict(type='str', required=False, default=None, no_log=True),
import_key=dict(type='bool', required=False, default=True),
dest=dict(type='str', required=False, default='/etc/ceph/'),
user=dict(type='str', required=False, default='client.admin'),
user_key=dict(type='str', required=False, default=None)
)

module = AnsibleModule(
Expand All @@ -523,6 +531,8 @@ def run_module():
secret = module.params.get('secret')
import_key = module.params.get('import_key')
dest = module.params.get('dest')
user = module.params.get('user')
user_key = module.params.get('user_key')

changed = False

Expand Down Expand Up @@ -551,9 +561,13 @@ def run_module():
_caps = caps
key_exist = 1

user = "client.admin"
keyring_filename = cluster + '.' + user + '.keyring'
user_key = os.path.join("/etc/ceph/", keyring_filename)
if not user_key:
user_key_filename = '{}.{}.keyring'.format(cluster, user)
user_key_dir = '/etc/ceph'
user_key_path = os.path.join(user_key_dir, user_key_filename)
else:
user_key_path = user_key

output_format = "json"

if (state in ["present", "update"]):
Expand All @@ -575,7 +589,7 @@ def run_module():
if import_key:
_info_key = []
rc, cmd, out, err = exec_commands(
module, info_key(cluster, name, user, user_key, output_format, container_image)) # noqa E501
module, info_key(cluster, name, user, user_key_path, output_format, container_image)) # noqa E501
key_exist = rc
if not caps and key_exist != 0:
fatal("Capabilities must be provided when state is 'present'", module) # noqa E501
Expand All @@ -591,7 +605,7 @@ def run_module():
_caps = _info_key[0]['caps']
if secret == _secret and caps == _caps:
if not os.path.isfile(file_path):
rc, cmd, out, err = exec_commands(module, get_key(cluster, name, file_path, container_image)) # noqa E501
rc, cmd, out, err = exec_commands(module, get_key(cluster, user, user_key_path, name, file_path, container_image)) # noqa E501
result["rc"] = rc
if rc != 0:
result["stdout"] = "Couldn't fetch the key {0} at {1}.".format(name, file_path) # noqa E501
Expand All @@ -609,7 +623,7 @@ def run_module():
module.exit_json(**result)
if (key_exist == 0 and (secret != _secret or caps != _caps)) or key_exist != 0:
rc, cmd, out, err = exec_commands(module, create_key(
module, result, cluster, name, secret, caps, import_key, file_path, container_image)) # noqa E501
module, result, cluster, user, user_key_path, name, secret, caps, import_key, file_path, container_image)) # noqa E501
if rc != 0:
result["stdout"] = "Couldn't create or update {0}".format(name)
result["stderr"] = err
Expand All @@ -620,31 +634,31 @@ def run_module():
elif state == "absent":
if key_exist == 0:
rc, cmd, out, err = exec_commands(
module, delete_key(cluster, name, container_image))
module, delete_key(cluster, user, user_key_path, name, container_image))
if rc == 0:
changed = True
else:
rc = 0

elif state == "info":
rc, cmd, out, err = exec_commands(
module, info_key(cluster, name, user, user_key, output_format, container_image)) # noqa E501
module, info_key(cluster, name, user, user_key_path, output_format, container_image)) # noqa E501
if rc != 0:
result["stdout"] = "skipped, since {0} does not exist".format(name)
result['rc'] = 0
module.exit_json(**result)

elif state == "list":
rc, cmd, out, err = exec_commands(
module, list_keys(cluster, user, user_key, container_image))
module, list_keys(cluster, user, user_key_path, container_image))

elif state == "fetch_initial_keys":
hostname = socket.gethostname().split('.', 1)[0]
user = "mon."
keyring_filename = cluster + "-" + hostname + "/keyring"
user_key = os.path.join("/var/lib/ceph/mon/", keyring_filename)
user_key_path = os.path.join("/var/lib/ceph/mon/", keyring_filename)
rc, cmd, out, err = exec_commands(
module, list_keys(cluster, user, user_key, container_image))
module, list_keys(cluster, user, user_key_path, container_image))
if rc != 0:
result["stdout"] = "failed to retrieve ceph keys"
result["sdterr"] = err
Expand All @@ -669,7 +683,7 @@ def run_module():
]

info_cmd = info_key(cluster, entity, user,
user_key, output_format, container_image)
user_key_path, output_format, container_image)
# we use info_cmd[0] because info_cmd is an array made of an array
info_cmd[0].extend(extra_args)
rc, cmd, out, err = exec_commands(
Expand Down

0 comments on commit 18b34a5

Please sign in to comment.