WIP - Add support for FreeBSD 10, 11 and 12
diff --git a/README.md b/README.md
index 816b5db..9576798 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,9 @@
  * EL 5
  * EL 6
  * EL 7
+ * FreeBSD 10
+ * FreeBSD 11
+ * FreeBSD 12
  * SLES 10
  * SLES 11
  * SLES 12
@@ -80,7 +83,7 @@
 ----------------
 ssh_config's group.
 
-- *Default*: 'root'
+- *Default*: 'USE_DEFAULTS'
 
 ssh_config_mode
 ---------------
@@ -194,7 +197,7 @@
 ----------------
 sshd_config's group.
 
-- *Default*: 'root'
+- *Default*: 'USE_DEFAULTS'
 
 sshd_config_loglevel
 ---------------------------
@@ -672,7 +675,7 @@
 ----------------------------------
 Group of the global known_hosts file
 
-- *Default*: 'root'
+- *Default*: 'USE_DEFAULTS'
 
 ssh_config_global_known_hosts_mode
 ----------------------------------
diff --git a/manifests/init.pp b/manifests/init.pp
index ee99870..e3697c8 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -13,7 +13,7 @@
   $ssh_config_hash_known_hosts         = 'USE_DEFAULTS',
   $ssh_config_path                     = '/etc/ssh/ssh_config',
   $ssh_config_owner                    = 'root',
-  $ssh_config_group                    = 'root',
+  $ssh_config_group                    = 'USE_DEFAULTS',
   $ssh_config_mode                     = '0644',
   $ssh_config_forward_x11              = undef,
   $ssh_config_forward_x11_trusted      = 'USE_DEFAULTS',
@@ -31,7 +31,7 @@
   $ssh_gssapidelegatecredentials       = undef,
   $sshd_config_path                    = '/etc/ssh/sshd_config',
   $sshd_config_owner                   = 'root',
-  $sshd_config_group                   = 'root',
+  $sshd_config_group                   = 'USE_DEFAULTS',
   $sshd_config_loglevel                = 'INFO',
   $sshd_config_mode                    = 'USE_DEFAULTS',
   $sshd_config_permitemptypasswords    = undef,
@@ -99,7 +99,7 @@
   $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_group = 'USE_DEFAULTS',
   $ssh_config_global_known_hosts_mode  = '0644',
   $ssh_config_user_known_hosts_file    = undef,
   $keys                                = undef,
@@ -107,7 +107,39 @@
   $root_ssh_config_content             = "# This file is being maintained by Puppet.\n# DO NOT EDIT\n",
 ) {
 
+  if $::osfamily == 'FreeBSD' {
+    $default_ssh_config_group = 'wheel'
+    $default_sshd_config_group = 'wheel'
+    $default_ssh_config_global_known_hosts_group = 'wheel'
+  } else {
+    $default_ssh_config_group = 'root'
+    $default_sshd_config_group = 'root'
+    $default_ssh_config_global_known_hosts_group = 'root'
+  }
+
   case $::osfamily {
+    'FreeBSD': {
+      $default_packages                        = undef
+      $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
+      $default_sshd_config_serverkeybits       = '1024'
+      $default_sshd_config_hostkey             = [ '/etc/ssh/ssh_host_rsa_key' ]
+      $default_sshd_addressfamily              = 'any'
+    }
     'RedHat': {
       $default_packages                        = ['openssh-server',
                                                   'openssh-clients']
@@ -242,7 +274,7 @@
       }
     }
     default: {
-      fail("ssh supports osfamilies RedHat, Suse, Debian and Solaris. Detected osfamily is <${::osfamily}>.")
+      fail("ssh supports osfamilies Debian, FreeBSD, RedHat, Solaris and Suse. Detected osfamily is <${::osfamily}>.")
     }
   }
 
@@ -267,6 +299,27 @@
     $packages_real = $packages
   }
 
