Projet

Général

Profil

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

root / spec / classes / nftables_spec.rb @ cc9fc807

Historique | Voir | Annoter | Télécharger (8,53 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

    
19
      it { is_expected.to compile.with_all_deps }
20

    
21
      it { is_expected.to contain_package('nftables') }
22

    
23
      it {
24
        is_expected.to contain_file('/etc/nftables').with(
25
          ensure: 'directory',
26
          owner: 'root',
27
          group: 'root',
28
          mode: '0750'
29
        )
30
      }
31

    
32
      it {
33
        expect(subject).to contain_file('/etc/nftables/puppet.nft').with(
34
          ensure: 'file',
35
          owner: 'root',
36
          group: 'root',
37
          mode: '0640',
38
          content: %r{flush ruleset}
39
        )
40
      }
41

    
42
      it {
43
        expect(subject).to contain_file('/etc/nftables/puppet').with(
44
          ensure: 'directory',
45
          owner: 'root',
46
          group: 'root',
47
          mode: '0750',
48
          purge: true,
49
          force: true,
50
          recurse: true
51
        )
52
      }
53

    
54
      it {
55
        expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').with(
56
          ensure: 'file',
57
          owner: 'root',
58
          group: 'root',
59
          mode: '0640',
60
          content: %r{flush ruleset}
61
        )
62
      }
63

    
64
      it {
65
        expect(subject).to contain_file('/etc/nftables/puppet-preflight').with(
66
          ensure: 'directory',
67
          owner: 'root',
68
          group: 'root',
69
          mode: '0750',
70
          purge: true,
71
          force: true,
72
          recurse: true
73
        )
74
      }
