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