Getting started
Changes from Debian defaults
The debops.sshd role will configure the OpenSSH server to lookup the client
hostnames in DNS by setting the UseDNS option to yes (the Debian and
upstream default is no). This allows use of the DNS hostnames and domains
in the authorized keys files and PAM access control rules.
The role will divert the original /etc/pam.d/sshd configuration file
and generate a new one, with PAM access control enabled and using the separate
/etc/security/access-sshd.conf configuration file. The ACL rules are
defined in the sshd__pam_access__dependent_rules variable and are
managed by the debops.pam_access Ansible role.
To disable the custom access control configuration, set the
sshd__pam_deploy_state variable to absent. The PAM access control
file will still be generated, but it will not be used by the sshd service.
Global root access
By default the debops.pam_access configuration restricts access to the
root account to hosts on the same DNS domain, for security. This might
cause unintended lockouts if your Ansible Controller host is on a completely
different domain than the remote host.
To disable the restricted access and allow connections to the root account
from anywhere on the network, you can set in your Ansible inventory, for
example in ansible/inventory/group_vars/debops_all_hosts/pam_access.yml file:
pam_access__rules:
- name: 'sshd'
state: 'append'
options:
- name: 'allow-root'
origins: 'ALL'
Then, you need to apply the changes to the configuration using the "context" of the debops.sshd role, for example by executing the command:
$ debops run service/sshd -l <host> --tags role::pam_access --diff
This command will apply the PAM access configuration defined by the debops.sshd role with modifications from the inventory; they won't be applied in other contexts of the debops.pam_access role is used in and shouldn't affect other access lists.
You could also add subnets, domains or other origins instead of allowing access from any host; refer to the pam_access__rules for more details.
Access to the root account via password
The debops.sshd role checks if the /root/.ssh/authorized_keys
file is present on the host, using Ansible local facts defined by the
debops.root_account role. If the file is present, we assume that the
sysadmin SSH keys are on the host, and password-based access to the root
account is disabled by setting the PermitRootLogin option to
prohibit-password and the PasswordAuthentication option to no.
If the SSH authorized keys file is not present, the host is assumed to not be
fully provisioned yet. The PermitRootLogin option as well as the
PasswordAuthentication option will be set to yes to permit access to
the root account via SSH. Note that the default PAM access policy set in
the sshd__pam_access__dependent_rules variable still applies and
access to the root account will be limited to hosts on the same DNS domain.
Alternatively, if the sysadmin accounts are configured using the
debops.system_users Ansible role, access to the root account via
password and password authentication will also be disabled.
Useful variables
This is a list of role variables which you most likely want to define in Ansible inventory to customize OpenSSH server:
sshd__whitelist/sshd__group_whitelist/sshd__host_whitelistLists which contain IP addresses or CIDR subnets that are permitted to connect to OpenSSH without restrictions or firewall limits. Adding entries here will not impose additional restrictions, unlike using
sshd__*_allowlists.sshd__known_hosts/sshd__group_known_hosts/sshd__host_known_hostsHere you can add lists of FQDN hostnames which should be added to systemwide
/etc/ssh/ssh_known_hostsfile. For example, setting:sshd__known_hosts: [ 'github.com' ]
will add GitHub SSH fingerprint and allow you to clone git repositories over SSH with proper host authentication, without the need to ignore host fingerprints.
sshd__authorized_keys_lookupBoolean. If
True, role will enable lookup of SSH public keys in external authentication databases, like LDAP. This might require additional configuration usingsshd__ldap_*variables.LDAP key lookup depends on system-wide LDAP configuration in
/etc/ldap/ldap.conf, which can be performed (at the moment) using debops.ldap role. It will be configured when LDAP-POSIX integration is enabled on a given host.
Example inventory
debops.sshd role is part of the common.yml DebOps playbook. It will be
executed automatically on every host managed by DebOps.
Example playbook
If you are using this role without DebOps, here's an example Ansible playbook
that uses the debops.sshd role:
---
- name: Manage OpenSSH Server
collections: [ 'debops.debops' ]
hosts: [ 'debops_all_hosts', 'debops_service_sshd' ]
become: True
environment: '{{ inventory__environment | d({})
| combine(inventory__group_environment | d({}))
| combine(inventory__host_environment | d({})) }}'
pre_tasks:
- name: Prepare sshd environment
ansible.builtin.import_role:
name: 'sshd'
tasks_from: 'main_env'
tags: [ 'role::sshd', 'role::ldap' ]
roles:
- role: ferm
tags: [ 'role::ferm', 'skip::ferm' ]
ferm__dependent_rules:
- '{{ sshd__ferm__dependent_rules }}'
- role: tcpwrappers
tags: [ 'role::tcpwrappers', 'skip::tcpwrappers' ]
tcpwrappers_dependent_allow:
- '{{ sshd__tcpwrappers__dependent_allow }}'
- role: python
tags: [ 'role::python', 'skip::python', 'role::ldap' ]
python__dependent_packages3:
- '{{ ldap__python__dependent_packages3 }}'
python__dependent_packages2:
- '{{ ldap__python__dependent_packages2 }}'
- role: ldap
tags: [ 'role::ldap', 'skip::ldap' ]
ldap__dependent_tasks:
- '{{ sshd__ldap__dependent_tasks }}'
- role: pam_access
tags: [ 'role::pam_access', 'skip::pam_access' ]
pam_access__dependent_rules:
- '{{ sshd__pam_access__dependent_rules }}'
- role: sudo
tags: [ 'role::sudo', 'skip::sudo' ]
sudo__dependent_sudoers:
- '{{ sshd__sudo__dependent_sudoers }}'
- role: sshd
tags: [ 'role::sshd', 'skip::sshd' ]