## puppetlabs-firewall module
+## User Guide
+
### Overview
-This is the puppet-firewall module. Here we are providing a module which can be used to configure various firewalls
+This type provides the capability to manage firewall rules within
+puppet.
+
+Current support includes:
+
+* iptables
+* ip6tables
### Disclaimer
-Warning! While this software is written in the best interest of quality it has not been formally tested by our QA teams. Use at your own risk, but feel free to enjoy and perhaps improve it while you do.
+Warning! While this software is written in the best interest of quality it has
+not been formally tested by our QA teams. Use at your own risk, but feel free
+to enjoy and perhaps improve it while you do.
+
+Please see the included Apache Software License for more legal details
+regarding warranty.
+
+Also as this is a 0.x release the API is still in flux and may change. Make sure
+you read the release notes before upgrading.
+
+### Downloading
-Please see the included Apache Software License for more legal details regarding warranty.
+If you are intending to use this module it is recommended you obtain this from the
+forge and not Github:
+
+ http://forge.puppetlabs.com/puppetlabs/firewall
+
+The forge releases are vetted releases. Using code from Github means you are
+accessing a development version or early release of the code.
### Installation
-From github, download the module into your modulepath on your Puppetmaster. If you are not sure where your module path is try this command:
+Using the puppet-module gem, you can install it into your Puppet's
+module path. If you are not sure where your module path is try
+this command:
puppet --configprint modulepath
-Depending on the version of Puppet, you may need to restart the puppetmasterd (or Apache) process before this module will work.
+Firstly change into that directory. For example:
+
+ cd /etc/puppet/modules
+
+Then run the module tool:
+
+ puppet-module install puppetlabs-firewall
-This module uses both Ruby based providers so your Puppet configuration (ie. puppet.conf) must include the following items:
+Depending on the version of Puppet, you may need to restart the
+puppetmasterd (or Apache) process before this module will work.
+
+This module uses both Ruby based providers so your Puppet configuration
+(ie. puppet.conf) must include the following items:
[agent]
pluginsync = true
The module will not operate normally without these features enabled.
-### Quickstart
-
-Once the module is in the correct modulepath, you should be able to create some
-firewall rules like the below examples. Remember, that rules are lexically
-ordered by the resource title at this point.
+### Examples
Basic accept ICMP request example:
action => "accept",
}
-Deny all:
+Drop all:
firewall { "999 drop all other requests":
action => "drop",
}
If you wish to ensure any reject rules are executed last, try using stages.
-The following example shows the creation of a class which is where your
+The following example shows the creation of a class which is where your
last rules should run, this however should belong in a puppet module.
class my_fw::drop {
By placing the 'my_fw::drop' class in the post stage it will always be inserted
last thereby avoiding locking you out before the accept rules are inserted.
-### Supported firewalls
-
-Currently we support:
-
-* Iptables
-
-But plans are to support lots of other firewall implementations:
-
-* Linux IPv6 (ip6tables)
-* FreeBSD (ipf)
-* Mac OS X (ipfw)
-* OpenBSD (pf)
-* Cisco (ASA and basic access lists)
-
-If you have knowledge in these rules and wish to contribute to this project
-feel free to submit patches (after signing a Puppetlabs CLA :-).
-
-### Generic Properties
-
-#### ensure
-
-Creates rule when present, removes it when absent.
-
-#### name
-
-* namevar
-
-Name of firewall rule. This at the moment also is used for ordering, so its
-common practice to prefix all rules with numbers to force ordering. For example:
-
- name => "000 accept local traffic"
-
-This will occur very early.
-
-#### action
-
-This is the action to perform on a match. Can be one of:
-
-* accept - the packet is accepted
-* reject - the packet is rejected with a suitable ICMP response
-* drop - the packet is dropped
-
-If you specify no value it will simply match the rule but perform no
-action unless you provide a provider specific parameter (such as 'jump').
-
-#### proto
-
-Protocol to filter. By default this is 'tcp'.
-
-#### source
-
-An array of source addresses. For example:
-
- source => ['192.168.2.0/24', '10.2.3.0/24']
-
-#### destination
-
-An array of destination addresses to match. For example:
+### Further documentation
- destination => ['192.168.2.0/24', '10.2.3.0/24']
+More documentation is available from the forge for each release:
-#### sport
+ <http://forge.puppetlabs.com/puppetlabs/firewall>
-For protocols that support ports, this is a list of source ports to filter on.
+Or you can access the inline documentation:
-#### dport
+ puppet describe firewall
-For protocols that support ports, this is a list of destination ports to filter on.
+Or:
-### Iptables Properties
+ puppet doc -r type
-#### chain
+(and search for firewall).
-Name of the chain to use. Can be one of the built-ins:
+### Bugs
-* INPUT
-* FORWARD
-* OUTPUT
-* PREROUTING
-* POSTROUTING
+Bugs can be reported in the Puppetlabs Redmine project:
-Or you can provide a user-based chain.
+ <http://projects.puppetlabs.com/projects/modules/>
-The default value is 'INPUT'.
+## Developer Guide
-#### table
+### Contributing
-Table to use. Can be one of:
+Make sure you read CONTRIBUTING.md before contributing.
-* nat
-* mangle
-* filter
-* raw
-* rawpost
-
-By default the setting is 'filter'.
-
-#### jump
-
-Action to perform when filter is matched for iptables. Can be one of:
-
-* QUEUE
-* RETURN
-* DNAT
-* SNAT
-* LOG
-* MASQUERADE
-* REDIRECT
-
-But any valid chain name is allowed.
-
-For the values ACCEPT, DROP and REJECT you must use the generic
-'action' parameter. This is to enfore the use of generic parameters where
-possible for maximum cross-platform modelling.
-
-If you set both 'accept' and 'jump' parameters, you will get an error as
-only one of the options should be set.
-
-### Interface Matching Properties
-
-#### iniface
-
-Input interface to filter on.
-
-#### outiface
-
-Output interface to filter on.
-
-### NAT Properties
-
-#### tosource
-
-When using jump => "SNAT" you can specify the new source address using this
-parameter.
-
-#### todestination
-
-When using jump => "DNAT" you can specify the new destination address using
-this paramter.
-
-#### toports
-
-Specifies a range of ports to use for masquerade.
-
-### Reject Properties
-
-#### reject
-
-When combined with jump => "REJECT" you can specify a different icmp response
-to be sent back to the packet sender.
-
-### Logging Properties
-
-#### log_level
-
-When combined with jump => "LOG" specifies the log level to log to.
-
-#### log_prefix
-
-When combined with jump => "LOG" specifies the log prefix to use when logging.
-
-### ICMP Matching Properties
-
-#### icmp
-
-Specifies the type of ICMP to match.
-
-### State Matching Properties
-
-#### state
-
-When matching using stateful inspection you can match on different states such
-as:
-
-* INVALID
-* ESTABLISHED
-* NEW
-* RELATED
-
-### Rate Limiting Properties
-
-#### limit
+Currently we support:
-A rate to limit matched packets in the form of:
+* iptables
+* ip6tables
- rate/[/second/|/minute|/hour|/day]
+But plans are to support lots of other firewall implementations:
-#### burst
+* FreeBSD (ipf)
+* Mac OS X (ipfw)
+* OpenBSD (pf)
+* Cisco (ASA and basic access lists)
-Maximum initial packets to match before limit checks (above) apply.
+If you have knowledge in these technology, know how to code and wish to contribute
+to this project we would welcome the help.
### Testing
Puppet::Type.newtype(:firewall) do
include Puppet::Util::Firewall
- @doc = "This type provides the capability to manage firewall rules within
- puppet."
+ @doc = <<-EOS
+ This type provides the capability to manage firewall rules within
+ puppet.
+ EOS
feature :rate_limiting, "Rate limiting features."
feature :snat, "Source NATing"
feature :iptables, "The provider provides iptables features."
ensurable do
- desc "Manage the state of this rule."
+ desc <<-EOS
+ Manage the state of this rule. The default action is *present*.
+ EOS
newvalue(:present) do
provider.insert
end
newparam(:name) do
- desc "The canonical name of the rule."
+ desc <<-EOS
+ The canonical name of the rule. This name is also used for ordering
+ so make sure you prefix the rule with a number:
+
+ 000 this runs first
+ 999 this runs last
+
+ Depending on the provider, the name of the rule can be stored using
+ the comment feature of the underlying firewall subsystem.
+ EOS
isnamevar
# Keep rule names simple - they must start with a number
end
newproperty(:action) do
- desc "Action to perform on this rule."
+ desc <<-EOS
+ This is the action to perform on a match. Can be one of:
+
+ * accept - the packet is accepted
+ * reject - the packet is rejected with a suitable ICMP response
+ * drop - the packet is dropped
+
+ If you specify no value it will simply match the rule but perform no
+ action unless you provide a provider specific parameter (such as *jump*).
+ EOS
newvalues(:accept, :reject, :drop)
end
# Generic matching properties
newproperty(:source) do
- desc "The source IP address to match."
+ desc <<-EOS
+ An array of source addresses. For example:
+
+ source => '192.168.2.0/24'
+
+ The source can also be an IPv6 address if your provider supports it.
+ EOS
end
newproperty(:destination) do
- desc "The destination IP address to match."
+ desc <<-EOS
+ An array of destination addresses to match. For example:
+
+ destination => '192.168.1.0/24'
+
+ The destination can also be an IPv6 address if your provider supports it.
+ EOS
end
newproperty(:sport, :array_matching => :all) do
- desc "The source port to match for this filter (if the protocol supports
- ports). Will accept a single element or an array."
+ desc <<-EOS
+ For protocols that support ports, this is a list of source ports
+ to filter on.
+ EOS
munge do |value|
@resource.string_to_port(value)
end
newproperty(:dport, :array_matching => :all) do
- desc "The destination port to match for this filter (if the protocol
- supports ports). Will accept a single element or an array."
+ desc <<-EOS
+ For protocols that support ports, this is a list of destination
+ ports to filter on.
+ EOS
munge do |value|
@resource.string_to_port(value)
end
newproperty(:proto) do
- desc "The specific protocol to match for this rule."
+ desc <<-EOS
+ The specific protocol to match for this rule. By default this is
+ *tcp*.
+ EOS
+
newvalues(:tcp, :udp, :icmp, :"ipv6-icmp", :esp, :ah, :vrrp, :igmp, :all)
defaultto "tcp"
end
# Iptables specific
newproperty(:chain, :required_features => :iptables) do
- desc "The value for the iptables -A parameter. Normal values are: 'INPUT',
- 'FORWARD', 'OUTPUT', 'PREROUTING', 'POSTROUTING' but you can also
- specify a user created chain."
+ desc <<-EOS
+ Name of the chain to use. Can be one of the built-ins:
+
+ * INPUT
+ * FORWARD
+ * OUTPUT
+ * PREROUTING
+ * POSTROUTING
+
+ Or you can provide a user-based chain.
+
+ The default value is 'INPUT'.
+ EOS
defaultto "INPUT"
newvalue(/^[a-zA-Z0-9\-_]+$/)
end
newproperty(:table, :required_features => :iptables) do
- desc "The value for the iptables -t parameter."
+ desc <<-EOS
+ Table to use. Can be one of:
+
+ * nat
+ * mangle
+ * filter
+ * raw
+ * rawpost
+
+ By default the setting is 'filter'.
+ EOS
+
newvalues(:nat, :mangle, :filter, :raw, :rawpost)
defaultto "filter"
end
newproperty(:jump, :required_features => :iptables) do
- desc <<EOS
-The value for the iptables --jump parameter. Normal values are:
-
-* QUEUE
-* RETURN
-* DNAT
-* SNAT
-* LOG
-* MASQUERADE
-* REDIRECT.
-
-But any valid chain name is allowed.
-
-For the values ACCEPT, DROP and REJECT you must use the generic
-'action' parameter. This is to enfore the use of generic parameters where
-possible for maximum cross-platform modelling.
-
-If you set both 'accept' and 'jump' parameters, the jump parameter will take
-precedence.
-EOS
+ desc <<-EOS
+ The value for the iptables --jump parameter. Normal values are:
+
+ * QUEUE
+ * RETURN
+ * DNAT
+ * SNAT
+ * LOG
+ * MASQUERADE
+ * REDIRECT
+
+ But any valid chain name is allowed.
+
+ For the values ACCEPT, DROP and REJECT you must use the generic
+ 'action' parameter. This is to enfore the use of generic parameters where
+ possible for maximum cross-platform modelling.
+
+ If you set both 'accept' and 'jump' parameters, you will get an error as
+ only one of the options should be set.
+ EOS
+
validate do |value|
- raise ArgumentError, "Jump destination must consist of alphanumeric characters, an underscore or a hyphen." unless value =~ /^[a-zA-Z0-9\-_]+$/
- raise ArgumentError, "Jump destination should not be one of ACCEPT, REJECT or DENY. Use the action property instead." if ["accept","reject","drop"].include?(value.downcase)
+ unless value =~ /^[a-zA-Z0-9\-_]+$/
+ raise ArgumentError, <<-EOS
+ Jump destination must consist of alphanumeric characters, an
+ underscore or a yphen.
+ EOS
+ end
+
+ if ["accept","reject","drop"].include?(value.downcase)
+ raise ArgumentError, <<-EOS
+ Jump destination should not be one of ACCEPT, REJECT or DENY. Use
+ the action property instead.
+ EOS
+ end
+
end
end
# Interface specific matching properties
newproperty(:iniface, :required_features => :interface_match) do
- desc "Match input interface."
+ desc <<-EOS
+ Input interface to filter on.
+ EOS
newvalues(/^[a-zA-Z0-9\-_]+$/)
end
newproperty(:outiface, :required_features => :interface_match) do
- desc "Match ouput interface."
+ desc <<-EOS
+ Output interface to filter on.
+ EOS
newvalues(/^[a-zA-Z0-9\-_]+$/)
end
# NAT specific properties
newproperty(:tosource, :required_features => :snat) do
- desc "For SNAT this is the IP address that will replace the source IP
- address."
+ desc <<-EOS
+ When using jump => "SNAT" you can specify the new source address using
+ this parameter.
+ EOS
end
newproperty(:todest, :required_features => :dnat) do
- desc "For DNAT this is the IP address that will replace the destination IP
- address."
+ desc <<-EOS
+ When using jump => "DNAT" you can specify the new destination address
+ using this paramter.
+ EOS
end
newproperty(:toports, :required_features => :dnat) do
- desc "For DNAT this is the port that will replace the destination port."
+ desc <<-EOS
+ For DNAT this is the port that will replace the destination port.
+ EOS
end
# Reject ICMP type
newproperty(:reject, :required_features => :reject_type) do
- desc "The ICMP response to reject a packet with."
+ desc <<-EOS
+ When combined with jump => "REJECT" you can specify a different icmp
+ response to be sent back to the packet sender.
+ EOS
end
# Logging properties
newproperty(:log_level, :required_features => :log_level) do
- desc "The syslog level to log to."
+ desc <<-EOS
+ When combined with jump => "LOG" specifies the system log level to log
+ to.
+ EOS
end
newproperty(:log_prefix, :required_features => :log_prefix) do
- desc "The syslog prefix."
+ desc <<-EOS
+ When combined with jump => "LOG" specifies the log prefix to use when
+ logging.
+ EOS
end
# ICMP matching property
newproperty(:icmp, :required_features => :icmp_match) do
- desc "When matching ICMP packets, this is the type of ICMP packet to match."
+ desc <<-EOS
+ When matching ICMP packets, this is the type of ICMP packet to match.
+ EOS
munge do |value|
if value.kind_of?(String)
end
end
- newproperty(:state, :array_matching => :all, :required_features => :state_match) do
- desc "Matches a packet based on its state in the firewall stateful inspection
- table."
+ newproperty(:state, :array_matching => :all, :required_features =>
+ :state_match) do
+
+ desc <<-EOS
+ Matches a packet based on its state in the firewall stateful inspection
+ table. Values can be:
+
+ * INVALID
+ * ESTABLISHED
+ * NEW
+ * RELATED
+ EOS
newvalues(:INVALID,:ESTABLISHED,:NEW,:RELATED)
# Rate limiting properties
newproperty(:limit, :required_features => :rate_limiting) do
- desc "Rate limiting value. Example values are: '50/sec', '40/min',
- '30/hour', '10/day'."
+ desc <<-EOS
+ Rate limiting value for matched packets. The format is:
+ rate/[/second/|/minute|/hour|/day].
+
+ Example values are: '50/sec', '40/min', '30/hour', '10/day'."
+ EOS
end
newproperty(:burst, :required_features => :rate_limiting) do
- desc "Rate limiting burst value (per second)."
+ desc <<-EOS
+ Rate limiting burst value (per second) before limit checks apply.
+ EOS
newvalue(/^\d+$/)
end
newparam(:line) do
- desc 'Read-only property for caching the rule line'
+ desc <<-EOS
+ Read-only property for caching the rule line.
+ EOS
end
validate do
end
# First we make sure the chains and tables are valid combinations
- if value(:table).to_s == "filter" && value(:chain) =~ /PREROUTING|POSTROUTING/
+ if value(:table).to_s == "filter" &&
+ value(:chain) =~ /PREROUTING|POSTROUTING/
+
self.fail "PREROUTING and POSTROUTING cannot be used in table 'filter'"
end
self.fail "INPUT and FORWARD cannot be used in table 'nat'"
end
- if value(:table).to_s == "raw" && value(:chain) =~ /INPUT|FORWARD|POSTROUTING/
+ if value(:table).to_s == "raw" &&
+ value(:chain) =~ /INPUT|FORWARD|POSTROUTING/
+
self.fail "INPUT, FORWARD and POSTROUTING cannot be used in table raw"
end