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

[crmsh-4.6] Dev: bootstrap: implement ssh-agent support (jsc#PED-5774) #1261

Merged
merged 14 commits into from
Nov 23, 2023
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
12 changes: 12 additions & 0 deletions .github/workflows/crmsh-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,18 @@ jobs:
$DOCKER_SCRIPT `$GET_INDEX_OF user_access`
- uses: codecov/codecov-action@v3

functional_test_ssh_agent:
runs-on: ubuntu-20.04
timeout-minutes: 40
steps:
- uses: actions/checkout@v3
- name: functional test for user access
run: |
echo '{ "exec-opts": ["native.cgroupdriver=systemd"] }' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker.service
$DOCKER_SCRIPT `$GET_INDEX_OF ssh_agent` && $DOCKER_SCRIPT -d && $DOCKER_SCRIPT -u `$GET_INDEX_OF ssh_agent`
- uses: codecov/codecov-action@v3

original_regression_test:
runs-on: ubuntu-20.04
timeout-minutes: 40
Expand Down
4 changes: 2 additions & 2 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ coverage:
codecov:
token: 16b01c29-3b23-4923-b33a-4d26a49d80c4
notify:
after_n_builds: 22
after_n_builds: 23
comment:
after_n_builds: 22
after_n_builds: 23
431 changes: 280 additions & 151 deletions crmsh/bootstrap.py

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crmsh/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ def get(self, value):
'pager': opt_program('PAGER', ('less', 'more', 'pg')),
'user': opt_string(''),
'hosts': opt_list([]), # 'alice@host1, bob@host2'
'no_generating_ssh_key': opt_boolean('no'),
'skill_level': opt_choice('expert', ('operator', 'administrator', 'expert')),
'sort_elements': opt_boolean('yes'),
'check_frequency': opt_choice('always', ('always', 'on-verify', 'never')),
Expand Down
10 changes: 4 additions & 6 deletions crmsh/healthcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,10 @@ def fix_cluster(self, nodes: typing.Iterable[str], ask: typing.Callable[[str], N
remote_nodes = set(nodes)
remote_nodes.remove(local_node)
remote_nodes = list(remote_nodes)
local_user = crmsh.utils.user_pair_for_ssh(remote_nodes[0])[0]
crmsh.bootstrap.init_ssh_impl(
local_user,
None,
[(crmsh.utils.user_pair_for_ssh(node)[1], node) for node in remote_nodes],
)
crmsh.bootstrap.configure_ssh_key('hacluster')
crmsh.bootstrap.swap_key_for_hacluster(remote_nodes)
for node in remote_nodes:
crmsh.bootstrap.change_user_shell('hacluster', node)


def main_check_local(args) -> int:
Expand Down
30 changes: 18 additions & 12 deletions crmsh/prun/prun.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,17 @@ def pcopy_to_remote(
script = "put {} '{}' '{}'\n".format(flags, src, dst)
ssh = None
try:
ssh = tempfile.NamedTemporaryFile('w', encoding='utf-8', delete=False)
os.fchmod(ssh.fileno(), 0o700)
# sftp -S does not parse args, it accepts only a single executable. So we create one.
ssh.write(f'''#!/bin/sh
if local_sudoer == crmsh.userdir.getuser():
tasks = [_build_copy_task('', script, host) for host in hosts]
else:
ssh = tempfile.NamedTemporaryFile('w', encoding='utf-8', delete=False)
os.fchmod(ssh.fileno(), 0o700)
ssh.write(f'''#!/bin/sh
exec sudo -u {local_sudoer} ssh "$@"''')
# It is necessary to close the file before executing, or we will get an EBUSY.
ssh.close()
tasks = [_build_copy_task("-S '{}'".format(ssh.name), script, host) for host in hosts]
ssh.close()
tasks = [_build_copy_task("-S '{}'".format(ssh.name), script, host) for host in hosts]
runner = Runner(concurrency)
for task in tasks:
runner.add_task(task)
Expand Down Expand Up @@ -209,13 +212,16 @@ def pfetch_from_remote(
local_sudoer, _ = UserOfHost.instance().user_pair_for_ssh(hosts[0])
ssh = None
try:
ssh = tempfile.NamedTemporaryFile('w', encoding='utf-8', delete=False)
os.fchmod(ssh.fileno(), 0o700)
ssh.write(f'''#!/bin/sh
exec sudo -u {local_sudoer} ssh "$@"''')
# It is necessary to close the file before executing
ssh.close()
tasks = [_build_fetch_task("-S '{}'".format(ssh.name), host, src, dst, flags) for host in hosts]
if local_sudoer == crmsh.userdir.getuser():
tasks = [_build_fetch_task('', host, src, dst, flags) for host in hosts]
else:
ssh = tempfile.NamedTemporaryFile('w', encoding='utf-8', delete=False)
os.fchmod(ssh.fileno(), 0o700)
ssh.write(f'''#!/bin/sh
exec sudo -u {local_sudoer} ssh "$@"''')
# It is necessary to close the file before executing
ssh.close()
tasks = [_build_fetch_task("-S '{}'".format(ssh.name), host, src, dst, flags) for host in hosts]
runner = Runner(concurrency)
for task in tasks:
runner.add_task(task)
Expand Down
10 changes: 9 additions & 1 deletion crmsh/report/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import pwd
import datetime

import crmsh.user_of_host
from crmsh import log, sh
from crmsh import utils as crmutils
from crmsh.report import constants, utillib
Expand Down Expand Up @@ -56,7 +57,14 @@
"""
# since the "trace_dir" attribute been removed from cib after untrace
# need to parse crmsh log file to extract custom trace ra log directory on each node
shell = sh.cluster_shell()
if crmsh.user_of_host.instance().use_ssh_agent():
shell = sh.ClusterShell(

Check warning on line 61 in crmsh/report/collect.py

View check run for this annotation

Codecov / codecov/patch

crmsh/report/collect.py#L60-L61

Added lines #L60 - L61 were not covered by tests
sh.LocalShell(additional_environ={'SSH_AUTH_SOCK': os.environ.get('SSH_AUTH_SOCK', '')}),
crmsh.user_of_host.instance(),
forward_ssh_agent=True,
)
else:
shell = sh.cluster_shell()

Check warning on line 67 in crmsh/report/collect.py

View check run for this annotation

Codecov / codecov/patch

crmsh/report/collect.py#L67

Added line #L67 was not covered by tests
log_contents = ""
cmd = "grep 'INFO: Trace for .* is written to ' {}*|grep -v 'collect'".format(log.CRMSH_LOG_FILE)
for node in crmutils.list_cluster_nodes():
Expand Down
2 changes: 1 addition & 1 deletion crmsh/report/utillib.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@
res = re.search("PRETTY_NAME=\"(.*)\"", read_from_file(constants.OSRELEASE))
elif which("lsb_release"):
logger.debug("Using lsb_release to get distribution info")
out = sh.cluster_shell().get_stdout_or_raise_error("lsb_release -d")
out = sh.LocalShell().get_stdout_or_raise_error("lsb_release -d")

Check warning on line 420 in crmsh/report/utillib.py

View check run for this annotation

Codecov / codecov/patch

crmsh/report/utillib.py#L420

Added line #L420 was not covered by tests
res = re.search("Description:\s+(.*)", out)
return res.group(1) if res else "Unknown"

Expand Down
Loading