From: Daniel-Pivonka Date: Thu, 11 Jun 2020 14:28:44 +0000 (-0400) Subject: cephadm: add sudo ssh user option X-Git-Tag: wip-pdonnell-testing-20200918.022351~813^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=1052b9db7bdc50f61705e1f1331c5cbb20120586;p=ceph-ci.git cephadm: add sudo ssh user option add the ability to use a non-root users for connecting to hosts, this user requires pass wordless sudo access useful for clusters that have root ssh access disabled Fixes: https://tracker.ceph.com/issues/44866 Signed-off-by: Daniel-Pivonka --- diff --git a/doc/cephadm/install.rst b/doc/cephadm/install.rst index c172b903dab..3a1463a5605 100644 --- a/doc/cephadm/install.rst +++ b/doc/cephadm/install.rst @@ -105,6 +105,11 @@ or run ``cephadm bootstrap -h`` to see all available options: cluster by putting them in a standard ini-style configuration file and using the ``--config **`` option. +* You can choose the ssh user cephadm will use to connect to hosts by + using the ``--ssh-user **`` option. The ssh key will be added + to ``/home/**/.ssh/authorized_keys``. This user will require + passwordless sudo access. + Enable Ceph CLI =============== diff --git a/doc/cephadm/operations.rst b/doc/cephadm/operations.rst index d7f5ee7128e..198286a3a30 100644 --- a/doc/cephadm/operations.rst +++ b/doc/cephadm/operations.rst @@ -141,6 +141,21 @@ You will then need to restart the mgr daemon to reload the configuration with:: ceph mgr fail +Configuring a different SSH user +---------------------------------- + +Cephadm must be able to log into all the Ceph cluster nodes as an user +that has enough privileges to download container images, start containers +and execute commands without prompting for a password. If you do not want +to use the "root" user (default option in cephadm), you must provide +cephadm the name of the user that is going to be used to perform all the +cephadm operations. Use the command:: + + ceph cephadm set-user + +Prior to running this the cluster ssh key needs to be added to this users +authorized_keys file and non-root users must have passwordless sudo access. + Customizing the SSH configuration --------------------------------- diff --git a/doc/man/8/cephadm.rst b/doc/man/8/cephadm.rst index 39859554cbc..6c7ddb2508e 100644 --- a/doc/man/8/cephadm.rst +++ b/doc/man/8/cephadm.rst @@ -64,7 +64,8 @@ Synopsis | [--dashboard-crt DASHBOARD_CRT] | [--ssh-config SSH_CONFIG] | [--ssh-private-key SSH_PRIVATE_KEY] -| [--ssh-public-key SSH_PUBLIC_KEY] [--skip-mon-network] +| [--ssh-public-key SSH_PUBLIC_KEY] +| [--ssh-user SSH_USER] [--skip-mon-network] | [--skip-dashboard] [--dashboard-password-noupdate] | [--no-minimize-config] [--skip-ping-check] | [--skip-pull] [--skip-firewalld] [--allow-overwrite] @@ -206,6 +207,7 @@ Arguments: * [--ssh-config SSH_CONFIG] SSH config * [--ssh-private-key SSH_PRIVATE_KEY] SSH private key * [--ssh-public-key SSH_PUBLIC_KEY] SSH public key +* [--ssh-user SSH_USER] set user for SSHing to cluster hosts, passwordless sudo will be needed for non-root users' * [--skip-mon-network] set mon public_network based on bootstrap mon ip * [--skip-dashboard] do not enable the Ceph Dashboard * [--dashboard-password-noupdate] stop forced dashboard password change diff --git a/src/cephadm/cephadm b/src/cephadm/cephadm index 6aaf4938c03..1a62a61f639 100755 --- a/src/cephadm/cephadm +++ b/src/cephadm/cephadm @@ -46,6 +46,7 @@ import json import logging import os import platform +import pwd import random import re import select @@ -2668,6 +2669,8 @@ def command_bootstrap(): # ssh if not args.skip_ssh: + cli(['config-key', 'set', 'mgr/cephadm/ssh_user', args.ssh_user]) + logger.info('Enabling cephadm module...') cli(['mgr', 'module', 'enable', 'cephadm']) wait_for_mgr_restart() @@ -2699,11 +2702,21 @@ def command_bootstrap(): f.write(ssh_pub) logger.info('Wrote public SSH key to to %s' % args.output_pub_ssh_key) - logger.info('Adding key to root@localhost\'s authorized_keys...') - if not os.path.exists('/root/.ssh'): - os.mkdir('/root/.ssh', 0o700) - auth_keys_file = '/root/.ssh/authorized_keys' + logger.info('Adding key to %s@localhost\'s authorized_keys...' % args.ssh_user) + try: + s_pwd = pwd.getpwnam(args.ssh_user) + except KeyError as e: + raise Error('Cannot find uid/gid for ssh-user: %s' % (args.ssh_user)) + ssh_uid = s_pwd.pw_uid + ssh_gid = s_pwd.pw_gid + ssh_dir = os.path.join(s_pwd.pw_dir, '.ssh') + + if not os.path.exists(ssh_dir): + makedirs(ssh_dir, ssh_uid, ssh_gid, 0o700) + + auth_keys_file = '%s/authorized_keys' % ssh_dir add_newline = False + if os.path.exists(auth_keys_file): with open(auth_keys_file, 'r') as f: f.seek(0, os.SEEK_END) @@ -2711,7 +2724,9 @@ def command_bootstrap(): f.seek(f.tell()-1, os.SEEK_SET) # go to last char if f.read() != '\n': add_newline = True + with open(auth_keys_file, 'a') as f: + os.fchown(f.fileno(), ssh_uid, ssh_gid) # just in case we created it os.fchmod(f.fileno(), 0o600) # just in case we created it if add_newline: f.write('\n') @@ -2786,7 +2801,7 @@ def command_bootstrap(): ssh_key = '/etc/ceph/ceph.pub' if args.ssh_public_key: ssh_key = args.ssh_public_key.name - out, err, code = call_throws(['ssh-copy-id', '-f', '-i', ssh_key, 'root@%s' % split[1]]) + out, err, code = call_throws(['ssh-copy-id', '-f', '-i', ssh_key, '%s@%s' % (args.ssh_user, split[1])]) mounts = {} mounts[pathify(args.apply_spec)] = '/tmp/spec.yml:z' @@ -4645,6 +4660,10 @@ def _get_parser(): '--ssh-public-key', type=argparse.FileType('r'), help='SSH public key') + parser_bootstrap.add_argument( + '--ssh-user', + default='root', + help='set user for SSHing to cluster hosts, passwordless sudo will be needed for non-root users') parser_bootstrap.add_argument( '--skip-mon-network', diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index 793b8355d23..94c88425b3b 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -633,7 +633,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule): self._ssh_options = None if self.mode == 'root': - self.ssh_user = 'root' + self.ssh_user = self.get_store('ssh_user', default='root') elif self.mode == 'cephadm-package': self.ssh_user = 'cephadm' @@ -810,6 +810,30 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule): def _get_user(self): return 0, self.ssh_user, '' + @orchestrator._cli_read_command( + 'cephadm set-user', + 'name=user,type=CephString', + 'Set user for SSHing to cluster hosts, passwordless sudo will be needed for non-root users') + def set_ssh_user(self, user): + current_user = self.ssh_user + + self.set_store('ssh_user', user) + self._reconfig_ssh() + + host = self.cache.get_hosts()[0] + r = self._check_host(host) + if r is not None: + #connection failed reset user + self.set_store('ssh_user', current_user) + self._reconfig_ssh() + return -errno.EINVAL, '', 'ssh connection %s@%s failed' % (user, host) + + msg = 'ssh user set to %s' % user + if user != 'root': + msg += ' sudo will be used' + self.log.info(msg) + return 0, msg, '' + @orchestrator._cli_read_command( 'cephadm check-host', 'name=host,type=CephString ' @@ -869,7 +893,8 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule): conn = remoto.Connection( n, logger=child_logger, - ssh_options=self._ssh_options) + ssh_options=self._ssh_options, + sudo=True if self.ssh_user != 'root' else False) r = conn.import_module(remotes) self._cons[host] = conn, r @@ -919,7 +944,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule): self.offline_hosts.add(host) self._reset_con(host) - user = 'root' if self.mode == 'root' else 'cephadm' + user = self.ssh_user if self.mode == 'root' else 'cephadm' msg = f'''Failed to connect to {host} ({addr}). Check that the host is reachable and accepts connections using the cephadm SSH key @@ -1004,9 +1029,9 @@ you may want to run: host, remotes.PYTHONS, remotes.PATH)) try: out, err, code = remoto.process.check( - conn, - [python, '-u'], - stdin=script.encode('utf-8')) + conn, + [python, '-u'], + stdin=script.encode('utf-8')) except RuntimeError as e: self._reset_con(host) if error_ok: