Update to 2021-12-01 19:13

This commit is contained in:
Daniel Berteaud
2021-12-01 19:13:34 +01:00
commit 4c4556c660
2153 changed files with 60999 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
---
# List of port sshd will bind to
sshd_ports: [ '22' ]
# Will restrict ssh access to the following IP
#
sshd_src_ip: []
# sshd_src_ip:
# - 12.13.14.15
# - 192.168.17.0/24
sshd_permit_root_login: no
sshd_password_auth: yes
# Control the AllowUsers, DenyUsers, AllowGroups and DenyGroups
# sshd_allow_users:
# - fws
# - dani
# sshd_deny_users:
# - dimitri
# - flo
# sshd_allow_groups:
# - tech
# - support
# sshd_deny_groups:
# - sales
# - interim
#
#
# User configuration
#ssh_users:
# - name: dani
# create_user: False
# ssh_keys:
# - 'ssh-rsa AAAAB3NzaC1yc2...'
# - 'ssh-rsa AAAAB3NzaC1yc2...'
# key_options:
# - from="192.168.3.7"
# - no-pty
# sftp_only: True
# chroot: /var/www/html
# keys_file: %h/.ssh/authorized_keys
# allow_forwarding: False
# sudo_defaults:
# - '!env_reset'
# - '!requiretty'
# sudo:
# - cmd:
# - /usr/local/bin/
# run_as: root
# nopasswd: False
#
#ssh_extra_users (can be used as ssh_users)
#
#
# Max number of conn / minute. 0 to disable rate limit
sshd_max_conn_per_minute: 0
# Authorized Keys custom command
# sshd_authorized_keys_command: /usr/local/bin/ssh-getkeys
# sshd_authorized_keys_command_user: ldapsshkey
# Use DNS. If disabled, kerb auth won't be used (as it uses DNS)
# You might need to disable it when you need no SSH login delay even if DNS is unavailable
sshd_use_dns: True

View File

@@ -0,0 +1,4 @@
---
- name: restart sshd
service: name=sshd state=restarted enabled=yes

1
roles/ssh/meta/main.yml Normal file
View File

@@ -0,0 +1 @@
---

139
roles/ssh/tasks/main.yml Normal file
View File

@@ -0,0 +1,139 @@
---
- name: Install ssh components
yum:
name:
- openssh-server
- openssh-clients
when: ansible_os_family == 'RedHat'
tags: ssh
- name: Install ssh components
apt:
name:
- openssh-server
- openssh-client
when: ansible_os_family == 'Debian'
tags: ssh
- name: Allow ssh port in SELinux
seport: ports={{ sshd_ports|join(',') }} proto=tcp setype=ssh_port_t state=present
when: ansible_selinux.status == 'enabled'
tags: ssh
- name: Combine SSH users
set_fact:
ssh_users: "{{ ssh_users + ssh_extra_users | default([]) }}"
tags: ssh
- name: Deploy sshd configuration
template: src=sshd_config.j2 dest=/etc/ssh/sshd_config backup=yes
notify: restart sshd
tags: ssh
- name: Set SSH rate limit
iptables_raw:
name: sshd_limit
rules: |
-A INPUT -p tcp -m state --state NEW -m multiport --dports {{ sshd_ports | join(',') }} -m recent --name ssh_limit --set
-A INPUT -p tcp -m state --state NEW -m multiport --dports {{ sshd_ports | join(',') }} -m recent --name ssh_limit --rcheck --seconds 60 --hitcount {{ sshd_max_conn_per_minute }} -j LOG --log-prefix "Firewall (ssh limit): "
-A INPUT -p tcp -m state --state NEW -m multiport --dports {{ sshd_ports | join(',') }} -m recent --name ssh_limit --rcheck --seconds 60 --hitcount {{ sshd_max_conn_per_minute }} -j REJECT
state: "{{ (sshd_max_conn_per_minute > 0) | ternary('present','absent') }}"
weight: 10
when: iptables_manage | default(True)
tags: ssh,firewall
- name: Handle ssh ports
iptables_raw:
name: sshd_ports
state: "{{ (sshd_src_ip is defined and sshd_src_ip | length > 0) | ternary('present','absent') }}"
rules: "-A INPUT -m state --state new -p tcp -m multiport --dports {{ sshd_ports | join(',') }} -s {{ sshd_src_ip | flatten | join(',') }} -j ACCEPT"
when: iptables_manage | default(True)
tags: ssh,firewall
- name: Create top level authorized keys directory
file: path=/etc/ssh/authorized_keys/ state=directory mode=755 owner=root group=root
tags: ssh
- name: Create an SSH key pair for root
user:
name: root
generate_ssh_key: yes
ssh_key_file: .ssh/id_rsa
tags: ssh
# Do this in two times, to prevent hitting a bug in ansible
# where usermod could be called before useradd
# See https://github.com/ansible/ansible/issues/22576
- name: Create ssh users
user:
name: "{{ item.name }}"
with_items: "{{ ssh_users }}"
register: ssh_create_user
when: item.create_user | default(False)
tags: ssh
- name: Check if sssd is installed
stat: path=/usr/sbin/sss_cache
register: ssh_sss_cache
tags: ssh
# Flush sss cache so we can modify freshly created users
- name: Reset sss cache
command: sss_cache -E
when: ssh_sss_cache.stat.exists and ssh_create_user.results | selectattr('changed','equalto',True) | list | length > 0
tags: ssh
- name: Set ssh user attributes
user:
name: "{{ item.name }}"
comment: "{{ item.full_name | default(omit) }}"
shell: "{{ item.shell | default(omit) }}"
with_items: "{{ ssh_users }}"
when: item.create_user | default(False)
tags: ssh
- name: Create private dir for Authorized keys
file: path=/etc/ssh/authorized_keys/{{ item.name }} state=directory mode=700 owner={{ item.name }}
ignore_errors: True # Needed eg, if LDAP isn't available on first run
with_items: "{{ ssh_users }}"
tags: ssh
- name: Deploy ssh user keys
authorized_key:
user: "{{ item.name }}"
key: "{{ item.ssh_keys| default([]) | join(\"\n\") }}"
key_options: "{{ item.key_options | default([]) | join(',') }}"
path: "/etc/ssh/authorized_keys/{{ item.name }}/authorized_keys"
manage_dir: False
exclusive: True
ignore_errors: True # Needed eg, if LDAP isn't available on first run
#when: item.ssh_keys is defined
with_items: "{{ ssh_users }}"
tags: ssh
- name: Ensure permissions and ownership on authorized_keys files
file:
path: /etc/ssh/authorized_keys/{{ item.name }}/authorized_keys
mode: 0600
owner: "{{ item.name }}"
when: item.ssh_keys is defined
ignore_errors: True
with_items: "{{ ssh_users }}"
tags: ssh
- name: List all authorized keys directories
shell: ls -1 /etc/ssh/authorized_keys | xargs -n1 basename
register: existing_ssh_keys
changed_when: False
tags: ssh
- name: Remove unmanaged ssh keys
file: path=/etc/ssh/authorized_keys/{{ item }} state=absent
with_items: "{{ existing_ssh_keys.stdout_lines | default([]) }}"
when: item not in ssh_users | map(attribute='name')
tags: ssh
- name: Deploy sudo fragment
template: src=sudo.j2 dest=/etc/sudoers.d/ssh_users mode=600
tags: ssh

