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_whitelist
Lists 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__*_allow
lists.sshd__known_hosts
/sshd__group_known_hosts
/sshd__host_known_hosts
Here you can add lists of FQDN hostnames which should be added to systemwide
/etc/ssh/ssh_known_hosts
file. 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_lookup
Boolean. 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', 'debops.roles01',
'debops.roles02', 'debops.roles03' ]
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' ]