Vendor Galaxy Roles and Collections

This commit is contained in:
Stefan Bethke 2026-02-06 22:07:16 +01:00
commit 2aed20393f
3553 changed files with 387444 additions and 2 deletions

View file

@ -0,0 +1,19 @@
debops.sudo - Configure 'sudo' support using Ansible
Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
Copyright (C) 2018 DebOps <https://debops.org/>
SPDX-License-Identifier: GPL-3.0-only
This Ansible role is part of DebOps.
DebOps is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3, as
published by the Free Software Foundation.
DebOps is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DebOps. If not, see https://www.gnu.org/licenses/.

View file

@ -0,0 +1,261 @@
---
# .. vim: foldmarker=[[[,]]]:foldmethod=marker
# .. Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# .. Copyright (C) 2018 DebOps <https://debops.org/>
# .. SPDX-License-Identifier: GPL-3.0-only
# .. _sudo__ref_defaults:
# debops.sudo default variables
# =============================
# .. contents:: Sections
# :local:
#
# .. include:: ../../../../includes/global.rst
# General configuration [[[
# -------------------------
# .. envvar:: sudo__enabled [[[
#
# Enable or disable support for :command:`sudo` management on a host.
sudo__enabled: True
# ]]]
# .. envvar:: sudo__base_packages [[[
#
# List of base APT packages to install for :command:`sudo` support.
sudo__base_packages: '{{ ["sudo-ldap"]
if sudo__ldap_enabled | bool
else ["sudo"] }}'
# ]]]
# .. envvar:: sudo__packages [[[
#
# List of additional APT packages to install with :command:`sudo` command.
sudo__packages: []
# ]]]
# .. envvar:: sudo__logind_session [[[
#
# Enable or disable a workaround for :command:`sudo` login session not having
# a ``$XDG_RUNTIME_DIR`` environment variable set. This allows control over
# another user's :command:`systemd` instance.
sudo__logind_session: '{{ True if (ansible_service_mgr == "systemd") else False }}'
# ]]]
# ]]]
# LDAP environment [[[
# --------------------
# .. envvar:: sudo__ldap_base_dn [[[
#
# The base Distinguished Name which should be used to create Distinguished
# Names of the LDAP directory objects, defined as a YAML list.
sudo__ldap_base_dn: '{{ ansible_local.ldap.base_dn | d([]) }}'
# ]]]
# .. envvar:: sudo__ldap_device_dn [[[
#
# The Distinguished Name of the current host LDAP object, defined as a YAML
# list. It will be used as a base for the :command:`sudo` service account LDAP
# object. If the list is empty, the role will not create the account LDAP
# object automatically.
sudo__ldap_device_dn: '{{ ansible_local.ldap.device_dn | d([]) }}'
# ]]]
# .. envvar:: sudo__ldap_self_rdn [[[
#
# The Relative Distinguished Name of the account LDAP object used by the
# :command:`sudo` service to access the LDAP directory.
sudo__ldap_self_rdn: 'uid=sudo'
# ]]]
# .. envvar:: sudo__ldap_self_object_classes [[[
#
# List of the LDAP object classes which will be used to create the LDAP object
# used by the :command:`sudo` service to access the LDAP directory.
sudo__ldap_self_object_classes: [ 'account', 'simpleSecurityObject' ]
# ]]]
# .. envvar:: sudo__ldap_self_attributes [[[
#
# YAML dictionary that defines the attributes of the LDAP object used by the
# :command:`sudo` service to access the LDAP directory.
sudo__ldap_self_attributes:
uid: '{{ sudo__ldap_self_rdn.split("=")[1] }}'
userPassword: '{{ sudo__ldap_bindpw }}'
host: '{{ [ansible_fqdn, ansible_hostname] | unique }}'
description: 'Account used by the "sudo" service to access the LDAP directory'
# ]]]
# .. envvar:: sudo__ldap_binddn [[[
#
# The Distinguished Name of the account LDAP object used by the
# :command:`sudo` service to bind to the LDAP directory.
sudo__ldap_binddn: '{{ ([sudo__ldap_self_rdn] + sudo__ldap_device_dn) | join(",") }}'
# ]]]
# .. envvar:: sudo__ldap_bindpw [[[
#
# The password stored in the account LDAP object used by the :command:`sudo`
# service to bind to the LDAP directory.
sudo__ldap_bindpw: '{{ (lookup("password", secret + "/ldap/credentials/"
+ sudo__ldap_binddn | to_uuid + ".password length=32"))
if sudo__ldap_enabled | bool
else "" }}'
# ]]]
# ]]]
# Local sudoers configuration [[[
# -------------------------------
# These lists define what :command:`sudo` configuration will be present in the
# :file:`/etc/sudoers.d/` directory. See :ref:`sudo__ref_sudoers` for more
# details.
# .. envvar:: sudo__sudoers [[[
#
# Configuration which should be present on all hosts in the Ansible inventory.
sudo__sudoers: []
# ]]]
# .. envvar:: sudo__group_sudoers [[[
#
# Configuration which should be present on hosts in a specific Ansible
# inventory group.
sudo__group_sudoers: []
# ]]]
# .. envvar:: sudo__host_sudoers [[[
#
# Configuration which should be present on specific hosts in the Ansible
# inventory.
sudo__host_sudoers: []
# ]]]
# .. envvar:: sudo__dependent_sudoers [[[
#
# List of sudoers configurations defined in other Ansible roles
sudo__dependent_sudoers: []
# ]]]
# .. envvar:: sudo__combined_sudoers [[[
#
# The variable which combines all other ``sudoers`` configuration variables and
# is used in the role tasks.
sudo__combined_sudoers: '{{ sudo__sudoers
+ sudo__group_sudoers
+ sudo__host_sudoers
+ sudo__dependent_sudoers }}'
# ]]]
# ]]]
# LDAP sudoers configuration [[[
# ------------------------------
# The variables below define the contents of the :file:`/etc/sudo-ldap.conf`
# configuration file which is used by :command:`sudo` service to access the
# LDAP directory and retrieve sudoers configuration stored in the directory.
#
# The syntax of the ``sudo__ldap_*_configuration`` variables is the same as the
# :ref:`ldap__ref_configuration` variable syntax. Refer to its documentation
# for more details. The configuration options supported by :command:`sudo` can
# be found in the :man:`sudoers.ldap(5)` manual page.
# .. envvar:: sudo__ldap_enabled [[[
#
# Enable or disable support for the :file:`/etc/sudo-ldap.conf` configuration
# file management. If the support is disabled, existing configuration file will
# not be changed or removed.
sudo__ldap_enabled: '{{ True
if (ansible_local | d() and ansible_local.ldap | d() and
(ansible_local.ldap.posix_enabled | d()) | bool and not
(ansible_local.sssd | d() and ansible_local.sssd.installed | d()) | bool)
else False }}'
# ]]]
# .. envvar:: sudo__ldap_default_configuration [[[
#
# The contents of the :file:`/etc/sudo-ldap.conf` configuration file defined by
# default in the role.
sudo__ldap_default_configuration:
- name: 'sudoers_base'
comment: 'The base DN to use when performing "sudo" LDAP queries.'
value: '{{ (["ou=SUDOers"] + sudo__ldap_base_dn) | join(",") }}'
- name: 'uri'
comment: 'The location at which the LDAP server(s) should be reachable.'
value: '{{ ansible_local.ldap.uri | d("") }}'
- name: 'ssl'
comment: 'SSL options'
value: '{{ "start_tls"
if (ansible_local | d() and ansible_local.ldap | d() and
(ansible_local.ldap.start_tls | d()) | bool)
else "on" }}'
- name: 'tls_reqcert'
value: 'demand'
- name: 'tls_cacert'
value: '/etc/ssl/certs/ca-certificates.crt'
- name: 'binddn'
comment: 'The "sudo" service LDAP credentials used to bind to the directory.'
value: '{{ sudo__ldap_binddn }}'
- name: 'bindpw'
value: '{{ sudo__ldap_bindpw }}'
# ]]]
# .. envvar:: sudo__ldap_configuration [[[
#
# The contents of the :file:`/etc/sudo-ldap.conf` configuration file defined on
# all hosts in the Ansible inventory.
sudo__ldap_configuration: []
# ]]]
# .. envvar:: sudo__ldap_group_configuration [[[
#
# The contents of the :file:`/etc/sudo-ldap.conf` configuration file defined on
# hosts in a specific Ansible inventory group.
sudo__ldap_group_configuration: []
# ]]]
# .. envvar:: sudo__ldap_host_configuration [[[
#
# The contents of the :file:`/etc/sudo-ldap.conf` configuration file defined on
# specific hosts in the Ansible inventory.
sudo__ldap_host_configuration: []
# ]]]
# .. envvar:: sudo__ldap_combined_configuration [[[
#
# Variable which combines :command:`sudo` LDAP configuration from other
# variables and is used in the role templates.
sudo__ldap_combined_configuration: '{{ sudo__ldap_default_configuration
+ sudo__ldap_configuration
+ sudo__ldap_group_configuration
+ sudo__ldap_host_configuration }}'
# ]]]
# ]]]
# Configuration for other Ansible roles [[[
# -----------------------------------------
# .. envvar:: sudo__ldap__dependent_tasks [[[
#
# Configuration for the :ref:`debops.ldap` Ansible role.
sudo__ldap__dependent_tasks:
- name: 'Create sudo account for {{ sudo__ldap_device_dn | join(",") }}'
dn: '{{ sudo__ldap_binddn }}'
objectClass: '{{ sudo__ldap_self_object_classes }}'
attributes: '{{ sudo__ldap_self_attributes }}'
no_log: '{{ debops__no_log | d(True) }}'
state: '{{ "present"
if sudo__ldap_enabled | bool
else "ignore" }}'
# ]]]
# ]]]

