Skip to content

Commit

Permalink
Fix: bootstrap: add informative logging for generating new ssh keypairs
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholasyang2022 committed Nov 23, 2023
1 parent f4d5ba9 commit 59bd4b3
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
18 changes: 12 additions & 6 deletions crmsh/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,9 @@ def _init_ssh_for_secondary_user_on_remote_nodes(
if not sh.SSHShell(cluster_shell.local_shell, user).can_run_as(node, user):
for key in local_keys:
authorized_key_manager.add(node, user, key)
remote_keys = key_file_manager.ensure_key_pair_exists_for_user(node, user)
is_generated, remote_keys = key_file_manager.ensure_key_pair_exists_for_user(node, user)
if is_generated:
logger.info("A new ssh keypair is generated for user %s@%s.", user, node)
for key in remote_keys:
authorized_key_manager.add(None, user, key)

Expand Down Expand Up @@ -1037,8 +1039,10 @@ def configure_ssh_key(user):
shell = sh.LocalShell()
key_file_manager = ssh_key.KeyFileManager(sh.ClusterShellAdaptorForLocalShell(shell))
authorized_key_manager = ssh_key.AuthorizedKeyManager(sh.SSHShell(shell, None))
key = key_file_manager.ensure_key_pair_exists_for_user(None, user)[0]
authorized_key_manager.add(None, user, key)
is_generated, keys = key_file_manager.ensure_key_pair_exists_for_user(None, user)
if is_generated:
logger.info("A new ssh keypair is generated for user %s.", user)
authorized_key_manager.add(None, user, keys[0])


def generate_ssh_key_pair_on_remote(
Expand Down Expand Up @@ -1809,9 +1813,11 @@ def join_ssh_with_ssh_agent(
def swap_public_ssh_key_for_secondary_user(shell: sh.ClusterShell, host: str, user: str):
key_file_manager = ssh_key.KeyFileManager(shell)
local_key = ssh_key.KeyFile(key_file_manager.list_public_key_for_user(None, user)[0])
remote_key = key_file_manager.ensure_key_pair_exists_for_user(host, user)[0]
is_generated, remote_keys = key_file_manager.ensure_key_pair_exists_for_user(host, user)
if is_generated:
logger.info("A new ssh keypair is generated for user %s@%s.", user, host)
authorized_key_manager = ssh_key.AuthorizedKeyManager(shell)
authorized_key_manager.add(None, user, remote_key)
authorized_key_manager.add(None, user, remote_keys[0])
authorized_key_manager.add(host, user, local_key)


Expand Down Expand Up @@ -2092,7 +2098,7 @@ def swap_key_for_hacluster(other_node_list):
key_file_manager = ssh_key.KeyFileManager(shell)
authorized_key_manager = ssh_key.AuthorizedKeyManager(shell)
keys: typing.List[ssh_key.Key] = [
key_file_manager.ensure_key_pair_exists_for_user(node, 'hacluster')[0]
key_file_manager.ensure_key_pair_exists_for_user(node, 'hacluster')[1][0]
for node in other_node_list
]
keys.append(ssh_key.KeyFile(key_file_manager.list_public_key_for_user(None, 'hacluster')[0]))
Expand Down
23 changes: 21 additions & 2 deletions crmsh/ssh_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,21 @@ def load_public_keys_for_user(self, host: typing.Optional[str], user: str) -> ty
raise sh.CommandFailure(cmd, host, user, sh.Utils.decode_str(result.stderr).strip())
return [InMemoryPublicKey(line) for line in sh.Utils.decode_str(result.stdout).splitlines()]

Check warning on line 218 in crmsh/ssh_key.py

View check run for this annotation

Codecov / codecov/patch

crmsh/ssh_key.py#L216-L218

Added lines #L216 - L218 were not covered by tests

def ensure_key_pair_exists_for_user(self, host: typing.Optional[str], user: str) -> typing.List[InMemoryPublicKey]:
def ensure_key_pair_exists_for_user(
self,
host: typing.Optional[str],
user: str,
) -> typing.Tuple[bool, typing.List[InMemoryPublicKey]]:
"""Ensure at least one keypair exists for the specified user. If it does not exist, generate a new one.
Return (is_generated, list_of_public_keys):
* is_generated: whether a new keypair is generated
* list_of_public_keys: all public keys of known types, including the newly generated one
"""
script = '''if [ ! \\( {condition} \\) ]; then
ssh-keygen -t rsa -f ~/.ssh/id_rsa -q -C "Cluster internal on $(hostname)" -N '' <> /dev/null
echo 'GENERATED=1'
fi
for file in ~/.ssh/id_{{{pattern}}}; do
if [ -f "$file" ]; then
Expand All @@ -243,4 +255,11 @@ def ensure_key_pair_exists_for_user(self, host: typing.Optional[str], user: str)
print(script)
print(result.stdout)
raise sh.CommandFailure(f'Script({script[:16]}...) failed. rc = {result.returncode}', host, user, sh.Utils.decode_str(result.stderr).strip())

Check warning on line 257 in crmsh/ssh_key.py

View check run for this annotation

Codecov / codecov/patch

crmsh/ssh_key.py#L255-L257

Added lines #L255 - L257 were not covered by tests
return [InMemoryPublicKey(line) for line in sh.Utils.decode_str(result.stdout).splitlines()]
generated = False
keys = list()
for line in sh.Utils.decode_str(result.stdout).splitlines():
if line == 'GENERATED=1':
generated = True
else:
keys.append(InMemoryPublicKey(line))
return generated, keys

0 comments on commit 59bd4b3

Please sign in to comment.