forked from puppetlabs/puppetlabs-firewall
/
firewallchain.rb
125 lines (108 loc) · 4.52 KB
/
firewallchain.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
Puppet::Type.newtype(:firewallchain) do
@doc = <<-EOS
This type provides the capability to manage rule chains for firewalls.
Currently this supports only iptables, ip6tables and ebtables on Linux. And
provides support for setting the default policy on chains and tables that
allow it.
EOS
feature :iptables_chain, "The provider provides iptables chain features."
feature :policy, "Default policy (inbuilt chains only)"
ensurable do
defaultvalues
defaultto :present
end
newparam(:name) do
desc <<-EOS
The canonical name of the chain.
For iptables the format must be {chain}:{table}:{protocol}.
EOS
isnamevar
validate do |value|
if value !~ Nameformat then
raise ArgumentError, "Inbuilt chains must be in the form {chain}:{table}:{protocol} where {table} is one of FILTER, NAT, MANGLE, RAW, RAWPOST, BROUTE or empty (alias for filter), chain can be anything without colons or one of PREROUTING, POSTROUTING, BROUTING, INPUT, FORWARD, OUTPUT for the inbuilt chains, and {protocol} being IPv4, IPv6, ethernet (ethernet bridging) got '#{value}' table:'#{$1}' chain:'#{$2}' protocol:'#{$3}'"
else
chain = $1
table = $2
protocol = $3
case table
when 'filter'
if chain =~ /^(PREROUTING|POSTROUTING|BROUTING)$/
raise ArgumentError, "INPUT, OUTPUT and FORWARD are the only inbuilt chains that can be used in table 'filter'"
end
when 'mangle'
if chain =~ InternalChains && chain == 'BROUTING'
raise ArgumentError, "PREROUTING, POSTROUTING, INPUT, FORWARD and OUTPUT are the only inbuilt chains that can be used in table 'mangle'"
end
when 'nat'
if chain =~ /^(BROUTING|INPUT|FORWARD)$/
raise ArgumentError, "PREROUTING, POSTROUTING and OUTPUT are the only inbuilt chains that can be used in table 'nat'"
end
if protocol =~/^(IP(v6)?)?$/
raise ArgumentError, "table nat isn't valid in IPv6. You must specify ':IPv4' as the name suffix"
end
when 'raw'
if chain =~ /^(POSTROUTING|BROUTING|INPUT|FORWARD)$/
raise ArgumentError,'PREROUTING and OUTPUT are the only inbuilt chains in the table \'raw\''
end
when 'broute'
if protocol != 'ethernet'
raise ArgumentError,'BROUTE is only valid with protocol \'ethernet\''
end
if chain =~ /^PREROUTING|POSTROUTING|INPUT|FORWARD|OUTPUT$/
raise ArgumentError,'BROUTING is the only inbuilt chain allowed on on table \'broute\''
end
end
if chain == 'BROUTING' && ( protocol != 'ethernet' || table!='broute')
raise ArgumentError,'BROUTING is the only inbuilt chain allowed on on table \'BROUTE\' with protocol \'ethernet\' i.e. \'broute:BROUTING:enternet\''
end
end
end
end
newproperty(:policy) do
desc <<-EOS
This is the action to when the end of the chain is reached.
It can only be set on inbuilt chains (INPUT, FORWARD, OUTPUT,
PREROUTING, POSTROUTING) and can be one of:
* accept - the packet is accepted
* drop - the packet is dropped
* queue - the packet is passed userspace
* return - the packet is returned to calling (jump) queue
or the default of inbuilt chains
EOS
newvalues(:accept, :drop, :queue, :return)
defaultto do
# ethernet chain have an ACCEPT default while other haven't got an
# allowed value
if @resource[:name] =~ /:ethernet$/
:accept
else
nil
end
end
end
validate do
debug("[validate]")
value(:name).match(Nameformat)
chain = $1
table = $2
protocol = $3
# Check that we're not removing an internal chain
if chain =~ InternalChains && value(:ensure) == :absent
self.fail "Cannot remove in-built chains"
end
if value(:policy).nil? && protocol == 'ethernet'
self.fail "you must set a non-empty policy on all ethernet table chains"
end
# Check that we're not setting a policy on a user chain
if chain !~ InternalChains &&
!value(:policy).nil? &&
protocol != 'ethernet'
self.fail "policy can only be set on in-built chains (with the exception of ethernet chains) (table:#{table} chain:#{chain} protocol:#{protocol})"
end
# no DROP policy on nat table
if table == 'nat' &&
value(:policy) == :drop
self.fail 'The "nat" table is not intended for filtering, the use of DROP is therefore inhibited'
end
end
end