This state manages /etc/ssh/ssh_known_hosts and fills it with public SSH host keys of other minions.master
@@ -41,3 +41,42 @@ Installs the ssh daemon configuration file included in this formula | |||
by values from pillar. ``pillar.example`` results in the generation | |||
of the default ``sshd_config`` file on Debian Wheezy. | |||
``openssh.known_hosts`` | |||
----------------------- | |||
Manages the site-wide ssh_known_hosts file and fills it with the | |||
public SSH host keys of all minions. You can restrict the set of minions | |||
whose keys are listed by using the pillar data ``openssh:known_hosts:target`` | |||
and ``openssh:known_hosts:expr_form`` (those fields map directly to the | |||
corresponding attributes of the ``mine.get`` function). | |||
The Salt mine is used to share the public SSH host keys, you must thus | |||
configure it accordingly on all hosts that must export their keys. Two | |||
mine functions are required, one that exports the keys (one key per line, | |||
as they are stored in ``/etc/ssh/ssh_host_*_key.pub``) and one that defines | |||
the public hostname that the keys are associated to. Here's the way to | |||
setup those functions through pillar:: | |||
# Required for openssh.known_hosts | |||
mine_functions: | |||
public_ssh_host_keys: | |||
mine_function: cmd.run | |||
cmd: cat /etc/ssh/ssh_host_*_key.pub | |||
public_ssh_hostname: | |||
mine_function: grains.get | |||
key: id | |||
The above example assumes that the minion identifier is a valid DNS name | |||
that can be used to connect to the host. If that's not the case, you might | |||
want to use the ``fqdn`` grain instead of the ``id`` one. The above example | |||
also uses the default mine function names used by this formula. If you have to | |||
use other names, then you should indicate the names to use in pillar keys | |||
``openssh:known_hosts:mine_keys_function`` and | |||
``openssh:known_hosts:mine_hostname_function``. | |||
You can also integrate alternate DNS names of the various hosts in the | |||
ssh_known_hosts files. You just have to list all the alternate DNS names as a | |||
list in the ``openssh:known_hosts:aliases`` pillar key. Whenever the IPv4 or | |||
IPv6 behind one of those DNS entries matches an IPv4 or IPv6 behind the | |||
official hostname of a minion, the alternate DNS name will be associated to the | |||
minion's public SSH host key. |
@@ -0,0 +1,34 @@ | |||
{%- set target = salt['pillar.get']('openssh:known_hosts:target', '*') -%} | |||
{%- set expr_form = salt['pillar.get']('openssh:known_hosts:expr_form', 'glob') -%} | |||
{%- set keys_function = salt['pillar.get']('openssh:known_hosts:mine_keys_function', 'public_ssh_host_keys') -%} | |||
{%- set hostname_function = salt['pillar.get']('openssh:known_hosts:mine_hostname_function', 'public_ssh_hostname') -%} | |||
{#- Lookup IP of all aliases so that when we have a matching IP, we inject the alias name | |||
in the SSH known_hosts entry -#} | |||
{%- set aliases = salt['pillar.get']('openssh:known_hosts:aliases', []) -%} | |||
{%- set aliases_ips = {} -%} | |||
{%- for alias in aliases -%} | |||
{%- for ip in salt['dig.A'](alias) + salt['dig.AAAA'](alias) -%} | |||
{%- do aliases_ips.setdefault(ip, []).append(alias) -%} | |||
{%- endfor -%} | |||
{%- endfor -%} | |||
{#- Loop over targetted minions -#} | |||
{%- set host_keys = salt['mine.get'](target, keys_function, expr_form=expr_form) -%} | |||
{%- set host_names = salt['mine.get'](target, hostname_function, expr_form=expr_form) -%} | |||
{%- for host, keys in host_keys|dictsort -%} | |||
{%- set ip4 = salt['dig.A'](host) -%} | |||
{%- set ip6 = salt['dig.AAAA'](host) -%} | |||
{%- set names = [host_names.get(host, host)] -%} | |||
{%- for ip in ip4 + ip6 -%} | |||
{%- do names.append(ip) -%} | |||
{%- for alias in aliases_ips.get(ip, []) -%} | |||
{%- if alias not in names -%} | |||
{%- do names.append(alias) -%} | |||
{%- endif -%} | |||
{%- endfor -%} | |||
{%- endfor -%} | |||
{%- for line in keys.split('\n') -%} | |||
{%- if line -%} | |||
{{ ','.join(names) }} {{ line }} | |||
{% endif -%} | |||
{%- endfor -%} | |||
{%- endfor -%} |
@@ -0,0 +1,16 @@ | |||
{% from "openssh/map.jinja" import openssh with context %} | |||
ensure dig is available: | |||
pkg.installed: | |||
- name: {{ openssh.dig_pkg }} | |||
manage ssh_known_hosts file: | |||
file.managed: | |||
- name: {{ openssh.ssh_known_hosts }} | |||
- source: salt://openssh/files/ssh_known_hosts | |||
- template: jinja | |||
- user: root | |||
- group: root | |||
- mode: 644 | |||
- require: | |||
- pkg: ensure dig is available |
@@ -7,6 +7,8 @@ | |||
'sshd_config_src': 'salt://openssh/files/sshd_config', | |||
'banner': '/etc/ssh/banner', | |||
'banner_src': 'salt://openssh/files/banner', | |||
'dig_pkg': 'dnsutils', | |||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||
}, | |||
'Debian': { | |||
'server': 'openssh-server', | |||
@@ -16,6 +18,8 @@ | |||
'sshd_config_src': 'salt://openssh/files/sshd_config', | |||
'banner': '/etc/ssh/banner', | |||
'banner_src': 'salt://openssh/files/banner', | |||
'dig_pkg': 'dnsutils', | |||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||
}, | |||
'FreeBSD': { | |||
'service': 'sshd', | |||
@@ -23,6 +27,8 @@ | |||
'sshd_config_src': 'salt://openssh/files/sshd_config', | |||
'banner': '/etc/ssh/banner', | |||
'banner_src': 'salt://openssh/files/banner', | |||
'dig_pkg': 'bind-tools', | |||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||
}, | |||
'Gentoo': { | |||
'server': 'net-misc/openssh', | |||
@@ -32,6 +38,8 @@ | |||
'sshd_config_src': 'salt://openssh/files/sshd_config', | |||
'banner': '/etc/ssh/banner', | |||
'banner_src': 'salt://openssh/files/banner', | |||
'dig_pkg': 'net-dns/bind-tools', | |||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||
}, | |||
'RedHat': { | |||
'server': 'openssh-server', | |||
@@ -41,6 +49,8 @@ | |||
'sshd_config_src': 'salt://openssh/files/sshd_config', | |||
'banner': '/etc/ssh/banner', | |||
'banner_src': 'salt://openssh/files/banner', | |||
'dig_pkg': 'bind-utils', | |||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||
}, | |||
'Suse': { | |||
'server': 'openssh', | |||
@@ -50,5 +60,7 @@ | |||
'sshd_config_src': 'salt://openssh/files/sshd_config', | |||
'banner': '/etc/ssh/banner', | |||
'banner_src': 'salt://openssh/files/banner', | |||
'dig_pkg': 'bind-utils', | |||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||
}, | |||
}, merge=salt['pillar.get']('openssh:lookup')) %} |
@@ -104,3 +104,27 @@ openssh: | |||
-----END OPENSSH PRIVATE KEY----- | |||
public_key: | | |||
ssh-ed25519 NOT_DEFINED | |||
known_hosts: | |||
# The next 2 settings restrict the set of minions that will be added in | |||
# the generated ssh_known_hosts files (the default is to match all minions) | |||
target: '*' | |||
expr_form: 'glob' | |||
# Name of mining functions used to gather public keys and hostnames | |||
# (the default values are shown here) | |||
mine_keys_function: public_ssh_host_keys | |||
mine_hostname_function: public_ssh_hostname | |||
# List of DNS entries also pointing to our managed machines and that we want | |||
# to inject in our generated ssh_known_hosts file | |||
aliases: | |||
- cname-to-minion.example.org | |||
- alias.example.org | |||
# Required for openssh.known_hosts | |||
mine_functions: | |||
public_ssh_host_keys: | |||
mine_function: cmd.run | |||
cmd: cat /etc/ssh/ssh_host_*_key.pub | |||
public_ssh_hostname: | |||
mine_function: grains.get | |||
key: id |