Compare commits
1
Commits
master
..
93e3264215
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93e3264215
|
No files matched your search
File renamed without changes.
@@ -0,0 +1,20 @@
|
|||||||
|
name: Ansible Linter
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [ "opened", "reopened", "synchronize" ]
|
||||||
|
push:
|
||||||
|
branches: [ '**' ]
|
||||||
|
tags-ignore: [ '**' ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ansible-lint:
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||||
|
- name: Run ansible-lint
|
||||||
|
uses: ansible/ansible-lint@5fac056c45595896c973fbde871f01f6cb14d74c # v26.4.0
|
||||||
|
with:
|
||||||
|
args: "--config-file .ansible-lint"
|
||||||
|
setup_python: "true"
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
name: Ansible Linter
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [ "opened", "reopened", "synchronize" ]
|
|
||||||
push:
|
|
||||||
branches: [ '**' ]
|
|
||||||
tags-ignore: [ '**' ]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ansible-lint:
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- name: Run ansible-lint
|
|
||||||
uses: ansible/ansible-lint@9bce2bfb8f4a984e6b13767bc0d6bf0a49492164 # v26.10.1
|
|
||||||
with:
|
|
||||||
args: "--config-file .ansible-lint.yml"
|
|
||||||
# The molecule scenario is linted as well, so its collections are required beside the ones of the role.
|
|
||||||
requirements_file: "molecule/default/collections.yml"
|
|
||||||
setup_python: "true"
|
|
||||||
@@ -7,15 +7,12 @@ on:
|
|||||||
branches: [ '**' ]
|
branches: [ '**' ]
|
||||||
tags-ignore: [ '**' ]
|
tags-ignore: [ '**' ]
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
markdown-lint:
|
markdown-lint:
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||||
- uses: DavidAnson/markdownlint-cli2-action@ded1f9488f68a970bc66ea5619e13e9b52e601cd # v23.2.0
|
- uses: DavidAnson/markdownlint-cli2-action@ded1f9488f68a970bc66ea5619e13e9b52e601cd # v23.2.0
|
||||||
with:
|
with:
|
||||||
globs: '**/*.md'
|
globs: '**/*.md'
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
name: Molecule
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [ "opened", "reopened", "synchronize" ]
|
|
||||||
push:
|
|
||||||
branches: [ '**' ]
|
|
||||||
tags-ignore: [ '**' ]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
molecule:
|
|
||||||
name: Molecule
|
|
||||||
runs-on: ubuntu-latest-amd64
|
|
||||||
steps:
|
|
||||||
# The scenario includes the role by its name, so the directory must be named like the role and not like the
|
|
||||||
# repository. Its parent is used as roles path.
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
with:
|
|
||||||
path: sudo
|
|
||||||
- name: Install molecule
|
|
||||||
run: |
|
|
||||||
apt update --yes
|
|
||||||
apt install --yes python3-pip
|
|
||||||
pip3 install --break-system-packages molecule docker
|
|
||||||
- name: Run molecule
|
|
||||||
run: molecule test
|
|
||||||
working-directory: sudo
|
|
||||||
@@ -6,9 +6,6 @@ on:
|
|||||||
- '**'
|
- '**'
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Release Ansible Role
|
name: Release Ansible Role
|
||||||
File renamed without changes.
@@ -1,5 +1,3 @@
|
|||||||
---
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Documentation:
|
# Documentation:
|
||||||
# https://yamllint.readthedocs.io/en/stable/
|
# https://yamllint.readthedocs.io/en/stable/
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# volker-raschek.sudo
|
# sudo_users
|
||||||
|
|
||||||

|
[](https://galaxy.ansible.com/volker_raschek/networking_role)
|
||||||
|
|
||||||
With following role can be created sudoers files in `/etc/sudoers.d`. For
|
With following role can be created sudoers files in `/etc/sudoers.d`. For
|
||||||
example to grant a user special perimssions to execute a program as root.
|
example to grant a user special perimssions to execute a program as root.
|
||||||
@@ -18,42 +18,6 @@ example to grant a user special perimssions to execute a program as root.
|
|||||||
- Installing sudo
|
- Installing sudo
|
||||||
- Configuring drop-on files in `/etc/sudoers.d`
|
- Configuring drop-on files in `/etc/sudoers.d`
|
||||||
|
|
||||||
## Tests
|
|
||||||
|
|
||||||
The role is tested with [Molecule](https://ansible.readthedocs.io/projects/molecule/). The scenario starts one docker
|
|
||||||
container per supported distribution family, applies the role, asserts that a second run reports no change and finally
|
|
||||||
verifies the created drop-in files, their permissions and content, that a rule declared as `absent` is gone again and
|
|
||||||
that `visudo` accepts the resulting configuration.
|
|
||||||
|
|
||||||
Molecule ships only its `default` driver, therefore `docker` is required beside molecule itself. The collections are
|
|
||||||
declared in `molecule/default/collections.yml` and installed by molecule.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install molecule docker
|
|
||||||
```
|
|
||||||
|
|
||||||
The complete sequence creates the containers, tests them and removes them afterwards.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
molecule test
|
|
||||||
```
|
|
||||||
|
|
||||||
While working on the role the containers are better kept alive.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# create the containers and apply the role
|
|
||||||
molecule converge
|
|
||||||
|
|
||||||
# run the assertions of molecule/default/verify.yml against the running containers
|
|
||||||
molecule verify
|
|
||||||
|
|
||||||
# open a shell in one of the containers
|
|
||||||
molecule login --host sudo-debian
|
|
||||||
|
|
||||||
# remove the containers
|
|
||||||
molecule destroy
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuring
|
## Configuring
|
||||||
|
|
||||||
In the default directory are examples how to configure the network stack. Copy the
|
In the default directory are examples how to configure the network stack. Copy the
|
||||||
|
|||||||
@@ -7,5 +7,4 @@ sudo_users_sudoers: []
|
|||||||
# group: "" # Group or User, not booth!
|
# group: "" # Group or User, not booth!
|
||||||
# nopassword: true
|
# nopassword: true
|
||||||
# runas: "" # Optional
|
# runas: "" # Optional
|
||||||
# state: present # Optional: present or absent. Default to present
|
|
||||||
# user: "markus": # Group or User, not booth!
|
# user: "markus": # Group or User, not booth!
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
---
|
|
||||||
argument_specs:
|
|
||||||
main:
|
|
||||||
short_description: "Role to configure sudoers on different distributions"
|
|
||||||
description:
|
|
||||||
- "This Ansible role installs sudo and manages drop-in files in /etc/sudoers.d."
|
|
||||||
- "Each drop-in file grants a unix user or a unix group the permission to execute commands, optionally as another
|
|
||||||
unix user."
|
|
||||||
author: "Markus Pesch"
|
|
||||||
options:
|
|
||||||
sudo_users_sudoers:
|
|
||||||
description:
|
|
||||||
- "List of sudoers drop-in files. Each entry must define either 'user' or 'group', but not both."
|
|
||||||
- "Supported keys are 'commands', 'filename', 'group', 'nopassword', 'runas', 'state' and 'user'."
|
|
||||||
type: list
|
|
||||||
elements: dict
|
|
||||||
default: []
|
|
||||||
@@ -7,15 +7,12 @@ galaxy_info:
|
|||||||
- sudo
|
- sudo
|
||||||
- sudoers
|
- sudoers
|
||||||
license: MIT
|
license: MIT
|
||||||
min_ansible_version: "2.11"
|
min_ansible_version: "2.9"
|
||||||
namespace: volker-raschek
|
namespace: volker-raschek
|
||||||
platforms:
|
platforms:
|
||||||
- name: ArchLinux
|
- name: ArchLinux
|
||||||
versions:
|
versions:
|
||||||
- all
|
- all
|
||||||
- name: Debian
|
|
||||||
versions:
|
|
||||||
- all
|
|
||||||
- name: EL
|
- name: EL
|
||||||
versions:
|
versions:
|
||||||
- all
|
- all
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
collections:
|
|
||||||
- name: community.docker
|
|
||||||
- name: community.general
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
- name: Converge
|
|
||||||
hosts: all
|
|
||||||
vars:
|
|
||||||
sudo_users_sudoers:
|
|
||||||
# A user without runas, restricted to a single command.
|
|
||||||
- user: molecule-alice
|
|
||||||
commands:
|
|
||||||
- /usr/bin/systemctl restart nginx
|
|
||||||
nopassword: true
|
|
||||||
# A user that acts as another user and stores its rule under a custom filename.
|
|
||||||
- user: molecule-bob
|
|
||||||
runas: molecule-alice
|
|
||||||
filename: molecule-bob-as-alice
|
|
||||||
nopassword: true
|
|
||||||
# A group that has to authenticate itself.
|
|
||||||
- group: molecule-ops
|
|
||||||
commands:
|
|
||||||
- /usr/bin/id
|
|
||||||
nopassword: false
|
|
||||||
# A group that acts as root.
|
|
||||||
- group: molecule-admins
|
|
||||||
runas: root
|
|
||||||
filename: molecule-admins-as-root
|
|
||||||
nopassword: true
|
|
||||||
- user: molecule-obsolete
|
|
||||||
state: absent
|
|
||||||
tasks:
|
|
||||||
# The role is included by the name of its directory, which molecule put on the roles path.
|
|
||||||
- name: Include the role sudo
|
|
||||||
ansible.builtin.include_role:
|
|
||||||
name: sudo
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
- name: Create
|
|
||||||
hosts: localhost
|
|
||||||
gather_facts: false
|
|
||||||
tasks:
|
|
||||||
- name: Start a container per platform
|
|
||||||
community.docker.docker_container:
|
|
||||||
name: "{{ item.name }}"
|
|
||||||
image: "{{ item.image }}"
|
|
||||||
command: "sleep infinity"
|
|
||||||
state: started
|
|
||||||
loop: "{{ molecule_yml.platforms }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.name }}"
|
|
||||||
|
|
||||||
- name: Write the instance config
|
|
||||||
ansible.builtin.copy:
|
|
||||||
content: |
|
|
||||||
{% for platform in molecule_yml.platforms %}
|
|
||||||
- instance: {{ platform.name }}
|
|
||||||
connection: community.docker.docker
|
|
||||||
{% endfor %}
|
|
||||||
dest: "{{ molecule_instance_config }}"
|
|
||||||
mode: "0600"
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
- name: Destroy
|
|
||||||
hosts: localhost
|
|
||||||
gather_facts: false
|
|
||||||
tasks:
|
|
||||||
- name: Remove the container of every platform
|
|
||||||
community.docker.docker_container:
|
|
||||||
name: "{{ item.name }}"
|
|
||||||
state: absent
|
|
||||||
loop: "{{ molecule_yml.platforms }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.name }}"
|
|
||||||
|
|
||||||
- name: Empty the instance config
|
|
||||||
ansible.builtin.copy:
|
|
||||||
content: "[]"
|
|
||||||
dest: "{{ molecule_instance_config }}"
|
|
||||||
mode: "0600"
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
driver:
|
|
||||||
name: default
|
|
||||||
options:
|
|
||||||
managed: true
|
|
||||||
login_cmd_template: "docker exec --interactive --tty {instance} bash"
|
|
||||||
|
|
||||||
platforms:
|
|
||||||
- name: sudo-archlinux
|
|
||||||
image: docker.io/library/archlinux:base
|
|
||||||
- name: sudo-debian
|
|
||||||
image: docker.io/library/debian:13
|
|
||||||
- name: sudo-fedora
|
|
||||||
image: registry.fedoraproject.org/fedora:43
|
|
||||||
|
|
||||||
provisioner:
|
|
||||||
name: ansible
|
|
||||||
# The role under test is the project directory itself, so its parent has to be on the roles path.
|
|
||||||
env:
|
|
||||||
ANSIBLE_ROLES_PATH: "${MOLECULE_PROJECT_DIRECTORY}/.."
|
|
||||||
config_options:
|
|
||||||
defaults:
|
|
||||||
interpreter_python: auto_silent
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
- name: Prepare
|
|
||||||
hosts: all
|
|
||||||
gather_facts: false
|
|
||||||
vars:
|
|
||||||
# The base images ship neither a python interpreter for ansible nor the package manager bindings the role relies on.
|
|
||||||
_bootstrap: |
|
|
||||||
set -eu
|
|
||||||
if command -v pacman > /dev/null; then
|
|
||||||
pacman --sync --refresh --noconfirm python shadow
|
|
||||||
elif command -v apt-get > /dev/null; then
|
|
||||||
apt-get update
|
|
||||||
apt-get install --yes passwd python3 python3-apt
|
|
||||||
else
|
|
||||||
dnf install --assumeyes python3 python3-libdnf5 shadow-utils
|
|
||||||
fi
|
|
||||||
tasks:
|
|
||||||
# The raw command is wrapped explicitly, because the bootstrap relies on shell builtins.
|
|
||||||
- name: Bootstrap the python interpreter and the package manager bindings
|
|
||||||
ansible.builtin.raw: "/bin/sh -c {{ _bootstrap | quote }}"
|
|
||||||
changed_when: true
|
|
||||||
|
|
||||||
- name: Seed the objects the converge refers to
|
|
||||||
hosts: all
|
|
||||||
tasks:
|
|
||||||
- name: Create the groups the converge grants permissions to
|
|
||||||
ansible.builtin.group:
|
|
||||||
name: "{{ item }}"
|
|
||||||
state: present
|
|
||||||
loop:
|
|
||||||
- molecule-admins
|
|
||||||
- molecule-ops
|
|
||||||
|
|
||||||
- name: Create the users the converge grants permissions to
|
|
||||||
ansible.builtin.user:
|
|
||||||
name: "{{ item }}"
|
|
||||||
group: users
|
|
||||||
state: present
|
|
||||||
loop:
|
|
||||||
- molecule-alice
|
|
||||||
- molecule-bob
|
|
||||||
|
|
||||||
# The removal path of the role can only be observed on a drop-in file that exists before the role runs.
|
|
||||||
- name: Create the drop-in directory the seeded file lives in
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: /etc/sudoers.d
|
|
||||||
state: directory
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0750"
|
|
||||||
|
|
||||||
- name: Seed the drop-in file that the converge removes again
|
|
||||||
ansible.builtin.copy:
|
|
||||||
content: "molecule-alice ALL=NOPASSWD: /usr/bin/true\n"
|
|
||||||
dest: /etc/sudoers.d/molecule-obsolete
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0440"
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
# The role has no role dependencies, but molecule warns about the missing file.
|
|
||||||
roles: []
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
- name: Verify
|
|
||||||
hosts: all
|
|
||||||
vars:
|
|
||||||
# The exact spacing the sudoers module emits differs between releases, so only the tokens are matched.
|
|
||||||
_expected_rules:
|
|
||||||
molecule-alice: 'molecule-alice\s+ALL=\s*NOPASSWD:\s*/usr/bin/systemctl restart nginx'
|
|
||||||
molecule-bob-as-alice: 'molecule-bob\s+ALL=\(molecule-alice\)\s*NOPASSWD:\s*ALL'
|
|
||||||
molecule-ops: '%molecule-ops\s+ALL=\s*/usr/bin/id'
|
|
||||||
molecule-admins-as-root: '%molecule-admins\s+ALL=\(root\)\s*NOPASSWD:\s*ALL'
|
|
||||||
tasks:
|
|
||||||
- name: Stat the drop-in directory and the removed drop-in file
|
|
||||||
ansible.builtin.stat:
|
|
||||||
path: "{{ item }}"
|
|
||||||
register: _directory
|
|
||||||
loop:
|
|
||||||
- /etc/sudoers.d
|
|
||||||
- /etc/sudoers.d/molecule-obsolete
|
|
||||||
|
|
||||||
- name: Assert that the drop-in directory exists and that the obsolete drop-in file is gone
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- _directory.results[0].stat.isdir
|
|
||||||
- _directory.results[0].stat.mode == '0750'
|
|
||||||
- not _directory.results[1].stat.exists
|
|
||||||
fail_msg: "/etc/sudoers.d is not owned by the role or the file molecule-obsolete was not removed"
|
|
||||||
|
|
||||||
- name: Stat the drop-in files of the declared rules
|
|
||||||
ansible.builtin.stat:
|
|
||||||
path: "/etc/sudoers.d/{{ item.key }}"
|
|
||||||
register: _rule_files
|
|
||||||
loop: "{{ _expected_rules | dict2items }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.key }}"
|
|
||||||
|
|
||||||
- name: Assert that every drop-in file exists and is only readable by root
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- item.stat.exists
|
|
||||||
- item.stat.mode == '0440'
|
|
||||||
- item.stat.pw_name == 'root'
|
|
||||||
- item.stat.gr_name == 'root'
|
|
||||||
fail_msg: >-
|
|
||||||
/etc/sudoers.d/{{ item.item.key }} has mode {{ item.stat.mode | default('none') }} and owner
|
|
||||||
{{ item.stat.pw_name | default('none') }}:{{ item.stat.gr_name | default('none') }} instead of 0440 and root:root
|
|
||||||
loop: "{{ _rule_files.results }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.item.key }}"
|
|
||||||
|
|
||||||
- name: Read the drop-in files of the declared rules
|
|
||||||
ansible.builtin.slurp:
|
|
||||||
src: "/etc/sudoers.d/{{ item.key }}"
|
|
||||||
register: _rule_contents
|
|
||||||
loop: "{{ _expected_rules | dict2items }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.key }}"
|
|
||||||
|
|
||||||
- name: Assert that every drop-in file holds the declared rule
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that: item.content | b64decode is search(item.item.value)
|
|
||||||
fail_msg: >-
|
|
||||||
/etc/sudoers.d/{{ item.item.key }} contains
|
|
||||||
{{ item.content | b64decode | trim }} instead of a rule matching {{ item.item.value }}
|
|
||||||
loop: "{{ _rule_contents.results }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.item.key }}"
|
|
||||||
|
|
||||||
- name: Read /etc/sudoers
|
|
||||||
ansible.builtin.slurp:
|
|
||||||
src: /etc/sudoers
|
|
||||||
register: _sudoers
|
|
||||||
|
|
||||||
- name: Assert that the drop-in directory is included exactly once
|
|
||||||
vars:
|
|
||||||
_includedir: "{{ (_sudoers.content | b64decode).splitlines() | select('search', 'includedir\\s+/etc/sudoers.d') }}"
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that: _includedir == ['#includedir /etc/sudoers.d']
|
|
||||||
fail_msg: "/etc/sudoers includes the drop-in directory as {{ _includedir }}"
|
|
||||||
|
|
||||||
# A drop-in file that sudo rejects would lock out every rule of the directory.
|
|
||||||
- name: Assert that sudo is installed and parses the resulting configuration
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: visudo --check --strict
|
|
||||||
changed_when: false
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
collections:
|
|
||||||
# The sudoers module has been added in community.general 4.3.0, its runas
|
|
||||||
# parameter in 4.7.0.
|
|
||||||
- name: community.general
|
|
||||||
version: ">=4.7.0"
|
|
||||||
@@ -5,24 +5,22 @@
|
|||||||
vars:
|
vars:
|
||||||
params:
|
params:
|
||||||
files:
|
files:
|
||||||
- "{{ ansible_facts['distribution'] }}_{{ ansible_facts['architecture'] }}.yml"
|
- "{{ ansible_facts['distribution'] }}_{{ ansible_facts['architecture'] }}.yaml"
|
||||||
- "{{ ansible_facts['distribution'] }}.yml"
|
- "{{ ansible_facts['distribution'] }}.yaml"
|
||||||
- "{{ ansible_facts['os_family'] }}_{{ ansible_facts['architecture'] }}.yml"
|
- "{{ ansible_facts['os_family'] }}_{{ ansible_facts['architecture'] }}.yaml"
|
||||||
- "{{ ansible_facts['os_family'] }}.yml"
|
- "{{ ansible_facts['os_family'] }}.yaml"
|
||||||
- main.yml
|
- main.yaml
|
||||||
paths:
|
paths:
|
||||||
- vars
|
- vars
|
||||||
|
|
||||||
- name: Verify variables
|
- name: Verify variables
|
||||||
ansible.builtin.include_tasks: "{{ lookup('first_found', params) }}"
|
ansible.builtin.include_vars: "{{ lookup('first_found', params) }}"
|
||||||
vars:
|
vars:
|
||||||
params:
|
params:
|
||||||
files:
|
files:
|
||||||
- "{{ ansible_facts['distribution'] }}_verify_vars.yml"
|
- "{{ ansible_facts['distribution'] }}_verify_vars.yaml"
|
||||||
- "{{ ansible_facts['os_family'] }}_verify_vars.yml"
|
- "{{ ansible_facts['os_family'] }}_verify_vars.yaml"
|
||||||
- verify_vars.yml
|
- "verify_vars.yaml"
|
||||||
paths:
|
|
||||||
- tasks
|
|
||||||
|
|
||||||
- name: Install sudo
|
- name: Install sudo
|
||||||
ansible.builtin.package:
|
ansible.builtin.package:
|
||||||
@@ -34,72 +32,74 @@
|
|||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /etc/sudoers
|
dest: /etc/sudoers
|
||||||
state: present
|
state: present
|
||||||
# sudo >= 1.9.1 ships the directive as @includedir, older releases as #includedir
|
regexp: "^(#)+(\\s)*includedir(\\s)*/etc/sudoers.d"
|
||||||
regexp: "^[#@]+(\\s)*includedir(\\s)*/etc/sudoers\\.d"
|
|
||||||
line: "#includedir /etc/sudoers.d"
|
line: "#includedir /etc/sudoers.d"
|
||||||
validate: 'visudo --check --file %s'
|
validate: 'visudo --check --file %s'
|
||||||
mode: "0440"
|
mode: "0440"
|
||||||
owner: "root"
|
owner: "root"
|
||||||
group: "root"
|
group: "root"
|
||||||
|
|
||||||
- name: Create drop-in directory of sudoers
|
- name: Flush drop-in files of sudoers.d
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
state: directory
|
state: "{{ item }}"
|
||||||
path: "/etc/sudoers.d"
|
path: "/etc/sudoers.d"
|
||||||
owner: "root"
|
owner: "root"
|
||||||
group: "root"
|
group: "root"
|
||||||
mode: "0750"
|
mode: "0750"
|
||||||
|
with_items:
|
||||||
|
- absent
|
||||||
|
- directory
|
||||||
|
|
||||||
- name: "Create sudoers drop-in file to execute commands for specific unix users"
|
- name: "Create sudoers drop-in file to execute commands for specific unix users"
|
||||||
community.general.sudoers:
|
community.general.sudoers:
|
||||||
name: "{{ item.filename | default(item.user, true) }}"
|
name: "{{ item.filename | default(item.user) }}"
|
||||||
state: "{{ item.state | default('present') }}"
|
state: present
|
||||||
user: "{{ item.user }}"
|
user: "{{ item.user }}"
|
||||||
nopassword: "{{ item.nopassword | default(false) }}"
|
nopassword: "{{ item.nopassword | default(false) }}"
|
||||||
commands: "{{ item.commands | default('ALL') }}"
|
commands: "{{ item.commands | default('ALL') }}"
|
||||||
with_items:
|
with_items:
|
||||||
- "{{ sudo_users_sudoers }}"
|
- "{{ sudo_users_sudoers }}"
|
||||||
when: item.user | default('') | length > 0 and
|
when: item.user is defined and item.user | length > 0 and
|
||||||
item.group | default('') | length == 0 and
|
item.group is not defined and
|
||||||
item.runas | default('') | length == 0
|
item.runas is not defined
|
||||||
|
|
||||||
- name: "Create sudoers drop-in file to execute commands for specific unix users as specific unix user"
|
- name: "Create sudoers drop-in file to execute commands for specific unix users as specific unix user"
|
||||||
community.general.sudoers:
|
community.general.sudoers:
|
||||||
name: "{{ item.filename | default(item.user, true) }}"
|
name: "{{ item.filename | default(item.user) }}"
|
||||||
state: "{{ item.state | default('present') }}"
|
state: present
|
||||||
user: "{{ item.user }}"
|
user: "{{ item.user }}"
|
||||||
runas: "{{ item.runas }}"
|
runas: "{{ item.runas }}"
|
||||||
nopassword: "{{ item.nopassword | default(false) }}"
|
nopassword: "{{ item.nopassword | default(false) }}"
|
||||||
commands: "{{ item.commands | default('ALL') }}"
|
commands: "{{ item.commands | default('ALL') }}"
|
||||||
with_items:
|
with_items:
|
||||||
- "{{ sudo_users_sudoers }}"
|
- "{{ sudo_users_sudoers }}"
|
||||||
when: item.user | default('') | length > 0 and
|
when: item.user is defined and item.user | length > 0 and
|
||||||
item.group | default('') | length == 0 and
|
item.group is not defined and
|
||||||
item.runas | default('') | length > 0
|
item.runas is defined and item.runas | length > 0
|
||||||
|
|
||||||
- name: "Create sudoers drop-in file to execute commands for specific unix groups"
|
- name: "Create sudoers drop-in file to execute commands for specific unix groups"
|
||||||
community.general.sudoers:
|
community.general.sudoers:
|
||||||
name: "{{ item.filename | default(item.group, true) }}"
|
name: "{{ item.filename | default(item.group) }}"
|
||||||
state: "{{ item.state | default('present') }}"
|
state: present
|
||||||
group: "{{ item.group }}"
|
group: "{{ item.group }}"
|
||||||
nopassword: "{{ item.nopassword | default(false) }}"
|
nopassword: "{{ item.nopassword | default(false) }}"
|
||||||
commands: "{{ item.commands | default('ALL') }}"
|
commands: "{{ item.commands | default('ALL') }}"
|
||||||
with_items:
|
with_items:
|
||||||
- "{{ sudo_users_sudoers }}"
|
- "{{ sudo_users_sudoers }}"
|
||||||
when: item.user | default('') | length == 0 and
|
when: item.user is not defined and
|
||||||
item.group | default('') | length > 0 and
|
item.group is defined and item.group | length > 0 and
|
||||||
item.runas | default('') | length == 0
|
item.runas is not defined
|
||||||
|
|
||||||
- name: "Create sudoers drop-in file to execute commands for specific unix groups as specifix unix user"
|
- name: "Create sudoers drop-in file to execute commands for specific unix groups as specifix unix user"
|
||||||
community.general.sudoers:
|
community.general.sudoers:
|
||||||
name: "{{ item.filename | default(item.group, true) }}"
|
name: "{{ item.filename | default(item.group) }}"
|
||||||
state: "{{ item.state | default('present') }}"
|
state: present
|
||||||
group: "{{ item.group }}"
|
group: "{{ item.group }}"
|
||||||
runas: "{{ item.runas }}"
|
runas: "{{ item.runas }}"
|
||||||
nopassword: "{{ item.nopassword | default(false) }}"
|
nopassword: "{{ item.nopassword | default(false) }}"
|
||||||
commands: "{{ item.commands | default('ALL') }}"
|
commands: "{{ item.commands | default('ALL') }}"
|
||||||
with_items:
|
with_items:
|
||||||
- "{{ sudo_users_sudoers }}"
|
- "{{ sudo_users_sudoers }}"
|
||||||
when: item.user | default('') | length == 0 and
|
when: item.user is not defined and
|
||||||
item.group | default('') | length > 0 and
|
item.group is defined and item.group | length > 0 and
|
||||||
item.runas | default('') | length > 0
|
item.runas is defined and item.runas | length > 0
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
# - name: Verify if not user and group exists for each entry
|
||||||
|
# ansible.builtin.assert:
|
||||||
|
# that:
|
||||||
|
# - (item.user is defined and item.group is not defined) or
|
||||||
|
# (item.user is not defined and item.group is defined)
|
||||||
|
# with_items: "{{ sudo_users_sudoers }}"
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
|
|
||||||
- name: Verify that each entry defines either a user or a group
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- (item.user is defined and item.user | length > 0) !=
|
|
||||||
(item.group is defined and item.group | length > 0)
|
|
||||||
fail_msg: >
|
|
||||||
Each entry of sudo_users_sudoers must define either 'user' or 'group',
|
|
||||||
but not both and not none.
|
|
||||||
quiet: true
|
|
||||||
with_items: "{{ sudo_users_sudoers }}"
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user