aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Meusel <tim@bastelfreak.de>2019-09-30 14:51:12 +0200
committerTim Meusel <tim@bastelfreak.de>2019-10-01 16:27:42 +0200
commitd4b8909eab6194da389b121e46137da7618eb45c (patch)
tree8cfc5af5a35a1557af027d68eccbd9def263dbde
parent5d00a506f896fccb2485ebf3ea316f0156b80f8b (diff)
downloadpuppet-ferm-d4b8909eab6194da389b121e46137da7618eb45c.tar.gz
puppet-ferm-d4b8909eab6194da389b121e46137da7618eb45c.tar.bz2
implement ipset support
-rw-r--r--README.md18
-rw-r--r--REFERENCE.md76
-rw-r--r--manifests/chain.pp6
-rw-r--r--manifests/ipset.pp62
-rw-r--r--spec/defines/ipset_spec.rb29
-rw-r--r--templates/ferm-chain-ipset.epp13
6 files changed, 201 insertions, 3 deletions
diff --git a/README.md b/README.md
index 93edb62..01217bd 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,8 @@ You can collect them like this:
Ferm::Rule <<| tag == 'allow_kafka_server2server' |>>
```
-You can also define rules in Hiera. Make sure to use `alias()` as interpolation function, because `hiera()` will always return a string.
+You can also define rules in Hiera. Make sure to use `alias()` as interpolation
+function, because `hiera()` will always return a string.
```yaml
---
@@ -94,6 +95,20 @@ defined hashes and hand them over to the class. The main class will create
rules for all of them. It also collects all exported resources that are tagged
with the FQDN of a box.
+It's also possible to match against [ipsets](http://ipset.netfilter.org/). This
+allows to easily match against a huge amount of IP addresses or network ranges.
+You can use this as follows:
+
+```puppet
+ferm::ipset { 'INPUT':
+ sets => {
+ 'office' => 'ACCPET',
+ 'internet' => 'DROP',
+ }
+}
+```
+
+please see the [references](#reference) section for more examples.
## Examples
@@ -131,7 +146,6 @@ The second rule will disable connection tracking for all other traffic coming in
This will prevent your conntrack table from overflowing, tracking only the relevant connections and allowing you to use a stateful ruleset.
-
## Reference
All parameters are documented within the classes. We generate markdown
diff --git a/REFERENCE.md b/REFERENCE.md
index 019c5a4..7e7d518 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -18,6 +18,7 @@ _Private Classes_
**Defined types**
* [`ferm::chain`](#fermchain): This defined resource manages ferm/iptables chains
+* [`ferm::ipset`](#fermipset): a defined resource that can match for ipsets at the top of a chain. This is a per-chain resource. You cannot mix IPv4 and IPv6 sets.
* [`ferm::rule`](#fermrule): This defined resource manages a single rule in a specific chain
**Data types**
@@ -273,6 +274,81 @@ Default value: $ferm::ip_versions
Default value: $ferm::ip_versions
+### ferm::ipset
+
+a defined resource that can match for ipsets at the top of a chain. This is a per-chain resource. You cannot mix IPv4 and IPv6 sets.
+
+* **See also**
+http://ferm.foo-projects.org/download/2.1/ferm.html#set
+
+#### Examples
+
+#####
+
+```puppet
+ferm::ipset { 'CONSUL':
+ sets => {
+ 'internet' => 'ACCEPT'
+ },
+}
+```
+
+##### create to matches for IPv6, both at the end of the `INPUT` chain. Explicitly mention the `filter` table.
+
+```puppet
+ferm::ipset { 'INPUT':
+ prepend_to_chain => false,
+ table => 'filter',
+ ip_version => 'ip6',
+ sets => {
+ 'testset01' => 'ACCEPT',
+ 'anothertestset' => 'DROP'
+ },
+}
+```
+
+#### Parameters
+
+The following parameters are available in the `ferm::ipset` defined type.
+
+##### `chain`
+
+Data type: `String[1]`
+
+name of the chain we want to apply those rules to. The name of the defined resource will be used as default value for this.
+
+Default value: $name
+
+##### `table`
+
+Data type: `Ferm::Tables`
+
+name of the table where we want to apply this. Defaults to `filter` because that's the most common usecase.
+
+Default value: 'filter'
+
+##### `ip_version`
+
+Data type: `Enum['ip','ip6']`
+
+sadly, ip sets are version specific. You cannot mix IPv4 and IPv6 addresses. Because of this you need to provide the version.
+
+Default value: 'ip'
+
+##### `sets`
+
+Data type: `Hash[String[1], Ferm::Actions]`
+
+A hash with multiple sets. For each hash you can provide an action like `DROP` or `ACCEPT`.
+
+##### `prepend_to_chain`
+
+Data type: `Boolean`
+
+
+
+Default value: `true`
+
### ferm::rule
This defined resource manages a single rule in a specific chain
diff --git a/manifests/chain.pp b/manifests/chain.pp
index 10cc9c1..1be7e83 100644
--- a/manifests/chain.pp
+++ b/manifests/chain.pp
@@ -73,6 +73,10 @@ define ferm::chain (
}
# make sure the generated snippet is actually included
+ # the ordering here is hacked. We might end up with multiple blocks for the same filter+chain.
+ # This happens if we add ipset matches. We suffix this ordering with `bbb`. This allows us to
+ # insert ipset matches before other rules by adding `-aaa` or
+ # insert them at the end by ordering them with `-ccc`.
concat::fragment{"${table}-${chain}-config-include":
target => $ferm::configfile,
content => epp(
@@ -83,7 +87,7 @@ define ferm::chain (
'filename' => $filename,
}
),
- order => "${table}-${chain}",
+ order => "${table}-${chain}-bbb",
require => Concat[$filename],
}
}
diff --git a/manifests/ipset.pp b/manifests/ipset.pp
new file mode 100644
index 0000000..fab7894
--- /dev/null
+++ b/manifests/ipset.pp
@@ -0,0 +1,62 @@
+#
+# @summary a defined resource that can match for ipsets at the top of a chain. This is a per-chain resource. You cannot mix IPv4 and IPv6 sets.
+#
+# @see http://ferm.foo-projects.org/download/2.1/ferm.html#set
+#
+# @example
+# ferm::ipset { 'CONSUL':
+# sets => {
+# 'internet' => 'ACCEPT'
+# },
+# }
+#
+# @example create to matches for IPv6, both at the end of the `INPUT` chain. Explicitly mention the `filter` table.
+# ferm::ipset { 'INPUT':
+# prepend_to_chain => false,
+# table => 'filter',
+# ip_version => 'ip6',
+# sets => {
+# 'testset01' => 'ACCEPT',
+# 'anothertestset' => 'DROP'
+# },
+# }
+#
+# @param chain
+# name of the chain we want to apply those rules to. The name of the defined resource will be used as default value for this.
+#
+# @param table
+# name of the table where we want to apply this. Defaults to `filter` because that's the most common usecase.
+#
+# @param ip_version
+# sadly, ip sets are version specific. You cannot mix IPv4 and IPv6 addresses. Because of this you need to provide the version.
+#
+# @param sets
+# A hash with multiple sets. For each hash you can provide an action like `DROP` or `ACCEPT`.
+#
+define ferm::ipset (
+ Hash[String[1], Ferm::Actions] $sets,
+ String[1] $chain = $name,
+ Ferm::Tables $table = 'filter',
+ Enum['ip','ip6'] $ip_version = 'ip',
+ Boolean $prepend_to_chain = true,
+) {
+
+ $suffix = $prepend_to_chain ? {
+ true => 'aaa',
+ false => 'ccc',
+ }
+
+ # make sure the generated snippet is actually included
+ concat::fragment{"${table}-${chain}-ipset":
+ target => $ferm::configfile,
+ content => epp(
+ "${module_name}/ferm-chain-ipset.epp", {
+ 'ip' => $ip_version,
+ 'table' => $table,
+ 'chain' => $chain,
+ 'sets' => $sets,
+ }
+ ),
+ order => "${table}-${chain}-${suffix}",
+ }
+}
diff --git a/spec/defines/ipset_spec.rb b/spec/defines/ipset_spec.rb
new file mode 100644
index 0000000..050e5ef
--- /dev/null
+++ b/spec/defines/ipset_spec.rb
@@ -0,0 +1,29 @@
+require 'spec_helper'
+
+describe 'ferm::ipset', type: :define do
+ on_supported_os.each do |os, facts|
+ context "on #{os} " do
+ let :facts do
+ facts
+ end
+ let(:title) { 'INPUT' }
+
+ let :pre_condition do
+ 'include ferm'
+ end
+
+ context 'default params creates INPUT2 chain' do
+ let :params do
+ {
+ sets: {
+ office: 'ACCEPT',
+ internet: 'DROP'
+ }
+ }
+ end
+
+ it { is_expected.to compile.with_all_deps }
+ end
+ end
+ end
+end
diff --git a/templates/ferm-chain-ipset.epp b/templates/ferm-chain-ipset.epp
new file mode 100644
index 0000000..79aeb5c
--- /dev/null
+++ b/templates/ferm-chain-ipset.epp
@@ -0,0 +1,13 @@
+<%- | String[1] $ip,
+Ferm::Tables $table,
+String[1] $chain,
+Hash[String[1], Ferm::Actions] $sets,
+| -%>
+
+domain (<%= $ip %>) table <%= $table %> {
+ chain <%= $chain %> {
+ <%- $sets.each |$ipset, $action| { -%>
+ mod set set <%= $ipset %> src <%= $action %>;
+ <%- } -%>
+ }
+}