commit 584f250bff1cb4caea05e5b737b403a8a368f30a
Author: Nicolas Chauvet <kwizart(a)gmail.com>
Date: Wed Jul 31 11:41:31 2019 +0200
Add basessh role
roles/basessh/README | 4 +
roles/basessh/handlers/main.yml | 3 +
roles/basessh/tasks/main.yml | 253 +++++++++++++++++++++++++++++++++++
roles/basessh/templates/sshd_config | 55 ++++++++
4 files changed, 315 insertions(+), 0 deletions(-)
---
diff --git a/roles/basessh/README b/roles/basessh/README
new file mode 100644
index 0000000..317ef04
--- /dev/null
+++ b/roles/basessh/README
@@ -0,0 +1,4 @@
+This role is the base setup for all our machines.
+
+If there's something that shouldn't be run on every single
+machine, it should be in another role.
diff --git a/roles/basessh/handlers/main.yml b/roles/basessh/handlers/main.yml
new file mode 100644
index 0000000..0c4def4
--- /dev/null
+++ b/roles/basessh/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: restart sshd
+ service: name=sshd state=restarted
diff --git a/roles/basessh/tasks/main.yml b/roles/basessh/tasks/main.yml
new file mode 100644
index 0000000..49a5aff
--- /dev/null
+++ b/roles/basessh/tasks/main.yml
@@ -0,0 +1,253 @@
+---
+#
+# We have some tasks here in case this is a bare metal machine
+# and we are provisioning it for the first time.
+# virtual machines are handled in tasks/virt-instance-create
+#
+
+- name: make sure there is no old ssh host key for the host still around
+ local_action: known_hosts path={{item}} host={{ inventory_hostname }} state=absent
+ ignore_errors: True
+ with_items:
+ - /root/.ssh/known_hosts
+ when: birthday is defined
+
+- name: gather ssh host key from new instance
+ local_action: command ssh-keyscan -t rsa {{ inventory_hostname }}
+ ignore_errors: True
+ register: hostkey
+ when: birthday is defined
+
+- name: add new ssh host key (until we can sign it)
+ local_action: known_hosts path={{item}} key="{{ hostkey.stdout }}" host={{
inventory_hostname }} state=present
+ ignore_errors: True
+ with_items:
+ - /root/.ssh/known_hosts
+ when: birthday is defined
+
+- name: make sure libselinux-python is installed
+ package: name=libselinux-python state=present
+ tags:
+ - basessh
+ - sshd_config
+ - config
+ - sshd
+ - selinux
+ when: ansible_distribution_major_version|int < 30 and
ansible_distribution_major_version|int != 8
+
+- name: make sure python3-libselinux is installed
+ package: name=python3-libselinux state=present
+ tags:
+ - basessh
+ - sshd_config
+ - config
+ - sshd
+ - selinux
+ when: ansible_distribution_major_version|int >= 30 or
ansible_distribution_major_version|int == 8
+
+- name: check if sshd port is already known by selinux
+ shell: semanage port -l | grep ssh
+ register: sshd_selinux_port
+ check_mode: no
+ changed_when: false
+ failed_when: false
+ tags:
+ - basessh
+ - sshd_config
+ - config
+ - sshd
+ - selinux
+ - base
+
+- name: allow alternate sshd port
+ command: semanage port -a -t ssh_port_t -p tcp {{ sshd_port }}
+ when: sshd_port in sshd_selinux_port
+ failed_when: false
+ tags:
+ - basessh
+ - sshd_config
+ - config
+ - sshd
+ - selinux
+ - base
+
+- name: sshd_config
+ template: src=sshd_config dest=/etc/ssh/sshd_config mode=0600
+ notify:
+ - restart sshd
+ tags:
+ - basessh
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Determine SSH keys generated by this machine
+ find: paths=/etc/ssh
+ file_type=file
+ patterns="ssh_host_*_key"
+ register: ssh_key_files
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Determine SSH keys never signed
+ stat: path="{{item.path}}-cert.pub"
+ with_items: "{{ssh_key_files.files}}"
+ register: ssh_cert_files
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Set lists of certs to sign to empty
+ set_fact:
+ certs_to_sign: "[]"
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Set list of certs to sign
+ set_fact:
+ certs_to_sign: "{{certs_to_sign}} + [ '{{item.item.path}}' ]"
+ with_items: "{{ssh_cert_files.results}}"
+ when: not item.stat.exists
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+# Renew if last mod was more than 10 months ago
+- name: Get soon-to-expire certificates to sign
+ set_fact:
+ certs_to_sign: "{{certs_to_sign}} + [ '{{item.item.path}}' ]"
+ with_items: "{{ssh_cert_files.results}}"
+ when: "item.stat.exists and item.stat.mtime|int < (lookup('pipe',
'date +%s')|int - 25920000)"
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- set_fact:
+ pubkeydir: "/tmp/sshkeysign/{{inventory_hostname}}"
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Create directory for storing pubkeys
+ file: path="{{pubkeydir}}"
+ owner=root
+ group=root
+ mode=0600
+ state=directory
+ delegate_to: localhost
+ run_once: true
+ changed_when: False
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Get public keys for certs to sign
+ fetch: src="{{item}}.pub"
+ dest="{{pubkeydir}}"
+ fail_on_missing=true
+ with_items: "{{certs_to_sign}}"
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Set some extra signing facts
+ set_fact:
+ sign_hostnames: "{{ssh_hostnames}} + ['{{inventory_hostname}}']"
+ sign_validity: "-1h:+52w"
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+# Currently, we use the epoch as serial. That's unique enough for now
+- name: Sign the certificates
+ shell: "ssh-keygen -s {{private}}/files/ssh/{{env}}_ca_host_key -I
{{inventory_hostname}} -h -n {{ sign_hostnames|join(',') }} -V {{sign_validity}}
-z `date +%s` {{pubkeydir}}/{{inventory_hostname}}{{item}}.pub"
+ delegate_to: localhost
+ with_items: "{{certs_to_sign}}"
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Copy the certificates
+ copy: src="{{pubkeydir}}/{{inventory_hostname}}{{item}}-cert.pub"
+ dest="{{item}}-cert.pub"
+ with_items: "{{certs_to_sign}}"
+ register: certcopy
+ notify:
+ - restart sshd
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Remove the generated certificates
+ local_action: file path="{{pubkeydir}}/{{inventory_hostname}}" state=absent
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: Restart sshd in case we just signed a new certificate so it gets applied
+ service: name=sshd state=restarted
+ when: certcopy.changed
+ tags:
+ - basessh
+ - sshd_cert
+ - sshd_config
+ - config
+ - sshd
+ - base
+
+- name: make sure there is no old ssh host key for the host still around
+ local_action: known_hosts path={{item}} host={{ inventory_hostname }} state=absent
+ ignore_errors: True
+ with_items:
+ - /root/.ssh/known_hosts
diff --git a/roles/basessh/templates/sshd_config b/roles/basessh/templates/sshd_config
new file mode 100644
index 0000000..3138bfd
--- /dev/null
+++ b/roles/basessh/templates/sshd_config
@@ -0,0 +1,55 @@
+Protocol 2
+
+Port {{ sshd_port|22 }}
+
+{% if ansible_distribution_major_version == "6" %}
+KexAlgorithms diffie-hellman-group-exchange-sha256
+MACs hmac-sha2-512,hmac-sha2-256
+Ciphers aes256-ctr,aes192-ctr,aes128-ctr
+{% else %}
+KexAlgorithms
curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
+Ciphers
chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm(a)openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
+MACs
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(a)openssh.com
+{% endif %}
+
+HostKey /etc/ssh/ssh_host_rsa_key
+{% if sshd_host_certificate %}
+HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub
+{% endif %}
+
+SyslogFacility AUTHPRIV
+LogLevel VERBOSE
+
+PermitRootLogin without-password
+StrictModes yes
+AuthorizedKeysFile .ssh/authorized_keys
+
+PasswordAuthentication no
+ChallengeResponseAuthentication no
+GSSAPIAuthentication no
+UsePAM yes
+
+AllowAgentForwarding no
+X11Forwarding no
+PermitTunnel no
+
+{% if ansible_distribution_major_version == "6" %}
+UsePrivilegeSeparation yes
+{% elif ansible_distribution_major_version == "7" %}
+UsePrivilegeSeparation sandbox
+{% endif %}
+
+# Accept locale-related environment
+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
+
+{% if sshd_keyhelper %}
+# For repospanner/git
+AuthorizedKeysCommandUser git
+AuthorizedKeysCommand /usr/libexec/pagure/keyhelper.py "%u" "%h"
"%t" "%f"
+{% endif %}
+{% if sshd_sftp %}
+Subsystem sftp internal-sftp
+{% endif %}