1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-06-10 18:15:39 +00:00
This commit is contained in:
Tiziano Müller 2026-06-06 01:39:59 -04:00 committed by GitHub
commit 099de8ecfe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 76 additions and 1 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- sudoers - add ``defaults`` parameter to allow specifying ``Defaults`` directives scoped to the user or group in the generated sudoers file (https://github.com/ansible-collections/community.general/pull/12186).

View file

@ -87,6 +87,16 @@ options:
- The name of the user for the sudoers rule.
- This option cannot be used in conjunction with O(group).
type: str
defaults:
description:
- A list of C(Defaults) directives to include in the sudoers rule file.
- Each entry is written as a C(Defaults) line scoped to the user or group specified in the rule.
- For example, V(!targetpw) becomes C(Defaults:%group !targetpw) for a group rule
or C(Defaults:user !targetpw) for a user rule.
- The directives are placed before the privilege rule in the generated file.
type: list
elements: str
version_added: 13.1.0
validation:
description:
- If V(absent), the sudoers rule is added without validation.
@ -154,6 +164,15 @@ EXAMPLES = r"""
user: alice
commands: /usr/bin/less
noexec: true
- name: Allow members of the operators group to sudo with their user password, overriding targetpw default
community.general.sudoers:
name: operators
group: operators
commands: ALL
nopassword: false
defaults:
- "!targetpw"
"""
import os
@ -180,6 +199,7 @@ class Sudoers:
self.sudoers_path = module.params["sudoers_path"]
self.file = os.path.join(self.sudoers_path, self.name)
self.commands = module.params["commands"]
self.defaults = module.params["defaults"]
self.validation = module.params["validation"]
def write(self):
@ -215,12 +235,18 @@ class Sudoers:
elif self.group:
owner = f"%{self.group}"
if self.defaults:
defaults_lines = [f"Defaults:{owner} {d}" for d in self.defaults]
defaults_str = "\n".join(defaults_lines) + "\n"
else:
defaults_str = ""
commands_str = ", ".join(self.commands)
noexec_str = "NOEXEC:" if self.noexec else ""
nopasswd_str = "NOPASSWD:" if self.nopassword else ""
setenv_str = "SETENV:" if self.setenv else ""
runas_str = f"({self.runas})" if self.runas is not None else ""
return f"{owner} {self.host}={runas_str}{noexec_str}{nopasswd_str}{setenv_str} {commands_str}\n"
return f"{defaults_str}{owner} {self.host}={runas_str}{noexec_str}{nopasswd_str}{setenv_str} {commands_str}\n"
def validate(self):
if self.validation == "absent":
@ -261,6 +287,10 @@ def main():
"type": "list",
"elements": "str",
},
"defaults": {
"type": "list",
"elements": "str",
},
"group": {},
"name": {
"required": True,

View file

@ -173,6 +173,39 @@
src: "{{ sudoers_path }}/my-sudo-rule-9"
register: rule_9_contents
- name: Create rule with defaults directives for a group
community.general.sudoers:
name: my-sudo-rule-10
state: present
group: operators
commands: ALL
nopassword: false
defaults:
- "!targetpw"
register: rule_10
- name: Grab contents of my-sudo-rule-10
ansible.builtin.slurp:
src: "{{ sudoers_path }}/my-sudo-rule-10"
register: rule_10_contents
- name: Create rule with defaults directives for a user
community.general.sudoers:
name: my-sudo-rule-11
state: present
user: alice
commands: ALL
nopassword: false
defaults:
- "!targetpw"
- "env_reset"
register: rule_11
- name: Grab contents of my-sudo-rule-11
ansible.builtin.slurp:
src: "{{ sudoers_path }}/my-sudo-rule-11"
register: rule_11_contents
- name: Revoke rule 1
community.general.sudoers:
name: my-sudo-rule-1
@ -261,6 +294,14 @@
- revoke_non_existing_rule is not changed
- name: Check contents
vars:
expected_result_rule10: |
Defaults:%operators !targetpw
%operators ALL= ALL
expected_result_rule11: |
Defaults:alice !targetpw
Defaults:alice env_reset
alice ALL= ALL
ansible.builtin.assert:
that:
- "rule_1_contents['content'] | b64decode == 'alice ALL=NOPASSWD: /usr/local/bin/command\n'"
@ -272,6 +313,8 @@
- "rule_7_contents['content'] | b64decode == 'alice host-1=NOPASSWD: /usr/local/bin/command\n'"
- "rule_8_contents['content'] | b64decode == 'alice ALL=NOPASSWD:SETENV: /usr/local/bin/command\n'"
- "rule_9_contents['content'] | b64decode == 'alice ALL=NOEXEC:NOPASSWD: /usr/local/bin/command\n'"
- "rule_10_contents['content'] | b64decode == expected_result_rule10"
- "rule_11_contents['content'] | b64decode == expected_result_rule11"
- name: Check revocation stat
ansible.builtin.assert: