debops.sshd default variables

OpenSSH packages

sshd__base_packages

List of base packages that should be installed for OpenSSH support.

sshd__base_packages: [ 'openssh-server', 'openssh-client' ]

List of recommended packages that should be installed with OpenSSH.

sshd__recommended_packages: '{{ [ "openssh-blacklist", "openssh-blacklist-extra" ]
                                if (ansible_distribution_release in [ "wheezy", "jessie",
                                    "precise", "trusty", "xenial" ]) else [] }}'
sshd__optional_packages

List of optional packages that should be installed with OpenSSH.

sshd__optional_packages: [ 'molly-guard' ]
sshd__ldap_packages

List of packages related to LDAP support required by OpenSSH.

sshd__ldap_packages: '{{ [ "ldap-utils" ]
                         if (sshd__authorized_keys_lookup|bool and
                             ("ldap" in sshd__authorized_keys_lookup_type))
                         else [] }}'
sshd__packages

List of additional packages to install.

sshd__packages: []
sshd__version

The version of the currently installed sshd daemon, exposed using Ansible local facts.

sshd__version: '{{ ansible_local.sshd.version | d("0.0") }}'

Host whitelists and allow lists

sshd__whitelist

List of IP addresses or CIDR subnets which should be allowed to connect to SSH without any restrictions. This list does not disallow connections from other hosts. This is a global list.

sshd__whitelist: []
sshd__group_whitelist

List of IP addresses or CIDR subnets which should be allowed to connect to SSH without any restrictions. This list does not disallow connections from other hosts. This is a group-based list.

sshd__group_whitelist: []
sshd__host_whitelist

List of IP addresses or CIDR subnets which should be allowed to connect to SSH without any restrictions. This list does not disallow connections from other hosts. This is a host-based list.

sshd__host_whitelist: []
sshd__allow

List of IP addresses or CIDR subnets that should be allowed to access SSH service. If it's set, access from hosts and networks not specified here is denied in TCP Wrappers and limited in iptables. This is a global list.

sshd__allow: []
sshd__group_allow

List of IP addresses or CIDR subnets that should be allowed to access SSH service. If it's set, access from hosts and networks not specified here is denied in TCP Wrappers and limited in iptables. This is a group list.

sshd__group_allow: []
sshd__host_allow

List of IP addresses or CIDR subnets that should be allowed to access SSH service. If it's set, access from hosts and networks not specified here is denied in TCP Wrappers and limited in iptables. This is a host list.

sshd__host_allow: []

TCP Wrappers configuration

sshd__tcpwrappers_default

If list of allowed hosts is not specified, this value will be set in TCP Wrappers for sshd service. By default any host is allowed to connect.

sshd__tcpwrappers_default: 'ALL'

Firewall (ferm) configuration

sshd__ferm_weight

Specify the "weight" of the sshd firewall rules. The more weight they have, the later in the firewall they will be defined. If you change the default weight, you will need to remove the old rules manually from the remote host.

sshd__ferm_weight: '30'
sshd__ferm_limit

Enable or disable limited SSH access from all hosts in ip(6)tables. Recent new connections are filtered and when too many new connections are created in specified time window, the host is added to the recent blocklist.

sshd__ferm_limit: True
sshd__ferm_limit_seconds

Length of the time window used by firewall to catch new offenders, by default 5 minutes.

sshd__ferm_limit_seconds: '{{ (60 * 5) }}'
sshd__ferm_limit_hits

How many new connections to allow in specified time window.

sshd__ferm_limit_hits: '8'
sshd__ferm_limit_chain

Name of the iptables chain used for filtering SSH connections.

sshd__ferm_limit_chain: 'filter-ssh'
sshd__ferm_limit_target

Specify what happens with packets filtered by the firewall that are above the specified limit. Either REJECT, DROP or name of iptables chain where packets will be sent through.

sshd__ferm_limit_target: 'REJECT'
sshd__ferm_ports

List of TCP ports to open in the firewall for SSH connections. You can use port numbers or service names from /etc/services.

sshd__ferm_ports: '{{ sshd__ports }}'
sshd__ferm_interface

List of interfaces to open in the firewall for SSH connections. Consider settings this to {{ [ ansible_default_ipv4.interface ] }} for example if the host has multiple network interfaces like when it is running a VPN.

sshd__ferm_interface: []

OpenSSH server configuration

sshd__ports

List of ports which sshd will listen on.

sshd__ports: [ '22' ]
sshd__listen

List of IP addresses on which sshd should listen for new connections. If it's empty, sshd listens on all interfaces.

sshd__listen: []
sshd__host_keys

List of SSH host keys that should be enabled, in order of preference.

sshd__host_keys: [ 'ed25519', 'rsa', 'ecdsa' ]
sshd__trusted_user_ca_keys

List of CA public keys used to assemble a TrustedUserCAKeys file.

sshd__trusted_user_ca_keys: []
sshd__trusted_user_ca_keys_file

File name which will contain CA trusted keys

sshd__trusted_user_ca_keys_file: '/etc/ssh/trusted-user-ca-keys.pem'
sshd__scan_for_host_certs

Detect, and add, any host certificates found in /etc/ssh/ that match ssh_host_*_key-cert.pub, as long as the key type matches what's in sshd__host_keys

sshd__scan_for_host_certs: False
sshd__banner

Path to file which should be displayed before user authentication.

sshd__banner: 'none'
sshd__log_level

How much information should be logged by sshd server.

sshd__log_level: 'INFO'
sshd__permit_root_login

Specify if access to root account should be granted. By default, if the debops.root_account role has been applied on the host, the root can be accessed only using SSH public keys since the role is expected to set them up. Otherwise, access via password is allowed. Alternatively, configured sysadmin accounts via the debops.system_users disable password-based access.

sshd__permit_root_login: '{{ "without-password"
                             if (ansible_local.root_account.ssh_authorized_keys|d()|bool or
                                 ansible_local.system_users.configured|d()|bool)
                             else "yes" }}'
sshd__password_authentication

Enable or disable password authentication. This option will be enabled if the root account does not have SSH authorized keys present, to allow the root account to login to the host. Alternatively, sysadmin access configured by the debops.system_users role disables password authentication.

sshd__password_authentication: '{{ "no"
                                   if (ansible_local.root_account.ssh_authorized_keys|d()|bool or
                                       ansible_local.system_users.configured|d()|bool)
                                   else "yes" }}'
sshd__accept_env

Specifies what environment variables sent by the client will be copied into the session's environment.

sshd__accept_env:
  - 'LANG'
  - 'LC_*'
sshd__x11_forwarding

Enable or disable X11 forwarding by the server.

sshd__x11_forwarding: 'no'
sshd__max_auth_tries

Maximum number of failed authentication attempts allowed by the server.

sshd__max_auth_tries: '4'
sshd__max_sessions

Maximum number of open shell, login or subsystem (e.g. sftp) sessions permitted per network connection.

sshd__max_sessions: '10'
sshd__max_startups

Maximum number of unauthenticated connections (3), after which there's 80% probability of next unauthenticated connection to be dropped, finishing at 7, after which all new unauthenticated connections will be refused.

sshd__max_startups: '3:80:7'
sshd__login_grace_time

Time after which unauthenticated sessions are disconnected. Note: setting this much lower is not recommended when sshd__use_dns is enabled. Ref: https://github.com/debops/debops/issues/1904

sshd__login_grace_time: '60s'
sshd__client_alive_count_max

Sets the number of client alive messages which may be sent without sshd receiving any messages back from the client.

sshd__client_alive_count_max: '3'
sshd__compression

Specifies whether compression is enabled after the user has authenticated successfully. The argument must be yes, delayed (a legacy synonym for yes) or no. The default is yes.

sshd__compression: 'yes'
sshd__privilege_separation

Specify if sshd should use unprivileged processes for incoming session authentication. Setting this to sandbox enables use of additional kernel restrictions. This option has no effect with sshd version 7.5+ since privilege separation became mandatory.

sshd__privilege_separation: 'sandbox'
sshd__use_dns

Enable or disable support for client hostname lookups by the SSH service. This is required if access control based on hostnames is used in the SSH server configuration, authorized keys or PAM access rules.

sshd__use_dns: 'yes'
sshd__custom_options

Additional sshd_config(5) options specified in a YAML text block format.

sshd__custom_options: ''

Group-based access control

Warning

The user and group access control on the sshd_config level is deprecated. Use the PAM access control rules managed by the debops.pam_access role instead. Default rules are defined in the sshd__pam_access__dependent_rules variable.

sshd__default_allow_groups

List of UNIX system groups which allow connections to SSH service defined by default.

sshd__default_allow_groups: []
sshd__allow_groups

List of UNIX groups which allow connections to SSH service (global).

sshd__allow_groups: []
sshd__group_allow_groups

List of UNIX groups which allow connections to SSH service (host group).

sshd__group_allow_groups: []
sshd__host_allow_groups

List of UNIX groups which allow connections to SSH service (host).

sshd__host_allow_groups: []

Authorized keys management

sshd__authorized_keys

List of files which contain SSH public keys, to be used to authenticate remote users.

sshd__authorized_keys: '{{ sshd__authorized_keys_system +
                           sshd__authorized_keys_user }}'
sshd__authorized_keys_system

List of system-wide files containing SSH public keys. These files are expected to be maintained by system administrator and might be used in restricted environments (for example SFTPonly accounts).

sshd__authorized_keys_system:
  - '/etc/ssh/authorized_keys/%u'
sshd__authorized_keys_user

List of user files containing SSH public keys. These files are maintained by the users themselves.

sshd__authorized_keys_user:
  - '%h/.ssh/authorized_keys'
  - '%h/.ssh/authorized_keys2'

System-wide host fingerprints

sshd__known_hosts

List of FQDN hostnames that should be scanned to add host fingerprints to the system-wide known hosts file (global).

sshd__known_hosts: []
sshd__group_known_hosts

List of FQDN hostnames that should be scanned to add host fingerprints to the system-wide known hosts file (host group).

sshd__group_known_hosts: []
sshd__host_known_hosts

List of FQDN hostnames that should be scanned to add host fingerprints to the system-wide known hosts file (host).

sshd__host_known_hosts: []
sshd__known_hosts_file

System-wide file where host fingerprints are stored.

sshd__known_hosts_file: '/etc/ssh/ssh_known_hosts'
sshd__known_hosts_command

Command used to scan host fingerprints into system-wide known hosts file.

sshd__known_hosts_command: 'ssh-keyscan -H -T 10'

Encryption parameters

sshd__ciphers_map

Dict with list of ciphers which should be used by the sshd server, depending on available version, ordered from strongest to weakest. Newer version supersedes older version.

sshd__ciphers_map:

  # Source: https://wiki.mozilla.org/Security/Guidelines/OpenSSH
  '6.5': [ 'chacha20-poly1305@openssh.com', 'aes256-gcm@openssh.com',
           'aes128-gcm@openssh.com', 'aes256-ctr', 'aes192-ctr',
           'aes128-ctr' ]

  # Source: https://xivilization.net/~marek/blog/2015/01/12/secure-secure-shell-on-debian-wheezy/
  '6.0': [ 'aes256-ctr', 'aes192-ctr', 'aes128-ctr' ]
sshd__ciphers_additional

List of additional key exchange algorithms which should be used by the sshd server, depending on available version, depending on available version, ordered from stronger to weaker. Newer version supersedes older version.

sshd__ciphers_additional: []
sshd__kex_algorithms_map

Dict with list of key exchange algorithms which should be used by the sshd server, depending on available version, ordered from strongest to oldest. Newer version supersedes older version.

sshd__kex_algorithms_map:

  # Source: https://wiki.mozilla.org/Security/Guidelines/OpenSSH
  '6.5': [ 'curve25519-sha256@libssh.org', 'ecdh-sha2-nistp521',
           'ecdh-sha2-nistp384', 'ecdh-sha2-nistp256',
           'diffie-hellman-group-exchange-sha256' ]

  # Source: https://xivilization.net/~marek/blog/2015/01/12/secure-secure-shell-on-debian-wheezy/
  '6.0': [ 'diffie-hellman-group-exchange-sha256' ]
sshd__kex_algorithms_additional

List of additional key exchange algorithms which should be used by the sshd server, depending on available version, depending on available version, ordered from stronger to weaker. Newer version supersedes older version.

sshd__kex_algorithms_additional: []
sshd__macs_map

Dict with list of message authentication code algorithms which should be used by the sshd server, depending on available version, ordered from stronger to weaker. Newer version supersedes older version.

sshd__macs_map:

  # Source: https://wiki.mozilla.org/Security/Guidelines/OpenSSH
  '6.5': [ 'hmac-sha2-512-etm@openssh.com', 'hmac-sha2-256-etm@openssh.com',
           'umac-128-etm@openssh.com', 'hmac-sha2-512', 'hmac-sha2-256',
           'umac-128@openssh.com' ]

  # Source: https://xivilization.net/~marek/blog/2015/01/12/secure-secure-shell-on-debian-wheezy/
  '6.0': [ 'hmac-sha2-512', 'hmac-sha2-256', 'hmac-ripemd160' ]
sshd__macs_additional

List of additional message authentication code algorithms to support by the sshd server, depending on available version, ordered from stronger to weaker. Newer version supersedes older version.

sshd__macs_additional: []
sshd__moduli_minimum

Specify minimum size of Diffie-Hellman parameters available to the SSH server. Parameters smaller than the given amount will be removed from the /etc/ssh/moduli file.

sshd__moduli_minimum: '2048'
sshd__paranoid

If set to True, only the first item (which is considered the strongest method available) from the lists sshd__ciphers_map, sshd__kex_algorithms_map and sshd__macs_map will be configured for sshd. Use this with care as it will deny access to anyone not able to use the first cryptographic method. See https://github.com/debops/ansible-sshd/issues/20

sshd__paranoid: False

Authorized key lookup configuration

sshd__authorized_keys_lookup

Enable support for looking up authorized public keys in external data sources (currently LDAP is supported). This function works only with OpenSSH 6.2+.

sshd__authorized_keys_lookup: '{{ ansible_local.ldap.posix_enabled|d()|bool }}'
sshd__authorized_keys_lookup_user

Name of the UNIX account which will be used to look up authorized keys.

sshd__authorized_keys_lookup_user: 'sshd'
sshd__authorized_keys_lookup_type

List of lookup scripts that should be enabled on a host.

sshd__authorized_keys_lookup_type: [ 'ldap', 'sss' ]

LDAP lookup configuration

sshd__ldap_enabled

Enable or disable integration with the LDAP directory. The integration is enabled automatically when the debops.ldap environment is configured on the host.

sshd__ldap_enabled: '{{ ansible_local.ldap.enabled
                        if (ansible_local|d() and ansible_local.ldap|d() and
                            ansible_local.ldap.enabled is defined)
                        else False }}'
sshd__ldap_base_dn

The base LDAP Distinguished Name used for SSH public key lookups.

sshd__ldap_base_dn: '{{ ansible_local.ldap.base_dn|d([]) }}'
sshd__ldap_device_dn

The Distinguished Name of the device LDAP object that represents current host. It will be used as a base DN for the sshd LDAP account object.

sshd__ldap_device_dn: '{{ ansible_local.ldap.device_dn|d([]) }}'
sshd__ldap_device_object_classes

List of additional LDAP Object Classes to add to the device LDAP object.

sshd__ldap_device_object_classes: [ 'ldapPublicKey' ]
sshd__ldap_device_attributes

YAML dictionary with additional LDAP attributes which will be added to the device LDAP object.

sshd__ldap_device_attributes:
  sshPublicKey: '{{ sshd__env_register_host_public_keys.stdout_lines }}'
sshd__ldap_self_rdn

The Relative Distinguished Name of the sshd LDAP account object.

sshd__ldap_self_rdn: 'uid={{ sshd__authorized_keys_lookup_user }}'
sshd__ldap_self_object_classes

The LDAP Object Classes used to create the sshd LDAP account object.

sshd__ldap_self_object_classes: [ 'account', 'simpleSecurityObject' ]
sshd__ldap_self_attributes

YAML dictionary that contains the attributes of the sshd LDAP account object.

sshd__ldap_self_attributes:
  uid: '{{ sshd__ldap_self_rdn.split("=")[1] }}'
  userPassword: '{{ sshd__ldap_bindpw }}'
  host: '{{ [ ansible_fqdn, ansible_hostname ] | unique }}'
  description: 'Account used by the "sshd" service to access the LDAP directory'
sshd__ldap_binddn

The Distinguished Name of the sshd LDAP account object used to authenticate to the LDAP directory, defined as a string.

sshd__ldap_binddn: '{{ ([ sshd__ldap_self_rdn ] + sshd__ldap_device_dn) | join(",") }}'
sshd__ldap_bindpw

The password defined in the sshd LDAP account object used to authenticate to the LDAP directory.

sshd__ldap_bindpw: '{{ (lookup("password", secret + "/ldap/credentials/"
                               + sshd__ldap_binddn | to_uuid + ".password length=32"))
                       if sshd__ldap_enabled|bool
                       else "" }}'
sshd__ldap_filter

Active ldapsearch filter used to select correct account while looking up the SSH public key.

sshd__ldap_filter: '{{ sshd__ldap_filter_map["service+host"] }}'
sshd__ldap_posix_urns

List of LDAP search filters which are derived from URN-like patterns defined for a given host in the debops.ldap role. See Host-based access control for more details.

sshd__ldap_posix_urns: '{{ ansible_local.ldap.urn_patterns|d([])
                           | map("regex_replace", "^(.*)$", "(host=posix:urn:\1)")
                           | list }}'
sshd__ldap_filter_map

Dict with set of available LDAP filters that can be used to lookup the SSH public key.

sshd__ldap_filter_map:

  # User account needs 'authorizedService' attribute
  'service': '(&
                (objectClass=posixAccount)
                (uid=$username)
                (|
                  (authorizedService=all)
                  (authorizedService=$service)
                  (authorizedService=shell)
                )
              )'

  # User account needs 'host' attribute
  'host': '(&
             (objectClass=posixAccount)
             (uid=$username)
             (|
               (host=posix:all)
               (host=posix:$fqdn)
               (host=posix:\2a.$domain)
               {{ sshd__ldap_posix_urns | join(" ") }}
             )
           )'

  # User account needs both 'authorizedService' and 'host' attributes.
  'service+host': '(&
                     (objectClass=posixAccount)
                     (uid=$username)
                     (|
                       (authorizedService=all)
                       (authorizedService=$service)
                       (authorizedService=shell)
                     )
                     (|
                       (host=posix:all)
                       (host=posix:$fqdn)
                       (host=posix:\2a.$domain)
                       {{ sshd__ldap_posix_urns | join(" ") }}
                     )
                   )'

PAM configuration

sshd__pam_deploy_state

Enable or disable support for custom PAM configuration for the sshd service. Set to absent to remove the customizations.

sshd__pam_deploy_state: 'present'
sshd__pam_access_file

Specify the absolute path of the PAM access file to use for the sshd service.

sshd__pam_access_file: '{{ "/etc/security/access-sshd.conf"
                           if ("sshd" in ansible_local.pam_access.rules|d([]))
                           else "/etc/security/access.conf" }}'

Match conditional blocks

sshd__match_list

List of conditional Match blocks to include in sshd_config. Required parameters:

  • match: specify User, Group, or other Match arguments which should activate a given configuration block.

  • options: YAML text block which contains sshd_config(5) options active in a given Match block.

sshd__match_list: [ '{{ sshd__match_group_sftponly }}' ]
sshd__match_group_sftponly

Default Match conditional block which defines configuration for SFTPonly accounts. The stfponly UNIX system group is created by the debops.system_groups Ansible role.

sshd__match_group_sftponly:
  match: 'Group sftponly'
  options: |
    AuthorizedKeysFile {{ sshd__authorized_keys_system | join(' ') }}
    ChrootDirectory %h
    X11Forwarding no
    AllowAgentForwarding no
    AllowTcpForwarding no
    PermitTunnel no
    ForceCommand internal-sftp

Configuration of other services

sshd__apt_preferences__dependent_list

List of apt_preferences(5) rules. This is used to change what package versions are installed on a particular distribution.

sshd__apt_preferences__dependent_list:

  - package: 'ssh ssh-* openssh-*'
    backports: [ 'wheezy' ]
    reason:  'Version parity with Debian Jessie, support for AuthorizedKeysCommand, better ciphers'
    by_role: 'debops.sshd'
sshd__ferm__dependent_rules:

Configuration for iptables firewall managed by ferm.