+  if $ssh_config_group == 'USE_DEFAULTS' {
+    $ssh_config_group_real = $default_ssh_config_group
+  } else {
+    $ssh_config_group_real = $ssh_config_group
+  }
+  validate_string($ssh_config_group_real)
+
+  if $sshd_config_group == 'USE_DEFAULTS' {
+    $sshd_config_group_real = $default_sshd_config_group
+  } else {
+    $sshd_config_group_real = $sshd_config_group
+  }
+  validate_string($sshd_config_group_real)
+
+  if $ssh_config_global_known_hosts_group == 'USE_DEFAULTS' {
+    $ssh_config_global_known_hosts_group_real = $default_ssh_config_global_known_hosts_group
+  } else {
+    $ssh_config_global_known_hosts_group_real = $ssh_config_global_known_hosts_group
+  }
+  validate_string($ssh_config_global_known_hosts_group_real)
+
   if $ssh_config_hash_known_hosts == 'USE_DEFAULTS' {
     $ssh_config_hash_known_hosts_real = $default_ssh_config_hash_known_hosts
   } else {
@@ -672,7 +725,6 @@
   }
 
   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}>.")
 
@@ -750,20 +802,25 @@
     validate_array($sshd_config_allowgroups_real)
   }
 
-  package { $packages_real:
-    ensure    => installed,
-    source    => $ssh_package_source_real,
-    adminfile => $ssh_package_adminfile_real,
+  if $packages_real != undef {
+    package { $packages_real:
+      ensure    => installed,
+      source    => $ssh_package_source_real,
+      adminfile => $ssh_package_adminfile_real,
+      before    => [
+        File['ssh_config'],
+        File['sshd_config'],
+      ],
+    }
   }
 
   file  { 'ssh_config' :
     ensure  => file,
     path    => $ssh_config_path,
     owner   => $ssh_config_owner,
-    group   => $ssh_config_group,
+    group   => $ssh_config_group_real,
     mode    => $ssh_config_mode,
     content => template($ssh_config_template),
-    require => Package[$packages_real],
   }
 
   file  { 'sshd_config' :
@@ -771,20 +828,31 @@
     path    => $sshd_config_path,
     mode    => $sshd_config_mode_real,
     owner   => $sshd_config_owner,
-    group   => $sshd_config_group,
+    group   => $sshd_config_group_real,
     content => template($sshd_config_template),
-    require => Package[$packages_real],
   }
 
   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],
+    if $packages_real == 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 => undef,
+      }
+    } else {
+      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],
+      }
     }
   }
 
@@ -844,7 +912,7 @@
     ensure => file,
     path   => $ssh_config_global_known_hosts_file,
     owner  => $ssh_config_global_known_hosts_owner,
-    group  => $ssh_config_global_known_hosts_group,
+    group  => $ssh_config_global_known_hosts_group_real,
     mode   => $ssh_config_global_known_hosts_mode,
   }
 
