diff options
Diffstat (limited to 'manifests')
-rw-r--r-- | manifests/chain.pp | 71 | ||||
-rw-r--r-- | manifests/config.pp | 29 | ||||
-rw-r--r-- | manifests/init.pp | 9 | ||||
-rw-r--r-- | manifests/rule.pp | 76 |
4 files changed, 163 insertions, 22 deletions
diff --git a/manifests/chain.pp b/manifests/chain.pp index 1198f62..a01b9b4 100644 --- a/manifests/chain.pp +++ b/manifests/chain.pp @@ -1,23 +1,57 @@ -# defined resource which creates all rules for one chain -# @param policy Set the default policy for a CHAIN +# @summary This defined resource manages ferm/iptables chains +# +# @example create a custom chain, e.g. for all incoming SSH connections +# ferm::chain{'check-ssh': +# chain => 'SSH', +# disable_conntrack => true, +# log_dropped_packets => true, +# } +# # @param disable_conntrack Disable/Enable usage of conntrack -# @param chain Name of the chain that should be managed # @param log_dropped_packets Enable/Disable logging of packets to the kernel log, if no explicit chain matched +# @param policy Set the default policy for CHAIN (works only for builtin chains) +# Default value: undef +# Allowed values: (ACCEPT|DROP) (see Ferm::Policies type) +# @param chain Name of the chain that should be managed +# Default value: $name (resource name) +# Allowed values: String[1] +# @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::chain ( - Ferm::Policies $policy, Boolean $disable_conntrack, Boolean $log_dropped_packets, - String[1] $chain = $name, + String[1] $chain = $name, + Optional[Ferm::Policies] $policy = undef, + Ferm::Tables $table = 'filter', ) { + # 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" + } + + $builtin_chains = { + 'raw' => ['PREROUTING', 'OUTPUT'], + 'nat' => ['PREROUTING', 'INPUT', 'OUTPUT', 'POSTROUTING'], + 'mangle' => ['PREROUTING', 'INPUT', 'FORWARD', 'OUTPUT', 'POSTROUTING'], + 'filter' => ['INPUT', 'FORWARD', 'OUTPUT'], + } + + if $policy and ! ($chain in $builtin_chains[$table]) { + fail("Can only set a default policy for builtin chains. '${chain}' is not a builtin chain.") + } # concat resource for the chain - $filename = downcase($chain) - concat{"${ferm::configdirectory}/chains/${chain}.conf": + concat{$filename: ensure => 'present', } - concat::fragment{"${chain}-policy": - target => "${ferm::configdirectory}/chains/${chain}.conf", + concat::fragment{"${table}-${chain}-policy": + target => $filename, content => epp( "${module_name}/ferm_chain_header.conf.epp", { 'policy' => $policy, @@ -28,10 +62,25 @@ define ferm::chain ( } if $log_dropped_packets { - concat::fragment{"${chain}-footer": - target => "${ferm::configdirectory}/chains/${chain}.conf", + concat::fragment{"${table}-${chain}-footer": + target => $filename, content => epp("${module_name}/ferm_chain_footer.conf.epp", { 'chain' => $chain }), order => 'zzzzzzzzzzzzzzzzzzzzz', } } + + # make sure the generated snippet is actually included + concat::fragment{"${table}-${chain}-config-include": + target => $ferm::configfile, + content => epp( + "${module_name}/ferm-table-chain-config-include.epp", { + 'ip' => join($ferm::ip_versions, ' '), + 'table' => $table, + 'chain' => $chain, + 'filename' => $filename, + } + ), + order => "${table}-${chain}", + require => Concat[$filename], + } } diff --git a/manifests/config.pp b/manifests/config.pp index 25607ad..efabe2b 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -57,4 +57,33 @@ class ferm::config { disable_conntrack => $ferm::disable_conntrack, log_dropped_packets => $ferm::output_log_dropped_packets, } + + # initialize default tables and chains + ['PREROUTING', 'OUTPUT'].each |$raw_chain| { + ferm::chain{"raw-${raw_chain}": + chain => $raw_chain, + policy => 'ACCEPT', + disable_conntrack => true, + log_dropped_packets => false, + table => 'raw', + } + } + ['PREROUTING', 'INPUT', 'OUTPUT', 'POSTROUTING'].each |$nat_chain| { + ferm::chain{"nat-${nat_chain}": + chain => $nat_chain, + policy => 'ACCEPT', + disable_conntrack => true, + log_dropped_packets => false, + table => 'nat', + } + } + ['PREROUTING', 'INPUT', 'FORWARD', 'OUTPUT', 'POSTROUTING'].each |$mangle_chain| { + ferm::chain{"mangle-${mangle_chain}": + chain => $mangle_chain, + policy => 'ACCEPT', + disable_conntrack => true, + log_dropped_packets => false, + table => 'mangle', + } + } } diff --git a/manifests/init.pp b/manifests/init.pp index 221e148..d2251c9 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -45,13 +45,13 @@ # Allowed values: (true|false) # @param forward_policy Default policy for the FORWARD chain # Default value: DROP -# Allowed values: (ACCEPT|DROP|REJECT) +# Allowed values: (ACCEPT|DROP) # @param output_policy Default policy for the OUTPUT chain # Default value: ACCEPT -# Allowed values: (ACCEPT|DROP|REJECT) +# Allowed values: (ACCEPT|DROP) # @param input_policy Default policy for the INPUT chain # Default value: DROP -# Allowed values: (ACCEPT|DROP|REJECT) +# Allowed values: (ACCEPT|DROP) # @param rules A hash that holds all data for ferm::rule # Default value: Empty Hash # Allowed value: Any Hash @@ -95,6 +95,9 @@ class ferm ( -> Class['ferm::config'] ~> Class['ferm::service'] + Ferm::Chain <| |> + ~> Class['ferm::service'] + $rules.each |$rulename, $attributes| { ferm::rule{$rulename: * => $attributes, 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", } } |