Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cc_ssh_import_id: add Alpine support and add doas support #4277

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions cloudinit/config/cc_ssh_import_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from cloudinit.settings import PER_INSTANCE

# https://launchpad.net/ssh-import-id
distros = ["ubuntu", "debian", "cos"]
distros = ["alpine", "cos", "debian", "ubuntu"]

SSH_IMPORT_ID_BINARY = "ssh-import-id"
MODULE_DESCRIPTION = """\
Expand Down Expand Up @@ -152,13 +152,24 @@ def import_ssh_ids(ids, user):
# I'm including the `--preserve-env` here as a one-off, but we should
# have a better way of setting env earlier in boot and using it later.
# Perhaps a 'set_env' module?
cmd = [
"sudo",
"--preserve-env=https_proxy",
"-Hu",
user,
SSH_IMPORT_ID_BINARY,
] + ids
if subp.which("sudo"):
cmd = [
"sudo",
"--preserve-env=https_proxy",
"-Hu",
user,
SSH_IMPORT_ID_BINARY,
] + ids
elif subp.which("doas"):
cmd = [
"doas",
"-u",
user,
SSH_IMPORT_ID_BINARY,
] + ids
else:
LOG.error("Neither sudo nor doas available! Unable to import SSH ids.")
return
LOG.debug("Importing SSH ids for user %s.", user)

try:
Expand Down
49 changes: 49 additions & 0 deletions tests/unittests/config/test_cc_ssh_import_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,52 @@ def test_skip_inapplicable_configs(self, m_which, cfg, log, caplog):
cloud = get_cloud("ubuntu")
cc_ssh_import_id.handle("name", cfg, cloud, [])
assert log in caplog.text

@mock.patch("cloudinit.ssh_util.pwd.getpwnam")
@mock.patch("cloudinit.config.cc_ssh_import_id.subp.subp")
@mock.patch("cloudinit.subp.which")
def test_use_sudo(self, m_which, m_subp, m_getpwnam):
"""Check that sudo is available and use that"""
m_which.return_value = "/usr/bin/ssh-import-id"
ids = ["waffle"]
user = "bob"
cc_ssh_import_id.import_ssh_ids(ids, user)
m_subp.assert_called_once_with(
[
"sudo",
"--preserve-env=https_proxy",
"-Hu",
user,
"ssh-import-id",
]
+ ids,
capture=False,
)

@mock.patch("cloudinit.ssh_util.pwd.getpwnam")
@mock.patch("cloudinit.config.cc_ssh_import_id.subp.subp")
@mock.patch("cloudinit.subp.which")
def test_use_doas(self, m_which, m_subp, m_getpwnam):
"""Check that doas is available and use that"""
m_which.side_effect = [None, "/usr/bin/doas"]
ids = ["waffle"]
user = "bob"
cc_ssh_import_id.import_ssh_ids(ids, user)
m_subp.assert_called_once_with(
["doas", "-u", user, "ssh-import-id"] + ids, capture=False
)

@mock.patch("cloudinit.ssh_util.pwd.getpwnam")
@mock.patch("cloudinit.config.cc_ssh_import_id.subp.subp")
@mock.patch("cloudinit.subp.which")
def test_use_neither_sudo_nor_doas(
self, m_which, m_subp, m_getpwnam, caplog
):
"""Test when neither sudo nor doas is available"""
m_which.return_value = None
ids = ["waffle"]
user = "bob"
cc_ssh_import_id.import_ssh_ids(ids, user)
assert (
"Neither sudo nor doas available! Unable to import SSH ids"
) in caplog.text
Loading