View file

@ -0,0 +1,32 @@
---
# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018-2022 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
# Ensure that custom Ansible plugins and modules included in the main DebOps
# collection are available to roles in other collections.
collections: [ 'debops.debops' ]
dependencies: []
galaxy_info:
author: 'Maciej Delmanowski'
description: 'Configure sudo support on a host'
company: 'DebOps'
license: 'GPL-3.0-only'
min_ansible_version: '2.4.0'
platforms:
- name: 'Ubuntu'
versions: [ 'all' ]
- name: 'Debian'
versions: [ 'all' ]
galaxy_tags:
- sudo
- authentication
- authorization
- security

View file

@ -0,0 +1,102 @@
---
# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
- name: Import custom Ansible plugins
ansible.builtin.import_role:
name: 'ansible_plugins'
- name: Import DebOps global handlers
ansible.builtin.import_role:
name: 'global_handlers'
- name: Import DebOps secret role
ansible.builtin.import_role:
name: 'secret'
- name: Configure access to LDAP directory
ansible.builtin.template:
src: 'etc/sudo-ldap.conf.j2'
dest: '/etc/sudo-ldap.conf'
mode: '0440'
when: sudo__enabled | bool and sudo__ldap_enabled | bool
- name: Install required packages
environment:
SUDO_FORCE_REMOVE: 'yes'
ansible.builtin.package:
name: '{{ q("flattened", (sudo__base_packages
+ sudo__packages)) }}'
state: 'present'
register: sudo__register_packages
until: sudo__register_packages is succeeded
when: sudo__enabled | bool
- name: Make sure that Ansible local facts directory exists
ansible.builtin.file:
path: '/etc/ansible/facts.d'
state: 'directory'
owner: 'root'
group: 'root'
mode: '0755'
- name: Save sudo local facts
ansible.builtin.template:
src: 'etc/ansible/facts.d/sudo.fact.j2'
dest: '/etc/ansible/facts.d/sudo.fact'
owner: 'root'
group: 'root'
mode: '0755'
notify: [ 'Refresh host facts' ]
tags: [ 'meta::facts' ]
- name: Update Ansible facts if they were modified
ansible.builtin.meta: 'flush_handlers'
- name: Ensure that '/etc/sudoers' includes '/etc/sudoers.d'
ansible.builtin.lineinfile:
dest: '/etc/sudoers'
regexp: '^(?:@|#)includedir\s+\/etc\/sudoers.d$'
line: '{{ ("#"
if ansible_local.sudo.version | d("0.0.0") is version("1.9.1", "<")
else "@") + "includedir /etc/sudoers.d" }}'
insertafter: 'EOF'
state: 'present'
validate: 'visudo -cf "%s"'
mode: '0440'
when: sudo__enabled | bool and not ansible_check_mode | bool
- name: Remove sudoers configuration if requested
ansible.builtin.file:
path: '/etc/sudoers.d/{{ item.filename | d(item.name) }}'
state: 'absent'
with_items: '{{ sudo__combined_sudoers | flatten | debops.debops.parse_kv_items }}'
notify: [ 'Refresh host facts' ]
when: sudo__enabled | bool and
item.name | d() and item.state | d('present') == 'absent'
- name: Configure sudoers
ansible.builtin.template:
src: 'etc/sudoers.d/config.j2'
dest: '/etc/sudoers.d/{{ item.filename | d(item.name) }}'
owner: 'root'
group: 'root'
mode: '0440'
validate: 'visudo -cf %s'
with_items: '{{ sudo__combined_sudoers | flatten | debops.debops.parse_kv_items }}'
notify: [ 'Refresh host facts' ]
when: sudo__enabled | bool and
item.name | d() and item.state | d('present') not in ['init', 'absent', 'ignore']
- name: Configure workaround for logind sessions via sudo
ansible.builtin.template:
src: 'etc/profile.d/sudo_logind_session.sh.j2'
dest: '/etc/profile.d/sudo_logind_session.sh'
owner: 'root'
group: 'root'
mode: '0644'
when: sudo__enabled | bool and sudo__logind_session | bool
- name: Update Ansible facts if they were modified
ansible.builtin.meta: 'flush_handlers'