diff --git a/metadata.json b/metadata.json
index a232ebb..9a7c1a9 100644
--- a/metadata.json
+++ b/metadata.json
@@ -25,6 +25,14 @@
       ]
     },
     {
+      "operatingsystem": "FreeBSD",
+      "operatingsystemrelease": [
+        "10",
+        "11",
+        "12"
+      ]
+    },
+    {
       "operatingsystem": "RedHat",
       "operatingsystemrelease": [
         "5",
diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb
index 457f29e..fe7123e 100644
--- a/spec/classes/init_spec.rb
+++ b/spec/classes/init_spec.rb
@@ -36,6 +36,45 @@
       :sshd_config_fixture    => 'sshd_config_debian',
       :ssh_config_fixture     => 'ssh_config_debian',
     },
+    'FreeBSD-10' => {
+      :architecture           => 'amd64',
+      :osfamily               => 'FreeBSD',
+      :operatingsystemrelease => '10',
+      :ssh_version            => 'OpenSSH_7.2p2',
+      :ssh_version_numeric    => '7.2',
+      :ssh_packages           => nil,
+      :sshd_config_mode       => '0600',
+      :sshd_service_name      => 'sshd',
+      :sshd_service_hasstatus => true,
+      :sshd_config_fixture    => nil,
+      :ssh_config_fixture     => nil,
+    },
+    'FreeBSD-11' => {
+      :architecture           => 'amd64',
+      :osfamily               => 'FreeBSD',
+      :operatingsystemrelease => '11',
+      :ssh_version            => 'OpenSSH_7.2p2',
+      :ssh_version_numeric    => '7.2',
+      :ssh_packages           => nil,
+      :sshd_config_mode       => '0600',
+      :sshd_service_name      => 'sshd',
+      :sshd_service_hasstatus => true,
+      :sshd_config_fixture    => nil,
+      :ssh_config_fixture     => nil,
+    },
+    'FreeBSD-12' => {
+      :architecture           => 'amd64',
+      :osfamily               => 'FreeBSD',
+      :operatingsystemrelease => '12',
+      :ssh_version            => 'OpenSSH_7.2p2',
+      :ssh_version_numeric    => '7.2',
+      :ssh_packages           => nil,
+      :sshd_config_mode       => '0600',
+      :sshd_service_name      => 'sshd',
+      :sshd_service_hasstatus => true,
+      :sshd_config_fixture    => nil,
+      :ssh_config_fixture     => nil,
+    },
     'RedHat-5' => {
       :architecture           => 'x86_64',
       :osfamily               => 'RedHat',
@@ -199,18 +238,32 @@
         )
       end
 
+      if facts[:osfamily] == 'FreeBSD'
+        group = 'wheel'
+      else
+        group = 'root'
+      end
+
       it { should compile.with_all_deps }
 
       it { should contain_class('ssh')}
 
       it { should_not contain_class('common')}
 
-      facts[:ssh_packages].each do |pkg|
-        it {
-          should contain_package(pkg).with({
-            'ensure' => 'installed',
-          })
-        }
+      if facts[:ssh_packages] == nil
+        it { is_expected.to have_package_resource_count(0) }
+      else
+        facts[:ssh_packages].each do |pkg|
+          it {
+            should contain_package(pkg).with({
+              'ensure' => 'installed',
+              'before' => [
+                'File[ssh_config]',
+                'File[sshd_config]',
+              ],
+            })
+          }
+        end
       end
 
       it {
@@ -218,7 +271,7 @@
           'ensure' => 'file',
           'path'   => '/etc/ssh/ssh_known_hosts',
           'owner'  => 'root',
-          'group'  => 'root',
+          'group'  => group,
           'mode'   => '0644',
         })
       }
@@ -228,18 +281,14 @@
           'ensure'  => 'file',
           'path'    => '/etc/ssh/ssh_config',
           'owner'   => 'root',
-          'group'   => 'root',
+          'group'   => group,
           '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}]")
-        }
+      if facts[:ssh_config_fixture] != nil
+        ssh_config_fixture = File.read(fixtures(facts[:ssh_config_fixture]))
+        it { should contain_file('ssh_config').with_content(ssh_config_fixture) }
       end
 
       it {
@@ -247,20 +296,16 @@
           'ensure'  => 'file',
           'path'    => '/etc/ssh/sshd_config',
           'owner'   => 'root',
-          'group'   => 'root',
+          'group'   => group,
           'mode'    => facts[:sshd_config_mode],
         })
       }
 
-      facts[:ssh_packages].each do |pkg|
-        it {
-          should contain_file('sshd_config').that_requires("Package[#{pkg}]")
-        }
+      if facts[:sshd_config_fixture] != nil
+        sshd_config_fixture = File.read(fixtures(facts[:sshd_config_fixture]))
+        it { should contain_file('sshd_config').with_content(sshd_config_fixture) }
       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',
@@ -296,7 +341,7 @@
     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>\./)
+      }.to raise_error(Puppet::Error,/ssh supports osfamilies Debian, FreeBSD, RedHat, Solaris and Suse\. Detected osfamily is <C64>\./)
     end
   end
 
@@ -348,7 +393,6 @@
         'owner'   => 'root',
         'group'   => 'root',
         'mode'    => '0644',
-        'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
       })
     }
 
@@ -450,7 +494,6 @@
         'owner'   => 'root',
         'group'   => 'root',
         'mode'    => '0600',
-        'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
       })
     }