This commit is contained in:
Denis Knauf 2020-09-16 14:19:19 +02:00
parent 8516bed41f
commit 56b505cf94
11 changed files with 307 additions and 0 deletions

110
README.adoc Normal file
View file

@ -0,0 +1,110 @@
ssh_cert
========
Implements SSH-Certificate-renewal on hosts.
The renewal-process connects to ssh-ca-host and fetches a new certificate, if needed.
These renewal can be used for host-certificates and user-certificates.
Prepares `sshd_config` to use the CA and the host-certificate.
Requirements
------------
systemd is required, so it would not work on alpine or openwrt, yet.
Role Variables
--------------
ssh_ca_host::
Hostmachine for CA.
This is not host-specific, so you should change it for all hosts or neither.
Must match with `ssh_ca`-role.
ssh_ca_user::
Hostmachine for CA.
This is not host-specific, so you should change it for all hosts or neither.
Must match with `ssh_ca`-role.
Default: `sshca`
ssh_ca_base_dir::
Path to CA base on ssh-ca-host.
This is not host-specific, so you should change it for all hosts or neither.
Must match with `ssh_ca`-role.
Default: `~/.ssh-ca`
ssh_cert_mail_to::
If you want to be informed on renewal or errors, provide a mailto-address.
Mandatory, yet.
ssh_cert_mail_from::
If you want to be informed on renewal or errors, provide an address of sender.
Mandatory, yet.
ssh_cert_sign_host::
Default: `{{ssh_ca_user}}@{{ssh_ca_host}}`
ssh_cert_host_pub_path::
Path to host-key-pub on host-machine.
Would be used like a CSR.
Default: `/etc/ssh/ssh_host_ed25519_key.pub`
ssh_cert_host_cert_path::
Where to place the host-certificate on host-machine?
Default: `/etc/ssh/ssh_host_ed25519_key-cert.pub`
ssh_cert_host_capub_path::
Where to place the CA on host-machine?
Default: `/etc/ssh/ca.pub`
ssh_cert_user_pub_path::
Path to user-key-pub on host-machine.
Would be used like a CSR.
Default: `~/.ssh/id_ed25519.pub`
ssh_cert_user_cert_path::
Where to place the user-certificate on host-machine?
Default: `~/.ssh/id_ed25519-cert.pub`
ssh_cert_host_addition_ids::
Additional IDs (as list) placed in certificate.
For host-keys, additional hostnames like `git.example.net`.
Default is empty.
Dependencies
------------
* ssh-ca
Example Playbook
----------------
Optional, use ssh-ca-role before:
----
- name: SSH-CA
hosts: ssh_ca_server
roles:
- role: ssh-ca
----
This you need only on one machine.
Then use the regular role:
----
- name: SSH-Cert
hosts: hosts
roles:
- role: ssh-cert
----
License
-------
AGPLv3
Author Information
------------------
Denis Knauf - https://git.denkn.at/deac/ansible-role-ssh-cert

2
defaults/main.yml Normal file
View file

@ -0,0 +1,2 @@
---
# defaults file for ssh-ca

6
files/ssh-cert-renew Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env sh
set -e
ssh_ca_host="$1"
filepf="$2"
>"${filepf}-cert.pub.tmp" ssh -o BatchMode=true -i "${filepf}" "${ssh_ca_host}" renew show
mv "${filepf}-cert.pub.tmp" "${filepf}-cert.pub"

View file

@ -0,0 +1,8 @@
[Unit]
Description=Renewal ssh host certificate %i
[Service]
EnvironmentFile=/etc/default/ssh-cert-renew
Type=oneshot
ExecStart=/usr/local/bin/timer-mail -t ${ssh_ca_mail_to} -f ${ssh_ca_mail_from} -s "ssh certificate renewal %i" -ve \
/etc/systemd/ssh-cert-renew ${ssh_ca_sign_host} /etc/ssh/%i

View file

@ -0,0 +1,8 @@
[Unit]
Description=Renewal ssh host certificate %i
[Install]
WantedBy=timers.target
[Timer]
OnCalendar=4:00

2
handlers/main.yml Normal file
View file

@ -0,0 +1,2 @@
---
# handlers file for ssh-ca

53
meta/main.yml Normal file
View file

@ -0,0 +1,53 @@
galaxy_info:
author: your name
description: your role description
company: your company (optional)
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: license (GPL-2.0-or-later, MIT, etc)
min_ansible_version: 2.9
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
#
# Provide a list of supported platforms, and for each platform a list of versions.
# If you don't wish to enumerate all versions for a particular platform, use 'all'.
# To view available platforms and versions (or releases), visit:
# https://galaxy.ansible.com/api/v1/platforms/
#
# platforms:
# - name: Fedora
# versions:
# - all
# - 25
# - name: SomePlatform
# versions:
# - all
# - 1.0
# - 7
# - 99.99
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.