75

    
76
      it {
77
        expect(subject).to contain_exec('nft validate').with(
78
          refreshonly: true,
79
          command: %r{^#{nft_path} -I /etc/nftables/puppet-preflight -c -f /etc/nftables/puppet-preflight.nft.*}
80
        )
81
      }
82

    
83
      it {
84
        expect(subject).to contain_service('nftables').with(
85
          ensure: 'running',
86
          enable: true,
87
          hasrestart: true,
88
          restart: %r{PATH=/usr/bin:/bin systemctl reload nft.*}
89
        )
90
      }
91

    
92
      if os_facts[:os]['family'] == 'Archlinux'
93
        it {
94
          expect(subject).to contain_systemd__dropin_file('puppet_nft.conf').with(
95
            content: %r{^ExecReload=#{nft_path} -I /etc/nftables/puppet -f /etc/nftables.conf$}
96
          )
97
        }
98

    
99
        it {
100
          expect(subject).to contain_service('firewalld').with(
101
            ensure: 'stopped',
102
            enable: false
103
          )
104
        }
105
      else
106
        it {
107
          expect(subject).to contain_systemd__dropin_file('puppet_nft.conf').with(
108
            content: %r{^ExecReload=#{nft_path} -I /etc/nftables/puppet -f /etc/sysconfig/nftables.conf$}
109
          )
110
        }
111

    
112
        it {
113
          expect(subject).to contain_service('firewalld').with(
114
            ensure: 'stopped',
115
            enable: 'mask'
116
          )
117
        }
118
      end
119

    
120
      it { is_expected.to contain_class('nftables::inet_filter') }
121
      it { is_expected.to contain_class('nftables::ip_nat') }
122
      it { is_expected.to contain_class('nftables::rules::out::http') }
123
      it { is_expected.to contain_class('nftables::rules::out::https') }
124
      it { is_expected.to contain_class('nftables::rules::out::dns') }
125
      it { is_expected.to contain_class('nftables::rules::out::chrony') }
126
      it { is_expected.not_to contain_class('nftables::rules::out::all') }
127
      it { is_expected.not_to contain_nftables__rule('default_out-all') }
128

    
129
      context 'with out_all set true' do
130
        let(:params) do
131
          {
132
            out_all: true,
133
          }
134
        end
135

    
136
        it { is_expected.to contain_class('nftables::rules::out::all') }
137
        it { is_expected.not_to contain_class('nftables::rules::out::http') }
138
        it { is_expected.not_to contain_class('nftables::rules::out::https') }
139
        it { is_expected.not_to contain_class('nftables::rules::out::dns') }
140
        it { is_expected.not_to contain_class('nftables::rules::out::chrony') }
141
        it { is_expected.to contain_nftables__rule('default_out-all').with_content('accept') }
142
        it { is_expected.to contain_nftables__rule('default_out-all').with_order('90') }
143
      end
144

    
145
      context 'with custom rules' do
146
        let(:params) do
147
          {
148
            rules: {
149
              'INPUT-web_accept' => {
150
                order: '50',
151
                content: 'iifname eth0 tcp dport { 80, 443 } accept',
152
              },
153
            },
154
          }
155
        end
156

    
157
        it {
158
          expect(subject).to contain_concat__fragment('nftables-inet-filter-chain-INPUT-rule-web_accept').with(
159
            target: 'nftables-inet-filter-chain-INPUT',
160
            content: %r{^  iifname eth0 tcp dport \{ 80, 443 \} accept$},
161
            order: '50-nftables-inet-filter-chain-INPUT-rule-web_accept-b'
162
          )
163
        }
164
      end
165

    
166
      context 'with custom sets' do
167
        let(:params) do
168
          {
169
            sets: {
170
              'testset1' => {
171
                type: 'ipv4_addr',
172
                gc_interval: 2,
173
              },
174
              'testset2' => {
175
                type: 'ipv6_addr',
176
                elements: ['2a02:62:c601::dead:beef'],
177
              },
178
            },
179
          }
180
        end
181

    
182
        it {
183
          expect(subject).to contain_nftables__set('testset1').with(
184
            type: 'ipv4_addr',
185
            gc_interval: 2,
186
            table: 'inet-filter'
187
          )
188
        }
189

    
190
        it {
191
          expect(subject).to contain_nftables__set('testset2').with(
192
            type: 'ipv6_addr',
193
            elements: ['2a02:62:c601::dead:beef'],
194
            table: 'inet-filter'
195
          )
196
        }
197
      end
198

    
199
      context 'without masking firewalld' do
200
        let(:params) do
201
          {
202
            'firewalld_enable' => false,
203
          }
204
        end
205

    
206
        it {
207
          expect(subject).to contain_service('firewalld').with(
208
            ensure: 'stopped',
209
            enable: false
210
          )
211
        }
212
      end
213

    
214
      context 'with no default filtering rules' do
215
        let(:params) do
216
          {
217
            'inet_filter' => false,
218
          }
219
        end
220

    
221
        it { is_expected.to contain_class('nftables::ip_nat') }
222
        it { is_expected.not_to contain_class('nftables::inet_filter') }
223
      end
224

    
225
      context 'with no default tables, chains or rules' do
226
        let(:params) do
227
          {
228
            'inet_filter' => false,
229
            'nat' => false,
230
          }
231
        end
232

    
233
        it { is_expected.not_to contain_class('nftables::ip_nat') }
234
        it { is_expected.not_to contain_class('nftables::inet_filter') }
235
        it { is_expected.to have_nftables__config_resource_count(0) }
236
        it { is_expected.to have_nftables__chain_resource_count(0) }
237
        it { is_expected.to have_nftables__rule_resource_count(0) }
238
        it { is_expected.to have_nftables__set_resource_count(0) }
239
      end
240

    
241
      context 'with with noflush_tables parameter' do
242
        let(:params) do
243
          {
244
            noflush_tables: ['inet-f2b-table'],
245
          }
246
        end
247

    
248
        context 'with no nftables fact' do
249
          it { is_expected.to contain_file('/etc/nftables/puppet-preflight.nft').with_content(%r{^flush ruleset$}) }
250
        end
251

    
252
        context 'with nftables fact matching' do
253
          let(:facts) do
254
            super().merge(nftables: { tables: %w[inet-abc inet-f2b-table] })
255
          end
256

    
257
          it {
258
            expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
259
              with_content(%r{^table inet abc \{\}$})
260
          }
261

    
262
          it {
263
            expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
264
              with_content(%r{^flush table inet abc$})
265
          }
266
        end
267

    
268
        context 'with nftables fact not matching' do
269
          let(:facts) do
270
            super().merge(nftables: { tables: %w[inet-abc inet-ijk] })
271
          end
272

    
273
          it {
274
            expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
275
              with_content(%r{^table inet abc \{\}$})
276
          }
277

    
278
          it {
279
            expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
280
              with_content(%r{^flush table inet abc$})
281
          }
282

    
283
          it {
284
            expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
285
              with_content(%r{^table inet ijk \{\}$})
286
          }
287

    
288
          it {
289
            expect(subject).to contain_file('/etc/nftables/puppet-preflight.nft').
290
              with_content(%r{^flush table inet ijk$})
291
          }
292
        end
293
      end
294
    end
295
  end
296
end