From d224752cf1957c64af4962671b357922293a141c Mon Sep 17 00:00:00 2001 From: Jeff Goldschrafe Date: Wed, 8 Dec 2021 23:53:43 -0500 Subject: [PATCH] Minor fixes to nsenter connection plugin (#249) * Minor fixes to nsenter connection plugin - Ensure the nsoption_pid option is retrieved in _connect instead of __init__ to prevent a crasher due to initialization order - Replace the use of --all-namespaces with specific namespaces to support compatibility with Busybox nsenter (for example, Alpine) * minor tidy * Fix PEP8 violation * Changelog fragment * Update changelogs/fragments/249-nsenter-fixes.yml Co-authored-by: Felix Fontein Co-authored-by: Jeff Goldschrafe Co-authored-by: Felix Fontein --- changelogs/fragments/249-nsenter-fixes.yml | 3 +++ plugins/connection/nsenter.py | 29 ++++++++++++++-------- 2 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 changelogs/fragments/249-nsenter-fixes.yml diff --git a/changelogs/fragments/249-nsenter-fixes.yml b/changelogs/fragments/249-nsenter-fixes.yml new file mode 100644 index 00000000..ea5e0c75 --- /dev/null +++ b/changelogs/fragments/249-nsenter-fixes.yml @@ -0,0 +1,3 @@ +bugfixes: + - "nsenter connection plugin - ensure the ``nsenter_pid`` option is retrieved in ``_connect`` instead of ``__init__`` to prevent a crasher due to bad initialization order (https://github.com/ansible-collections/community.docker/pull/249)." + - "nsenter connection plugin - replace the use of ``--all-namespaces`` with specific namespaces to support compatibility with Busybox nsenter (used on, for example, Alpine containers) (https://github.com/ansible-collections/community.docker/pull/249)." diff --git a/plugins/connection/nsenter.py b/plugins/connection/nsenter.py index 04ab35af..17bef1f9 100644 --- a/plugins/connection/nsenter.py +++ b/plugins/connection/nsenter.py @@ -70,9 +70,10 @@ class Connection(ConnectionBase): def __init__(self, *args, **kwargs): super(Connection, self).__init__(*args, **kwargs) self.cwd = None - self._nsenter_pid = self.get_option("nsenter_pid") def _connect(self): + self._nsenter_pid = self.get_option("nsenter_pid") + # Because nsenter requires very high privileges, our remote user # is always assumed to be root. self._play_context.remote_user = "root" @@ -99,18 +100,24 @@ class Connection(ConnectionBase): " Please verify if the executable exists and re-try." % executable) # Rewrite the provided command to prefix it with nsenter + nsenter_cmd_parts = [ + "nsenter", + "--ipc", + "--mount", + "--net", + "--pid", + "--uts", + "--preserve-credentials", + "--target={0}".format(self._nsenter_pid), + "--", + ] + if isinstance(cmd, (text_type, binary_type)): - nsenter_cmd = "nsenter --all --preserve-credentials --target={0} -- ".format(self._nsenter_pid) - cmd = to_bytes(nsenter_cmd) + to_bytes(cmd) + cmd_parts = nsenter_cmd_parts + [cmd] + cmd = to_bytes(" ".join(cmd_parts)) else: - nsenter_cmd = [ - "nsenter", - "--all", - "--preserve-credentials", - "--target={0}".format(self._nsenter_pid), - "--", - ] - cmd = [to_bytes(arg) for arg in nsenter_cmd + cmd] + cmd_parts = nsenter_cmd_parts + cmd + cmd = [to_bytes(arg) for arg in cmd_parts] display.vvv(u"EXEC {0}".format(to_text(cmd)), host=self._play_context.remote_addr) display.debug("opening command with Popen()")