102
tasks/main.yml Normal file
View file

@ -0,0 +1,102 @@
---
# vim: set expandtab tabstop=2 shiftwidth=2:
- name: Pull host pub
register: host_pub
slurp:
src: '{{ssh_cert_host_pub_path}}'
#dest: '{{ssh_cert_base_dir}}/host-{{inventory_hostname}}.pub'
#flat: true
- set_fact:
host_pub_type: '{{(host_pub.content | b64decode).split(" ")[0]}}'
host_pub_hash: '{{(host_pub.content | b64decode).split(" ")[1]}}'
principals: "{{lookup( 'flattened',
[inventory_hostname, inventory_hostname+'.'+domain, inventory_hostname+'.local'] +
lookup ('dig', inventory_hostname, 'qtype=A', wantlist=True)|difference('NXDOMAIN') +
lookup ('dig', inventory_hostname, 'qtype=AAAA', wantlist=True)|difference('NXDOMAIN') +
(ssh_cert_host_addition_ids | default ([]))
)}}"
- name: Register host pub for sshca
remote_user: root
delegate_to: '{{ssh_ca_host}}'
authorized_key:
user: '{{ssh_ca_user}}'
state: present
key: '{{host_pub_type}} {{host_pub_hash}} {{inventory_hostname}}'
key_options: 'restrict,command="/var/lib/sshca/ssh-ca host {{inventory_hostname|quote}} {{principals|quote}}"'
- name: Push ca pub
copy:
src: '{{ssh_cert_host_capub_path}}'
dest: '{{ssh_cert_host_capub_path}}'
mode: 0644
owner: root
group: root
- name: sshd_config - HostCertificate
lineinfile:
path: /etc/ssh/sshd_config
insertbefore: '^# HostKeys for protocol'
regexp: '^\s*HostCertificate\s+'
line: 'HostCertificate {{ssh_cert_host_cert_path}}'
- name: known_hosts ca-cert
known_hosts:
hash_host: false
path: /etc/ssh/ssh_known_hosts
name: denkn.at
key: "@cert-authority * {{lookup('file', ssh_cert_host_capub_path)}}"
- name: install ssh-cert-renew
copy:
dest: '{{item.value}}'
src: '{{item.key}}'
mode: 0644
owner: root
group: root
with_dict:
ssh-cert-renew@.timer: /etc/systemd/system/ssh-cert-renew@.timer
ssh-cert-renew@.service: /etc/systemd/system/ssh-cert-renew@.service
- name: install ssh-cert-renew
copy:
dest: '{{item.value}}'
src: '{{item.key}}'
mode: 0755
owner: root
group: root
with_dict:
ssh-cert-renew: /etc/systemd/ssh-cert-renew
- name: config ssh-cert-renew
lineinfile:
create: true
path: '/etc/default/ssh-cert-renew'
regexp: '^\s*{{item.key}}='
line: '{{item.key}}={{item.value}}'
with_dict:
ssh_cert_mail_to: '{{ssh_cert_mail_to |mandatory}}'
ssh_cert_mail_from: '{{ssh_cert_mail_from|mandatory}}'
ssh_cert_sign_host: '{{ssh_cert_sign_host|mandatory}}'
- name: renew ssh-cert
systemd:
daemon_reload: true
name: "ssh-cert-renew@ssh_host_ed25519_key.service"
state: started
- name: enable services
systemd:
name: '{{item}}'
enabled: true
state: started
with_items:
- "ssh-cert-renew@ssh_host_ed25519_key.timer"
- ssh.service
- name: reload ssh
service:
name: ssh
state: reloaded
- name: remove from local known_hosts
known_hosts:
state: absent
host: '{{item}}'
with_items: '{{principals.split(",")}}'

2
tests/inventory Normal file
View file

@ -0,0 +1,2 @@
localhost

5
tests/test.yml Normal file
View file

@ -0,0 +1,5 @@
---
- hosts: localhost
remote_user: root
roles:
- ssh-ca

9
vars/main.yml Normal file
View file

@ -0,0 +1,9 @@
ssh_ca_user: sshca
ssh_ca_base_dir: ~/.ssh-ca
ssh_cert_sign_host: '{{ssh_ca_host}}'
ssh_cert_host_pub_path: /etc/ssh/ssh_host_ed25519_key.pub
ssh_cert_host_cert_path: /etc/ssh/ssh_host_ed25519_key-cert.pub
ssh_cert_host_capub_path: /etc/ssh/ca.pub
ssh_cert_user_pub_path: ~/.ssh/id_ed25519.pub
ssh_cert_user_cert_path: ~/.ssh/id_ed25519-cert.pub
#ssh_cert_host_addition_ids: []