sshd__ferm__dependent_rules:

  - type: 'accept'
    dport: '{{ sshd__ferm_ports }}'
    interface: '{{ sshd__ferm_interface }}'
    weight: '0'
    weight_class: 'sshd-chain'
    name: 'sshd_jump-filter-ssh'
    target: '{{ sshd__ferm_limit_chain }}'
    rule_state: '{{ "present" if sshd__ferm_limit|bool else "absent" }}'
    comment: 'Create a separate "iptables" chain for SSH rules'

  - chain: '{{ sshd__ferm_limit_chain if (sshd__ferm_limit|bool) else "INPUT" }}'
    type: 'accept'
    dport: '{{ sshd__ferm_ports }}'
    saddr: '{{ sshd__whitelist + sshd__group_whitelist + sshd__host_whitelist }}'
    interface: '{{ [] if (sshd__ferm_limit|bool) else sshd__ferm_interface }}'
    weight: '1'
    weight_class: 'sshd-chain'
    name: 'sshd_whitelist'
    subchain: False
    accept_any: False
    comment: 'Accept any hosts in the whitelist unconditionally'

  - chain: '{{ sshd__ferm_limit_chain if sshd__ferm_limit | bool else "INPUT" }}'
    type: 'accept'
    dport: '{{ sshd__ferm_ports }}'
    saddr: '{{ sshd__allow + sshd__group_allow + sshd__host_allow }}'
    interface: '{{ [] if (sshd__ferm_limit|bool) else sshd__ferm_interface }}'
    weight: '2'
    weight_class: 'sshd-chain'
    name: 'sshd_allow'
    subchain: False
    accept_any: '{{ False if sshd__ferm_limit | bool else True }}'
    comment: |
      Accept any hosts in the allow list. If there are any hosts specified,
      block connections from other hosts using TCP Wrappers.

  - chain: '{{ sshd__ferm_limit_chain }}'
    type: 'recent'
    weight: '3'
    weight_class: 'sshd-chain'
    name: 'sshd_block-ssh'
    dport: '{{ sshd__ferm_ports }}'
    state: [ 'NEW' ]
    subchain: False
    recent_name: 'ssh-new'
    recent_update: True
    recent_seconds: '{{ sshd__ferm_limit_seconds }}'
    recent_hitcount: '{{ sshd__ferm_limit_hits }}'
    recent_target: 'REJECT'
    rule_state: '{{ "present" if sshd__ferm_limit|bool else "absent" }}'
    comment: |
      Block new SSH connections that have been marked as recent if they make
      too many new connection attempts.

  - chain: '{{ sshd__ferm_limit_chain }}'
    type: 'recent'
    weight: '4'
    weight_class: 'sshd-chain'
    name: 'sshd_mark-ssh'
    dport: '{{ sshd__ferm_ports }}'
    state: [ 'NEW' ]
    subchain: False
    recent_set_name: 'ssh-new'
    recent_log: False
    rule_state: '{{ "present" if sshd__ferm_limit|bool else "absent" }}'
    comment: 'Mark new connections to the SSH service for recent tracking'

  - chain: '{{ sshd__ferm_limit_chain }}'
    type: 'accept'
    weight: '5'
    weight_class: 'sshd-chain'
    role: 'sshd'
    role_weight: '60'
    name: 'sshd_accept-ssh'
    dport: '{{ sshd__ferm_ports }}'
    rule_state: '{{ "present" if sshd__ferm_limit|bool else "absent" }}'
    comment: 'Accept connections to the SSH service'
sshd__tcpwrappers__dependent_allow

Configure TCP wrappers to allow access to the sshd daemon.

sshd__tcpwrappers__dependent_allow:

  - daemon: 'sshd'
    client: '{{ sshd__whitelist + sshd__group_whitelist + sshd__host_whitelist }}'
    accept_any: '{{ False if (sshd__allow + sshd__group_allow + sshd__host_allow) else True }}'
    weight: '25'
    filename: 'sshd_dependent_whitelist'
    comment: 'Whitelist of hosts allowed to connect to ssh'

  - daemon: 'sshd'
    client: '{{ sshd__allow + sshd__group_allow + sshd__host_allow }}'
    default: '{{ sshd__tcpwrappers_default }}'
    accept_any: '{{ True if (sshd__whitelist + sshd__group_whitelist + sshd__host_whitelist) else False }}'
    weight: '30'
    filename: 'sshd_dependent_allow'
    comment: 'List of hosts allowed to connect to ssh'
