]> gitweb.fluxo.info Git - puppet-ferm.git/commitdiff
add install_method parameter
authorFabien COMBERNOUS <fabien.combernous@adullact.org>
Sat, 2 May 2020 09:32:08 +0000 (11:32 +0200)
committerFabien COMBERNOUS <fabien.combernous@adullact.org>
Mon, 18 May 2020 20:06:35 +0000 (22:06 +0200)
README.md
REFERENCE.md
manifests/config.pp
manifests/init.pp
manifests/install.pp
manifests/service.pp
metadata.json
spec/acceptance/ferm_spec.rb
templates/dropin_ferm.conf.epp [new file with mode: 0644]

index 01217bd49756477e7ad1e24ea8d7e21f5503607c..64a9f8481570b06ab322a6b5153f903c59f53ad7 100644 (file)
--- a/README.md
+++ b/README.md
@@ -44,6 +44,17 @@ This will install the package, but nothing more. It won't explicitly enable it
 or write any rules. Be careful here: The default Debian package enabled
 autostart for the service and only allows incoming SSH/IPSec connections.
 
+It is also possible to install ferm from sources:
+```puppet
+class {'ferm':
+  install_method = 'vcsrepo',
+}
+```
+
+When `install_method` is `vcsrepo`, the `git` binary is required, this module should handle Git installation.
+
+When `install_method` is `vcsrepo` with `vcstag` >= `v2.5` ferm call "legacy" xtables tools because nft based tools are incompatible.
+
 You can easily define rules in Puppet (they don't need to be exported resources):
 
 ```puppet
index 5c85d3871a887ae503da35fc9930846f24f78be7..eef0dc5133e405cf5776746cba9825c97e1f1778 100644 (file)
@@ -220,11 +220,35 @@ Default value: ['ip','ip6']
 
 Data type: `Hash[String[1],Array[String[1]]]`
 
-Hash with table:chains[] to use ferm @preserve for
+Hash with table:chains[] to use ferm @preserve for (since ferm v2.4)
 Example: {'nat' => ['PREROUTING', 'POSTROUTING']}
 
 Default value: {}
 
+##### `install_method`
+
+Data type: `Enum['package','vcsrepo']`
+
+method used to install ferm
+
+Default value: 'package'
+
+##### `vcsrepo`
+
+Data type: `Stdlib::HTTPSUrl`
+
+git repository where ferm sources are hosted
+
+Default value: 'https://github.com/MaxKellermann/ferm.git'
+
+##### `vcstag`
+
+Data type: `String[1]`
+
+git tag used when install_method is vcsrepo
+
+Default value: 'v2.5.1'
+
 ## Defined types
 
 ### ferm::chain
index 5876bd71ee0d5bcc2f9e171052dbba85451e4853..8ed0f57bb33b7956054d77b552fad8a6b593ec9a 100644 (file)
@@ -10,6 +10,16 @@ class ferm::config {
 
   $_ip = join($ferm::ip_versions, ' ')
 
+  if $facts['systemd'] { #fact provided by systemd module
+    if $ferm::install_method == 'vcsrepo' and $ferm::manage_service {
+      systemd::dropin_file { 'ferm.conf':
+        unit    => 'ferm.service',
+        content => epp("${module_name}/dropin_ferm.conf.epp"),
+        before  => Service['ferm'],
+      }
+    }
+  }
+
   # copy static files to ferm
   # on a long term point of view, we want to package this
   file{$ferm::configdirectory:
index b1d051e8a7d34efc73e96cfc6209b55bcf3f9d7c..251effefd833cc283802dda19678c6aeaa9888fb 100644 (file)
 # @param output_log_dropped_packets Enable/Disable logging in the OUTPUT chain of packets to the kernel log, if no explicit chain matched
 # @param input_log_dropped_packets Enable/Disable logging in the INPUT chain of packets to the kernel log, if no explicit chain matched
 # @param ip_versions Set list of versions of ip we want ot use.
-# @param preserve_chains_in_tables Hash with table:chains[] to use ferm @preserve for
+# @param preserve_chains_in_tables Hash with table:chains[] to use ferm @preserve for (since ferm v2.4)
 #   Example: {'nat' => ['PREROUTING', 'POSTROUTING']}
+# @param install_method method used to install ferm
+# @param vcsrepo git repository where ferm sources are hosted
+# @param vcstag git tag used when install_method is vcsrepo
 class ferm (
   Stdlib::Absolutepath $configfile,
   Stdlib::Absolutepath $configdirectory,
@@ -67,6 +70,9 @@ class ferm (
   Hash $chains = {},
   Array[Enum['ip','ip6']] $ip_versions = ['ip','ip6'],
   Hash[String[1],Array[String[1]]] $preserve_chains_in_tables = {},
+  Enum['package','vcsrepo'] $install_method = 'package',
+  Stdlib::HTTPSUrl $vcsrepo = 'https://github.com/MaxKellermann/ferm.git',
+  String[1] $vcstag = 'v2.5.1',
 ) {
   contain ferm::install
   contain ferm::config
index 4337a9947c32964e00a542aaae366690f346c880..5755ead10824046e13f3557c96b9e5e6d476fe2e 100644 (file)
@@ -8,8 +8,40 @@ class ferm::install {
   # this is a private class
   assert_private("You're not supposed to do that!")
 
-  package{'ferm':
-    ensure => 'latest',
+  case $ferm::install_method {
+    'package': {
+      package{'ferm':
+        ensure => 'latest',
+      }
+    }
+    'vcsrepo': {
+      $_source_path = '/opt/ferm'
+      ensure_packages (['git', 'iptables', 'perl', 'make'], { ensure => present })
+
+      package{'ferm':
+        ensure => absent,
+      }
+      -> vcsrepo { $_source_path :
+        ensure   => present,
+        provider => git,
+        source   => $ferm::vcsrepo,
+        revision => $ferm::vcstag,
+      }
+      -> exec { 'make install':
+        cwd     => $_source_path,
+        path    => '/usr/sbin:/usr/bin:/sbin:/bin',
+        creates => '/usr/sbin/ferm',
+      }
+      -> file { '/etc/ferm':
+        ensure => directory,
+        owner  => 0,
+        group  => 0,
+        mode   => '0700',
+      }
+    }
+    default: {
+      fail("unexpected install_method ${ferm::install_method}")
+    }
   }
 
   if $ferm::manage_initfile {
index e9eb3696cd36df588d5bf3f0d8cdb079608944a0..9fb1737842d8226f19033ce37ad14d93b2924da8 100644 (file)
@@ -15,7 +15,7 @@ class ferm::service {
     }
 
     # on Ubuntu, we can't start the service, unless we set ENABLED=true in /etc/default/ferm...
-    if ($facts['os']['name'] in ['Ubuntu', 'Debian']) {
+    if ($facts['os']['name'] in ['Ubuntu', 'Debian']) and ($ferm::install_method == 'package') {
       file_line{'enable_ferm':
         path   => '/etc/default/ferm',
         line   => 'ENABLED="yes"',
index ee832e8b95ed71bcc5486dec898edd601ea071f6..08032e33889202411ac4d50eeb1686fc56c37a08 100644 (file)
     {
       "name": "puppetlabs/stdlib",
       "version_requirement": ">= 4.25.0 < 7.0.0"
+    },
+    {
+      "name": "puppetlabs/vcsrepo",
+      "version_requirement": ">= 3.0.0 < 4.0.0"
+    },
+    {
+      "name": "camptocamp-systemd",
+      "version_requirement": ">= 2.9.0 < 3.0.0"
     }
   ],
   "operatingsystem_support": [
index 8c5c454760062eb273820fdd76763cd58e83dc9c..f8f0ef46568f5a70c44a8958744b7ec23835b2a1 100644 (file)
@@ -30,6 +30,15 @@ iptables_output = case sut_os
 iptables_output_custom = ['-A FORWARD -s 10.8.0.0/24 -p udp -m comment --comment "OpenVPN - FORWORD all udp traffic from network 10.8.0.0/24 to subchain OPENVPN_FORWORD_RULES" -j OPENVPN_FORWORD_RULES',
                           '-A OPENVPN_FORWORD_RULES -s 10.8.0.0/24 -i tun0 -o enp4s0 -p udp -m conntrack --ctstate NEW -j ACCEPT']
 
+# When `install_method` is `vcsrepo` with `vcstag` >= `v2.5` ferm call "legacy"
+# xtables tools because nft based tools are incompatible.
+iptables_save_cmd = case sut_os
+                    when 'Debian-10'
+                      'iptables-legacy-save'
+                    else
+                      'iptables-save'
+                    end
+
 basic_manifest = %(
   class { 'ferm':
     manage_service    => true,
@@ -47,12 +56,36 @@ basic_manifest = %(
       },
     },
     ip_versions      => ['ip'], #only ipv4 available with CI
-  }
 )
 
 describe 'ferm' do
-  context 'with basics settings' do
-    pp = basic_manifest
+  context 'with basics settings and vcsrepo install_method' do
+    pp = [basic_manifest, "install_method => 'vcsrepo',}"].join("\n")
+
+    it 'works with no error' do
+      apply_manifest(pp, catch_failures: true)
+    end
+    it 'works idempotently' do
+      apply_manifest(pp, catch_changes: true)
+    end
+
+    describe package('ferm') do
+      it { is_expected.not_to be_installed }
+    end
+
+    describe service('ferm') do
+      it { is_expected.to be_running }
+    end
+
+    describe command("#{iptables_save_cmd} -t filter") do
+      its(:stdout) { is_expected.to match %r{.*filter.*:INPUT DROP.*:FORWARD DROP.*:OUTPUT ACCEPT.*}m }
+      its(:stdout) { is_expected.not_to match %r{state INVALID -j DROP} }
+      its(:stdout) { is_expected.to match %r{allow_acceptance_tests.*-j ACCEPT}m }
+    end
+  end
+
+  context 'with basics settings and default install_method' do
+    pp = [basic_manifest, '}'].join("\n")
 
     it 'works with no error' do
       apply_manifest(pp, catch_failures: true)
@@ -105,7 +138,7 @@ describe 'ferm' do
           require           => Ferm::Chain['check-http'],
         }
       )
-      pp = [basic_manifest, advanced_manifest].join("\n")
+      pp = [basic_manifest, '}', advanced_manifest].join("\n")
 
       it 'works with no error' do
         apply_manifest(pp, catch_failures: true)
@@ -193,7 +226,8 @@ describe 'ferm' do
         proto     => 'udp',
       }
     )
-    pp = [basic_manifest, advanced_manifest].join("\n")
+
+    pp = [basic_manifest, '}', advanced_manifest].join("\n")
 
     it 'works with no error' do
       apply_manifest(pp, catch_failures: true)
diff --git a/templates/dropin_ferm.conf.epp b/templates/dropin_ferm.conf.epp
new file mode 100644 (file)
index 0000000..d5ed63b
--- /dev/null
@@ -0,0 +1,6 @@
+# THIS SNIPPET IS MANAGED BY PUPPET
+[Service]
+ExecStart=
+ExecStart=/usr/sbin/ferm <%= $ferm::configfile %>
+ExecStop=
+ExecStop=/usr/sbin/ferm -F <%= $ferm::configfile %>