init
This commit is contained in:
parent
8516bed41f
commit
56b505cf94
110
README.adoc
Normal file
110
README.adoc
Normal 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
2
defaults/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
# defaults file for ssh-ca
|
6
files/ssh-cert-renew
Executable file
6
files/ssh-cert-renew
Executable 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"
|
8
files/ssh-cert-renew@.service
Normal file
8
files/ssh-cert-renew@.service
Normal 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
|
8
files/ssh-cert-renew@.timer
Normal file
8
files/ssh-cert-renew@.timer
Normal 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
2
handlers/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
# handlers file for ssh-ca
|
53
meta/main.yml
Normal file
53
meta/main.yml
Normal 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
102
tasks/main.yml
Normal 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
2
tests/inventory
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
localhost
|
||||||
|
|
5
tests/test.yml
Normal file
5
tests/test.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
remote_user: root
|
||||||
|
roles:
|
||||||
|
- ssh-ca
|
9
vars/main.yml
Normal file
9
vars/main.yml
Normal 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: []
|
Loading…
Reference in a new issue