diff --git a/openssh/auth.sls b/openssh/auth.sls index 2bf04a8..7fb6b4b 100644 --- a/openssh/auth.sls +++ b/openssh/auth.sls @@ -32,7 +32,7 @@ include: {%- from "openssh/map.jinja" import openssh with context -%} {%- set openssh_pillar = pillar.get('openssh', {}) -%} {%- set auth = openssh_pillar.get('auth', {}) -%} -{%- for identifier,keys in auth.iteritems() -%} +{%- for identifier,keys in auth.items() -%} {%- for key in keys -%} {% if 'present' in key and key['present'] %} {{ print_name(identifier, key) }}: diff --git a/openssh/defaults.yaml b/openssh/defaults.yaml index 6e9d837..c58bf08 100644 --- a/openssh/defaults.yaml +++ b/openssh/defaults.yaml @@ -8,3 +8,12 @@ openssh: ssh_known_hosts: /etc/ssh/ssh_known_hosts dig_pkg: dnsutils ssh_moduli: /etc/ssh/moduli + root_group: root +sshd_config: {} +ssh_config: + Hosts: + '*': + SendEnv: LANG LC_* + HashKnownHosts: yes + GSSAPIAuthentication: yes + GSSAPIDelegateCredentials: no diff --git a/openssh/files/ssh_config b/openssh/files/ssh_config index 46f0506..4bd2146 100644 --- a/openssh/files/ssh_config +++ b/openssh/files/ssh_config @@ -1,11 +1,9 @@ -{%- set ssh_config = pillar.get('ssh_config', {}) -%} +{%- import_yaml "openssh/defaults.yaml" as default_settings -%} +{%- set ssh_config = salt['pillar.get']('ssh_config', default=default_settings.ssh_config, merge=True) -%} {#- present in ssh_config and known in actual file options -#} {%- set processed_options = [] -%} -{#- generic renderer used for ssh matches, known options, -#} -{#- and unknown options -#} -{%- macro render_option(keyword, default, config_dict=ssh_config) -%} - {%- set value = config_dict.get(keyword, default) -%} +{%- macro render_raw_option(keyword, value) -%} {%- if value is sameas true -%} {{ keyword }} yes {%- elif value is sameas false -%} @@ -19,6 +17,13 @@ {%- endif -%} {%- endmacro -%} +{#- generic renderer used for ssh matches, known options, -#} +{#- and unknown options -#} +{%- macro render_option(keyword, default, config_dict=ssh_config) -%} + {%- set value = config_dict.get(keyword, default) -%} +{{ render_raw_option(keyword, value) }} +{%- endmacro -%} + {#- macros for render option according to present -#} {%- macro option_impl(keyword, default, present) -%} {%- if present -%} @@ -45,28 +50,15 @@ # Do not edit this file manually! # It will be overwritten by salt! -{{ option_default_uncommented('Host', '*') }} -{{ option(' ForwardAgent', 'no') }} -{{ option(' ForwardX11', 'no') }} -{{ option(' RhostsRSAAuthentication', 'no') }} -{{ option(' RSAAuthentication', 'yes') }} -{{ option(' PasswordAuthentication', 'yes') }} -{{ option(' HostbasedAuthentication', 'no') }} -{{ option(' GSSAPIAuthentication', 'no') }} -{{ option(' GSSAPIDelegateCredentials', 'no') }} -{{ option(' BatchMode', 'no') }} -{{ option(' CheckHostIP', 'yes') }} -{{ option(' AddressFamily', 'any') }} -{{ option(' ConnectTimeout', 0) }} -{{ option(' StrictHostKeyChecking', 'ask') }} -{{ option(' IdentityFile', '~/.ssh/id_rsa') }} -{{ option(' Port', 22) }} -{{ option(' Protocol', 2) }} -{{ option(' Cipher', '3des') }} -{{ option(' Tunnel', 'no') }} -{{ option(' TunnelDevice', 'any:any') }} -{{ option(' PermitLocalCommand', 'no') }} -{{ option(' VisualHostKey', 'no') }} +{%- if 'Hosts' in ssh_config %} +{%- do processed_options.append('Hosts') %} +{% for host, conf in ssh_config['Hosts'].items() %} +Host {{ host }} + {%- for key, val in conf.items() %} + {{ render_raw_option(key, val) }} + {%- endfor %} +{%- endfor %} +{%- endif %} {# Handling unknown in salt template options #} {%- for keyword in ssh_config.keys() %} diff --git a/openssh/files/sshd_config b/openssh/files/sshd_config index 286200b..471e031 100644 --- a/openssh/files/sshd_config +++ b/openssh/files/sshd_config @@ -1,4 +1,4 @@ -{%- set sshd_config = pillar.get('sshd_config', {}) -%} +{% from "openssh/map.jinja" import sshd_config with context %} {#- present in sshd_config and known in actual file options -#} {%- set processed_options = [] -%} @@ -66,10 +66,16 @@ {{ option_default_uncommented('SyslogFacility', 'AUTH') }} {{ option_default_uncommented('LogLevel', 'INFO') }} +# Session idle time out +{{ option_default_uncommented('ClientAliveInterval', 0) }} +{{ option_default_uncommented('ClientAliveCountMax', 3) }} + # Authentication: {{ option_default_uncommented('LoginGraceTime', 120) }} {{ option_default_uncommented('PermitRootLogin', 'yes') }} {{ option_default_uncommented('StrictModes', 'yes') }} +{{ option_default_uncommented('MaxAuthTries', '6') }} +{{ option_default_uncommented('MaxSessions', '10') }} {{ option('DSAAuthentication', 'yes') }} {{ option_default_uncommented('RSAAuthentication', 'yes') }} diff --git a/openssh/known_hosts.sls b/openssh/known_hosts.sls index 8f8d2a8..9541e55 100644 --- a/openssh/known_hosts.sls +++ b/openssh/known_hosts.sls @@ -3,6 +3,7 @@ ensure dig is available: pkg.installed: - name: {{ openssh.dig_pkg }} + - unless: which dig manage ssh_known_hosts file: file.managed: @@ -10,7 +11,7 @@ manage ssh_known_hosts file: - source: salt://openssh/files/ssh_known_hosts - template: jinja - user: root - - group: root + - group: {{ openssh.root_group }} - mode: 644 - require: - pkg: ensure dig is available diff --git a/openssh/map.jinja b/openssh/map.jinja index 639b81d..908b645 100644 --- a/openssh/map.jinja +++ b/openssh/map.jinja @@ -10,6 +10,7 @@ that differ from whats in defaults.yaml 'server': 'openssh', 'client': 'openssh', 'service': 'sshd', + 'dig_pkg': 'bind-utils', }, 'Debian': { 'server': 'openssh-server', @@ -19,6 +20,11 @@ that differ from whats in defaults.yaml 'FreeBSD': { 'service': 'sshd', 'dig_pkg': 'bind-tools', + 'root_group': 'wheel', + }, + 'OpenBSD': { + 'service': 'sshd', + 'root_group': 'wheel', }, 'Gentoo': { 'server': 'net-misc/openssh', @@ -28,7 +34,7 @@ that differ from whats in defaults.yaml }, 'RedHat': { 'server': 'openssh-server', - 'client': 'openssh', + 'client': 'openssh-clients', 'service': 'sshd', 'dig_pkg': 'bind-utils', }, @@ -54,3 +60,30 @@ that differ from whats in defaults.yaml ) %} +{% set os_family_map = salt['grains.filter_by']({ + 'FreeBSD': { + 'Subsystem': 'sftp /usr/libexec/sftp-server', + }, + 'OpenBSD': { + 'Subsystem': 'sftp /usr/libexec/sftp-server', + }, + 'Suse': { + 'Subsystem': 'sftp /usr/lib/ssh/sftp-server', + }, + 'default': {} + } + , grain="os_family" + , merge=salt['pillar.get']('sshd_config:lookup')) +%} + + +{## Merge the flavor_map to the default settings ##} +{% do default_settings.sshd_config.update(os_family_map) %} + +{## Merge in sshd_config:lookup pillar ##} +{% set sshd_config = salt['pillar.get']( + 'sshd_config', + default=default_settings.sshd_config, + merge=True + ) +%} diff --git a/openssh/moduli.sls b/openssh/moduli.sls index d871006..7e0bd3a 100644 --- a/openssh/moduli.sls +++ b/openssh/moduli.sls @@ -1,8 +1,19 @@ {% from "openssh/map.jinja" import openssh with context %} -{% if salt['pillar.get']('openssh:moduli', False) %} +{% set moduli = salt['pillar.get']('openssh:moduli', False) -%} +{% set moduli_source = salt['pillar.get']('openssh:moduli_source', False) -%} +{% if moduli or moduli_source -%} ssh_moduli: file.managed: - name: {{ openssh.ssh_moduli }} + {% if moduli -%} + # Although we have the contents of the moduli in the variable 'moduli', + # inlining the variable here *will* cause problems. Using the '|' literal string indicator + # Necessitates using the '|indent' filter, and this is too complex. + # Rather, let salt read the pillar itself. - contents_pillar: openssh:moduli + {% elif moduli_source -%} + - source: {{ moduli_source }} + - source_hash: {{ moduli_source|trim }}.hash + {%- endif %} {% endif %} diff --git a/pillar.example b/pillar.example index 6baf78d..0af3574 100644 --- a/pillar.example +++ b/pillar.example @@ -11,10 +11,14 @@ sshd_config: ServerKeyBits: 768 SyslogFacility: AUTH LogLevel: INFO + ClientAliveInterval: 0 + ClientAliveCountMax: 3 LoginGraceTime: 120 PermitRootLogin: 'yes' PasswordAuthentication: 'no' StrictModes: 'yes' + MaxAuthTries: 6 + MaxSessions: 10 RSAAuthentication: 'yes' PubkeyAuthentication: 'yes' IgnoreRhosts: 'yes' @@ -155,13 +159,21 @@ openssh: - cname-to-minion.example.org - alias.example.org -# specify DH parameters (see /etc/ssh/moduli) + # specify DH parameters (see /etc/ssh/moduli) moduli: | # Time Type Tests Tries Size Generator Modulus 20120821045639 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C604293680B09D63 20120821045830 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C6042936814C2FFB 20120821050046 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C60429368214FC53 20120821050054 2 6 100 2047 5 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E58281FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA45C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231BBE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116B8119892C60429368218E83F + # ALTERNATIVELY, specify the location of the moduli file. Examples: + #moduli_source: http://some.server.somewhere/salt/moduli + #moduli_source: salt://files/ssh/moduli + # If moduli is specified, moduli_source will be ignored. + # Also, a proper hash file *must* be included in the same path. E.g.: + # http://some.server.somewhere/salt/moduli.hash + # salt://files/ssh/moduli.hash + # These will be automatically referenced to by the ssh_moduli state. # Required for openssh.known_hosts mine_functions: