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
---
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
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
**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**
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
}
# 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(
'filename' => $filename,
}
),
- order => "${table}-${chain}",
+ order => "${table}-${chain}-bbb",
require => Concat[$filename],
}
}
--- /dev/null
+#
+# @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}",
+ }
+}
--- /dev/null
+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
--- /dev/null
+<%- | 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 %>;
+ <%- } -%>
+ }
+}