View file

@ -0,0 +1,55 @@
#!{{ ansible_python['executable'] }}
# -*- coding: utf-8 -*-
# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
# {{ ansible_managed }}
from __future__ import print_function
from json import dumps
import os
import subprocess
import locale
try:
from subprocess import DEVNULL
except ImportError:
DEVNULL = open(os.devnull, 'wb')
def cmd_exists(cmd):
return any(
os.access(os.path.join(path, cmd), os.X_OK)
for path in os.environ["PATH"].split(os.pathsep)
)
# Ensure that external application output is consistent
locale.setlocale(locale.LC_MESSAGES, 'C')
output = {'configured': True,
'installed': cmd_exists('sudo')}
if output['installed']:
try:
version_stdout = subprocess.check_output(
["dpkg-query", "-W", "-f=${Version}",
"sudo-ldap"]).decode('utf-8').split('-')[0]
if version_stdout:
output['version'] = version_stdout.split('p')[0]
output['package'] = 'sudo-ldap'
else:
version_stdout = subprocess.check_output(
["dpkg-query", "-W", "-f=${Version}",
"sudo"]).decode('utf-8').split('-')[0]
if version_stdout:
output['version'] = version_stdout.split('p')[0]
output['package'] = 'sudo'
except Exception:
pass
print(dumps(output, sort_keys=True, indent=4))

