mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
add systemd run0 as a become method (#8306)
* add systemd run0 as a become method Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * add fragment Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * remove space after hyphen Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * replace ansible with collection version Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * update version_added and remove changelog fragment Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * update formating Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * add types Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * slim super() Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * imports must appear below docs Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * add initial unit test Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> * update unit tests Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com> --------- Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com>
This commit is contained in:
parent
3b7f13c58e
commit
d347bf5fa0
3 changed files with 194 additions and 0 deletions
2
.github/BOTMETA.yml
vendored
2
.github/BOTMETA.yml
vendored
|
@ -33,6 +33,8 @@ files:
|
|||
maintainers: $team_ansible_core
|
||||
$becomes/pmrun.py:
|
||||
maintainers: $team_ansible_core
|
||||
$becomes/run0.py:
|
||||
maintainers: konstruktoid
|
||||
$becomes/sesu.py:
|
||||
maintainers: nekonyuu
|
||||
$becomes/sudosu.py:
|
||||
|
|
128
plugins/become/run0.py
Normal file
128
plugins/become/run0.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2024, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = """
|
||||
name: run0
|
||||
short_description: Systemd's run0
|
||||
description:
|
||||
- This become plugins allows your remote/login user to execute commands as another user via the C(run0) utility.
|
||||
author:
|
||||
- Thomas Sjögren (@konstruktoid)
|
||||
version_added: '9.0.0'
|
||||
options:
|
||||
become_user:
|
||||
description: User you 'become' to execute the task.
|
||||
default: root
|
||||
ini:
|
||||
- section: privilege_escalation
|
||||
key: become_user
|
||||
- section: run0_become_plugin
|
||||
key: user
|
||||
vars:
|
||||
- name: ansible_become_user
|
||||
- name: ansible_run0_user
|
||||
env:
|
||||
- name: ANSIBLE_BECOME_USER
|
||||
- name: ANSIBLE_RUN0_USER
|
||||
type: string
|
||||
become_exe:
|
||||
description: The C(run0) executable.
|
||||
default: run0
|
||||
ini:
|
||||
- section: privilege_escalation
|
||||
key: become_exe
|
||||
- section: run0_become_plugin
|
||||
key: executable
|
||||
vars:
|
||||
- name: ansible_become_exe
|
||||
- name: ansible_run0_exe
|
||||
env:
|
||||
- name: ANSIBLE_BECOME_EXE
|
||||
- name: ANSIBLE_RUN0_EXE
|
||||
type: string
|
||||
become_flags:
|
||||
description: Options to pass to run0.
|
||||
default: ''
|
||||
ini:
|
||||
- section: privilege_escalation
|
||||
key: become_flags
|
||||
- section: run0_become_plugin
|
||||
key: flags
|
||||
vars:
|
||||
- name: ansible_become_flags
|
||||
- name: ansible_run0_flags
|
||||
env:
|
||||
- name: ANSIBLE_BECOME_FLAGS
|
||||
- name: ANSIBLE_RUN0_FLAGS
|
||||
type: string
|
||||
notes:
|
||||
- This plugin will only work when a polkit rule is in place.
|
||||
"""
|
||||
|
||||
EXAMPLES = r"""
|
||||
# An example polkit rule that allows the user 'ansible' in the 'wheel' group
|
||||
# to execute commands using run0 without authentication.
|
||||
/etc/polkit-1/rules.d/60-run0-fast-user-auth.rules: |
|
||||
polkit.addRule(function(action, subject) {
|
||||
if(action.id == "org.freedesktop.systemd1.manage-units" &&
|
||||
subject.isInGroup("wheel")
|
||||
subject.user == "ansible") {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
"""
|
||||
|
||||
from re import compile as re_compile
|
||||
|
||||
from ansible.plugins.become import BecomeBase
|
||||
from ansible.module_utils._text import to_bytes
|
||||
|
||||
ansi_color_codes = re_compile(to_bytes(r"\x1B\[[0-9;]+m"))
|
||||
|
||||
|
||||
class BecomeModule(BecomeBase):
|
||||
|
||||
name = "community.general.run0"
|
||||
|
||||
prompt = "Password: "
|
||||
fail = ("==== AUTHENTICATION FAILED ====",)
|
||||
success = ("==== AUTHENTICATION COMPLETE ====",)
|
||||
require_tty = (
|
||||
True # see https://github.com/ansible-collections/community.general/issues/6932
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def remove_ansi_codes(line):
|
||||
return ansi_color_codes.sub(b"", line)
|
||||
|
||||
def build_become_command(self, cmd, shell):
|
||||
super().build_become_command(cmd, shell)
|
||||
|
||||
if not cmd:
|
||||
return cmd
|
||||
|
||||
become = self.get_option("become_exe")
|
||||
flags = self.get_option("become_flags")
|
||||
user = self.get_option("become_user")
|
||||
|
||||
return (
|
||||
f"{become} --user={user} {flags} {self._build_success_command(cmd, shell)}"
|
||||
)
|
||||
|
||||
def check_success(self, b_output):
|
||||
b_output = self.remove_ansi_codes(b_output)
|
||||
return super().check_success(b_output)
|
||||
|
||||
def check_incorrect_password(self, b_output):
|
||||
b_output = self.remove_ansi_codes(b_output)
|
||||
return super().check_incorrect_password(b_output)
|
||||
|
||||
def check_missing_password(self, b_output):
|
||||
b_output = self.remove_ansi_codes(b_output)
|
||||
return super().check_missing_password(b_output)
|
64
tests/unit/plugins/become/test_run0.py
Normal file
64
tests/unit/plugins/become/test_run0.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
# Copyright (c) 2024 Ansible Project
|
||||
#
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
import re
|
||||
|
||||
from ansible import context
|
||||
|
||||
from .helper import call_become_plugin
|
||||
|
||||
|
||||
def test_run0_basic(mocker, parser, reset_cli_args):
|
||||
options = parser.parse_args([])
|
||||
context._init_global_context(options)
|
||||
|
||||
default_cmd = "/bin/foo"
|
||||
default_exe = "/bin/sh"
|
||||
run0_exe = "run0"
|
||||
|
||||
success = "BECOME-SUCCESS-.+?"
|
||||
|
||||
task = {
|
||||
"become_method": "community.general.run0",
|
||||
}
|
||||
var_options = {}
|
||||
cmd = call_become_plugin(task, var_options, cmd=default_cmd, executable=default_exe)
|
||||
assert (
|
||||
re.match(
|
||||
f"{run0_exe} --user=root {default_exe} -c 'echo {success}; {default_cmd}'",
|
||||
cmd,
|
||||
)
|
||||
is not None
|
||||
)
|
||||
|
||||
|
||||
def test_run0_flags(mocker, parser, reset_cli_args):
|
||||
options = parser.parse_args([])
|
||||
context._init_global_context(options)
|
||||
|
||||
default_cmd = "/bin/foo"
|
||||
default_exe = "/bin/sh"
|
||||
run0_exe = "run0"
|
||||
run0_flags = "--nice=15"
|
||||
|
||||
success = "BECOME-SUCCESS-.+?"
|
||||
|
||||
task = {
|
||||
"become_method": "community.general.run0",
|
||||
"become_flags": run0_flags,
|
||||
}
|
||||
var_options = {}
|
||||
cmd = call_become_plugin(task, var_options, cmd=default_cmd, executable=default_exe)
|
||||
assert (
|
||||
re.match(
|
||||
f"{run0_exe} --user=root --nice=15 {default_exe} -c 'echo {success}; {default_cmd}'",
|
||||
cmd,
|
||||
)
|
||||
is not None
|
||||
)
|
Loading…
Reference in a new issue