This state manages /etc/ssh/ssh_known_hosts and fills it with public SSH host keys of other minions.master
by values from pillar. ``pillar.example`` results in the generation | by values from pillar. ``pillar.example`` results in the generation | ||||
of the default ``sshd_config`` file on Debian Wheezy. | 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. |
{%- 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 -%} |
{% 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 |
'sshd_config_src': 'salt://openssh/files/sshd_config', | 'sshd_config_src': 'salt://openssh/files/sshd_config', | ||||
'banner': '/etc/ssh/banner', | 'banner': '/etc/ssh/banner', | ||||
'banner_src': 'salt://openssh/files/banner', | 'banner_src': 'salt://openssh/files/banner', | ||||
'dig_pkg': 'dnsutils', | |||||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||||
}, | }, | ||||
'Debian': { | 'Debian': { | ||||
'server': 'openssh-server', | 'server': 'openssh-server', | ||||
'sshd_config_src': 'salt://openssh/files/sshd_config', | 'sshd_config_src': 'salt://openssh/files/sshd_config', | ||||
'banner': '/etc/ssh/banner', | 'banner': '/etc/ssh/banner', | ||||
'banner_src': 'salt://openssh/files/banner', | 'banner_src': 'salt://openssh/files/banner', | ||||
'dig_pkg': 'dnsutils', | |||||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||||
}, | }, | ||||
'FreeBSD': { | 'FreeBSD': { | ||||
'service': 'sshd', | 'service': 'sshd', | ||||
'sshd_config_src': 'salt://openssh/files/sshd_config', | 'sshd_config_src': 'salt://openssh/files/sshd_config', | ||||
'banner': '/etc/ssh/banner', | 'banner': '/etc/ssh/banner', | ||||
'banner_src': 'salt://openssh/files/banner', | 'banner_src': 'salt://openssh/files/banner', | ||||
'dig_pkg': 'bind-tools', | |||||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||||
}, | }, | ||||
'Gentoo': { | 'Gentoo': { | ||||
'server': 'net-misc/openssh', | 'server': 'net-misc/openssh', | ||||
'sshd_config_src': 'salt://openssh/files/sshd_config', | 'sshd_config_src': 'salt://openssh/files/sshd_config', | ||||
'banner': '/etc/ssh/banner', | 'banner': '/etc/ssh/banner', | ||||
'banner_src': 'salt://openssh/files/banner', | 'banner_src': 'salt://openssh/files/banner', | ||||
'dig_pkg': 'net-dns/bind-tools', | |||||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||||
}, | }, | ||||
'RedHat': { | 'RedHat': { | ||||
'server': 'openssh-server', | 'server': 'openssh-server', | ||||
'sshd_config_src': 'salt://openssh/files/sshd_config', | 'sshd_config_src': 'salt://openssh/files/sshd_config', | ||||
'banner': '/etc/ssh/banner', | 'banner': '/etc/ssh/banner', | ||||
'banner_src': 'salt://openssh/files/banner', | 'banner_src': 'salt://openssh/files/banner', | ||||
'dig_pkg': 'bind-utils', | |||||
'ssh_known_hosts': '/etc/ssh/ssh_known_hosts', | |||||
}, | }, | ||||
'Suse': { | 'Suse': { | ||||
'server': 'openssh', | 'server': 'openssh', | ||||
'sshd_config_src': 'salt://openssh/files/sshd_config', | 'sshd_config_src': 'salt://openssh/files/sshd_config', | ||||
'banner': '/etc/ssh/banner', | 'banner': '/etc/ssh/banner', | ||||
'banner_src': 'salt://openssh/files/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')) %} | }, merge=salt['pillar.get']('openssh:lookup')) %} |
-----END OPENSSH PRIVATE KEY----- | -----END OPENSSH PRIVATE KEY----- | ||||
public_key: | | public_key: | | ||||
ssh-ed25519 NOT_DEFINED | 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 |