Initial commit
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
new file mode 100644
index 0000000..ef0b741
--- /dev/null
+++ b/CHANGELOG.rst
@@ -0,0 +1,13 @@
+openssh formula
+===============
+
+0.0.2
+-----
+
+- Client proxy condition fix
+
+
+0.0.1
+-----
+
+- Initial commit to Community form
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8e80b12
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2014-2015 tcp cloud a. s.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..ba51d6b
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,84 @@
+=======
+OpenSSH
+=======
+
+OpenSSH is a FREE version of the SSH connectivity tools that technical users of the Internet rely on. Users of telnet, rlogin, and ftp may not realize that their password is transmitted across the Internet unencrypted, but it is. OpenSSH encrypts all traffic (including passwords) to effectively eliminate eavesdropping, connection hijacking, and other attacks. Additionally, OpenSSH provides secure tunneling capabilities and several authentication methods, and supports all SSH protocol versions. 
+
+Sample pillar
+=============
+
+OpenSSH client
+--------------
+
+OpenSSH client with shared private key
+
+.. code-block:: yaml
+
+    openssh:
+      client:
+        enabled: true
+        user:
+          root:
+            enabled: true
+            private_key: ${private_keys:vaio.newt.cz}
+            user: ${linux:system:user:root}
+
+OpenSSH client with individual private key and known host
+
+.. code-block:: yaml
+
+    openssh:
+      client:
+        enabled: true
+        user:
+          root:
+            enabled: true
+            user: ${linux:system:user:root}
+            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
+
+OpenSSH server
+--------------
+
+OpenSSH server with configuration parameters
+
+.. code-block:: yaml
+
+    openssh:
+      server:
+        enabled: true
+        permit_root_login: true
+        public_key_auth: true
+        password_auth: true
+        host_auth: true
+        banner: Welcome to server!
+
+OpenSSH server with auth keys for users
+
+.. code-block:: yaml
+
+    openssh:
+      server:
+        enabled: true
+        ...
+        user:
+          newt:
+            enabled: true
+            user: ${linux:system:user:newt}
+            public_keys:
+            - ${public_keys:newt}
+          root:
+            enabled: true
+            user: ${linux:system:user:root}
+            public_keys:
+            - ${public_keys:newt}
+
+Read more
+=========
+
+* http://www.openssh.org/manual.html
+* https://help.ubuntu.com/community/SSH/OpenSSH/Configuring
+* http://www.cyberciti.biz/tips/linux-unix-bsd-openssh-server-best-practices.html
+* http://www.zeitoun.net/articles/ssh-through-http-proxy/start
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..3b04cfb
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.2
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..719c12a
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,11 @@
+salt-formula-openssh (0.2) trusty; urgency=medium
+
+  * First public release
+
+ -- Filip Pytloun <filip.pytloun@tcpcloud.eu>  Tue, 06 Oct 2015 16:38:50 +0200
+
+salt-formula-openssh (0.1) trusty; urgency=medium
+
+  * Initial release
+
+ -- Ales Komarek <ales.komarek@tcpcloud.eu>  Thu, 13 Aug 2015 23:23:41 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..1d031d0
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,15 @@
+Source: salt-formula-openssh
+Maintainer: Ales Komarek <ales.komarek@tcpcloud.eu>
+Section: admin
+Priority: optional
+Build-Depends: debhelper (>= 9)
+Standards-Version: 3.9.6
+Homepage: http://www.tcpcloud.eu
+Vcs-Browser: https://github.com/tcpcloud/salt-formula-openssh
+Vcs-Git: https://github.com/tcpcloud/salt-formula-openssh.git
+
+Package: salt-formula-openssh
+Architecture: all
+Depends: ${misc:Depends}, salt-master, reclass
+Description: OpenSSH salt formula
+ Install and configure OpenSSH server and setup OpenSSH for system users.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..7ee2675
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,15 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: salt-formula-openssh
+Upstream-Contact: Ales Komarek <ales.komarek@tcpcloud.eu>
+Source: https://github.com/tcpcloud/salt-formula-openssh
+
+Files: *
+Copyright: 2014-2015 tcp cloud a.s.
+License: Apache-2.0
+  Copyright (C) 2014-2015 tcp cloud a.s.
+  .
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  .
+  On a Debian system you can find a copy of this license in
+  /usr/share/common-licenses/Apache-2.0.
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..d585829
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,3 @@
+README.rst
+CHANGELOG.rst
+VERSION
diff --git a/debian/install b/debian/install
new file mode 100644
index 0000000..97390e9
--- /dev/null
+++ b/debian/install
@@ -0,0 +1,2 @@
+openssh/*             /usr/share/salt-formulas/env/openssh/
+metadata/service/*      /usr/share/salt-formulas/reclass/service/openssh/
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..abde6ef
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,5 @@
+#!/usr/bin/make -f
+
+%:
+	dh $@
+
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/metadata/service/client/init.yml b/metadata/service/client/init.yml
new file mode 100644
index 0000000..58497f7
--- /dev/null
+++ b/metadata/service/client/init.yml
@@ -0,0 +1,10 @@
+applications:
+- openssh
+parameters:
+  openssh:
+    client:
+      enabled: true
+      user:
+        root:
+          enabled: true
+          user: ${linux:system:user:root}
diff --git a/metadata/service/server/init.yml b/metadata/service/server/init.yml
new file mode 100644
index 0000000..18ab826
--- /dev/null
+++ b/metadata/service/server/init.yml
@@ -0,0 +1,7 @@
+applications:
+- openssh
+parameters:
+  openssh:
+    server:
+      enabled: true
+      password_auth: false
diff --git a/openssh/client/init.sls b/openssh/client/init.sls
new file mode 100644
index 0000000..8d03493
--- /dev/null
+++ b/openssh/client/init.sls
@@ -0,0 +1,4 @@
+include:
+- openssh.client.service
+- openssh.client.private_key
+- openssh.client.known_host
\ No newline at end of file
diff --git a/openssh/client/known_host.sls b/openssh/client/known_host.sls
new file mode 100644
index 0000000..82f66a2
--- /dev/null
+++ b/openssh/client/known_host.sls
@@ -0,0 +1,25 @@
+{%- from "openssh/map.jinja" import client with context %}
+{%- if client.enabled %}
+
+include:
+- openssh.client.service
+
+{%- for user_name, user in client.user.iteritems() %}
+
+{%- for host in user.get('known_hosts', []) %}
+
+{{ user_name }}_known_hosts_{{ host.name }}:
+  ssh_known_hosts.present:
+  - user: {{ user_name }}
+  - name: {{ host.name }}
+  - enc: {{ host.get('type', 'ecdsa') }}
+  - fingerprint: {{ host.fingerprint }}
+  - require:
+    - pkg: openssh_client_packages
+    - file: {{ user.user.home }}/.ssh
+
+{%- endfor %}
+
+{%- endfor %}
+
+{%- endif %}
\ No newline at end of file
diff --git a/openssh/client/private_key.sls b/openssh/client/private_key.sls
new file mode 100644
index 0000000..508320f
--- /dev/null
+++ b/openssh/client/private_key.sls
@@ -0,0 +1,39 @@
+{%- from "openssh/map.jinja" import client with context %}
+{%- if client.enabled %}
+
+include:
+- openssh.client.service
+
+{%- for user_name, user in client.user.iteritems() %}
+
+{%- if user.private_key is defined %}
+
+{{ user.user.home }}/.ssh/id_{{ user.private_key.type }}:
+  file.managed:
+  - user: {{ user.user.name }}
+  - source: salt://openssh/files/private_key
+  - mode: 400
+  - template: jinja
+  - defaults:
+    user_name: {{ user.user.name }}
+  - require: 
+    - file: {{ user.user.home }}/.ssh
+
+{%- if user.public_key is defined %}
+{{ user.user.home }}/.ssh/id_{{ user.private_key.type }}.pub:
+  file.managed:
+  - user: {{ user.user.name }}
+  - source: salt://openssh/files/public_key
+  - mode: 400
+  - template: jinja
+  - defaults:
+    user_name: {{ user.user.name }}
+  - require: 
+    - file: {{ user.user.home }}/.ssh
+{%- endif %}
+
+{%- endif %}
+
+{%- endfor %}
+
+{%- endif %}
diff --git a/openssh/client/service.sls b/openssh/client/service.sls
new file mode 100644
index 0000000..b38d65f
--- /dev/null
+++ b/openssh/client/service.sls
@@ -0,0 +1,50 @@
+{%- from "openssh/map.jinja" import client with context %}
+{%- from "linux/map.jinja" import network with context %}
+{%- if client.enabled %}
+
+openssh_client_packages:
+  pkg.installed:
+  - names: {{ client.pkgs }}
+
+{%- if network.proxy.host != 'none' and not network.proxy.get("pkg_only", true) %}
+
+openssh_client_proxy_packages:
+  pkg.installed:
+  - names: {{ client.proxy_pkgs }}
+
+{%- endif %}
+
+openssh_client_config:
+  file.managed:
+  - name: {{ client.config }}
+  - user: root
+  - group: root
+  - source: salt://openssh/files/ssh_config
+  - mode: 600
+  - template: jinja
+  - require:
+    - pkg: openssh_client_packages
+
+{%- for user_name, user in client.user.iteritems() %}
+
+{{ user.user.home }}/.ssh:
+  file.directory:
+  - user: {{ user.user.name }}
+  - mode: 755
+  - makedirs: true
+  - require:
+    - pkg: openssh_client_packages
+
+openssh_client_{{ user_name }}_config:
+  file.managed:
+  - name: {{ user.user.home }}/.ssh/config
+  - user: {{ user.user.name }}
+  - source: salt://openssh/files/ssh_config
+  - mode: 600
+  - template: jinja
+  - require:
+    - pkg: openssh_client_packages
+
+{%- endfor %}
+
+{%- endif %}
diff --git a/openssh/files/banner b/openssh/files/banner
new file mode 100644
index 0000000..2172b6e
--- /dev/null
+++ b/openssh/files/banner
@@ -0,0 +1 @@
+{% from "openssh/map.jinja" import server with context %}{{ server.banner }}
\ No newline at end of file
diff --git a/openssh/files/private_key b/openssh/files/private_key
new file mode 100644
index 0000000..cbcb47f
--- /dev/null
+++ b/openssh/files/private_key
@@ -0,0 +1,3 @@
+{%- from "openssh/map.jinja" import client with context %}{%- for name, user in client.user.iteritems() %}{% if user.user.name == user_name %}{{ user.private_key.key }}
+{%- endif %}
+{%- endfor %}
\ No newline at end of file
diff --git a/openssh/files/public_key b/openssh/files/public_key
new file mode 100644
index 0000000..015e6fe
--- /dev/null
+++ b/openssh/files/public_key
@@ -0,0 +1,3 @@
+{%- from "openssh/map.jinja" import client with context %}{%- for name, user in client.user.iteritems() %}{% if user.user.name == user_name %}{{ user.public_key.key }}
+{%- endif %}
+{%- endfor %}
diff --git a/openssh/files/sensu.conf b/openssh/files/sensu.conf
new file mode 100644
index 0000000..73de6de
--- /dev/null
+++ b/openssh/files/sensu.conf
@@ -0,0 +1,6 @@
+local_openssh_server_proc:
+  command: "PATH=$PATH:/usr/lib64/nagios/plugins:/usr/lib/nagios/plugins check_procs -a '/usr/sbin/sshd' -u root -c 1:1"
+  interval: 60
+  occurrences: 1
+  subscribers:
+  - local-openssh-server
\ No newline at end of file
diff --git a/openssh/files/ssh_config b/openssh/files/ssh_config
new file mode 100644
index 0000000..b7d3229
--- /dev/null
+++ b/openssh/files/ssh_config
@@ -0,0 +1,14 @@
+{%- from "openssh/map.jinja" import client with context %}
+{%- from "linux/map.jinja" import network with context %}
+
+Host *
+
+    SendEnv LANG LC_*
+    HashKnownHosts yes
+    GSSAPIAuthentication {% if client.gssapi_authentication %}yes{% else %}no{% endif %}
+    GSSAPIDelegateCredentials no
+    ForwardAgent {% if client.forward_agent %}yes{% else %}no{% endif %}
+
+    {%- if network.proxy.host != 'none' and not network.proxy.get("pkg_only", true) %}
+    ProxyCommand connect -H {{ network.proxy.host }}:{{ network.proxy.port }} %h %p
+    {%- endif %}
diff --git a/openssh/files/sshd_config b/openssh/files/sshd_config
new file mode 100755
index 0000000..c3b8639
--- /dev/null
+++ b/openssh/files/sshd_config
@@ -0,0 +1,111 @@
+{%- from "openssh/map.jinja" import server with context %}
+
+# Package generated configuration file
+# See the sshd_config(5) manpage for details
+
+# What ports, IPs and protocols we listen for
+Port 22
+# Use these options to restrict which interfaces/protocols sshd will bind to
+#ListenAddress ::
+#ListenAddress 0.0.0.0
+Protocol 2
+# HostKeys for protocol version 2
+HostKey /etc/ssh/ssh_host_rsa_key
+HostKey /etc/ssh/ssh_host_dsa_key
+{%- if grains.os_family != 'CentOS' %}
+HostKey /etc/ssh/ssh_host_ecdsa_key
+{%- endif %}
+#Privilege Separation is turned on for security
+UsePrivilegeSeparation yes
+
+# Lifetime and size of ephemeral version 1 server key
+KeyRegenerationInterval 3600
+ServerKeyBits 768
+
+# Logging
+SyslogFacility AUTH
+LogLevel INFO
+
+# Authentication:
+LoginGraceTime 120
+
+PermitRootLogin {% if server.get('permit_root_login', False) %}yes{% else %}no{% endif %}
+
+StrictModes yes
+
+RSAAuthentication yes
+
+PubkeyAuthentication {% if server.get('public_key_auth', True) %}yes{% else %}no{% endif %}
+AuthorizedKeysFile     %h/.ssh/authorized_keys
+
+# Don't read the user's ~/.rhosts and ~/.shosts files
+IgnoreRhosts yes
+# For this to work you will also need host keys in /etc/ssh_known_hosts
+RhostsRSAAuthentication no
+# similar for protocol version 2
+
+HostbasedAuthentication {% if server.get('host_auth', False) %}yes{% else %}no{% endif %}
+
+# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
+#IgnoreUserKnownHosts yes
+
+# To enable empty passwords, change to yes (NOT RECOMMENDED)
+PermitEmptyPasswords no
+
+# Change to yes to enable challenge-response passwords (beware issues with
+# some PAM modules and threads)
+ChallengeResponseAuthentication no
+
+# Change to no to disable tunnelled clear text passwords
+PasswordAuthentication {% if server.get('password_auth', True) %}yes{% else %}no{% endif %}
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosGetAFSToken no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+
+X11Forwarding yes
+X11DisplayOffset 10
+PrintMotd no
+PrintLastLog yes
+TCPKeepAlive yes
+#UseLogin no
+
+{%- if server.max_sessions is defined %}
+MaxSessions {{ server.max_sessions }}
+{%- else %}
+MaxSessions 10
+{%- endif %}
+{%- if server.max_startups is defined %}
+MaxStartups {{ server.max_startups }}
+{%- else %}
+#MaxStartups 10:30:60
+{%- endif %}
+
+{%- if server.banner is defined %}
+Banner /etc/banner
+{%- else %}
+#Banner /etc/banner
+{%- endif %}
+
+# Allow client to pass locale environment variables
+AcceptEnv LANG LC_*
+
+Subsystem sftp {{ server.lib_dir }}/sftp-server
+
+# Set this to 'yes' to enable PAM authentication, account processing,
+# and session processing. If this is enabled, PAM authentication will
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication.  Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+UsePAM yes
+
diff --git a/openssh/init.sls b/openssh/init.sls
new file mode 100644
index 0000000..a18aa26
--- /dev/null
+++ b/openssh/init.sls
@@ -0,0 +1,8 @@
+
+include:
+{% if pillar.openssh.server is defined %}
+- openssh.server
+{% endif %}
+{% if pillar.openssh.client is defined %}
+- openssh.client
+{% endif %}
diff --git a/openssh/map.jinja b/openssh/map.jinja
new file mode 100644
index 0000000..2749ac5
--- /dev/null
+++ b/openssh/map.jinja
@@ -0,0 +1,61 @@
+{% set server = salt['grains.filter_by']({
+    'Arch': {
+        'pkgs': ['openssh'],
+        'service': 'sshd',
+        'config': '/etc/ssh/sshd_config',
+        'lib_dir': '/usr/lib/openssh',
+        'user': {},
+    },
+    'Debian': {
+        'pkgs': ['openssh-server'],
+        'service': 'ssh',
+        'config': '/etc/ssh/sshd_config',
+        'lib_dir': '/usr/lib/openssh',
+        'user': {},
+    },
+    'MacOS': {
+        'pkgs': ['openssh'],
+        'service': 'ssh',
+        'config': '/etc/sshd_config',
+        'lib_dir': '/usr/lib/openssh',
+        'user': {},
+    },
+    'RedHat': {
+        'pkgs': ['openssh'],
+        'service': 'sshd',
+        'config': '/etc/ssh/sshd_config',
+        'lib_dir': '/usr/libexec/openssh',
+        'user': {},
+    },
+}, merge=salt['pillar.get']('openssh:server')) %}
+
+{% set client = salt['grains.filter_by']({
+    'Arch': {
+        'pkgs': ['openssh'],
+        'proxy_pkgs': ['openssh'],
+        'config': '/etc/ssh/ssh_config',
+        'forward_agent': True,
+        'gssapi_authentication': False,
+    },
+    'Debian': {
+        'pkgs': ['openssh-client'],
+        'proxy_pkgs': ['connect-proxy'],
+        'config': '/etc/ssh/ssh_config',
+        'forward_agent': True,
+        'gssapi_authentication': False,
+    },
+    'MacOS': {
+        'pkgs': ['openssh'],
+        'proxy_pkgs': ['connect-proxy'],
+        'config': '/etc/ssh/ssh_config',
+        'forward_agent': True,
+        'gssapi_authentication': False,
+    },
+    'RedHat': {
+        'pkgs': ['openssh-clients'],
+        'proxy_pkgs': ['connect-proxy'],
+        'config': '/etc/ssh/ssh_config',
+        'forward_agent': True,
+        'gssapi_authentication': False,
+    },
+}, merge=salt['pillar.get']('openssh:client')) %}
diff --git a/openssh/server/init.sls b/openssh/server/init.sls
new file mode 100644
index 0000000..f365540
--- /dev/null
+++ b/openssh/server/init.sls
@@ -0,0 +1,3 @@
+include:
+- openssh.server.service
+- openssh.server.public_key
\ No newline at end of file
diff --git a/openssh/server/public_key.sls b/openssh/server/public_key.sls
new file mode 100644
index 0000000..293d015
--- /dev/null
+++ b/openssh/server/public_key.sls
@@ -0,0 +1,20 @@
+{%- from "openssh/map.jinja" import server with context %}
+{%- if server.enabled %}
+
+{%- for user_name, user in server.user.iteritems() %}
+
+{%- if user.public_keys is defined %}
+
+{{ user.user.name }}_auth_keys:
+  ssh_auth.present:
+  - user: {{ user.user.name }}
+  - names:
+    {%- for public_key in user.public_keys %}
+    - {{ public_key.key }}
+    {%- endfor %}
+
+{%- endif %}
+
+{%- endfor %}
+
+{%- endif %}
\ No newline at end of file
diff --git a/openssh/server/service.sls b/openssh/server/service.sls
new file mode 100644
index 0000000..fd83a54
--- /dev/null
+++ b/openssh/server/service.sls
@@ -0,0 +1,41 @@
+{%- from "openssh/map.jinja" import server with context %}
+{%- if server.enabled %}
+
+openssh_server_packages:
+  pkg.installed:
+  - names: {{ server.pkgs }}
+
+{%- if server.banner is defined %}
+
+/etc/banner:
+  file.managed:
+  - user: root
+  - group: root
+  - source: salt://openssh/files/banner
+  - mode: 644
+  - template: jinja
+  - require:
+    - pkg: openssh_server_packages
+  - watch_in:
+    - service: openssh_server_service
+
+{%- endif %}
+
+openssh_server_config:
+  file.managed:
+  - name: {{ server.config }}
+  - user: root
+  - group: root
+  - source: salt://openssh/files/sshd_config
+  - mode: 600
+  - template: jinja
+  - require:
+    - pkg: openssh_server_packages
+
+openssh_server_service:
+  service.running:
+  - name: {{ server.service }}
+  - watch:
+    - file: openssh_server_config
+
+{%- endif %}
\ No newline at end of file