From d0bbb879904d27426a596ed14addfc73bdf67e89 Mon Sep 17 00:00:00 2001 From: Radovan Sroka Date: Tue, 21 May 2024 11:46:59 +0200 Subject: [PATCH] feat: Add the sudo role (#2) Signed-off-by: Radovan Sroka --- .ansible-lint | 2 +- README.md | 458 +++++++++++++++--- contributing.md | 8 +- defaults/main.yml | 74 ++- examples/simple.yml | 9 - handlers/main.yml | 7 - meta/collection-requirements.yml | 4 - meta/main.yml | 57 +-- tasks/main.yml | 96 +++- templates/foo.conf.j2 | 9 - templates/sudoers.j2 | 174 +++++++ .../tests_large_configuration_pingers.ok | 10 + tests/files/tests_large_configuration_root.ok | 10 + .../tests_large_configuration_sudoers.ok | 46 ++ tests/files/tests_multiple_sudoers_pingers.ok | 7 + tests/files/tests_multiple_sudoers_root.ok | 10 + tests/files/tests_multiple_sudoers_sudoers.ok | 34 ++ tests/files/tests_role_applied.ok | 26 + tests/roles/linux-system-roles.sudo/defaults | 1 + tests/roles/linux-system-roles.sudo/handlers | 1 + tests/roles/linux-system-roles.sudo/meta | 1 + tests/roles/linux-system-roles.sudo/tasks | 1 + tests/roles/linux-system-roles.sudo/templates | 1 + tests/roles/linux-system-roles.sudo/vars | 1 + tests/setup-snapshot.yml | 4 +- tests/tasks/assert_files_identical.yml | 18 + tests/tests_default.yml | 6 +- tests/tests_include_vars_from_parent.yml | 2 +- tests/tests_large_configuration.yml | 222 +++++++++ tests/tests_multiple_sudoers.yml | 174 +++++++ tests/tests_role_applied.yml | 66 +++ vars/CentOS_7.yml | 7 - vars/CentOS_8.yml | 7 - vars/CentOS_9.yml | 7 - vars/Fedora.yml | 7 - vars/RedHat_7.yml | 7 - vars/RedHat_8.yml | 7 - vars/RedHat_9.yml | 7 - vars/main.yml | 21 +- 39 files changed, 1362 insertions(+), 247 deletions(-) delete mode 100644 examples/simple.yml delete mode 100644 handlers/main.yml delete mode 100644 meta/collection-requirements.yml delete mode 100644 templates/foo.conf.j2 create mode 100644 templates/sudoers.j2 create mode 100644 tests/files/tests_large_configuration_pingers.ok create mode 100644 tests/files/tests_large_configuration_root.ok create mode 100644 tests/files/tests_large_configuration_sudoers.ok create mode 100644 tests/files/tests_multiple_sudoers_pingers.ok create mode 100644 tests/files/tests_multiple_sudoers_root.ok create mode 100644 tests/files/tests_multiple_sudoers_sudoers.ok create mode 100644 tests/files/tests_role_applied.ok create mode 120000 tests/roles/linux-system-roles.sudo/defaults create mode 120000 tests/roles/linux-system-roles.sudo/handlers create mode 120000 tests/roles/linux-system-roles.sudo/meta create mode 120000 tests/roles/linux-system-roles.sudo/tasks create mode 120000 tests/roles/linux-system-roles.sudo/templates create mode 120000 tests/roles/linux-system-roles.sudo/vars create mode 100644 tests/tasks/assert_files_identical.yml create mode 100644 tests/tests_large_configuration.yml create mode 100644 tests/tests_multiple_sudoers.yml create mode 100644 tests/tests_role_applied.yml delete mode 100644 vars/CentOS_7.yml delete mode 100644 vars/CentOS_8.yml delete mode 100644 vars/CentOS_9.yml delete mode 100644 vars/Fedora.yml delete mode 100644 vars/RedHat_7.yml delete mode 100644 vars/RedHat_8.yml delete mode 100644 vars/RedHat_9.yml diff --git a/.ansible-lint b/.ansible-lint index 8986d7a..85ce45b 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -21,4 +21,4 @@ exclude_paths: - .markdownlint.yaml - examples/roles/ mock_roles: - - linux-system-roles.template + - linux-system-roles.sudo diff --git a/README.md b/README.md index dc99348..cda4b60 100644 --- a/README.md +++ b/README.md @@ -1,105 +1,435 @@ -# Role Name +# Sudo -[![ansible-lint.yml](https://github.com/linux-system-roles/template/actions/workflows/ansible-lint.yml/badge.svg)](https://github.com/linux-system-roles/template/actions/workflows/ansible-lint.yml) [![ansible-test.yml](https://github.com/linux-system-roles/template/actions/workflows/ansible-test.yml/badge.svg)](https://github.com/linux-system-roles/template/actions/workflows/ansible-test.yml) [![markdownlint.yml](https://github.com/linux-system-roles/template/actions/workflows/markdownlint.yml/badge.svg)](https://github.com/linux-system-roles/template/actions/workflows/markdownlint.yml) [![shellcheck.yml](https://github.com/linux-system-roles/template/actions/workflows/shellcheck.yml/badge.svg)](https://github.com/linux-system-roles/template/actions/workflows/shellcheck.yml) [![woke.yml](https://github.com/linux-system-roles/template/actions/workflows/woke.yml/badge.svg)](https://github.com/linux-system-roles/template/actions/workflows/woke.yml) - -![template](https://github.com/linux-system-roles/template/workflows/tox/badge.svg) - -A template for an ansible role that configures some GNU/Linux subsystem or -service. A brief description of the role goes here. +This role configures sudo. ## Requirements -Any prerequisites that may not be covered by Ansible itself or the role should -be mentioned here. This includes platform dependencies not managed by the -role, hardware requirements, external collections, etc. There should be a -distinction between *control node* requirements (like collections) and -*managed node* requirements (like special hardware, platform provisioning). +This role is only supported on RHEL8+ and Fedora distributions. +Consider reading sudo documentation before setting it up. ### Collection requirements -For instance, if the role depends on some collections and has a -`meta/collection-requirements.yml` file for installing those dependencies, and -in order to manage `rpm-ostree` systems, it should be mentioned here that the - user should run +None. + +## Role Variables + +The defaults defined for this role are based on a default RHEL8.4 `/etc/sudoers` configuration. +Check the defaults in [`defaults/main.yml`](defaults/main.yml) prior to running for OS compatibility. + +### sudo_rewrite_default_sudoers_file + +Use role default or user defined `sudo_sudoers_files` definition, replacing your distribution supplied `/etc/sudoers` file. +Useful when attempting to deploy new configuration files to the `include_directories` and you do not wish to modify the `/etc/sudoers` file. + +Default: `true` + +Type: `bool` + +### sudo_remove_unauthorized_included_files + +***Dangerous!*** Setting this to `true` removes each existing sudoers file in the `include_directories` dictionary that are not defined in the`sudo_sudoers_files` variable. +This allows for enforcing a desired state. + +Default: `false` +Type: `bool` + +### sudo_visudo_path + +Fully-qualified path to the `visudo` binary required for validation of sudoers configuration changes +Added for Operating System compatibility. + +Default: `/usr/bin/visudo` + +Type: `string` + +### sudo_sudoers_files + +A list that defines sudoers configurations. -```bash -ansible-galaxy collection install -vv -r meta/collection-requirements.yml +For the default configuration, see [defaults/main.yml](defaults/main.yml). + +Type: `list` + +#### path + +Where to deploy the configuration file to on the filesystem. + +Type: `string` + +#### aliases + +A dictionary containing optional definition of `User_Alias`, `Runas_Alias`, `Host_Alias`, and `Cmnd_Alias` aliases. + +This dictionary can be used to assign either user specifications or default overrides. + +Available keys: + +1. `user_alias`, requires setting a name with the `name` string and a list of users with the `users` list. +2. `runas_alias`, requires setting a name with the `name` string and a list of users with the `users` list. +3. `host_alias`, requires setting a name with the `name` string and a list of hosts with the `hosts` list. +4. `cmnd_alias`, requires setting a name with the `name` string and a list of commands with the `commands` list. + +Example definition: + +```yaml +sudo_sudoers_files: + aliases: + user_alias: + - name: PINGERS + users: + - username + runas_alias: + - name: RUNAS + users: + - username + cmnd_alias: + - name: PING + commands: + - /usr/bin/ping + cmnd_alias: + - name: PING + commands: + - /usr/bin/ping ``` -on the *control node* before using the role. +#### defaults -## Role Variables +You can use this to define the defaults of sudoers configuration. + +You can perform default overrides via the [`user_specifications`](#default-override-user_specifications) key. + +Type: `list` + +#### include_files + +Optional, a list of files that your configuration must include. + +This is a list of fully-qualified paths to include via the `#include` option of a sudoers configuration. -A description of all input variables (i.e. variables that are defined in -`defaults/main.yml`) for the role should go here as these form an API of the -role. Each variable should have its own section e.g. +Type: `list` -### template_foo +#### include_directories -This variable is required. It is a string that lists the foo of the role. -There is no default value. +Optional, a list of directories that your configurations must include. -### template_bar +This is a list of fully-qualified paths to directories to include via the `#includedir` option of a sudoers configuration. -This variable is optional. It is a boolean that tells the role to disable bar. -The default value is `true`. +Type: `list` -Variables that are not intended as input, like variables defined in -`vars/main.yml`, variables that are read from other roles and/or the global -scope (ie. hostvars, group vars, etc.) can be also mentioned here but keep in -mind that as these are probably not part of the role API they may change during -the lifetime. +#### user_specifications -Example of setting the variables: +You can use this `list` variable to apply user specifications to a sudoers file configuration. + +Supported entries: + +1. `users` - List of users to apply the specification to. +You can use a `user_alias` name as well as user names. + +2. `hosts` - List of hosts to apply the specification to. +You can use a defined `host_alias` name as well as host names. + +3. `operators` - List of operators to apply the specification to. +You can use a defined `runas_alias` name as well as user names. + +4. `selinux_role` - Optional selinux role to apply to the specification. + +5. `selinux_type` - Optional selinux type to apply to the specification. + +6. `solaris_privs` - Optional Solaris privset to apply to the specification. + +7. `solaris_limitprivs` - Optional Solaris privset to apply to the specification. + +8. `tags` - Optional list of tags to apply to the specification. + +9. `commands` - List of commands to apply the specification to. +You can use a defined `cmnd_alias` name as well as commands. + +Example definition: ```yaml -template_foo: "oof" -template_bar: false + sudo_sudoers_files: + - path: /etc/sudoers.d/pingers + user_specifications: + - users: + - root + hosts: + - ALL + operators: + - ALL + commands: + - ALL + - users: + - "%wheel" + hosts: + - ALL + operators: + - ALL + commands: + - ALL ``` -## Variables Exported by the Role +#### default_overrides + +You can use this `list` variable to apply Default Override user_specifications to a sudoers file configuration. + +Supported entries: + +1. `defaults` - List of defaults to override from the main configuration. -This section is optional. Some roles may export variables for playbooks to -use later. These are analogous to "return values" in Ansible modules. For -example, if a role performs some action that will require a system reboot, but -the user wants to defer the reboot, the role might set a variable like -`template_reboot_needed: true` that the playbook can use to reboot at a more -convenient time. +2. `type` - Type of default to override, this affects the operator in the configuration ( host -> `@`, user -> `:`, command -> `!`, and runas -> `>`). +The type field can be one of the following values: `command`, `host`, `runas`, or `user`. -Example: +3. `commands` - Use when `type: command`. +List of `cmnd_alias` names as well as commands to override specific default values. -### template_reboot_needed +4. `hosts` - Use when `type: host`. +List of `host_alias` names as well as individual host names to override specific default values. -Default `false` - if `true`, this means a reboot is needed to apply the changes -made by the role +5. `operators` - Use when `type: runas`. +List of `runas_alias` names as well as individual user names to override specific default values. -## Example Playbook +6. `users` - Use when `type: user`. +List of `user_alias` names as well as individual user names to override specific default values. -Including an example of how to use your role (for instance, with variables -passed in as parameters) is always nice for users too: +Example Definition: ```yaml -- name: Manage the template subsystem + sudo_sudoers_files: + - path: /etc/sudoers.d/pingers + default_overrides: + - type: user + defaults: + - "!requiretty" + users: + - PINGERS + - type: runas + defaults: + - "!set_logname" + operators: + - root + - type: host + defaults: + - "!requiretty" + - "!requiretty" + hosts: + - host1 + - host2 + - type: command + defaults: + - "!requiretty" + commands: + - /usr/bin/ls +``` + +## Example Playbooks + +### Applying a RHEL Default /etc/sudoers configuration + +```yaml +--- +- name: Apply a RHEL Default /etc/sudoers configuration + hosts: all + roles: + - role: linux-system-roles.sudo +``` + +### Applying custom /etc/sudoers configuration + +```yaml +--- +- name: Apply a custom /etc/sudoers configuration hosts: all vars: - template_foo: "foo foo!" - template_bar: false + sudoers_files: + - path: /etc/sudoers + user_specifications: + - users: + - root + hosts: + - x + commands: + - /usr/bin/ls roles: - - linux-system-roles.template + - role: linux-system-roles.sudo ``` -More examples can be provided in the [`examples/`](examples) directory. These -can be useful, especially for documentation. +### Applying defaults -## rpm-ostree +```yaml +--- +- name: Apply defaults + hosts: all + vars: + sudoers_files: + - path: /etc/sudoers + defaults: + - "!visiblepw" + - always_set_home + - match_group_by_gid + - always_query_group_plugin + - env_reset + - secure_path: + - /sbin + - /bin + - /usr/sbin + - /usr/bin + - env_keep: + - COLORS + - DISPLAY + - HOSTNAME + - HISTSIZE + - KDEDIR + - LS_COLORS + - MAIL + - PS1 + - PS2 + - QTDIR + - USERNAME + - LANG + - LC_ADDRESS + - LC_CTYPE + - LC_COLLATE + - LC_IDENTIFICATION + - LC_MEASUREMENT + - LC_MESSAGES + - LC_MONETARY + - LC_NAME + - LC_NUMERIC + - LC_PAPER + - LC_TELEPHONE + - LC_TIME + - LC_ALL + - LANGUAGE + - LINGUAS + - _XKB_CHARSET + - XAUTHORITY + user_specifications: + - users: + - root + hosts: + - ALL + operators: + - ALL + commands: + - ALL + - users: + - "%wheel" + hosts: + - ALL + operators: + - ALL + commands: + - ALL + include_directories: + - /etc/sudoers.d + roles: + - role: linux-system-roles.sudo +``` -See README-ostree.md +### Applying a multi-file sudoers configuration -## License +```yaml +--- +- name: Apply a multi-file sudoers configuration + hosts: all + tasks: + - name: Configure /etc/sudoers and included files + include_role: + name: linux-system-roles.sudo + vars: + sudo_rewrite_default_sudoers_file: true + sudo_remove_unauthorized_included_files: true + sudo_sudoers_files: + - path: /etc/sudoers + defaults: + - "!visiblepw" + - always_set_home + - match_group_by_gid + - always_query_group_plugin + - env_reset + - secure_path: + - /sbin + - /bin + - /usr/sbin + - /usr/bin + - env_keep: + - COLORS + - DISPLAY + - HOSTNAME + - HISTSIZE + - KDEDIR + - LS_COLORS + - MAIL + - PS1 + - PS2 + - QTDIR + - USERNAME + - LANG + - LC_ADDRESS + - LC_CTYPE + - LC_COLLATE + - LC_IDENTIFICATION + - LC_MEASUREMENT + - LC_MESSAGES + - LC_MONETARY + - LC_NAME + - LC_NUMERIC + - LC_PAPER + - LC_TELEPHONE + - LC_TIME + - LC_ALL + - LANGUAGE + - LINGUAS + - _XKB_CHARSET + - XAUTHORITY + user_specifications: + - users: + - root + hosts: + - ALL + operators: + - ALL + commands: + - ALL + - users: + - "%wheel" + hosts: + - ALL + operators: + - ALL + commands: + - ALL + include_directories: + - /etc/sudoers.d + aliases: + cmnd_alias: + - name: PING + commands: + - /usr/bin/ping + user_alias: + - name: PINGERS + users: + - username + - path: /etc/sudoers.d/pingers + user_specifications: + - type: user + defaults: + - "!requiretty" + users: + - PINGERS + - path: /etc/sudoers.d/root + defaults: + - syslog=auth + user_specifications: + - type: runas + defaults: + - "!set_logname" + operators: + - root +``` -Whenever possible, please prefer MIT. +## License -## Author Information +MIT -An optional section for the role authors to include contact information, or a -website (HTML is not allowed). +Based on [Ansible-sudoers](https://github.com/ahuffman/ansible-sudoers). diff --git a/contributing.md b/contributing.md index 44e3ad0..6c64db5 100644 --- a/contributing.md +++ b/contributing.md @@ -1,4 +1,4 @@ -# Contributing to the template Linux System Role +# Contributing to the Sudo Linux System Role ## Where to start @@ -12,10 +12,10 @@ This has all of the common information that all role developers need: * How to create git commits and submit pull requests **Bugs and needed implementations** are listed on -[Github Issues](https://github.com/linux-system-roles/template/issues). +[Github Issues](https://github.com/linux-system-roles/sudo/issues). Issues labeled with -[**help wanted**](https://github.com/linux-system-roles/template/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) +[**help wanted**](https://github.com/linux-system-roles/sudo/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) are likely to be suitable for new contributors! -**Code** is managed on [Github](https://github.com/linux-system-roles/template), using +**Code** is managed on [Github](https://github.com/linux-system-roles/sudo), using [Pull Requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests). diff --git a/defaults/main.yml b/defaults/main.yml index 6944529..f2e7191 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,8 +1,70 @@ -# SPDX-License-Identifier: MIT --- -# Here is the right place to put the role's input variables. -# This file also serves as a documentation for such a variables. +sudo_rewrite_default_sudoers_file: true +sudo_remove_unauthorized_included_files: false -# Examples of role input variables: -template_foo: foo -template_bar: true +sudo_visudo_path: /usr/sbin/visudo + +sudo_sudoers_files: + - path: /etc/sudoers + defaults: + - "!visiblepw" + - always_set_home + - match_group_by_gid + - always_query_group_plugin + - env_reset + - secure_path: + - /sbin + - /bin + - /usr/sbin + - /usr/bin + - env_keep: + - COLORS + - DISPLAY + - HOSTNAME + - HISTSIZE + - KDEDIR + - LS_COLORS + - MAIL + - PS1 + - PS2 + - QTDIR + - USERNAME + - LANG + - LC_ADDRESS + - LC_CTYPE + - LC_COLLATE + - LC_IDENTIFICATION + - LC_MEASUREMENT + - LC_MESSAGES + - LC_MONETARY + - LC_NAME + - LC_NUMERIC + - LC_PAPER + - LC_TELEPHONE + - LC_TIME + - LC_ALL + - LANGUAGE + - LINGUAS + - _XKB_CHARSET + - XAUTHORITY + user_specifications: + - users: + - root + hosts: + - ALL + operators: + - ALL + commands: + - ALL + - users: + - "%wheel" + hosts: + - ALL + operators: + - ALL + commands: + - ALL + include_directories: + - /etc/sudoers.d + # include_files: [] + # aliases: [] diff --git a/examples/simple.yml b/examples/simple.yml deleted file mode 100644 index 4f1456e..0000000 --- a/examples/simple.yml +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -- name: Example template role invocation - hosts: all - vars: - template_foo: example variable value - template_bar: false - roles: - - linux-system-roles.template diff --git a/handlers/main.yml b/handlers/main.yml deleted file mode 100644 index 726022e..0000000 --- a/handlers/main.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -- name: Handler for template to restart services - service: - name: "{{ item }}" - state: restarted - loop: "{{ __template_services }}" diff --git a/meta/collection-requirements.yml b/meta/collection-requirements.yml deleted file mode 100644 index 0110bbe..0000000 --- a/meta/collection-requirements.yml +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -collections: - - ansible.posix diff --git a/meta/main.yml b/meta/main.yml index 0862691..25e4ebf 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,68 +1,21 @@ # SPDX-License-Identifier: MIT --- galaxy_info: - # Replace with role's author name: - author: John Doe - # Replace with the real description of what is role's purpose: - description: Basic template for Linux system roles - # Replace with the company the role's author is member of: - company: John Doe, Inc. - - # If the issue tracker for your role is not on github, uncomment the next - # line and provide a value - # issue_tracker_url: http://example.com/issue/tracker - - # Some suggested licenses: - # - BSD (default) - # - MIT - # - GPLv2 - # - GPLv3 - # - Apache - # - CC-BY + author: Radovan Sroka + description: Sudo system role + company: Red Hat Inc. license: MIT min_ansible_version: "2.9" - - # Optionally specify the branch Galaxy will use when accessing the GitHub - # repo for this role. During role install, if no tags are available, Galaxy - # will use this branch. During import Galaxy will access files on this - # branch. If Travis integration is configured, only notifications for this - # branch will be accepted. Otherwise, in all cases, the repo's default branch - # (usually main) will be used. - # github_branch: - - # - # platforms is a list of platforms, and each platform has a name and a list - # of versions. - # - # platforms: - # - name: Fedora - # versions: - # - all - # - "25" - # - name: SomePlatform - # versions: - # - all - # - "1.0" - # - "7" - # - "99.99" platforms: - # Replace the below with your platform list: - name: Fedora versions: - all - name: EL versions: - - all + - "8" + - "9" galaxy_tags: [] - # List tags for your role here, one per line. A tag is a keyword that - # describes and categorizes the role. Users find roles by searching for tags. - # Be sure to remove the '[]' above, if you add tags to this list. - # - # NOTE: A tag is limited to a single word comprised of alphanumeric - # characters. Maximum 20 tags per role. dependencies: [] -# List your role dependencies here, one per line. Be sure to remove the '[]' -# above, if you add dependencies to this list. diff --git a/tasks/main.yml b/tasks/main.yml index f510ef4..2453457 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,27 +1,81 @@ -# SPDX-License-Identifier: MIT --- -- name: Set platform/version specific variables - include_tasks: tasks/set_vars.yml - -# Examples of some tasks: -- name: Ensure required packages are installed +- name: Ensure sudo is installed package: - name: "{{ __template_packages }}" + name: sudo state: present - use: "{{ (__template_is_ostree | d(false)) | - ternary('ansible.posix.rhel_rpm_ostree', omit) }}" -- name: Ensure required services are enabled and started - service: - name: "{{ item }}" - state: started - enabled: true - loop: "{{ __template_services }}" +- name: Set include directories variable + set_fact: + sudo_include_dirs: "{{ sudo_sudoers_files + | selectattr('include_directories', 'defined') + | map(attribute='include_directories') | flatten }}" + +- name: Set sudoer file paths variable + set_fact: + sudo_file_paths: "{{ sudo_sudoers_files + | selectattr('path', 'defined') + | map(attribute='path') | flatten }}" + +- name: Ensure include directories are created + file: + path: "{{ item }}" + owner: root + group: root + mode: 0750 + state: directory + with_items: "{{ sudo_include_dirs }}" + when: sudo_include_dirs | length > 0 + +- name: Ensure sudoers include files are configured + template: + src: sudoers.j2 + dest: "{{ item.path }}" + owner: root + group: root + mode: 0440 + validate: "{{ sudo_visudo_path }} -cf %s" + with_items: "{{ sudo_sudoers_files }}" + loop_control: + label: "{{ item.path }}" + when: item.path != '/etc/sudoers' -- name: Generate /etc/{{ __template_foo_config }} +- name: Ensure /etc/sudoers is configured template: - src: "{{ __template_foo_config }}.j2" - dest: /etc/{{ __template_foo_config }} - backup: true - mode: 0400 - notify: Handler for template to restart services + src: sudoers.j2 + dest: "{{ item.path }}" + owner: root + group: root + mode: 0440 + validate: "{{ sudo_visudo_path }} -cf %s" + with_items: "{{ sudo_sudoers_files }}" + loop_control: + label: "{{ item.path }}" + when: + - item.path == '/etc/sudoers' + - sudo_rewrite_default_sudoers_file | bool + +- name: Remove unauthorized included sudoer files + when: + - sudo_remove_unauthorized_included_files | bool + - sudo_include_dirs | length > 0 + block: + - name: Search for sudoers files in included directories + find: + paths: "{{ sudo_include_dirs }}" + recurse: true + hidden: true + file_type: any + register: sudo_existing_included_files + + - name: Set unauthorized included sudoers files variable + set_fact: + sudo_unauthorized_files: "{{ sudo_existing_included_files['files'] + | selectattr('path', 'defined') | map(attribute='path') + | flatten | difference(sudo_file_paths) }}" + + - name: Remove unauthorized included sudoers files + file: + path: "{{ item }}" + state: absent + with_items: "{{ sudo_unauthorized_files }}" + when: sudo_unauthorized_files | length > 0 diff --git a/templates/foo.conf.j2 b/templates/foo.conf.j2 deleted file mode 100644 index 5fc204b..0000000 --- a/templates/foo.conf.j2 +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: MIT -# -# Example of a template of configuration file -# -{{ ansible_managed | comment }} -{{ "system_role:template" | comment(prefix="", postfix="") }} -[foo] -foo = {{ template_foo }} -bar = {{ template_bar }} diff --git a/templates/sudoers.j2 b/templates/sudoers.j2 new file mode 100644 index 0000000..6d0fd8a --- /dev/null +++ b/templates/sudoers.j2 @@ -0,0 +1,174 @@ +{%- macro render_aliases(alias_desc,alias_str,alias_dict,alias_subdict_name) %} +{% if item.aliases[alias_dict] is defined %} + +## {{ alias_desc }} +{% for alias_item in item.aliases[alias_dict] %} +{% set _alias = [] %} +{% for alias_val in alias_item[alias_subdict_name] %} +{% set _ = _alias.append(alias_val) %} +{% endfor %} +{{ alias_str }} {{ alias_item.name }} = {{ _alias | join(", ") }} +{% endfor %} +{% endif %} +{% endmacro -%} +{%- macro render_override_spec(spec,spec_type, spec_dict, sign) %} +{% if spec.type == spec_type %} +{% set _spec_original = [] %} +{% set _spec_default = [] %} +{% for spec_original in spec[spec_dict] %} +{% set _ = _spec_original.append(spec_original) %} +{% endfor %} +{% for spec_default in spec.defaults %} +{% set _ = _spec_default.append(spec_default) %} +{% endfor %} +Defaults{{ sign }} {{ _spec_original | join(", ")}} {{ _spec_default | + join(", ")}} +{% endif %} +{% endmacro -%} +{{ ansible_managed | default('Ansible managed') | comment }} +{{ "system_role:sudo" | comment(prefix="", postfix="") }} +{%- if item.defaults is defined %} + +# Default specifications +{% for default in item.defaults %} +{% if default is mapping %} +{% for name, values in default.items() %} +{% if name == 'secure_path' %} +{% set paths = [] %} +{% for my_value in values %} +{% set _ = paths.append(my_value) %} +{% endfor %} +Defaults {{ name }} = {{ paths | join(":") }} +{% else %} +{% for items in values | list | slice(6) %} +{% if items %} +{% if loop.first %} +Defaults {{ name }} = "{{ items | list | join(' ') }}" +{% else %} +Defaults {{ name }} += "{{ items | list | join(' ') }}" +{% endif -%} +{% endif -%} +{% endfor %} +{% endif %} +{% endfor %} +{% elif default | first == ':' %} +Defaults{{ default }} +{% else %} +Defaults {{ default }} +{% endif %} +{% endfor %} +{% endif -%} +{%- if item.aliases is defined %} + +# Alias specifications +{{ render_aliases("Command Aliases", "Cmnd_Alias", "cmnd_alias", "commands") -}} +{{ render_aliases("Host Aliases", "Host_Alias", "host_alias", "hosts") -}} +{{ render_aliases("Runas Aliases", "Runas_Alias", "runas_alias", "users") -}} +{{ render_aliases("User Aliases", "User_Alias", "user_alias", "users") -}} +{% endif -%} +{%- if item.user_specifications is defined %} + +# User specifications +{% for spec in item.user_specifications %} +{% set user_spec = [] %} +{% set spec_users = [] %} +{% set spec_hosts = [] %} +{% set spec_ops = [] %} +{% set spec_types = [] %} +{% set spec_roles = [] %} +{% set spec_privs = [] %} +{% set spec_lprivs = [] %} +{% set spec_tags = [] %} +{% set spec_cmnds = [] %} +{% for user in spec.users %} +{% set _ = spec_users.append(user) %} +{% endfor %} +{% set _ = user_spec.append(spec_users | join(", ")) %} +{% set _ = user_spec.append(" ") %} +{% for host in spec.hosts %} +{% set _ = spec_hosts.append(host) %} +{% endfor %} +{% set _ = user_spec.append(spec_hosts | join(", ")) %} +{% set _ = user_spec.append("=") %} +{% if spec.operators is defined %} +{% set _ = user_spec.append("(") %} +{% for op in spec.operators %} +{% set _ = spec_ops.append(op) %} +{% endfor %} +{% set _ = user_spec.append(spec_ops | join(", ")) %} +{% set _ = user_spec.append(")") %} +{% endif %} +{% set _ = user_spec.append(" ") %} +{% if spec.selinux_type is defined %} +{% set _ = user_spec.append("TYPE=") %} +{% for type in spec.selinux_type %} +{% set _ = spec_types.append(type) %} +{% endfor %} +{% set _ = user_spec.append(spec_types | join(", ")) %} +{% set _ = user_spec.append(" ") %} +{% endif %} +{% if spec.selinux_role is defined %} +{% set _ = user_spec.append("ROLE=") %} +{% for role in spec.selinux_role %} +{% set _ = spec_roles.append(role) %} +{% endfor %} +{% set _ = user_spec.append(spec_roles | join(", ")) %} +{% set _ = user_spec.append(" ") %} +{% endif %} +{% if spec.solaris_privs is defined %} +{% set _ = user_spec.append("PRIVS=") %} +{% for priv in spec.solaris_privs %} +{% set _ = spec_privs.append(priv) %} +{% endfor %} +{% set _ = user_spec.append(spec_privs | join(", ")) %} +{% set _ = user_spec.append(" ") %} +{% endif %} +{% if spec.solaris_limitprivs is defined %} +{% set _ = user_spec.append("LIMITPRIVS=") %} +{% for lpriv in spec.solaris_limitprivs %} +{% set _ = spec_lprivs.append(lpriv) %} +{% endfor %} +{% set _ = user_spec.append(spec_lprivs | join(", ")) %} +{% set _ = user_spec.append(" ") %} +{% endif %} +{% if spec.tags is defined %} +{% for tag in spec.tags %} +{% set _ = spec_tags.append(tag) %} +{% endfor %} +{% set _ = user_spec.append(spec_tags | join(":")) %} +{% set _ = user_spec.append(": ") %} +{% endif %} +{% for cmnd in spec.commands %} +{% set _ = spec_cmnds.append(cmnd) %} +{% endfor %} +{% set _ = user_spec.append(spec_cmnds | join(", ")) %} +{{ user_spec | join('') }} +{% endfor %} +{% endif -%} +{%- if item.default_overrides is defined %} + +# Default override specifications +{% for spec in item.default_overrides %} +{{ render_override_spec(spec,"user","users",":") -}} +{{ render_override_spec(spec,"runas","operators",">") -}} +{{ render_override_spec(spec,"host","hosts","@") -}} +{{ render_override_spec(spec,"command","commands","!") -}} +{% endfor %} +{%- endif %} +{%- if item.include_files is defined or item.include_directories is defined %} + +# Includes +{% if item.include_files is defined and item.include_files | length > 0 %} +## Include files +{% for file in item.include_files %} +#include {{ file }} +{% endfor %} +{% endif %} +{% if item.include_directories is defined and item.include_directories | + length > 0 %} +## Include directories +{% for dir in item.include_directories %} +#includedir {{ dir }} +{% endfor %} +{% endif %} +{% endif -%} diff --git a/tests/files/tests_large_configuration_pingers.ok b/tests/files/tests_large_configuration_pingers.ok new file mode 100644 index 0000000..637e18a --- /dev/null +++ b/tests/files/tests_large_configuration_pingers.ok @@ -0,0 +1,10 @@ +# +# Ansible managed +# +# system_role:sudo + +# Default override specifications +Defaults: PINGERS !requiretty +Defaults> root !set_logname +Defaults@ host1, host2 !requiretty, !requiretty +Defaults! /usr/bin/ls !requiretty diff --git a/tests/files/tests_large_configuration_root.ok b/tests/files/tests_large_configuration_root.ok new file mode 100644 index 0000000..f3da320 --- /dev/null +++ b/tests/files/tests_large_configuration_root.ok @@ -0,0 +1,10 @@ +# +# Ansible managed +# +# system_role:sudo + +# Default specifications +Defaults syslog=auth + +# Default override specifications +Defaults> root !set_logname diff --git a/tests/files/tests_large_configuration_sudoers.ok b/tests/files/tests_large_configuration_sudoers.ok new file mode 100644 index 0000000..f2f29f4 --- /dev/null +++ b/tests/files/tests_large_configuration_sudoers.ok @@ -0,0 +1,46 @@ +# +# Ansible managed +# +# system_role:sudo + +# Default specifications +Defaults !visiblepw +Defaults always_set_home +Defaults match_group_by_gid +Defaults always_query_group_plugin +Defaults env_reset +Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin +Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR" +Defaults env_keep += "LS_COLORS MAIL PS1 PS2 QTDIR" +Defaults env_keep += "USERNAME LANG LC_ADDRESS LC_CTYPE LC_COLLATE" +Defaults env_keep += "LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME" +Defaults env_keep += "LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL" +Defaults env_keep += "LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" + +# Alias specifications + +## Command Aliases +Cmnd_Alias PING = /usr/bin/ping + +## Host Aliases +Host_Alias HOST = myhost + +## Runas Aliases +Runas_Alias RUNAS = username + +## User Aliases +User_Alias PINGERS = username + +# User specifications +root ALL=(ALL) ALL +%wheel ALL=(ALL) ALL + +# Default override specifications +Defaults: PINGERS !requiretty +Defaults> root !set_logname +Defaults@ host1, host2 !requiretty, !set_logname +Defaults! /usr/bin/cd !requiretty + +# Includes +## Include directories +#includedir /etc/sudoers.d diff --git a/tests/files/tests_multiple_sudoers_pingers.ok b/tests/files/tests_multiple_sudoers_pingers.ok new file mode 100644 index 0000000..6bc8220 --- /dev/null +++ b/tests/files/tests_multiple_sudoers_pingers.ok @@ -0,0 +1,7 @@ +# +# Ansible managed +# +# system_role:sudo + +# Default override specifications +Defaults: PINGERS !requiretty diff --git a/tests/files/tests_multiple_sudoers_root.ok b/tests/files/tests_multiple_sudoers_root.ok new file mode 100644 index 0000000..f3da320 --- /dev/null +++ b/tests/files/tests_multiple_sudoers_root.ok @@ -0,0 +1,10 @@ +# +# Ansible managed +# +# system_role:sudo + +# Default specifications +Defaults syslog=auth + +# Default override specifications +Defaults> root !set_logname diff --git a/tests/files/tests_multiple_sudoers_sudoers.ok b/tests/files/tests_multiple_sudoers_sudoers.ok new file mode 100644 index 0000000..b4102d4 --- /dev/null +++ b/tests/files/tests_multiple_sudoers_sudoers.ok @@ -0,0 +1,34 @@ +# +# Ansible managed +# +# system_role:sudo + +# Default specifications +Defaults !visiblepw +Defaults always_set_home +Defaults match_group_by_gid +Defaults always_query_group_plugin +Defaults env_reset +Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin +Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR" +Defaults env_keep += "LS_COLORS MAIL PS1 PS2 QTDIR" +Defaults env_keep += "USERNAME LANG LC_ADDRESS LC_CTYPE LC_COLLATE" +Defaults env_keep += "LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME" +Defaults env_keep += "LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL" +Defaults env_keep += "LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" + +# Alias specifications + +## Command Aliases +Cmnd_Alias PING = /usr/bin/ping + +## User Aliases +User_Alias PINGERS = username + +# User specifications +root ALL=(ALL) ALL +%wheel ALL=(ALL) ALL + +# Includes +## Include directories +#includedir /etc/sudoers.d diff --git a/tests/files/tests_role_applied.ok b/tests/files/tests_role_applied.ok new file mode 100644 index 0000000..0e2ef7c --- /dev/null +++ b/tests/files/tests_role_applied.ok @@ -0,0 +1,26 @@ +# +# Ansible managed +# +# system_role:sudo + +# Default specifications +Defaults !visiblepw +Defaults always_set_home +Defaults match_group_by_gid +Defaults always_query_group_plugin +Defaults env_reset +Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin +Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR" +Defaults env_keep += "LS_COLORS MAIL PS1 PS2 QTDIR" +Defaults env_keep += "USERNAME LANG LC_ADDRESS LC_CTYPE LC_COLLATE" +Defaults env_keep += "LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME" +Defaults env_keep += "LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL" +Defaults env_keep += "LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" + +# User specifications +root ALL=(ALL) ALL +%wheel ALL=(ALL) ALL + +# Includes +## Include directories +#includedir /etc/sudoers.d diff --git a/tests/roles/linux-system-roles.sudo/defaults b/tests/roles/linux-system-roles.sudo/defaults new file mode 120000 index 0000000..30459c3 --- /dev/null +++ b/tests/roles/linux-system-roles.sudo/defaults @@ -0,0 +1 @@ +../../../defaults \ No newline at end of file diff --git a/tests/roles/linux-system-roles.sudo/handlers b/tests/roles/linux-system-roles.sudo/handlers new file mode 120000 index 0000000..3b11237 --- /dev/null +++ b/tests/roles/linux-system-roles.sudo/handlers @@ -0,0 +1 @@ +../../../handlers \ No newline at end of file diff --git a/tests/roles/linux-system-roles.sudo/meta b/tests/roles/linux-system-roles.sudo/meta new file mode 120000 index 0000000..8df72eb --- /dev/null +++ b/tests/roles/linux-system-roles.sudo/meta @@ -0,0 +1 @@ +../../../meta \ No newline at end of file diff --git a/tests/roles/linux-system-roles.sudo/tasks b/tests/roles/linux-system-roles.sudo/tasks new file mode 120000 index 0000000..d97297b --- /dev/null +++ b/tests/roles/linux-system-roles.sudo/tasks @@ -0,0 +1 @@ +../../../tasks \ No newline at end of file diff --git a/tests/roles/linux-system-roles.sudo/templates b/tests/roles/linux-system-roles.sudo/templates new file mode 120000 index 0000000..0e4c94f --- /dev/null +++ b/tests/roles/linux-system-roles.sudo/templates @@ -0,0 +1 @@ +../../../templates \ No newline at end of file diff --git a/tests/roles/linux-system-roles.sudo/vars b/tests/roles/linux-system-roles.sudo/vars new file mode 120000 index 0000000..663079d --- /dev/null +++ b/tests/roles/linux-system-roles.sudo/vars @@ -0,0 +1 @@ +../../../vars \ No newline at end of file diff --git a/tests/setup-snapshot.yml b/tests/setup-snapshot.yml index a7704df..a97e269 100644 --- a/tests/setup-snapshot.yml +++ b/tests/setup-snapshot.yml @@ -4,11 +4,11 @@ tasks: - name: Set platform/version specific variables include_role: - name: linux-system-roles.template + name: linux-system-roles.sudo tasks_from: set_vars.yml public: true - name: Install test packages package: - name: "{{ __template_packages }}" + name: "{{ __sudo_packages }}" state: present diff --git a/tests/tasks/assert_files_identical.yml b/tests/tasks/assert_files_identical.yml new file mode 100644 index 0000000..ebf4bdb --- /dev/null +++ b/tests/tasks/assert_files_identical.yml @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: MIT +--- +- name: Get stat of {{ __sudo_ok_path }} + delegate_to: localhost + stat: + path: "{{ __sudo_ok_path }}" + checksum_algorithm: sha256 + register: __ok_path_stat + +- name: Get stat of {{ __sudo_test_path }} + stat: + path: "{{ __sudo_test_path }}" + checksum_algorithm: sha256 + register: __test_path_stat + +- name: Assert that files are identical + assert: + that: __ok_path_stat.stat.checksum == __test_path_stat.stat.checksum diff --git a/tests/tests_default.yml b/tests/tests_default.yml index 4457422..1a72731 100644 --- a/tests/tests_default.yml +++ b/tests/tests_default.yml @@ -4,10 +4,10 @@ hosts: all gather_facts: false # test that role works in this case roles: - - linux-system-roles.template + - linux-system-roles.sudo tasks: - name: Check header for ansible_managed, fingerprint include_tasks: tasks/check_header.yml vars: - __file: /etc/foo.conf - __fingerprint: system_role:template + __file: /etc/sudoers + __fingerprint: system_role:sudo diff --git a/tests/tests_include_vars_from_parent.yml b/tests/tests_include_vars_from_parent.yml index fc795dd..749b0ef 100644 --- a/tests/tests_include_vars_from_parent.yml +++ b/tests/tests_include_vars_from_parent.yml @@ -44,7 +44,7 @@ import_role: name: caller vars: - roletoinclude: linux-system-roles.template + roletoinclude: linux-system-roles.sudo - name: Cleanup file: diff --git a/tests/tests_large_configuration.yml b/tests/tests_large_configuration.yml new file mode 100644 index 0000000..3ce46c9 --- /dev/null +++ b/tests/tests_large_configuration.yml @@ -0,0 +1,222 @@ +--- +- name: Basic test for Sudo + hosts: all + tasks: + - name: Run tests + block: + - name: Run the role + include_role: + name: linux-system-roles.sudo + vars: + sudo_rewrite_default_sudoers_file: true + sudo_remove_unauthorized_included_files: true + sudo_sudoers_files: + - path: /etc/sudoers + defaults: + - "!visiblepw" + - always_set_home + - match_group_by_gid + - always_query_group_plugin + - env_reset + - secure_path: + - /sbin + - /bin + - /usr/sbin + - /usr/bin + - env_keep: + - COLORS + - DISPLAY + - HOSTNAME + - HISTSIZE + - KDEDIR + - LS_COLORS + - MAIL + - PS1 + - PS2 + - QTDIR + - USERNAME + - LANG + - LC_ADDRESS + - LC_CTYPE + - LC_COLLATE + - LC_IDENTIFICATION + - LC_MEASUREMENT + - LC_MESSAGES + - LC_MONETARY + - LC_NAME + - LC_NUMERIC + - LC_PAPER + - LC_TELEPHONE + - LC_TIME + - LC_ALL + - LANGUAGE + - LINGUAS + - _XKB_CHARSET + - XAUTHORITY + user_specifications: + - users: + - root + hosts: + - ALL + operators: + - ALL + commands: + - ALL + - users: + - "%wheel" + hosts: + - ALL + operators: + - ALL + commands: + - ALL + default_overrides: + - type: user + defaults: + - "!requiretty" + users: + - PINGERS + - type: runas + defaults: + - "!set_logname" + operators: + - root + - type: host + defaults: + - "!requiretty" + - "!set_logname" + hosts: + - host1 + - host2 + - type: command + defaults: + - "!requiretty" + commands: + - /usr/bin/cd + include_directories: + - /etc/sudoers.d + aliases: + cmnd_alias: + - name: PING + commands: + - /usr/bin/ping + host_alias: + - name: HOST + hosts: + - myhost + user_alias: + - name: PINGERS + users: + - username + runas_alias: + - name: RUNAS + users: + - username + - path: /etc/sudoers.d/pingers + default_overrides: + - type: user + defaults: + - "!requiretty" + users: + - PINGERS + - type: runas + defaults: + - "!set_logname" + operators: + - root + - type: host + defaults: + - "!requiretty" + - "!requiretty" + hosts: + - host1 + - host2 + - type: command + defaults: + - "!requiretty" + commands: + - /usr/bin/ls + - path: /etc/sudoers.d/root + defaults: + - syslog=auth + default_overrides: + - type: runas + defaults: + - "!set_logname" + operators: + - root + + - name: Create temp test directory + tempfile: + path: /var/tmp + prefix: sudo_ + state: directory + register: __sudo_tmpdir + + - name: Backup sudoers + copy: + src: /etc/sudoers + dest: "{{ __sudo_tmpdir.path }}/sudoers" + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Backup sudoers.d + copy: + src: /etc/sudoers.d + dest: "{{ __sudo_tmpdir.path }}/sudoers.d" + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Get stat of {{ ok_path }} + delegate_to: localhost + vars: + ok_path: files/tests_large_configuration_sudoers.ok + stat: + path: "{{ ok_path }}" + checksum_algorithm: sha256 + register: sudoers_ok + + - name: Check sudoers + include_tasks: tasks/assert_files_identical.yml + vars: + __sudo_ok_path: files/tests_large_configuration_sudoers.ok + __sudo_test_path: /etc/sudoers + + - name: Check pingers + include_tasks: tasks/assert_files_identical.yml + vars: + __sudo_ok_path: files/tests_large_configuration_pingers.ok + __sudo_test_path: /etc/sudoers.d/pingers + + - name: Check root + include_tasks: tasks/assert_files_identical.yml + vars: + __sudo_ok_path: files/tests_large_configuration_root.ok + __sudo_test_path: /etc/sudoers.d/root + + - name: Restore sudoers + copy: + src: "{{ __sudo_tmpdir.path }}/sudoers" + dest: /etc/sudoers + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Restore sudoers.d + copy: + src: "{{ __sudo_tmpdir.path }}/sudoers.d" + dest: /etc/sudoers.d + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Clean up temp directory + file: + path: "{{ __sudo_tmpdir.path }}" + state: absent diff --git a/tests/tests_multiple_sudoers.yml b/tests/tests_multiple_sudoers.yml new file mode 100644 index 0000000..0907bca --- /dev/null +++ b/tests/tests_multiple_sudoers.yml @@ -0,0 +1,174 @@ +--- +- name: Basic test for Sudo + hosts: all + tasks: + - name: Run tests + block: + - name: Run the role + include_role: + name: linux-system-roles.sudo + vars: + sudo_rewrite_default_sudoers_file: true + sudo_remove_unauthorized_included_files: true + sudo_sudoers_files: + - path: /etc/sudoers + defaults: + - "!visiblepw" + - always_set_home + - match_group_by_gid + - always_query_group_plugin + - env_reset + - secure_path: + - /sbin + - /bin + - /usr/sbin + - /usr/bin + - env_keep: + - COLORS + - DISPLAY + - HOSTNAME + - HISTSIZE + - KDEDIR + - LS_COLORS + - MAIL + - PS1 + - PS2 + - QTDIR + - USERNAME + - LANG + - LC_ADDRESS + - LC_CTYPE + - LC_COLLATE + - LC_IDENTIFICATION + - LC_MEASUREMENT + - LC_MESSAGES + - LC_MONETARY + - LC_NAME + - LC_NUMERIC + - LC_PAPER + - LC_TELEPHONE + - LC_TIME + - LC_ALL + - LANGUAGE + - LINGUAS + - _XKB_CHARSET + - XAUTHORITY + user_specifications: + - users: + - root + hosts: + - ALL + operators: + - ALL + commands: + - ALL + - users: + - "%wheel" + hosts: + - ALL + operators: + - ALL + commands: + - ALL + include_directories: + - /etc/sudoers.d + aliases: + cmnd_alias: + - name: PING + commands: + - /usr/bin/ping + user_alias: + - name: PINGERS + users: + - username + - path: /etc/sudoers.d/pingers + default_overrides: + - type: user + defaults: + - "!requiretty" + users: + - PINGERS + - path: /etc/sudoers.d/root + defaults: + - syslog=auth + default_overrides: + - type: runas + defaults: + - "!set_logname" + operators: + - root + + - name: Create temp test directory + tempfile: + path: /var/tmp + prefix: sudo_ + state: directory + register: __sudo_tmpdir + + - name: Backup sudoers + copy: + src: /etc/sudoers + dest: "{{ __sudo_tmpdir.path }}/sudoers" + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Backup sudoers.d + copy: + src: /etc/sudoers.d + dest: "{{ __sudo_tmpdir.path }}/sudoers.d" + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Get stat of {{ ok_path }} + delegate_to: localhost + vars: + ok_path: files/tests_multiple_sudoers_sudoers.ok + stat: + path: "{{ ok_path }}" + checksum_algorithm: sha256 + register: sudoers_ok + + - name: Check sudoers + include_tasks: tasks/assert_files_identical.yml + vars: + __sudo_ok_path: files/tests_multiple_sudoers_sudoers.ok + __sudo_test_path: /etc/sudoers + + - name: Check pingers + include_tasks: tasks/assert_files_identical.yml + vars: + __sudo_ok_path: files/tests_multiple_sudoers_pingers.ok + __sudo_test_path: /etc/sudoers.d/pingers + + - name: Check root + include_tasks: tasks/assert_files_identical.yml + vars: + __sudo_ok_path: files/tests_multiple_sudoers_root.ok + __sudo_test_path: /etc/sudoers.d/root + + - name: Restore sudoers + copy: + src: "{{ __sudo_tmpdir.path }}/sudoers" + dest: /etc/sudoers + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Restore sudoers.d + copy: + src: "{{ __sudo_tmpdir.path }}/sudoers.d" + dest: /etc/sudoers.d + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Clean up temp directory + file: + path: "{{ __sudo_tmpdir.path }}" + state: absent diff --git a/tests/tests_role_applied.yml b/tests/tests_role_applied.yml new file mode 100644 index 0000000..c1a7e81 --- /dev/null +++ b/tests/tests_role_applied.yml @@ -0,0 +1,66 @@ +--- +- name: Basic test for Sudo + hosts: all + tasks: + - name: Run tests + block: + - name: Run the role + include_role: + name: linux-system-roles.sudo + vars: + sudo_rewrite_default_sudoers_file: true + sudo_remove_unauthorized_included_files: true + + - name: Create temp test directory + tempfile: + path: /var/tmp + prefix: sudo_ + state: directory + register: __sudo_tmpdir + + - name: Backup sudoers + copy: + src: /etc/sudoers + dest: "{{ __sudo_tmpdir.path }}/sudoers" + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Backup sudoers.d + copy: + src: /etc/sudoers.d + dest: "{{ __sudo_tmpdir.path }}/sudoers.d" + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Check sudoers + include_tasks: tasks/assert_files_identical.yml + vars: + __sudo_ok_path: files/tests_role_applied.ok + __sudo_test_path: /etc/sudoers + + - name: Restore sudoers + copy: + src: "{{ __sudo_tmpdir.path }}/sudoers" + dest: /etc/sudoers + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Restore sudoers.d + copy: + src: "{{ __sudo_tmpdir.path }}/sudoers.d" + dest: /etc/sudoers.d + owner: root + group: root + mode: 0644 + remote_src: true + + - name: Clean up temp directory + file: + path: "{{ __sudo_tmpdir.path }}" + state: absent diff --git a/vars/CentOS_7.yml b/vars/CentOS_7.yml deleted file mode 100644 index 24448bc..0000000 --- a/vars/CentOS_7.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with CentOS 7 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/CentOS_8.yml b/vars/CentOS_8.yml deleted file mode 100644 index 0fb6af8..0000000 --- a/vars/CentOS_8.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with CentOS 8 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/CentOS_9.yml b/vars/CentOS_9.yml deleted file mode 100644 index 7c25b3c..0000000 --- a/vars/CentOS_9.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with CentOS 9 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/Fedora.yml b/vars/Fedora.yml deleted file mode 100644 index a783f79..0000000 --- a/vars/Fedora.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Fedora specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/RedHat_7.yml b/vars/RedHat_7.yml deleted file mode 100644 index 3815df4..0000000 --- a/vars/RedHat_7.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Red Hat Enterprise Linux 7 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/RedHat_8.yml b/vars/RedHat_8.yml deleted file mode 100644 index 954bf90..0000000 --- a/vars/RedHat_8.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Red Hat Enterprise Linux 8 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/RedHat_9.yml b/vars/RedHat_9.yml deleted file mode 100644 index b367bff..0000000 --- a/vars/RedHat_9.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Red Hat Enterprise Linux 9 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/main.yml b/vars/main.yml index 24f178c..939a517 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,21 +1,12 @@ # SPDX-License-Identifier: MIT --- -# Put the role's internal variables here that are not distribution specific. -# You can override these by defining the same variable with a different -# value in a platform/version specific file in vars/ - -# Examples of non-distribution specific (generic) internal variables: -__template_foo_config: foo.conf -__template_packages: [] -__template_services: [] -# ansible_facts required by the role -__template_required_facts: +__sudo_sudoers_config: /etc/sudoers +__sudo_packages: sudo +__sudo_services: [] +__sudo_required_facts: - distribution - distribution_major_version - distribution_version - os_family -# the subsets of ansible_facts that need to be gathered in case any of the -# facts in required_facts is missing; see the documentation of -# the 'gather_subset' parameter of the 'setup' module -__template_required_facts_subsets: "{{ ['!all', '!min'] + - __template_required_facts }}" +__sudo_required_facts_subsets: "{{ ['!all', '!min'] + + __sudo_required_facts }}"