2024-05-11 16:53:44 +02:00
|
|
|
# -*- 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: |
|
2024-05-19 20:50:41 +02:00
|
|
|
polkit.addRule(function(action, subject) {
|
|
|
|
if(action.id == "org.freedesktop.systemd1.manage-units" &&
|
|
|
|
subject.isInGroup("wheel") &&
|
|
|
|
subject.user == "ansible") {
|
2024-05-11 16:53:44 +02:00
|
|
|
return polkit.Result.YES;
|
2024-05-19 20:50:41 +02:00
|
|
|
}
|
|
|
|
});
|
2024-05-11 16:53:44 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
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)
|