WIP - v4 - rewrite to be feature complete
diff --git a/.fixtures-puppetv3.yml b/.fixtures-puppetv3.yml
deleted file mode 100644
index e8a1576..0000000
--- a/.fixtures-puppetv3.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-fixtures:
-  repositories:
-    stdlib:
-      repo: 'https://github.com/puppetlabs/puppetlabs-stdlib.git'
-      ref: '4.6.0'
-    concat:
-      repo: 'https://github.com/puppetlabs/puppetlabs-concat.git'
-      ref: '2.2.1'
-    common:
-      repo: 'https://github.com/ghoneycutt/puppet-module-common.git'
-      ref: 'v1.4.1'
-    firewall:
-      repo: 'https://github.com/puppetlabs/puppetlabs-firewall.git'
-      ref: '1.9.0'
-  symlinks:
-    ssh: "#{source_dir}"
diff --git a/.fixtures.yml b/.fixtures.yml
index 91a33d7..d0917ee 100644
--- a/.fixtures.yml
+++ b/.fixtures.yml
@@ -2,18 +2,11 @@
   repositories:
     stdlib:
       repo: 'https://github.com/puppetlabs/puppetlabs-stdlib.git'
-      ref: '4.6.0'
+      ref: '5.2.0'
     concat:
       repo: 'https://github.com/puppetlabs/puppetlabs-concat.git'
-      ref: '2.2.1'
-    common:
-      repo: 'https://github.com/ghoneycutt/puppet-module-common.git'
-      ref: 'v1.4.1'
-    firewall:
-      repo: 'https://github.com/puppetlabs/puppetlabs-firewall.git'
-      ref: '1.9.0'
+      ref: '5.2.0'
     sshkeys:
-      repo: 'git://github.com/puppetlabs/puppetlabs-sshkeys_core.git'
-      ref: '1.0.1'
-  symlinks:
-    ssh: "#{source_dir}"
+      repo: 'https://github.com/puppetlabs/puppetlabs-sshkeys_core.git'
+      ref: '1.0.2'
+      puppet_version: '>= 6.0.0'
diff --git a/.gitignore b/.gitignore
index 29471a6..178b162 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@
 test/tmp
 test/version_tmp
 tmp
+Gemfile.lock
 
 # YARD artifacts
 .yardoc
@@ -31,7 +32,10 @@
 coverage/
 spec/fixtures/manifests/*
 spec/fixtures/modules/*
-Gemfile.lock
+log/
+
+# Vagrant
+.vagrant/*
 
 # JetBrains IDE
 .idea/
diff --git a/.puppet-lint.rc b/.puppet-lint.rc
new file mode 100644
index 0000000..f7e6028
--- /dev/null
+++ b/.puppet-lint.rc
@@ -0,0 +1,3 @@
+--no-relative
+--no-80chars-check
+--no-140chars-check
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..bab9844
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,151 @@
+---
+require: rubocop-rspec
+AllCops:
+  DisplayCopNames: true
+  TargetRubyVersion: '2.1'
+  Include:
+  - "./**/*.rb"
+  Exclude:
+  - bin/*
+  - ".vendor/**/*"
+  - "**/Gemfile"
+  - "**/Rakefile"
+  - pkg/**/*
+  - spec/fixtures/**/*
+  - vendor/**/*
+  - "**/Puppetfile"
+  - "**/Vagrantfile"
+  - "**/Guardfile"
+Metrics/LineLength:
+  Description: People have wide screens, use them.
+  Max: 200
+GetText/DecorateString:
+  Description: We don't want to decorate test output.
+  Exclude:
+  - spec/*
+RSpec/BeforeAfterAll:
+  Description: Beware of using after(:all) as it may cause state to leak between tests.
+    A necessary evil in acceptance testing.
+  Exclude:
+  - spec/acceptance/**/*.rb
+RSpec/HookArgument:
+  Description: Prefer explicit :each argument, matching existing module's style
+  EnforcedStyle: each
+  Enabled: false
+Style/BlockDelimiters:
+  Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to
+    be consistent then.
+  EnforcedStyle: braces_for_chaining
+Style/ClassAndModuleChildren:
+  Description: Compact style reduces the required amount of indentation.
+  EnforcedStyle: compact
+Style/EmptyElse:
+  Description: Enforce against empty else clauses, but allow `nil` for clarity.
+  EnforcedStyle: empty
+Style/FormatString:
+  Description: Following the main puppet project's style, prefer the % format format.
+  EnforcedStyle: percent
+Style/FormatStringToken:
+  Description: Following the main puppet project's style, prefer the simpler template
+    tokens over annotated ones.
+  EnforcedStyle: template
+Style/Lambda:
+  Description: Prefer the keyword for easier discoverability.
+  EnforcedStyle: literal
+Style/RegexpLiteral:
+  Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168
+  EnforcedStyle: percent_r
+  Enabled: false
+Style/TernaryParentheses:
+  Description: Checks for use of parentheses around ternary conditions. Enforce parentheses
+    on complex expressions for better readability, but seriously consider breaking
+    it up.
+  EnforcedStyle: require_parentheses_when_complex
+Style/TrailingCommaInArguments:
+  Description: Prefer always trailing comma on multiline argument lists. This makes
+    diffs, and re-ordering nicer.
+  EnforcedStyleForMultiline: comma
+Style/TrailingCommaInLiteral:
+  Description: Prefer always trailing comma on multiline literals. This makes diffs,
+    and re-ordering nicer.
+  EnforcedStyleForMultiline: comma
+  Enabled: false
+Style/SymbolArray:
+  Description: Using percent style obscures symbolic intent of array's contents.
+  EnforcedStyle: brackets
+Layout/AlignHash:
+  Enabled: false
+Layout/IndentationConsistency:
+  Enabled: false
+Layout/IndentHash:
+  Enabled: false
+Layout/SpaceAfterNot:
+  Enabled: false
+Layout/SpaceInsideParens:
+  Enabled: false
+RSpec/EmptyLineAfterFinalLet:
+  Enabled: false
+RSpec/ExampleWording:
+  Enabled: false
+RSpec/ImplicitExpect:
+  Enabled: false
+RSpec/NamedSubject:
+  Enabled: false
+Style/AndOr:
+  Enabled: false
+Style/BracesAroundHashParameters:
+  Enabled: false
+Style/HashSyntax:
+  Enabled: false
+Style/NegatedIf:
+  Enabled: false
+RSpec/MessageSpies:
+  EnforcedStyle: receive
+Style/Documentation:
+  Exclude:
+  - lib/puppet/parser/functions/**/*
+  - spec/**/*
+Style/WordArray:
+  EnforcedStyle: brackets
+Style/CollectionMethods:
+  Enabled: true
+Style/MethodCalledOnDoEndBlock:
+  Enabled: true
+Style/StringMethods:
+  Enabled: true
+Layout/EndOfLine:
+  Enabled: false
+Layout/IndentHeredoc:
+  Enabled: false
+Metrics/AbcSize:
+  Enabled: false
+Metrics/BlockLength:
+  Enabled: false
+Metrics/ClassLength:
+  Enabled: false
+Metrics/CyclomaticComplexity:
+  Enabled: false
+Metrics/MethodLength:
+  Enabled: false
+Metrics/ModuleLength:
+  Enabled: false
+Metrics/ParameterLists:
+  Enabled: false
+Metrics/PerceivedComplexity:
+  Enabled: false
+RSpec/DescribeClass:
+  Enabled: false
+RSpec/ExampleLength:
+  Enabled: false
+RSpec/MessageExpectation:
+  Enabled: false
+RSpec/MultipleExpectations:
+  Enabled: false
+RSpec/NestedGroups:
+  Enabled: false
+Style/AsciiComments:
+  Enabled: false
+Style/IfUnlessModifier:
+  Enabled: false
+Style/SymbolProc:
+  Enabled: false
diff --git a/.travis.yml b/.travis.yml
index 0650a11..bf14b20 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,29 +15,39 @@
 
 sudo: false
 
-script: 'SPEC_OPTS="--format documentation" bundle exec rake validate lint spec'
+script: 'SPEC_OPTS="--format documentation" bundle exec rake validate lint strings:generate reference spec'
 
 matrix:
   fast_finish: true
   include:
-  - rvm: 1.9.3
-    env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3
-  - rvm: 1.9.3
-    env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3
-  - rvm: 2.0.0
-    env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3
-  - rvm: 2.0.0
-    env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3
-  - rvm: 2.1.9
-    env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3
-  - rvm: 2.1.9
-    env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3
-  - rvm: 2.1.9
-    env: PUPPET_GEM_VERSION="~> 4" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3
-  - rvm: 2.4.1
+  - rvm: 2.4.4
     env: PUPPET_GEM_VERSION="~> 5"
-  - rvm: 2.5.1
+  - rvm: 2.5.3
     env: PUPPET_GEM_VERSION="~> 6"
+  - rvm: 2.4.4
+    sudo: required
+    services: docker
+    env: BEAKER_set="centos-6" BEAKER_PUPPET_COLLECTION=puppet5
+    bundler_args:
+    script: bundle exec rake beaker
+  - rvm: 2.5.3
+    sudo: required
+    services: docker
+    env: BEAKER_set="centos-6" BEAKER_PUPPET_COLLECTION=puppet6
+    bundler_args:
+    script: bundle exec rake beaker
+  - rvm: 2.4.4
+    sudo: required
+    services: docker
+    env: BEAKER_set="centos-7" BEAKER_PUPPET_COLLECTION=puppet5
+    bundler_args:
+    script: bundle exec rake beaker
+  - rvm: 2.5.3
+    sudo: required
+    services: docker
+    env: BEAKER_set="centos-7" BEAKER_PUPPET_COLLECTION=puppet6
+    bundler_args:
+    script: bundle exec rake beaker
 
 notifications:
   email: false
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..be75c27
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,55 @@
+# Contribution Guidelines
+
+## Tests
+
+  - Pull requests that add any additional functionality should have
+    tests which cover the new feature to ensure it does what is
+expected.
+
+  - All platforms must have spec tests.
+
+  - Only supported platforms will run functional tests with Beaker and
+      Vagrant. Once a platform is end of life (EOL), it will no longer
+      be supported and functional tests will be removed, though spec
+      tests will remain.
+
+  - Pull requests with failing tests will not be merged.
+
+## Features
+
+  - Keep feature based PRs as small as possible, with as few commits as
+    necessary. These are easier to review and will be merged quicker.
+
+## Bug Fixes
+
+  - Make sure you reference the issue you're closing with `Fixes #<issue
+    number>`.
+
+## Commits
+
+  - Squash/rebase any commits where possible to reduce the noise in the PR
+
+## Git commits
+
+Reference the issue number, in the format `(GH-###)`.
+
+```
+(GH-901) Add support for foo
+```
+
+# Release process
+
+1. update version in `metadata.json`
+1. run `github_changelog_generator`
+1. update `CHANGELOG.md` and change `unreleased` at the top to the
+   version, such as `v2.0.0`, and change `HEAD` to the same version,
+   such as `v2.0.0`.
+1. Update `REFERENCE.md` with the command `bundle exec rake reference`
+1. Commit changes and push to master
+1. Tag the new version, such as `git tag -a 'v2.0.0' -m 'v2.0.0'`
+1. Push tags `git push --tags`
+1. Update the puppet strings documentation with `bundle exec rake strings:gh_pages:update`
+1. Clean up tests with `bundle exec rake spec_clean`
+1. Remove junit directory from beaker runs `rm -fr junit`
+1. Build module with `puppet module build`
+1. Upload module to Puppet Forge.
diff --git a/Gemfile b/Gemfile
index f8bdb02..0f45b5c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -6,33 +6,35 @@
   gem 'puppet', :require => false
 end
 
-gem 'facter', '>= 1.7.0', :require => false
-gem 'rspec-puppet', '>= 2.4.0', :require => false
-gem 'puppet-lint', '~> 2.0', :require => false
-gem 'puppet-lint-absolute_classname-check', :require => false
-gem 'puppet-lint-alias-check', :require => false
-gem 'puppet-lint-empty_string-check', :require => false
-gem 'puppet-lint-file_ensure-check', :require => false
-gem 'puppet-lint-file_source_rights-check', :require => false
-gem 'puppet-lint-leading_zero-check', :require => false
+gem 'rake'
+gem 'metadata-json-lint',                               :require => false
+gem 'puppetlabs_spec_helper',                           :require => false
+gem 'rspec-puppet',                                     :require => false
+gem 'puppet-lint',                                      :require => false
+gem 'puppet-lint-absolute_classname-check',             :require => false
+gem 'puppet-lint-alias-check',                          :require => false
+gem 'puppet-lint-empty_string-check',                   :require => false
+gem 'puppet-lint-file_ensure-check',                    :require => false
+gem 'puppet-lint-file_source_rights-check',             :require => false
+gem 'puppet-lint-leading_zero-check',                   :require => false
 gem 'puppet-lint-spaceship_operator_without_tag-check', :require => false
-gem 'puppet-lint-trailing_comma-check', :require => false
-gem 'puppet-lint-undef_in_function-check', :require => false
-gem 'puppet-lint-unquoted_string-check', :require => false
-gem 'puppet-lint-variable_contains_upcase', :require => false
+gem 'puppet-lint-trailing_comma-check',                 :require => false
+gem 'puppet-lint-undef_in_function-check',              :require => false
+gem 'puppet-lint-unquoted_string-check',                :require => false
+gem 'puppet-lint-variable_contains_upcase',             :require => false
 
-gem 'rspec',     '~> 2.0', :require => false          if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9'
-gem 'rake',      '~> 10.0', :require => false         if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9'
-gem 'json',      '<= 1.8', :require => false          if RUBY_VERSION < '2.0.0'
-gem 'json_pure', '<= 2.0.1', :require => false        if RUBY_VERSION < '2.0.0'
-gem 'metadata-json-lint',     '0.0.11'   if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9'
-gem 'metadata-json-lint',     '1.0.0'    if RUBY_VERSION >= '1.9' && RUBY_VERSION < '2.0'
-gem 'metadata-json-lint' if RUBY_VERSION >= '2.0'
+group :documentation do
+  gem 'puppet-strings', require: false
+  gem 'redcarpet',      require: false
+  gem 'yard',           require: false
+end
 
-gem 'puppetlabs_spec_helper', '2.0.2',    :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9'
-gem 'puppetlabs_spec_helper', '>= 2.0.0', :require => false if RUBY_VERSION >= '1.9'
-gem 'parallel_tests',         '<= 2.9.0', :require => false if RUBY_VERSION < '2.0.0'
-
-if puppetversion && puppetversion < '5.0'
-  gem 'semantic_puppet', :require => false
+group :system_tests do
+  gem 'beaker',                       :require => false
+  gem 'beaker-docker',                :require => false
+  gem 'beaker-module_install_helper', :require => false
+  gem 'beaker-puppet',                :require => false
+  gem 'beaker-puppet_install_helper', :require => false
+  gem 'beaker-rspec',                 :require => false
+  gem 'serverspec',                   :require => false
 end
diff --git a/REFERENCE.md b/REFERENCE.md
new file mode 100644
index 0000000..a3e1daa
--- /dev/null
+++ b/REFERENCE.md
@@ -0,0 +1,1821 @@
+# Reference
+<!-- DO NOT EDIT: This document was generated by Puppet Strings -->
+
+## Table of Contents
+
+**Classes**
+
+* [`ssh`](#ssh): Class to manage SSH client
+* [`ssh::server`](#sshserver): Class to manage SSH server
+
+**Defined types**
+
+* [`ssh::config_entry`](#sshconfig_entry): Create config entries in a users' ~/.ssh/config
+
+## Classes
+
+### ssh
+
+Notes: `Match` and `Host` attributes are not directly supported as multiple
+match/host blocks can exist. Use the `custom` parameter for that.
+
+#### Parameters
+
+The following parameters are available in the `ssh` class.
+
+##### `packages`
+
+Data type: `Variant[String[1], Array[String[1]]]`
+
+
+
+Default value: 'openssh-clients'
+
+##### `package_source`
+
+Data type: `Optional[Stdlib::Absolutepath]`
+
+
+
+Default value: `undef`
+
+##### `package_adminfile`
+
+Data type: `Optional[Stdlib::Absolutepath]`
+
+
+
+Default value: `undef`
+
+##### `config_path`
+
+Data type: `Stdlib::Absolutepath`
+
+
+
+Default value: '/etc/ssh/ssh_config'
+
+##### `config_owner`
+
+Data type: `String[1]`
+
+
+
+Default value: 'root'
+
+##### `config_group`
+
+Data type: `String[1]`
+
+
+
+Default value: 'root'
+
+##### `config_mode`
+
+Data type: `Stdlib::Filemode`
+
+
+
+Default value: '0644'
+
+##### `global_known_hosts`
+
+Data type: `Stdlib::Absolutepath`
+
+
+
+Default value: '/etc/ssh/ssh_known_hosts'
+
+##### `global_known_hosts_owner`
+
+Data type: `String[1]`
+
+
+
+Default value: 'root'
+
+##### `global_known_hosts_group`
+
+Data type: `String[1]`
+
+
+
+Default value: 'root'
+
+##### `global_known_hosts_mode`
+
+Data type: `Stdlib::Filemode`
+
+
+
+Default value: '0644'
+
+##### `manage_root_ssh_config`
+
+Data type: `Boolean`
+
+
+
+Default value: `false`
+
+##### `root_ssh_config_content`
+
+Data type: `String[1]`
+
+
+
+Default value: "# This file is being maintained by Puppet.\n# DO NOT EDIT\n"
+
+##### `manage_server`
+
+Data type: `Boolean`
+
+
+
+Default value: `true`
+
+##### `key_export`
+
+Data type: `Boolean`
+
+
+
+Default value: `false`
+
+##### `purge_keys`
+
+Data type: `Boolean`
+
+
+
+Default value: `true`
+
+##### `ssh_key_ensure`
+
+Data type: `Enum['present', 'absent']`
+
+
+
+Default value: 'present'
+
+##### `ssh_key_import`
+
+Data type: `Boolean`
+
+
+
+Default value: `false`
+
+##### `ssh_key_type`
+
+Data type: `Ssh::Key::Type`
+
+
+
+Default value: 'ssh-rsa'
+
+##### `keys`
+
+Data type: `Hash`
+
+
+
+Default value: `undef`
+
+##### `config_entries`
+
+Data type: `Hash`
+
+
+
+Default value: {}
+
+##### `host`
+
+Data type: `String[1]`
+
+
+
+Default value: '*'
+
+##### `add_keys_to_agent`
+
+Data type: `Optional[Enum['yes', 'no', 'ask', 'confirm']]`
+
+
+
+Default value: `undef`
+
+##### `address_family`
+
+Data type: `Optional[Enum['any', 'inet', 'inet6']]`
+
+
+
+Default value: `undef`
+
+##### `batch_mode`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `bind_address`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `bind_interface`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `canonical_domains`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `canonicalize_fallback_local`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `canonicalize_hostname`
+
+Data type: `Optional[Enum['yes', 'no', 'always']]`
+
+
+
+Default value: `undef`
+
+##### `canonicalize_max_dots`
+
+Data type: `Optional[Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `canonicalize_permitted_cnames`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `ca_signature_algorithms`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `certificate_file`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `challenge_response_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `check_host_ip`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `ciphers`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `clear_all_forwardings`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `compression`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `connection_attempts`
+
+Data type: `Optional[Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `connect_timeout`
+
+Data type: `Optional[Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `control_master`
+
+Data type: `Optional[Enum['yes', 'no', 'ask', 'auto', 'autoask']]`
+
+
+
+Default value: `undef`
+
+##### `control_path`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `control_persist`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `dynamic_forward`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `enable_ssh_keysign`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `escape_char`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `exit_on_forward_failure`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `fingerprint_hash`
+
+Data type: `Optional[Enum['sha256', 'md5']]`
+
+
+
+Default value: `undef`
+
+##### `forward_agent`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `forward_x11`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `forward_x11_timeout`
+
+Data type: `Variant[Undef, String[1], Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `forward_x11_trusted`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `gateway_ports`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `global_known_hosts_file`
+
+Data type: `Variant[Undef, String[1], Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `gss_api_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `gss_api_delegate_credentials`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `hash_known_hosts`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `hostbased_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `hostbased_key_types`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `host_key_algorithms`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `host_key_alias`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `host_name`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `identities_only`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `identity_agent`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `identity_file`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `ignore_unknown`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `include`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `ip_qos`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `kbd_interactive_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `kbd_interactive_devices`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `kex_algorithms`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `local_command`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `local_forward`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `log_level`
+
+Data type: `Optional[Ssh::Log_level]`
+
+
+
+Default value: `undef`
+
+##### `no_host_authentication_for_localhost`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `number_of_password_prompts`
+
+Data type: `Optional[Integer]`
+
+
+
+Default value: `undef`
+
+##### `password_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `permit_local_command`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `pkcs11_provider`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `port`
+
+Data type: `Optional[Stdlib::Port]`
+
+
+
+Default value: `undef`
+
+##### `preferred_authentications`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `proxy_command`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `proxy_jump`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `proxy_use_fdpass`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `pubkey_accepted_key_types`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `pubkey_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `rekey_limit`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `remote_command`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `remote_forward`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `request_tty`
+
+Data type: `Optional[Enum['no', 'yes', 'force', 'auto']]`
+
+
+
+Default value: `undef`
+
+##### `revoked_host_keys`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `send_env`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `server_alive_count_max`
+
+Data type: `Variant[Undef, String[1], Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `server_alive_interval`
+
+Data type: `Variant[Undef, String[1], Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `set_env`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `stream_local_bind_mask`
+
+Data type: `Optional[Pattern[/^[0-7]{4}$/]]`
+
+
+
+Default value: `undef`
+
+##### `stream_local_bind_unlink`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `strict_host_key_checking`
+
+Data type: `Optional[Enum['yes', 'no', 'accept-new', 'off', 'ask']]`
+
+
+
+Default value: `undef`
+
+##### `syslog_facility`
+
+Data type: `Optional[Ssh::Syslog_facility]`
+
+
+
+Default value: `undef`
+
+##### `tcp_keep_alive`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `tunnel`
+
+Data type: `Optional[Enum['yes', 'no', 'point-to-point', 'ethernet']]`
+
+
+
+Default value: `undef`
+
+##### `tunnel_device`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `update_host_keys`
+
+Data type: `Optional[Enum['yes', 'no', 'ask']]`
+
+
+
+Default value: `undef`
+
+##### `user`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `user_known_hosts_file`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `verify_host_key_dns`
+
+Data type: `Optional[Enum['yes', 'no', 'ask']]`
+
+
+
+Default value: `undef`
+
+##### `visual_host_key`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `xauth_location`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `custom`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+### ssh::server
+
+Notes: `Match` attribute is not directly supported as multiple match blocks can
+exist. Use the `custom` parameter for that.
+
+#### Parameters
+
+The following parameters are available in the `ssh::server` class.
+
+##### `packages`
+
+Data type: `Variant[String[1], Array[String[1]]]`
+
+
+
+Default value: 'openssh-server'
+
+##### `package_source`
+
+Data type: `Optional[Stdlib::Absolutepath]`
+
+
+
+Default value: `undef`
+
+##### `package_adminfile`
+
+Data type: `Optional[Stdlib::Absolutepath]`
+
+
+
+Default value: `undef`
+
+##### `config_path`
+
+Data type: `Stdlib::Absolutepath`
+
+
+
+Default value: '/etc/ssh/sshd_config'
+
+##### `config_owner`
+
+Data type: `String[1]`
+
+
+
+Default value: 'root'
+
+##### `config_group`
+
+Data type: `String[1]`
+
+
+
+Default value: 'root'
+
+##### `config_mode`
+
+Data type: `Stdlib::Filemode`
+
+
+
+Default value: '0600'
+
+##### `banner_path`
+
+Data type: `Stdlib::Absolutepath`
+
+
+
+Default value: '/etc/sshd_banner'
+
+##### `banner_content`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `banner_owner`
+
+Data type: `String[1]`
+
+
+
+Default value: 'root'
+
+##### `banner_group`
+
+Data type: `String[1]`
+
+
+
+Default value: 'root'
+
+##### `banner_mode`
+
+Data type: `Stdlib::Filemode`
+
+
+
+Default value: '0644'
+
+##### `manage_service`
+
+Data type: `Boolean`
+
+
+
+Default value: `true`
+
+##### `service_ensure`
+
+Data type: `Stdlib::Ensure::Service`
+
+
+
+Default value: 'running'
+
+##### `service_name`
+
+Data type: `String[1]`
+
+
+
+Default value: 'sshd'
+
+##### `service_enable`
+
+Data type: `Boolean`
+
+
+
+Default value: `true`
+
+##### `service_hasrestart`
+
+Data type: `Boolean`
+
+
+
+Default value: `true`
+
+##### `service_hasstatus`
+
+Data type: `Boolean`
+
+
+
+Default value: `true`
+
+##### `accept_env`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `address_family`
+
+Data type: `Optional[Enum['any', 'inet', 'inet6']]`
+
+
+
+Default value: `undef`
+
+##### `allow_agent_forwarding`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `allow_groups`
+
+Data type: `Variant[Undef, String[1], Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `allow_stream_local_forwarding`
+
+Data type: `Optional[Enum['yes', 'all', 'no', 'local', 'remote']]`
+
+
+
+Default value: `undef`
+
+##### `allow_tcp_forwarding`
+
+Data type: `Optional[Enum['yes', 'no', 'local', 'remote']]`
+
+
+
+Default value: `undef`
+
+##### `allow_users`
+
+Data type: `Variant[Undef, String[1], Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `authentication_methods`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `authorized_keys_command`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `authorized_keys_command_user`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `authorized_keys_file`
+
+Data type: `Variant[Undef, String[1], Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `authorized_principals_command`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `authorized_principals_command_user`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `authorized_principals_file`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `banner`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `ca_signature_algorithms`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `challenge_response_authentication`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `chroot_directory`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `ciphers`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `client_alive_count_max`
+
+Data type: `Optional[Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `client_alive_interval`
+
+Data type: `Optional[Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `compression`
+
+Data type: `Optional[Enum['yes', 'delayed', 'no']]`
+
+
+
+Default value: `undef`
+
+##### `deny_groups`
+
+Data type: `Variant[Undef, String[1], Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `deny_users`
+
+Data type: `Variant[Undef, String[1], Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `disable_forwarding`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `expose_auth_info`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `fingerprint_hash`
+
+Data type: `Optional[Enum['md5', 'sha256']]`
+
+
+
+Default value: `undef`
+
+##### `force_command`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `gateway_ports`
+
+Data type: `Optional[Enum['no', 'yes', 'clientspecified']]`
+
+
+
+Default value: `undef`
+
+##### `gss_api_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `gss_api_cleanup_credentials`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `gss_api_strict_acceptor_check`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `hostbased_accepted_key_types`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `hostbased_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `hostbased_uses_name_from_packet_only`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `host_certificate`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `host_key`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `host_key_agent`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `host_key_algorithms`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `ignore_rhosts`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `ignore_user_known_hosts`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `ip_qos`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `kbd_interactive_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `kerberos_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `kerberos_get_afs_token`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `kerberos_or_local_passwd`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `kerberos_ticket_cleanup`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `kex_algorithms`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `listen_address`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `login_grace_time`
+
+Data type: `Optional[Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `log_level`
+
+Data type: `Optional[Ssh::Log_level]`
+
+
+
+Default value: `undef`
+
+##### `macs`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `max_auth_tries`
+
+Data type: `Optional[Integer[2]]`
+
+
+
+Default value: `undef`
+
+##### `max_sessions`
+
+Data type: `Optional[Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `max_startups`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `password_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `permit_empty_passwords`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `permit_listen`
+
+Data type: `Variant[Undef, String[1], Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `permit_root_login`
+
+Data type: `Optional[Ssh::Permit_root_login]`
+
+
+
+Default value: `undef`
+
+##### `permit_tty`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `permit_tunnel`
+
+Data type: `Optional[Enum['yes', 'point-to-point', 'ethernet', 'no']]`
+
+
+
+Default value: `undef`
+
+##### `permit_user_environment`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `permit_user_rc`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `pid_file`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `port`
+
+Data type: `Optional[Stdlib::Port]`
+
+
+
+Default value: `undef`
+
+##### `print_last_log`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `print_motd`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `pubkey_accepted_key_types`
+
+Data type: `Optional[Array[String[1]]]`
+
+
+
+Default value: `undef`
+
+##### `pubkey_authentication`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `rekey_limit`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `revoked_keys`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `rdomain`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `set_env`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `stream_local_bind_mask`
+
+Data type: `Optional[Pattern[/^[0-7]{4}$/]]`
+
+
+
+Default value: `undef`
+
+##### `stream_local_bind_unlink`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `strict_modes`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `subsystem`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `syslog_facility`
+
+Data type: `Optional[Ssh::Syslog_facility]`
+
+
+
+Default value: `undef`
+
+##### `tcp_keep_alive`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `trusted_user_ca_keys`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `use_dns`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `use_pam`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `version_addendum`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `x11_display_offset`
+
+Data type: `Optional[Integer[0]]`
+
+
+
+Default value: `undef`
+
+##### `x11_forwarding`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `x11_use_localhost`
+
+Data type: `Optional[Ssh::Yes_no]`
+
+
+
+Default value: `undef`
+
+##### `xauth_location`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+##### `custom`
+
+Data type: `Optional[String[1]]`
+
+
+
+Default value: `undef`
+
+## Defined types
+
+### ssh::config_entry
+
+Manage an entry in ~/.ssh/config for a particular user. Lines model the
+lines in each Host block.
+
+#### Parameters
+
+The following parameters are available in the `ssh::config_entry` defined type.
+
+##### `owner`
+
+Data type: `String[1]`
+
+
+
+##### `group`
+
+Data type: `String[1]`
+
+
+
+##### `path`
+
+Data type: `Stdlib::Absolutepath`
+
+
+
+##### `host`
+
+Data type: `String[1]`
+
+
+
+##### `order`
+
+Data type: `Integer[0]`
+
+
+
+Default value: 10
+
+##### `ensure`
+
+Data type: `Enum['present','absent']`
+
+
+
+Default value: 'present'
+
+##### `lines`
+
+Data type: `Array[String]`
+
+
+
+Default value: []
+
diff --git a/Rakefile b/Rakefile
index 93b6400..f0514ed 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,9 +5,21 @@
 PuppetLint.configuration.relative = true
 PuppetLint.configuration.ignore_paths = ['spec/**/*.pp', 'pkg/**/*.pp', 'vendor/**/*.pp']
 
-desc 'Validate manifests, templates, ruby files and shell scripts'
+desc 'Validate ruby files'
 task :validate do
-  Dir['spec/**/*.rb', 'lib/**/*.rb'].each do |ruby_file|
+  Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file|
     sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/
   end
 end
+
+# Puppet Strings (Documentation generation from inline comments)
+# See: https://github.com/puppetlabs/puppet-strings#rake-tasks
+require 'puppet-strings/tasks'
+
+desc 'Alias for strings:generate'
+task :doc => ['strings:generate']
+
+desc 'Generate REFERENCE.md'
+task :reference do
+  sh 'puppet strings generate --format markdown'
+end
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000..a0a1b3b
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,69 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+if not Vagrant.has_plugin?('vagrant-vbguest')
+  abort <<-EOM
+
+vagrant plugin vagrant-vbguest >= 0.16.0 is required.
+https://github.com/dotless-de/vagrant-vbguest
+To install the plugin, please run, 'vagrant plugin install vagrant-vbguest'.
+
+  EOM
+end
+
+# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
+VAGRANTFILE_API_VERSION = "2"
+
+Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+
+  config.vm.synced_folder ".", "/vagrant", type: "virtualbox"
+
+  config.vm.provider :virtualbox do |vb|
+    vb.customize ["modifyvm", :id, "--memory", "512"]
+  end
+
+  # TODO: remove comments around provision once we have a clean copy of
+  # sshd_config and ssh_config from that platform and the platform has been
+  # added to the module and those spec tests work.
+  config.vm.define "el7-ssh", autostart: true do |c|
+    c.vm.box = "centos/7"
+    c.vm.hostname = 'el7-ssh.example.com'
+    c.vm.provision :shell, :path => "tests/provision.sh", :args => "el"
+    c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp"
+  end
+
+  config.vm.define "el6-ssh", autostart: false do |c|
+    c.vm.box = "centos/6"
+    c.vm.hostname = 'el6-ssh.example.com'
+    c.vm.provision :shell, :path => "tests/provision.sh", :args => "el"
+    c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp"
+  end
+
+  config.vm.define "debian8-ssh", autostart: false do |c|
+    c.vm.box = "debian/jessie64"
+    c.vm.hostname = 'debian8-ssh.example.com'
+    c.vm.provision :shell, :path => "tests/provision.sh", :args => "debian"
+#    c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp"
+  end
+
+  config.vm.define "debian9-ssh", autostart: false do |c|
+    c.vm.box = "debian/stretch64"
+    c.vm.hostname = 'debian9-ssh.example.com'
+    c.vm.provision :shell, :path => "tests/provision.sh", :args => "debian"
+#    c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp"
+  end
+
+  config.vm.define "ubuntu1604-ssh", autostart: false do |c|
+    c.vm.box = "ubuntu/xenial64"
+    c.vm.hostname = 'ubuntu1604-ssh.example.com'
+    c.vm.provision :shell, :path => "tests/provision.sh", :args => "debian"
+#    c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp"
+  end
+
+  config.vm.define "ubuntu1804-ssh", autostart: false do |c|
+    c.vm.box = "ubuntu/bionic64"
+    c.vm.hostname = 'ubuntu1804-ssh.example.com'
+    c.vm.provision :shell, :path => "tests/provision.sh", :args => "debian"
+#    c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp"
+  end
+end
diff --git a/data/os/Debian/7.yaml b/data/os/Debian/7.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Debian/7.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Debian/8.yaml b/data/os/Debian/8.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Debian/8.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/RedHat/5.yaml b/data/os/RedHat/5.yaml
new file mode 100644
index 0000000..40e39a2
--- /dev/null
+++ b/data/os/RedHat/5.yaml
@@ -0,0 +1,51 @@
+---
+
+ssh::forward_x11_trusted: 'yes'
+ssh::gss_api_authentication: 'yes'
+
+ssh::send_env:
+  - 'LANG'
+  - 'LANGUAGE'
+  - 'LC_ADDRESS'
+  - 'LC_ALL'
+  - 'LC_COLLATE'
+  - 'LC_CTYPE'
+  - 'LC_IDENTIFICATION'
+  - 'LC_MEASUREMENT'
+  - 'LC_MESSAGES'
+  - 'LC_MONETARY'
+  - 'LC_NAME'
+  - 'LC_NUMERIC'
+  - 'LC_PAPER'
+  - 'LC_TELEPHONE'
+  - 'LC_TIME'
+
+ssh::server::packages: 'openssh-server'
+
+ssh::server::accept_env:
+  - 'LANG'
+  - 'LANGUAGE'
+  - 'LC_ADDRESS'
+  - 'LC_ALL'
+  - 'LC_COLLATE'
+  - 'LC_CTYPE'
+  - 'LC_IDENTIFICATION'
+  - 'LC_MEASUREMENT'
+  - 'LC_MESSAGES'
+  - 'LC_MONETARY'
+  - 'LC_NAME'
+  - 'LC_NUMERIC'
+  - 'LC_PAPER'
+  - 'LC_TELEPHONE'
+  - 'LC_TIME'
+
+ssh::server::challenge_response_authentication: 'no'
+ssh::server::gss_api_authentication: 'yes'
+ssh::server::gss_api_cleanup_credentials: 'yes'
+ssh::server::password_authentication: 'yes'
+ssh::server::subsystem: 'sftp /usr/libexec/openssh/sftp-server'
+ssh::server::syslog_facility: 'AUTHPRIV'
+ssh::server::use_pam: 'yes'
+ssh::server::x11_forwarding: 'yes'
+
+ssh::server::custom: 'Protocol 2'
diff --git a/data/os/RedHat/6.yaml b/data/os/RedHat/6.yaml
new file mode 100644
index 0000000..7398dbc
--- /dev/null
+++ b/data/os/RedHat/6.yaml
@@ -0,0 +1,54 @@
+---
+
+ssh::forward_x11_trusted: 'yes'
+ssh::gss_api_authentication: 'yes'
+
+ssh::send_env:
+  - 'LANG'
+  - 'LANGUAGE'
+  - 'LC_ADDRESS'
+  - 'LC_ALL'
+  - 'LC_COLLATE'
+  - 'LC_CTYPE'
+  - 'LC_IDENTIFICATION'
+  - 'LC_MEASUREMENT'
+  - 'LC_MESSAGES'
+  - 'LC_MONETARY'
+  - 'LC_NAME'
+  - 'LC_NUMERIC'
+  - 'LC_PAPER'
+  - 'LC_TELEPHONE'
+  - 'LC_TIME'
+  - 'XMODIFIERS'
+
+ssh::server::packages: 'openssh-server'
+
+ssh::server::accept_env:
+  - 'LANG'
+  - 'LANGUAGE'
+  - 'LC_ADDRESS'
+  - 'LC_ALL'
+  - 'LC_COLLATE'
+  - 'LC_CTYPE'
+  - 'LC_IDENTIFICATION'
+  - 'LC_MEASUREMENT'
+  - 'LC_MESSAGES'
+  - 'LC_MONETARY'
+  - 'LC_NAME'
+  - 'LC_NUMERIC'
+  - 'LC_PAPER'
+  - 'LC_TELEPHONE'
+  - 'LC_TIME'
+  - 'XMODIFIERS'
+
+ssh::server::challenge_response_authentication: 'no'
+ssh::server::gss_api_authentication: 'yes'
+ssh::server::gss_api_cleanup_credentials: 'yes'
+ssh::server::password_authentication: 'no'
+ssh::server::subsystem: 'sftp /usr/libexec/openssh/sftp-server'
+ssh::server::syslog_facility: 'AUTHPRIV'
+ssh::server::use_dns: 'no'
+ssh::server::use_pam: 'yes'
+ssh::server::x11_forwarding: 'yes'
+
+ssh::server::custom: 'Protocol 2'
diff --git a/data/os/RedHat/7.yaml b/data/os/RedHat/7.yaml
new file mode 100644
index 0000000..512aca5
--- /dev/null
+++ b/data/os/RedHat/7.yaml
@@ -0,0 +1,58 @@
+---
+
+ssh::forward_x11_trusted: 'yes'
+ssh::gss_api_authentication: 'yes'
+
+ssh::send_env:
+  - 'LANG'
+  - 'LANGUAGE'
+  - 'LC_ADDRESS'
+  - 'LC_ALL'
+  - 'LC_COLLATE'
+  - 'LC_CTYPE'
+  - 'LC_IDENTIFICATION'
+  - 'LC_MEASUREMENT'
+  - 'LC_MESSAGES'
+  - 'LC_MONETARY'
+  - 'LC_NAME'
+  - 'LC_NUMERIC'
+  - 'LC_PAPER'
+  - 'LC_TELEPHONE'
+  - 'LC_TIME'
+  - 'XMODIFIERS'
+
+ssh::server::packages: 'openssh-server'
+
+ssh::server::accept_env:
+  - 'LANG'
+  - 'LC_CTYPE'
+  - 'LC_NUMERIC'
+  - 'LC_TIME'
+  - 'LC_COLLATE'
+  - 'LC_MONETARY'
+  - 'LC_MESSAGES'
+  - 'LC_PAPER'
+  - 'LC_NAME'
+  - 'LC_ADDRESS'
+  - 'LC_TELEPHONE'
+  - 'LC_MEASUREMENT'
+  - 'LC_IDENTIFICATION'
+  - 'LC_ALL'
+  - 'LANGUAGE'
+  - 'XMODIFIERS'
+
+ssh::server::authorized_keys_file: '.ssh/authorized_keys'
+ssh::server::challenge_response_authentication: 'no'
+ssh::server::gss_api_authentication: 'yes'
+ssh::server::gss_api_cleanup_credentials: 'no'
+ssh::server::host_key:
+  - '/etc/ssh/ssh_host_ecdsa_key'
+  - '/etc/ssh/ssh_host_ed25519_key'
+  - '/etc/ssh/ssh_host_rsa_key'
+
+ssh::server::password_authentication: 'no'
+ssh::server::subsystem: 'sftp /usr/libexec/openssh/sftp-server'
+ssh::server::syslog_facility: 'AUTHPRIV'
+ssh::server::use_dns: 'no'
+ssh::server::use_pam: 'yes'
+ssh::server::x11_forwarding: 'yes'
diff --git a/data/os/Solaris/5.10.yaml b/data/os/Solaris/5.10.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Solaris/5.10.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Solaris/5.11.yaml b/data/os/Solaris/5.11.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Solaris/5.11.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Solaris/5.9.yaml b/data/os/Solaris/5.9.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Solaris/5.9.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Suse/10.yaml b/data/os/Suse/10.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Suse/10.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Suse/11.yaml b/data/os/Suse/11.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Suse/11.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Suse/12.yaml b/data/os/Suse/12.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Suse/12.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Suse/13.yaml b/data/os/Suse/13.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Suse/13.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Suse/9.yaml b/data/os/Suse/9.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Suse/9.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Ubuntu/12.04.yaml b/data/os/Ubuntu/12.04.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Ubuntu/12.04.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Ubuntu/14.04.yaml b/data/os/Ubuntu/14.04.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Ubuntu/14.04.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/data/os/Ubuntu/16.04.yaml b/data/os/Ubuntu/16.04.yaml
new file mode 100644
index 0000000..cd21505
--- /dev/null
+++ b/data/os/Ubuntu/16.04.yaml
@@ -0,0 +1,2 @@
+---
+
diff --git a/hiera.yaml b/hiera.yaml
new file mode 100644
index 0000000..4ab76e5
--- /dev/null
+++ b/hiera.yaml
@@ -0,0 +1,17 @@
+---
+version: 5
+defaults:
+  datadir: data
+  data_hash: yaml_data
+hierarchy:
+  - name: "osfamily/major release"
+    paths:
+      - "os/%{facts.os.family}/%{facts.os.release.major}.yaml"
+        # Used for Solaris
+      - "os/%{facts.os.family}/%{facts.kernelrelease}.yaml"
+        # Used to distinguish between Debian and Ubuntu
+      - "os/%{facts.os.name}/%{facts.os.release.major}.yaml"
+  - name: "osfamily"
+    paths:
+      - "os/%{facts.os.family}.yaml"
+      - "os/%{facts.os.name}.yaml"
diff --git a/manifests/config_entry.pp b/manifests/config_entry.pp
index 3b368db..3b89bfc 100644
--- a/manifests/config_entry.pp
+++ b/manifests/config_entry.pp
@@ -1,21 +1,36 @@
-# == Define: ssh::config_entry
+# @summary Create config entries in a users' ~/.ssh/config
 #
-# Manage an entry in ~/.ssh/config for a particular user.  Lines model the lines
-# in each Host block.
+# Manage an entry in ~/.ssh/config for a particular user. Lines model the
+# lines in each Host block.
+#
+# @param owner
+#
+# @param group
+#
+# @param path
+#
+# @param host
+#
+# @param order
+#
+# @param ensure
+#
+# @param lines
+#
 define ssh::config_entry (
-  $owner,
-  $group,
-  $path,
-  $host,
-  $order  = '10',
-  $ensure = 'present',
-  $lines  = [],
+  String[1] $owner,
+  String[1] $group,
+  Stdlib::Absolutepath $path,
+  String[1] $host,
+  Enum['present','absent'] $ensure = 'present',
+  Integer[0] $order  = 10,
+  Array[String] $lines  = [],
 ) {
 
-  # All lines including the host line.  This will be joined with "\n  " for
+  # All lines including the host line. This will be joined with "\n  " for
   # indentation.
   $entry = concat(["Host ${host}"], $lines)
-  $content = join($entry, "\n")
+  $content = join($entry, "\n  ")
 
   if ! defined(Concat[$path]) {
     concat { $path:
diff --git a/manifests/init.pp b/manifests/init.pp
index 66788b9..399c7b7 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -1,159 +1,347 @@
-# == Class: ssh
+# @summary Class to manage SSH client
 #
-# Manage ssh client and server
+# Notes: `Match` and `Host` attributes are not directly supported as multiple
+# match/host blocks can exist. Use the `custom` parameter for that.
+#
+# @param packages
+#
+# @param package_source
+#
+# @param package_adminfile
+#
+# @param config_path
+#
+# @param config_owner
+#
+# @param config_group
+#
+# @param config_mode
+#
+# @param global_known_hosts
+#
+# @param global_known_hosts_owner
+#
+# @param global_known_hosts_group
+#
+# @param global_known_hosts_mode
+#
+# @param manage_root_ssh_config
+#
+# @param root_ssh_config_content
+#
+# @param manage_server
+#
+# @param key_export
+#
+# @param purge_keys
+#
+# @param ssh_key_ensure
+#
+# @param ssh_key_import
+#
+# @param ssh_key_type
+#
+# @param keys
+#
+# @param config_entries
+#
+# @param host
+#
+# @param add_keys_to_agent
+#
+# @param address_family
+#
+# @param batch_mode
+#
+# @param bind_address
+#
+# @param bind_interface
+#
+# @param canonical_domains
+#
+# @param canonicalize_fallback_local
+#
+# @param canonicalize_hostname
+#
+# @param canonicalize_max_dots
+#
+# @param canonicalize_permitted_cnames
+#
+# @param ca_signature_algorithms
+#
+# @param certificate_file
+#
+# @param challenge_response_authentication
+#
+# @param check_host_ip
+#
+# @param ciphers
+#
+# @param clear_all_forwardings
+#
+# @param compression
+#
+# @param connection_attempts
+#
+# @param connect_timeout
+#
+# @param control_master
+#
+# @param control_path
+#
+# @param control_persist
+#
+# @param dynamic_forward
+#
+# @param enable_ssh_keysign
+#
+# @param escape_char
+#
+# @param exit_on_forward_failure
+#
+# @param fingerprint_hash
+#
+# @param forward_agent
+#
+# @param forward_x11
+#
+# @param forward_x11_timeout
+#
+# @param forward_x11_trusted
+#
+# @param gateway_ports
+#
+# @param global_known_hosts_file
+#
+# @param gss_api_authentication
+#
+# @param gss_api_delegate_credentials
+#
+# @param hash_known_hosts
+#
+# @param hostbased_authentication
+#
+# @param hostbased_key_types
+#
+# @param host_key_algorithms
+#
+# @param host_key_alias
+#
+# @param host_name
+#
+# @param identities_only
+#
+# @param identity_agent
+#
+# @param identity_file
+#
+# @param ignore_unknown
+#
+# @param include
+#
+# @param ip_qos
+#
+# @param kbd_interactive_authentication
+#
+# @param kbd_interactive_devices
+#
+# @param kex_algorithms
+#
+# @param local_command
+#
+# @param local_forward
+#
+# @param log_level
+#
+# @param no_host_authentication_for_localhost
+#
+# @param number_of_password_prompts
+#
+# @param password_authentication
+#
+# @param permit_local_command
+#
+# @param pkcs11_provider
+#
+# @param port
+#
+# @param preferred_authentications
+#
+# @param proxy_command
+#
+# @param proxy_jump
+#
+# @param proxy_use_fdpass
+#
+# @param pubkey_accepted_key_types
+#
+# @param pubkey_authentication
+#
+# @param rekey_limit
+#
+# @param remote_command
+#
+# @param remote_forward
+#
+# @param request_tty
+#
+# @param revoked_host_keys
+#
+# @param send_env
+#
+# @param server_alive_count_max
+#
+# @param server_alive_interval
+#
+# @param set_env
+#
+# @param stream_local_bind_mask
+#
+# @param stream_local_bind_unlink
+#
+# @param strict_host_key_checking
+#
+# @param syslog_facility
+#
+# @param tcp_keep_alive
+#
+# @param tunnel
+#
+# @param tunnel_device
+#
+# @param update_host_keys
+#
+# @param user
+#
+# @param user_known_hosts_file
+#
+# @param verify_host_key_dns
+#
+# @param visual_host_key
+#
+# @param xauth_location
+#
+# @param custom
 #
 class ssh (
-  $hiera_merge                            = false,
-  $packages                               = 'USE_DEFAULTS',
-  $permit_root_login                      = 'yes',
-  $purge_keys                             = true,
-  $manage_firewall                        = false,
-  $ssh_package_source                     = 'USE_DEFAULTS',
-  $ssh_package_adminfile                  = 'USE_DEFAULTS',
-  $ssh_config_hash_known_hosts            = 'USE_DEFAULTS',
-  $ssh_config_path                        = '/etc/ssh/ssh_config',
-  $ssh_config_owner                       = 'root',
-  $ssh_config_group                       = 'root',
-  $ssh_config_mode                        = '0644',
-  $ssh_config_forward_x11                 = undef,
-  $ssh_config_forward_x11_trusted         = 'USE_DEFAULTS',
-  $ssh_config_forward_agent               = undef,
-  $ssh_config_server_alive_interval       = undef,
-  $ssh_config_sendenv_xmodifiers          = false,
-  $ssh_hostbasedauthentication            = undef,
-  $ssh_config_proxy_command               = undef,
-  $ssh_strict_host_key_checking           = undef,
-  $ssh_config_ciphers                     = undef,
-  $ssh_config_kexalgorithms               = undef,
-  $ssh_config_macs                        = undef,
-  $ssh_config_use_roaming                 = 'USE_DEFAULTS',
-  $ssh_config_template                    = 'ssh/ssh_config.erb',
-  $ssh_sendenv                            = 'USE_DEFAULTS',
-  $ssh_gssapiauthentication               = 'yes',
-  $ssh_gssapidelegatecredentials          = undef,
-  $sshd_config_path                       = '/etc/ssh/sshd_config',
-  $sshd_config_owner                      = 'root',
-  $sshd_config_group                      = 'root',
-  $sshd_config_loglevel                   = 'INFO',
-  $sshd_config_mode                       = 'USE_DEFAULTS',
-  $sshd_config_permitemptypasswords       = undef,
-  $sshd_config_permituserenvironment      = undef,
-  $sshd_config_compression                = undef,
-  $sshd_config_port                       = '22',
-  $sshd_config_syslog_facility            = 'AUTH',
-  $sshd_config_template                   = 'ssh/sshd_config.erb',
-  $sshd_config_login_grace_time           = '120',
-  $sshd_config_challenge_resp_auth        = 'yes',
-  $sshd_config_print_motd                 = 'yes',
-  $sshd_config_print_last_log             = undef,
-  $sshd_config_use_dns                    = 'USE_DEFAULTS',
-  $sshd_config_authkey_location           = undef,
-  $sshd_config_strictmodes                = undef,
-  $sshd_config_serverkeybits              = 'USE_DEFAULTS',
-  $sshd_config_banner                     = 'none',
-  $sshd_config_ciphers                    = undef,
-  $sshd_config_kexalgorithms              = undef,
-  $sshd_config_macs                       = undef,
-  $ssh_enable_ssh_keysign                 = undef,
-  $sshd_config_allowgroups                = [],
-  $sshd_config_allowusers                 = [],
-  $sshd_config_denygroups                 = [],
-  $sshd_config_denyusers                  = [],
-  $sshd_config_maxauthtries               = undef,
-  $sshd_config_maxstartups                = undef,
-  $sshd_config_maxsessions                = undef,
-  $sshd_config_chrootdirectory            = undef,
-  $sshd_config_forcecommand               = undef,
-  $sshd_config_match                      = undef,
-  $sshd_authorized_keys_command           = undef,
-  $sshd_authorized_keys_command_user      = undef,
-  $sshd_banner_content                    = undef,
-  $sshd_banner_owner                      = 'root',
-  $sshd_banner_group                      = 'root',
-  $sshd_banner_mode                       = '0644',
-  $sshd_config_xauth_location             = 'USE_DEFAULTS',
-  $sshd_config_subsystem_sftp             = 'USE_DEFAULTS',
-  $sshd_kerberos_authentication           = undef,
-  $sshd_password_authentication           = 'yes',
-  $sshd_allow_tcp_forwarding              = 'yes',
-  $sshd_x11_forwarding                    = 'yes',
-  $sshd_x11_use_localhost                 = 'yes',
-  $sshd_use_pam                           = 'USE_DEFAULTS',
-  $sshd_client_alive_count_max            = '3',
-  $sshd_client_alive_interval             = '0',
-  $sshd_gssapiauthentication              = 'yes',
-  $sshd_gssapikeyexchange                 = 'USE_DEFAULTS',
-  $sshd_pamauthenticationviakbdint        = 'USE_DEFAULTS',
-  $sshd_gssapicleanupcredentials          = 'USE_DEFAULTS',
-  $sshd_acceptenv                         = 'USE_DEFAULTS',
-  $sshd_config_hostkey                    = 'USE_DEFAULTS',
-  $sshd_listen_address                    = undef,
-  $sshd_hostbasedauthentication           = 'no',
-  $sshd_pubkeyacceptedkeytypes            = undef,
-  $sshd_pubkeyauthentication              = 'yes',
-  $sshd_ignoreuserknownhosts              = 'no',
-  $sshd_ignorerhosts                      = 'yes',
-  $sshd_config_authenticationmethods      = undef,
-  $manage_service                         = true,
-  $sshd_addressfamily                     = 'USE_DEFAULTS',
-  $service_ensure                         = 'running',
-  $service_name                           = 'USE_DEFAULTS',
-  $service_enable                         = true,
-  $service_hasrestart                     = true,
-  $service_hasstatus                      = 'USE_DEFAULTS',
-  $ssh_key_ensure                         = 'present',
-  $ssh_key_import                         = true,
-  $ssh_key_type                           = 'ssh-rsa',
-  $ssh_config_global_known_hosts_file     = '/etc/ssh/ssh_known_hosts',
-  $ssh_config_global_known_hosts_list     = undef,
-  $ssh_config_global_known_hosts_owner    = 'root',
-  $ssh_config_global_known_hosts_group    = 'root',
-  $ssh_config_global_known_hosts_mode     = '0644',
-  $ssh_config_user_known_hosts_file       = undef,
-  $config_entries                         = {},
-  $keys                                   = undef,
-  $manage_root_ssh_config                 = false,
-  $root_ssh_config_content                = "# This file is being maintained by Puppet.\n# DO NOT EDIT\n",
-  $sshd_config_tcp_keepalive              = undef,
-  $sshd_config_use_privilege_separation   = undef,
-  $sshd_config_permittunnel               = undef,
-  $sshd_config_hostcertificate            = undef,
-  $sshd_config_trustedusercakeys          = undef,
-  $sshd_config_key_revocation_list        = undef,
-  $sshd_config_authorized_principals_file = undef,
-  $sshd_config_allowagentforwarding       = undef,
+  Variant[String[1], Array[String[1]]] $packages = 'openssh-clients',
+  Optional[Stdlib::Absolutepath] $package_source = undef,
+  Optional[Stdlib::Absolutepath] $package_adminfile = undef,
+  Stdlib::Absolutepath $config_path = '/etc/ssh/ssh_config',
+  String[1] $config_owner = 'root',
+  String[1] $config_group = 'root',
+  Stdlib::Filemode $config_mode = '0644',
+  Stdlib::Absolutepath $global_known_hosts = '/etc/ssh/ssh_known_hosts',
+  String[1] $global_known_hosts_owner = 'root',
+  String[1] $global_known_hosts_group = 'root',
+  Stdlib::Filemode $global_known_hosts_mode = '0644',
+  Boolean $manage_root_ssh_config = false,
+  String[1] $root_ssh_config_content = "# This file is being maintained by Puppet.\n# DO NOT EDIT\n",
+  Boolean $manage_server = true,
+  Boolean $key_export = false,
+  Boolean $purge_keys = true,
+  Enum['present', 'absent'] $ssh_key_ensure = 'present',
+  Boolean $ssh_key_import = false,
+  Ssh::Key::Type $ssh_key_type = 'ssh-rsa',
+  Hash $keys = {},
+  Hash $config_entries = {},
+  # class parameters below this line directly correlate with ssh_config parameters
+  String[1] $host = '*',
+  Optional[Enum['yes', 'no', 'ask', 'confirm']] $add_keys_to_agent = undef,
+  Optional[Enum['any', 'inet', 'inet6']] $address_family = undef,
+  Optional[Ssh::Yes_no] $batch_mode = undef,
+  Optional[String[1]] $bind_address = undef,
+  Optional[String[1]] $bind_interface = undef,
+  Optional[Array[String[1]]] $canonical_domains = undef,
+  Optional[Ssh::Yes_no] $canonicalize_fallback_local = undef,
+  Optional[Enum['yes', 'no', 'always']] $canonicalize_hostname = undef,
+  Optional[Integer[0]] $canonicalize_max_dots = undef,
+  Optional[Array[String[1]]] $canonicalize_permitted_cnames = undef,
+  Optional[Array[String[1]]] $ca_signature_algorithms = undef,
+  Optional[Array[String[1]]] $certificate_file = undef,
+  Optional[Ssh::Yes_no] $challenge_response_authentication = undef,
+  Optional[Ssh::Yes_no] $check_host_ip = undef,
+  Optional[Array[String[1]]] $ciphers = undef,
+  Optional[Ssh::Yes_no] $clear_all_forwardings = undef,
+  Optional[Ssh::Yes_no] $compression = undef,
+  Optional[Integer[0]] $connection_attempts = undef,
+  Optional[Integer[0]] $connect_timeout = undef,
+  Optional[Enum['yes', 'no', 'ask', 'auto', 'autoask']] $control_master = undef,
+  Optional[String[1]] $control_path = undef,
+  Optional[String[1]] $control_persist = undef,
+  Optional[String[1]] $dynamic_forward = undef,
+  Optional[Ssh::Yes_no] $enable_ssh_keysign = undef,
+  Optional[String[1]] $escape_char = undef,
+  Optional[Ssh::Yes_no] $exit_on_forward_failure = undef,
+  Optional[Enum['sha256', 'md5']] $fingerprint_hash = undef,
+  Optional[Ssh::Yes_no] $forward_agent = undef,
+  Optional[Ssh::Yes_no] $forward_x11 = undef,
+  Variant[Undef, String[1], Integer[0]] $forward_x11_timeout = undef,
+  Optional[Ssh::Yes_no] $forward_x11_trusted = undef,
+  Optional[Ssh::Yes_no] $gateway_ports = undef,
+  Variant[Undef, String[1], Array[String[1]]] $global_known_hosts_file = undef,
+  Optional[Ssh::Yes_no] $gss_api_authentication = undef,
+  Optional[Ssh::Yes_no] $gss_api_delegate_credentials = undef,
+  Optional[Ssh::Yes_no] $hash_known_hosts = undef,
+  Optional[Ssh::Yes_no] $hostbased_authentication = undef,
+  Optional[Array[String[1]]] $hostbased_key_types = undef,
+  Optional[Array[String[1]]] $host_key_algorithms = undef,
+  Optional[String[1]] $host_key_alias = undef,
+  Optional[String[1]] $host_name = undef,
+  Optional[Ssh::Yes_no] $identities_only = undef,
+  Optional[String[1]] $identity_agent = undef,
+  Optional[Array[String[1]]] $identity_file = undef,
+  Optional[Array[String[1]]] $ignore_unknown = undef,
+  Optional[String[1]] $include = undef,
+  Optional[String[1]] $ip_qos = undef,
+  Optional[Ssh::Yes_no] $kbd_interactive_authentication = undef,
+  Optional[Array[String[1]]] $kbd_interactive_devices = undef,
+  Optional[Array[String[1]]] $kex_algorithms = undef,
+  Optional[String[1]] $local_command = undef,
+  Optional[String[1]] $local_forward = undef,
+  Optional[Ssh::Log_level] $log_level = undef,
+  Optional[Ssh::Yes_no] $no_host_authentication_for_localhost = undef,
+  Optional[Integer] $number_of_password_prompts = undef,
+  Optional[Ssh::Yes_no] $password_authentication = undef,
+  Optional[Ssh::Yes_no] $permit_local_command = undef,
+  Optional[String[1]] $pkcs11_provider = undef,
+  Optional[Stdlib::Port] $port = undef,
+  Optional[Array[String[1]]] $preferred_authentications = undef,
+  Optional[String[1]] $proxy_command = undef,
+  Optional[Array[String[1]]] $proxy_jump = undef,
+  Optional[Ssh::Yes_no] $proxy_use_fdpass = undef,
+  Optional[Array[String[1]]] $pubkey_accepted_key_types = undef,
+  Optional[Ssh::Yes_no] $pubkey_authentication = undef,
+  Optional[String[1]] $rekey_limit = undef,
+  Optional[String[1]] $remote_command = undef,
+  Optional[String[1]] $remote_forward = undef,
+  Optional[Enum['no', 'yes', 'force', 'auto']] $request_tty = undef,
+  Optional[String[1]] $revoked_host_keys = undef,
+  Optional[Array[String[1]]] $send_env = undef,
+  Variant[Undef, String[1], Integer[0]] $server_alive_count_max = undef,
+  Variant[Undef, String[1], Integer[0]] $server_alive_interval = undef,
+  Optional[Array[String[1]]] $set_env = undef,
+  Optional[Pattern[/^[0-7]{4}$/]] $stream_local_bind_mask = undef,
+  Optional[Ssh::Yes_no] $stream_local_bind_unlink = undef,
+  Optional[Enum['yes', 'no', 'accept-new', 'off', 'ask']] $strict_host_key_checking = undef,
+  Optional[Ssh::Syslog_facility] $syslog_facility = undef,
+  Optional[Ssh::Yes_no] $tcp_keep_alive = undef,
+  Optional[Enum['yes', 'no', 'point-to-point', 'ethernet']] $tunnel = undef,
+  Optional[String[1]] $tunnel_device = undef,
+  Optional[Enum['yes', 'no', 'ask']] $update_host_keys = undef,
+  Optional[String[1]] $user = undef,
+  Optional[Array[String[1]]] $user_known_hosts_file = undef,
+  Optional[Enum['yes', 'no', 'ask']] $verify_host_key_dns = undef,
+  Optional[Ssh::Yes_no] $visual_host_key = undef,
+  Optional[String[1]] $xauth_location = undef,
+  # custom is a string that allows for multiple lines to be appended to end of
+  # the sshd_config file.
+  Optional[String[1]] $custom = undef,
 ) {
 
-  case $::osfamily {
-    'RedHat': {
-      $default_packages                        = ['openssh-server',
-                                                  'openssh-clients']
-      $default_service_name                    = 'sshd'
-      $default_ssh_config_hash_known_hosts     = 'no'
-      $default_ssh_config_forward_x11_trusted  = 'yes'
-      $default_ssh_package_source              = undef
-      $default_ssh_package_adminfile           = undef
-      $default_ssh_sendenv                     = true
-      $default_sshd_config_subsystem_sftp      = '/usr/libexec/openssh/sftp-server'
-      $default_sshd_config_mode                = '0600'
-      $default_sshd_config_use_dns             = 'yes'
-      $default_sshd_config_xauth_location      = '/usr/bin/xauth'
-      $default_sshd_use_pam                    = 'yes'
-      $default_sshd_gssapikeyexchange          = undef
-      $default_sshd_pamauthenticationviakbdint = undef
-      $default_sshd_gssapicleanupcredentials   = 'yes'
-      $default_sshd_acceptenv                  = true
-      $default_service_hasstatus               = true
-      if versioncmp($::operatingsystemrelease, '7.4') < 0 {
-        $default_sshd_config_serverkeybits = '1024'
-      } else {
-        $default_sshd_config_serverkeybits = undef
-      }
-      $default_sshd_config_hostkey             = [ '/etc/ssh/ssh_host_rsa_key' ]
-      $default_sshd_addressfamily              = 'any'
-      $default_sshd_config_tcp_keepalive       = 'yes'
-      $default_sshd_config_permittunnel        = 'no'
-    }
+  # TODO: This huge case statement is getting transitioned to hiera
+  case $facts['os']['family'] {
+    'RedHat': {}
     'Suse': {
       $default_packages                        = 'openssh'
       $default_service_name                    = 'sshd'
@@ -386,7 +574,7 @@
       }
     }
     default: {
-      fail("ssh supports osfamilies RedHat, Suse, Debian and Solaris. Detected osfamily is <${::osfamily}>.")
+      fail("ssh supports osfamilies RedHat, Suse, Debian and Solaris. Detected os family is <${facts['os']['family']}>.")
     }
   }
 
@@ -405,639 +593,29 @@
       $default_ssh_config_use_roaming = 'unset'
   }
 
-  if $packages == 'USE_DEFAULTS' {
-    $packages_real = $default_packages
-  } else {
-    $packages_real = $packages
-  }
-
-  case $ssh_config_hash_known_hosts {
-    'unset':        { $ssh_config_hash_known_hosts_real = undef }
-    'USE_DEFAULTS': { $ssh_config_hash_known_hosts_real = $default_ssh_config_hash_known_hosts }
-    default:        { $ssh_config_hash_known_hosts_real = $ssh_config_hash_known_hosts }
-  }
-
-  if $service_name == 'USE_DEFAULTS' {
-    $service_name_real = $default_service_name
-  } else {
-    $service_name_real = $service_name
-  }
-
-  if $sshd_config_subsystem_sftp == 'USE_DEFAULTS' {
-    $sshd_config_subsystem_sftp_real = $default_sshd_config_subsystem_sftp
-  } else {
-    $sshd_config_subsystem_sftp_real = $sshd_config_subsystem_sftp
-  }
-
-  if $sshd_config_mode    == 'USE_DEFAULTS' {
-    $sshd_config_mode_real = $default_sshd_config_mode
-  } else {
-    $sshd_config_mode_real = $sshd_config_mode
-  }
-
-  if $sshd_config_xauth_location == 'USE_DEFAULTS' {
-    $sshd_config_xauth_location_real = $default_sshd_config_xauth_location
-  } else {
-    $sshd_config_xauth_location_real = $sshd_config_xauth_location
-  }
-
-  if $sshd_config_xauth_location_real != undef {
-    validate_absolute_path($sshd_config_xauth_location_real)
-  }
-
-  if $ssh_package_source == 'USE_DEFAULTS' {
-    $ssh_package_source_real = $default_ssh_package_source
-  } else {
-    $ssh_package_source_real = $ssh_package_source
-  }
-
-  if $ssh_package_source_real != undef {
-    validate_absolute_path($ssh_package_source_real)
-  }
-
-  if $ssh_package_adminfile == 'USE_DEFAULTS' {
-    $ssh_package_adminfile_real = $default_ssh_package_adminfile
-  } else {
-    $ssh_package_adminfile_real = $ssh_package_adminfile
-  }
-
-  if $ssh_package_adminfile_real != undef {
-    validate_absolute_path($ssh_package_adminfile_real)
-  }
-
-  if $sshd_config_use_dns == 'USE_DEFAULTS' {
-    $sshd_config_use_dns_real = $default_sshd_config_use_dns
-  } else {
-    $sshd_config_use_dns_real = $sshd_config_use_dns
-  }
-
-  if $sshd_use_pam == 'USE_DEFAULTS' {
-    $sshd_use_pam_real = $default_sshd_use_pam
-  } else {
-    $sshd_use_pam_real = $sshd_use_pam
-  }
-
-  if $sshd_config_serverkeybits == 'USE_DEFAULTS' {
-    $sshd_config_serverkeybits_real = $default_sshd_config_serverkeybits
-  } else {
-    $sshd_config_serverkeybits_real = $sshd_config_serverkeybits
-  }
-
-  if $ssh_config_forward_x11_trusted == 'USE_DEFAULTS' {
-    $ssh_config_forward_x11_trusted_real = $default_ssh_config_forward_x11_trusted
-  } else {
-    $ssh_config_forward_x11_trusted_real = $ssh_config_forward_x11_trusted
-  }
-  if $ssh_config_forward_x11_trusted_real != undef {
-    validate_re($ssh_config_forward_x11_trusted_real, '^(yes|no)$', "ssh::ssh_config_forward_x11_trusted may be either 'yes' or 'no' and is set to <${ssh_config_forward_x11_trusted_real}>.")
-  }
-
-  if $sshd_gssapikeyexchange == 'USE_DEFAULTS' {
-    $sshd_gssapikeyexchange_real = $default_sshd_gssapikeyexchange
-  } else {
-    $sshd_gssapikeyexchange_real = $sshd_gssapikeyexchange
-  }
-
-  if $sshd_pamauthenticationviakbdint == 'USE_DEFAULTS' {
-    $sshd_pamauthenticationviakbdint_real = $default_sshd_pamauthenticationviakbdint
-  } else {
-    $sshd_pamauthenticationviakbdint_real = $sshd_pamauthenticationviakbdint
-  }
-
-  if $sshd_gssapicleanupcredentials == 'USE_DEFAULTS' {
-    $sshd_gssapicleanupcredentials_real = $default_sshd_gssapicleanupcredentials
-  } else {
-    $sshd_gssapicleanupcredentials_real = $sshd_gssapicleanupcredentials
-  }
-
-  if $ssh_config_use_roaming == 'USE_DEFAULTS' {
-    $ssh_config_use_roaming_real = $default_ssh_config_use_roaming
-  } else {
-    $ssh_config_use_roaming_real = $ssh_config_use_roaming
-  }
-
-  if $ssh_sendenv == 'USE_DEFAULTS' {
-    $ssh_sendenv_real = $default_ssh_sendenv
-  } else {
-    case type3x($ssh_sendenv) {
-      'string': {
-        validate_re($ssh_sendenv, '^(true|false)$', "ssh::ssh_sendenv may be either 'true' or 'false' and is set to <${ssh_sendenv}>.")
-        $ssh_sendenv_real = str2bool($ssh_sendenv)
-      }
-      'boolean': {
-        $ssh_sendenv_real = $ssh_sendenv
-      }
-      default: {
-        fail('ssh::ssh_sendenv type must be true or false.')
-      }
-    }
-  }
-
-  if $sshd_acceptenv == 'USE_DEFAULTS' {
-    $sshd_acceptenv_real = $default_sshd_acceptenv
-  } else {
-    case type3x($sshd_acceptenv) {
-      'string': {
-        validate_re($sshd_acceptenv, '^(true|false)$', "ssh::sshd_acceptenv may be either 'true' or 'false' and is set to <${sshd_acceptenv}>.")
-        $sshd_acceptenv_real = str2bool($sshd_acceptenv)
-      }
-      'boolean': {
-        $sshd_acceptenv_real = $sshd_acceptenv
-      }
-      default: {
-        fail('ssh::sshd_acceptenv type must be true or false.')
-      }
-    }
-  }
-
-  if $sshd_config_hostkey == 'USE_DEFAULTS' {
-    $sshd_config_hostkey_real = $default_sshd_config_hostkey
-  } else {
-    validate_array($sshd_config_hostkey)
-    validate_absolute_path($sshd_config_hostkey)
-    $sshd_config_hostkey_real = $sshd_config_hostkey
-  }
-
-  if $sshd_listen_address {
-    validate_array($sshd_listen_address)
-  }
-
-  if $service_hasstatus == 'USE_DEFAULTS' {
-    $service_hasstatus_real = $default_service_hasstatus
-  } else {
-    case type3x($service_hasstatus) {
-      'string': {
-        validate_re($service_hasstatus, '^(true|false)$', "ssh::service_hasstatus must be 'true' or 'false' and is set to <${service_hasstatus}>.")
-        $service_hasstatus_real = str2bool($service_hasstatus)
-      }
-      'boolean': {
-        $service_hasstatus_real = $service_hasstatus
-      }
-      default: {
-        fail('ssh::service_hasstatus must be true or false.')
-      }
-    }
-  }
-
-  if $sshd_addressfamily == 'USE_DEFAULTS' {
-    $sshd_addressfamily_real = $default_sshd_addressfamily
-  } else {
-    $sshd_addressfamily_real = $sshd_addressfamily
-  }
-
-  case $sshd_config_maxsessions {
-    'unset', undef: { $sshd_config_maxsessions_integer = undef }
-    default:        { $sshd_config_maxsessions_integer = floor($sshd_config_maxsessions) }
-  }
-
-  case $sshd_config_tcp_keepalive {
-    'unset': { $sshd_config_tcp_keepalive_real = undef }
-    undef:   { $sshd_config_tcp_keepalive_real = $default_sshd_config_tcp_keepalive }
-    default: { $sshd_config_tcp_keepalive_real = $sshd_config_tcp_keepalive }
-  }
-
-  case $sshd_config_permittunnel {
-    'unset': { $sshd_config_permittunnel_real = undef }
-    undef:   { $sshd_config_permittunnel_real = $default_sshd_config_permittunnel }
-    default: { $sshd_config_permittunnel_real = $sshd_config_permittunnel }
-  }
-
-  case $sshd_config_hostcertificate {
-    'unset', undef: { $sshd_config_hostcertificate_real = undef }
-    default: { $sshd_config_hostcertificate_real = $sshd_config_hostcertificate }
-  }
-
-  case $sshd_config_trustedusercakeys {
-    'unset', undef: { $sshd_config_trustedusercakeys_real = undef }
-    default: { $sshd_config_trustedusercakeys_real = $sshd_config_trustedusercakeys }
-  }
-
-  case $sshd_config_key_revocation_list {
-    'unset', undef: { $sshd_config_key_revocation_list_real = undef }
-    default: { $sshd_config_key_revocation_list_real = $sshd_config_key_revocation_list }
-  }
-
-  case $sshd_config_authorized_principals_file {
-    'unset', undef: { $sshd_config_authorized_principals_file_real = undef }
-    default: { $sshd_config_authorized_principals_file_real = $sshd_config_authorized_principals_file }
-  }
-
-  # validate params
-  if $ssh_config_ciphers != undef {
-    validate_array($ssh_config_ciphers)
-  }
-
-  if $sshd_config_ciphers != undef {
-    validate_array($sshd_config_ciphers)
-  }
-
-  if $ssh_config_kexalgorithms != undef {
-    validate_array($ssh_config_kexalgorithms)
-  }
-
-  if $sshd_config_kexalgorithms != undef {
-    validate_array($sshd_config_kexalgorithms)
-  }
-
-  if $ssh_config_macs != undef {
-    validate_array($ssh_config_macs)
-  }
-
-  if $sshd_config_macs != undef {
-    validate_array($sshd_config_macs)
-  }
-
-  if $ssh_config_hash_known_hosts_real != undef {
-    validate_re($ssh_config_hash_known_hosts_real, '^(yes|no)$', "ssh::ssh_config_hash_known_hosts may be either 'yes', 'no' or 'unset' and is set to <${ssh_config_hash_known_hosts_real}>.")
-  }
-  if $sshd_config_permitemptypasswords != undef {
-    validate_re($sshd_config_permitemptypasswords, '^(yes|no)$', "ssh::sshd_config_permitemptypasswords may be either 'yes' or 'no' and is set to <${sshd_config_permitemptypasswords}>.")
-  }
-  if $sshd_config_permituserenvironment != undef {
-    validate_re($sshd_config_permituserenvironment, '^(yes|no)$', "ssh::sshd_config_permituserenvironment may be either 'yes' or 'no' and is set to <${sshd_config_permituserenvironment}>.")
-  }
-  if $sshd_config_compression != undef {
-    validate_re($sshd_config_compression, '^(yes|no|delayed)$', "ssh::sshd_config_compression may be either 'yes', 'no' or 'delayed' and is set to <${sshd_config_compression}>.")
-  }
-  case type3x($sshd_config_port) {
-    'string': {
-      validate_re($sshd_config_port, '^\d+$', "ssh::sshd_config_port must be a valid number and is set to <${sshd_config_port}>.")
-      $sshd_config_port_array = [ str2num($sshd_config_port) ]
-    }
-    'array': {
-      $sshd_config_port_array = $sshd_config_port
-    }
-    'integer': {
-      $sshd_config_port_array = [ $sshd_config_port ]
-    }
-    default: {
-      fail('ssh:sshd_config_port must be a string, an integer or an array. ')
-    }
-  }
-  validate_numeric($sshd_config_port_array, 65535, 1)
-  if $sshd_kerberos_authentication != undef {
-    validate_re($sshd_kerberos_authentication, '^(yes|no)$', "ssh::sshd_kerberos_authentication may be either 'yes' or 'no' and is set to <${sshd_kerberos_authentication}>.")
-  }
-  validate_re($sshd_password_authentication, '^(yes|no)$', "ssh::sshd_password_authentication may be either 'yes' or 'no' and is set to <${sshd_password_authentication}>.")
-  validate_re($sshd_allow_tcp_forwarding, '^(yes|no)$', "ssh::sshd_allow_tcp_forwarding may be either 'yes' or 'no' and is set to <${sshd_allow_tcp_forwarding}>.")
-  validate_re($sshd_x11_forwarding, '^(yes|no)$', "ssh::sshd_x11_forwarding may be either 'yes' or 'no' and is set to <${sshd_x11_forwarding}>.")
-  validate_re($sshd_x11_use_localhost, '^(yes|no)$', "ssh::sshd_x11_use_localhost may be either 'yes' or 'no' and is set to <${sshd_x11_use_localhost}>.")
-  if $sshd_config_print_last_log != undef {
-    validate_re($sshd_config_print_last_log, '^(yes|no)$', "ssh::sshd_config_print_last_log may be either 'yes' or 'no' and is set to <${sshd_config_print_last_log}>.")
-  }
-  if $sshd_use_pam_real != undef {
-    validate_re($sshd_use_pam_real, '^(yes|no)$', "ssh::sshd_use_pam may be either 'yes' or 'no' and is set to <${sshd_use_pam_real}>.")
-  }
-  if $sshd_config_serverkeybits_real != undef {
-    if is_integer($sshd_config_serverkeybits_real) == false { fail("ssh::sshd_config_serverkeybits must be an integer and is set to <${sshd_config_serverkeybits}>.") }
-  }
-  if $ssh_config_use_roaming_real != undef {
-    validate_re($ssh_config_use_roaming_real, '^(yes|no|unset)$', "ssh::ssh_config_use_roaming may be either 'yes', 'no' or 'unset' and is set to <${$ssh_config_use_roaming}>.")
-  }
-  if is_integer($sshd_client_alive_interval) == false { fail("ssh::sshd_client_alive_interval must be an integer and is set to <${sshd_client_alive_interval}>.") }
-  if is_integer($sshd_client_alive_count_max) == false { fail("ssh::sshd_client_alive_count_max must be an integer and is set to <${sshd_client_alive_count_max}>.") }
-
-  if $sshd_config_banner != 'none' {
-    validate_absolute_path($sshd_config_banner)
-  }
-  if $sshd_banner_content != undef and $sshd_config_banner == 'none' {
-    fail('ssh::sshd_config_banner must be set to be able to use sshd_banner_content.')
-  }
-
-  validate_re($ssh_gssapiauthentication, '^(yes|no)$', "ssh::ssh_gssapiauthentication may be either 'yes' or 'no' and is set to <${ssh_gssapiauthentication}>.")
-
-  if $ssh_gssapidelegatecredentials != undef {
-    validate_re($ssh_gssapidelegatecredentials, '^(yes|no)$', "ssh::ssh_gssapidelegatecredentials may be either 'yes' or 'no' and is set to <${ssh_gssapidelegatecredentials}>.")
-  }
-
-  validate_re($sshd_gssapiauthentication, '^(yes|no)$', "ssh::sshd_gssapiauthentication may be either 'yes' or 'no' and is set to <${sshd_gssapiauthentication}>.")
-
-  if $sshd_gssapikeyexchange_real != undef {
-    validate_re($sshd_gssapikeyexchange_real, '^(yes|no)$', "ssh::sshd_gssapikeyexchange may be either 'yes' or 'no' and is set to <${sshd_gssapikeyexchange_real}>.")
-  }
-
-  if $sshd_pamauthenticationviakbdint_real != undef {
-    validate_re($sshd_pamauthenticationviakbdint_real, '^(yes|no)$', "ssh::sshd_pamauthenticationviakbdint may be either 'yes' or 'no' and is set to <${sshd_pamauthenticationviakbdint_real}>.")
-  }
-
-  if $sshd_gssapicleanupcredentials_real != undef {
-    validate_re($sshd_gssapicleanupcredentials_real, '^(yes|no)$', "ssh::sshd_gssapicleanupcredentials may be either 'yes' or 'no' and is set to <${sshd_gssapicleanupcredentials_real}>.")
-  }
-
-  if $ssh_strict_host_key_checking != undef {
-    validate_re($ssh_strict_host_key_checking, '^(yes|no|ask)$', "ssh::ssh_strict_host_key_checking may be 'yes', 'no' or 'ask' and is set to <${ssh_strict_host_key_checking}>.")
-  }
-
-  if $ssh_config_proxy_command != undef {
-    validate_string($ssh_config_proxy_command)
-  }
-
-  if $ssh_enable_ssh_keysign != undef {
-    validate_re($ssh_enable_ssh_keysign, '^(yes|no)$', "ssh::ssh_enable_ssh_keysign may be either 'yes' or 'no' and is set to <${ssh_enable_ssh_keysign}>.")
-  }
-
-  if $sshd_config_authkey_location != undef {
-    validate_string($sshd_config_authkey_location)
-  }
-
-  if $sshd_config_maxauthtries != undef {
-    if is_integer($sshd_config_maxauthtries) == false {
-      fail("ssh::sshd_config_maxauthtries must be a valid number and is set to <${sshd_config_maxauthtries}>.")
-    }
-  }
-
-  if $sshd_config_maxstartups != undef {
-    validate_re($sshd_config_maxstartups,'^((\d+)|(\d+?:\d+?:\d+)?)$',
-      "ssh::sshd_config_maxstartups may be either an integer or three integers separated with colons, such as 10:30:100. Detected value is <${sshd_config_maxstartups}>.")
-  }
-
-  if $sshd_config_chrootdirectory != undef {
-    validate_absolute_path($sshd_config_chrootdirectory)
-  }
-
-  if $sshd_config_forcecommand != undef {
-    validate_string($sshd_config_forcecommand)
-  }
-
-  if $sshd_authorized_keys_command != undef {
-    validate_absolute_path($sshd_authorized_keys_command)
-  }
-
-  if $sshd_authorized_keys_command_user != undef {
-    validate_string($sshd_authorized_keys_command_user)
-  }
-
-  if $sshd_config_match != undef {
-    validate_hash($sshd_config_match)
-  }
-
-  if $sshd_config_strictmodes != undef {
-    validate_re($sshd_config_strictmodes, '^(yes|no)$', "ssh::sshd_config_strictmodes may be either 'yes' or 'no' and is set to <${sshd_config_strictmodes}>.")
-  }
-  if $ssh_hostbasedauthentication != undef {
-    validate_re($ssh_hostbasedauthentication, '^(yes|no)$', "ssh::ssh_hostbasedauthentication may be either 'yes' or 'no' and is set to <${ssh_hostbasedauthentication}>.")
-  }
-
-  validate_re($sshd_hostbasedauthentication, '^(yes|no)$', "ssh::sshd_hostbasedauthentication may be either 'yes' or 'no' and is set to <${sshd_hostbasedauthentication}>.")
-
-  if $sshd_pubkeyacceptedkeytypes != undef {
-    validate_array($sshd_pubkeyacceptedkeytypes)
-  }
-
-  if $sshd_config_authenticationmethods != undef {
-    validate_array($sshd_config_authenticationmethods)
-  }
-
-  validate_re($sshd_pubkeyauthentication, '^(yes|no)$', "ssh::sshd_pubkeyauthentication may be either 'yes' or 'no' and is set to <${sshd_pubkeyauthentication}>.")
-
-  validate_re($sshd_ignoreuserknownhosts, '^(yes|no)$', "ssh::sshd_ignoreuserknownhosts may be either 'yes' or 'no' and is set to <${sshd_ignoreuserknownhosts}>.")
-
-  validate_re($sshd_ignorerhosts, '^(yes|no)$', "ssh::sshd_ignorerhosts may be either 'yes' or 'no' and is set to <${sshd_ignorerhosts}>.")
-
-  case type3x($hiera_merge) {
-    'string': {
-      validate_re($hiera_merge, '^(true|false)$', "ssh::hiera_merge may be either 'true' or 'false' and is set to <${hiera_merge}>.")
-      $hiera_merge_real = str2bool($hiera_merge)
-    }
-    'boolean': {
-      $hiera_merge_real = $hiera_merge
-    }
-    default: {
-      fail('ssh::hiera_merge type must be true or false.')
-    }
-  }
-
-  case type3x($ssh_key_import) {
-    'string': {
-      validate_re($ssh_key_import, '^(true|false)$', "ssh::ssh_key_import may be either 'true' or 'false' and is set to <${ssh_key_import}>.")
-      $ssh_key_import_real = str2bool($ssh_key_import)
-    }
-    'boolean': {
-      $ssh_key_import_real = $ssh_key_import
-    }
-    default: {
-      fail('ssh::ssh_key_import type must be true or false.')
-    }
-  }
-  validate_bool($ssh_key_import_real)
-
-  case type3x($ssh_config_sendenv_xmodifiers) {
-    'string': {
-      $ssh_config_sendenv_xmodifiers_real = str2bool($ssh_config_sendenv_xmodifiers)
-    }
-    'boolean': {
-      $ssh_config_sendenv_xmodifiers_real = $ssh_config_sendenv_xmodifiers
-    }
-    default: {
-      fail('ssh::ssh_config_sendenv_xmodifiers type must be true or false.')
-    }
-  }
-
-  case $permit_root_login {
-    'no', 'yes', 'without-password', 'forced-commands-only': {
-      # noop
-    }
-    default: {
-      fail("ssh::permit_root_login may be either 'yes', 'without-password', 'forced-commands-only' or 'no' and is set to <${permit_root_login}>.")
-    }
-  }
-
-  case $ssh_key_type {
-    'ssh-rsa','rsa': {
-      $key = $::sshrsakey
-    }
-    'ssh-dsa','dsa': {
-      $key = $::sshdsakey
-    }
-    'ecdsa-sha2-nistp256': {
-          $key = $::sshecdsakey
-    }
-    default: {
-      fail("ssh::ssh_key_type must be 'ecdsa-sha2-nistp256', 'ssh-rsa', 'rsa', 'ssh-dsa', or 'dsa' and is <${ssh_key_type}>.")
-    }
-  }
-
-  validate_absolute_path($ssh_config_global_known_hosts_file)
-  $ssh_config_global_known_hosts_file_real = any2array($ssh_config_global_known_hosts_file)
-
-  if $ssh_config_global_known_hosts_list != undef {
-    validate_array($ssh_config_global_known_hosts_list)
-    validate_absolute_path($ssh_config_global_known_hosts_list)
-    $ssh_config_global_known_hosts_list_real = concat($ssh_config_global_known_hosts_file_real, $ssh_config_global_known_hosts_list)
-  } else {
-    $ssh_config_global_known_hosts_list_real = $ssh_config_global_known_hosts_file_real
-  }
-
-  if $ssh_config_user_known_hosts_file != undef {
-    validate_array($ssh_config_user_known_hosts_file)
-  }
-
-  validate_string($ssh_config_global_known_hosts_owner)
-  validate_string($ssh_config_global_known_hosts_group)
-  validate_re($ssh_config_global_known_hosts_mode, '^[0-7]{4}$',
-    "ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation. Detected value is <${ssh_config_global_known_hosts_mode}>.")
-
-  if type3x($purge_keys) == 'string' {
-    $purge_keys_real = str2bool($purge_keys)
-  } else {
-    $purge_keys_real = $purge_keys
-  }
-  validate_bool($purge_keys_real)
-
-  if type3x($manage_service) == 'string' {
-    $manage_service_real = str2bool($manage_service)
-  } else {
-    $manage_service_real = $manage_service
-  }
-  validate_bool($manage_service_real)
-
-  if type3x($service_enable) == 'string' {
-    $service_enable_real = str2bool($service_enable)
-  } else {
-    $service_enable_real = $service_enable
-  }
-  validate_bool($service_enable_real)
-
-  if type3x($service_hasrestart) == 'string' {
-    $service_hasrestart_real = str2bool($service_hasrestart)
-  } else {
-    $service_hasrestart_real = $service_hasrestart
-  }
-  validate_bool($service_hasrestart_real)
-
-  if type3x($manage_root_ssh_config) == 'string' {
-    $manage_root_ssh_config_real = str2bool($manage_root_ssh_config)
-  } else {
-    $manage_root_ssh_config_real = $manage_root_ssh_config
-  }
-  validate_bool($manage_root_ssh_config_real)
-
-  #ssh_config template
-  validate_string($ssh_config_template)
-
-  #sshd_config template
-  validate_string($sshd_config_template)
-
-  #loglevel
-  $supported_loglevel_vals=['QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE']
-  validate_re($sshd_config_loglevel, $supported_loglevel_vals)
-
-  #enable hiera merging for groups, users, and config_entries
-  if $hiera_merge_real == true {
-    $sshd_config_allowgroups_real = hiera_array('ssh::sshd_config_allowgroups',[])
-    $sshd_config_allowusers_real  = hiera_array('ssh::sshd_config_allowusers',[])
-    $sshd_config_denygroups_real  = hiera_array('ssh::sshd_config_denygroups',[])
-    $sshd_config_denyusers_real   = hiera_array('ssh::sshd_config_denyusers',[])
-    $config_entries_real          = hiera_hash('ssh::config_entries',{})
-  } else {
-    $sshd_config_allowgroups_real = $sshd_config_allowgroups
-    $sshd_config_allowusers_real  = $sshd_config_allowusers
-    $sshd_config_denygroups_real  = $sshd_config_denygroups
-    $sshd_config_denyusers_real   = $sshd_config_denyusers
-    $config_entries_real          = $config_entries
-  }
-  validate_hash($config_entries_real)
-
-  if $sshd_config_denyusers_real != [] {
-    validate_array($sshd_config_denyusers_real)
-  }
-
-  if $sshd_config_denygroups_real != [] {
-    validate_array($sshd_config_denygroups_real)
-  }
-
-  if $sshd_config_allowusers_real != [] {
-    validate_array($sshd_config_allowusers_real)
-  }
-
-  if $sshd_config_allowgroups_real != [] {
-    validate_array($sshd_config_allowgroups_real)
-  }
-
-
-  if $sshd_config_tcp_keepalive_real != undef {
-    validate_re($sshd_config_tcp_keepalive_real, '^(yes|no)$', "ssh::sshd_config_tcp_keepalive may be either 'yes', 'no' or 'unset' and is set to <${sshd_config_tcp_keepalive_real}>.")
-  }
-
-  if $sshd_config_use_privilege_separation != undef {
-    validate_re($sshd_config_use_privilege_separation, '^(yes|no|sandbox)$', "ssh::sshd_config_use_privilege_separation may be either 'yes', 'no' or 'sandbox' and is set to <${sshd_config_use_privilege_separation}>.")
-  }
-
-  if $sshd_config_permittunnel_real != undef {
-    validate_re($sshd_config_permittunnel_real, '^(yes|no|point-to-point|ethernet|unset)$', "ssh::sshd_config_permittunnel may be either 'yes', 'point-to-point', 'ethernet', 'no' or 'unset' and is set to <${sshd_config_permittunnel_real}>.")
-  }
-
-  if $sshd_config_hostcertificate_real != undef {
-    if is_array($sshd_config_hostcertificate_real) {
-      validate_array($sshd_config_hostcertificate_real)
-    }
-    validate_absolute_path($sshd_config_hostcertificate_real)
-  }
-
-  if $sshd_config_trustedusercakeys_real != undef {
-    # TrustedUserCAKeys may be a path to the keys or 'none'
-    if $sshd_config_trustedusercakeys_real != 'none' {
-      validate_absolute_path($sshd_config_trustedusercakeys_real)
-    }
-  }
-  if $sshd_config_key_revocation_list_real != undef {
-    # RevokedKeys may be a path to the key revocation list or 'none'
-    if $sshd_config_key_revocation_list_real != 'none' {
-      validate_absolute_path($sshd_config_key_revocation_list)
-    }
-  }
-
-  if $sshd_config_authorized_principals_file_real != undef {
-    validate_string($sshd_config_authorized_principals_file_real)
-  }
-
-  if $sshd_config_allowagentforwarding != undef {
-    validate_re($sshd_config_allowagentforwarding, '^(yes|no)$', "ssh::sshd_config_allowagentforwarding may be either 'yes' or 'no' and is set to <${sshd_config_allowagentforwarding}>.")
-  }
-
-  package { $packages_real:
+  package { $packages:
     ensure    => installed,
-    source    => $ssh_package_source_real,
-    adminfile => $ssh_package_adminfile_real,
+    source    => $package_source,
+    adminfile => $package_adminfile,
   }
 
   file  { 'ssh_config' :
     ensure  => file,
-    path    => $ssh_config_path,
-    owner   => $ssh_config_owner,
-    group   => $ssh_config_group,
-    mode    => $ssh_config_mode,
-    content => template($ssh_config_template),
-    require => Package[$packages_real],
+    path    => $config_path,
+    owner   => $config_owner,
+    group   => $config_group,
+    mode    => $config_mode,
+    content => template('ssh/ssh_config.erb'),
+    require => Package[$packages],
   }
 
-  file  { 'sshd_config' :
-    ensure  => file,
-    path    => $sshd_config_path,
-    mode    => $sshd_config_mode_real,
-    owner   => $sshd_config_owner,
-    group   => $sshd_config_group,
-    content => template($sshd_config_template),
-    require => Package[$packages_real],
-  }
+  if $manage_root_ssh_config == true {
 
-  if $sshd_config_banner != 'none' and $sshd_banner_content != undef {
-    file { 'sshd_banner' :
-      ensure  => file,
-      path    => $sshd_config_banner,
-      owner   => $sshd_banner_owner,
-      group   => $sshd_banner_group,
-      mode    => $sshd_banner_mode,
-      content => $sshd_banner_content,
-      require => Package[$packages_real],
+    exec { "mkdir_p-${::root_home}/.ssh":
+      command => "mkdir -p ${::root_home}/.ssh",
+      unless  => "test -d ${::root_home}/.ssh",
+      path    => '/bin:/usr/bin',
     }
-  }
-
-  if $manage_root_ssh_config_real == true {
-
-    include ::common
-
-    common::mkdir_p { "${::root_home}/.ssh": }
 
     file { 'root_ssh_dir':
       ensure  => directory,
@@ -1045,7 +623,7 @@
       owner   => 'root',
       group   => 'root',
       mode    => '0700',
-      require => Common::Mkdir_p["${::root_home}/.ssh"],
+      require => Exec["mkdir_p-${::root_home}/.ssh"],
     }
 
     file { 'root_ssh_config':
@@ -1058,25 +636,6 @@
     }
   }
 
-  if $manage_service_real {
-    service { 'sshd_service' :
-      ensure     => $service_ensure,
-      name       => $service_name_real,
-      enable     => $service_enable_real,
-      hasrestart => $service_hasrestart_real,
-      hasstatus  => $service_hasstatus_real,
-      subscribe  => File['sshd_config'],
-    }
-  }
-
-  if $manage_firewall == true {
-    firewall { '22 open port 22 for SSH':
-      action => 'accept',
-      dport  => 22,
-      proto  => 'tcp',
-    }
-  }
-
   # If either IPv4 or IPv6 stack is not configured on the agent, the
   # corresponding $::ipaddress(6)? fact is not present. So, we cannot assume
   # these variables are defined. Getvar (Stdlib 4.13+, ruby 1.8.7+) handles
@@ -1086,55 +645,57 @@
   else { $host_aliases = [$::hostname, $::ipaddress] }
 
   # export each node's ssh key
-  @@sshkey { $::fqdn :
-    ensure       => $ssh_key_ensure,
-    host_aliases => $host_aliases,
-    type         => $ssh_key_type,
-    key          => $key,
+  if $key_export == true {
+    # ssh_key_type might start with 'ssh-' though facter stores them without
+    # the 'ssh-' prefix.
+    #$key_type = delete_regex($ssh_key_type, '^ssh-')
+    $key_type = 'rsa'
+    @@sshkey { $::fqdn :
+      ensure       => $ssh_key_ensure,
+      host_aliases => $host_aliases,
+      type         => $ssh_key_type,
+      key          => $facts['ssh'][$key_type]['key'],
+    }
   }
 
   file { 'ssh_known_hosts':
     ensure  => file,
-    path    => $ssh_config_global_known_hosts_file,
-    owner   => $ssh_config_global_known_hosts_owner,
-    group   => $ssh_config_global_known_hosts_group,
-    mode    => $ssh_config_global_known_hosts_mode,
-    require => Package[$packages_real],
+    path    => $global_known_hosts,
+    owner   => $global_known_hosts_owner,
+    group   => $global_known_hosts_group,
+    mode    => $global_known_hosts_mode,
+    require => Package[$packages],
   }
 
   # import all nodes' ssh keys
-  if $ssh_key_import_real == true {
+  if $ssh_key_import == true {
     Sshkey <<||>> {
-      target => $ssh_config_global_known_hosts_file,
+      target => $global_known_hosts,
     }
   }
 
   # remove ssh key's not managed by puppet
   resources  { 'sshkey':
-    purge => $purge_keys_real,
+    purge => $purge_keys,
   }
 
   # manage users' ssh config entries if present
-  create_resources('ssh::config_entry',$config_entries_real)
-
-  # manage users' ssh authorized keys if present
-  if $keys != undef {
-    if $hiera_merge_real == true {
-      $keys_real = hiera_hash('ssh::keys')
-    } else {
-      $keys_real = $keys
-      notice('Future versions of the ssh module will default ssh::hiera_merge_real to true')
+  $config_entries.each |$key,$value| {
+    ssh::config_entry { $key:
+      * => $value,
     }
-    validate_hash($keys_real)
-    create_resources('ssh_authorized_key', $keys_real)
   }
 
-  if $sshd_addressfamily_real != undef {
-    if $::osfamily == 'Solaris' {
-      fail("ssh::sshd_addressfamily is not supported on Solaris and is set to <${sshd_addressfamily}>.")
-    } else {
-      validate_re($sshd_addressfamily_real, '^(any|inet|inet6)$',
-        "ssh::sshd_addressfamily can be undef, 'any', 'inet' or 'inet6' and is set to ${sshd_addressfamily_real}.")
+  # manage users' ssh authorized keys if present
+  if $keys.empty == false {
+    $keys.each |$key,$value| {
+      ssh_authorized_key { $key:
+        * => $value,
+      }
     }
   }
+
+  if $manage_server == true {
+    include ssh::server
+  }
 }
diff --git a/manifests/server.pp b/manifests/server.pp
new file mode 100644
index 0000000..5d7b3bc
--- /dev/null
+++ b/manifests/server.pp
@@ -0,0 +1,536 @@
+# @summary Class to manage SSH server
+#
+# Notes: `Match` attribute is not directly supported as multiple match blocks can
+# exist. Use the `custom` parameter for that.
+#
+# @param packages
+#
+# @param package_source
+#
+# @param package_adminfile
+#
+# @param config_path
+#
+# @param config_owner
+#
+# @param config_group
+#
+# @param config_mode
+#
+# @param banner_path
+#
+# @param banner_content
+#
+# @param banner_owner
+#
+# @param banner_group
+#
+# @param banner_mode
+#
+# @param manage_service
+#
+# @param service_ensure
+#
+# @param service_name
+#
+# @param service_enable
+#
+# @param service_hasrestart
+#
+# @param service_hasstatus
+#
+# @param accept_env
+#
+# @param address_family
+#
+# @param allow_agent_forwarding
+#
+# @param allow_groups
+#
+# @param allow_stream_local_forwarding
+#
+# @param allow_tcp_forwarding
+#
+# @param allow_users
+#
+# @param authentication_methods
+#
+# @param authorized_keys_command
+#
+# @param authorized_keys_command_user
+#
+# @param authorized_keys_file
+#
+# @param authorized_principals_command
+#
+# @param authorized_principals_command_user
+#
+# @param authorized_principals_file
+#
+# @param banner
+#
+# @param ca_signature_algorithms
+#
+# @param challenge_response_authentication
+#
+# @param chroot_directory
+#
+# @param ciphers
+#
+# @param client_alive_count_max
+#
+# @param client_alive_interval
+#
+# @param compression
+#
+# @param deny_groups
+#
+# @param deny_users
+#
+# @param disable_forwarding
+#
+# @param expose_auth_info
+#
+# @param fingerprint_hash
+#
+# @param force_command
+#
+# @param gateway_ports
+#
+# @param gss_api_authentication
+#
+# @param gss_api_cleanup_credentials
+#
+# @param gss_api_strict_acceptor_check
+#
+# @param hostbased_accepted_key_types
+#
+# @param hostbased_authentication
+#
+# @param hostbased_uses_name_from_packet_only
+#
+# @param host_certificate
+#
+# @param host_key
+#
+# @param host_key_agent
+#
+# @param host_key_algorithms
+#
+# @param ignore_rhosts
+#
+# @param ignore_user_known_hosts
+#
+# @param ip_qos
+#
+# @param kbd_interactive_authentication
+#
+# @param kerberos_authentication
+#
+# @param kerberos_get_afs_token
+#
+# @param kerberos_or_local_passwd
+#
+# @param kerberos_ticket_cleanup
+#
+# @param kex_algorithms
+#
+# @param listen_address
+#
+# @param login_grace_time
+#
+# @param log_level
+#
+# @param macs
+#
+# @param max_auth_tries
+#
+# @param max_sessions
+#
+# @param max_startups
+#
+# @param password_authentication
+#
+# @param permit_empty_passwords
+#
+# @param permit_listen
+#
+# @param permit_root_login
+#
+# @param permit_tty
+#
+# @param permit_tunnel
+#
+# @param permit_user_environment
+#
+# @param permit_user_rc
+#
+# @param pid_file
+#
+# @param port
+#
+# @param print_last_log
+#
+# @param print_motd
+#
+# @param pubkey_accepted_key_types
+#
+# @param pubkey_authentication
+#
+# @param rekey_limit
+#
+# @param revoked_keys
+#
+# @param rdomain
+#
+# @param set_env
+#
+# @param stream_local_bind_mask
+#
+# @param stream_local_bind_unlink
+#
+# @param strict_modes
+#
+# @param subsystem
+#
+# @param syslog_facility
+#
+# @param tcp_keep_alive
+#
+# @param trusted_user_ca_keys
+#
+# @param use_dns
+#
+# @param use_pam
+#
+# @param version_addendum
+#
+# @param x11_display_offset
+#
+# @param x11_forwarding
+#
+# @param x11_use_localhost
+#
+# @param xauth_location
+#
+# @param custom
+#
+class ssh::server (
+  Variant[String[1], Array[String[1]]] $packages = 'openssh-server',
+  Optional[Stdlib::Absolutepath] $package_source = undef,
+  Optional[Stdlib::Absolutepath] $package_adminfile = undef,
+  Stdlib::Absolutepath $config_path = '/etc/ssh/sshd_config',
+  String[1] $config_owner = 'root',
+  String[1] $config_group = 'root',
+  Stdlib::Filemode $config_mode = '0600',
+  Stdlib::Absolutepath $banner_path = '/etc/sshd_banner',
+  Optional[String[1]] $banner_content = undef,
+  String[1] $banner_owner = 'root',
+  String[1] $banner_group = 'root',
+  Stdlib::Filemode $banner_mode = '0644',
+  Boolean $manage_service = true,
+  Stdlib::Ensure::Service $service_ensure = 'running',
+  String[1] $service_name = 'sshd',
+  Boolean $service_enable = true,
+  Boolean $service_hasrestart = true,
+  Boolean $service_hasstatus = true,
+  # all paramters below this line are for sshd_config
+  Optional[Array[String[1]]] $accept_env = undef,
+  Optional[Enum['any', 'inet', 'inet6']] $address_family = undef,
+  Optional[Ssh::Yes_no] $allow_agent_forwarding = undef,
+  Variant[Undef, String[1], Array[String[1]]] $allow_groups = undef,
+  Optional[Enum['yes', 'all', 'no', 'local', 'remote']] $allow_stream_local_forwarding = undef,
+  Optional[Enum['yes', 'no', 'local', 'remote']] $allow_tcp_forwarding = undef,
+  Variant[Undef, String[1], Array[String[1]]] $allow_users = undef,
+  Optional[Array[String[1]]] $authentication_methods = undef,
+  Optional[String[1]] $authorized_keys_command = undef,
+  Optional[String[1]] $authorized_keys_command_user = undef,
+  Variant[Undef, String[1], Array[String[1]]] $authorized_keys_file = undef,
+  Optional[String[1]] $authorized_principals_command = undef,
+  Optional[String[1]] $authorized_principals_command_user = undef,
+  Optional[String[1]] $authorized_principals_file = undef,
+  Optional[String[1]] $banner = undef,
+  Optional[Array[String[1]]] $ca_signature_algorithms = undef,
+  Optional[String[1]] $challenge_response_authentication = undef,
+  Optional[String[1]] $chroot_directory = undef,
+  Optional[Array[String[1]]] $ciphers = undef,
+  Optional[Integer[0]] $client_alive_count_max = undef,
+  Optional[Integer[0]] $client_alive_interval = undef,
+  Optional[Enum['yes', 'delayed', 'no']] $compression = undef,
+  Variant[Undef, String[1], Array[String[1]]] $deny_groups = undef,
+  Variant[Undef, String[1], Array[String[1]]] $deny_users = undef,
+  Optional[Ssh::Yes_no] $disable_forwarding = undef,
+  Optional[Ssh::Yes_no] $expose_auth_info = undef,
+  Optional[Enum['md5', 'sha256']] $fingerprint_hash = undef,
+  Optional[String[1]] $force_command = undef,
+  Optional[Enum['no', 'yes', 'clientspecified']] $gateway_ports = undef,
+  Optional[Ssh::Yes_no] $gss_api_authentication = undef,
+  Optional[Ssh::Yes_no] $gss_api_cleanup_credentials = undef,
+  Optional[Ssh::Yes_no] $gss_api_strict_acceptor_check = undef,
+  Optional[Array[String[1]]] $hostbased_accepted_key_types = undef,
+  Optional[Ssh::Yes_no] $hostbased_authentication = undef,
+  Optional[Ssh::Yes_no] $hostbased_uses_name_from_packet_only = undef,
+  Optional[String[1]] $host_certificate = undef,
+  Optional[Array[String[1]]] $host_key = undef,
+  Optional[String[1]] $host_key_agent = undef,
+  Optional[Array[String[1]]] $host_key_algorithms = undef,
+  Optional[Ssh::Yes_no] $ignore_rhosts = undef,
+  Optional[Ssh::Yes_no] $ignore_user_known_hosts = undef,
+  Optional[String[1]] $ip_qos = undef,
+  Optional[Ssh::Yes_no] $kbd_interactive_authentication = undef,
+  Optional[Ssh::Yes_no] $kerberos_authentication = undef,
+  Optional[Ssh::Yes_no] $kerberos_get_afs_token = undef,
+  Optional[Ssh::Yes_no] $kerberos_or_local_passwd = undef,
+  Optional[Ssh::Yes_no] $kerberos_ticket_cleanup = undef,
+  Optional[Array[String[1]]] $kex_algorithms = undef,
+  Optional[Array[String[1]]] $listen_address = undef,
+  Optional[Integer[0]] $login_grace_time = undef,
+  Optional[Ssh::Log_level] $log_level = undef,
+  Optional[Array[String[1]]] $macs = undef,
+  Optional[Integer[2]] $max_auth_tries = undef,
+  Optional[Integer[0]] $max_sessions = undef,
+  Optional[String[1]] $max_startups = undef,
+  Optional[Ssh::Yes_no] $password_authentication = undef,
+  Optional[Ssh::Yes_no] $permit_empty_passwords = undef,
+  Variant[Undef, String[1], Array[String[1]]] $permit_listen = undef,
+  Optional[Ssh::Permit_root_login] $permit_root_login = undef,
+  Optional[Ssh::Yes_no] $permit_tty = undef,
+  Optional[Enum['yes', 'point-to-point', 'ethernet', 'no']] $permit_tunnel = undef,
+  Optional[String[1]] $permit_user_environment = undef,
+  Optional[Ssh::Yes_no] $permit_user_rc = undef,
+  Optional[String[1]] $pid_file = undef,
+  Optional[Stdlib::Port] $port = undef, #TODO, this can be specified multiple times
+  Optional[Ssh::Yes_no] $print_last_log = undef,
+  Optional[Ssh::Yes_no] $print_motd = undef,
+  Optional[Array[String[1]]] $pubkey_accepted_key_types = undef,
+  Optional[Ssh::Yes_no] $pubkey_authentication = undef,
+  Optional[String[1]] $rekey_limit = undef,
+  Optional[String[1]] $revoked_keys = undef,
+  Optional[String[1]] $rdomain = undef,
+  Optional[String[1]] $set_env = undef,
+  Optional[Pattern[/^[0-7]{4}$/]] $stream_local_bind_mask = undef,
+  Optional[Ssh::Yes_no] $stream_local_bind_unlink = undef,
+  Optional[Ssh::Yes_no] $strict_modes = undef,
+  Optional[String[1]] $subsystem = undef,
+  Optional[Ssh::Syslog_facility] $syslog_facility = undef,
+  Optional[Ssh::Yes_no] $tcp_keep_alive = undef,
+  Optional[String[1]] $trusted_user_ca_keys = undef,
+  Optional[Ssh::Yes_no] $use_dns = undef,
+  Optional[Ssh::Yes_no] $use_pam = undef,
+  Optional[String[1]] $version_addendum = undef,
+  Optional[Integer[0]] $x11_display_offset = undef,
+  Optional[Ssh::Yes_no] $x11_forwarding = undef,
+  Optional[Ssh::Yes_no] $x11_use_localhost = undef,
+  Optional[String[1]] $xauth_location = undef,
+  # custom is a string that allows for multiple lines to be appended to end of
+  # the sshd_config file.
+  Optional[String[1]] $custom = undef,
+) {
+
+#  if $authorized_keys_command_user != undef and $authorized_keys_command == undef {
+#    fail("If AuthorizedKeysCommand is specified but AuthorizedKeysCommandUser is not, then sshd(8) will refuse to start. authorized_keys_command_user = <${authorized_keys_command_user}> and authorized_keys_command = <${authorized_keys_command}>")
+#  }
+#
+#  if $authorized_principals_command_user != undef and $authorized_principals_command == undef {
+#    fail("If AuthorizedPrincipalsCommand is specified but AuthorizedPrincipalsCommandUser is not, then sshd(8) will refuse to start. authorized_principals_command_user = <${authorized_principals_command_user}> and authorized_principals_command = <${authorized_principals_command}>")
+#  }
+
+# TODO: This huge case statement is getting transitioned to hiera
+  case $facts['os']['family'] {
+    'RedHat': {}
+    'Suse': {
+      $default_packages                        = 'openssh'
+      $default_service_name                    = 'sshd'
+      $default_ssh_config_hash_known_hosts     = 'no'
+      $default_ssh_package_source              = undef
+      $default_ssh_package_adminfile           = undef
+      $default_ssh_sendenv                     = true
+      $default_ssh_config_forward_x11_trusted  = 'yes'
+      $default_sshd_config_mode                = '0600'
+      $default_sshd_config_use_dns             = 'yes'
+      $default_sshd_config_xauth_location      = '/usr/bin/xauth'
+      $default_sshd_use_pam                    = 'yes'
+      $default_sshd_gssapikeyexchange          = undef
+      $default_sshd_pamauthenticationviakbdint = undef
+      $default_sshd_gssapicleanupcredentials   = 'yes'
+      $default_sshd_acceptenv                  = true
+      $default_service_hasstatus               = true
+      $default_sshd_config_serverkeybits       = '1024'
+      $default_sshd_config_hostkey             = [ '/etc/ssh/ssh_host_rsa_key' ]
+      $default_sshd_addressfamily              = 'any'
+      $default_sshd_config_tcp_keepalive       = 'yes'
+      $default_sshd_config_permittunnel        = 'no'
+      case $::architecture {
+        'x86_64': {
+          if ($::operatingsystem == 'SLES') and ($::operatingsystemrelease =~ /^12\./) {
+            $default_sshd_config_subsystem_sftp = '/usr/lib/ssh/sftp-server'
+          } else {
+            $default_sshd_config_subsystem_sftp = '/usr/lib64/ssh/sftp-server'
+          }
+        }
+        'i386' : {
+          $default_sshd_config_subsystem_sftp = '/usr/lib/ssh/sftp-server'
+      }
+        default: {
+          fail("ssh supports architectures x86_64 and i386 for Suse. Detected architecture is <${::architecture}>.")
+        }
+      }
+    }
+    'Debian': {
+      # Ubuntu 16.04
+      if $::operatingsystemrelease == '16.04' {
+        $default_sshd_config_hostkey             = [
+          '/etc/ssh/ssh_host_rsa_key',
+          '/etc/ssh/ssh_host_dsa_key',
+          '/etc/ssh/ssh_host_ecdsa_key',
+          '/etc/ssh/ssh_host_ed25519_key',
+        ]
+        $default_ssh_config_hash_known_hosts     = 'yes'
+        $default_sshd_config_xauth_location      = undef
+      } else {
+        $default_sshd_config_hostkey             = [ '/etc/ssh/ssh_host_rsa_key' ]
+        $default_ssh_config_hash_known_hosts     = 'no'
+        $default_sshd_config_xauth_location      = '/usr/bin/xauth'
+      }
+      $default_packages                        = ['openssh-server',
+                                                  'openssh-client']
+      $default_service_name                    = 'ssh'
+      $default_ssh_config_forward_x11_trusted  = 'yes'
+      $default_ssh_package_source              = undef
+      $default_ssh_package_adminfile           = undef
+      $default_ssh_sendenv                     = true
+      $default_sshd_config_subsystem_sftp      = '/usr/lib/openssh/sftp-server'
+      $default_sshd_config_mode                = '0600'
+      $default_sshd_config_use_dns             = 'yes'
+      $default_sshd_use_pam                    = 'yes'
+      $default_sshd_gssapikeyexchange          = undef
+      $default_sshd_pamauthenticationviakbdint = undef
+      $default_sshd_gssapicleanupcredentials   = 'yes'
+      $default_sshd_acceptenv                  = true
+      $default_service_hasstatus               = true
+      $default_sshd_config_serverkeybits       = '1024'
+      $default_sshd_addressfamily              = 'any'
+      $default_sshd_config_tcp_keepalive       = 'yes'
+      $default_sshd_config_permittunnel        = 'no'
+    }
+    'Solaris': {
+      $default_ssh_config_hash_known_hosts     = undef
+      $default_ssh_sendenv                     = false
+      $default_ssh_config_forward_x11_trusted  = undef
+      $default_sshd_config_subsystem_sftp      = '/usr/lib/ssh/sftp-server'
+      $default_sshd_config_mode                = '0644'
+      $default_sshd_config_use_dns             = undef
+      $default_sshd_config_xauth_location      = '/usr/openwin/bin/xauth'
+      $default_sshd_use_pam                    = undef
+      $default_sshd_gssapikeyexchange          = 'yes'
+      $default_sshd_pamauthenticationviakbdint = 'yes'
+      $default_sshd_gssapicleanupcredentials   = undef
+      $default_sshd_acceptenv                  = false
+      $default_sshd_config_serverkeybits       = '768'
+      $default_ssh_package_adminfile           = undef
+      $default_sshd_config_hostkey             = [ '/etc/ssh/ssh_host_rsa_key' ]
+      $default_sshd_addressfamily              = undef
+      $default_sshd_config_tcp_keepalive       = undef
+      $default_sshd_config_permittunnel        = undef
+      case $::kernelrelease {
+        '5.11': {
+          $default_packages                      = ['network/ssh',
+                                                    'network/ssh/ssh-key',
+                                                    'service/network/ssh']
+          $default_service_name                  = 'ssh'
+          $default_service_hasstatus             = true
+          $default_ssh_package_source            = undef
+        }
+        '5.10': {
+          $default_packages                      = ['SUNWsshcu',
+                                                    'SUNWsshdr',
+                                                    'SUNWsshdu',
+                                                    'SUNWsshr',
+                                                    'SUNWsshu']
+          $default_service_name                  = 'ssh'
+          $default_service_hasstatus             = true
+          $default_ssh_package_source            = '/var/spool/pkg'
+        }
+        '5.9' : {
+          $default_packages                      = ['SUNWsshcu',
+                                                    'SUNWsshdr',
+                                                    'SUNWsshdu',
+                                                    'SUNWsshr',
+                                                    'SUNWsshu']
+          $default_service_name                  = 'sshd'
+          $default_service_hasstatus             = false
+          $default_ssh_package_source            = '/var/spool/pkg'
+        }
+        default: {
+          fail('ssh module supports Solaris kernel release 5.9, 5.10 and 5.11.')
+        }
+      }
+    }
+    default: {
+      fail("ssh supports osfamilies RedHat, Suse, Debian and Solaris. Detected os.family is <${facts['os']['family']}>.")
+    }
+  }
+
+  if "${::ssh_version}" =~ /^OpenSSH/  { # lint:ignore:only_variable_string
+    $ssh_version_array = split($::ssh_version_numeric, '\.')
+    $ssh_version_maj_int = 0 + $ssh_version_array[0]
+    $ssh_version_min_int = 0 + $ssh_version_array[1]
+    if $ssh_version_maj_int > 5 {
+      $default_ssh_config_use_roaming = 'no'
+    } elsif $ssh_version_maj_int == 5 and $ssh_version_min_int >= 4 {
+      $default_ssh_config_use_roaming = 'no'
+    } else {
+      $default_ssh_config_use_roaming = 'unset'
+    }
+  } else {
+      $default_ssh_config_use_roaming = 'unset'
+  }
+
+  package { $packages:
+    ensure    => installed,
+    source    => $package_source,
+    adminfile => $package_adminfile,
+  }
+
+  file  { 'sshd_config' :
+    ensure  => file,
+    path    => $config_path,
+    mode    => $config_mode,
+    owner   => $config_owner,
+    group   => $config_group,
+    content => template('ssh/sshd_config.erb'),
+    require => Package[$packages],
+  }
+
+  if $banner_content != undef {
+    file { 'sshd_banner' :
+      ensure  => file,
+      path    => $banner_path,
+      owner   => $banner_owner,
+      group   => $banner_group,
+      mode    => $banner_mode,
+      content => $banner_content,
+      require => Package[$packages],
+    }
+  }
+
+  if $manage_service {
+    service { 'sshd_service' :
+      ensure     => $service_ensure,
+      name       => $service_name,
+      enable     => $service_enable,
+      hasrestart => $service_hasrestart,
+      hasstatus  => $service_hasstatus,
+      subscribe  => File['sshd_config'],
+    }
+  }
+
+  # TODO: remove and document that the code will not check these types of
+  # things. It introduces too much complexity here and in the testing. Anyone
+  # using this would test their own custom options to ensure they work anyhow.
+  if $address_family != undef {
+    if $facts['os']['family'] == 'Solaris' {
+      fail("address_family is not supported on Solaris and is set to <${address_family}>.")
+    }
+  }
+}
diff --git a/metadata.json b/metadata.json
index 3ca9272..e7857e3 100644
--- a/metadata.json
+++ b/metadata.json
@@ -1,6 +1,6 @@
 {
   "name": "ghoneycutt-ssh",
-  "version": "3.61.0",
+  "version": "4.0.0",
   "author": "ghoneycutt",
   "summary": "Manages SSH",
   "license": "Apache-2.0",
@@ -10,7 +10,7 @@
   "requirements": [
     {
       "name": "puppet",
-      "version_requirement": ">= 3.8.7 < 7.0.0"
+      "version_requirement": ">= 5.5.10 < 7.0.0"
     }
   ],
   "operatingsystem_support": [
@@ -25,7 +25,6 @@
     {
       "operatingsystem": "RedHat",
       "operatingsystemrelease": [
-        "5",
         "6",
         "7"
       ]
@@ -33,7 +32,6 @@
     {
       "operatingsystem": "CentOS",
       "operatingsystemrelease": [
-        "5",
         "6",
         "7"
       ]
@@ -41,7 +39,6 @@
     {
       "operatingsystem": "OracleLinux",
       "operatingsystemrelease": [
-        "5",
         "6",
         "7"
       ]
@@ -49,7 +46,6 @@
     {
       "operatingsystem": "Scientific",
       "operatingsystemrelease": [
-        "5",
         "6",
         "7"
       ]
@@ -90,10 +86,8 @@
   ],
   "description": "Manage SSH",
   "dependencies": [
-    {"name":"puppetlabs/stdlib","version_requirement":">= 4.6.0 < 6.0.0"},
-    {"name":"puppetlabs/concat","version_requirement":">= 2.0.0 < 6.0.0"},
-    {"name":"ghoneycutt/common","version_requirement":">= 1.4.1 < 2.0.0"},
-    {"name":"puppetlabs/firewall","version_requirement":">= 1.9.0 < 2.0.0"},
-    {"name":"puppetlabs/sshkeys_core","version_requirement":">= 1.0.1 <2.0.0"}
+    {"name":"puppetlabs/stdlib","version_requirement":">= 5.2.0 < 6.0.0"},
+    {"name":"puppetlabs/concat","version_requirement":">= 5.2.0 < 6.0.0"},
+    {"name":"puppetlabs/sshkeys_core","version_requirement":">= 1.0.2 < 2.0.0"}
   ]
 }
diff --git a/spec/acceptance/nodesets/centos-6.yml b/spec/acceptance/nodesets/centos-6.yml
new file mode 100644
index 0000000..dbafe0c
--- /dev/null
+++ b/spec/acceptance/nodesets/centos-6.yml
@@ -0,0 +1,20 @@
+HOSTS:
+  centos-6:
+    roles:
+      - agent
+    platform: el-6-x86_64
+    hypervisor: docker
+    image: centos:6
+    docker_preserve_image: true
+    docker_cmd:
+      - '/sbin/init'
+    docker_image_commands:
+      - 'yum install -y tar wget cronie git'
+    docker_container_name: 'ssh-el6'
+CONFIG:
+  log_level: debug
+  type: foss
+ssh:
+  password: root
+  auth_methods: ["password"]
+
diff --git a/spec/acceptance/nodesets/centos-7.yml b/spec/acceptance/nodesets/centos-7.yml
new file mode 100644
index 0000000..983b909
--- /dev/null
+++ b/spec/acceptance/nodesets/centos-7.yml
@@ -0,0 +1,20 @@
+HOSTS:
+  centos-7:
+    roles:
+      - agent
+    platform: el-7-x86_64
+    hypervisor: docker
+    image: centos:7
+    docker_preserve_image: true
+    docker_cmd:
+      - '/usr/sbin/init'
+    docker_image_commands:
+      - 'yum install -y tar wget cronie git iproute'
+    docker_container_name: 'ssh-el7'
+CONFIG:
+  log_level: debug
+  type: foss
+ssh:
+  password: root
+  auth_methods: ["password"]
+
diff --git a/spec/acceptance/nodesets/debian-8.yml b/spec/acceptance/nodesets/debian-8.yml
new file mode 100644
index 0000000..d6c5b87
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-8.yml
@@ -0,0 +1,25 @@
+HOSTS:
+  debian-8:
+    roles:
+      - agent
+    platform: debian-8-amd64
+    hypervisor: docker
+    image: debian:8
+    docker_preserve_image: true
+    docker_cmd:
+      - '/sbin/init'
+    docker_image_commands:
+      - 'apt-get install -y tar wget cron git net-tools locales'
+      - 'rm -f /usr/sbin/policy-rc.d'
+      - 'echo "LC_ALL=en_US.UTF-8" >> /etc/environment'
+      - 'echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen'
+      - 'echo "LANG=en_US.UTF-8" > /etc/locale.conf'
+      - 'locale-gen en_US.UTF-8'
+    docker_container_name: 'ssh-debian8'
+CONFIG:
+  log_level: debug
+  type: foss
+ssh:
+  password: root
+  auth_methods: ["password"]
+
diff --git a/spec/acceptance/nodesets/debian-9.yml b/spec/acceptance/nodesets/debian-9.yml
new file mode 100644
index 0000000..84ae7f7
--- /dev/null
+++ b/spec/acceptance/nodesets/debian-9.yml
@@ -0,0 +1,24 @@
+HOSTS:
+  debian-9:
+    roles:
+      - agent
+    platform: debian-9-amd64
+    hypervisor: docker
+    image: debian:9
+    docker_preserve_image: true
+    docker_cmd:
+      - '/sbin/init'
+    docker_image_commands:
+      - 'apt-get install -y tar wget cron git net-tools systemd-sysv locales'
+      - 'echo "LC_ALL=en_US.UTF-8" >> /etc/environment'
+      - 'echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen'
+      - 'echo "LANG=en_US.UTF-8" > /etc/locale.conf'
+      - 'locale-gen en_US.UTF-8'
+    docker_container_name: 'ssh-debian9'
+CONFIG:
+  log_level: debug
+  type: foss
+ssh:
+  password: root
+  auth_methods: ["password"]
+
diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml
new file mode 100644
index 0000000..983b909
--- /dev/null
+++ b/spec/acceptance/nodesets/default.yml
@@ -0,0 +1,20 @@
+HOSTS:
+  centos-7:
+    roles:
+      - agent
+    platform: el-7-x86_64
+    hypervisor: docker
+    image: centos:7
+    docker_preserve_image: true
+    docker_cmd:
+      - '/usr/sbin/init'
+    docker_image_commands:
+      - 'yum install -y tar wget cronie git iproute'
+    docker_container_name: 'ssh-el7'
+CONFIG:
+  log_level: debug
+  type: foss
+ssh:
+  password: root
+  auth_methods: ["password"]
+
diff --git a/spec/acceptance/nodesets/ubuntu-1404.yml b/spec/acceptance/nodesets/ubuntu-1404.yml
new file mode 100644
index 0000000..100656e
--- /dev/null
+++ b/spec/acceptance/nodesets/ubuntu-1404.yml
@@ -0,0 +1,21 @@
+HOSTS:
+  ubuntu-1404:
+    roles:
+      - agent
+    platform: ubuntu-14.04-amd64
+    hypervisor : docker
+    image: ubuntu:14.04
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'rm /usr/sbin/policy-rc.d'
+      - 'rm /sbin/initctl; dpkg-divert --rename --remove /sbin/initctl'
+      - 'apt-get install -y -q net-tools wget'
+      - 'locale-gen en_US.UTF-8'
+CONFIG:
+  type: foss
+  log_level: debug
+ssh:
+  password: root
+  auth_methods: ["password"]
+
diff --git a/spec/acceptance/nodesets/ubuntu-1604.yml b/spec/acceptance/nodesets/ubuntu-1604.yml
new file mode 100644
index 0000000..9763af0
--- /dev/null
+++ b/spec/acceptance/nodesets/ubuntu-1604.yml
@@ -0,0 +1,19 @@
+HOSTS:
+  ubuntu-1604:
+    roles:
+      - agent
+    platform: ubuntu-16.04-amd64
+    hypervisor : docker
+    image: ubuntu:16.04
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y -q net-tools wget locales'
+      - 'locale-gen en_US.UTF-8'
+CONFIG:
+  type: foss
+  log_level: debug
+ssh:
+  password: root
+  auth_methods: ["password"]
+
diff --git a/spec/acceptance/nodesets/ubuntu-1804.yml b/spec/acceptance/nodesets/ubuntu-1804.yml
new file mode 100644
index 0000000..030af55
--- /dev/null
+++ b/spec/acceptance/nodesets/ubuntu-1804.yml
@@ -0,0 +1,19 @@
+HOSTS:
+  ubuntu-1804:
+    roles:
+      - agent
+    platform: ubuntu-18.04-amd64
+    hypervisor : docker
+    image: ubuntu:18.04
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y -q net-tools wget locales'
+      - 'locale-gen en_US.UTF-8'
+CONFIG:
+  type: foss
+  log_level: debug
+ssh:
+  password: root
+  auth_methods: ["password"]
+
diff --git a/spec/acceptance/ssh_spec.rb b/spec/acceptance/ssh_spec.rb
new file mode 100644
index 0000000..e05f6cf
--- /dev/null
+++ b/spec/acceptance/ssh_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper_acceptance'
+
+describe 'ssh class' do
+  context 'ssh' do
+    context 'with default values for all parameters' do
+      context 'it should be idempotent' do
+#        if fact('osfamily') == 'Debian' and fact('operatingsystemrelease') == '16.04'
+#          before { skip('Ubuntu 16.04 has a systemd issue that makes setting the service enable not idempotent. Skipping test.') }
+#        end
+
+        it 'should work with no errors' do
+          pp = <<-EOS
+          include ssh
+          EOS
+
+          # Run it twice and test for idempotency
+          apply_manifest(pp, :catch_failures => true)
+          apply_manifest(pp, :catch_changes  => true)
+        end
+      end
+
+      context 'should contain resources' do
+        pp = <<-EOS
+        include ssh
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+
+        describe package('openssh-clients') do
+          it { is_expected.to be_installed }
+        end
+
+        describe service('sshd') do
+          it { is_expected.to be_running }
+          it { is_expected.to be_enabled }
+        end
+      end
+    end
+  end
+end
diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb
index 5ca3914..800d98c 100644
--- a/spec/classes/init_spec.rb
+++ b/spec/classes/init_spec.rb
@@ -6,14 +6,22 @@
     :fqdn                   => 'monkey.example.com',
     :hostname               => 'monkey',
     :ipaddress              => '127.0.0.1',
-    :lsbmajdistrelease      => '6',
-    :operatingsystemrelease => '6.7',
-    :osfamily               => 'RedHat',
+    :os                     => {
+      :family => 'RedHat',
+      :release => {
+        :major => '7',
+      },
+    },
     :root_home              => '/root',
     :specific               => 'dummy',
     :ssh_version            => 'OpenSSH_6.6p1',
     :ssh_version_numeric    => '6.6',
     :sshrsakey              => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==',
+    :ssh => {
+      :rsa => {
+        :key => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1  AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==',
+      }
+    }
   }
 
   default_solaris_facts = {
@@ -27,248 +35,187 @@
     :ssh_version         => 'Sun_SSH_2.2',
     :ssh_version_numeric => '2.2',
     :sshrsakey           => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==',
+    :ssh => {
+      :rsa => {
+        :key => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1  AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==',
+      }
+    }
   }
 
   let(:facts) { default_facts }
 
   osfamily_matrix = {
-    'Debian-7' => {
-      :architecture           => 'x86_64',
-      :osfamily               => 'Debian',
-      :operatingsystemrelease => '7',
-      :ssh_version            => 'OpenSSH_6.0p1',
-      :ssh_version_numeric    => '6.0',
-      :ssh_packages           => ['openssh-server', 'openssh-client'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'ssh',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_debian',
-      :ssh_config_fixture     => 'ssh_config_debian',
-    },
-    'Debian-8' => {
-      :architecture           => 'x86_64',
-      :osfamily               => 'Debian',
-      :operatingsystemrelease => '8',
-      :ssh_version            => 'OpenSSH_6.7p1',
-      :ssh_version_numeric    => '8.11',
-      :ssh_packages           => ['openssh-server', 'openssh-client'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'ssh',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_debian8',
-      :ssh_config_fixture     => 'ssh_config_debian8',
-    },
-    'Debian-9' => {
-      :architecture           => 'x86_64',
-      :osfamily               => 'Debian',
-      :operatingsystemrelease => '9',
-      :ssh_version            => 'OpenSSH_7.4p1',
-      :ssh_version_numeric    => '7.4',
-      :ssh_packages           => ['openssh-server', 'openssh-client'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'ssh',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_debian9',
-      :ssh_config_fixture     => 'ssh_config_debian9',
-    },
+#    'Debian-7' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Debian',
+#      :operatingsystemrelease => '7',
+#      :ssh_version            => 'OpenSSH_6.0p1',
+#      :ssh_version_numeric    => '6.0',
+#      :ssh_packages           => ['openssh-server', 'openssh-client'],
+#      :ssh_config_fixture     => 'ssh_config_debian',
+#    },
+#    'Debian-8' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Debian',
+#      :operatingsystemrelease => '8',
+#      :ssh_version            => 'OpenSSH_6.7p1',
+#      :ssh_version_numeric    => '8.11',
+#      :ssh_packages           => ['openssh-server', 'openssh-client'],
+#      :ssh_config_fixture     => 'ssh_config_debian8',
+#    },
+#    'Debian-9' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Debian',
+#      :operatingsystemrelease => '9',
+#      :ssh_version            => 'OpenSSH_7.4p1',
+#      :ssh_version_numeric    => '7.4',
+#      :ssh_packages           => ['openssh-server', 'openssh-client'],
+#      :ssh_config_fixture     => 'ssh_config_debian9',
+#    },
     'RedHat-5' => {
       :architecture           => 'x86_64',
-      :osfamily               => 'RedHat',
-      :operatingsystemrelease => '5.11',
+      :os                     => {
+        :family => 'RedHat',
+        :release => {
+          :major => '5',
+        },
+      },
       :ssh_version            => 'OpenSSH_4.3p2',
       :ssh_version_numeric    => '4.3',
-      :ssh_packages           => ['openssh-server', 'openssh-clients'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_rhel',
-      :ssh_config_fixture     => 'ssh_config_rhel_old',
+      :ssh_packages           => ['openssh-clients'],
+      :ssh_config_fixture     => 'ssh_config_el5',
     },
-    'RedHat-6' => {
+    'EL-6' => {
       :architecture           => 'x86_64',
-      :osfamily               => 'RedHat',
-      :operatingsystemrelease => '6.7',
+      :os                     => {
+        :family => 'RedHat',
+        :release => {
+          :major => '6',
+        },
+      },
       :ssh_version            => 'OpenSSH_5.3p1',
       :ssh_version_numeric    => '5.3',
-      :ssh_packages           => ['openssh-server', 'openssh-clients'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_rhel',
-      :ssh_config_fixture     => 'ssh_config_rhel_old',
+      :ssh_packages           => ['openssh-clients'],
+      :ssh_config_fixture     => 'ssh_config_el6',
     },
-    'RedHat-7' => {
+    'EL-7' => {
       :architecture           => 'x86_64',
-      :osfamily               => 'RedHat',
-      :operatingsystemrelease => '7.2',
-      :ssh_version            => 'OpenSSH_6.6p1',
-      :ssh_version_numeric    => '6.6',
-      :ssh_packages           => ['openssh-server', 'openssh-clients'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_rhel',
-      :ssh_config_fixture     => 'ssh_config_rhel',
+      :os                     => {
+        :family => 'RedHat',
+        :release => {
+          :major => '7',
+        },
+      },
+      :ssh_version            => 'OpenSSH_7.4p1',
+      :ssh_version_numeric    => '7.4',
+      :ssh_packages           => ['openssh-clients'],
+      :ssh_config_fixture     => 'ssh_config_el7',
     },
-    'RedHat-7.4' => {
-      :architecture           => 'x86_64',
-      :osfamily               => 'RedHat',
-      :operatingsystemrelease => '7.4',
-      :ssh_version            => 'OpenSSH_6.6p1',
-      :ssh_version_numeric    => '6.6',
-      :ssh_packages           => ['openssh-server', 'openssh-clients'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_rhel7',
-      :ssh_config_fixture     => 'ssh_config_rhel',
-    },
-    'Suse-10-x86_64' => {
-      :architecture           => 'x86_64',
-      :osfamily               => 'Suse',
-      :operatingsystem        => 'SLES',
-      :operatingsystemrelease => '10.4',
-      :ssh_version            => 'OpenSSH_5.1p1',
-      :ssh_version_numeric    => '5.1',
-      :ssh_packages           => ['openssh'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_suse_x86_64',
-      :ssh_config_fixture     => 'ssh_config_suse_old',
-    },
-    'Suse-10-i386' => {
-      :architecture           => 'i386',
-      :osfamily               => 'Suse',
-      :operatingsystem        => 'SLES',
-      :operatingsystemrelease => '10.4',
-      :ssh_version            => 'OpenSSH_5.1p1',
-      :ssh_version_numeric    => '5.1',
-      :ssh_packages           => ['openssh'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_suse_i386',
-      :ssh_config_fixture     => 'ssh_config_suse_old',
-    },
-    'Suse-11-x86_64' => {
-      :architecture           => 'x86_64',
-      :osfamily               => 'Suse',
-      :operatingsystem        => 'SLES',
-      :operatingsystemrelease => '11.4',
-      :ssh_version            => 'OpenSSH_6.6.1p1',
-      :ssh_version_numeric    => '6.6',
-      :ssh_packages           => ['openssh'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_suse_x86_64',
-      :ssh_config_fixture     => 'ssh_config_suse',
-    },
-    'Suse-11-i386' => {
-      :architecture           => 'i386',
-      :osfamily               => 'Suse',
-      :operatingsystem        => 'SLES',
-      :operatingsystemrelease => '11.4',
-      :ssh_version            => 'OpenSSH_6.6.1p1',
-      :ssh_version_numeric    => '6.6',
-      :ssh_packages           => ['openssh'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_suse_i386',
-      :ssh_config_fixture     => 'ssh_config_suse',
-    },
-    'Suse-12-x86_64' => {
-      :architecture           => 'x86_64',
-      :osfamily               => 'Suse',
-      :operatingsystem        => 'SLES',
-      :operatingsystemrelease => '12.0',
-      :ssh_version            => 'OpenSSH_6.6.1p1',
-      :ssh_version_numeric    => '6.6',
-      :ssh_packages           => ['openssh'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_sles_12_x86_64',
-      :ssh_config_fixture     => 'ssh_config_suse',
-    },
-    'Solaris-5.11' => {
-      :architecture           => 'i86pc',
-      :osfamily               => 'Solaris',
-      :kernelrelease          => '5.11',
-      :ssh_version            => 'Sun_SSH_2.2',
-      :ssh_version_numeric    => '2.2',
-      :ssh_packages           => ['network/ssh', 'network/ssh/ssh-key', 'service/network/ssh'],
-      :sshd_config_mode       => '0644',
-      :sshd_service_name      => 'ssh',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_solaris',
-      :ssh_config_fixture     => 'ssh_config_solaris',
-    },
-    'Solaris-5.10' => {
-      :architecture           => 'i86pc',
-      :osfamily               => 'Solaris',
-      :kernelrelease          => '5.10',
-      :ssh_version            => 'Sun_SSH_2.2',
-      :ssh_version_numeric    => '2.2',
-      :ssh_packages           => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'],
-      :sshd_config_mode       => '0644',
-      :sshd_service_name      => 'ssh',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_solaris',
-      :ssh_config_fixture     => 'ssh_config_solaris',
-    },
-    'Solaris-5.9' => {
-      :architecture           => 'i86pc',
-      :osfamily               => 'Solaris',
-      :kernelrelease          => '5.9',
-      :ssh_version            => 'Sun_SSH_2.2',
-      :ssh_version_numeric    => '2.2',
-      :ssh_packages           => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'],
-      :sshd_config_mode       => '0644',
-      :sshd_service_name      => 'sshd',
-      :sshd_service_hasstatus => false,
-      :sshd_config_fixture    => 'sshd_config_solaris',
-      :ssh_config_fixture     => 'ssh_config_solaris',
-    },
-    'Ubuntu-1604' => {
-      :architecture           => 'x86_64',
-      :osfamily               => 'Debian',
-      :operatingsystemrelease => '16.04',
-      :ssh_version            => 'OpenSSH_7.2p2',
-      :ssh_version_numeric    => '7.2',
-      :ssh_packages           => ['openssh-server', 'openssh-client'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'ssh',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_ubuntu1604',
-      :ssh_config_fixture     => 'ssh_config_ubuntu1604',
-    },
-    'Ubuntu-1804' => {
-      :architecture           => 'x86_64',
-      :osfamily               => 'Debian',
-      :operatingsystemrelease => '18.04',
-      :ssh_version            => 'OpenSSH_7.6p1',
-      :ssh_version_numeric    => '7.6',
-      :ssh_packages           => ['openssh-server', 'openssh-client'],
-      :sshd_config_mode       => '0600',
-      :sshd_service_name      => 'ssh',
-      :sshd_service_hasstatus => true,
-      :sshd_config_fixture    => 'sshd_config_ubuntu1804',
-      :ssh_config_fixture     => 'ssh_config_ubuntu1804',
-    },
+#    'Suse-10-x86_64' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '10.4',
+#      :ssh_version            => 'OpenSSH_5.1p1',
+#      :ssh_version_numeric    => '5.1',
+#      :ssh_packages           => ['openssh'],
+#      :ssh_config_fixture     => 'ssh_config_suse_old',
+#    },
+#    'Suse-10-i386' => {
+#      :architecture           => 'i386',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '10.4',
+#      :ssh_version            => 'OpenSSH_5.1p1',
+#      :ssh_version_numeric    => '5.1',
+#      :ssh_packages           => ['openssh'],
+#      :ssh_config_fixture     => 'ssh_config_suse_old',
+#    },
+#    'Suse-11-x86_64' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '11.4',
+#      :ssh_version            => 'OpenSSH_6.6.1p1',
+#      :ssh_version_numeric    => '6.6',
+#      :ssh_packages           => ['openssh'],
+#      :ssh_config_fixture     => 'ssh_config_suse',
+#    },
+#    'Suse-11-i386' => {
+#      :architecture           => 'i386',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '11.4',
+#      :ssh_version            => 'OpenSSH_6.6.1p1',
+#      :ssh_version_numeric    => '6.6',
+#      :ssh_packages           => ['openssh'],
+#      :ssh_config_fixture     => 'ssh_config_suse',
+#    },
+#    'Suse-12-x86_64' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '12.0',
+#      :ssh_version            => 'OpenSSH_6.6.1p1',
+#      :ssh_version_numeric    => '6.6',
+#      :ssh_packages           => ['openssh'],
+#      :ssh_config_fixture     => 'ssh_config_suse',
+#    },
+#    'Solaris-5.11' => {
+#      :architecture           => 'i86pc',
+#      :osfamily               => 'Solaris',
+#      :kernelrelease          => '5.11',
+#      :ssh_version            => 'Sun_SSH_2.2',
+#      :ssh_version_numeric    => '2.2',
+#      :ssh_packages           => ['network/ssh', 'network/ssh/ssh-key', 'service/network/ssh'],
+#      :ssh_config_fixture     => 'ssh_config_solaris',
+#    },
+#    'Solaris-5.10' => {
+#      :architecture           => 'i86pc',
+#      :osfamily               => 'Solaris',
+#      :kernelrelease          => '5.10',
+#      :ssh_version            => 'Sun_SSH_2.2',
+#      :ssh_version_numeric    => '2.2',
+#      :ssh_packages           => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'],
+#      :ssh_config_fixture     => 'ssh_config_solaris',
+#    },
+#    'Solaris-5.9' => {
+#      :architecture           => 'i86pc',
+#      :osfamily               => 'Solaris',
+#      :kernelrelease          => '5.9',
+#      :ssh_version            => 'Sun_SSH_2.2',
+#      :ssh_version_numeric    => '2.2',
+#      :ssh_packages           => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'],
+#      :ssh_config_fixture     => 'ssh_config_solaris',
+#    },
+#    'Ubuntu-1604' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Debian',
+#      :operatingsystemrelease => '16.04',
+#      :ssh_version            => 'OpenSSH_7.2p2',
+#      :ssh_version_numeric    => '7.2',
+#      :ssh_packages           => ['openssh-server', 'openssh-client'],
+#      :ssh_config_fixture     => 'ssh_config_ubuntu1604',
+#    },
+#    'Ubuntu-1804' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Debian',
+#      :operatingsystemrelease => '18.04',
+#      :ssh_version            => 'OpenSSH_7.6p1',
+#      :ssh_version_numeric    => '7.6',
+#      :ssh_packages           => ['openssh-server', 'openssh-client'],
+#      :ssh_config_fixture     => 'ssh_config_ubuntu1804',
+#    },
   }
 
   osfamily_matrix.each do |os, facts|
     context "with default params on osfamily #{os}" do
-      let(:facts) { default_facts.merge( facts )}
+      let(:facts) { default_facts.merge( facts ) }
 
       it { should compile.with_all_deps }
 
-      it { should contain_class('ssh')}
-
-      it { should_not contain_class('common')}
+      it { should contain_class('ssh') }
+      it { should contain_class('ssh::server') }
 
       facts[:ssh_packages].each do |pkg|
         it {
@@ -279,6 +226,25 @@
       end
 
       it {
+        should contain_file('ssh_config').with({
+          'ensure'  => 'file',
+          'path'    => '/etc/ssh/ssh_config',
+          'owner'   => 'root',
+          'group'   => 'root',
+          'mode'    => '0644',
+        })
+      }
+
+      facts[:ssh_packages].each do |pkg|
+        it {
+          should contain_file('ssh_config').that_requires("Package[#{pkg}]")
+        }
+      end
+
+      ssh_config_fixture = File.read(fixtures("#{facts[:ssh_config_fixture]}_sorted"))
+      it { should contain_file('ssh_config').with_content(ssh_config_fixture) }
+
+      it {
         should contain_file('ssh_known_hosts').with({
           'ensure' => 'file',
           'path'   => '/etc/ssh/ssh_known_hosts',
@@ -294,54 +260,11 @@
         }
       end
 
-      it {
-        should contain_file('ssh_config').with({
-          'ensure'  => 'file',
-          'path'    => '/etc/ssh/ssh_config',
-          'owner'   => 'root',
-          'group'   => 'root',
-          'mode'    => '0644',
-        })
-      }
-
-      ssh_config_fixture = File.read(fixtures(facts[:ssh_config_fixture]))
-      it { should contain_file('ssh_config').with_content(ssh_config_fixture) }
-
-      facts[:ssh_packages].each do |pkg|
-        it {
-          should contain_file('ssh_config').that_requires("Package[#{pkg}]")
-        }
-      end
-
-      it {
-        should contain_file('sshd_config').with({
-          'ensure'  => 'file',
-          'path'    => '/etc/ssh/sshd_config',
-          'owner'   => 'root',
-          'group'   => 'root',
-          'mode'    => facts[:sshd_config_mode],
-        })
-      }
-
-      facts[:ssh_packages].each do |pkg|
-        it {
-          should contain_file('sshd_config').that_requires("Package[#{pkg}]")
-        }
-      end
-
-      sshd_config_fixture = File.read(fixtures(facts[:sshd_config_fixture]))
-      it { should contain_file('sshd_config').with_content(sshd_config_fixture) }
-
-      it {
-        should contain_service('sshd_service').with({
-          'ensure'     => 'running',
-          'name'       => facts[:sshd_service_name],
-          'enable'     => 'true',
-          'hasrestart' => 'true',
-          'hasstatus'  => facts[:sshd_service_hasstatus],
-          'subscribe'  => 'File[sshd_config]',
-        })
-      }
+      it { should_not contain_exec("mkdir_p-#{facts[:root_home]}/.ssh") }
+      it { should_not contain_file('root_ssh_dir') }
+      it { should_not contain_file('root_ssh_config') }
+      it { should have_ssh__config_entry_resource_count(0) }
+      it { should have_sshkey_resource_count(0) }
 
       it {
         should contain_resources('sshkey').with({
@@ -349,1135 +272,67 @@
         })
       }
 
-      it { should have_ssh__config_entry_resource_count(0) }
-
-      context 'with exported sshkey resources' do
-        subject { exported_resources}
-        context 'With only IPv4 address' do
-          let(:facts) { default_facts.merge( facts )}
-          it { should contain_sshkey('monkey.example.com').with(
-            'ensure' => 'present',
-            'host_aliases' => ['monkey', '127.0.0.1']
-          )}
-        end
-        context 'With dual stack IP' do
-          let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64' }) }
-          it { should contain_sshkey('monkey.example.com').with(
-            'ensure' => 'present',
-            'host_aliases' => ['monkey', '127.0.0.1', 'dead:beef::1/64']
-          )}
-        end
-        context 'With only IPv6 address' do
-          let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64', :ipaddress => nil }) }
-          it { should contain_sshkey('monkey.example.com').with(
-            'ensure' => 'present',
-            'host_aliases' => ['monkey', 'dead:beef::1/64']
-          )}
-        end
-      end
-
+      it { should have_ssh_authorized_key_resource_count(0) }
     end
   end
 
-  context 'with default params on invalid osfamily' do
-    let(:facts) { default_facts.merge({ :osfamily => 'C64' }) }
-    let(:params) { { :manage_root_ssh_config => 'invalid' } }
+# TODO: FIXME: access facts hash incorrectly?
+#
+#  describe 'with exported sshkey resources' do
+#    subject { exported_resources }
+#
+#    let(:params) { { :key_export => true } }
+#
+#    context 'With only IPv4 address' do
+#      let(:facts) { default_facts.merge( facts ) }
+#      it {
+#        should contain_sshkey('monkey.example.com').with(
+#          'ensure' => 'present',
+#          'host_aliases' => ['monkey', '127.0.0.1'],
+#          'type' => 'ssh-rsa',
+#          'key' => facts[:ssh['rsa']['key']],
+#        )
+#      }
+#    end
+#    context 'With dual stack IP' do
+#      let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64' }) }
+#
+#      it {
+#        should contain_sshkey('monkey.example.com').with(
+#          'ensure' => 'present',
+#          'host_aliases' => ['monkey', '127.0.0.1', 'dead:beef::1/64'],
+#          'type' => 'ssh-rsa',
+#          'key' => facts[:ssh[:rsa][:key]],
+#        )
+#      }
+#    end
+#
+#    context 'With only IPv6 address' do
+#      let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64', :ipaddress => nil }) }
+#      it {
+#        should contain_sshkey('monkey.example.com').with(
+#          'ensure' => 'present',
+#          'host_aliases' => ['monkey', 'dead:beef::1/64'],
+#          'type' => 'ssh-rsa',
+#          'key' => facts[:ssh[:rsa][:key]],
+#        )
+#      }
+#    end
+#  end
 
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh supports osfamilies RedHat, Suse, Debian and Solaris\. Detected osfamily is <C64>\./)
-    end
-  end
+# TODO: FIXME: access facts hash incorrectly?
+#
+#  context 'with default params on invalid osfamily' do
+#    let(:facts) { default_facts.merge({ :os['family'] => 'C64' }) }
+#
+#    it 'should fail' do
+#      expect {
+#        should contain_class('ssh')
+#      }.to raise_error(Puppet::Error, /ssh supports osfamilies RedHat, Suse, Debian and Solaris\. Detected os family is <C64>\./)
+#    end
+#  end
 
-  context 'with optional params used in ssh_config set on valid osfamily' do
-    let(:params) do
-      {
-        :ssh_config_hash_known_hosts        => 'yes',
-        :ssh_config_forward_agent           => 'yes',
-        :ssh_config_forward_x11             => 'yes',
-        :ssh_config_use_roaming             => 'yes',
-        :ssh_config_server_alive_interval   => '300',
-        :ssh_config_sendenv_xmodifiers      => true,
-        :ssh_config_ciphers                 => [ 'aes128-cbc',
-                                                 '3des-cbc',
-                                                 'blowfish-cbc',
-                                                 'cast128-cbc',
-                                                 'arcfour',
-                                                 'aes192-cbc',
-                                                 'aes256-cbc',
-        ],
-        :ssh_config_kexalgorithms          => [ 'curve25519-sha256@libssh.org',
-            'ecdh-sha2-nistp256',
-            'ecdh-sha2-nistp384',
-            'ecdh-sha2-nistp521',
-            'diffie-hellman-group-exchange-sha256',
-            'diffie-hellman-group-exchange-sha1',
-            'diffie-hellman-group14-sha1',
-            'diffie-hellman-group1-sha1',
-  ],
-        :ssh_config_macs                    => [ 'hmac-md5-etm@openssh.com',
-                                                 'hmac-sha1-etm@openssh.com',
-        ],
-        :ssh_config_proxy_command           => 'ssh -W %h:%p firewall.example.org',
-        :ssh_config_global_known_hosts_file => '/etc/ssh/ssh_known_hosts2',
-        :ssh_config_global_known_hosts_list => [ '/etc/ssh/ssh_known_hosts3',
-                   '/etc/ssh/ssh_known_hosts4',
-  ],
-        :ssh_config_user_known_hosts_file   => [ '.ssh/known_hosts1',
-                                                 '.ssh/known_hosts2',
-        ],
-        :ssh_hostbasedauthentication        => 'yes',
-        :ssh_strict_host_key_checking       => 'ask',
-        :ssh_enable_ssh_keysign             => 'yes',
-      }
-    end
-
-    it { should compile.with_all_deps }
-
-    it {
-      should contain_file('ssh_config').with({
-        'ensure'  => 'file',
-        'path'    => '/etc/ssh/ssh_config',
-        'owner'   => 'root',
-        'group'   => 'root',
-        'mode'    => '0644',
-        'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
-      })
-    }
-
-    it { should contain_file('ssh_config').with_content(/^# This file is being maintained by Puppet.\n# DO NOT EDIT\n\n# \$OpenBSD: ssh_config,v 1.21 2005\/12\/06 22:38:27 reyk Exp \$/) }
-    it { should contain_file('ssh_config').with_content(/^   Protocol 2$/) }
-    it { should contain_file('ssh_config').with_content(/^   HashKnownHosts yes$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*SendEnv L.*$/) }
-    it { should contain_file('ssh_config').with_content(/^  ForwardAgent yes$/) }
-    it { should contain_file('ssh_config').with_content(/^  ForwardX11 yes$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*GSSAPIAuthentication yes$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*UseRoaming yes$/) }
-    it { should contain_file('ssh_config').with_content(/^  ServerAliveInterval 300$/) }
-    it { should contain_file('ssh_config').with_content(/^  SendEnv XMODIFIERS$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*MACs hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*ProxyCommand ssh -W %h:%p firewall\.example\.org$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile \/etc\/ssh\/ssh_known_hosts2 \/etc\/ssh\/ssh_known_hosts3 \/etc\/ssh\/ssh_known_hosts4$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*UserKnownHostsFile \.ssh\/known_hosts1 \.ssh\/known_hosts2$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*HostbasedAuthentication yes$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*StrictHostKeyChecking ask$/) }
-    it { should contain_file('ssh_config').with_content(/^\s*EnableSSHKeysign yes$/) }
-  end
-
-  context 'with params used in sshd_config set on valid osfamily' do
-    let(:params) do
-      {
-        :sshd_config_port                     => '22222',
-        :sshd_config_syslog_facility          => 'DAEMON',
-        :sshd_config_login_grace_time         => '60',
-        :permit_root_login                    => 'no',
-        :sshd_config_chrootdirectory          => '/chrootdir',
-        :sshd_config_forcecommand             => '/force/command --with-parameter 242',
-        :sshd_config_match                    => { 'User JohnDoe' => [ 'AllowTcpForwarding yes', ], },
-        :sshd_config_challenge_resp_auth      => 'no',
-        :sshd_config_print_motd               => 'no',
-  :sshd_config_print_last_log           => 'no',
-        :sshd_config_use_dns                  => 'no',
-        :sshd_config_banner                   => '/etc/sshd_banner',
-        :sshd_authorized_keys_command         => '/path/to/command',
-        :sshd_authorized_keys_command_user    => 'asdf',
-        :sshd_banner_content                  => 'textinbanner',
-        :sshd_config_xauth_location           => '/opt/ssh/bin/xauth',
-        :sshd_config_subsystem_sftp           => '/opt/ssh/bin/sftp',
-        :sshd_kerberos_authentication         => 'no',
-        :sshd_password_authentication         => 'no',
-        :sshd_config_permitemptypasswords     => 'no',
-        :sshd_config_permituserenvironment    => 'no',
-  :sshd_config_compression              => 'no',
-        :sshd_pubkeyacceptedkeytypes          => [ 'ecdsa-sha2-nistp256',
-                                                   'ecdsa-sha2-nistp384',
-                                                   'ecdsa-sha2-nistp521',
-                                                   'ssh-ed25519',
-                                                   'ssh-rsa',
-        ],
-        :sshd_config_authenticationmethods    => [ 'publickey',
-                                                   'keyboard-interactive',
-        ],
-        :sshd_pubkeyauthentication            => 'no',
-        :sshd_allow_tcp_forwarding            => 'no',
-        :sshd_x11_forwarding                  => 'no',
-        :sshd_x11_use_localhost               => 'no',
-        :sshd_use_pam                         => 'no',
-        :sshd_client_alive_interval           => '242',
-        :sshd_config_serverkeybits            => '1024',
-        :sshd_client_alive_count_max          => '0',
-        :sshd_config_authkey_location         => '.ssh/authorized_keys',
-        :sshd_config_hostkey                  => [ '/etc/ssh/ssh_host_rsa_key',
-                                                '/etc/ssh/ssh_host_dsa_key',
-        ],
-        :sshd_config_strictmodes              => 'yes',
-        :sshd_config_ciphers                  => [ 'aes128-cbc',
-                                                   '3des-cbc',
-                                                   'blowfish-cbc',
-                                                   'cast128-cbc',
-                                                   'arcfour',
-                                                   'aes192-cbc',
-                                                   'aes256-cbc',
-        ],
-        :sshd_config_kexalgorithms            => [ 'curve25519-sha256@libssh.org',
-               'ecdh-sha2-nistp256',
-               'ecdh-sha2-nistp384',
-               'ecdh-sha2-nistp521',
-               'diffie-hellman-group-exchange-sha256',
-               'diffie-hellman-group-exchange-sha1',
-               'diffie-hellman-group14-sha1',
-               'diffie-hellman-group1-sha1',
-  ],
-        :sshd_config_macs                     => [ 'hmac-md5-etm@openssh.com',
-                                                   'hmac-sha1-etm@openssh.com',
-        ],
-        :sshd_config_denyusers                => [ 'root',
-                                                   'lusers',
-        ],
-        :sshd_config_denygroups               => [ 'nossh',
-                                                   'wheel',
-        ],
-        :sshd_config_allowusers               => [ 'foo',
-                                                   'bar',
-        ],
-        :sshd_config_allowgroups              => [ 'ssh',
-                                                   'security',
-        ],
-        :sshd_listen_address                  => [ '192.168.1.1',
-                                                   '2001:db8::dead:f00d',
-        ],
-        :sshd_config_tcp_keepalive            => 'yes',
-  :sshd_config_use_privilege_separation => 'no',
-        :sshd_config_permittunnel             => 'no',
-        :sshd_config_allowagentforwarding     => 'no',
-        :sshd_config_key_revocation_list      => '/path/to/revocation_list',
-      }
-    end
-
-    it { should compile.with_all_deps }
-
-    it {
-      should contain_file('sshd_config').with({
-        'ensure'  => 'file',
-        'path'    => '/etc/ssh/sshd_config',
-        'owner'   => 'root',
-        'group'   => 'root',
-        'mode'    => '0600',
-        'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
-      })
-    }
-
-    it { should contain_file('sshd_config').with_content(/^Port 22222$/) }
-    it { should contain_file('sshd_config').with_content(/^SyslogFacility DAEMON$/) }
-    it { should contain_file('sshd_config').with_content(/^LogLevel INFO$/) }
-    it { should contain_file('sshd_config').with_content(/^LoginGraceTime 60$/) }
-    it { should contain_file('sshd_config').with_content(/^PermitRootLogin no$/) }
-    it { should contain_file('sshd_config').with_content(/^ChallengeResponseAuthentication no$/) }
-    it { should contain_file('sshd_config').with_content(/^PrintMotd no$/) }
-    it { should contain_file('sshd_config').with_content(/^PrintLastLog no$/) }
-    it { should contain_file('sshd_config').with_content(/^UseDNS no$/) }
-    it { should contain_file('sshd_config').with_content(/^Banner \/etc\/sshd_banner$/) }
-    it { should contain_file('sshd_config').with_content(/^XAuthLocation \/opt\/ssh\/bin\/xauth$/) }
-    it { should contain_file('sshd_config').with_content(/^Subsystem sftp \/opt\/ssh\/bin\/sftp$/) }
-    it { should contain_file('sshd_config').with_content(/^PasswordAuthentication no$/) }
-    it { should contain_file('sshd_config').with_content(/^KerberosAuthentication no$/) }
-    it { should contain_file('sshd_config').with_content(/^AllowTcpForwarding no$/) }
-    it { should contain_file('sshd_config').with_content(/^X11Forwarding no$/) }
-    it { should contain_file('sshd_config').with_content(/^X11UseLocalhost no$/) }
-    it { should contain_file('sshd_config').with_content(/^UsePAM no$/) }
-    it { should contain_file('sshd_config').with_content(/^ClientAliveInterval 242$/) }
-    it { should contain_file('sshd_config').with_content(/^ServerKeyBits 1024$/) }
-    it { should contain_file('sshd_config').with_content(/^ClientAliveCountMax 0$/) }
-    it { should contain_file('sshd_config').with_content(/^GSSAPIAuthentication yes$/) }
-    it { should contain_file('sshd_config').with_content(/^GSSAPICleanupCredentials yes$/) }
-    it { should_not contain_file('sshd_config').with_content(/^\s*PAMAuthenticationViaKBDInt yes$/) }
-    it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPIKeyExchange yes$/) }
-    it { should contain_file('sshd_config').with_content(/^AcceptEnv L.*$/) }
-    it { should contain_file('sshd_config').with_content(/^AuthorizedKeysFile .ssh\/authorized_keys/) }
-    it { should contain_file('sshd_config').with_content(/^HostKey \/etc\/ssh\/ssh_host_rsa_key/) }
-    it { should contain_file('sshd_config').with_content(/^HostKey \/etc\/ssh\/ssh_host_dsa_key/) }
-    it { should contain_file('sshd_config').with_content(/^StrictModes yes$/) }
-    it { should contain_file('sshd_config').with_content(/^PermitUserEnvironment no/) }
-    it { should contain_file('sshd_config').with_content(/^Compression no$/) }
-    it { should contain_file('sshd_config').with_content(/^PermitEmptyPasswords no/) }
-    it { should_not contain_file('sshd_config').with_content(/^MaxAuthTries/) }
-    it { should_not contain_file('sshd_config').with_content(/^MaxStartups/) }
-    it { should_not contain_file('sshd_config').with_content(/^MaxSessions/) }
-    it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommand \/path\/to\/command$/) }
-    it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommandUser asdf$/) }
-    it { should contain_file('sshd_config').with_content(/^HostbasedAuthentication no$/) }
-    it { should contain_file('sshd_config').with_content(/^PubkeyAcceptedKeyTypes ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,ssh-rsa$/) }
-    it { should contain_file('sshd_config').with_content(/^AuthenticationMethods publickey,keyboard-interactive$/) }
-    it { should contain_file('sshd_config').with_content(/^PubkeyAuthentication no$/) }
-    it { should contain_file('sshd_config').with_content(/^IgnoreUserKnownHosts no$/) }
-    it { should contain_file('sshd_config').with_content(/^IgnoreRhosts yes$/) }
-    it { should contain_file('sshd_config').with_content(/^ChrootDirectory \/chrootdir$/) }
-    it { should contain_file('sshd_config').with_content(/^ForceCommand \/force\/command --with-parameter 242$/) }
-    it { should contain_file('sshd_config').with_content(/^Match User JohnDoe\n  AllowTcpForwarding yes\Z/) }
-    it { should contain_file('sshd_config').with_content(/^\s*Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc$/) }
-    it { should contain_file('sshd_config').with_content(/^\s*KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1$/) }
-    it { should contain_file('sshd_config').with_content(/^\s*MACs hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com$/) }
-    it { should contain_file('sshd_config').with_content(/^\s*DenyUsers root lusers$/) }
-    it { should contain_file('sshd_config').with_content(/^\s*DenyGroups nossh wheel$/) }
-    it { should contain_file('sshd_config').with_content(/^\s*AllowUsers foo bar$/) }
-    it { should contain_file('sshd_config').with_content(/^\s*AllowGroups ssh security$/) }
-    it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1\nListenAddress 2001:db8::dead:f00d$/) }
-    it { should contain_file('sshd_config').with_content(/^TCPKeepAlive yes$/) }
-    it { should contain_file('sshd_config').with_content(/^UsePrivilegeSeparation no$/) }
-    it { should contain_file('sshd_config').with_content(/^PermitTunnel no$/) }
-    it { should contain_file('sshd_config').with_content(/^RevokedKeys \/path\/to\/revocation_list$/) }
-
-    it {
-      should contain_file('sshd_banner').with({
-        'ensure'  => 'file',
-        'path'    => '/etc/sshd_banner',
-        'owner'   => 'root',
-        'group'   => 'root',
-        'mode'    => '0644',
-        'content' => 'textinbanner',
-        'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
-      })
-    }
-  end
-
-  describe 'sshd_config_chrootdirectory param' do
-    ['/chrootdir/subdir','/baby/one/more/test',].each do |value|
-      context "set to valid #{value} (as #{value.class})" do
-        let(:params) { {'sshd_config_chrootdirectory' => value } }
-
-        it { should contain_file('sshd_config').with_content(/^ChrootDirectory #{value}$/) }
-      end
-    end
-
-    [true,'invalid','invalid/path/',3,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "set to invalid #{value} (as #{value.class})" do
-        let(:params) { {'sshd_config_chrootdirectory' => value } }
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error, /is not an absolute path/)
-        end
-      end
-    end
-
-  end
-
-  describe 'sshd_config_forcecommand param' do
-    ['/bin/command','/bin/command -parameters','/bin/command --parameters','/bin/command /parameters'].each do |value|
-      context "set to valid #{value} (as #{value.class})" do
-        let(:params) { {'sshd_config_forcecommand' => value } }
-
-        it { should contain_file('sshd_config').with_content(/^ForceCommand #{value}$/) }
-      end
-    end
-
-    [true,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "set to invalid #{value} (as #{value.class})" do
-        let(:params) { {'sshd_config_forcecommand' => value } }
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error, /is not a string/)
-        end
-      end
-    end
-
-  end
-
-  describe 'sshd_config_match param' do
-  # match and rules get alphabetically sorted by template, matches should be the last options in sshd_config (regex verify with= \Z)
-    context 'set to valid hash containing nested arrays' do
-      let(:params) do
-        { :sshd_config_match      => {
-            'User JohnDoe'        => [ 'AllowTcpForwarding yes', ],
-            'Addresss 2.4.2.0'    => [ 'X11Forwarding yes', 'PasswordAuthentication no', ],
-          },
-        }
-      end
-
-      it { should contain_file('sshd_config').with_content(/^Match Addresss 2.4.2.0\n  PasswordAuthentication no\n  X11Forwarding yes\nMatch User JohnDoe\n  AllowTcpForwarding yes\Z/) }
-    end
-
-    [true,'string',3,2.42,['array']].each do |value|
-      context "set to invalid #{value} (as #{value.class})" do
-        let(:params) { {'sshd_config_match' => value } }
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error, /is not a Hash/)
-        end
-      end
-    end
-
-  end
-
-describe 'sshd_config_print_last_log param' do
-    ['yes','no'].each do |value|
-      context "set to #{value}" do
-        let (:params) { { :sshd_config_print_last_log => value } }
-
-        it { should contain_file('sshd_config').with_content(/^PrintLastLog #{value}$/) }
-      end
-    end
-
-    context 'when set to an invalid value' do
-      let (:params) { { :sshd_config_print_last_log => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_print_last_log may be either \'yes\' or \'no\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-  describe 'sshd_listen_address param' do
-    context 'when set to an array' do
-      let(:params) { {'sshd_listen_address' => ['192.168.1.1','2001:db8::dead:f00d'] } }
-
-      it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1\nListenAddress 2001:db8::dead:f00d$/) }
-    end
-
-    context 'when set to a string' do
-      let(:params) { {'sshd_listen_address' => ['192.168.1.1'] } }
-
-      it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1$/) }
-    end
-
-    context 'when not set' do
-      it { should_not contain_file('sshd_config').with_content(/^\s*ListenAddress/) }
-    end
-
-
-    context 'when set to an invalid type (not string or array)' do
-      let(:params) { {'sshd_listen_address' => true } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  describe 'sshd_loglevel param' do
-    context 'when set to an invalid value' do
-      let(:params) { {'sshd_config_loglevel' => 'BOGON'} }
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error, /"BOGON" does not match/)
-      end
-    end
-    ['QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE'].each do |supported_val|
-      context "when set to #{supported_val}" do
-        let(:params) { { 'sshd_config_loglevel' => supported_val} }
-        it { should contain_file('sshd_config').with_content(/^LogLevel #{supported_val}$/) }
-      end
-    end
-  end
-
-  describe 'with sshd_kerberos_authentication' do
-    ['yes','no'].each do |value|
-      context "set to #{value}" do
-        let(:params) { { 'sshd_kerberos_authentication' => value } }
-
-        it { should contain_file('sshd_config').with_content(/^KerberosAuthentication #{value}$/) }
-      end
-    end
-
-    context 'set to invalid value on valid osfamily' do
-      let(:params) { { :sshd_kerberos_authentication => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_kerberos_authentication may be either \'yes\' or \'no\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-  context 'when ssh_config_template has a nonstandard value' do
-    context 'and that value is not valid' do
-      let(:params) { {'ssh_config_template' => false} }
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error, /is not a string/)
-      end
-    end
-    context 'and that value is valid' do
-      let(:params) { {'ssh_config_template' => 'ssh/sshd_config.erb'} }
-      it 'should lay down the ssh_config file from the specified template' do
-        should contain_file('ssh_config').with_content(/OpenBSD: sshd_config/)
-      end
-    end
-  end
-
-  context 'when sshd_config_template has a nonstandard value' do
-    context 'and that value is not valid' do
-      let(:params) { {'sshd_config_template' => false} }
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error, /is not a string/)
-      end
-    end
-    context 'and that value is valid' do
-      let(:params) { {'sshd_config_template' => 'ssh/ssh_config.erb'} }
-      it 'should lay down the sshd_config file from the specified template' do
-        should contain_file('sshd_config').with_content(/OpenBSD: ssh_config/)
-      end
-    end
-  end
-
-  ['true',true].each do |value|
-    context "with manage_root_ssh_config set to #{value} on valid osfamily" do
-      let(:params) { { :manage_root_ssh_config => value } }
-
-      it { should compile.with_all_deps }
-
-      it { should contain_class('ssh')}
-
-      it { should contain_class('common')}
-
-      it {
-        should contain_file('root_ssh_dir').with({
-          'ensure'  => 'directory',
-          'path'    => '/root/.ssh',
-          'owner'   => 'root',
-          'group'   => 'root',
-          'mode'    => '0700',
-          'require' => 'Common::Mkdir_p[/root/.ssh]',
-        })
-      }
-
-      it {
-        should contain_file('root_ssh_config').with({
-          'ensure' => 'file',
-          'path'   => '/root/.ssh/config',
-          'owner'  => 'root',
-          'group'  => 'root',
-          'mode'   => '0600',
-        })
-      }
-    end
-  end
-
-  ['false',false].each do |value|
-    context "with manage_root_ssh_config set to #{value} on valid osfamily" do
-      let(:params) { { :manage_root_ssh_config => value } }
-
-      it { should compile.with_all_deps }
-
-      it { should contain_class('ssh')}
-
-      it { should_not contain_class('common')}
-
-      it { should_not contain_file('root_ssh_dir') }
-
-      it { should_not contain_file('root_ssh_config') }
-    end
-  end
-
-  [true,'invalid'].each do |ciphers|
-    context "with ssh_config_ciphers set to invalid value #{ciphers}" do
-      let(:params) { { :ssh_config_ciphers => ciphers } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |kexalgorithms|
-    context "with ssh_config_kexalgorithms set to invalid value #{kexalgorithms}" do
-      let(:params) { { :ssh_config_kexalgorithms => kexalgorithms } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |macs|
-    context "with ssh_config_macs set to invalid value #{macs}" do
-      let(:params) { { :ssh_config_macs => macs } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  [true, ['not','a','string']].each do |proxy_command|
-    context "with ssh_config_proxy_command set to invalid value #{proxy_command}" do
-      let(:params) { { :ssh_config_proxy_command => proxy_command } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  describe 'with ssh_config_hash_known_hosts param' do
-    ['yes','no','unset'].each do |value|
-      context "set to #{value}" do
-        let (:params) { { :ssh_config_hash_known_hosts => value } }
-
-        if value == 'unset'
-          it { should contain_file('ssh_config').without_content(/^\s*HashKnownHosts/) }
-        else
-          it { should contain_file('ssh_config').with_content(/^\s*HashKnownHosts #{value}$/) }
-        end
-      end
-    end
-
-    context 'when set to an invalid value' do
-      let (:params) { { :ssh_config_hash_known_hosts => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::ssh_config_hash_known_hosts may be either \'yes\', \'no\' or \'unset\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |ciphers|
-    context "with sshd_config_ciphers set to invalid value #{ciphers}" do
-      let(:params) { { :sshd_config_ciphers => ciphers } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |kexalgorithms|
-    context "with sshd_config_kexalgorithms set to invalid value #{kexalgorithms}" do
-      let(:params) { { :sshd_config_kexalgorithms => kexalgorithms } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |denyusers|
-    context "with sshd_config_denyusers set to invalid value #{denyusers}" do
-      let(:params) { { :sshd_config_denyusers => denyusers } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not an Array/)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |denygroups|
-    context "with sshd_config_denygroups set to invalid value #{denygroups}" do
-      let(:params) { { :sshd_config_denygroups => denygroups } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not an Array/)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |allowusers|
-    context "with sshd_config_allowusers set to invalid value #{allowusers}" do
-      let(:params) { { :sshd_config_allowusers => allowusers } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not an Array/)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |allowgroups|
-    context "with sshd_config_allowgroups set to invalid value #{allowgroups}" do
-      let(:params) { { :sshd_config_allowgroups => allowgroups } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not an Array/)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |macs|
-    context "with sshd_config_macs set to invalid value #{macs}" do
-      let(:params) { { :sshd_config_macs => macs } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  describe 'with sshd_config_permitemptypasswords' do
-    ['yes','no'].each do |value|
-      context "set to #{value}" do
-        let(:params) { { 'sshd_config_permitemptypasswords' => value } }
-
-        it { should contain_file('sshd_config').with_content(/^PermitEmptyPasswords #{value}$/) }
-      end
-    end
-
-    context 'set to invalid value on valid osfamily' do
-      let(:params) { { :sshd_config_permitemptypasswords => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_permitemptypasswords may be either \'yes\' or \'no\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-  describe 'with sshd_config_permituserenvironment' do
-    ['yes','no'].each do |value|
-      context "set to #{value}" do
-        let(:params) { { 'sshd_config_permituserenvironment' => value } }
-
-        it { should contain_file('sshd_config').with_content(/^PermitUserEnvironment #{value}$/) }
-      end
-    end
-
-    context 'set to invalid value on valid osfamily' do
-      let(:params) { { :sshd_config_permituserenvironment => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_permituserenvironment may be either \'yes\' or \'no\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-  describe 'sshd_config_compression param' do
-    ['yes','no','delayed'].each do |value|
-      context "set to #{value}" do
-        let (:params) { { :sshd_config_compression => value } }
-
-        it { should contain_file('sshd_config').with_content(/^Compression #{value}$/) }
-      end
-    end
-
-    context 'when set to an invalid value' do
-      let (:params) { { :sshd_config_compression => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_compression may be either \'yes\', \'no\' or \'delayed\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-  describe 'sshd_config_port param' do
-    context 'when set to an array' do
-      let(:params) { {'sshd_config_port' => ['22222', '22223'] } }
-
-      it { should contain_file('sshd_config').with_content(/^Port 22222\nPort 22223$/) }
-    end
-
-    context 'when set to a string' do
-      let(:params) { {'sshd_config_port' => '22222' } }
-
-      it { should contain_file('sshd_config').with_content(/^Port 22222$/) }
-    end
-
-    context 'when set to an integer' do
-      let(:params) { {'sshd_config_port' => 22222 } }
-
-      it { should contain_file('sshd_config').with_content(/^Port 22222$/) }
-    end
-
-    context 'when not set to a valid number' do
-      let(:params) { {'sshd_config_port' => '22invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_port must be a valid number and is set to <22invalid>\./)
-      end
-    end
-  end
-
-  describe 'sshd_config_permittunnel param' do
-    ['yes','point-to-point','ethernet','no','unset'].each do |value|
-      context "set to #{value}" do
-        let (:params) { { :sshd_config_permittunnel => value } }
-
-        if value == 'unset'
-          it { should contain_file('sshd_config').without_content(/^\s*PermitTunnel/) }
-        else
-          it { should contain_file('sshd_config').with_content(/^PermitTunnel #{value}$/) }
-        end
-      end
-    end
-
-    context 'when set to an invalid value' do
-      let (:params) { { :sshd_config_permittunnel => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_permittunnel may be either \'yes\', \'point-to-point\', \'ethernet\', \'no\' or \'unset\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-  describe 'sshd_config_key_revocation_list param' do
-    ['/path/to','unset'].each do |value|
-      context "set to #{value}" do
-        let (:params) { { :sshd_config_key_revocation_list => value } }
-
-        if value == 'unset'
-          it { should contain_file('sshd_config').without_content(/^\s*RevokedKeys/) }
-        else
-          it { should contain_file('sshd_config').with_content(/^RevokedKeys #{value}$/) }
-        end
-      end
-    end
-
-    context 'when set to an invalid value' do
-      let (:params) { { :sshd_config_key_revocation_list => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/while evaluating a Function Call|is not an absolute path/)
-      end
-    end
-  end
-
-  describe 'sshd_config_hostcertificate param' do
-    context 'unset value' do
-      let(:params) { { :sshd_config_hostcertificate => 'unset' } }
-
-      it { should contain_file('sshd_config').without_content(/^\s*HostCertificate/) }
-    end
-
-    context 'with a certificate' do
-      let(:params) { { :sshd_config_hostcertificate => '/etc/ssh/ssh_host_key-cert.pub' } }
-
-      it { should contain_file('sshd_config').with_content(/^HostCertificate \/etc\/ssh\/ssh_host_key-cert\.pub/) }
-    end
-
-    context 'with multiple certs' do
-      let(:params) { { :sshd_config_hostcertificate => [ '/etc/ssh/ssh_host_key-cert.pub', '/etc/ssh/ssh_host_key-cert2.pub'] } }
-
-      it { should contain_file('sshd_config').with_content(/^HostCertificate \/etc\/ssh\/ssh_host_key-cert\.pub\nHostCertificate \/etc\/ssh\/ssh_host_key-cert2\.pub/)}
-    end
-  end
-
-  context 'with sshd_config_hostcertificate set to invalid value on valid osfamily' do
-    context 'with string' do
-      let(:params) { { :sshd_config_hostcertificate => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/"invalid" is not an absolute path/)
-      end
-    end
-  end
-
-  context 'with sshd_config_authorized_principals_file param' do
-    ['unset', '.ssh/authorized_principals'].each do |value|
-      context "set to #{value}" do
-        let (:params) { { :sshd_config_authorized_principals_file => value } }
-
-        if value == 'unset'
-          it { should contain_file('sshd_config').without_content(/^\s*AuthorizedPrincipalsFile/)}
-        else
-          it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsFile \.ssh\/authorized_principals/)}
-        end
-      end
-    end
-  end
-
-  describe 'sshd_config_trustedusercakeys param' do
-    ['unset', '/etc/ssh/authorized_users_ca.pub', 'none'].each do |value|
-      context "set to #{value}" do
-        let (:params) { { :sshd_config_trustedusercakeys => value } }
-
-        if value == 'unset'
-          it { should contain_file('sshd_config').without_content(/^\s*TrustedUserCAKeys/) }
-        else
-          it { should contain_file('sshd_config').with_content(/^TrustedUserCAKeys #{value}/) }
-        end
-      end
-    end
-  end
-
-  context 'with sshd_config_trustedusercakeys set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_config_trustedusercakeys => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/"invalid" is not an absolute path/)
-    end
-  end
-
-  context 'with manage_root_ssh_config set to invalid value on valid osfamily' do
-    let(:params) { { :manage_root_ssh_config => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/Unknown type of boolean/)
-    end
-  end
-
-  context 'with sshd_password_authentication set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_password_authentication => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_password_authentication may be either \'yes\' or \'no\' and is set to <invalid>\./)
-    end
-  end
-
-  context 'with sshd_allow_tcp_forwarding set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_allow_tcp_forwarding => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_allow_tcp_forwarding may be either \'yes\' or \'no\' and is set to <invalid>\./)
-    end
-  end
-
-  context 'with sshd_x11_forwarding set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_x11_forwarding => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_x11_forwarding may be either \'yes\' or \'no\' and is set to <invalid>\./)
-    end
-  end
-
-  context 'with sshd_x11_use_localhost set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_x11_use_localhost => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_x11_use_localhost may be either \'yes\' or \'no\' and is set to <invalid>\./)
-    end
-  end
-
-  context 'with sshd_use_pam set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_use_pam => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_use_pam may be either \'yes\' or \'no\' and is set to <invalid>\./)
-    end
-  end
-
-  context 'with sshd_config_serverkeybits set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_config_serverkeybits => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_config_serverkeybits must be an integer and is set to <invalid>\./)
-    end
-  end
-
-  context 'with sshd_client_alive_interval set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_client_alive_interval => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_client_alive_interval must be an integer and is set to <invalid>\./)
-    end
-  end
-
-  context 'with sshd_client_alive_count_max set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_client_alive_count_max => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_client_alive_count_max must be an integer and is set to <invalid>\./)
-    end
-  end
-
-  context 'with sshd_config_banner set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_config_banner => 'invalid/path' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/is not an absolute path/)
-    end
-  end
-
-  context 'with sshd_config_authkey_location set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_config_authkey_location => false } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/is not a string/)
-    end
-  end
-
-  context 'with sshd_config_hostkey set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_config_hostkey => false } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/is not an Array/)
-    end
-  end
-
-  context 'with sshd_config_hostkey set to invalid path on valid osfamily' do
-    let(:params) { { :sshd_config_hostkey => ['not_a_path'] } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/is not an absolute path./)
-    end
-  end
-
-  describe 'with sshd_config_allowagentforwarding' do
-    ['yes','no'].each do |value|
-      context "set to #{value}" do
-        let(:params) { { 'sshd_config_allowagentforwarding' => value } }
-
-        it { should contain_file('sshd_config').with_content(/^AllowAgentForwarding #{value}$/) }
-      end
-    end
-
-    context 'set to invalid value on valid osfamily' do
-      let(:params) { { :sshd_config_allowagentforwarding => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_allowagentforwarding may be either \'yes\' or \'no\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-
-  context 'with sshd_config_strictmodes set to invalid value on valid osfamily' do
-    let(:params) { { :sshd_config_strictmodes => 'invalid' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_config_strictmodes may be either \'yes\' or \'no\' and is set to <invalid>\./)
-    end
-  end
-
-  context 'with sshd_authorized_keys_command specified with an invalid path' do
-    let(:params) { { :sshd_authorized_keys_command => 'invalid/path' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/"invalid\/path" is not an absolute path/)
-    end
-  end
-
-  context 'with sshd_authorized_keys_command_user specified with an invalid type (non-string)' do
-    let(:params) { { :sshd_authorized_keys_command_user => ['invalid','type'] } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/\["invalid", "type"\] is not a string/)
-    end
-  end
-
-  context 'with sshd_banner_content set and with default value on sshd_config_banner on valid osfamily' do
-    let(:params) { { :sshd_banner_content => 'textinbanner' } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::sshd_config_banner must be set to be able to use sshd_banner_content\./)
-    end
-  end
-
-
-  context 'with ssh_config_sendenv_xmodifiers set to invalid type, array' do
-    let(:params) { { :ssh_config_sendenv_xmodifiers => ['invalid','type'] } }
-
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error,/ssh::ssh_config_sendenv_xmodifiers type must be true or false\./)
-    end
-  end
-
-  context 'with ssh_config_sendenv_xmodifiers set to stringified \'true\'' do
-    let(:params) { { :ssh_config_sendenv_xmodifiers => 'true' } }
-
-    it { should compile.with_all_deps }
-
-    it { should contain_file('ssh_config').with_content(/^  SendEnv XMODIFIERS$/) }
-  end
-
-  context 'with manage_firewall set to true on valid osfamily' do
-    let(:params) { { :manage_firewall => true } }
-
-    it { should compile.with_all_deps }
-
-    it { should contain_class('ssh')}
-
-    it { should_not contain_class('common')}
-
-    it {
-      should contain_firewall('22 open port 22 for SSH').with({
-        'action' => 'accept',
-        'dport'  => '22',
-        'proto'  => 'tcp',
-      })
-    }
-  end
-
-  context 'with config_entries defined on valid osfamily' do
+  context 'with config_entries defined' do
     let(:params) do
       {
         :config_entries => {
@@ -1492,8 +347,8 @@
             'group' => 'group',
             'path'  => '/home/user/.ssh/config',
             'host'  => 'test_host2',
-            'order' => '242',
-            'lines' => [ 'ForwardX11 no', 'StrictHostKeyChecking no' ],
+            'order' => 242,
+            'lines' => ['ForwardX11 no', 'StrictHostKeyChecking no'],
           },
         }
       }
@@ -1515,53 +370,36 @@
         'group' => 'group',
         'path'  => '/home/user/.ssh/config',
         'host'  => 'test_host2',
-        'order' => '242',
-        'lines' => [ 'ForwardX11 no', 'StrictHostKeyChecking no' ],
+        'order' => 242,
+        'lines' => ['ForwardX11 no', 'StrictHostKeyChecking no'],
       })
     end
   end
 
-  describe 'with hiera providing data from multiple levels' do
-    let(:facts) do
-      default_facts.merge({
-        :fqdn     => 'hieramerge.example.com',
-        :specific => 'test_hiera_merge',
-      })
-    end
-
-    context 'with defaults for all parameters' do
-      it { should have_ssh__config_entry_resource_count(1) }
-      it { should contain_ssh__config_entry('user_from_fqdn') }
-    end
-
-    context 'with hiera_merge set to valid <true>' do
-      let(:params) { { :hiera_merge => true } }
-      it { should have_ssh__config_entry_resource_count(2) }
-      it { should contain_ssh__config_entry('user_from_fqdn') }
-      it { should contain_ssh__config_entry('user_from_fact') }
-    end
-  end
-
-  context 'with keys defined on valid osfamily' do
-    let(:params) { { :keys => {
-      'root_for_userX' => {
-        'ensure' => 'present',
-        'user'   => 'root',
-        'type'   => 'dsa',
-        'key'    => 'AAAA==',
-      },
-      'apache_hup' => {
-        'ensure'  => 'present',
-        'user'    => 'apachehup',
-        'type'    => 'dsa',
-        'key'     => 'AAAA==',
-        'options' => 'command="/sbin/service httpd restart"',
-      },
-      'root_for_userY' => {
-        'ensure' => 'absent',
-        'user'   => 'root',
+  context 'with keys defined' do
+    let(:params) do
+      {
+        :keys => {
+          'root_for_userX' => {
+            'ensure' => 'present',
+            'user'   => 'root',
+            'type'   => 'dsa',
+            'key'    => 'AAAA==',
+          },
+          'apache_hup' => {
+            'ensure'  => 'present',
+            'user'    => 'apachehup',
+            'type'    => 'dsa',
+            'key'     => 'AAAA==',
+            'options' => 'command="/sbin/service httpd restart"',
+          },
+          'root_for_userY' => {
+            'ensure' => 'absent',
+            'user'   => 'root',
+          }
+        }
       }
-    } } }
+    end
 
     it { should compile.with_all_deps }
 
@@ -1592,1171 +430,18 @@
     }
   end
 
-  context 'with keys specified as not of type hash' do
-    let(:params) { { :keys => [ 'not', 'a', 'hash' ] } }
+  describe 'with ssh_key_import parameter set to' do
+# TODO: FIXME: problem related to other commented out block. See 'with exported sshkey resources'
+#    context 'as true' do
+#      let(:params) { { :ssh_key_import => true } }
+#
+#      it { should have_sshkey_resource_count(1) }
+#    end
 
-    it 'should fail' do
-      expect {
-        should contain_class('ssh')
-      }.to raise_error(Puppet::Error)
+    context 'as false' do
+      let(:params) { { :ssh_key_import => false } }
+
+      it { should have_sshkey_resource_count(0) }
     end
   end
-
-  describe 'with hiera_merge parameter specified' do
-    context 'as a non-boolean or non-string' do
-      let(:facts) { default_facts.merge( { :fqdn => 'hieramerge.example.com'} )}
-      let(:params) { { :hiera_merge => ['not_a_boolean','or_a_string'] } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-
-    context 'as an invalid string' do
-      let(:params) { { :hiera_merge => 'invalid_string' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::hiera_merge may be either 'true' or 'false' and is set to <invalid_string>./)
-      end
-    end
-
-    ['true',true].each do |value|
-      context "as #{value} with hiera data getting collected" do
-        let(:facts) { default_facts.merge( { :fqdn => 'hieramerge.example.com'} )}
-        let(:params) { { :hiera_merge => value } }
-
-        it { should compile.with_all_deps }
-
-        it { should contain_class('ssh') }
-
-        it { should contain_file('sshd_config').with_content(/^\s*DenyUsers denyuser_from_fqdn/) }
-        it { should contain_file('sshd_config').with_content(/^\s*DenyGroups denygroup_from_fqdn/) }
-        it { should contain_file('sshd_config').with_content(/^\s*AllowUsers allowuser_from_fqdn/) }
-        it { should contain_file('sshd_config').with_content(/^\s*AllowGroups allowgroup_from_fqdn/) }
-
-      end
-    end
-
-    context "as true with with hiera data getting merged through levels" do
-      let(:facts) do
-        default_facts.merge(
-          {
-            :fqdn              => 'hieramerge.example.com',
-            :specific          => 'test_hiera_merge',
-          }
-        )
-      end
-      let(:params) { { :hiera_merge => true } }
-
-      it { should compile.with_all_deps }
-
-      it { should contain_class('ssh') }
-
-      it { should contain_file('sshd_config').with_content(/^\s*DenyUsers denyuser_from_fqdn denyuser_from_fact/) }
-      it { should contain_file('sshd_config').with_content(/^\s*DenyGroups denygroup_from_fqdn denygroup_from_fact/) }
-      it { should contain_file('sshd_config').with_content(/^\s*AllowUsers allowuser_from_fqdn allowuser_from_fact/) }
-      it { should contain_file('sshd_config').with_content(/^\s*AllowGroups allowgroup_from_fqdn allowgroup_from_fact/) }
-
-    end
-
-    context "as true with no hiera data provided" do
-      let(:facts) do
-        default_facts.merge(
-          {
-            :osfamily               => 'Suse',
-            :operatingsystem        => 'SLES',
-            :operatingsystemrelease => '11.4',
-            :architecture           => 'x86_64',
-          }
-        )
-      end
-      let(:params) { { :hiera_merge => true } }
-
-      it { should compile.with_all_deps }
-
-      it { should contain_class('ssh') }
-
-      it { should contain_file('sshd_config').without_content(/^\s*DenyUsers/) }
-      it { should contain_file('sshd_config').without_content(/^\s*DenyGroups/) }
-      it { should contain_file('sshd_config').without_content(/^\s*AllowUsers/) }
-      it { should contain_file('sshd_config').without_content(/^\s*AllowGroups/) }
-
-    end
-
-    ['false',false].each do |value|
-      context "as #{value}" do
-        let(:params) { { :hiera_merge => value } }
-
-        it { should compile.with_all_deps }
-
-        it { should contain_class('ssh') }
-      end
-    end
-  end
-
-  describe 'with ssh_package_adminfile parameter specified' do
-    context 'as a valid path' do
-      let(:facts) { default_solaris_facts }
-      let(:params) { { :ssh_package_adminfile => '/var/tmp/admin' } }
-
-      ['SUNWsshcu','SUNWsshdr','SUNWsshdu','SUNWsshr','SUNWsshu'].each do |pkg|
-        it {
-          should contain_package(pkg).with({
-            'ensure'    => 'installed',
-            'source'    => '/var/spool/pkg',
-            'adminfile' => '/var/tmp/admin',
-          })
-        }
-      end
-    end
-
-    context 'as an invalid path' do
-      let(:facts) { default_solaris_facts }
-      let(:params) { { :ssh_package_adminfile => 'invalid/path' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not an absolute path/)
-      end
-    end
-  end
-
-  describe 'with sshd_config_xauth_location parameter specified' do
-    context 'as a valid path' do
-      let(:params) { { :sshd_config_xauth_location => '/opt/ssh/bin/xauth' } }
-
-      it { should contain_file('sshd_config').with_content(/^XAuthLocation \/opt\/ssh\/bin\/xauth$/) }
-    end
-
-    context 'as an invalid path' do
-      let(:params) { { :sshd_config_xauth_location => 'invalid/path' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not an absolute path/)
-      end
-    end
-
-    context 'as an invalid type' do
-      let(:params) { { :sshd_config_xauth_location => true } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  describe 'with ssh_package_source parameter specified' do
-    let(:facts) { default_solaris_facts }
-    context 'as a valid path' do
-      let(:params) { { :ssh_package_source => '/mnt/packages' } }
-
-      ['SUNWsshcu','SUNWsshdr','SUNWsshdu','SUNWsshr','SUNWsshu'].each do |pkg|
-        it {
-          should contain_package(pkg).with({
-            'ensure'    => 'installed',
-            'source'    => '/mnt/packages',
-            'adminfile' => nil,
-          })
-        }
-      end
-    end
-
-    context 'as an invalid path' do
-      let(:params) { { :ssh_package_source => 'invalid/path' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not an absolute path/)
-      end
-    end
-
-    context 'as an invalid type' do
-      let(:params) { { :ssh_package_source => true } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  describe 'with parameter ssh_config_forward_x11_trusted' do
-    ['yes','no'].each do |value|
-      context "specified as #{value}" do
-        let(:params) { { :ssh_config_forward_x11_trusted => value } }
-
-        it { should contain_file('ssh_config').with_content(/^\s*ForwardX11Trusted #{value}$/) }
-      end
-    end
-
-    context 'not specified' do
-      let(:facts) { default_solaris_facts }
-      it { should_not contain_file('ssh_config').with_content(/^\s*ForwardX11Trusted/) }
-    end
-
-    ['YES',true].each do |value|
-      context "specified an invalid value #{value}" do
-        let(:params) { { :ssh_config_forward_x11_trusted => value } }
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::ssh_config_forward_x11_trusted may be either 'yes' or 'no' and is set to <#{value}>\./)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter ssh_gssapidelegatecredentials' do
-    ['yes','no'].each do |value|
-      context "specified as #{value}" do
-        let(:facts) { default_solaris_facts }
-        let(:params) { { :ssh_gssapidelegatecredentials => value } }
-
-        it { should contain_file('ssh_config').with_content(/^GSSAPIDelegateCredentials #{value}$/) }
-      end
-    end
-
-    ['YES',true].each do |value|
-      context "specified an invalid value #{value}" do
-        let(:params) { { :ssh_gssapidelegatecredentials => value } }
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::ssh_gssapidelegatecredentials may be either 'yes' or 'no' and is set to <#{value}>\./)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter ssh_gssapiauthentication' do
-    ['yes','no'].each do |value|
-      context "specified as valid #{value} (as #{value.class})" do
-        let(:params) { { :ssh_gssapiauthentication => value } }
-
-        it { should contain_file('ssh_config').with_content(/^\s*GSSAPIAuthentication #{value}$/) }
-      end
-    end
-
-    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :ssh_gssapiauthentication => value } }
-
-        if value.is_a?(Array)
-          value = value.join
-        elsif value.is_a?(Hash)
-          value = '{ha => sh}'
-        end
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::ssh_gssapiauthentication may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter ssh_hostbasedauthentication' do
-    ['yes','no'].each do |value|
-      context "specified as valid #{value} (as #{value.class})" do
-        let(:params) { { :ssh_hostbasedauthentication => value } }
-
-        it { should contain_file('ssh_config').with_content(/^\s*HostbasedAuthentication #{value}$/) }
-      end
-    end
-
-    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :ssh_hostbasedauthentication => value } }
-
-        if value.is_a?(Array)
-          value = value.join
-        elsif value.is_a?(Hash)
-          value = '{ha => sh}'
-        end
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::ssh_hostbasedauthentication may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter ssh_strict_host_key_checking' do
-    ['yes','no', 'ask'].each do |value|
-      context "specified as valid #{value} (as #{value.class})" do
-        let(:params) { { :ssh_strict_host_key_checking => value } }
-
-        it { should contain_file('ssh_config').with_content(/^\s*StrictHostKeyChecking #{value}$/) }
-      end
-    end
-
-    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :ssh_strict_host_key_checking => value } }
-
-        if value.is_a?(Array)
-          value = value.join
-        elsif value.is_a?(Hash)
-          value = '{ha => sh}'
-        end
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::ssh_strict_host_key_checking may be 'yes', 'no' or 'ask' and is set to <#{Regexp.escape(value.to_s)}>\./)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter ssh_enable_ssh_keysign' do
-    ['yes','no'].each do |value|
-      context "specified as valid #{value} (as #{value.class})" do
-        let(:params) { { :ssh_enable_ssh_keysign => value } }
-
-        it { should contain_file('ssh_config').with_content(/^\s*EnableSSHKeysign #{value}$/) }
-      end
-    end
-
-    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :ssh_enable_ssh_keysign => value } }
-
-        if value.is_a?(Array)
-          value = value.join
-        elsif value.is_a?(Hash)
-          value = '{ha => sh}'
-        end
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::ssh_enable_ssh_keysign may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter sshd_gssapiauthentication' do
-    ['yes','no'].each do |value|
-      context "specified as valid #{value} (as #{value.class})" do
-        let(:params) { { :sshd_gssapiauthentication => value } }
-
-        it { should contain_file('sshd_config').with_content(/^GSSAPIAuthentication #{value}$/) }
-      end
-    end
-
-    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :sshd_gssapiauthentication => value } }
-
-        if value.is_a?(Array)
-          value = value.join
-        elsif value.is_a?(Hash)
-          value = '{ha => sh}'
-        end
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_gssapiauthentication may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter sshd_gssapikeyexchange' do
-    ['yes','no'].each do |value|
-      context "specified as #{value}" do
-        let(:params) { { :sshd_gssapikeyexchange => value } }
-
-        it { should contain_file('sshd_config').with_content(/^GSSAPIKeyExchange #{value}$/) }
-      end
-    end
-
-    context 'not specified' do
-
-      it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPIKeyExchange/) }
-    end
-
-    ['YES',true].each do |value|
-      context "specified an invalid value #{value}" do
-        let(:params) { { :sshd_gssapikeyexchange => value } }
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_gssapikeyexchange may be either 'yes' or 'no' and is set to <#{value}>\./)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter sshd_pamauthenticationviakbdint' do
-    ['yes','no'].each do |value|
-      context "specified as #{value}" do
-        let(:params) { { :sshd_pamauthenticationviakbdint => value } }
-
-        it { should contain_file('sshd_config').with_content(/^PAMAuthenticationViaKBDInt #{value}$/) }
-      end
-    end
-
-    context 'not specified' do
-
-      it { should_not contain_file('sshd_config').with_content(/^\s*PAMAuthenticationViaKBDInt/) }
-    end
-
-    ['YES',true].each do |value|
-      context "specified an invalid value #{value}" do
-        let(:params) { { :sshd_pamauthenticationviakbdint => value } }
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_pamauthenticationviakbdint may be either 'yes' or 'no' and is set to <#{value}>\./)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter sshd_gssapicleanupcredentials' do
-    ['yes','no'].each do |value|
-      context "specified as #{value}" do
-        let(:params) { { :sshd_gssapicleanupcredentials => value } }
-
-        it { should contain_file('sshd_config').with_content(/^GSSAPICleanupCredentials #{value}$/) }
-      end
-    end
-
-    context 'not specified' do
-      let(:facts) { default_solaris_facts }
-
-      it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPICleanupCredentials/) }
-    end
-
-    ['YES',true].each do |value|
-      context "specified an invalid value #{value}" do
-        let(:params) { { :sshd_gssapicleanupcredentials => value } }
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_gssapicleanupcredentials may be either 'yes' or 'no' and is set to <#{value}>\./)
-        end
-      end
-    end
-  end
-
-
-  describe 'with parameter ssh_sendenv specified' do
-    ['true',true].each do |value|
-      context "as #{value}" do
-        let(:params) { { :ssh_sendenv => value } }
-
-        it { should contain_file('ssh_config').with_content(/^\s*SendEnv/) }
-      end
-    end
-
-    ['false',false].each do |value|
-      context "as #{value}" do
-        let(:params) { { :ssh_sendenv => value } }
-
-        it { should_not contain_file('ssh_config').with_content(/^\s*SendEnv/) }
-      end
-    end
-
-    context 'as an invalid string' do
-      let(:params) { { :ssh_sendenv => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::ssh_sendenv may be either 'true' or 'false' and is set to <invalid>\./)
-      end
-    end
-
-    context 'as an invalid type' do
-      let(:params) { { :ssh_sendenv => ['invalid','type'] } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::ssh_sendenv type must be true or false\./)
-      end
-    end
-  end
-
-  describe 'with paramter sshd_config_maxauthtries specified'  do
-    context 'as a valid integer' do
-     let(:params) { { :sshd_config_maxauthtries => 6}}
-     it { should contain_file('sshd_config').with_content(/^MaxAuthTries 6$/)}
-    end
-    context 'as an invalid type' do
-      let(:params) { { :sshd_config_maxauthtries => 'BOGUS'} }
-      it 'should fail' do
-        expect{
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_maxauthtries must be a valid number and is set to <BOGUS>\./)
-      end
-    end
- end
-
-  describe 'with parameter sshd_config_maxstartups specified' do
-    ['10','10:30:100'].each do |value|
-      context "as a valid string - #{value}" do
-        let(:params) { { :sshd_config_maxstartups => value } }
-
-        it { should contain_file('sshd_config').with_content(/^MaxStartups #{value}$/) }
-      end
-    end
-
-    ['10a',true,'10:30:1a'].each do |value|
-      context "as an invalid string - #{value}" do
-        let(:params) { { :sshd_config_maxstartups => value } }
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_config_maxstartups may be either an integer or three integers separated with colons, such as 10:30:100\. Detected value is <#{value}>\./)
-        end
-      end
-    end
-
-    context 'as an invalid type' do
-      let(:params) { { :sshd_config_maxstartups => true } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  describe 'with parameter sshd_config_maxsessions specified' do
-    context 'as a valid integer' do
-      let(:params) { { :sshd_config_maxsessions => 10 } }
-
-      it { should contain_file('sshd_config').with_content(/^MaxSessions 10$/) }
-    end
-
-    context 'as a valid string <unset>' do
-      let(:params) { { :sshd_config_maxsessions => 'unset' } }
-
-      it { should contain_file('sshd_config').without_content(/^\s*MaxSessions/) }
-    end
-
-    context 'as an invalid type' do
-      let(:params) { { :sshd_config_maxsessions => 'BOGUS' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
-
-  describe 'with parameter sshd_acceptenv specified' do
-    ['true',true].each do |value|
-      context "as #{value}" do
-        let(:params) { { :sshd_acceptenv => value } }
-
-        it { should contain_file('sshd_config').with_content(/^\s*AcceptEnv/) }
-      end
-    end
-
-    ['false',false].each do |value|
-      context "as #{value}" do
-        let(:params) { { :sshd_acceptenv => value } }
-
-        it { should_not contain_file('sshd_config').with_content(/^\s*AcceptEnv/) }
-      end
-    end
-
-    context 'as an invalid string' do
-      let(:params) { { :sshd_acceptenv => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_acceptenv may be either 'true' or 'false' and is set to <invalid>\./)
-      end
-    end
-
-    context 'as an invalid type' do
-      let(:params) { { :sshd_acceptenv => ['invalid','type'] } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_acceptenv type must be true or false\./)
-      end
-    end
-  end
-
-  describe 'with parameter service_hasstatus' do
-    ['true',true,'false',false].each do |value|
-      context "specified as #{value}" do
-        let(:params) { { :service_hasstatus => value } }
-
-        it {
-          should contain_service('sshd_service').with({
-            'ensure'     => 'running',
-            'name'       => 'sshd',
-            'enable'     => 'true',
-            'hasrestart' => 'true',
-            'hasstatus'  => value,
-            'subscribe'  => 'File[sshd_config]',
-          })
-        }
-      end
-    end
-
-    context 'specified as an invalid string' do
-      let(:params) { { :service_hasstatus => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::service_hasstatus must be 'true' or 'false' and is set to <invalid>\./)
-      end
-    end
-
-    context 'specified as an invalid type' do
-      let(:params) { { :service_hasstatus => ['invalid','type'] } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::service_hasstatus must be true or false\./)
-      end
-    end
-  end
-
-  describe 'with parameter ssh_config_global_known_hosts_file' do
-    context 'specified as a valid path' do
-      let(:params) { { :ssh_config_global_known_hosts_file => '/valid/path' } }
-
-      it {
-        should contain_file('ssh_known_hosts').with({
-          'ensure' => 'file',
-          'path'   => '/valid/path',
-          'owner'  => 'root',
-          'group'  => 'root',
-          'mode'   => '0644',
-          'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
-        })
-      }
-
-      it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile \/valid\/path$/) }
-    end
-
-    context 'specified as an invalid path' do
-      let(:params) { { :ssh_config_global_known_hosts_file => 'invalid/path' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/\"invalid\/path\" is not an absolute path\./)
-      end
-    end
-
-    context 'specified as an invalid type' do
-      let(:params) { { :ssh_config_global_known_hosts_file => { 'invalid' => 'type'} } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not an absolute path/)
-      end
-    end
-  end
-
-  describe 'with parameter ssh_config_global_known_hosts_list' do
-    context 'when set to an array of valid absolute paths' do
-      let(:params) { {'ssh_config_global_known_hosts_list' => ['/valid/path1','/valid/path2'] } }
-
-      it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile.*\/valid\/path1 \/valid\/path2$/) }
-    end
-
-    context 'specified as an invalid path' do
-      let(:params) { { :ssh_config_global_known_hosts_list => ['/valid/path','invalid/path'] } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/\"invalid\/path\" is not an absolute path\./)
-      end
-    end
-
-    ['YES',true,2.42,a = { 'ha' => 'sh' }].each do |value|
-       context "specified as invalid value #{value} (as #{value.class})" do
-         let(:params) { { :ssh_config_global_known_hosts_list => value } }
-
-         if value.is_a?(Hash)
-           value = '{ha => sh}'
-         end
-
-         it 'should fail' do
-           expect {
-             should contain_class('ssh')
-           }.to raise_error(Puppet::Error, /is not an Array/)
-         end
-       end
-     end
-  end
-
-  describe 'with parameter ssh_config_user_known_hosts_file' do
-    context 'when set to an array of paths' do
-      let(:params) { {'ssh_config_user_known_hosts_file' => ['valid/path1','/valid/path2'] } }
-
-      it { should contain_file('ssh_config').with_content(/^\s*UserKnownHostsFile valid\/path1 \/valid\/path2$/) }
-    end
-
-    ['YES',true,2.42,a = { 'ha' => 'sh' }].each do |value|
-       context "specified as invalid value #{value} (as #{value.class})" do
-         let(:params) { { :ssh_config_user_known_hosts_file => value } }
-
-         if value.is_a?(Hash)
-           value = '{ha => sh}'
-         end
-
-         it 'should fail' do
-           expect {
-             should contain_class('ssh')
-           }.to raise_error(Puppet::Error, /is not an Array/)
-         end
-       end
-     end
-  end
-
-  describe 'with parameter ssh_config_global_known_hosts_owner' do
-    context 'specified as a valid string' do
-      let(:params) { { :ssh_config_global_known_hosts_owner => 'gh' } }
-
-      it {
-        should contain_file('ssh_known_hosts').with({
-          'ensure' => 'file',
-          'path'   => '/etc/ssh/ssh_known_hosts',
-          'owner'  => 'gh',
-          'group'  => 'root',
-          'mode'   => '0644',
-          'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
-        })
-      }
-    end
-
-    context 'specified as an invalid type [non-string]' do
-      let(:params) { { :ssh_config_global_known_hosts_owner => ['invalid','type'] } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/\[\"invalid\", \"type\"\] is not a string\.  It looks to be a Array/)
-      end
-    end
-  end
-
-  describe 'with parameter ssh_config_global_known_hosts_group' do
-    context 'specified as a valid string' do
-      let(:params) { { :ssh_config_global_known_hosts_group => 'gh' } }
-
-      it {
-        should contain_file('ssh_known_hosts').with({
-          'ensure' => 'file',
-          'path'   => '/etc/ssh/ssh_known_hosts',
-          'owner'  => 'root',
-          'group'  => 'gh',
-          'mode'   => '0644',
-          'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
-        })
-      }
-    end
-
-    context 'specified as an invalid type [non-string]' do
-      let(:params) { { :ssh_config_global_known_hosts_group => ['invalid','type'] } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/\[\"invalid\", \"type\"\] is not a string\.  It looks to be a Array/)
-      end
-    end
-  end
-
-  describe 'with parameter ssh_config_global_known_hosts_mode' do
-    context 'specified as a valid mode' do
-      let(:params) { { :ssh_config_global_known_hosts_mode => '0666' } }
-
-      it {
-        should contain_file('ssh_known_hosts').with({
-          'ensure' => 'file',
-          'path'   => '/etc/ssh/ssh_known_hosts',
-          'owner'  => 'root',
-          'group'  => 'root',
-          'mode'   => '0666',
-          'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
-        })
-      }
-    end
-
-    ['666','0842','06666'].each do |value|
-      context "specified as invalid mode - #{value}" do
-        let(:params) { { :ssh_config_global_known_hosts_mode => value } }
-
-        it 'should fail' do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation\. Detected value is <#{value}>\./)
-        end
-      end
-    end
-
-    context 'specified as an invalid type [non-string]' do
-      let(:params) { { :ssh_config_global_known_hosts_mode => ['invalid','type'] } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation\. Detected value is <[\[]?invalid.*type[\]]?/)
-      end
-    end
-  end
-
-  describe 'with ssh_key_import parameter specified' do
-    context 'as a non-boolean or non-string' do
-    let(:params) { { :ssh_key_import => ['not_a_boolean','or_a_string'] } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-
-    context 'as an invalid string' do
-      let(:params) { { :ssh_key_import => 'invalid_string' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::ssh_key_import may be either 'true' or 'false' and is set to <invalid_string>\./)
-      end
-    end
-
-    ['true',true].each do |value|
-      context "as #{value}" do
-        let(:params) { { :ssh_key_import => value } }
-
-        it { should compile.with_all_deps }
-
-        it { should contain_class('ssh') }
-
-        it {
-          should contain_file('ssh_known_hosts').with({
-            'ensure'  => 'file',
-            'path'    => '/etc/ssh/ssh_known_hosts',
-            'owner'   => 'root',
-            'group'   => 'root',
-            'mode'    => '0644',
-            'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
-          })
-        }
-      end
-    end
-
-    ['false',false].each do |value|
-      context "as #{value}" do
-        let(:params) { { :ssh_key_import => value } }
-
-        it { should compile.with_all_deps }
-
-        it { should contain_class('ssh') }
-      end
-    end
-  end
-
-  describe 'with parameter sshd_hostbasedauthentication' do
-    ['yes','no'].each do |value|
-      context "specified as valid #{value} (as #{value.class})" do
-        let(:params) { { :sshd_hostbasedauthentication => value } }
-
-        it { should contain_file('sshd_config').with_content(/^HostbasedAuthentication #{value}$/) }
-      end
-    end
-
-    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :sshd_hostbasedauthentication => value } }
-
-        if value.is_a?(Array)
-          value = value.join
-        end
-
-        it do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_hostbasedauthentication may be either 'yes' or 'no' and is set to/)
-        end
-      end
-    end
-  end
-
-  [true,'invalid'].each do |pubkeyacceptedkeytypes|
-    context "with sshd_pubkeyacceptedkeytypes set to invalid value #{pubkeyacceptedkeytypes}" do
-      let(:params) { { :sshd_pubkeyacceptedkeytypes => pubkeyacceptedkeytypes } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not/)
-      end
-    end
-  end
-
-  [true,'invalid'].each do |authenticationmethods|
-    context "with sshd_config_authenticationmethods set to invalid value #{authenticationmethods}" do
-      let(:params) { { :sshd_config_authenticationmethods => authenticationmethods } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/is not/)
-      end
-    end
-  end
-
-  describe 'with parameter sshd_pubkeyauthentication' do
-    ['yes','no'].each do |value|
-      context "specified as valid #{value} (as #{value.class})" do
-        let(:params) { { :sshd_pubkeyauthentication => value } }
-
-        it { should contain_file('sshd_config').with_content(/^PubkeyAuthentication #{value}$/) }
-      end
-    end
-
-    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :sshd_pubkeyauthentication => value } }
-        if value.is_a?(Array)
-          value = value.join
-        end
-
-        it do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_pubkeyauthentication may be either 'yes' or 'no' and is set to/)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter sshd_ignoreuserknownhosts' do
-    ['yes','no'].each do |value|
-      context "specified as valid #{value} (as #{value.class})" do
-        let(:params) { { :sshd_ignoreuserknownhosts => value } }
-
-        it { should contain_file('sshd_config').with_content(/^IgnoreUserKnownHosts #{value}$/) }
-      end
-    end
-
-    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :sshd_ignoreuserknownhosts => value } }
-        if value.is_a?(Array)
-          value = value.join
-        end
-
-        it do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_ignoreuserknownhosts may be either 'yes' or 'no' and is set to/)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter sshd_ignorerhosts' do
-    ['yes','no'].each do |value|
-      context "specified as valid #{value} (as #{value.class})" do
-        let(:params) { { :sshd_ignorerhosts => value } }
-
-        it { should contain_file('sshd_config').with_content(/^IgnoreRhosts #{value}$/) }
-      end
-    end
-
-    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :sshd_ignorerhosts => value } }
-        if value.is_a?(Array)
-          value = value.join
-        end
-
-        it do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_ignorerhosts may be either 'yes' or 'no' and is set to/)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter manage_service' do
-    ['YES','badvalue',2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
-      context "specified as invalid value #{value} (as #{value.class})" do
-        let(:params) { { :manage_service => value } }
-        it do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/(is not a boolean|Unknown type of boolean)/)
-        end
-      end
-    end
-
-    ['true', true].each do |value|
-      context "specified as valid true value #{value} (as #{value.class})" do
-        let(:params) { { :manage_service => value } }
-        it { should contain_service('sshd_service') }
-      end
-    end
-
-    ['false', false].each do |value|
-      context "specified as valid false value #{value} (as #{value.class})" do
-        let(:params) { { :manage_service => value } }
-        it { should_not contain_service('sshd_service') }
-      end
-    end
-  end
-
-  describe 'sshd_config_tcp_keepalive param' do
-    ['yes','no','unset'].each do |value|
-      context "set to #{value}" do
-        let (:params) { { :sshd_config_tcp_keepalive => value } }
-
-        if value == 'unset'
-          it { should contain_file('sshd_config').without_content(/^\s*TCPKeepAlive/) }
-        else
-          it { should contain_file('sshd_config').with_content(/^TCPKeepAlive #{value}$/) }
-        end
-      end
-    end
-
-    context 'when set to an invalid value' do
-      let (:params) { { :sshd_config_tcp_keepalive => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_tcp_keepalive may be either \'yes\', \'no\' or \'unset\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-  describe 'sshd_config_use_privilege_separation param' do
-    ['yes','no','sandbox'].each do |value|
-      context "set to #{value}" do
-        let (:params) { { :sshd_config_use_privilege_separation => value } }
-
-        it { should contain_file('sshd_config').with_content(/^UsePrivilegeSeparation #{value}$/) }
-      end
-    end
-
-    context 'when set to an invalid value' do
-      let (:params) { { :sshd_config_use_privilege_separation => 'invalid' } }
-
-      it 'should fail' do
-        expect {
-          should contain_class('ssh')
-        }.to raise_error(Puppet::Error,/ssh::sshd_config_use_privilege_separation may be either \'yes\', \'no\' or \'sandbox\' and is set to <invalid>\./)
-      end
-    end
-  end
-
-  describe 'with parameter sshd_addressfamily' do
-    ['any','inet','inet6'].each do |value|
-      context "set to a valid entry of #{value}" do
-        let(:params) { { :sshd_addressfamily => value } }
-        it { should contain_file('sshd_config').with_content(/^AddressFamily #{value}$/) }
-      end
-    end
-
-    ['foo','bar',123].each do |value|
-      context "specified as invalid value #{value}" do
-        let(:params) { { :sshd_addressfamily => value } }
-        it do
-          expect {
-            should contain_class('ssh')
-          }.to raise_error(Puppet::Error,/ssh::sshd_addressfamily can be undef, 'any', 'inet' or 'inet6' and is set to/)
-        end
-      end
-    end
-  end
-
-  describe 'with parameter ssh_config_use_roaming' do
-    ['yes','no','unset'].each do |value|
-      context "set to valid value #{value}" do
-        let(:params) { { :ssh_config_use_roaming => value } }
-        if value == 'unset'
-          it { should contain_file('ssh_config').without_content(/^\s*UseRoaming/) }
-        else
-          it { should contain_file('ssh_config').with_content(/^\s*UseRoaming #{value}$/) }
-        end
-      end
-    end
-  end
-
-  describe 'variable type and content validations' do
-    mandatory_params = {} if mandatory_params.nil?
-
-    validations = {
-      'hash' => {
-        :name    => %w[config_entries],
-        :valid   => [], # valid hashes are to complex to block test them here. types::mount should have its own spec tests anyway.
-        :invalid => ['string', %w[array], 3, 2.42, true],
-        :message => 'is not a Hash',
-      },
-      'regex (yes|no|unset)' => {
-        :name    => %w(ssh_config_use_roaming),
-        :valid   => ['yes', 'no', 'unset'],
-        :invalid => ['string', %w(array), { 'ha' => 'sh' }, 3, 2.42, true, false, nil],
-        :message => 'may be either \'yes\', \'no\' or \'unset\'',
-      },
-    }
-
-    validations.sort.each do |type, var|
-      var[:name].each do |var_name|
-        var[:params] = {} if var[:params].nil?
-        var[:valid].each do |valid|
-          context "when #{var_name} (#{type}) is set to valid #{valid} (as #{valid.class})" do
-            let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => valid, }].reduce(:merge) }
-            it { should compile }
-          end
-        end
-
-        var[:invalid].each do |invalid|
-          context "when #{var_name} (#{type}) is set to invalid #{invalid} (as #{invalid.class})" do
-            let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => invalid, }].reduce(:merge) }
-            it { is_expected.to compile.and_raise_error(/#{var[:message]}/) }
-          end
-        end
-      end # var[:name].each
-    end # validations.sort.each
-  end # describe 'variable type and content validations'
 end
diff --git a/spec/classes/server_spec.rb b/spec/classes/server_spec.rb
new file mode 100644
index 0000000..89ea304
--- /dev/null
+++ b/spec/classes/server_spec.rb
@@ -0,0 +1,1321 @@
+require 'spec_helper'
+
+describe 'ssh::server' do
+
+  osfamily_matrix = {
+#    'Debian-7' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Debian',
+#      :operatingsystemrelease => '7',
+#      :ssh_version            => 'OpenSSH_6.0p1',
+#      :ssh_version_numeric    => '6.0',
+#      :sshd_packages           => ['openssh-server', 'openssh-client'],
+#      :sshd_config_mode       => '0600',
+#      :sshd_service_name      => 'ssh',
+#      :sshd_service_hasstatus => true,
+#      :sshd_config_fixture    => 'sshd_config_debian',
+#      :ssh_config_fixture     => 'ssh_config_debian',
+#    },
+    'RedHat-5' => {
+      :architecture           => 'x86_64',
+      :os                     => {
+        :family  => 'RedHat',
+        :release => {
+          :major  => '5',
+        },
+      },
+      :ssh_version            => 'OpenSSH_4.3p2',
+      :ssh_version_numeric    => '4.3',
+      :sshd_packages           => ['openssh-server'],
+      :sshd_config_mode       => '0600',
+      :sshd_service_name      => 'sshd',
+      :sshd_service_hasstatus => true,
+      :sshd_config_fixture    => 'sshd_config_el5',
+    },
+    'EL-6' => {
+      :architecture           => 'x86_64',
+      :os                     => {
+        :family  => 'RedHat',
+        :release => {
+          :major  => '6',
+        },
+      },
+      :ssh_version            => 'OpenSSH_5.3p1',
+      :ssh_version_numeric    => '5.3',
+      :sshd_packages          => ['openssh-server'],
+      :sshd_config_mode       => '0600',
+      :sshd_service_name      => 'sshd',
+      :sshd_service_hasstatus => true,
+      :sshd_config_fixture    => 'sshd_config_el6',
+    },
+    'EL-7' => {
+      :architecture           => 'x86_64',
+      :os                     => {
+        :family  => 'RedHat',
+        :release => {
+          :major  => '7',
+        },
+      },
+      :ssh_version            => 'OpenSSH_7.4p1',
+      :ssh_version_numeric    => '7.4',
+      :sshd_config_mode       => '0600',
+      :sshd_service_name      => 'sshd',
+      :sshd_service_hasstatus => true,
+      :sshd_packages          => ['openssh-server'],
+      :sshd_config_fixture    => 'sshd_config_el7',
+    },
+#    'Suse-10-x86_64' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '10.4',
+#      :ssh_version            => 'OpenSSH_5.1p1',
+#      :ssh_version_numeric    => '5.1',
+#      :sshd_packages           => ['openssh'],
+#      :sshd_config_mode       => '0600',
+#      :sshd_service_name      => 'sshd',
+#      :sshd_service_hasstatus => true,
+#      :sshd_config_fixture    => 'sshd_config_suse_x86_64',
+#      :ssh_config_fixture     => 'ssh_config_suse_old',
+#    },
+#    'Suse-10-i386' => {
+#      :architecture           => 'i386',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '10.4',
+#      :ssh_version            => 'OpenSSH_5.1p1',
+#      :ssh_version_numeric    => '5.1',
+#      :sshd_packages           => ['openssh'],
+#      :sshd_config_mode       => '0600',
+#      :sshd_service_name      => 'sshd',
+#      :sshd_service_hasstatus => true,
+#      :sshd_config_fixture    => 'sshd_config_suse_i386',
+#      :ssh_config_fixture     => 'ssh_config_suse_old',
+#    },
+#    'Suse-11-x86_64' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '11.4',
+#      :ssh_version            => 'OpenSSH_6.6.1p1',
+#      :ssh_version_numeric    => '6.6',
+#      :sshd_packages           => ['openssh'],
+#      :sshd_config_mode       => '0600',
+#      :sshd_service_name      => 'sshd',
+#      :sshd_service_hasstatus => true,
+#      :sshd_config_fixture    => 'sshd_config_suse_x86_64',
+#      :ssh_config_fixture     => 'ssh_config_suse',
+#    },
+#    'Suse-11-i386' => {
+#      :architecture           => 'i386',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '11.4',
+#      :ssh_version            => 'OpenSSH_6.6.1p1',
+#      :ssh_version_numeric    => '6.6',
+#      :sshd_packages           => ['openssh'],
+#      :sshd_config_mode       => '0600',
+#      :sshd_service_name      => 'sshd',
+#      :sshd_service_hasstatus => true,
+#      :sshd_config_fixture    => 'sshd_config_suse_i386',
+#      :ssh_config_fixture     => 'ssh_config_suse',
+#    },
+#    'Suse-12-x86_64' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Suse',
+#      :operatingsystem        => 'SLES',
+#      :operatingsystemrelease => '12.0',
+#      :ssh_version            => 'OpenSSH_6.6.1p1',
+#      :ssh_version_numeric    => '6.6',
+#      :sshd_packages           => ['openssh'],
+#      :sshd_config_mode       => '0600',
+#      :sshd_service_name      => 'sshd',
+#      :sshd_service_hasstatus => true,
+#      :sshd_config_fixture    => 'sshd_config_sles_12_x86_64',
+#      :ssh_config_fixture     => 'ssh_config_suse',
+#    },
+#    'Solaris-5.11' => {
+#      :architecture           => 'i86pc',
+#      :osfamily               => 'Solaris',
+#      :kernelrelease          => '5.11',
+#      :ssh_version            => 'Sun_SSH_2.2',
+#      :ssh_version_numeric    => '2.2',
+#      :sshd_packages           => ['network/ssh', 'network/ssh/ssh-key', 'service/network/ssh'],
+#      :sshd_config_mode       => '0644',
+#      :sshd_service_name      => 'ssh',
+#      :sshd_service_hasstatus => true,
+#      :sshd_config_fixture    => 'sshd_config_solaris',
+#      :ssh_config_fixture     => 'ssh_config_solaris',
+#    },
+#    'Solaris-5.10' => {
+#      :architecture           => 'i86pc',
+#      :osfamily               => 'Solaris',
+#      :kernelrelease          => '5.10',
+#      :ssh_version            => 'Sun_SSH_2.2',
+#      :ssh_version_numeric    => '2.2',
+#      :sshd_packages           => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'],
+#      :sshd_config_mode       => '0644',
+#      :sshd_service_name      => 'ssh',
+#      :sshd_service_hasstatus => true,
+#      :sshd_config_fixture    => 'sshd_config_solaris',
+#      :ssh_config_fixture     => 'ssh_config_solaris',
+#    },
+#    'Solaris-5.9' => {
+#      :architecture           => 'i86pc',
+#      :osfamily               => 'Solaris',
+#      :kernelrelease          => '5.9',
+#      :ssh_version            => 'Sun_SSH_2.2',
+#      :ssh_version_numeric    => '2.2',
+#      :sshd_packages           => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'],
+#      :sshd_config_mode       => '0644',
+#      :sshd_service_name      => 'sshd',
+#      :sshd_service_hasstatus => false,
+#      :sshd_config_fixture    => 'sshd_config_solaris',
+#      :ssh_config_fixture     => 'ssh_config_solaris',
+#    },
+#    'Ubuntu-1604' => {
+#      :architecture           => 'x86_64',
+#      :osfamily               => 'Debian',
+#      :operatingsystemrelease => '16.04',
+#      :ssh_version            => 'OpenSSH_7.2p2',
+#      :ssh_version_numeric    => '7.2',
+#      :sshd_packages           => ['openssh-server', 'openssh-client'],
+#      :sshd_config_mode       => '0600',
+#      :sshd_service_name      => 'ssh',
+#      :sshd_service_hasstatus => true,
+#      :sshd_config_fixture    => 'sshd_config_ubuntu1604',
+#      :ssh_config_fixture     => 'ssh_config_ubuntu1604',
+#    },
+  }
+
+  defaults = {
+    :fqdn                   => 'monkey.example.com',
+    :hostname               => 'monkey',
+    :ipaddress              => '127.0.0.1',
+    :root_home              => '/root',
+    :specific               => 'dummy',
+    :sshrsakey              => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==',
+  }
+
+  defaults_solaris = {
+    :fqdn                => 'monkey.example.com',
+    :hostname            => 'monkey',
+    :ipaddress           => '127.0.0.1',
+    :kernelrelease       => '5.10',
+    :osfamily            => 'Solaris',
+    :root_home           => '/root',
+    :specific            => 'dummy',
+    :ssh_version         => 'Sun_SSH_2.2',
+    :ssh_version_numeric => '2.2',
+    :sshrsakey           => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==',
+  }
+
+  default_facts = osfamily_matrix['EL-7'].merge(defaults)
+
+  let(:facts) { default_facts }
+
+  osfamily_matrix.each do |os, facts|
+    context "with default params on osfamily #{os}" do
+      let(:facts) { defaults.merge(facts)}
+
+      # FIXME - first one fails. If you remove the duplicate, the first compile
+      # fails, if you remove both compile lines, then contain class fails and so on. Get this error
+      #
+      # Evaluation Error: Error while evaluating a Resource Statement, Could not autoload puppet/type/service: Could not autoload puppet/provider/service/upstart: Could not autoload puppet/provider/service/debian: Could not autoload puppet/provider/service/init: undefined method `downcase' for nil:NilClass (file: /Users/gh/git/puppet-module-ssh/spec/fixtures/modules/ssh/manifests/server.pp, line: 332, column: 5)
+      it { should compile.with_all_deps }
+      it { should compile.with_all_deps }
+
+      it { should contain_class('ssh::server')}
+
+      facts[:sshd_packages].each do |pkg|
+        it {
+          should contain_package(pkg).with({
+            'ensure' => 'installed',
+          })
+        }
+      end
+
+      it {
+        should contain_file('sshd_config').with({
+          'ensure'  => 'file',
+          'path'    => '/etc/ssh/sshd_config',
+          'owner'   => 'root',
+          'group'   => 'root',
+          'mode'    => facts[:sshd_config_mode],
+        })
+      }
+
+      facts[:sshd_packages].each do |pkg|
+        it {
+          should contain_file('sshd_config').that_requires("Package[#{pkg}]")
+        }
+      end
+
+      sshd_config_fixture = File.read(fixtures("#{facts[:sshd_config_fixture]}_sorted"))
+      it { should contain_file('sshd_config').with_content(sshd_config_fixture) }
+
+      it { should_not contain_file('sshd_banner') }
+
+      it {
+        should contain_service('sshd_service').with({
+          'ensure'     => 'running',
+          'name'       => facts[:sshd_service_name],
+          'enable'     => 'true',
+          'hasrestart' => 'true',
+          'hasstatus'  => facts[:sshd_service_hasstatus],
+          'subscribe'  => 'File[sshd_config]',
+        })
+      }
+    end
+  end
+
+# TODO: test failure on unsupported platforms
+#  context 'with default params on invalid osfamily' do
+#    let(:facts) { default_facts.merge({ :osfamily => 'C64' }) }
+#
+#    it 'should fail' do
+#      expect {
+#        should contain_class('ssh')
+#      }.to raise_error(Puppet::Error,/ssh supports osfamilies RedHat, Suse, Debian and Solaris\. Detected osfamily is <C64>\./)
+#    end
+#  end
+#
+
+  # TODO: test each param here
+  #
+  describe 'with parameter' do
+
+    context 'syslog_facility' do
+      context "set to a valid facility" do
+        let(:params) do { :syslog_facility => 'LOCAL1' } end
+
+        it { should contain_file('sshd_config').with_content(/^SyslogFacility LOCAL1$/) }
+      end
+    end
+
+    context 'stream_local_bind_mask' do
+      context "set to a valid umask" do
+        let(:params) do { :stream_local_bind_mask => '0022' } end
+
+        it { should contain_file('sshd_config').with_content(/^StreamLocalBindMask 0022$/) }
+      end
+    end
+
+    context 'client_alive_count_max' do
+      context "set to a valid Integer" do
+        let(:params) do { :client_alive_count_max => 23 } end
+
+        it { should contain_file('sshd_config').with_content(/^ClientAliveCountMax 23$/) }
+      end
+    end
+
+    context 'client_alive_interval' do
+      context "set to a valid Integer" do
+        let(:params) do { :client_alive_interval => 23 } end
+
+        it { should contain_file('sshd_config').with_content(/^ClientAliveInterval 23$/) }
+      end
+    end
+
+    context 'login_grace_time' do
+      context "set to a valid Integer" do
+        let(:params) do { :login_grace_time => 23 } end
+
+        it { should contain_file('sshd_config').with_content(/^LoginGraceTime 23$/) }
+      end
+    end
+
+    context 'max_auth_tries' do
+      context "set to a valid Integer" do
+        let(:params) do { :max_auth_tries => 23 } end
+
+        it { should contain_file('sshd_config').with_content(/^MaxAuthTries 23$/) }
+      end
+    end
+
+    context 'max_sessions' do
+      context "set to a valid Integer" do
+        let(:params) do { :max_sessions => 23 } end
+
+        it { should contain_file('sshd_config').with_content(/^MaxSessions 23$/) }
+      end
+    end
+
+    context 'x11_display_offset' do
+      context "set to a valid Integer" do
+        let(:params) do { :x11_display_offset => 23 } end
+
+        it { should contain_file('sshd_config').with_content(/^X11DisplayOffset 23$/) }
+      end
+    end
+
+    context 'authorized_keys_command' do
+      context "set to valid string 'test'" do
+        let(:params) do { :authorized_keys_command => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommand test$/) }
+      end
+    end
+
+    context 'authorized_keys_command_user' do
+      context "set to valid string 'test'" do
+        let(:params) do { :authorized_keys_command_user => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommandUser test$/) }
+      end
+    end
+
+    context 'authorized_principals_command' do
+      context "set to valid string 'test'" do
+        let(:params) do { :authorized_principals_command => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsCommand test$/) }
+      end
+    end
+
+    context 'authorized_principals_command_user' do
+      context "set to valid string 'test'" do
+        let(:params) do { :authorized_principals_command_user => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsCommandUser test$/) }
+      end
+    end
+
+    context 'authorized_principals_file' do
+      context "set to valid string 'test'" do
+        let(:params) do { :authorized_principals_file => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsFile test$/) }
+      end
+    end
+
+    context 'banner' do
+      context "set to valid string 'test'" do
+        let(:params) do { :banner => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^Banner test$/) }
+      end
+    end
+
+    context 'challenge_response_authentication' do
+      context "set to valid string 'test'" do
+        let(:params) do { :challenge_response_authentication => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^ChallengeResponseAuthentication test$/) }
+      end
+    end
+
+    context 'chroot_directory' do
+      context "set to valid string 'test'" do
+        let(:params) do { :chroot_directory => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^ChrootDirectory test$/) }
+      end
+    end
+
+    context 'force_command' do
+      context "set to valid string 'test'" do
+        let(:params) do { :force_command => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^ForceCommand test$/) }
+      end
+    end
+
+    context 'host_certificate' do
+      context "set to valid string 'test'" do
+        let(:params) do { :host_certificate => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^HostCertificate test$/) }
+      end
+    end
+
+    context 'host_key_agent' do
+      context "set to valid string 'test'" do
+        let(:params) do { :host_key_agent => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^HostKeyAgent test$/) }
+      end
+    end
+
+    context 'ip_qos' do
+      context "set to valid string 'test'" do
+        let(:params) do { :ip_qos => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^IPQoS test$/) }
+      end
+    end
+
+    context 'log_level' do
+      context "set to valid string 'DEBUG1'" do
+        let(:params) do { :log_level => 'DEBUG1' } end
+
+        it { should contain_file('sshd_config').with_content(/^LogLevel DEBUG1$/) }
+      end
+    end
+
+    context 'max_startups' do
+      context "set to valid string 'test'" do
+        let(:params) do { :max_startups => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^MaxStartups test$/) }
+      end
+    end
+
+    context 'permit_user_environment' do
+      context "set to valid string 'test'" do
+        let(:params) do { :permit_user_environment => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^PermitUserEnvironment test$/) }
+      end
+    end
+
+    context 'pid_file' do
+      context "set to valid string 'test'" do
+        let(:params) do { :pid_file => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^PidFile test$/) }
+      end
+    end
+
+    context 'rekey_limit' do
+      context "set to valid string 'test'" do
+        let(:params) do { :rekey_limit => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^RekeyLimit test$/) }
+      end
+    end
+
+    context 'revoked_keys' do
+      context "set to valid string 'test'" do
+        let(:params) do { :revoked_keys => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^RevokedKeys test$/) }
+      end
+    end
+
+    context 'rdomain' do
+      context "set to valid string 'test'" do
+        let(:params) do { :rdomain => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^RDomain test$/) }
+      end
+    end
+
+    context 'set_env' do
+      context "set to valid string 'test'" do
+        let(:params) do { :set_env => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^SetEnv test$/) }
+      end
+    end
+
+    context 'subsystem' do
+      context "set to valid string 'test'" do
+        let(:params) do { :subsystem => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^Subsystem test$/) }
+      end
+    end
+
+    context 'trusted_user_ca_keys' do
+      context "set to valid string 'test'" do
+        let(:params) do { :trusted_user_ca_keys => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^TrustedUserCAKeys test$/) }
+      end
+    end
+
+    context 'version_addendum' do
+      context "set to valid string 'test'" do
+        let(:params) do { :version_addendum => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^VersionAddendum test$/) }
+      end
+    end
+
+    context 'xauth_location' do
+      context "set to valid string 'test'" do
+        let(:params) do { :xauth_location => 'test' } end
+
+        it { should contain_file('sshd_config').with_content(/^XAuthLocation test$/) }
+      end
+    end
+
+    context 'custom' do
+      context "set to valid string 'Foo test'" do
+        let(:params) do { :custom => 'Foo test' } end
+
+        it { should contain_file('sshd_config').with_content(/^Foo test$/) }
+      end
+    end
+
+    context 'address_family' do
+      ['any','inet','inet6'].each do |v|
+        context "set to valid string #{v}" do
+          let(:params) do { :address_family => v } end
+
+          it { should contain_file('sshd_config').with_content(/^AddressFamily #{v}$/) }
+        end
+      end
+    end
+
+    context 'allow_stream_local_forwarding' do
+      ['yes','all','no','local','remote'].each do |v|
+        context "set to valid string #{v}" do
+          let(:params) do { :allow_stream_local_forwarding => v } end
+
+          it { should contain_file('sshd_config').with_content(/^AllowStreamLocalForwarding #{v}$/) }
+        end
+      end
+    end
+
+    context 'allow_tcp_forwarding' do
+      ['yes','no','local','remote'].each do |v|
+        context "set to valid string #{v}" do
+          let(:params) do { :allow_tcp_forwarding => v } end
+
+          it { should contain_file('sshd_config').with_content(/^AllowTcpForwarding #{v}$/) }
+        end
+      end
+    end
+
+    context 'compression' do
+      ['yes','delayed','no'].each do |v|
+        context "set to valid string #{v}" do
+          let(:params) do { :compression => v } end
+
+          it { should contain_file('sshd_config').with_content(/^Compression #{v}$/) }
+        end
+      end
+    end
+
+    context 'fingerprint_hash' do
+      ['md5','sha256'].each do |v|
+        context "set to valid string #{v}" do
+          let(:params) do { :fingerprint_hash => v } end
+
+          it { should contain_file('sshd_config').with_content(/^FingerprintHash #{v}$/) }
+        end
+      end
+    end
+
+    context 'gateway_ports' do
+      ['no','yes','clientspecified'].each do |v|
+        context "set to valid string #{v}" do
+          let(:params) do { :gateway_ports => v } end
+
+          it { should contain_file('sshd_config').with_content(/^GatewayPorts #{v}$/) }
+        end
+      end
+    end
+
+    context 'permit_tunnel' do
+      ['yes','point-to-point','ethernet','no'].each do |v|
+        context "set to valid string #{v}" do
+          let(:params) do { :permit_tunnel => v } end
+
+          it { should contain_file('sshd_config').with_content(/^PermitTunnel #{v}$/) }
+        end
+      end
+    end
+
+    context 'allow_agent_forwarding' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :allow_agent_forwarding => v } end
+
+          it { should contain_file('sshd_config').with_content(/^AllowAgentForwarding #{v}$/) }
+        end
+      end
+    end
+
+    context 'disable_forwarding' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :disable_forwarding => v } end
+
+          it { should contain_file('sshd_config').with_content(/^DisableForwarding #{v}$/) }
+        end
+      end
+    end
+
+    context 'expose_auth_info' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :expose_auth_info => v } end
+
+          it { should contain_file('sshd_config').with_content(/^ExposeAuthInfo #{v}$/) }
+        end
+      end
+    end
+
+    context 'gss_api_authentication' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :gss_api_authentication => v } end
+
+          it { should contain_file('sshd_config').with_content(/^GSSAPIAuthentication #{v}$/) }
+        end
+      end
+    end
+
+    context 'gss_api_cleanup_credentials' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :gss_api_cleanup_credentials => v } end
+
+          it { should contain_file('sshd_config').with_content(/^GSSAPICleanupCredentials #{v}$/) }
+        end
+      end
+    end
+
+    context 'gss_api_strict_acceptor_check' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :gss_api_strict_acceptor_check => v } end
+
+          it { should contain_file('sshd_config').with_content(/^GSSAPIStrictAcceptorCheck #{v}$/) }
+        end
+      end
+    end
+
+    context 'hostbased_authentication' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :hostbased_authentication => v } end
+
+          it { should contain_file('sshd_config').with_content(/^HostbasedAuthentication #{v}$/) }
+        end
+      end
+    end
+
+    context 'hostbased_uses_name_from_packet_only' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :hostbased_uses_name_from_packet_only => v } end
+
+          it { should contain_file('sshd_config').with_content(/^HostbasedUsesNameFromPacketOnly #{v}$/) }
+        end
+      end
+    end
+
+    context 'ignore_rhosts' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :ignore_rhosts => v } end
+
+          it { should contain_file('sshd_config').with_content(/^IgnoreRhosts #{v}$/) }
+        end
+      end
+    end
+
+    context 'ignore_user_known_hosts' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :ignore_user_known_hosts => v } end
+
+          it { should contain_file('sshd_config').with_content(/^IgnoreUserKnownHosts #{v}$/) }
+        end
+      end
+    end
+
+    context 'kbd_interactive_authentication' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :kbd_interactive_authentication => v } end
+
+          it { should contain_file('sshd_config').with_content(/^KbdInteractiveAuthentication #{v}$/) }
+        end
+      end
+    end
+
+    context 'kerberos_authentication' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :kerberos_authentication => v } end
+
+          it { should contain_file('sshd_config').with_content(/^KerberosAuthentication #{v}$/) }
+        end
+      end
+    end
+
+    context 'kerberos_get_afs_token' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :kerberos_get_afs_token => v } end
+
+          it { should contain_file('sshd_config').with_content(/^KerberosGetAFSToken #{v}$/) }
+        end
+      end
+    end
+
+    context 'kerberos_or_local_passwd' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :kerberos_or_local_passwd => v } end
+
+          it { should contain_file('sshd_config').with_content(/^KerberosOrLocalPasswd #{v}$/) }
+        end
+      end
+    end
+
+    context 'kerberos_ticket_cleanup' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :kerberos_ticket_cleanup => v } end
+
+          it { should contain_file('sshd_config').with_content(/^KerberosTicketCleanup #{v}$/) }
+        end
+      end
+    end
+
+    context 'password_authentication' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :password_authentication => v } end
+
+          it { should contain_file('sshd_config').with_content(/^PasswordAuthentication #{v}$/) }
+        end
+      end
+    end
+
+    context 'permit_empty_passwords' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :permit_empty_passwords => v } end
+
+          it { should contain_file('sshd_config').with_content(/^PermitEmptyPasswords #{v}$/) }
+        end
+      end
+    end
+
+    context 'permit_tty' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :permit_tty => v } end
+
+          it { should contain_file('sshd_config').with_content(/^PermitTTY #{v}$/) }
+        end
+      end
+    end
+
+    context 'permit_user_rc' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :permit_user_rc => v } end
+
+          it { should contain_file('sshd_config').with_content(/^PermitUserRC #{v}$/) }
+        end
+      end
+    end
+
+    context 'print_last_log' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :print_last_log => v } end
+
+          it { should contain_file('sshd_config').with_content(/^PrintLastLog #{v}$/) }
+        end
+      end
+    end
+
+    context 'print_motd' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :print_motd => v } end
+
+          it { should contain_file('sshd_config').with_content(/^PrintMotd #{v}$/) }
+        end
+      end
+    end
+
+    context 'pubkey_authentication' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :pubkey_authentication => v } end
+
+          it { should contain_file('sshd_config').with_content(/^PubkeyAuthentication #{v}$/) }
+        end
+      end
+    end
+
+    context 'stream_local_bind_unlink' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :stream_local_bind_unlink => v } end
+
+          it { should contain_file('sshd_config').with_content(/^StreamLocalBindUnlink #{v}$/) }
+        end
+      end
+    end
+
+    context 'strict_modes' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :strict_modes => v } end
+
+          it { should contain_file('sshd_config').with_content(/^StrictModes #{v}$/) }
+        end
+      end
+    end
+
+    context 'tcp_keep_alive' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :tcp_keep_alive => v } end
+
+          it { should contain_file('sshd_config').with_content(/^TCPKeepAlive #{v}$/) }
+        end
+      end
+    end
+
+    context 'use_dns' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :use_dns => v } end
+
+          it { should contain_file('sshd_config').with_content(/^UseDNS #{v}$/) }
+        end
+      end
+    end
+
+    context 'use_pam' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :use_pam => v } end
+
+          it { should contain_file('sshd_config').with_content(/^UsePAM #{v}$/) }
+        end
+      end
+    end
+
+    context 'x11_forwarding' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :x11_forwarding => v } end
+
+          it { should contain_file('sshd_config').with_content(/^X11Forwarding #{v}$/) }
+        end
+      end
+    end
+
+    context 'x11_use_localhost' do
+      ['yes','no'].each do |v|
+        context "set to #{v}" do
+          let(:params) do { :x11_use_localhost => v } end
+
+          it { should contain_file('sshd_config').with_content(/^X11UseLocalhost #{v}$/) }
+        end
+      end
+    end
+
+    context 'accept_env' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :accept_env => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AcceptEnv test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :accept_env => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AcceptEnv one$/) }
+        it { should contain_file('sshd_config').with_content(/^AcceptEnv two$/) }
+      end
+    end
+
+    context 'authentication_methods' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :authentication_methods => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AuthenticationMethods test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :authentication_methods => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AuthenticationMethods one,two$/) }
+      end
+    end
+
+    context 'ca_signature_algorithms' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :ca_signature_algorithms => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^CASignatureAlgorithms test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :ca_signature_algorithms => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^CASignatureAlgorithms one,two$/) }
+      end
+    end
+
+    context 'ciphers' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :ciphers => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^Ciphers test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :ciphers => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^Ciphers one,two$/) }
+      end
+    end
+
+    context 'hostbased_accepted_key_types' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :hostbased_accepted_key_types => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^HostbasedAcceptedKeyTypes test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :hostbased_accepted_key_types => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^HostbasedAcceptedKeyTypes one,two$/) }
+      end
+    end
+
+    context 'host_key' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :host_key => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^HostKey test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :host_key => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^HostKey one$/) }
+        it { should contain_file('sshd_config').with_content(/^HostKey two$/) }
+      end
+    end
+
+    context 'host_key_algorithms' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :host_key_algorithms => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^HostKeyAlgorithms test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :host_key_algorithms => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^HostKeyAlgorithms one,two$/) }
+      end
+    end
+
+    context 'kex_algorithms' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :kex_algorithms => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^KexAlgorithms test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :kex_algorithms => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^KexAlgorithms one,two$/) }
+      end
+    end
+
+    context 'listen_address' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :listen_address => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^ListenAddress test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :listen_address => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^ListenAddress one$/) }
+        it { should contain_file('sshd_config').with_content(/^ListenAddress two$/) }
+      end
+    end
+
+    context 'macs' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :macs => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^MACs test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :macs => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^MACs one,two$/) }
+      end
+    end
+
+    context 'pubkey_accepted_key_types' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :pubkey_accepted_key_types => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^PubkeyAcceptedKeyTypes test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :pubkey_accepted_key_types => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^PubkeyAcceptedKeyTypes one,two$/) }
+      end
+    end
+
+
+    context 'allow_groups' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :allow_groups => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AllowGroups test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :allow_groups => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AllowGroups one two$/) }
+      end
+    end
+
+    context 'allow_users' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :allow_users => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AllowUsers test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :allow_users => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AllowUsers one two$/) }
+      end
+    end
+
+    context 'authorized_keys_file' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :authorized_keys_file => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AuthorizedKeysFile test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :authorized_keys_file => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^AuthorizedKeysFile one two$/) }
+      end
+    end
+
+    context 'deny_groups' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :deny_groups => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^DenyGroups test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :deny_groups => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^DenyGroups one two$/) }
+      end
+    end
+
+    context 'deny_users' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :deny_users => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^DenyUsers test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :deny_users => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^DenyUsers one two$/) }
+      end
+    end
+
+    context 'permit_listen' do
+      context "set to an array of strings with one element ['test']" do
+        let(:params) do { :permit_listen => ['test'] } end
+
+        it { should contain_file('sshd_config').with_content(/^PermitListen test$/) }
+      end
+      context "set to an array of strings with multiple elements ['one','two']" do
+        let(:params) do { :permit_listen => ['one','two'] } end
+
+        it { should contain_file('sshd_config').with_content(/^PermitListen one two$/) }
+      end
+    end
+  end
+
+  describe 'validate data types of parameters' do
+    validations = {
+      'Stdlib::Absolutepath (optional)' => {
+        :name    => %w(package_adminfile package_source),
+        :valid   => ['/absolute/filepath', '/absolute/directory/', :undef],
+        :invalid => ['../invalid', %w(array), { 'ha' => 'sh' }, 3, 2.42, false],
+        :message => 'expects a (match for|match for Stdlib::Absolutepath =|Stdlib::Absolutepath =) Variant\[Stdlib::Windowspath.*Stdlib::Unixpath',
+      },
+      'Stdlib::Absolutepath' => {
+        :name    => %w(banner_path config_path),
+        :valid   => ['/absolute/filepath', '/absolute/directory/'],
+        :invalid => ['../invalid', %w(array), { 'ha' => 'sh' }, 3, 2.42, false, nil],
+        :message => 'expects a (match for|match for Stdlib::Absolutepath =|Stdlib::Absolutepath =) Variant\[Stdlib::Windowspath.*Stdlib::Unixpath',
+      },
+      'Stdlib::Ensure::Service' => {
+        :name    => %w(service_ensure),
+        :valid   => %w(running stopped),
+        :invalid => ['present', 'absent', %w(array), { 'ha' => 'sh' }, 3, 2.42, false, nil],
+        :message => 'expects a match for Stdlib::Ensure::Service',
+      },
+      'Stdlib::Filemode' => {
+        :name    => %w(banner_mode config_mode),
+        :valid   => %w(0644 0755 0640 1740),
+        :invalid => [2770, '0844', '00644', 'string', %w(array), { 'ha' => 'sh' }, 3, 2.42, false, nil],
+        :message => 'expects a match for Stdlib::Filemode|Error while evaluating a Resource Statement',
+      },
+      'Stdlib::Port (optional)' => {
+        :name    => %w(port),
+        :valid   => [0, 65535, :undef],
+        :invalid => ['string', %w(array), { 'ha' => 'sh' }, -1, 2.42, 65536, false],
+        :message => 'expects a match for Stdlib::Port|Error while evaluating a Resource Statement',
+      },
+      'String or Array of strings' => {
+        :name    => %w(packages),
+        :valid   => ['string', %w(array of strings)],
+        :invalid => [{ 'ha' => 'sh' }, 3, 2.42, false, [0]],
+        :message => 'String or Array|expects a String value|Error while evaluating a Resource Statement',
+      },
+      'String or Array of strings (optional)' => {
+        :name    => %w(allow_groups allow_users authorized_keys_file deny_groups deny_users permit_listen),
+        :valid   => ['string', %w(array of strings), :undef],
+        :invalid => [{ 'ha' => 'sh' }, 3, 2.42, false, [0]],
+        :message => 'String or Array|expects a String value|Error while evaluating a Resource Statement',
+      },
+      'Array of strings (optional)' => {
+        :name    => %w(accept_env authentication_methods ca_signature_algorithms ciphers host_key host_key_algorithms
+          hostbased_accepted_key_types kex_algorithms listen_address macs pubkey_accepted_key_types),
+        :valid   => [%w(array of strings), :undef],
+        :invalid => ['string', { 'ha' => 'sh' }, 3, 2.42, false, [0]],
+        :message => 'Undef or Array|expects a String value|Error while evaluating a Resource Statement',
+      },
+      'integer => 0 (optional)' => {
+        :name    => %w(client_alive_count_max client_alive_interval login_grace_time max_sessions x11_display_offset),
+        :valid   => [0, 1, 23, :undef],
+        :invalid => ['string', %w(array), { 'ha' => 'sh' }, -1, 2.42, false],
+        :message => 'Undef or Integer|Error while evaluating a Resource Statement',
+      },
+      'integer => 2 (optional)' => {
+        :name    => %w(max_auth_tries),
+        :valid   => [2, 23, :undef],
+        :invalid => ['string', %w(array), { 'ha' => 'sh' }, -1, 2.42, 0, 1, false],
+        :message => 'Undef or Integer|Error while evaluating a Resource Statement',
+      },
+      'four digit octal (optional) for umask' => {
+        :name    => %w(stream_local_bind_mask),
+        :valid   => ['0000', '1234', '7777', :undef],
+        :invalid => ['string', %w(array), { 'ha' => 'sh' }, -1, 2.42, false, '00000', 'x234', '77e1', '011'],
+        :message => 'Error while evaluating a Resource Statement',
+      },
+      'enumeration of valid strings for permit_root_login (optional)' => {
+        :name    => %w(permit_root_login),
+        :valid   => ['yes', 'prohibit-password', 'without-password', 'forced-commands-only', 'no', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'enumeration of valid strings for syslog_facility (optional)' => {
+        :name    => %w(syslog_facility),
+        :valid   => ['DAEMON', 'USER', 'AUTH', 'LOCAL0', 'LOCAL1', 'LOCAL2', 'LOCAL3', 'LOCAL4', 'LOCAL5', 'LOCAL6', 'LOCAL7', 'AUTHPRIV', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false, 'USER0', 'daemon'],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'enumeration of valid strings for fingerprint_hash (optional)' => {
+        :name    => %w(fingerprint_hash),
+        :valid   => ['md5', 'sha256', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'enumeration of valid strings for gateway_ports (optional)' => {
+        :name    => %w(gateway_ports),
+        :valid   => ['yes', 'no', 'clientspecified', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'enumeration of valid strings for allow_stream_local_forwarding (optional)' => {
+        :name    => %w(allow_stream_local_forwarding),
+        :valid   => ['yes', 'all', 'no', 'local', 'remote', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'enumeration of valid strings for compression (optional)' => {
+        :name    => %w(compression),
+        :valid   => ['yes', 'no', 'delayed', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'enumeration of valid strings for allow_tcp_forwarding (optional)' => {
+        :name    => %w(allow_tcp_forwarding),
+        :valid   => ['yes', 'no', 'local', 'remote', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'enumeration of valid strings for permit_tunnel (optional)' => {
+        :name    => %w(permit_tunnel),
+        :valid   => ['yes', 'point-to-point', 'ethernet', 'no', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'enumeration of valid strings for address_family (optional)' => {
+        :name    => %w(address_family),
+        :valid   => ['any', 'inet', 'inet6', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'yes or no (optional)' => {
+        :name    => %w(allow_agent_forwarding disable_forwarding expose_auth_info gss_api_authentication gss_api_cleanup_credentials
+          gss_api_strict_acceptor_check hostbased_authentication hostbased_uses_name_from_packet_only ignore_rhosts ignore_user_known_hosts
+          kbd_interactive_authentication kerberos_authentication kerberos_get_afs_token kerberos_or_local_passwd kerberos_ticket_cleanup
+          password_authentication permit_empty_passwords permit_tty permit_user_rc print_last_log print_motd pubkey_authentication
+          stream_local_bind_unlink strict_modes tcp_keep_alive use_dns use_pam x11_forwarding x11_use_localhost),
+        :valid   => ['yes', 'no', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false, 'YES', 'No'],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'Ssh::Log_level (optional)' => {
+        :name    => %w(log_level),
+        :valid   => ['QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE', 'DEBUG', 'DEBUG1', 'DEBUG2', 'DEBUG3', :undef],
+        :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false, 'INFO1'],
+        :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement',
+      },
+      'Boolean' => {
+        :name    => %w(manage_service service_enable service_hasrestart service_hasstatus),
+        :valid   => [true, false],
+        :invalid => ['string', %w(array), { 'ha' => 'sh' }, 3, 2.42, 'false', nil],
+        :message => 'expects a Boolean',
+      },
+      'String (optional)' => {
+        :name    => %w(authorized_keys_command authorized_keys_command_user
+          authorized_principals_command authorized_principals_command_user
+          authorized_principals_file banner banner_content
+          challenge_response_authentication chroot_directory force_command
+          host_certificate host_key_agent ip_qos max_startups
+          permit_user_environment pid_file rdomain rekey_limit revoked_keys
+          set_env subsystem trusted_user_ca_keys version_addendum xauth_location
+          custom),
+        :valid   => ['string', :undef],
+        :invalid => [%w(array), { 'ha' => 'sh' }, 3, 2.42, false],
+        :message => 'expects a value of type Undef or String',
+      },
+    }
+
+    validations.sort.each do |type, var|
+      mandatory_params = {} if mandatory_params.nil?
+      var[:name].each do |var_name|
+        var[:params] = {} if var[:params].nil?
+        var[:valid].each do |valid|
+          context "when #{var_name} (#{type}) is set to valid #{valid} (as #{valid.class})" do
+            let(:facts) { [mandatory_facts, var[:facts]].reduce(:merge) } if ! var[:facts].nil?
+            let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => valid, }].reduce(:merge) }
+            it { should compile }
+          end
+        end
+
+        var[:invalid].each do |invalid|
+          context "when #{var_name} (#{type}) is set to invalid #{invalid} (as #{invalid.class})" do
+            let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => invalid, }].reduce(:merge) }
+            it 'should fail' do
+              expect { should contain_class(subject) }.to raise_error(Puppet::Error, /#{var[:message]}/)
+            end
+          end
+        end
+      end # var[:name].each
+    end # validations.sort.each
+  end # describe 'validate data types of parameters'
+end
diff --git a/spec/defines/config_entry_spec.rb b/spec/defines/config_entry_spec.rb
index eee757e..b76f6e3 100644
--- a/spec/defines/config_entry_spec.rb
+++ b/spec/defines/config_entry_spec.rb
@@ -66,8 +66,8 @@
   end
 
   context 'with order set to valid string <242>' do
-    let(:params) { mandatory_params.merge({ :order => '242' }) }
-    it { should contain_concat__fragment('/test/path Host test_host').with_order('242') }
+    let(:params) { mandatory_params.merge({ :order => 242 }) }
+    it { should contain_concat__fragment('/test/path Host test_host').with_order(242) }
   end
 
 # /!\ no functionality for $ensure implemented yet
@@ -78,6 +78,6 @@
 
   context 'with lines set to valid array [ <ForwardX11 no>, <StrictHostKeyChecking no> ]' do
     let(:params) { mandatory_params.merge({ :lines => ['ForwardX11 no', 'StrictHostKeyChecking no'] }) }
-    it { should contain_concat__fragment('/test/path Host test_host').with_content("Host test_host\nForwardX11 no\nStrictHostKeyChecking no") }
+    it { should contain_concat__fragment('/test/path Host test_host').with_content("Host test_host\n  ForwardX11 no\n  StrictHostKeyChecking no") }
   end
 end
diff --git a/spec/fixtures/ssh_config_rhel_old b/spec/fixtures/ssh_config_el5
similarity index 69%
rename from spec/fixtures/ssh_config_rhel_old
rename to spec/fixtures/ssh_config_el5
index df3d4bc..7a90707 100644
--- a/spec/fixtures/ssh_config_rhel_old
+++ b/spec/fixtures/ssh_config_el5
@@ -1,7 +1,4 @@
-# This file is being maintained by Puppet.
-# DO NOT EDIT
-
-# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $
+#	$OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $
 
 # This is the ssh client system-wide configuration file.  See
 # ssh_config(5) for more information.  This file provides defaults for
@@ -25,8 +22,7 @@
 #   ForwardX11 no
 #   RhostsRSAAuthentication no
 #   RSAAuthentication yes
-   PasswordAuthentication yes
-   PubkeyAuthentication yes
+#   PasswordAuthentication yes
 #   HostbasedAuthentication no
 #   BatchMode no
 #   CheckHostIP yes
@@ -34,27 +30,23 @@
 #   ConnectTimeout 0
 #   StrictHostKeyChecking ask
 #   IdentityFile ~/.ssh/identity
-   IdentityFile ~/.ssh/id_rsa
-   IdentityFile ~/.ssh/id_dsa
+#   IdentityFile ~/.ssh/id_rsa
+#   IdentityFile ~/.ssh/id_dsa
 #   Port 22
-   Protocol 2
+#   Protocol 2,1
 #   Cipher 3des
 #   Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc
 #   EscapeChar ~
 #   Tunnel no
 #   TunnelDevice any:any
 #   PermitLocalCommand no
-#   HashKnownHosts no
-   HashKnownHosts no
-   GlobalKnownHostsFile /etc/ssh/ssh_known_hosts
 Host *
-#  GSSAPIAuthentication yes
-  GSSAPIAuthentication yes
+	GSSAPIAuthentication yes
 # If this option is set to yes then remote X11 clients will have full access
 # to the original X11 display. As virtually no X11 client supports the untrusted
 # mode correctly we set this to yes.
-  ForwardX11Trusted yes
+	ForwardX11Trusted yes
 # Send locale-related environment variables
-  SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
-  SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
-  SendEnv LC_IDENTIFICATION LC_ALL
+	SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+	SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+	SendEnv LC_IDENTIFICATION LC_ALL
diff --git a/spec/fixtures/ssh_config_el5_sorted b/spec/fixtures/ssh_config_el5_sorted
new file mode 100644
index 0000000..87ace30
--- /dev/null
+++ b/spec/fixtures/ssh_config_el5_sorted
@@ -0,0 +1,23 @@
+# This file is being maintained by Puppet.
+# DO NOT EDIT
+#
+# See https://man.openbsd.org/sshd_config for more info
+
+Host *
+  ForwardX11Trusted yes
+  GSSAPIAuthentication yes
+  SendEnv LANG
+  SendEnv LANGUAGE
+  SendEnv LC_ADDRESS
+  SendEnv LC_ALL
+  SendEnv LC_COLLATE
+  SendEnv LC_CTYPE
+  SendEnv LC_IDENTIFICATION
+  SendEnv LC_MEASUREMENT
+  SendEnv LC_MESSAGES
+  SendEnv LC_MONETARY
+  SendEnv LC_NAME
+  SendEnv LC_NUMERIC
+  SendEnv LC_PAPER
+  SendEnv LC_TELEPHONE
+  SendEnv LC_TIME
diff --git a/spec/fixtures/ssh_config_rhel_old b/spec/fixtures/ssh_config_el6
similarity index 65%
copy from spec/fixtures/ssh_config_rhel_old
copy to spec/fixtures/ssh_config_el6
index df3d4bc..96c532e 100644
--- a/spec/fixtures/ssh_config_rhel_old
+++ b/spec/fixtures/ssh_config_el6
@@ -1,7 +1,4 @@
-# This file is being maintained by Puppet.
-# DO NOT EDIT
-
-# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $
+#	$OpenBSD: ssh_config,v 1.25 2009/02/17 01:28:32 djm Exp $
 
 # This is the ssh client system-wide configuration file.  See
 # ssh_config(5) for more information.  This file provides defaults for
@@ -25,36 +22,38 @@
 #   ForwardX11 no
 #   RhostsRSAAuthentication no
 #   RSAAuthentication yes
-   PasswordAuthentication yes
-   PubkeyAuthentication yes
+#   PasswordAuthentication yes
 #   HostbasedAuthentication no
+#   GSSAPIAuthentication no
+#   GSSAPIDelegateCredentials no
+#   GSSAPIKeyExchange no
+#   GSSAPITrustDNS no
 #   BatchMode no
 #   CheckHostIP yes
 #   AddressFamily any
 #   ConnectTimeout 0
 #   StrictHostKeyChecking ask
 #   IdentityFile ~/.ssh/identity
-   IdentityFile ~/.ssh/id_rsa
-   IdentityFile ~/.ssh/id_dsa
+#   IdentityFile ~/.ssh/id_rsa
+#   IdentityFile ~/.ssh/id_dsa
 #   Port 22
-   Protocol 2
+#   Protocol 2,1
 #   Cipher 3des
-#   Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc
+#   Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
+#   MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
 #   EscapeChar ~
 #   Tunnel no
 #   TunnelDevice any:any
 #   PermitLocalCommand no
-#   HashKnownHosts no
-   HashKnownHosts no
-   GlobalKnownHostsFile /etc/ssh/ssh_known_hosts
+#   VisualHostKey no
 Host *
-#  GSSAPIAuthentication yes
-  GSSAPIAuthentication yes
+	GSSAPIAuthentication yes
 # If this option is set to yes then remote X11 clients will have full access
 # to the original X11 display. As virtually no X11 client supports the untrusted
 # mode correctly we set this to yes.
-  ForwardX11Trusted yes
+	ForwardX11Trusted yes
 # Send locale-related environment variables
-  SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
-  SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
-  SendEnv LC_IDENTIFICATION LC_ALL
+	SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES 
+	SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT 
+	SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+	SendEnv XMODIFIERS
diff --git a/spec/fixtures/ssh_config_el6_sorted b/spec/fixtures/ssh_config_el6_sorted
new file mode 100644
index 0000000..e227ec3
--- /dev/null
+++ b/spec/fixtures/ssh_config_el6_sorted
@@ -0,0 +1,24 @@
+# This file is being maintained by Puppet.
+# DO NOT EDIT
+#
+# See https://man.openbsd.org/sshd_config for more info
+
+Host *
+  ForwardX11Trusted yes
+  GSSAPIAuthentication yes
+  SendEnv LANG
+  SendEnv LANGUAGE
+  SendEnv LC_ADDRESS
+  SendEnv LC_ALL
+  SendEnv LC_COLLATE
+  SendEnv LC_CTYPE
+  SendEnv LC_IDENTIFICATION
+  SendEnv LC_MEASUREMENT
+  SendEnv LC_MESSAGES
+  SendEnv LC_MONETARY
+  SendEnv LC_NAME
+  SendEnv LC_NUMERIC
+  SendEnv LC_PAPER
+  SendEnv LC_TELEPHONE
+  SendEnv LC_TIME
+  SendEnv XMODIFIERS
diff --git a/spec/fixtures/ssh_config_el7 b/spec/fixtures/ssh_config_el7
new file mode 100644
index 0000000..d1c83ea
--- /dev/null
+++ b/spec/fixtures/ssh_config_el7
@@ -0,0 +1,68 @@
+#	$OpenBSD: ssh_config,v 1.30 2016/02/20 23:06:23 sobrado Exp $
+
+# This is the ssh client system-wide configuration file.  See
+# ssh_config(5) for more information.  This file provides defaults for
+# users, and the values can be changed in per-user configuration files
+# or on the command line.
+
+# Configuration data is parsed as follows:
+#  1. command line options
+#  2. user-specific file
+#  3. system-wide file
+# Any configuration value is only changed the first time it is set.
+# Thus, host-specific definitions should be at the beginning of the
+# configuration file, and defaults at the end.
+
+# Site-wide defaults for some commonly used options.  For a comprehensive
+# list of available options, their meanings and defaults, please see the
+# ssh_config(5) man page.
+
+# Host *
+#   ForwardAgent no
+#   ForwardX11 no
+#   RhostsRSAAuthentication no
+#   RSAAuthentication yes
+#   PasswordAuthentication yes
+#   HostbasedAuthentication no
+#   GSSAPIAuthentication no
+#   GSSAPIDelegateCredentials no
+#   GSSAPIKeyExchange no
+#   GSSAPITrustDNS no
+#   BatchMode no
+#   CheckHostIP yes
+#   AddressFamily any
+#   ConnectTimeout 0
+#   StrictHostKeyChecking ask
+#   IdentityFile ~/.ssh/identity
+#   IdentityFile ~/.ssh/id_rsa
+#   IdentityFile ~/.ssh/id_dsa
+#   IdentityFile ~/.ssh/id_ecdsa
+#   IdentityFile ~/.ssh/id_ed25519
+#   Port 22
+#   Protocol 2
+#   Cipher 3des
+#   Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
+#   MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
+#   EscapeChar ~
+#   Tunnel no
+#   TunnelDevice any:any
+#   PermitLocalCommand no
+#   VisualHostKey no
+#   ProxyCommand ssh -q -W %h:%p gateway.example.com
+#   RekeyLimit 1G 1h
+#
+# Uncomment this if you want to use .local domain
+# Host *.local
+#   CheckHostIP no
+
+Host *
+	GSSAPIAuthentication yes
+# If this option is set to yes then remote X11 clients will have full access
+# to the original X11 display. As virtually no X11 client supports the untrusted
+# mode correctly we set this to yes.
+	ForwardX11Trusted yes
+# Send locale-related environment variables
+	SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+	SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+	SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+	SendEnv XMODIFIERS
diff --git a/spec/fixtures/ssh_config_el7_sorted b/spec/fixtures/ssh_config_el7_sorted
new file mode 100644
index 0000000..e227ec3
--- /dev/null
+++ b/spec/fixtures/ssh_config_el7_sorted
@@ -0,0 +1,24 @@
+# This file is being maintained by Puppet.
+# DO NOT EDIT
+#
+# See https://man.openbsd.org/sshd_config for more info
+
+Host *
+  ForwardX11Trusted yes
+  GSSAPIAuthentication yes
+  SendEnv LANG
+  SendEnv LANGUAGE
+  SendEnv LC_ADDRESS
+  SendEnv LC_ALL
+  SendEnv LC_COLLATE
+  SendEnv LC_CTYPE
+  SendEnv LC_IDENTIFICATION
+  SendEnv LC_MEASUREMENT
+  SendEnv LC_MESSAGES
+  SendEnv LC_MONETARY
+  SendEnv LC_NAME
+  SendEnv LC_NUMERIC
+  SendEnv LC_PAPER
+  SendEnv LC_TELEPHONE
+  SendEnv LC_TIME
+  SendEnv XMODIFIERS
diff --git a/spec/fixtures/ssh_config_rhel b/spec/fixtures/ssh_config_rhel
deleted file mode 100644
index 4a1466c..0000000
--- a/spec/fixtures/ssh_config_rhel
+++ /dev/null
@@ -1,61 +0,0 @@
-# This file is being maintained by Puppet.
-# DO NOT EDIT
-
-# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $
-
-# This is the ssh client system-wide configuration file.  See
-# ssh_config(5) for more information.  This file provides defaults for
-# users, and the values can be changed in per-user configuration files
-# or on the command line.
-
-# Configuration data is parsed as follows:
-#  1. command line options
-#  2. user-specific file
-#  3. system-wide file
-# Any configuration value is only changed the first time it is set.
-# Thus, host-specific definitions should be at the beginning of the
-# configuration file, and defaults at the end.
-
-# Site-wide defaults for some commonly used options.  For a comprehensive
-# list of available options, their meanings and defaults, please see the
-# ssh_config(5) man page.
-
-# Host *
-#   ForwardAgent no
-#   ForwardX11 no
-#   RhostsRSAAuthentication no
-#   RSAAuthentication yes
-   PasswordAuthentication yes
-   PubkeyAuthentication yes
-#   HostbasedAuthentication no
-#   BatchMode no
-#   CheckHostIP yes
-#   AddressFamily any
-#   ConnectTimeout 0
-#   StrictHostKeyChecking ask
-#   IdentityFile ~/.ssh/identity
-   IdentityFile ~/.ssh/id_rsa
-   IdentityFile ~/.ssh/id_dsa
-#   Port 22
-   Protocol 2
-#   Cipher 3des
-#   Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc
-#   EscapeChar ~
-#   Tunnel no
-#   TunnelDevice any:any
-#   PermitLocalCommand no
-#   HashKnownHosts no
-   HashKnownHosts no
-   GlobalKnownHostsFile /etc/ssh/ssh_known_hosts
-Host *
-#  GSSAPIAuthentication yes
-  GSSAPIAuthentication yes
-# If this option is set to yes then remote X11 clients will have full access
-# to the original X11 display. As virtually no X11 client supports the untrusted
-# mode correctly we set this to yes.
-  ForwardX11Trusted yes
-  UseRoaming no
-# Send locale-related environment variables
-  SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
-  SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
-  SendEnv LC_IDENTIFICATION LC_ALL
diff --git a/spec/fixtures/sshd_config_rhel b/spec/fixtures/sshd_config_el5
similarity index 76%
rename from spec/fixtures/sshd_config_rhel
rename to spec/fixtures/sshd_config_el5
index 8b5c3de..925f43b 100644
--- a/spec/fixtures/sshd_config_rhel
+++ b/spec/fixtures/sshd_config_el5
@@ -1,7 +1,4 @@
-# This file is being maintained by Puppet.
-# DO NOT EDIT
-
-# $OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $
+#	$OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $
 
 # This is the sshd server system-wide configuration file.  See
 # sshd_config(5) for more information.
@@ -14,67 +11,60 @@
 # default value.
 
 #Port 22
-Port 22
 #Protocol 2,1
 Protocol 2
 #AddressFamily any
-AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
 
 # HostKey for protocol version 1
 #HostKey /etc/ssh/ssh_host_key
 # HostKeys for protocol version 2
 #HostKey /etc/ssh/ssh_host_rsa_key
 #HostKey /etc/ssh/ssh_host_dsa_key
-HostKey /etc/ssh/ssh_host_rsa_key
 
 # Lifetime and size of ephemeral version 1 server key
 #KeyRegenerationInterval 1h
-#ServerKeyBits 1024
-ServerKeyBits 1024
+#ServerKeyBits 768
+
 # Logging
 # obsoletes QuietMode and FascistLogging
 #SyslogFacility AUTH
-SyslogFacility AUTH
+SyslogFacility AUTHPRIV
 #LogLevel INFO
-LogLevel INFO
 
 # Authentication:
 
-#LoginGraceTime 120
-LoginGraceTime 120
+#LoginGraceTime 2m
 #PermitRootLogin yes
-PermitRootLogin yes
 #StrictModes yes
 #MaxAuthTries 6
 
 #RSAAuthentication yes
 #PubkeyAuthentication yes
-PubkeyAuthentication yes
-#AuthorizedKeysFile .ssh/authorized_keys
+#AuthorizedKeysFile	.ssh/authorized_keys
 
 # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
 #RhostsRSAAuthentication no
 # similar for protocol version 2
 #HostbasedAuthentication no
-HostbasedAuthentication no
 # Change to yes if you don't trust ~/.ssh/known_hosts for
 # RhostsRSAAuthentication and HostbasedAuthentication
 #IgnoreUserKnownHosts no
-IgnoreUserKnownHosts no
 # Don't read the user's ~/.rhosts and ~/.shosts files
 #IgnoreRhosts yes
-IgnoreRhosts yes
 
 # To disable tunneled clear text passwords, change to no here!
 #PasswordAuthentication yes
-PasswordAuthentication yes
 #PermitEmptyPasswords no
+PasswordAuthentication yes
 
 # Change to no to disable s/key passwords
 #ChallengeResponseAuthentication yes
-ChallengeResponseAuthentication yes
+ChallengeResponseAuthentication no
 
 # Kerberos options
+#KerberosAuthentication no
 #KerberosOrLocalPasswd yes
 #KerberosTicketCleanup yes
 #KerberosGetAFSToken no
@@ -97,47 +87,33 @@
 UsePAM yes
 
 # Accept locale-related environment variables
-AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+AcceptEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
 AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
 AcceptEnv LC_IDENTIFICATION LC_ALL
 #AllowTcpForwarding yes
-AllowTcpForwarding yes
 #GatewayPorts no
 #X11Forwarding no
 X11Forwarding yes
 #X11DisplayOffset 10
 #X11UseLocalhost yes
-X11UseLocalhost yes
 #PrintMotd yes
-PrintMotd yes
 #PrintLastLog yes
 #TCPKeepAlive yes
-TCPKeepAlive yes
 #UseLogin no
 #UsePrivilegeSeparation yes
 #PermitUserEnvironment no
 #Compression delayed
 #ClientAliveInterval 0
-ClientAliveInterval 0
-ClientAliveCountMax 3
+#ClientAliveCountMax 3
 #ShowPatchLevel no
 #UseDNS yes
-UseDNS yes
 #PidFile /var/run/sshd.pid
-#MaxStartups 10:30:100
-#MaxSessions 10
-
+#MaxStartups 10
 #PermitTunnel no
-PermitTunnel no
 #ChrootDirectory none
 
 # no default banner path
-#Banner none
-Banner none
-
-#XAuthLocation /usr/bin/xauth
-XAuthLocation /usr/bin/xauth
+#Banner /some/path
 
 # override default of no subsystems
-Subsystem sftp /usr/libexec/openssh/sftp-server
-
+Subsystem	sftp	/usr/libexec/openssh/sftp-server
diff --git a/spec/fixtures/sshd_config_el5_sorted b/spec/fixtures/sshd_config_el5_sorted
new file mode 100644
index 0000000..bc7c8a8
--- /dev/null
+++ b/spec/fixtures/sshd_config_el5_sorted
@@ -0,0 +1,29 @@
+# This file is being maintained by Puppet.
+# DO NOT EDIT
+#
+# See https://man.openbsd.org/sshd_config for more info
+
+AcceptEnv LANG
+AcceptEnv LANGUAGE
+AcceptEnv LC_ADDRESS
+AcceptEnv LC_ALL
+AcceptEnv LC_COLLATE
+AcceptEnv LC_CTYPE
+AcceptEnv LC_IDENTIFICATION
+AcceptEnv LC_MEASUREMENT
+AcceptEnv LC_MESSAGES
+AcceptEnv LC_MONETARY
+AcceptEnv LC_NAME
+AcceptEnv LC_NUMERIC
+AcceptEnv LC_PAPER
+AcceptEnv LC_TELEPHONE
+AcceptEnv LC_TIME
+ChallengeResponseAuthentication no
+GSSAPIAuthentication yes
+GSSAPICleanupCredentials yes
+PasswordAuthentication yes
+Subsystem sftp /usr/libexec/openssh/sftp-server
+SyslogFacility AUTHPRIV
+UsePAM yes
+X11Forwarding yes
+Protocol 2
diff --git a/spec/fixtures/sshd_config_rhel b/spec/fixtures/sshd_config_el6
similarity index 65%
copy from spec/fixtures/sshd_config_rhel
copy to spec/fixtures/sshd_config_el6
index 8b5c3de..810b458 100644
--- a/spec/fixtures/sshd_config_rhel
+++ b/spec/fixtures/sshd_config_el6
@@ -1,7 +1,4 @@
-# This file is being maintained by Puppet.
-# DO NOT EDIT
-
-# $OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $
+#	$OpenBSD: sshd_config,v 1.80 2008/07/02 02:24:18 djm Exp $
 
 # This is the sshd server system-wide configuration file.  See
 # sshd_config(5) for more information.
@@ -14,130 +11,129 @@
 # default value.
 
 #Port 22
-Port 22
-#Protocol 2,1
-Protocol 2
 #AddressFamily any
-AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
+
+# Disable legacy (protocol version 1) support in the server for new
+# installations. In future the default will change to require explicit
+# activation of protocol 1
+Protocol 2
 
 # HostKey for protocol version 1
 #HostKey /etc/ssh/ssh_host_key
 # HostKeys for protocol version 2
 #HostKey /etc/ssh/ssh_host_rsa_key
 #HostKey /etc/ssh/ssh_host_dsa_key
-HostKey /etc/ssh/ssh_host_rsa_key
 
 # Lifetime and size of ephemeral version 1 server key
 #KeyRegenerationInterval 1h
 #ServerKeyBits 1024
-ServerKeyBits 1024
+
 # Logging
 # obsoletes QuietMode and FascistLogging
 #SyslogFacility AUTH
-SyslogFacility AUTH
+SyslogFacility AUTHPRIV
 #LogLevel INFO
-LogLevel INFO
 
 # Authentication:
 
-#LoginGraceTime 120
-LoginGraceTime 120
+#LoginGraceTime 2m
 #PermitRootLogin yes
-PermitRootLogin yes
 #StrictModes yes
 #MaxAuthTries 6
+#MaxSessions 10
 
 #RSAAuthentication yes
 #PubkeyAuthentication yes
-PubkeyAuthentication yes
-#AuthorizedKeysFile .ssh/authorized_keys
+#AuthorizedKeysFile	.ssh/authorized_keys
+#AuthorizedKeysCommand none
+#AuthorizedKeysCommandRunAs nobody
 
 # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
 #RhostsRSAAuthentication no
 # similar for protocol version 2
 #HostbasedAuthentication no
-HostbasedAuthentication no
 # Change to yes if you don't trust ~/.ssh/known_hosts for
 # RhostsRSAAuthentication and HostbasedAuthentication
 #IgnoreUserKnownHosts no
-IgnoreUserKnownHosts no
 # Don't read the user's ~/.rhosts and ~/.shosts files
 #IgnoreRhosts yes
-IgnoreRhosts yes
 
 # To disable tunneled clear text passwords, change to no here!
 #PasswordAuthentication yes
-PasswordAuthentication yes
 #PermitEmptyPasswords no
+PasswordAuthentication no
 
 # Change to no to disable s/key passwords
 #ChallengeResponseAuthentication yes
-ChallengeResponseAuthentication yes
+ChallengeResponseAuthentication no
 
 # Kerberos options
+#KerberosAuthentication no
 #KerberosOrLocalPasswd yes
 #KerberosTicketCleanup yes
 #KerberosGetAFSToken no
+#KerberosUseKuserok yes
 
 # GSSAPI options
 #GSSAPIAuthentication no
 GSSAPIAuthentication yes
 #GSSAPICleanupCredentials yes
 GSSAPICleanupCredentials yes
+#GSSAPIStrictAcceptorCheck yes
+#GSSAPIKeyExchange no
 
-# 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 mechanism.
-# Depending on your PAM configuration, this may bypass the setting of
-# PasswordAuthentication, PermitEmptyPasswords, and
-# "PermitRootLogin without-password". If you just want the PAM account and
-# session checks to run without PAM authentication, then enable this but set
-# ChallengeResponseAuthentication=no
+# 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 no
 UsePAM yes
 
 # Accept locale-related environment variables
 AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
 AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
-AcceptEnv LC_IDENTIFICATION LC_ALL
+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+AcceptEnv XMODIFIERS
+
+#AllowAgentForwarding yes
 #AllowTcpForwarding yes
-AllowTcpForwarding yes
 #GatewayPorts no
 #X11Forwarding no
 X11Forwarding yes
 #X11DisplayOffset 10
 #X11UseLocalhost yes
-X11UseLocalhost yes
 #PrintMotd yes
-PrintMotd yes
 #PrintLastLog yes
 #TCPKeepAlive yes
-TCPKeepAlive yes
 #UseLogin no
 #UsePrivilegeSeparation yes
 #PermitUserEnvironment no
 #Compression delayed
 #ClientAliveInterval 0
-ClientAliveInterval 0
-ClientAliveCountMax 3
+#ClientAliveCountMax 3
 #ShowPatchLevel no
 #UseDNS yes
-UseDNS yes
+UseDNS no
 #PidFile /var/run/sshd.pid
 #MaxStartups 10:30:100
-#MaxSessions 10
-
 #PermitTunnel no
-PermitTunnel no
 #ChrootDirectory none
 
 # no default banner path
 #Banner none
-Banner none
-
-#XAuthLocation /usr/bin/xauth
-XAuthLocation /usr/bin/xauth
 
 # override default of no subsystems
-Subsystem sftp /usr/libexec/openssh/sftp-server
+Subsystem	sftp	/usr/libexec/openssh/sftp-server
 
+# Example of overriding settings on a per-user basis
+#Match User anoncvs
+#	X11Forwarding no
+#	AllowTcpForwarding no
+#	ForceCommand cvs server
diff --git a/spec/fixtures/sshd_config_el6_sorted b/spec/fixtures/sshd_config_el6_sorted
new file mode 100644
index 0000000..660b6ef
--- /dev/null
+++ b/spec/fixtures/sshd_config_el6_sorted
@@ -0,0 +1,31 @@
+# This file is being maintained by Puppet.
+# DO NOT EDIT
+#
+# See https://man.openbsd.org/sshd_config for more info
+
+AcceptEnv LANG
+AcceptEnv LANGUAGE
+AcceptEnv LC_ADDRESS
+AcceptEnv LC_ALL
+AcceptEnv LC_COLLATE
+AcceptEnv LC_CTYPE
+AcceptEnv LC_IDENTIFICATION
+AcceptEnv LC_MEASUREMENT
+AcceptEnv LC_MESSAGES
+AcceptEnv LC_MONETARY
+AcceptEnv LC_NAME
+AcceptEnv LC_NUMERIC
+AcceptEnv LC_PAPER
+AcceptEnv LC_TELEPHONE
+AcceptEnv LC_TIME
+AcceptEnv XMODIFIERS
+ChallengeResponseAuthentication no
+GSSAPIAuthentication yes
+GSSAPICleanupCredentials yes
+PasswordAuthentication no
+Subsystem sftp /usr/libexec/openssh/sftp-server
+SyslogFacility AUTHPRIV
+UseDNS no
+UsePAM yes
+X11Forwarding yes
+Protocol 2
diff --git a/spec/fixtures/sshd_config_el7 b/spec/fixtures/sshd_config_el7
new file mode 100644
index 0000000..12e4e15
--- /dev/null
+++ b/spec/fixtures/sshd_config_el7
@@ -0,0 +1,140 @@
+#	$OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $
+
+# This is the sshd server system-wide configuration file.  See
+# sshd_config(5) for more information.
+
+# This sshd was compiled with PATH=/usr/local/bin:/usr/bin
+
+# The strategy used for options in the default sshd_config shipped with
+# OpenSSH is to specify options with their default value where
+# possible, but leave them commented.  Uncommented options override the
+# default value.
+
+# If you want to change the port on a SELinux system, you have to tell
+# SELinux about this change.
+# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
+#
+#Port 22
+#AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
+
+HostKey /etc/ssh/ssh_host_rsa_key
+#HostKey /etc/ssh/ssh_host_dsa_key
+HostKey /etc/ssh/ssh_host_ecdsa_key
+HostKey /etc/ssh/ssh_host_ed25519_key
+
+# Ciphers and keying
+#RekeyLimit default none
+
+# Logging
+#SyslogFacility AUTH
+SyslogFacility AUTHPRIV
+#LogLevel INFO
+
+# Authentication:
+
+#LoginGraceTime 2m
+#PermitRootLogin yes
+#StrictModes yes
+#MaxAuthTries 6
+#MaxSessions 10
+
+#PubkeyAuthentication yes
+
+# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
+# but this is overridden so installations will only check .ssh/authorized_keys
+AuthorizedKeysFile	.ssh/authorized_keys
+
+#AuthorizedPrincipalsFile none
+
+#AuthorizedKeysCommand none
+#AuthorizedKeysCommandUser nobody
+
+# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+#HostbasedAuthentication no
+# Change to yes if you don't trust ~/.ssh/known_hosts for
+# HostbasedAuthentication
+#IgnoreUserKnownHosts no
+# Don't read the user's ~/.rhosts and ~/.shosts files
+#IgnoreRhosts yes
+
+# To disable tunneled clear text passwords, change to no here!
+#PasswordAuthentication yes
+#PermitEmptyPasswords no
+PasswordAuthentication no
+
+# Change to no to disable s/key passwords
+#ChallengeResponseAuthentication yes
+ChallengeResponseAuthentication no
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+#KerberosGetAFSToken no
+#KerberosUseKuserok yes
+
+# GSSAPI options
+GSSAPIAuthentication yes
+GSSAPICleanupCredentials no
+#GSSAPIStrictAcceptorCheck yes
+#GSSAPIKeyExchange no
+#GSSAPIEnablek5users no
+
+# 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'.
+# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several
+# problems.
+UsePAM yes
+
+#AllowAgentForwarding yes
+#AllowTcpForwarding yes
+#GatewayPorts no
+X11Forwarding yes
+#X11DisplayOffset 10
+#X11UseLocalhost yes
+#PermitTTY yes
+#PrintMotd yes
+#PrintLastLog yes
+#TCPKeepAlive yes
+#UseLogin no
+#UsePrivilegeSeparation sandbox
+#PermitUserEnvironment no
+#Compression delayed
+#ClientAliveInterval 0
+#ClientAliveCountMax 3
+#ShowPatchLevel no
+#UseDNS yes
+UseDNS no
+#PidFile /var/run/sshd.pid
+#MaxStartups 10:30:100
+#PermitTunnel no
+#ChrootDirectory none
+#VersionAddendum none
+
+# no default banner path
+#Banner none
+
+# Accept locale-related environment variables
+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+AcceptEnv XMODIFIERS
+
+# override default of no subsystems
+Subsystem	sftp	/usr/libexec/openssh/sftp-server
+
+# Example of overriding settings on a per-user basis
+#Match User anoncvs
+#	X11Forwarding no
+#	AllowTcpForwarding no
+#	PermitTTY no
+#	ForceCommand cvs server
diff --git a/spec/fixtures/sshd_config_el7_sorted b/spec/fixtures/sshd_config_el7_sorted
new file mode 100644
index 0000000..9e9977e
--- /dev/null
+++ b/spec/fixtures/sshd_config_el7_sorted
@@ -0,0 +1,34 @@
+# This file is being maintained by Puppet.
+# DO NOT EDIT
+#
+# See https://man.openbsd.org/sshd_config for more info
+
+AcceptEnv LANG
+AcceptEnv LC_CTYPE
+AcceptEnv LC_NUMERIC
+AcceptEnv LC_TIME
+AcceptEnv LC_COLLATE
+AcceptEnv LC_MONETARY
+AcceptEnv LC_MESSAGES
+AcceptEnv LC_PAPER
+AcceptEnv LC_NAME
+AcceptEnv LC_ADDRESS
+AcceptEnv LC_TELEPHONE
+AcceptEnv LC_MEASUREMENT
+AcceptEnv LC_IDENTIFICATION
+AcceptEnv LC_ALL
+AcceptEnv LANGUAGE
+AcceptEnv XMODIFIERS
+AuthorizedKeysFile .ssh/authorized_keys
+ChallengeResponseAuthentication no
+GSSAPIAuthentication yes
+GSSAPICleanupCredentials no
+HostKey /etc/ssh/ssh_host_ecdsa_key
+HostKey /etc/ssh/ssh_host_ed25519_key
+HostKey /etc/ssh/ssh_host_rsa_key
+PasswordAuthentication no
+Subsystem sftp /usr/libexec/openssh/sftp-server
+SyslogFacility AUTHPRIV
+UseDNS no
+UsePAM yes
+X11Forwarding yes
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 74f727d..eeff368 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,7 +1,11 @@
+# This RSpec.configure block is listed twice due to a bug with
+# puppetlabs_spec_helper. https://tickets.puppetlabs.com/browse/PDK-916
+RSpec.configure do |config|
+  config.mock_with :rspec
+end
 require 'puppetlabs_spec_helper/module_spec_helper'
 
 RSpec.configure do |config|
-  config.hiera_config = 'spec/fixtures/hiera/hiera.yaml'
   config.before :each do
     # Ensure that we don't accidentally cache facts and environment between
     # test cases.  This requires each example group to explicitly load the
@@ -10,7 +14,11 @@
     Facter.clear
     Facter.clear_messages
   end
-  config.default_facts = {
-    :environment => 'rp_env',
-  }
+end
+
+RSpec.configure do |c|
+  # Coverage generation
+  c.after(:suite) do
+    RSpec::Puppet::Coverage.report!
+  end
 end
diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb
new file mode 100644
index 0000000..c10f674
--- /dev/null
+++ b/spec/spec_helper_acceptance.rb
@@ -0,0 +1,13 @@
+require 'beaker-rspec'
+require 'beaker-puppet'
+require 'beaker/module_install_helper'
+require 'beaker/puppet_install_helper'
+
+run_puppet_install_helper
+install_module_dependencies
+install_module
+
+RSpec.configure do |c|
+  # Readable test descriptions
+  c.formatter = :documentation
+end
diff --git a/spec/type_aliases/key_type_spec.rb b/spec/type_aliases/key_type_spec.rb
new file mode 100644
index 0000000..fd1d677
--- /dev/null
+++ b/spec/type_aliases/key_type_spec.rb
@@ -0,0 +1,48 @@
+# coding: utf-8
+
+require 'spec_helper'
+
+describe 'Ssh::Key::Type' do
+  describe 'valid types' do
+    [
+      'ssh-dss',
+      'ssh-ed25519',
+      'ssh-rsa',
+      'ecdsa-sha2-nistp256',
+      'ecdsa-sha2-nistp384',
+      'ecdsa-sha2-nistp521',
+      'ed25519',
+      'rsa',
+      'dsa',
+    ].each do |value|
+      describe value.inspect do
+        it { is_expected.to allow_value(value) }
+      end
+    end
+  end
+
+  describe 'invalid types' do
+    context 'with garbage inputs' do
+      [
+        true,
+        false,
+        :keyword,
+        nil,
+        [nil],
+        [nil, nil],
+        { 'foo' => 'bar' },
+        {},
+        '',
+        'ネット',
+        '55555',
+        '0x123',
+        'ssh-dssss',
+        'xrsa',
+      ].each do |value|
+        describe value.inspect do
+          it { is_expected.not_to allow_value(value) }
+        end
+      end
+    end
+  end
+end
diff --git a/spec/type_aliases/permit_root_login_spec.rb b/spec/type_aliases/permit_root_login_spec.rb
new file mode 100644
index 0000000..90aef2a
--- /dev/null
+++ b/spec/type_aliases/permit_root_login_spec.rb
@@ -0,0 +1,44 @@
+# coding: utf-8
+
+require 'spec_helper'
+
+describe 'Ssh::Permit_root_login' do
+  describe 'valid types' do
+    [
+      'yes',
+      'prohibit-password',
+      'without-password',
+      'forced-commands-only',
+      'no',
+    ].each do |value|
+      describe value.inspect do
+        it { is_expected.to allow_value(value) }
+      end
+    end
+  end
+
+  describe 'invalid types' do
+    context 'with garbage inputs' do
+      [
+        true,
+        false,
+        :keyword,
+        nil,
+        [nil],
+        [nil, nil],
+        { 'foo' => 'bar' },
+        {},
+        '',
+        'ネット',
+        '55555',
+        '0x123',
+        'ssh-dssss',
+        'xrsa',
+      ].each do |value|
+        describe value.inspect do
+          it { is_expected.not_to allow_value(value) }
+        end
+      end
+    end
+  end
+end
diff --git a/spec/type_aliases/syslog_facility_spec.rb b/spec/type_aliases/syslog_facility_spec.rb
new file mode 100644
index 0000000..f1ae6f6
--- /dev/null
+++ b/spec/type_aliases/syslog_facility_spec.rb
@@ -0,0 +1,51 @@
+# coding: utf-8
+
+require 'spec_helper'
+
+describe 'Ssh::Syslog_facility' do
+  describe 'valid types' do
+    [
+      'DAEMON',
+      'USER',
+      'AUTH',
+      'LOCAL0',
+      'LOCAL1',
+      'LOCAL2',
+      'LOCAL3',
+      'LOCAL4',
+      'LOCAL5',
+      'LOCAL6',
+      'LOCAL7',
+      'AUTHPRIV',
+    ].each do |value|
+      describe value.inspect do
+        it { is_expected.to allow_value(value) }
+      end
+    end
+  end
+
+  describe 'invalid types' do
+    context 'with garbage inputs' do
+      [
+        true,
+        false,
+        :keyword,
+        nil,
+        ['yes', 'no'],
+        { 'foo' => 'bar' },
+        {},
+        '',
+        'ネット',
+        '55555',
+        '0x123',
+        'daemon',
+        'local',
+        'AUTH0',
+      ].each do |value|
+        describe value.inspect do
+          it { is_expected.not_to allow_value(value) }
+        end
+      end
+    end
+  end
+end
diff --git a/spec/type_aliases/yes_no_spec.rb b/spec/type_aliases/yes_no_spec.rb
new file mode 100644
index 0000000..b119c65
--- /dev/null
+++ b/spec/type_aliases/yes_no_spec.rb
@@ -0,0 +1,40 @@
+# coding: utf-8
+
+require 'spec_helper'
+
+describe 'Ssh::Yes_no' do
+  describe 'valid types' do
+    [
+      'yes',
+      'no',
+    ].each do |value|
+      describe value.inspect do
+        it { is_expected.to allow_value(value) }
+      end
+    end
+  end
+
+  describe 'invalid types' do
+    context 'with garbage inputs' do
+      [
+        true,
+        false,
+        :keyword,
+        nil,
+        ['yes', 'no'],
+        { 'foo' => 'bar' },
+        {},
+        '',
+        'ネット',
+        '55555',
+        '0x123',
+        'yess',
+        'nooo'
+      ].each do |value|
+        describe value.inspect do
+          it { is_expected.not_to allow_value(value) }
+        end
+      end
+    end
+  end
+end
diff --git a/templates/ssh_config.erb b/templates/ssh_config.erb
index 9cb65e3..d76efa5 100644
--- a/templates/ssh_config.erb
+++ b/templates/ssh_config.erb
@@ -1,111 +1,274 @@
 # This file is being maintained by Puppet.
 # DO NOT EDIT
+#
+# See https://man.openbsd.org/sshd_config for more info
 
-# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $
-
-# This is the ssh client system-wide configuration file.  See
-# ssh_config(5) for more information.  This file provides defaults for
-# users, and the values can be changed in per-user configuration files
-# or on the command line.
-
-# Configuration data is parsed as follows:
-#  1. command line options
-#  2. user-specific file
-#  3. system-wide file
-# Any configuration value is only changed the first time it is set.
-# Thus, host-specific definitions should be at the beginning of the
-# configuration file, and defaults at the end.
-
-# Site-wide defaults for some commonly used options.  For a comprehensive
-# list of available options, their meanings and defaults, please see the
-# ssh_config(5) man page.
-
-# Host *
-#   ForwardAgent no
-#   ForwardX11 no
-#   RhostsRSAAuthentication no
-#   RSAAuthentication yes
-   PasswordAuthentication yes
-   PubkeyAuthentication yes
-#   HostbasedAuthentication no
-<% if @ssh_hostbasedauthentication -%>
-   HostbasedAuthentication <%= @ssh_hostbasedauthentication %>
+Host <%= @host %>
+<% if @add_keys_to_agent != nil -%>
+  AddKeysToAgent <%= @add_keys_to_agent %>
 <% end -%>
-#   BatchMode no
-#   CheckHostIP yes
-#   AddressFamily any
-#   ConnectTimeout 0
-#   StrictHostKeyChecking ask
-<% if @ssh_strict_host_key_checking -%>
-   StrictHostKeyChecking <%= @ssh_strict_host_key_checking %>
+<% if @address_family != nil -%>
+  AddressFamily <%= @address_family %>
 <% end -%>
-#   IdentityFile ~/.ssh/identity
-   IdentityFile ~/.ssh/id_rsa
-   IdentityFile ~/.ssh/id_dsa
-#   Port 22
-   Protocol 2
-#   Cipher 3des
-#   Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc
-<% if @ssh_config_ciphers -%>
-    Ciphers <%= @ssh_config_ciphers.join(',') %>
+<% if @batch_mode != nil -%>
+  BatchMode <%= @batch_mode %>
 <% end -%>
-<% if @ssh_config_kexalgorithms -%>
-    KexAlgorithms <%= @ssh_config_kexalgorithms.join(',') %>
+<% if @bind_address != nil -%>
+  BindAddress <%= @bind_address %>
 <% end -%>
-#   EscapeChar ~
-#   Tunnel no
-#   TunnelDevice any:any
-#   PermitLocalCommand no
-#   HashKnownHosts no
-<% if @ssh_config_hash_known_hosts_real != nil -%>
-   HashKnownHosts <%= @ssh_config_hash_known_hosts_real %>
+<% if @bind_interface != nil -%>
+  BindInterface <%= @bind_interface %>
 <% end -%>
-<% if @ssh_config_global_known_hosts_list_real -%>
-   GlobalKnownHostsFile <%= @ssh_config_global_known_hosts_list_real.join(' ') %>
+<% if @canonical_domains != nil -%>
+  CanonicalDomains <%= @canonical_domains.join(' ') %>
 <% end -%>
-<% if @ssh_config_proxy_command -%>
-   ProxyCommand <%= @ssh_config_proxy_command %>
+<% if @canonicalize_fallback_local != nil -%>
+  CanonicalizeFallbackLocal <%= @canonicalize_fallback_local %>
 <% end -%>
-Host *
-#  GSSAPIAuthentication yes
-  GSSAPIAuthentication <%= @ssh_gssapiauthentication %>
-<% if @ssh_gssapidelegatecredentials != nil -%>
-GSSAPIDelegateCredentials <%= @ssh_gssapidelegatecredentials %>
+<% if @canonicalize_hostname != nil -%>
+  CanonicalizeHostname <%= @canonicalize_hostname %>
 <% end -%>
-# If this option is set to yes then remote X11 clients will have full access
-# to the original X11 display. As virtually no X11 client supports the untrusted
-# mode correctly we set this to yes.
-<% if @ssh_config_forward_x11_trusted_real != nil -%>
-  ForwardX11Trusted <%= @ssh_config_forward_x11_trusted_real %>
+<% if @canonicalize_max_dots != nil -%>
+  CanonicalizeMaxDots <%= @canonicalize_max_dots %>
 <% end -%>
-<% if @ssh_config_forward_agent != nil -%>
-  ForwardAgent <%= @ssh_config_forward_agent %>
+<% if @canonicalize_permitted_cnames != nil -%>
+  CanonicalizePermittedCNAMEs <%= @canonicalize_permitted_cnames.join(',') %>
 <% end -%>
-<% if @ssh_config_forward_x11 != nil -%>
-  ForwardX11 <%= @ssh_config_forward_x11 %>
+<% if @ca_signature_algorithms != nil -%>
+  CASignatureAlgorithms <%= @ca_signature_algorithms.join(',') %>
 <% end -%>
-<% if (@ssh_config_use_roaming_real == 'yes') or (@ssh_config_use_roaming_real == 'no') -%>
-  UseRoaming <%= @ssh_config_use_roaming_real %>
+<% if @certificate_file != nil -%>
+<%   @certificate_file.each do |v| -%>
+  CertificateFile <%= v %>
+<%   end -%>
 <% end -%>
-<% if @ssh_config_server_alive_interval != nil -%>
-  ServerAliveInterval <%= @ssh_config_server_alive_interval %>
+<% if @challenge_response_authentication != nil -%>
+  ChallengeResponseAuthentication <%= @challenge_response_authentication %>
 <% end -%>
-<% if @ssh_sendenv_real == true -%>
-# Send locale-related environment variables
-  SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
-  SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
-  SendEnv LC_IDENTIFICATION LC_ALL
-<% if @ssh_config_sendenv_xmodifiers_real == true -%>
-  SendEnv XMODIFIERS
+<% if @check_host_ip != nil -%>
+  CheckHostIP <%= @check_host_ip %>
 <% end -%>
+<% if @ciphers != nil -%>
+  Ciphers <%= @ciphers.join(',') %>
 <% end -%>
-<% if @ssh_config_macs -%>
-  MACs <%= @ssh_config_macs.join(',') %>
+<% if @clear_all_forwardings != nil -%>
+  ClearAllForwardings <%= @clear_all_forwardings %>
 <% end -%>
-<% if not @ssh_enable_ssh_keysign.nil? -%>
-# EnableSSHKeysign no
-  EnableSSHKeysign <%= @ssh_enable_ssh_keysign %>
+<% if @compression != nil -%>
+  Compression <%= @compression %>
 <% end -%>
-<% if @ssh_config_user_known_hosts_file -%>
-  UserKnownHostsFile <%= @ssh_config_user_known_hosts_file.join(' ') %>
+<% if @connection_attempts != nil -%>
+  ConnectionAttempts <%= @connection_attempts %>
+<% end -%>
+<% if @connect_timeout != nil -%>
+  ConnectTimeout <%= @connect_timeout %>
+<% end -%>
+<% if @control_master != nil -%>
+  ControlMaster <%= @control_master %>
+<% end -%>
+<% if @control_path != nil -%>
+  ControlPath <%= @control_path %>
+<% end -%>
+<% if @control_persist != nil -%>
+  ControlPersist <%= @control_persist %>
+<% end -%>
+<% if @dynamic_forward != nil -%>
+  DynamicForward <%= @dynamic_forward %>
+<% end -%>
+<% if @enable_ssh_keysign != nil -%>
+  EnableSSHKeysign <%= @enable_ssh_keysign %>
+<% end -%>
+<% if @escape_char != nil -%>
+  EscapeChar <%= @escape_char %>
+<% end -%>
+<% if @exit_on_forward_failure != nil -%>
+  ExitOnForwardFailure <%= @exit_on_forward_failure %>
+<% end -%>
+<% if @fingerprint_hash != nil -%>
+  FingerprintHash  <%= @fingerprint_hash %>
+<% end -%>
+<% if @forward_agent != nil -%>
+  ForwardAgent <%= @forward_agent %>
+<% end -%>
+<% if @forward_x11 != nil -%>
+  ForwardX11 <%= @forward_x11 %>
+<% end -%>
+<% if @forward_x11_timeout != nil -%>
+  ForwardX11Timeout <%= @forward_x11_timeout %>
+<% end -%>
+<% if @forward_x11_trusted != nil -%>
+  ForwardX11Trusted <%= @forward_x11_trusted %>
+<% end -%>
+<% if @gateway_ports != nil -%>
+  GatewayPorts <%= @gateway_ports %>
+<% end -%>
+<% if @global_known_hosts_file != nil -%>
+  GlobalKnownHostsFile <%= @global_known_hosts_file.join(' ') %>
+<% end -%>
+<% if @gss_api_authentication != nil -%>
+  GSSAPIAuthentication <%= @gss_api_authentication %>
+<% end -%>
+<% if @gss_api_delegate_credentials != nil -%>
+  GSSAPIDelegateCredentials <%= @gss_api_delegate_credentials %>
+<% end -%>
+<% if @hash_known_hosts != nil -%>
+  HashKnownHosts <%= @hash_known_hosts %>
+<% end -%>
+<% if @hostbased_authentication != nil -%>
+  HostbasedAuthentication <%= @hostbased_authentication %>
+<% end -%>
+<% if @hostbased_key_types != nil -%>
+  HostbasedKeyTypes <%= @hostbased_key_types.join(',') %>
+<% end -%>
+<% if @host_key_algorithms != nil -%>
+  HostKeyAlgorithms <%= @host_key_algorithms.join(',') %>
+<% end -%>
+<% if @host_key_alias != nil -%>
+  HostKeyAlias <%= @host_key_alias %>
+<% end -%>
+<% if @host_name != nil -%>
+  HostNname <%= @host_name %>
+<% end -%>
+<% if @identities_only != nil -%>
+  IdentitiesOnly <%= @identities_only %>
+<% end -%>
+<% if @identity_agent != nil -%>
+  IdentityAgent <%= @identity_agent %>
+<% end -%>
+<% if @identity_file != nil -%>
+  IdentityFile <%= @identity_file %>
+<% end -%>
+<% if @ignore_unknown != nil -%>
+  IgnoreUnknown <%= @ignore_unknown %>
+<% end -%>
+<% if @include != nil -%>
+  Include <%= @include %>
+<% end -%>
+<% if @ip_qos != nil -%>
+  IPQoS <%= @ip_qos %>
+<% end -%>
+<% if @kbd_interactive_authentication != nil -%>
+  KbdInteractiveAuthentication <%= @kbd_interactive_authentication %>
+<% end -%>
+<% if @kbd_interactive_devices != nil -%>
+  KbdInteractiveDevices <%= @kbd_interactive_devices.join(',') %>
+<% end -%>
+<% if @kex_algorithms != nil -%>
+  KexAlgorithms <%= @kex_algorithms.join(',') %>
+<% end -%>
+<% if @local_command != nil -%>
+  LocalCommand <%= @local_command %>
+<% end -%>
+<% if @local_forward != nil -%>
+  LocalForward <%= @local_forward %>
+<% end -%>
+<% if @log_level != nil -%>
+  LogLevel <%= @log_level %>
+<% end -%>
+<% if @no_host_authentication_for_localhost != nil -%>
+  NoHostAuthenticationForLocalhost <%= @no_host_authentication_for_localhost %>
+<% end -%>
+<% if @number_of_password_prompts != nil -%>
+  NumberOfPasswordPrompts <%= @number_of_password_prompts %>
+<% end -%>
+<% if @password_authentication != nil -%>
+  PasswordAuthentication <%= @password_authentication %>
+<% end -%>
+<% if @permit_local_command != nil -%>
+  PermitLocalCommand <%= @permit_local_command %>
+<% end -%>
+<% if @pkcs11_provider != nil -%>
+  PKCS11Provider <%= @pkcs11_provider %>
+<% end -%>
+<% if @port != nil -%>
+  Port <%= @port %>
+<% end -%>
+<% if @preferred_authentications != nil -%>
+  PreferredAuthentications <%= @preferred_authentications.join(',') %>
+<% end -%>
+<% if @proxy_command != nil -%>
+  ProxyCommand <%= @proxy_command %>
+<% end -%>
+<% if @proxy_jump != nil -%>
+  ProxyJump <%= @proxy_jump.join(',') %>
+<% end -%>
+<% if @proxy_use_fdpass != nil -%>
+  ProxyUseFdpass <%= @proxy_use_fdpass %>
+<% end -%>
+<% if @pubkey_accepted_key_types != nil -%>
+  PubkeyAcceptedKeyTypes <%= @pubkey_accepted_key_types.join(',') %>
+<% end -%>
+<% if @pubkey_authentication != nil -%>
+  PubkeyAuthentication <%= @pubkey_authentication %>
+<% end -%>
+<% if @rekey_limit != nil -%>
+  RekeyLimit <%= @rekey_limit %>
+<% end -%>
+<% if @remote_command != nil -%>
+  RemoteCommand <%= @remote_command %>
+<% end -%>
+<% if @remote_forward != nil -%>
+  RemoteForward <%= @remote_forward %>
+<% end -%>
+<% if @request_tty != nil -%>
+  RequestTTY <%= @request_tty %>
+<% end -%>
+<% if @revoked_host_keys != nil -%>
+  RevokedHostKeys <%= @revoked_host_keys %>
+<% end -%>
+<% if @send_env != nil -%>
+<%   @send_env.each do |v| -%>
+  SendEnv <%= v %>
+<%   end -%>
+<% end -%>
+<% if @server_alive_count_max != nil -%>
+  ServerAliveCountMax <%= @server_alive_count_max %>
+<% end -%>
+<% if @server_alive_interval != nil -%>
+  ServerAliveIAerval <%= @server_alive_interval %>
+<% end -%>
+<% if @set_env != nil -%>
+  SetEnv <%= @set_env.join(' ') %>
+<% end -%>
+<% if @stream_local_bind_mask != nil -%>
+  StreamLocalBindMask <%= @stream_local_bind_mask %>
+<% end -%>
+<% if @stream_local_bind_unlink != nil -%>
+  StreamLocalBindUnlink <%= @stream_local_bind_unlink %>
+<% end -%>
+<% if @strict_host_key_checking != nil -%>
+  StrictHostKeyChecking <%= @strict_host_key_checking %>
+<% end -%>
+<% if @syslog_facility != nil -%>
+  SyslogFacility <%= @syslog_facility %>
+<% end -%>
+<% if @tcp_keep_alive != nil -%>
+  TCPKeepAlive <%= @tcp_keep_alive %>
+<% end -%>
+<% if @tunnel != nil -%>
+  Tunnel <%= @tunnel %>
+<% end -%>
+<% if @tunnel_device != nil -%>
+  TunnelDevice <%= @tunnel_device %>
+<% end -%>
+<% if @update_host_keys != nil -%>
+  UpdateHostKeys <%= @update_host_keys %>
+<% end -%>
+<% if @user != nil -%>
+  User <%= @user %>
+<% end -%>
+<% if @user_known_hosts_file != nil -%>
+  UserKnownHostsFile <%= @user_known_hosts_file.join(' ') %>
+<% end -%>
+<% if @verify_host_key_dns != nil -%>
+ VerifyHostKeyDNS <%= @verify_host_key_dns %>
+<% end -%>
+<% if @visual_host_key != nil -%>
+  VisualHostKey <%= @visual_host_key %>
+<% end -%>
+<% if @xauth_location != nil -%>
+  XAuthLocation <%= @xauth_location %>
+<% end -%>
+<% if @custom != nil -%>
+<%= @custom %>
 <% end -%>
diff --git a/templates/sshd_config.erb b/templates/sshd_config.erb
index 4e1bd70..5694c3e 100644
--- a/templates/sshd_config.erb
+++ b/templates/sshd_config.erb
@@ -1,288 +1,297 @@
 # This file is being maintained by Puppet.
 # DO NOT EDIT
+#
+# See https://man.openbsd.org/sshd_config for more info
 
-# $OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $
-
-# This is the sshd server system-wide configuration file.  See
-# sshd_config(5) for more information.
-
-# This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin
-
-# The strategy used for options in the default sshd_config shipped with
-# OpenSSH is to specify options with their default value where
-# possible, but leave them commented.  Uncommented options change a
-# default value.
-
-#Port 22
-<% @sshd_config_port_array.each do |p| -%>
-<%= "Port #{p}" %>
-<% end -%>
-#Protocol 2,1
-Protocol 2
-<% if @sshd_addressfamily_real != nil -%>
-#AddressFamily any
-AddressFamily <%= @sshd_addressfamily_real %>
-<% end -%>
-<% if @sshd_listen_address.class == Array -%>
-<% @sshd_listen_address.each do |val| -%>
-ListenAddress <%= val %>
-<% end -%>
-<% elsif @sshd_listen_address.class == String -%>
-ListenAddress <%= @sshd_listen_address %>
-<% end -%>
-
-# HostKey for protocol version 1
-#HostKey /etc/ssh/ssh_host_key
-# HostKeys for protocol version 2
-#HostKey /etc/ssh/ssh_host_rsa_key
-#HostKey /etc/ssh/ssh_host_dsa_key
-<% @sshd_config_hostkey_real.each do |hostkey| -%>
-HostKey <%= hostkey %>
-<% end -%>
-
-# Lifetime and size of ephemeral version 1 server key
-#KeyRegenerationInterval 1h
-#ServerKeyBits 1024
-<% if @sshd_config_serverkeybits_real != nil -%>
-ServerKeyBits <%= @sshd_config_serverkeybits_real %>
-<% end -%>
-# Logging
-# obsoletes QuietMode and FascistLogging
-#SyslogFacility AUTH
-SyslogFacility <%= @sshd_config_syslog_facility %>
-#LogLevel INFO
-LogLevel <%= @sshd_config_loglevel %>
-
-# Authentication:
-
-#LoginGraceTime 120
-LoginGraceTime <%= @sshd_config_login_grace_time %>
-#PermitRootLogin yes
-PermitRootLogin <%= @permit_root_login %>
-#StrictModes yes
-<% if @sshd_config_strictmodes -%>
-StrictModes <%= @sshd_config_strictmodes %>
-<% end -%>
-#MaxAuthTries 6
-<% if @sshd_config_maxauthtries %>
-MaxAuthTries <%= @sshd_config_maxauthtries %>
-<% end -%>
-
-#RSAAuthentication yes
-<% if @sshd_pubkeyacceptedkeytypes -%>
-PubkeyAcceptedKeyTypes <%= @sshd_pubkeyacceptedkeytypes.join(',') %>
-<% end -%>
-#PubkeyAuthentication yes
-PubkeyAuthentication <%= @sshd_pubkeyauthentication %>
-#AuthorizedKeysFile .ssh/authorized_keys
-<% if @sshd_config_authkey_location -%>
-AuthorizedKeysFile <%= @sshd_config_authkey_location %>
-<% end -%>
-<% if @sshd_authorized_keys_command -%>
-AuthorizedKeysCommand <%= @sshd_authorized_keys_command %>
-<% end -%>
-<% if @sshd_authorized_keys_command_user -%>
-AuthorizedKeysCommandUser <%= @sshd_authorized_keys_command_user %>
-<% end -%>
-
-# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
-#RhostsRSAAuthentication no
-# similar for protocol version 2
-#HostbasedAuthentication no
-HostbasedAuthentication <%= @sshd_hostbasedauthentication %>
-# Change to yes if you don't trust ~/.ssh/known_hosts for
-# RhostsRSAAuthentication and HostbasedAuthentication
-#IgnoreUserKnownHosts no
-IgnoreUserKnownHosts <%= @sshd_ignoreuserknownhosts %>
-# Don't read the user's ~/.rhosts and ~/.shosts files
-#IgnoreRhosts yes
-IgnoreRhosts <%= @sshd_ignorerhosts %>
-
-<%- if @sshd_config_authenticationmethods -%>
-AuthenticationMethods <%= @sshd_config_authenticationmethods.join(',') %>
-<%- end -%>
-# To disable tunneled clear text passwords, change to no here!
-#PasswordAuthentication yes
-PasswordAuthentication <%= @sshd_password_authentication %>
-<% if @sshd_pamauthenticationviakbdint_real != nil -%>
-# Use PAM via keyboard interactive method for authentication.
-# Depending on the setup of pam.conf(4) this may allow tunneled clear text
-# passwords even when PasswordAuthentication is set to no. This is dependent
-# on what the individual modules request and is out of the control of sshd
-# or the protocol.
-PAMAuthenticationViaKBDInt <%= @sshd_pamauthenticationviakbdint_real %>
-<% end -%>
-#PermitEmptyPasswords no
-<% if @sshd_config_permitemptypasswords != nil -%>
-PermitEmptyPasswords <%= @sshd_config_permitemptypasswords %>
-<% end -%>
-
-# Change to no to disable s/key passwords
-#ChallengeResponseAuthentication yes
-ChallengeResponseAuthentication <%= @sshd_config_challenge_resp_auth %>
-
-# Kerberos options
-<% if @sshd_kerberos_authentication != nil -%>
-#KerberosAuthentication no
-KerberosAuthentication <%= @sshd_kerberos_authentication %>
-<% end -%>
-#KerberosOrLocalPasswd yes
-#KerberosTicketCleanup yes
-#KerberosGetAFSToken no
-
-# GSSAPI options
-#GSSAPIAuthentication no
-GSSAPIAuthentication <%= @sshd_gssapiauthentication %>
-<% if @sshd_gssapikeyexchange_real != nil -%>
-GSSAPIKeyExchange <%= @sshd_gssapikeyexchange_real %>
-<% end -%>
-<% if @sshd_gssapicleanupcredentials_real != nil -%>
-#GSSAPICleanupCredentials yes
-GSSAPICleanupCredentials <%= @sshd_gssapicleanupcredentials_real %>
-<% end -%>
-
-<% if @sshd_use_pam_real != nil -%>
-# 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 mechanism.
-# Depending on your PAM configuration, this may bypass the setting of
-# PasswordAuthentication, PermitEmptyPasswords, and
-# "PermitRootLogin without-password". If you just want the PAM account and
-# session checks to run without PAM authentication, then enable this but set
-# ChallengeResponseAuthentication=no
-#UsePAM no
-UsePAM <%= @sshd_use_pam_real %>
-<% end -%>
-
-<% if @sshd_acceptenv_real == true -%>
-# Accept locale-related environment variables
-AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
-AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
-AcceptEnv LC_IDENTIFICATION LC_ALL
-<% end -%>
-#AllowTcpForwarding yes
-AllowTcpForwarding <%= @sshd_allow_tcp_forwarding %>
-#GatewayPorts no
-#X11Forwarding no
-X11Forwarding <%= @sshd_x11_forwarding %>
-#X11DisplayOffset 10
-#X11UseLocalhost yes
-X11UseLocalhost <%= @sshd_x11_use_localhost %>
-#PrintMotd yes
-PrintMotd <%= @sshd_config_print_motd %>
-#PrintLastLog yes
-<% if @sshd_config_print_last_log != nil -%>
-PrintLastLog <%= @sshd_config_print_last_log %>
-<% end -%>
-#TCPKeepAlive yes
-<% if @sshd_config_tcp_keepalive_real != nil -%>
-TCPKeepAlive <%= @sshd_config_tcp_keepalive_real %>
-<% end -%>
-#UseLogin no
-#UsePrivilegeSeparation yes
-<% if @sshd_config_use_privilege_separation != nil -%>
-UsePrivilegeSeparation <%= @sshd_config_use_privilege_separation %>
-<% end -%>
-#PermitUserEnvironment no
-<% if @sshd_config_permituserenvironment != nil -%>
-PermitUserEnvironment <%= @sshd_config_permituserenvironment %>
-<% end -%>
-#Compression delayed
-<% if @sshd_config_compression != nil -%>
-Compression <%= @sshd_config_compression %>
-<% end -%>
-#ClientAliveInterval 0
-ClientAliveInterval <%= @sshd_client_alive_interval %>
-ClientAliveCountMax <%= @sshd_client_alive_count_max %>
-#ShowPatchLevel no
-<% if @sshd_config_use_dns_real != nil -%>
-#UseDNS yes
-UseDNS <%= @sshd_config_use_dns_real %>
-<% end -%>
-#PidFile /var/run/sshd.pid
-<% if @sshd_config_maxstartups -%>
-MaxStartups <%= @sshd_config_maxstartups %>
-<% else -%>
-#MaxStartups 10:30:100
-<% end -%>
-<% if @sshd_config_maxsessions_integer != nil -%>
-MaxSessions <%= @sshd_config_maxsessions_integer %>
-<% else -%>
-#MaxSessions 10
-<% end -%>
-
-#PermitTunnel no
-<% if @sshd_config_permittunnel_real != nil -%>
-PermitTunnel <%= @sshd_config_permittunnel_real %>
-<% end -%>
-<% if @sshd_config_chrootdirectory -%>
-ChrootDirectory <%= @sshd_config_chrootdirectory %>
-<% else -%>
-#ChrootDirectory none
-<% end -%>
-<% if @sshd_config_forcecommand -%>
-ForceCommand <%= @sshd_config_forcecommand %>
-<% end -%>
-<% if @sshd_config_allowagentforwarding != nil -%>
-#AllowAgentForwarding yes
-AllowAgentForwarding <%= @sshd_config_allowagentforwarding %>
-<% end -%>
-
-# no default banner path
-#Banner none
-Banner <%= @sshd_config_banner %>
-
-<% if @sshd_config_xauth_location_real -%>
-#XAuthLocation /usr/bin/xauth
-XAuthLocation <%= @sshd_config_xauth_location_real %>
-
-<% end -%>
-# override default of no subsystems
-Subsystem sftp <%= @sshd_config_subsystem_sftp_real %>
-
-<% if @sshd_config_ciphers -%>
-Ciphers <%= @sshd_config_ciphers.join(',') %>
-<% end -%>
-<% if @sshd_config_kexalgorithms -%>
-KexAlgorithms <%= @sshd_config_kexalgorithms.join(',') %>
-<% end -%>
-<% if @sshd_config_macs -%>
-MACs <%= @sshd_config_macs.join(',') %>
-<% end -%>
-<% if @sshd_config_denyusers_real != [] -%>
-DenyUsers <%= @sshd_config_denyusers_real.join(' ') %>
-<% end -%>
-<% if @sshd_config_denygroups_real != [] -%>
-DenyGroups <%= @sshd_config_denygroups_real.join(' ') %>
-<% end -%>
-<% if @sshd_config_allowusers_real != [] -%>
-AllowUsers <%= @sshd_config_allowusers_real.join(' ') %>
-<% end -%>
-<% if @sshd_config_allowgroups_real != [] -%>
-AllowGroups <%= @sshd_config_allowgroups_real.join(' ') %>
-<% end -%>
-<% if @sshd_config_key_revocation_list_real -%>
-RevokedKeys <%= @sshd_config_key_revocation_list_real %>
-<% end -%>
-<% if @sshd_config_hostcertificate_real.class == Array -%>
-<%   @sshd_config_hostcertificate_real.each do |cert| -%>
-HostCertificate <%= cert %>
+<% if @accept_env != nil -%>
+<%   @accept_env.each do |v| -%>
+AcceptEnv <%= v %>
 <%   end -%>
-<% elsif @sshd_config_hostcertificate_real.class == String -%>
-HostCertificate <%= @sshd_config_hostcertificate_real %>
 <% end -%>
-<% if @sshd_config_trustedusercakeys_real -%>
-TrustedUserCAKeys <%= @sshd_config_trustedusercakeys_real %>
+<% if @address_family != nil -%>
+AddressFamily <%= @address_family %>
 <% end -%>
-<% if @sshd_config_authorized_principals_file_real -%>
-AuthorizedPrincipalsFile <%= @sshd_config_authorized_principals_file_real %>
+<% if @allow_agent_forwarding != nil -%>
+AllowAgentForwarding <%= @allow_agent_forwarding %>
 <% end -%>
-<% if @sshd_config_match -%>
-
-<%   @sshd_config_match.sort.each do |key, hash| -%>
-Match <%= key %>
-<%     hash.sort.each do |values| -%>
-  <%= values %>
-<%     end -%>
+<% if @allow_groups != nil -%>
+<%   if @allow_groups.class == Array -%>
+AllowGroups <%= @allow_groups.join(' ') %>
+<%   elsif @allow_groups.class == String -%>
+AllowGroups <%= @allow_groups %>
 <%   end -%>
 <% end -%>
+<% if @allow_stream_local_forwarding != nil -%>
+AllowStreamLocalForwarding <%= @allow_stream_local_forwarding %>
+<% end -%>
+<% if @allow_tcp_forwarding != nil -%>
+AllowTcpForwarding <%= @allow_tcp_forwarding %>
+<% end -%>
+<% if @allow_users != nil -%>
+<%   if @allow_users.class == Array -%>
+AllowUsers <%= @allow_users.join(' ') %>
+<%   elsif @allow_users.class == String -%>
+AllowUsers <%= @allow_users %>
+<%   end -%>
+<% end -%>
+<% if @authentication_methods != nil -%>
+AuthenticationMethods <%= @authentication_methods.join(',') %>
+<% end -%>
+<% if @authorized_keys_command != nil -%>
+AuthorizedKeysCommand <%= @authorized_keys_command %>
+<% end -%>
+<% if @authorized_keys_command_user != nil -%>
+AuthorizedKeysCommandUser <%= @authorized_keys_command_user %>
+<% end -%>
+<% if @authorized_keys_file != nil -%>
+<%   if @authorized_keys_file.class == Array -%>
+AuthorizedKeysFile <%= @authorized_keys_file.join(' ') %>
+<%   elsif @authorized_keys_file.class == String -%>
+AuthorizedKeysFile <%= @authorized_keys_file %>
+<%   end -%>
+<% end -%>
+<% if @authorized_principals_command != nil -%>
+AuthorizedPrincipalsCommand <%= @authorized_principals_command %>
+<% end -%>
+<% if @authorized_principals_command_user != nil -%>
+AuthorizedPrincipalsCommandUser <%= @authorized_principals_command_user %>
+<% end -%>
+<% if @authorized_principals_file != nil -%>
+AuthorizedPrincipalsFile <%= @authorized_principals_file %>
+<% end -%>
+<% if @banner != nil -%>
+Banner <%= @banner %>
+<% end -%>
+<% if @ca_signature_algorithms != nil -%>
+CASignatureAlgorithms <%= @ca_signature_algorithms.join(',') %>
+<% end -%>
+<% if @challenge_response_authentication != nil -%>
+ChallengeResponseAuthentication <%= @challenge_response_authentication %>
+<% end -%>
+<% if @chroot_directory != nil -%>
+ChrootDirectory <%= @chroot_directory %>
+<% end -%>
+<% if @ciphers != nil -%>
+Ciphers <%= @ciphers.join(',') %>
+<% end -%>
+<% if @client_alive_count_max != nil -%>
+ClientAliveCountMax <%= @client_alive_count_max %>
+<% end -%>
+<% if @client_alive_interval != nil -%>
+ClientAliveInterval <%= @client_alive_interval %>
+<% end -%>
+<% if @compression != nil -%>
+Compression <%= @compression %>
+<% end -%>
+<% if @deny_groups != nil -%>
+<%   if @deny_groups.class == Array -%>
+DenyGroups <%= @deny_groups.join(' ') %>
+<%   elsif @deny_groups.class == String -%>
+DenyGroups <%= @deny_groups %>
+<%   end -%>
+<% end -%>
+<% if @deny_users != nil -%>
+<%   if @deny_users.class == Array -%>
+DenyUsers <%= @deny_users.join(' ') %>
+<%   elsif @deny_users.class == String -%>
+DenyUsers <%= @deny_users %>
+<%   end -%>
+<% end -%>
+<% if @disable_forwarding != nil -%>
+DisableForwarding <%= @disable_forwarding %>
+<% end -%>
+<% if @expose_auth_info != nil -%>
+ExposeAuthInfo <%= @expose_auth_info %>
+<% end -%>
+<% if @fingerprint_hash != nil -%>
+FingerprintHash <%= @fingerprint_hash %>
+<% end -%>
+<% if @force_command != nil -%>
+ForceCommand <%= @force_command %>
+<% end -%>
+<% if @gateway_ports != nil -%>
+GatewayPorts <%= @gateway_ports %>
+<% end -%>
+<% if @gss_api_authentication != nil -%>
+GSSAPIAuthentication <%= @gss_api_authentication %>
+<% end -%>
+<% if @gss_api_cleanup_credentials != nil -%>
+GSSAPICleanupCredentials <%= @gss_api_cleanup_credentials %>
+<% end -%>
+<% if @gss_api_strict_acceptor_check != nil -%>
+GSSAPIStrictAcceptorCheck <%= @gss_api_strict_acceptor_check %>
+<% end -%>
+<% if @hostbased_accepted_key_types != nil -%>
+HostbasedAcceptedKeyTypes <%= @hostbased_accepted_key_types.join(',') %>
+<% end -%>
+<% if @hostbased_authentication != nil -%>
+HostbasedAuthentication <%= @hostbased_authentication %>
+<% end -%>
+<% if @hostbased_uses_name_from_packet_only != nil -%>
+HostbasedUsesNameFromPacketOnly <%= @hostbased_uses_name_from_packet_only %>
+<% end -%>
+<% if @host_certificate != nil -%>
+HostCertificate <%= @host_certificate %>
+<% end -%>
+<% if @host_key != nil -%>
+<%   @host_key.each do |v| -%>
+HostKey <%= v %>
+<%   end -%>
+<% end -%>
+<% if @host_key_agent != nil -%>
+HostKeyAgent <%= @host_key_agent %>
+<% end -%>
+<% if @host_key_algorithms != nil -%>
+HostKeyAlgorithms <%= @host_key_algorithms.join(',') %>
+<% end -%>
+<% if @ignore_rhosts != nil -%>
+IgnoreRhosts <%= @ignore_rhosts %>
+<% end -%>
+<% if @ignore_user_known_hosts != nil -%>
+IgnoreUserKnownHosts <%= @ignore_user_known_hosts %>
+<% end -%>
+<% if @ip_qos != nil -%>
+IPQoS <%= @ip_qos %>
+<% end -%>
+<% if @kbd_interactive_authentication != nil -%>
+KbdInteractiveAuthentication <%= @kbd_interactive_authentication %>
+<% end -%>
+<% if @kerberos_authentication != nil -%>
+KerberosAuthentication <%= @kerberos_authentication %>
+<% end -%>
+<% if @kerberos_get_afs_token != nil -%>
+KerberosGetAFSToken <%= @kerberos_get_afs_token %>
+<% end -%>
+<% if @kerberos_or_local_passwd != nil -%>
+KerberosOrLocalPasswd <%= @kerberos_or_local_passwd %>
+<% end -%>
+<% if @kerberos_ticket_cleanup != nil -%>
+KerberosTicketCleanup <%= @kerberos_ticket_cleanup %>
+<% end -%>
+<% if @kex_algorithms != nil -%>
+KexAlgorithms <%= @kex_algorithms.join(',') %>
+<% end -%>
+<% if @listen_address != nil -%>
+<%   @listen_address.each do |v| -%>
+ListenAddress <%= v %>
+<%   end -%>
+<% end -%>
+<% if @login_grace_time != nil -%>
+LoginGraceTime <%= @login_grace_time %>
+<% end -%>
+<% if @log_level != nil -%>
+LogLevel <%= @log_level %>
+<% end -%>
+<% if @macs != nil -%>
+MACs <%= @macs.join(',') %>
+<% end -%>
+<% if @max_auth_tries != nil -%>
+MaxAuthTries <%= @max_auth_tries %>
+<% end -%>
+<% if @max_sessions != nil -%>
+MaxSessions <%= @max_sessions %>
+<% end -%>
+<% if @max_startups != nil -%>
+MaxStartups <%= @max_startups %>
+<% end -%>
+<% if @password_authentication != nil -%>
+PasswordAuthentication <%= @password_authentication %>
+<% end -%>
+<% if @permit_empty_passwords != nil -%>
+PermitEmptyPasswords <%= @permit_empty_passwords %>
+<% end -%>
+<% if @permit_listen != nil -%>
+<%   if @permit_listen.class == Array -%>
+PermitListen <%= @permit_listen.join(' ') %>
+<%   elsif @permit_listen.class == String -%>
+PermitListen <%= @permit_listen %>
+<%   end -%>
+<% end -%>
+<% if @permit_root_login != nil -%>
+<% end -%>
+<% if @permit_tty != nil -%>
+PermitTTY <%= @permit_tty %>
+<% end -%>
+<% if @permit_tunnel != nil -%>
+PermitTunnel <%= @permit_tunnel %>
+<% end -%>
+<% if @permit_user_environment != nil -%>
+PermitUserEnvironment <%= @permit_user_environment %>
+<% end -%>
+<% if @permit_user_rc != nil -%>
+PermitUserRC <%= @permit_user_rc %>
+<% end -%>
+<% if @pid_file != nil -%>
+PidFile <%= @pid_file %>
+<% end -%>
+<% if @port != nil -%>
+<% end -%>
+<% if @print_last_log != nil -%>
+PrintLastLog <%= @print_last_log %>
+<% end -%>
+<% if @print_motd != nil -%>
+PrintMotd <%= @print_motd %>
+<% end -%>
+<% if @pubkey_accepted_key_types != nil -%>
+PubkeyAcceptedKeyTypes <%= @pubkey_accepted_key_types.join(',') %>
+<% end -%>
+<% if @pubkey_authentication != nil -%>
+PubkeyAuthentication <%= @pubkey_authentication %>
+<% end -%>
+<% if @rekey_limit != nil -%>
+RekeyLimit <%= @rekey_limit %>
+<% end -%>
+<% if @revoked_keys != nil -%>
+RevokedKeys <%= @revoked_keys %>
+<% end -%>
+<% if @rdomain != nil -%>
+RDomain <%= @rdomain %>
+<% end -%>
+<% if @set_env != nil -%>
+SetEnv <%= @set_env %>
+<% end -%>
+<% if @stream_local_bind_mask != nil -%>
+StreamLocalBindMask <%= @stream_local_bind_mask %>
+<% end -%>
+<% if @stream_local_bind_unlink != nil -%>
+StreamLocalBindUnlink <%= @stream_local_bind_unlink %>
+<% end -%>
+<% if @strict_modes != nil -%>
+StrictModes <%= @strict_modes %>
+<% end -%>
+<% if @subsystem != nil -%>
+Subsystem <%= @subsystem %>
+<% end -%>
+<% if @syslog_facility != nil -%>
+SyslogFacility <%= @syslog_facility %>
+<% end -%>
+<% if @tcp_keep_alive != nil -%>
+TCPKeepAlive <%= @tcp_keep_alive %>
+<% end -%>
+<% if @trusted_user_ca_keys != nil -%>
+TrustedUserCAKeys <%= @trusted_user_ca_keys %>
+<% end -%>
+<% if @use_dns != nil -%>
+UseDNS <%= @use_dns %>
+<% end -%>
+<% if @use_pam != nil -%>
+UsePAM <%= @use_pam %>
+<% end -%>
+<% if @version_addendum != nil -%>
+VersionAddendum <%= @version_addendum %>
+<% end -%>
+<% if @x11_display_offset != nil -%>
+X11DisplayOffset <%= @x11_display_offset %>
+<% end -%>
+<% if @x11_forwarding != nil -%>
+X11Forwarding <%= @x11_forwarding %>
+<% end -%>
+<% if @x11_use_localhost != nil -%>
+X11UseLocalhost <%= @x11_use_localhost %>
+<% end -%>
+<% if @xauth_location != nil -%>
+XAuthLocation <%= @xauth_location %>
+<% end -%>
+<% if @custom != nil -%>
+<%= @custom %>
+<% end -%>
diff --git a/tests/init.pp b/tests/init.pp
index ea1c831..13a4638 100644
--- a/tests/init.pp
+++ b/tests/init.pp
@@ -1 +1 @@
-include ::ssh
+include ssh
diff --git a/tests/provision.sh b/tests/provision.sh
new file mode 100644
index 0000000..7f9a539
--- /dev/null
+++ b/tests/provision.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+if [ $# -ne 1 ]; then
+  echo "Must pass one argument of either 'debian' or 'el'"
+  exit 255
+fi
+
+case "$1" in
+  'el')
+    function rpm_install() {
+      package=$(echo $1 | awk -F "/" '{print $NF}')
+      wget --quiet $1
+      yum install -y ./$package
+      rm -f $package
+    }
+
+    release=$(awk -F \: '{print $5}' /etc/system-release-cpe)
+
+    rpm --import http://download-ib01.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-${release}
+    rpm --import http://yum.puppetlabs.com/RPM-GPG-KEY-puppet
+    rpm --import http://vault.centos.org/RPM-GPG-KEY-CentOS-${release}
+
+    yum install -y wget
+
+    rpm_install http://yum.puppetlabs.com/puppet5/puppet5-release-el-${release}.noarch.rpm
+    yum -y install puppet-agent
+  ;;
+
+  'debian')
+    function deb_install() {
+      package=$(echo $1 | awk -F "/" '{print $NF}')
+      wget --quiet $1
+      dpkg -i ./$package
+      rm -f $package
+    }
+
+    export DEBIAN_FRONTEND=noninteractive
+
+    if [ -f /etc/lsb-release ]; then
+      # ubuntu
+      . /etc/lsb-release
+      CODENAME=$DISTRIB_CODENAME
+    else
+      # debian
+      CODENAME=$(grep ^VERSION= /etc/os-release | awk -F \( '{print $2}' | awk -F \) '{print $1}')
+      apt-get -y install apt-transport-https
+      apt-get update
+    fi
+
+    # Debian 9 (stretch) complains about the dirmngr package missing.
+    if [ "${CODENAME}" == 'stretch' ]; then
+      apt-get -y install dirmngr
+    fi
+
+    apt-key adv --fetch-keys http://apt.puppetlabs.com/DEB-GPG-KEY-puppet
+    apt-get -y install wget
+
+    deb_install http://apt.puppetlabs.com/puppet5-release-${CODENAME}.deb
+    apt-get update
+    apt-get -y install puppet-agent
+  ;;
+
+  *)
+    echo "argument is <${1}> and must be either 'debian' or 'el'."
+    exit 1
+  ;;
+esac
+
+# ensure puppet is in the path by symlinking to /usr/bin
+ln -s /opt/puppetlabs/puppet/bin/puppet /usr/bin/puppet
+
+# use local ssh module
+puppet resource file /etc/puppetlabs/code/environments/production/modules/ssh ensure=link target=/vagrant
+
+# setup module dependencies
+puppet module install puppetlabs/stdlib --version 5.2.0
+
diff --git a/tests/vagrant_test_all.sh b/tests/vagrant_test_all.sh
new file mode 100755
index 0000000..ba96d21
--- /dev/null
+++ b/tests/vagrant_test_all.sh
@@ -0,0 +1,16 @@
+#!/bin/bash -e
+
+systems=$(vagrant status |grep virtualbox | awk '{print $1}')
+echo -e "\nsystems to test:"
+echo -e "================"
+echo -e "\n${systems}"
+
+for i in $systems
+do
+  echo -e "\n\n\n========= Running: vagrant up ${i}"
+  vagrant up $i
+  echo -e "\n\n\n========= Testing ssh to ${i}"
+  vagrant ssh $i -c "exit"
+  echo -e "\n\n\n========= Running: vagrant destroy -f ${i}"
+  vagrant destroy -f $i
+done
diff --git a/types/key/type.pp b/types/key/type.pp
new file mode 100644
index 0000000..d8f0277
--- /dev/null
+++ b/types/key/type.pp
@@ -0,0 +1,12 @@
+# From https://github.com/puppetlabs/puppetlabs-sshkeys_core/blob/master/lib/puppet/type/sshkey.rb v1.0.2
+type Ssh::Key::Type = Enum[
+  'ssh-dss',
+  'ssh-ed25519',
+  'ssh-rsa',
+  'ecdsa-sha2-nistp256',
+  'ecdsa-sha2-nistp384',
+  'ecdsa-sha2-nistp521',
+  'ed25519',
+  'rsa',
+  'dsa',
+]
diff --git a/types/log_level.pp b/types/log_level.pp
new file mode 100644
index 0000000..9513e50
--- /dev/null
+++ b/types/log_level.pp
@@ -0,0 +1,11 @@
+type Ssh::Log_level = Enum[
+  'QUIET',
+  'FATAL',
+  'ERROR',
+  'INFO',
+  'VERBOSE',
+  'DEBUG',
+  'DEBUG1',
+  'DEBUG2',
+  'DEBUG3',
+]
diff --git a/types/permit_root_login.pp b/types/permit_root_login.pp
new file mode 100644
index 0000000..921eaf6
--- /dev/null
+++ b/types/permit_root_login.pp
@@ -0,0 +1,8 @@
+# 'without-password' is a deprecated alias for 'prohibit-password'
+type Ssh::Permit_root_login = Enum[
+  'yes',
+  'prohibit-password',
+  'without-password',
+  'forced-commands-only',
+  'no',
+]
diff --git a/types/syslog_facility.pp b/types/syslog_facility.pp
new file mode 100644
index 0000000..1d5eca1
--- /dev/null
+++ b/types/syslog_facility.pp
@@ -0,0 +1,14 @@
+type Ssh::Syslog_facility = Enum[
+  'DAEMON',
+  'USER',
+  'AUTH',
+  'LOCAL0',
+  'LOCAL1',
+  'LOCAL2',
+  'LOCAL3',
+  'LOCAL4',
+  'LOCAL5',
+  'LOCAL6',
+  'LOCAL7',
+  'AUTHPRIV', # this is not documented, but it is what EL 7 uses
+]
diff --git a/types/yes_no.pp b/types/yes_no.pp
new file mode 100644
index 0000000..0d9789f
--- /dev/null
+++ b/types/yes_no.pp
@@ -0,0 +1 @@
+type Ssh::Yes_no = Enum['yes', 'no']