From: Daniel Pivonka Date: Wed, 10 Nov 2021 16:18:06 +0000 (-0500) Subject: mgr/cephadm: store contianer registry credentials in config-key X-Git-Tag: v17.1.0~228^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=2c29286b370b1079a35e0e0d47c33a7dabab3468;p=ceph-ci.git mgr/cephadm: store contianer registry credentials in config-key Signed-off-by: Daniel Pivonka --- diff --git a/doc/cephadm/install.rst b/doc/cephadm/install.rst index 08996c8fc23..95d65380afa 100644 --- a/doc/cephadm/install.rst +++ b/doc/cephadm/install.rst @@ -213,17 +213,13 @@ available options. designate with this option must have passwordless sudo access. * If you are using a container on an authenticated registry that requires - login, you may add the three arguments: - - #. ``--registry-url `` - - #. ``--registry-username `` + login, you may add the argument: - #. ``--registry-password `` + * ``--registry-json `` - OR + example contents of JSON file with login info:: - * ``--registry-json `` + {"url":"REGISTRY_URL", "username":"REGISTRY_USERNAME", "password":"REGISTRY_PASSWORD"} Cephadm will attempt to log in to this registry so it can pull your container and then store the login info in its config database. Other hosts added to diff --git a/qa/suites/orch/cephadm/mgr-nfs-upgrade/4-final.yaml b/qa/suites/orch/cephadm/mgr-nfs-upgrade/4-final.yaml index b1957d9d628..2a834ead4c0 100644 --- a/qa/suites/orch/cephadm/mgr-nfs-upgrade/4-final.yaml +++ b/qa/suites/orch/cephadm/mgr-nfs-upgrade/4-final.yaml @@ -7,4 +7,4 @@ tasks: - ceph nfs cluster ls | grep foo - ceph nfs export ls foo --detailed - rados -p .nfs --all ls - - - ceph config get mgr mgr/cephadm/migration_current | grep 4 + - ceph config get mgr mgr/cephadm/migration_current | grep 5 diff --git a/src/cephadm/cephadm b/src/cephadm/cephadm index 1a6b7dcd333..a9b10ffa33a 100755 --- a/src/cephadm/cephadm +++ b/src/cephadm/cephadm @@ -4862,9 +4862,8 @@ def command_bootstrap(ctx): prepare_ssh(ctx, cli, wait_for_mgr_restart) if ctx.registry_url and ctx.registry_username and ctx.registry_password: - cli(['config', 'set', 'mgr', 'mgr/cephadm/registry_url', ctx.registry_url, '--force']) - cli(['config', 'set', 'mgr', 'mgr/cephadm/registry_username', ctx.registry_username, '--force']) - cli(['config', 'set', 'mgr', 'mgr/cephadm/registry_password', ctx.registry_password, '--force']) + registry_credentials = {'url': ctx.registry_url, 'username': ctx.registry_username, 'password': ctx.registry_password} + cli(['config-key', 'set', 'mgr/cephadm/registry_credentials', json.dumps(registry_credentials)]) cli(['config', 'set', 'mgr', 'mgr/cephadm/container_init', str(ctx.container_init), '--force']) diff --git a/src/pybind/mgr/cephadm/migrations.py b/src/pybind/mgr/cephadm/migrations.py index b66eedb6907..95ec5d28770 100644 --- a/src/pybind/mgr/cephadm/migrations.py +++ b/src/pybind/mgr/cephadm/migrations.py @@ -12,7 +12,7 @@ from orchestrator import OrchestratorError, DaemonDescription if TYPE_CHECKING: from .module import CephadmOrchestrator -LAST_MIGRATION = 4 +LAST_MIGRATION = 5 logger = logging.getLogger(__name__) @@ -72,6 +72,10 @@ class Migrations: if self.migrate_3_4(): self.set(4) + if self.mgr.migration_current == 4: + if self.migrate_4_5(): + self.set(5) + def migrate_0_1(self) -> bool: """ Migration 0 -> 1 @@ -273,6 +277,38 @@ class Migrations: ) return True + def migrate_4_5(self) -> bool: + registry_url = self.mgr.get_module_option('registry_url') + registry_username = self.mgr.get_module_option('registry_username') + registry_password = self.mgr.get_module_option('registry_password') + if registry_url and registry_username and registry_password: + + registry_credentials = {'url': registry_url, + 'username': registry_username, 'password': registry_password} + self.mgr.set_store('registry_credentials', json.dumps(registry_credentials)) + + self.mgr.set_module_option('registry_url', None) + self.mgr.check_mon_command({ + 'prefix': 'config rm', + 'who': 'mgr', + 'key': 'mgr/cephadm/registry_url', + }) + self.mgr.set_module_option('registry_username', None) + self.mgr.check_mon_command({ + 'prefix': 'config rm', + 'who': 'mgr', + 'key': 'mgr/cephadm/registry_username', + }) + self.mgr.set_module_option('registry_password', None) + self.mgr.check_mon_command({ + 'prefix': 'config rm', + 'who': 'mgr', + 'key': 'mgr/cephadm/registry_password', + }) + + self.mgr.log.info('Done migrating registry login info') + return True + def queue_migrate_nfs_spec(mgr: "CephadmOrchestrator", spec_dict: Dict[Any, Any]) -> None: """ diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index c968d956e09..859d0799ab1 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -277,6 +277,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule, default='*', desc='PlacementSpec describing on which hosts to manage /etc/ceph/ceph.conf', ), + # not used anymore Option( 'registry_url', type='str', @@ -295,6 +296,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule, default=None, desc='Custom repository password' ), + #### Option( 'registry_insecure', type='bool', @@ -953,14 +955,12 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule, if not (url and username and password) and (inbuf is None or len(inbuf) == 0): return -errno.EINVAL, "", ("Invalid arguments. Please provide arguments " "or -i ") - elif not (url and username and password): + elif (url and username and password): + registry_json = {'url': url, 'username': username, 'password': password} + else: assert isinstance(inbuf, str) - login_info = json.loads(inbuf) - if "url" in login_info and "username" in login_info and "password" in login_info: - url = login_info["url"] - username = login_info["username"] - password = login_info["password"] - else: + registry_json = json.loads(inbuf) + if "url" not in registry_json or "username" not in registry_json or "password" not in registry_json: return -errno.EINVAL, "", ("json provided for custom registry login did not include all necessary fields. " "Please setup json file as\n" "{\n" @@ -968,6 +968,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule, " \"username\": \"REGISTRY_USERNAME\",\n" " \"password\": \"REGISTRY_PASSWORD\"\n" "}\n") + # verify login info works by attempting login on random host host = None for host_name in self.inventory.keys(): @@ -975,14 +976,12 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule, break if not host: raise OrchestratorError('no hosts defined') - r = self.wait_async(CephadmServe(self)._registry_login(host, url, username, password)) + r = self.wait_async(CephadmServe(self)._registry_login(host, registry_json)) if r is not None: return 1, '', r # if logins succeeded, store info self.log.debug("Host logins successful. Storing login info.") - self.set_module_option('registry_url', url) - self.set_module_option('registry_username', username) - self.set_module_option('registry_password', password) + self.set_store('registry_credentials', json.dumps(registry_json)) # distribute new login info to all hosts self.cache.distribute_new_registry_login_info() return 0, "registry login scheduled", '' diff --git a/src/pybind/mgr/cephadm/serve.py b/src/pybind/mgr/cephadm/serve.py index 9e3f9c0927f..4802b1d7c4a 100644 --- a/src/pybind/mgr/cephadm/serve.py +++ b/src/pybind/mgr/cephadm/serve.py @@ -242,10 +242,10 @@ class CephadmServe: failures.append(r) self.mgr.cache.metadata_up_to_date[host] = True - if self.mgr.cache.host_needs_registry_login(host) and self.mgr.registry_url: + if self.mgr.cache.host_needs_registry_login(host) and self.mgr.get_store('registry_credentials'): self.log.debug(f"Logging `{host}` into custom registry") - r = self.mgr.wait_async(self._registry_login(host, self.mgr.registry_url, - self.mgr.registry_username, self.mgr.registry_password)) + r = self.mgr.wait_async(self._registry_login( + host, json.loads(str(self.mgr.get_store('registry_credentials'))))) if r: bad_hosts.append(r) @@ -1096,8 +1096,7 @@ class CephadmServe: daemon_spec.extra_args.append('--allow-ptrace') if self.mgr.cache.host_needs_registry_login(daemon_spec.host) and self.mgr.registry_url: - await self._registry_login(daemon_spec.host, self.mgr.registry_url, - self.mgr.registry_username, self.mgr.registry_password) + await self._registry_login(daemon_spec.host, json.loads(str(self.mgr.get_store('registry_credentials')))) self.log.info('%s daemon %s on %s' % ( 'Reconfiguring' if reconfig else 'Deploying', @@ -1326,8 +1325,7 @@ class CephadmServe: if not host: raise OrchestratorError('no hosts defined') if self.mgr.cache.host_needs_registry_login(host) and self.mgr.registry_url: - await self._registry_login(host, self.mgr.registry_url, - self.mgr.registry_username, self.mgr.registry_password) + await self._registry_login(host, json.loads(str(self.mgr.get_store('registry_credentials')))) pullargs: List[str] = [] if self.mgr.registry_insecure: @@ -1344,19 +1342,15 @@ class CephadmServe: return r # function responsible for logging single host into custom registry - async def _registry_login(self, host: str, url: Optional[str], username: Optional[str], password: Optional[str]) -> Optional[str]: - self.log.debug(f"Attempting to log host {host} into custom registry @ {url}") + async def _registry_login(self, host: str, registry_json: Dict[str, str]) -> Optional[str]: + self.log.debug( + f"Attempting to log host {host} into custom registry @ {registry_json['url']}") # want to pass info over stdin rather than through normal list of args - args_str = json.dumps({ - 'url': url, - 'username': username, - 'password': password, - }) out, err, code = await self._run_cephadm( host, 'mon', 'registry-login', - ['--registry-json', '-'], stdin=args_str, error_ok=True) + ['--registry-json', '-'], stdin=json.dumps(registry_json), error_ok=True) if code: - return f"Host {host} failed to login to {url} as {username} with given password" + return f"Host {host} failed to login to {registry_json['url']} as {registry_json['username']} with given password" return None async def _deploy_cephadm_binary(self, host: str, addr: Optional[str] = None) -> None: diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index 889192a332b..b564039ce2d 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -1480,9 +1480,8 @@ class TestCephadm(object): @mock.patch("cephadm.serve.CephadmServe._run_cephadm") def test_registry_login(self, _run_cephadm, cephadm_module: CephadmOrchestrator): def check_registry_credentials(url, username, password): - assert cephadm_module.get_module_option('registry_url') == url - assert cephadm_module.get_module_option('registry_username') == username - assert cephadm_module.get_module_option('registry_password') == password + assert json.loads(cephadm_module.get_store('registry_credentials')) == { + 'url': url, 'username': username, 'password': password} _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'):