Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

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