aboutsummaryrefslogtreecommitdiff
path: root/manifests/rule.pp
diff options
context:
space:
mode:
authorThore Bödecker <me@foxxx0.de>2019-09-03 11:56:58 +0200
committerThore Bödecker <me@foxxx0.de>2019-09-11 13:20:35 +0200
commit882a45498ddefdfc83ff5b19da723fd0be3acdec (patch)
tree523f7a96c5b2640dbf2dd45cd89d931e12ceff9d /manifests/rule.pp
parent81748ba786c6a55c4575a400c08de99716da8fbb (diff)
downloadpuppet-ferm-882a45498ddefdfc83ff5b19da723fd0be3acdec.tar.gz
puppet-ferm-882a45498ddefdfc83ff5b19da723fd0be3acdec.tar.bz2
add ability to define rules in tables != filter
Previously it was neither possible to properly define custom chains nor to define rules in tables other than the default filter table. For various legitimate reasons it can be required to define rules in the raw, nat or mangle tables, e.g. to use NOTRACK or to configure DNAT/SNAT/MASQUERADE. Additionally it might come in handy to define custom chains to group certain rules and allow a more efficient evaluation for incoming packets by not cramming all rules into the filter/INPUT chain so that (worst-case) all packets need to traverse and evaluate all rules. I have tried to maintain backwards compatibility and to not change default filenames/paths so that it won't result in leftover obsolete unmaged files from previous versions of this module. In order to improve the naming schema the rule $policy has been renamed to $action, however both parameters are available and optional now, with some sanity checks that require at most one of them and issueing a warning() for users of the now deprecated $policy parameter. All previous tests have been adapted to the changes, a long with an additional set of tests for the new feature. Fixes #61
Diffstat (limited to 'manifests/rule.pp')
-rw-r--r--manifests/rule.pp76
1 files changed, 68 insertions, 8 deletions
diff --git a/manifests/rule.pp b/manifests/rule.pp
index 68e88a2..4f2c985 100644
--- a/manifests/rule.pp
+++ b/manifests/rule.pp
@@ -1,8 +1,31 @@
-# defined resource which creates a single rule in a specific chain
+# @summary This defined resource manages a single rule in a specific chain
+#
+# @example Jump to the 'SSH' chain for all incoming SSH traffic (see chain.pp examples on how to create the chain)
+# ferm::rule{'incoming-ssh':
+# chain => 'INPUT',
+# action => 'SSH',
+# proto => 'tcp',
+# dport => '22',
+# }
+#
+# @example Create a rule in the 'SSH' chain to allow connections from localhost
+# ferm::rule{'allow-ssh-localhost':
+# chain => 'SSH',
+# action => 'ACCEPT',
+# proto => 'tcp',
+# dport => '22',
+# saddr => '127.0.0.1',
+# }
+#
# @param chain Configure the chain where we want to add the rule
-# @param policy Configure what we want to do with the packet (drop, accept, log...)
# @param proto Which protocol do we want to match, typically UDP or TCP
# @param comment A comment that will be added to the ferm config and to ip{,6}tables
+# @param action Configure what we want to do with the packet (drop/accept/reject, can also be a target chain name)
+# Default value: undef
+# Allowed values: (RETURN|ACCEPT|DROP|REJECT|NOTRACK|LOG|MARK|DNAT|SNAT|MASQUERADE|REDIRECT|String[1])
+# @param policy Configure what we want to do with the packet (drop/accept/reject, can also be a target chain name) [DEPRECATED]
+# Default value: undef
+# Allowed values: (RETURN|ACCEPT|DROP|REJECT|NOTRACK|LOG|MARK|DNAT|SNAT|MASQUERADE|REDIRECT|String[1])
# @param dport The destination port, can be a range as string or a single port number as integer
# @param sport The source port, can be a range as string or a single port number as integer
# @param saddr The source address we want to match
@@ -10,11 +33,15 @@
# @param proto_options Optional parameters that will be passed to the protocol (for example to match specific ICMP types)
# @param interface an Optional interface where this rule should be applied
# @param ensure Set the rule to present or absent
+# @param table Select the target table (filter/raw/mangle/nat)
+# Default value: filter
+# Allowed values: (filter|raw|mangle|nat) (see Ferm::Tables type)
define ferm::rule (
String[1] $chain,
- Ferm::Policies $policy,
Ferm::Protocols $proto,
String $comment = $name,
+ Optional[Ferm::Actions] $action = undef,
+ Optional[Ferm::Policies] $policy = undef,
Optional[Variant[Stdlib::Port,String[1]]] $dport = undef,
Optional[Variant[Stdlib::Port,String[1]]] $sport = undef,
Optional[Variant[Array, String[1]]] $saddr = undef,
@@ -22,7 +49,31 @@ define ferm::rule (
Optional[String[1]] $proto_options = undef,
Optional[String[1]] $interface = undef,
Enum['absent','present'] $ensure = 'present',
+ Ferm::Tables $table = 'filter',
){
+
+ if $policy and $action {
+ fail('Cannot specify both policy and action. Do not provide policy when using the new action param.')
+ } elsif $policy and ! $action {
+ warning('The param "policy" is deprecated (superseded by "action") and will be dropped in a future release.')
+ $action_temp = $policy
+ } elsif $action and ! $policy {
+ $action_temp = $action
+ } else {
+ fail('Exactly one of "action" or the deprecated "policy" param is required.')
+ }
+
+ if $action_temp in ['RETURN', 'ACCEPT', 'DROP', 'REJECT', 'NOTRACK', 'LOG',
+ 'MARK', 'DNAT', 'SNAT', 'MASQUERADE', 'REDIRECT'] {
+ $action_real = $action_temp
+ } else {
+ # assume the action contains a target chain, so prefix it with the "jump" statement
+ $action_real = "jump ${action_temp}"
+ # make sure the target chain is created before we try to add rules to it
+ Ferm::Chain <| chain == $action_temp and table == $table |> -> Ferm::Rule[$name]
+ }
+
+
$proto_real = "proto ${proto}"
$dport_real = $dport ? {
@@ -63,33 +114,42 @@ define ferm::rule (
}
$comment_real = "mod comment comment '${comment}'"
- $rule = squeeze("${comment_real} ${proto_real} ${proto_options_real} ${dport_real} ${sport_real} ${daddr_real} ${saddr_real} ${policy};", ' ')
+ # prevent unmanaged files due to new naming schema
+ # keep the default "filter" chains in the original location
+ # only prefix chains in other tables with the table name
+ if $table == 'filter' and $chain in ['INPUT', 'FORWARD', 'OUTPUT'] {
+ $filename = "${ferm::configdirectory}/chains/${chain}.conf"
+ } else {
+ $filename = "${ferm::configdirectory}/chains/${table}-${chain}.conf"
+ }
+
+ $rule = squeeze("${comment_real} ${proto_real} ${proto_options_real} ${dport_real} ${sport_real} ${daddr_real} ${saddr_real} ${action_real};", ' ')
if $ensure == 'present' {
if $interface {
unless defined(Concat::Fragment["${chain}-${interface}-aaa"]) {
concat::fragment{"${chain}-${interface}-aaa":
- target => "${ferm::configdirectory}/chains/${chain}.conf",
+ target => $filename,
content => "interface ${interface} {\n",
order => $interface,
}
}
concat::fragment{"${chain}-${interface}-${name}":
- target => "${ferm::configdirectory}/chains/${chain}.conf",
+ target => $filename,
content => " ${rule}\n",
order => $interface,
}
unless defined(Concat::Fragment["${chain}-${interface}-zzz"]) {
concat::fragment{"${chain}-${interface}-zzz":
- target => "${ferm::configdirectory}/chains/${chain}.conf",
+ target => $filename,
content => "}\n",
order => $interface,
}
}
} else {
concat::fragment{"${chain}-${name}":
- target => "${ferm::configdirectory}/chains/${chain}.conf",
+ target => $filename,
content => "${rule}\n",
}
}