From: Sage Weil Date: Tue, 26 Oct 2021 17:30:36 +0000 (-0400) Subject: mgr/cephadm: add daemon 'rotate-key' action X-Git-Tag: v18.0.0~39^2~10 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8ca919f3cf3c0a172e44b90f3c52baae67f021f7;p=ceph.git mgr/cephadm: add daemon 'rotate-key' action Caveats: - only works with osd, mds, mgr so far - sometimes we have to restart the daemon Signed-off-by: Sage Weil --- diff --git a/src/pybind/mgr/cephadm/inventory.py b/src/pybind/mgr/cephadm/inventory.py index 04385a4fa81c..149ee1238409 100644 --- a/src/pybind/mgr/cephadm/inventory.py +++ b/src/pybind/mgr/cephadm/inventory.py @@ -1236,6 +1236,7 @@ class HostCache(): 'reconfig': 3, 'redeploy': 4, 'stop': 5, + 'rotate-key': 6, } existing_action = self.scheduled_daemon_actions.get(host, {}).get(daemon_name, None) if existing_action and priorities[existing_action] > priorities[action]: diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index e3d90f13aebd..2c0e7068bd53 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -1989,6 +1989,52 @@ Then run the following: for dd in dds ] + def _rotate_daemon_key(self, daemon_spec: CephadmDaemonDeploySpec) -> str: + self.log.info(f'Rotating authentication key for {daemon_spec.name()}') + rc, out, err = self.mon_command({ + 'prefix': 'auth get-or-create-pending', + 'entity': daemon_spec.name(), + 'format': 'json', + }) + j = json.loads(out) + pending_key = j[0]['pending_key'] + + # deploy a new keyring file + if daemon_spec.daemon_type != 'osd': + daemon_spec = self.cephadm_services[daemon_type_to_service( + daemon_spec.daemon_type)].prepare_create(daemon_spec) + CephadmServe(self)._create_daemon(daemon_spec, reconfig=True) + + # try to be clever, or fall back to restarting the daemon + rc = -1 + if daemon_spec.daemon_type == 'osd': + rc, out, err = self.tool_exec( + args=['ceph', 'tell', daemon_spec.name(), 'rotate-stored-key', '-i', '-'], + stdin=pending_key.encode() + ) + if not rc: + rc, out, err = self.tool_exec( + args=['ceph', 'tell', daemon_spec.name(), 'rotate-key', '-i', '-'], + stdin=pending_key.encode() + ) + elif daemon_spec.daemon_type == 'mds': + rc, out, err = self.tool_exec( + args=['ceph', 'tell', daemon_spec.name(), 'rotate-key', '-i', '-'], + stdin=pending_key.encode() + ) + elif ( + daemon_spec.daemon_type == 'mgr' + and daemon_spec.daemon_id == self.get_mgr_id() + ): + rc, out, err = self.tool_exec( + args=['ceph', 'tell', daemon_spec.name(), 'rotate-key', '-i', '-'], + stdin=pending_key.encode() + ) + if rc: + self._daemon_action(daemon_spec, 'restart') + + return f'Rotated key for {daemon_spec.name()}' + def _daemon_action(self, daemon_spec: CephadmDaemonDeploySpec, action: str, @@ -2001,6 +2047,9 @@ Then run the following: self.mgr_service.fail_over() return '' # unreachable + if action == 'rotate-key': + return self._rotate_daemon_key(daemon_spec) + if action == 'redeploy' or action == 'reconfig': if daemon_spec.daemon_type != 'osd': daemon_spec = self.cephadm_services[daemon_type_to_service( @@ -2057,6 +2106,12 @@ Then run the following: raise OrchestratorError( f'Unable to schedule redeploy for {daemon_name}: No standby MGRs') + if action == 'rotate-key': + if d.daemon_type not in ['mgr', 'osd', 'mds']: + raise OrchestratorError( + f'key rotation not supported for {d.daemon_type}' + ) + self._daemon_action_set_image(action, image, d.daemon_type, d.daemon_id) self.log.info(f'Schedule {action} daemon {daemon_name}') diff --git a/src/pybind/mgr/orchestrator/module.py b/src/pybind/mgr/orchestrator/module.py index fe975ff0c3dc..1fd9eebd9b94 100644 --- a/src/pybind/mgr/orchestrator/module.py +++ b/src/pybind/mgr/orchestrator/module.py @@ -74,6 +74,7 @@ class ServiceAction(enum.Enum): restart = 'restart' redeploy = 'redeploy' reconfig = 'reconfig' + rotate_key = 'rotate-key' class DaemonAction(enum.Enum): @@ -81,6 +82,7 @@ class DaemonAction(enum.Enum): stop = 'stop' restart = 'restart' reconfig = 'reconfig' + rotate_key = 'rotate-key' def to_format(what: Any, format: Format, many: bool, cls: Any) -> Any: @@ -1008,7 +1010,7 @@ Usage: @_cli_write_command('orch daemon') def _daemon_action(self, action: DaemonAction, name: str) -> HandleCommandResult: - """Start, stop, restart, (redeploy,) or reconfig a specific daemon""" + """Start, stop, restart, redeploy, reconfig, or rotate-key for a specific daemon""" if '.' not in name: raise OrchestratorError('%s is not a valid daemon name' % name) completion = self.daemon_action(action.value, name) @@ -1019,7 +1021,7 @@ Usage: def _daemon_action_redeploy(self, name: str, image: Optional[str] = None) -> HandleCommandResult: - """Redeploy a daemon (with a specifc image)""" + """Redeploy a daemon (with a specific image)""" if '.' not in name: raise OrchestratorError('%s is not a valid daemon name' % name) completion = self.daemon_action("redeploy", name, image=image)