View File

@@ -0,0 +1,91 @@
AddressFamily inet
Protocol 2
SyslogFacility AUTHPRIV
PermitRootLogin {{ (sshd_permit_root_login == True) | ternary('yes','no') }}
PasswordAuthentication {{ (sshd_password_auth == True) | ternary('yes','no') }}
{% if ad_auth is defined and ad_auth and sshd_use_dns %}
GSSAPIAuthentication yes
GSSAPIKeyExchange yes
GSSAPIStoreCredentialsOnRekey yes
{% endif %}
UseDNS {{ sshd_use_dns | ternary('yes', 'no') }}
{% if sshd_authorized_keys_command is defined %}
AuthorizedKeysCommand {{ sshd_authorized_keys_command }}
{% if sshd_authorized_keys_command_user is defined %}
AuthorizedKeysCommandUser {{ sshd_authorized_keys_command_user }}
{% endif %}
{% endif %}
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_ecdsa_key
AuthorizedKeysFile /etc/ssh/authorized_keys/%u/authorized_keys
{% if sshd_deny_users is defined and sshd_deny_users | length > 0 %}
DenyUsers {{ sshd_deny_users | join(' ') }}
{% endif %}
{% if sshd_allow_users is defined and sshd_allow_users | length > 0 %}
AllowUsers {{ sshd_allow_users | join(' ') }}
{% endif %}
{% if sshd_deny_groups is defined and sshd_deny_groups | length > 0 %}
DenyGroups {{ sshd_deny_groups | join(' ') }}
{% endif %}
{% if sshd_allow_groups is defined and sshd_allow_groups | length > 0 %}
AllowGroups {{ sshd_allow_groups | join(' ') }}
{% endif %}
{% for port in sshd_ports %}
Port {{ port }}
{% endfor %}
ChallengeResponseAuthentication no
UsePAM yes
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
AcceptEnv LC_PVE_*
X11Forwarding no
Subsystem sftp internal-sftp
# Local user are managed separately
Match User root,ansible,lbkp,zimbra,zfs-recv
AuthorizedKeysFile /etc/ssh/authorized_keys/%u/authorized_keys %h/.ssh/authorized_keys
{% for user in ssh_users | default([]) %}
Match user {{ user.name }}
{% if user.chroot is defined %}
ChrootDirectory {{ user.chroot }}
{% endif %}
{% if user.sftp_only | default(False) %}
ForceCommand internal-sftp{% if user.sftp_cd is defined %} -d {{ user.sftp_cd }}{% endif %}
{% endif %}
{% if user.allow_forwarding is defined %}
AllowTCPForwarding {{ user.allow_forwarding | ternary('yes', 'no') }}
X11Forwarding {{ user.allow_forwarding | ternary('yes', 'no') }}
{% endif %}
{% if user.keys_file is defined %}
AuthorizedKeysFile {{ user.keys_file }}
{% endif %}
{% endfor %}
{% for client in wh_clients | default([]) %}
# Web hosting client {{ client.name }}
# hosted app {{ client.apps | map(attribute='name') | list | join(', ') }}
Match Group client_{{ client.name }}{{ (samba_realm is defined) | ternary('@' + samba_realm | upper,'') }}
ChrootDirectory /opt/wh/{{ client.name }}
ForceCommand internal-sftp
AllowTCPForwarding no
X11Forwarding no
AuthorizedKeysFile /etc/ssh/wh/{{ client.name }}/authorized_keys
{% endfor %}

View File

@@ -0,0 +1,11 @@
{% for user in ssh_users | default([]) %}
{% if user.sudo_defaults is defined and user.sudo_defaults | length > 0 %}
Defaults:{{ user.name }} {{ user.sudo_defaults | join(',') }}
{% endif %}
{% if user.sudo is defined %}
{% for command in user.sudo %}
{{ user.name }} ALL=({{ command.run_as | default('root') }}) {% if command.nopasswd is defined and command.nopasswd %} NOPASSWD: {% endif %} {{ command.cmd | join(',') }}
{% endfor %}
{% endif %}
{% endfor %}