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..1fa14b2 100644
--- a/README.md
+++ b/README.md
@@ -1,105 +1,311 @@
-# 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.
+Sudo System Role
## 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.
-```bash
-ansible-galaxy collection install -vv -r meta/collection-requirements.yml
-```
+## Role Variables
-on the *control node* before using the role.
+The defaults defined for this role are based on a default RHEL8.4 `/etc/sudoers` configuration. Please check the defaults in [`defaults/main.yml`](defaults/main.yml) prior to running for OS compatibility.
-## Role Variables
+### sudo_rewrite_default_sudoers_file
-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.
+Use role default or user defined `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. | True | boolean |
-### template_foo
+### sudo_remove_unauthorized_included_files
-This variable is required. It is a string that lists the foo of the role.
-There is no default value.
+***Dangerous!*** Each existing sudoers file found in the `include_directories` dictionary which have not been defined in `sudoers_files` will be removed. This allows for enforcing a desired state. | False | boolean |
-### template_bar
+### sudo_visudo_path
-This variable is optional. It is a boolean that tells the role to disable bar.
-The default value is `true`.
+Fully-qualified path to the `visudo` binary required for validation of sudoers configuration changes. Added for Operating System compatibility. | /usr/sbin/visudo | string |
-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.
+### sudo_sudoers_files
-Example of setting the variables:
+Definition of all your sudoers configurations | see [defaults/main.yml](defaults/main.yml)| list of dictionaries |
-```yaml
-template_foo: "oof"
-template_bar: false
-```
+#### path
+
+Where to deploy the configuration file to on the filesystem. | string |
+
+#### aliases
+
+Optional definition of `cmnd_alias`, `host_alias`, `runas_alias`, or `user_alias` items. | dictionary |
+
+#### defaults
+
+This allows you to define the defaults of your sudoers configuration. Default overrides can be perfomed via the [`user_specifications`](#default-override-user_specifications) key.| list |
+
+#### include_files
+
+Optional specific files that you would like your configuration to include. This is a list of fully-qualified paths to include via the `#include` option of a sudoers configuration. | list |
+
+#### include_directories
+
+Optional specific directories that you would like your configurations to include. This is a list of fully-qualified paths to directories to include via the `#includedir` option of a sudoers configuration. | list |
+
+#### user_specifications
+
+List of user specifications and default overrides to apply to a sudoers file configuration. | list |
+
+### sudo_sudoers_files aliases
+
+#### cmnd_alias
+
+`name` Name of the command alias and commands. | string |
+`commands` List of commands to apply to the alias | list |
-## Variables Exported by the Role
+#### host_alias
-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.
+`name` Name of the host alias. | string |
+`hosts` List of hosts to apply to the alias | list |
-Example:
+#### runas_alias
-### template_reboot_needed
+`name` Name of the runas alias | string |
+`users` List of users to apply to the alias | list |
-Default `false` - if `true`, this means a reboot is needed to apply the changes
-made by the role
+#### user_alias
+
+`name` Name of the user_alias | string |
+`users` List of users to apply to the alias | list |
+
+### user_specifications
+
+This dictionary can be used to assign either user specifications or default overrides.
+
+#### Standard user_specifications
+
+`users` List of users to apply the specification to. You can use a `user_alias` name as well as user names. | list |
+`hosts` List of hosts to apply the specification to. You can use a defined `host_alias` name as well as host names. | list |
+`operators` List of operators to apply the specification to. You can use a defined `runas_alias` name as well as user names. | list |
+`selinux_role` Optional selinux role to apply to the specification | list |
+`selinux_type` Optional selinux type to apply to the specification | list |
+`solaris_privs` Optional Solaris privset to apply to the specification | list |
+`solaris_limitprivs` Optional Solaris privset to apply to the specification | list |
+`tags` Optional list of tags to apply to the specification. | list |
+`commands` List of commands to apply the specification to. You can use a defined `cmnd_alias` name as well as commands. | list |
+
+#### Default Override user_specifications
+
+`defaults` List of defaults to override from the main configuration | list |
+`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`. | string |
+`commands` Use when `type: command`. List of `cmnd_alias` names as well as commands to override specific default values.| list |
+`hosts` Use when `type: host`. List of `host_alias` names as well as individual host names to override specific default values. | list |
+`operators` Use when `type: runas`. List of `runas_alias` names as well as individual user names to override specific default values. | list |
+`users` Use when `type: user`. List of `user_alias` names as well as individual user names to override specific default values. | list |
## Example Playbook
-Including an example of how to use your role (for instance, with variables
-passed in as parameters) is always nice for users too:
+```yaml
+---
+- name: Apply a RHEL Default /etc/sudoers configuration
+ hosts: all
+ roles:
+ - role: linux-system-roles.sudo
+```
```yaml
-- name: Manage the template subsystem
+---
+- name: Apply 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.
-
-## rpm-ostree
+```yaml
+---
+- name: Apply a RHEL Default /etc/sudoers configuration
+ 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
+```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:
+ sudoers_rewrite_default_sudoers_file: True
+ sudoers_remove_unauthorized_included_files: True
+ sudoers_backup: True
+ sudoers_backup_path: sudoers-backups
+ 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:
+ - /bin/ping
+ user_alias:
+ - name: PINGERS
+ users:
+ - ahuffman
+ - 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
+```
## License
-Whenever possible, please prefer MIT.
+MIT
## Author Information
-An optional section for the role authors to include contact information, or a
-website (HTML is not allowed).
+Radovan Sroka @rsroka
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..e8653d6 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/examples/simple1.yml b/examples/simple1.yml
new file mode 100644
index 0000000..6e1df0a
--- /dev/null
+++ b/examples/simple1.yml
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+---
+- name: Apply a RHEL Default /etc/sudoers configuration
+ hosts: all
+ roles:
+ - role: linux-system-roles.sudo
diff --git a/examples/simple2.yml b/examples/simple2.yml
new file mode 100644
index 0000000..2d6a884
--- /dev/null
+++ b/examples/simple2.yml
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: MIT
+---
+- name: Apply custom /etc/sudoers configuration
+ hosts: all
+ vars:
+ sudoers_files:
+ - path: /etc/sudoers
+ user_specifications:
+ - users:
+ - root
+ hosts:
+ - x
+ commands:
+ - /usr/bin/ls
+ roles:
+ - role: linux-system-roles.sudo
diff --git a/examples/simple3.yml b/examples/simple3.yml
new file mode 100644
index 0000000..fd37061
--- /dev/null
+++ b/examples/simple3.yml
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: MIT
+---
+- name: Apply a RHEL Default /etc/sudoers configuration
+ 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
diff --git a/examples/simple4.yml b/examples/simple4.yml
new file mode 100644
index 0000000..bf4c033
--- /dev/null
+++ b/examples/simple4.yml
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: MIT
+---
+- 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:
+ sudoers_rewrite_default_sudoers_file: True
+ sudoers_remove_unauthorized_included_files: True
+ sudoers_backup: True
+ sudoers_backup_path: sudoers-backups
+ 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:
+ - /bin/ping
+ user_alias:
+ - name: PINGERS
+ users:
+ - ahuffman
+ - 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
diff --git a/handlers/main.yml b/handlers/main.yml
index 726022e..2820d37 100644
--- a/handlers/main.yml
+++ b/handlers/main.yml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: MIT
---
-- name: Handler for template to restart services
+- name: Handler for role to restart services
service:
name: "{{ item }}"
state: restarted
- loop: "{{ __template_services }}"
+ loop: "{{ __sudo_services }}"
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..6edabe9 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -1,27 +1,83 @@
-# 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) }}"
+ register: sudo_installed
+
+- 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 required services are enabled and started
- service:
- name: "{{ item }}"
- state: started
- enabled: true
- loop: "{{ __template_services }}"
+- 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 }}"
+# become: True
+ 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: /etc/sudoers
+ 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..0ae2fc7
--- /dev/null
+++ b/templates/sudoers.j2
@@ -0,0 +1,112 @@
+{{ 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' %}
+Defaults {{ name }} = {% for item in values %}{% if not loop.last %}{{ item }}:{% else %}{{ item }}{% endif %}{% endfor %}
+
+{% else %}
+{% for items in values | list | slice(6) %}
+{% if items %}
+Defaults {{ name }} {% if not loop.first %}+{% endif %}= "{{ items | list | join(' ') }}"
+{% endif -%}
+{% endfor %}
+{% endif %}
+{% endfor %}
+{% elif default | first == ':' %}
+Defaults{{ default }}
+{% else %}
+Defaults {{ default }}
+{% endif %}
+{% endfor %}
+
+{% endif %}
+{% if item.aliases is defined %}
+# Alias specifications
+{% if item.aliases.cmnd_alias is defined %}
+## Command Aliases
+{% for ca in item.aliases.cmnd_alias %}
+Cmnd_Alias {{ ca.name }} = {% for cmnd in ca.commands %}{% if not loop.last %}{{ cmnd }}, {% else %}{{ cmnd }}{% endif %}{% endfor %}
+
+{% endfor %}
+
+{% endif %}
+{% if item.aliases.host_alias is defined %}
+## Host Aliases
+{% for ha in item.aliases.host_alias %}
+Host_Alias {{ ha.name }} = {% for host in ha.hosts %}{% if not loop.last %}{{ host }}, {% else %}{{ host }}{% endif %}{% endfor %}
+
+{% endfor %}
+
+{% endif %}
+{% if item.aliases.runas_alias is defined %}
+## Runas Aliases
+{% for ra in item.aliases.runas_alias %}
+Runas_Alias {{ ra.name }} = {% for user in ra.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }}{% endif %}{% endfor %}
+
+{% endfor %}
+
+{% endif %}
+{% if item.aliases.user_alias is defined %}
+## User Aliases
+{% for ua in item.aliases.user_alias %}
+User_Alias {{ ua.name }} = {% for user in ua.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }}{% endif %}{% endfor %}
+
+{% endfor %}
+
+{% endif %}
+{% endif %}
+{% if item.user_specifications is defined %}
+{% if item.user_specifications | selectattr('type', 'undefined') | flatten | length > 0 %}
+# User specifications
+{% for spec in item.user_specifications %}
+{% if spec.type is undefined %}
+{% for user in spec.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }}{% endif %}{% endfor %} {% for host in spec.hosts %}{% if not loop.last %}{{ host }}, {% else %}{{ host }}{% endif %}{% endfor %}={% if spec.operators is defined %}({% for op in spec.operators %}{% if not loop.last%}{{ op }}, {% else %}{{ op }}{% endif %}{% endfor %}){% endif %} {% if spec.selinux_type is defined %}TYPE={% for type in spec.selinux_type %}{% if not loop.last %}{{ type }}, {% else %}{{ type }} {% endif %}{% endfor %}{% endif %}{% if spec.selinux_role is defined %}ROLE={% for role in spec.selinux_role %}{% if not loop.last %}{{ role }}, {% else %}{{ role }} {% endif %}{% endfor %}{% endif %}{% if spec.solaris_privs is defined %}PRIVS={% for priv in spec.solaris_privs %}{% if not loop.last %}{{ priv }}, {% else %}{{ priv }} {% endif %}{% endfor %}{% endif %}{% if spec.solaris_limitprivs is defined %}LIMITPRIVS={% for lpriv in spec.solaris_limitprivs %}{% if not loop.last %}{{ lpriv }}, {% else %}{{ lpriv }} {% endif %}{% endfor %}{% endif %}{% if spec.tags is defined %}{% for tag in spec.tags %}{{ tag }}:{% endfor %} {% endif %}{% for cmnd in spec.commands %}{% if not loop.last %}{{ cmnd }}, {% else %}{{ cmnd }}{% endif %}{% endfor %}
+
+{% endif %}
+{% endfor %}
+{% endif %}
+
+{% endif %}
+{% if item.user_specifications | selectattr('defaults', 'defined') | map(attribute='defaults') | flatten | length > 0 %}
+# Default override specifications
+{% for spec in item.user_specifications %}
+{% if spec.type is defined %}
+{% if spec.type == 'user'%}
+Defaults:{% for user in spec.users %}{% if not loop.last %}{{ user }}, {% else %}{{ user }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %}
+
+{% elif spec.type == 'runas' %}
+Defaults>{% for op in spec.operators %}{% if not loop.last %}{{ op }}, {% else %}{{ op }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %}
+
+{% elif spec.type == 'host' %}
+Defaults@{% for host in spec.hosts %}{% if not loop.last %}{{ host }}, {% else %}{{ host }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %}
+
+{% elif spec.type == 'command' %}
+Defaults!{% for cmnd in spec.commands %}{% if not loop.last %}{{ cmnd }}, {% else %}{{ cmnd }} {% endif %}{% endfor %}{% for default in spec.defaults %}{% if not loop.last %}{{ default }}, {% else %}{{ default }}{% endif %}{% endfor %}
+
+{% endif %}
+{% endif %}
+{% 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_role_applied.ok b/tests/files/tests_role_applied.ok
new file mode 100644
index 0000000..3e29e25
--- /dev/null
+++ b/tests/files/tests_role_applied.ok
@@ -0,0 +1,25 @@
+#
+# Ansible managed
+#
+
+# 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/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_role_applied.yml b/tests/tests_role_applied.yml
new file mode 100644
index 0000000..fa6167d
--- /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
+ command: >-
+ # sha256sum ./files/test_role_applied.ok
+ EXPECTED_SUDOERS_SHA256=5b88319c0fb98c646ee94b6ccd2314a1b46df1c3f42e6948a42fb920217d9726
+ sha256sum /etc/sudoers | sha256sum --check ${EXPECTED_SUDOERS_SHA256}
+
+ - 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/main.yml b/vars/main.yml
index 24f178c..64437c7 100644
--- a/vars/main.yml
+++ b/vars/main.yml
@@ -5,11 +5,11 @@
# 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: []
+__sudo_sudoers_config: /etc/sudoers
+__sudo_packages: sudo
+__sudo_services: []
# ansible_facts required by the role
-__template_required_facts:
+__sudo_required_facts:
- distribution
- distribution_major_version
- distribution_version
@@ -17,5 +17,5 @@ __template_required_facts:
# 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 }}"