View file

@ -0,0 +1,23 @@
# {{ ansible_managed }}
# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
# Workaround for missing XDG_RUNTIME_DIR environment variable in interactive
# login sessions. This assumes that an existing user session is present, for
# example when a given UNIX account is configured to "linger" in logind.
#
# This workaround allows control over another user's 'systemd' instance, when
# accessed via 'sudo' login session, for example:
#
# sudo -u <user> -l
#
# The 'pam_systemd.so' PAM module will not help in this case because an
# existing login session is present and the module refuses to create a new one.
# More details: https://bugs.debian.org/825949, https://github.com/systemd/systemd/issues/7451
if [ "`id -u`" -ne 0 ] && [ -n "${SUDO_USER}" ] && [ -z "${XDG_RUNTIME_DIR}" ] ; then
XDG_RUNTIME_DIR="/run/user/${UID}"
export XDG_RUNTIME_DIR
fi

View file

@ -0,0 +1,20 @@
{# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
#}
# {{ ansible_managed }}
# See sudoers.ldap(5) for details.
# This file shouldn't be world readable.
{% for option in sudo__ldap_combined_configuration | debops.debops.parse_kv_config %}
{% if option.state | d('present') not in [ 'absent', 'ignore' ] %}
{% if ((option.separator | d()) | bool or option.comment | d()) and not loop.first %}
{% endif %}
{% if option.comment | d() %}
{{ option.comment | regex_replace('\n$','') | comment(prefix='', postfix='') -}}
{% endif %}
{{ '{}{}\t{}{}'.format(('#' if (option.state | d('present') == 'comment') else ''), option.name | upper, ('\t' if (option.name | count < 8) else ''), (option.value if option.value is string else (option.value | selectattr("name", "defined") | map(attribute="name") | list | join(' ')))) }}
{% endif %}
{% endfor %}

View file

@ -0,0 +1,30 @@
{# Copyright (C) 2018 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2018 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-only
#}
# {{ ansible_managed }}
{% if item.comment | d() %}
{{ item.comment | regex_replace('\n$','') | comment(prefix='', postfix='\n') -}}
{% endif %}
{% if item.options | d() %}
{% for element in item.options %}
{% if element is mapping %}
{% if element.name | d() and element.value | d() and element.state | d('present') != 'absent' %}
{% if not loop.first %}
{% endif %}
{% if element.comment | d() %}
{% if not loop.first %}
{% endif %}
{{ element.comment | regex_replace('\n$','') | comment(prefix='', postfix='') -}}
{% endif %}
{{ element.value -}}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if item.raw | d() %}
{{ item.raw -}}
{% endif %}