root / spec / classes / nftables_spec.rb @ 1fd3f550
Historique | Voir | Annoter | Télécharger (9,25 ko)
1 |
# frozen_string_literal: true
|
---|---|
2 |
|
3 |
require 'spec_helper'
|
4 |
|
5 |
describe 'nftables' do |
6 |
let(:pre_condition) { 'Exec{path => "/bin"}' } |
7 |
|
8 |
on_supported_os.each do |os, os_facts|
|
9 |
context "on #{os}" do |
10 |
let(:facts) { os_facts }
|
11 |
|
12 |
nft_path = case os_facts[:os]['family'] |
13 |
when 'Archlinux' |
14 |
'/usr/bin/nft'
|
15 |
else
|
16 |
'/usr/sbin/nft'
|
17 |
end
|
18 |
nft_config = case os_facts[:os]['family'] |
19 |
when 'RedHat' |
20 |
'/etc/sysconfig/nftables.conf'
|
21 |
else
|
22 |
'/etc/nftables.conf'
|
23 |
end
|
24 |
|
25 |
it { is_expected.to compile.with_all_deps } |
26 |
|
27 |
it { is_expected.to contain_package('nftables') }
|
28 |
|
29 |
it { |
30 |
is_expected.to contain_file('/etc/nftables').with(
|
31 |
ensure: 'directory', |
32 |
owner: 'root', |
33 |
group: 'root', |
34 |
mode: '0750' |
35 |
) |
36 |
} |
37 |
|
38 |
it { |
39 |
expect(subject).to contain_file('/etc/nftables/puppet.nft').with(
|
40 |
ensure: 'file', |
41 |
owner: 'root', |
42 |
group: 'root', |
43 |
mode: '0640', |
44 |
content: %r{flush ruleset} |
45 |
) |
46 |
} |
47 |
|
48 |
it { |
49 |
expect(subject).to contain_file('/etc/nftables/puppet').with(
|
50 |
ensure: 'directory', |
51 |
owner: 'root', |
52 |
group: 'root', |
53 |
mode: '0750', |
54 |
purge: true, |
55 |
force: true, |
56 |
recurse: true |
57 |
) |
58 |
} |
59 |
|
60 |
it { |
61 |
expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').with(
|
62 |
ensure: 'file', |
63 |
owner: 'root', |
64 |
group: 'root', |
65 |
mode: '0640', |
66 |
content: %r{flush ruleset} |
67 |
) |
68 |
} |
69 |
|
70 |
it { |
71 |
expect(subject).to contain_file('/etc/nftables/puppet-preflight').with(
|
72 |
ensure: 'directory', |
73 |
owner: 'root', |
74 |
group: 'root', |
75 |
mode: '0750', |
76 |
purge: true, |
77 |
force: true, |
78 |
recurse: true |
79 |
) |
80 |
} |
81 |
|
82 |
it { |
83 |
expect(subject).to contain_exec('nft validate').with(
|
84 |
refreshonly: true, |
85 |
command: %r{^#{nft_path} -I /etc/nftables/puppet-preflight -c -f /etc/nftables/puppet-preflight.nft.*} |
86 |
) |
87 |
} |
88 |
|
89 |
it { |
90 |
expect(subject).to contain_service('nftables').with(
|
91 |
ensure: 'running', |
92 |
enable: true, |
93 |
hasrestart: true, |
94 |
restart: %r{PATH=/usr/bin:/bin systemctl reload nft.*} |
95 |
) |
96 |
} |
97 |
|
98 |
it { |
99 |
expect(subject).to contain_systemd__dropin_file('puppet_nft.conf').with(
|
100 |
content: %r{^ExecReload=#{nft_path} -I /etc/nftables/puppet -f #{nft_config}$} |
101 |
) |
102 |
} |
103 |
|
104 |
case os_facts[:os]['family'] |
105 |
when 'Archlinux' |
106 |
|
107 |
it { |
108 |
expect(subject).to contain_service('firewalld').with(
|
109 |
ensure: 'stopped', |
110 |
enable: false |
111 |
) |
112 |
} |
113 |
when 'Debian' |
114 |
it { |
115 |
is_expected.to contain_service('firewalld').with(
|
116 |
ensure: 'stopped', |
117 |
enable: false |
118 |
) |
119 |
} |
120 |
else
|
121 |
it { |
122 |
expect(subject).to contain_service('firewalld').with(
|
123 |
ensure: 'stopped', |
124 |
enable: 'mask' |
125 |
) |
126 |
} |
127 |
end
|
128 |
|
129 |
it { is_expected.to contain_class('nftables::inet_filter') }
|
130 |
it { is_expected.to contain_class('nftables::ip_nat') }
|
131 |
it { is_expected.to contain_class('nftables::rules::out::http') }
|
132 |
it { is_expected.to contain_class('nftables::rules::out::https') }
|
133 |
it { is_expected.to contain_class('nftables::rules::out::dns') }
|
134 |
it { is_expected.to contain_class('nftables::rules::out::chrony') }
|
135 |
it { is_expected.not_to contain_class('nftables::rules::out::all') }
|
136 |
it { is_expected.not_to contain_nftables__rule('default_out-all') }
|
137 |
|
138 |
context 'with out_all set true' do |
139 |
let(:params) do |
140 |
{ |
141 |
out_all: true, |
142 |
} |
143 |
end
|
144 |
|
145 |
it { is_expected.to contain_class('nftables::rules::out::all') }
|
146 |
it { is_expected.not_to contain_class('nftables::rules::out::http') }
|
147 |
it { is_expected.not_to contain_class('nftables::rules::out::https') }
|
148 |
it { is_expected.not_to contain_class('nftables::rules::out::dns') }
|
149 |
it { is_expected.not_to contain_class('nftables::rules::out::chrony') }
|
150 |
it { is_expected.to contain_nftables__rule('default_out-all').with_content('accept') } |
151 |
it { is_expected.to contain_nftables__rule('default_out-all').with_order('90') } |
152 |
end
|
153 |
|
154 |
context 'with custom rules' do |
155 |
let(:params) do |
156 |
{ |
157 |
rules: {
|
158 |
'INPUT-web_accept' => {
|
159 |
order: '50', |
160 |
content: 'iifname eth0 tcp dport { 80, 443 } accept', |
161 |
}, |
162 |
}, |
163 |
} |
164 |
end
|
165 |
|
166 |
it { |
167 |
expect(subject).to contain_concat__fragment('nftables-inet-filter-chain-INPUT-rule-web_accept').with(
|
168 |
target: 'nftables-inet-filter-chain-INPUT', |
169 |
content: %r{^ iifname eth0 tcp dport \{ 80, 443 \} accept$}, |
170 |
order: '50-nftables-inet-filter-chain-INPUT-rule-web_accept-b' |
171 |
) |
172 |
} |
173 |
end
|
174 |
|
175 |
context 'with custom sets' do |
176 |
let(:params) do |
177 |
{ |
178 |
sets: {
|
179 |
'testset1' => {
|
180 |
type: 'ipv4_addr', |
181 |
gc_interval: 2, |
182 |
}, |
183 |
'testset2' => {
|
184 |
type: 'ipv6_addr', |
185 |
elements: ['2a02:62:c601::dead:beef'], |
186 |
}, |
187 |
}, |
188 |
} |
189 |
end
|
190 |
|
191 |
it { |
192 |
expect(subject).to contain_nftables__set('testset1').with(
|
193 |
type: 'ipv4_addr', |
194 |
gc_interval: 2, |
195 |
table: 'inet-filter' |
196 |
) |
197 |
} |
198 |
|
199 |
it { |
200 |
expect(subject).to contain_nftables__set('testset2').with(
|
201 |
type: 'ipv6_addr', |
202 |
elements: ['2a02:62:c601::dead:beef'], |
203 |
table: 'inet-filter' |
204 |
) |
205 |
} |
206 |
end
|
207 |
|
208 |
context 'without masking firewalld' do |
209 |
let(:params) do |
210 |
{ |
211 |
'firewalld_enable' => false, |
212 |
} |
213 |
end
|
214 |
|
215 |
it { |
216 |
expect(subject).to contain_service('firewalld').with(
|
217 |
ensure: 'stopped', |
218 |
enable: false |
219 |
) |
220 |
} |
221 |
end
|
222 |
|
223 |
context 'with no default filtering rules' do |
224 |
let(:params) do |
225 |
{ |
226 |
'inet_filter' => false, |
227 |
} |
228 |
end
|
229 |
|
230 |
it { is_expected.to contain_class('nftables::ip_nat') }
|
231 |
it { is_expected.not_to contain_class('nftables::inet_filter') }
|
232 |
end
|
233 |
|
234 |
context 'with no default tables, chains or rules' do |
235 |
let(:params) do |
236 |
{ |
237 |
'inet_filter' => false, |
238 |
'nat' => false, |
239 |
} |
240 |
end
|
241 |
|
242 |
it { is_expected.not_to contain_class('nftables::ip_nat') }
|
243 |
it { is_expected.not_to contain_class('nftables::inet_filter') }
|
244 |
it { is_expected.to have_nftables__config_resource_count(0) }
|
245 |
it { is_expected.to have_nftables__chain_resource_count(0) }
|
246 |
it { is_expected.to have_nftables__rule_resource_count(0) }
|
247 |
it { is_expected.to have_nftables__set_resource_count(0) }
|
248 |
end
|
249 |
|
250 |
%w[ip ip6 inet arp bridge netdev].each do |family| |
251 |
context "with noflush_tables parameter set to valid family #{family}" do |
252 |
let(:params) do |
253 |
{ |
254 |
noflush_tables: ["#{family}-f2b-table"], |
255 |
} |
256 |
end
|
257 |
|
258 |
context 'with no nftables fact' do |
259 |
it { is_expected.to contain_file('/etc/nftables/puppet-preflight.nft').with_content(%r{^flush ruleset$}) } |
260 |
end
|
261 |
|
262 |
context 'with nftables fact matching' do |
263 |
let(:facts) do |
264 |
super().merge(nftables: { tables: %W[#{family}-abc #{family}-f2b-table] }) |
265 |
end
|
266 |
|
267 |
it { |
268 |
expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
|
269 |
with_content(%r{^table #{family} abc \{\}$})
|
270 |
} |
271 |
|
272 |
it { |
273 |
expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
|
274 |
with_content(%r{^flush table #{family} abc$})
|
275 |
} |
276 |
end
|
277 |
|
278 |
context 'with nftables fact not matching' do |
279 |
let(:facts) do |
280 |
super().merge(nftables: { tables: %W[#{family}-abc #{family}-ijk] }) |
281 |
end
|
282 |
|
283 |
it { |
284 |
expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
|
285 |
with_content(%r{^table #{family} abc \{\}$})
|
286 |
} |
287 |
|
288 |
it { |
289 |
expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
|
290 |
with_content(%r{^flush table #{family} abc$})
|
291 |
} |
292 |
|
293 |
it { |
294 |
expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
|
295 |
with_content(%r{^table #{family} ijk \{\}$})
|
296 |
} |
297 |
|
298 |
it { |
299 |
expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
|
300 |
with_content(%r{^flush table #{family} ijk$})
|
301 |
} |
302 |
end
|
303 |
end
|
304 |
end
|
305 |
|
306 |
%w[it ip7 inter arpa brid netdevs].each do |family| |
307 |
context "with noflush_tables parameter set to invalid family #{family}" do |
308 |
let(:params) do |
309 |
{ |
310 |
noflush_tables: ["#{family}-f2b-table"], |
311 |
} |
312 |
end
|
313 |
|
314 |
it { is_expected.not_to compile } |
315 |
end
|
316 |
end
|
317 |
end
|
318 |
end
|
319 |
end
|