sshd__ldap__dependent_tasks

Configuration for the debops.ldap Ansible role.

sshd__ldap__dependent_tasks:

  - name: 'Add missing LDAP object classes to {{ sshd__ldap_device_dn | join(",") }}'
    dn: '{{ sshd__ldap_device_dn }}'
    attributes:
      objectClass: '{{ sshd__ldap_device_object_classes }}'
    state: '{{ "present"
               if ((ansible_local.ldap.posix_enabled|d())|bool and
                   sshd__ldap_device_dn|d())
               else "ignore" }}'

  - name: 'Update SSH host public keys in {{ sshd__ldap_device_dn | join(",") }}'
    dn: '{{ sshd__ldap_device_dn }}'
    attributes: '{{ sshd__ldap_device_attributes }}'
    state: '{{ "exact"
               if ((ansible_local.ldap.posix_enabled|d())|bool and
                   sshd__ldap_device_dn|d())
               else "ignore" }}'

  - name: 'Create sshd account for {{ sshd__ldap_device_dn | join(",") }}'
    dn: '{{ sshd__ldap_binddn }}'
    objectClass: '{{ sshd__ldap_self_object_classes }}'
    attributes: '{{ sshd__ldap_self_attributes }}'
    no_log: '{{ debops__no_log | d(True) }}'
    state: '{{ "present"
               if (sshd__authorized_keys_lookup|bool and
                   ("ldap" in sshd__authorized_keys_lookup_type))
               else "ignore" }}'
sshd__pam_access__dependent_rules

Configuration for the debops.pam_access Ansible role.

sshd__pam_access__dependent_rules:

  - name: 'sshd'
    options:

      - name: 'allow-root-ansible-controllers'
        comment: 'Grant access via SSH to root account from the Ansible Controller hosts'
        permission: 'allow'
        users: 'root'
        origins: '{{ ansible_local.core.ansible_controllers|d([]) }}'

      - name: 'allow-root'
        comment: 'Grant access via SSH to root account on the same DNS domain'
        permission: 'allow'
        users: 'root'
        origins: '.{{ ansible_domain }}'

      - name: 'deny-root'
        comment: 'Deny access to root account via SSH from anywhere else'
        permission: 'deny'
        users: 'root'
        origins: 'ALL'

      - name: 'allow-system-groups'
        comment: |
          Grant access via SSH to members of UNIX groups defined on this host
        permission: 'allow'
        groups: '{{ ansible_local.system_groups.access.sshd
                    |d([ "admins", "sshusers", "sftponly" ]) }}'
        origins: 'ALL'

      - name: 'allow-ldap-groups'
        comment: |
          Grant access via SSH to members of UNIX groups defined in LDAP
        permission: 'allow'
        groups: [ 'admins', 'sshusers', 'sftponly' ]
        origins: 'ALL'
        state: '{{ "present"
                   if (ansible_local.ldap.posix_enabled|d()|bool)
                   else "absent" }}'

      - name: 'allow-domain'
        comment: |
          Grant access via SSH to users on the same DNS domain. The SSH server
          needs to have UseDNS option enabled for this rule to work correctly.
        permission: 'allow'
        users: 'ALL'
        origins: '.{{ ansible_domain }}'

      - name: 'deny-all'
        comment: 'Deny access via SSH by anyone from anywhere'
        permission: 'deny'
        users: 'ALL'
        origins: 'ALL'
        weight: 99999
sshd__sudo__dependent_sudoers

Configuration for the debops.sudo Ansible role.

sshd__sudo__dependent_sudoers:

  - name: 'sshd'
    options:

      - name: 'env_keep_ssh'
        comment: |-
          Allow molly-guard to detect that we connected via ssh even if
          combined with sudo and tmux.
          https://superuser.com/questions/666931/getting-molly-guard-to-work-with-sudo
          It is not perfect, but works in most cases.
          A case where it does not work is when `sudo tmux` is started via
          local tty and then attached to it via ssh.
          Or `sudo tmux` is executed via ssh and then attached locally.
          But when a new shell is created in tmux, the environment variables in
          that new shell are correct.
        value: |
          Defaults env_keep += SSH_CONNECTION