Add all hosts to known_hosts automatically
- optimize known_hosts.present state
- add ability to define port
- remove undefined known_hosts if enabled
Related: PROD-25697
Change-Id: Idbaeac91d271693905b53eccf8f6249e7aa274e7
(cherry picked from commit 186b01fb589c04baa2b7eedf0532d1824dbab8f8)
diff --git a/README.rst b/README.rst
index c2d3a3b..35a80f2 100644
--- a/README.rst
+++ b/README.rst
@@ -48,6 +48,31 @@
fingerprint: dd:fa:e8:68:b1:ea:ea:a0:63:f1:5a:55:48:e1:7e:37
fingerprint_hash_type: sha256|md5
+* The OpenSSH client configuration with definition of known_hosts using
+public key instead of fingerprint
+
+ - If `purge_defined` is set to `true` it will remove old known_hosts file
+ and start with a fresh one causing that known_host undefined in the pillar
+ will not be included.
+
+ .. code-block:: yaml
+
+ openssh:
+ client:
+ enabled: true
+ user:
+ root:
+ enabled: true
+ purge_undefined: false
+ user:
+ name: 'root'
+ home: '/root'
+ known_hosts:
+ - name: 10.11.1.50
+ port: 22
+ type: ssh-rsa
+ host_public_key: AAA...fkP
+
* The OpenSSH client configuration with keep alive settings:
.. code-block:: yaml
diff --git a/openssh/client/known_host.sls b/openssh/client/known_host.sls
index 8cf4a95..664e138 100644
--- a/openssh/client/known_host.sls
+++ b/openssh/client/known_host.sls
@@ -6,17 +6,44 @@
{%- for xxx, user in client.get('user', {}).iteritems() %}
+{%- if user.get('purge_undefined', False) %}
+{{ user.user.name }}_remove_old_known_hosts_file:
+ cmd.run:
+ - name: "if [ -e {{ user.user.home }}/.ssh/known_hosts ]; then mv {{ user.user.home }}/.ssh/known_hosts {{ user.user.home }}/.ssh/known_hosts_$(date +%F_%H-%M-%S); fi"
+ - require:
+ - file: {{ user.user.home }}/.ssh
+
+{{ user.user.name }}_create_empty_known_hosts_file:
+ file.touch:
+ - name: {{ user.user.home }}/.ssh/known_hosts
+{%- endif %}
+
{%- for host in user.get('known_hosts', []) %}
-{{ user.user.name }}_known_hosts_{{ host.name }}:
+{%- if host.port is defined %}
+{{ user.user.name }}_known_hosts_{{ host.name }}_{{ host.port }}-{{ loop.index }}:
+{%- else %}
+{{ user.user.name }}_known_hosts_{{ host.name }}-{{ loop.index }}:
+{%- endif %}
ssh_known_hosts.present:
- user: {{ user.user.name }}
- name: {{ host.name }}
- enc: {{ host.get('type', 'ecdsa') }}
- {%- if host.fingerprint_hash_type is defined %}
- - fingerprint_hash_type: {{ host.fingerprint_hash_type }}
- {%- endif %}
+ {%- if host.fingerprint is defined %}
- fingerprint: {{ host.fingerprint }}
+ {%- if host.fingerprint_hash_type is defined %}
+ - fingerprint_hash_type: {{ host.fingerprint_hash_type }}
+ {%- endif %}
+ {%- endif %}
+ {%- if host.host_public_key is defined %}
+ - key: {{ host.host_public_key }}
+ {%- endif %}
+ {%- if host.port is defined %}
+ - port: {{ host.port }}
+ {%- endif %}
+ {%- if grains.get('noservices') %}
+ - onlyif: /bin/false
+ {%- endif %}
- require:
- pkg: openssh_client_packages
- file: {{ user.user.home }}/.ssh
diff --git a/openssh/map.jinja b/openssh/map.jinja
index 5cbda1d..0a0fc88 100644
--- a/openssh/map.jinja
+++ b/openssh/map.jinja
@@ -1,3 +1,26 @@
+{% if pillar.openssh.get('client', {}).get('enabled', False) %}
+{% set local_hosts = salt['pillar.get']('linux:network:host') %} {# Get all defined hosts #}
+{% set root_public_key = salt['pillar.get']('_param:root_public_key')|replace('ssh-rsa', '') %} {# Get root's public key #}
+{% set root = salt['pillar.get'](key='openssh:client:user:root', default={}) %} {# Get predefined root user pillar data if there are any #}
+{% if root.known_hosts is not defined %}
+ {% do root.update({'known_hosts': []}) %} {# Prepare empty list if missing so it can be appended later #}
+{% endif %}
+{% for host_name, host in local_hosts.iteritems() %} {# Iterate through all defined hosts #}
+ {% if host.address is defined %}
+ {% set new_host = {'name': host.address, 'host_public_key': root_public_key, 'type': 'ssh-rsa'} %}
+ {% do root['known_hosts'].append(new_host) %} {# Add the host to the list of known hosts #}
+ {% endif %}
+ {% for hostname in host.get('names', []) %} {# Do the same again, but this time with all hostnames instead of IP addresses #}
+ {% set new_host = {'name': hostname, 'host_public_key': root_public_key, 'type': 'ssh-rsa'} %}
+ {% do root['known_hosts'].append(new_host) %}
+ {% endfor %}
+{% endfor %}
+{% if root['user'] is not defined %}
+ {% do root.update({'user': {}}) %}
+ {% do root['user'].update({'name': 'root', 'home': '/root'}) %} {# If remaining required data is not configured yet, do it now. #}
+{% endif %}
+{% endif %}
+
{% set server = salt['grains.filter_by']({
'Arch': {
'pkgs': ['openssh'],
@@ -47,6 +70,9 @@
'pkgs': ['openssh-client'],
'proxy_pkgs': ['connect-proxy'],
'config': '/etc/ssh/ssh_config',
+ 'user': {
+ 'root': root,
+ }
},
'MacOS': {
'pkgs': ['openssh'],
diff --git a/openssh/schemas/client.yaml b/openssh/schemas/client.yaml
index 3000b68..55655df 100644
--- a/openssh/schemas/client.yaml
+++ b/openssh/schemas/client.yaml
@@ -81,6 +81,9 @@
description: Define user private_key type
type: string
example: "rsa"
+ purge_undefined:
+ description: Defines if the known_hosts file should be removed before adding defined keys
+ type: boolean
user:
description: Define user login data. In scope of openssh - uses only to acquire user homepath
additionalProperties: false
@@ -103,6 +106,12 @@
fingerprint:
type: string
example: dd:fa:e8:68:b1:ea:ea:a0:63:f1:5a:55:48:e1:7e:37
+ port:
+ type: integer
+ example: 22
+ host_public_key:
+ type: string
+ example: AAAAB3NzaXXXXAAAXXXX
_global_useradd_user:
description: Define exactly one linux user login data.
diff --git a/tests/pillar/client.sls b/tests/pillar/client.sls
index bf746d9..b124cc3 100644
--- a/tests/pillar/client.sls
+++ b/tests/pillar/client.sls
@@ -9,6 +9,32 @@
uid: 9999
full_name: Test User
home: /home/testusername
+ network:
+ host:
+ cfg:
+ address:
+ 10.11.0.15
+ names:
+ - cfg
+ - cfg.example.com
+ ctl01:
+ address:
+ 10.11.0.11
+ names:
+ - ctl01
+ - ctl01.example.com
+ ctl02:
+ address:
+ 10.11.0.12
+ names:
+ - ctl02
+ - ctl02.example.com
+ ctl03:
+ address:
+ 10.11.0.13
+ names:
+ - ctl03
+ - ctl03.example.com
openssh:
client:
enabled: true
@@ -17,11 +43,12 @@
enabled: true
# Include from linux.system.user structure
user: *_user
- known_hosts:
- - name: repo.domain.com
- type: rsa
- fingerprint: dd:fa:e8:68:b1:ea:ea:a0:63:f1:5a:55:48:e1:7e:37
- alive:
- interval: 600
- count: 3
-
+ purge_undefined: true
+ known_hosts:
+ - name: localhost
+ type: rsa
+ fingerprint: dd:fa:e8:68:b1:ea:ea:a0:63:f1:5a:55:48:e1:7e:37
+ - name: 127.0.0.1
+ port: 22
+ type: ssh-rsa
+ host_public_key: AAA...fkP