iptables-ruby 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/test/common.rb ADDED
@@ -0,0 +1,22 @@
1
+ # this setup code is required by all tests
2
+ require 'rubygems'
3
+ $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?('/../lib')
4
+ require 'iptables'
5
+ require 'test/unit'
6
+
7
+ # inspired by https://github.com/cespare/ruby-dedent
8
+ class String
9
+ def dedent
10
+ lines = split "\n"
11
+ return self if lines.empty?
12
+ # first indented line determines indent level
13
+ indentation = nil
14
+ lines.each{ |line|
15
+ next unless line =~ /^(\s+)/
16
+ indentation = $1
17
+ break
18
+ }
19
+ return self if indentation.nil?
20
+ lines.map { |line| line.sub(/^#{indentation}/, "") }.join "\n"
21
+ end
22
+ end
data/test/tc_all.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'common'
2
+
3
+ require 'tc_configuration'
4
+ require 'tc_expansions'
5
+ require 'tc_primitives'
6
+ require 'tc_tables'
7
+ require 'tc_comparison'
@@ -0,0 +1,751 @@
1
+ require 'common'
2
+
3
+ class TestTablesComparison < Test::Unit::TestCase
4
+ def setup
5
+ @iptables_table1 =
6
+ <<-EOS.dedent
7
+ *table1
8
+ :chain1 ACCEPT [0:0]
9
+ :chain2 ACCEPT [0:0]
10
+ -A chain1 -m comment --comment "comment1"
11
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
12
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
13
+ -A chain2 -m comment --comment "comment2"
14
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
15
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
16
+ COMMIT
17
+ EOS
18
+ @iptables_text =
19
+ "#{@iptables_table1}\n"+
20
+ <<-EOS.dedent
21
+ *table2
22
+ :chain3 ACCEPT [0:0]
23
+ :chain4 ACCEPT [0:0]
24
+ -A chain3 -m comment --comment "comment3"
25
+ -A chain3 -p tcp -m tcp --dport 5 -j ACCEPT
26
+ -A chain3 -p tcp -m tcp --dport 6 -j ACCEPT
27
+ -A chain4 -m comment --comment "comment4"
28
+ -A chain4 -p tcp -m tcp --dport 7 -j ACCEPT
29
+ -A chain4 -p tcp -m tcp --dport 8 -j ACCEPT
30
+ COMMIT
31
+ EOS
32
+ @iptables1 = IPTables::Tables.new( @iptables_text )
33
+ end
34
+
35
+ def test_invalid
36
+ assert_raise( RuntimeError, 'should require valid IPTables::Tables object as first parameter' ) {
37
+ IPTables::TablesComparison.new(nil, @iptables1)
38
+ }
39
+ assert_raise( RuntimeError, 'should require valid IPTables::Tables object as second parameter' ) {
40
+ IPTables::TablesComparison.new(@iptables1, nil)
41
+ }
42
+ end
43
+
44
+ def test_equal
45
+ iptables2 = IPTables::Tables.new( @iptables_text )
46
+ comparison = IPTables::TablesComparison.new(@iptables1, iptables2)
47
+
48
+ assert(
49
+ comparison.equal?,
50
+ 'Set of tables with same contents should evaluate as equal.'
51
+ )
52
+ assert_equal(
53
+ [],
54
+ comparison.as_array,
55
+ 'Array output of tables with same contents should evaluate as empty.'
56
+ )
57
+ end
58
+
59
+ def test_missing_table
60
+ iptables2 = IPTables::Tables.new(
61
+ <<-EOS.dedent
62
+ *table1
63
+ :chain1 ACCEPT [0:0]
64
+ -A chain1 -m comment --comment "comment1"
65
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
66
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
67
+ :chain2 ACCEPT [0:0]
68
+ -A chain2 -m comment --comment "comment2"
69
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
70
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
71
+ COMMIT
72
+ EOS
73
+ )
74
+ comparison = IPTables::TablesComparison.new(@iptables1, iptables2)
75
+
76
+ assert_equal(
77
+ false,
78
+ comparison.equal?,
79
+ 'Set of tables with one missing a table should evaluate as unequal.'
80
+ )
81
+ assert_equal(
82
+ comparison.as_array,
83
+ [
84
+ "Missing table: table2",
85
+ ":chain3 ACCEPT",
86
+ ":chain4 ACCEPT",
87
+ "-A chain3 -m comment --comment \"comment3\"",
88
+ "-A chain3 -p tcp -m tcp --dport 5 -j ACCEPT",
89
+ "-A chain3 -p tcp -m tcp --dport 6 -j ACCEPT",
90
+ "-A chain4 -m comment --comment \"comment4\"",
91
+ "-A chain4 -p tcp -m tcp --dport 7 -j ACCEPT",
92
+ "-A chain4 -p tcp -m tcp --dport 8 -j ACCEPT"
93
+ ],
94
+ 'Array output of tables with one missing a table should evaluate to known values.'
95
+ )
96
+ end
97
+
98
+ def test_nil_existing_policy_table
99
+ iptables2 = IPTables::Tables.new({
100
+ 'table1' => {
101
+ 'chain1' => {
102
+ 'policy' => 'ACCEPT',
103
+ 'rules' => [
104
+ '-m comment --comment "comment1"',
105
+ '-p tcp -m tcp --dport 1 -j ACCEPT',
106
+ '-p tcp -m tcp --dport 2 -j ACCEPT',
107
+ ]
108
+ },
109
+ 'chain2' => {
110
+ 'policy' => 'ACCEPT',
111
+ 'rules' => [
112
+ '-m comment --comment "comment2"',
113
+ '-p tcp -m tcp --dport 3 -j ACCEPT',
114
+ '-p tcp -m tcp --dport 4 -j ACCEPT',
115
+ ]
116
+ },
117
+ },
118
+ 'table2' => nil
119
+ })
120
+ comparison = IPTables::TablesComparison.new(@iptables1, iptables2)
121
+
122
+ assert(
123
+ comparison.equal?,
124
+ 'Set of tables which match except one is nil and one is a table should evaluate as equal.'
125
+ )
126
+ assert_equal(
127
+ [],
128
+ comparison.as_array,
129
+ 'Array output of tables which match except one one is nil and one is a table should evaluate as empty.'
130
+ )
131
+ end
132
+
133
+ def test_nil_missing_policy_table
134
+ iptables1 = IPTables::Tables.new( @iptables_table1 )
135
+ iptables2 = IPTables::Tables.new({
136
+ 'table1' => {
137
+ 'chain1' => {
138
+ 'policy' => 'ACCEPT',
139
+ 'rules' => [
140
+ '-m comment --comment "comment1"',
141
+ '-p tcp -m tcp --dport 1 -j ACCEPT',
142
+ '-p tcp -m tcp --dport 2 -j ACCEPT',
143
+ ]
144
+ },
145
+ 'chain2' => {
146
+ 'policy' => 'ACCEPT',
147
+ 'rules' => [
148
+ '-m comment --comment "comment2"',
149
+ '-p tcp -m tcp --dport 3 -j ACCEPT',
150
+ '-p tcp -m tcp --dport 4 -j ACCEPT',
151
+ ]
152
+ },
153
+ },
154
+ 'table2' => nil
155
+ })
156
+ comparison = IPTables::TablesComparison.new(iptables1, iptables2)
157
+
158
+ assert(
159
+ comparison.equal?,
160
+ 'Set of tables which match except one is nil and one is missing should evaluate as equal.'
161
+ )
162
+ assert_equal(
163
+ [],
164
+ comparison.as_array,
165
+ 'Array output of tables which match except one is nil and one is missing should evaluate as empty.'
166
+ )
167
+ end
168
+
169
+ def test_additional_table
170
+ iptables2 = IPTables::Tables.new(
171
+ <<-EOS.dedent
172
+ *table1
173
+ :chain1 ACCEPT [0:0]
174
+ -A chain1 -m comment --comment "comment1"
175
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
176
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
177
+ :chain2 ACCEPT [0:0]
178
+ -A chain2 -m comment --comment "comment2"
179
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
180
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
181
+ COMMIT
182
+ *table2
183
+ :chain3 ACCEPT [0:0]
184
+ -A chain3 -m comment --comment "comment3"
185
+ -A chain3 -p tcp -m tcp --dport 5 -j ACCEPT
186
+ -A chain3 -p tcp -m tcp --dport 6 -j ACCEPT
187
+ :chain4 ACCEPT [0:0]
188
+ -A chain4 -m comment --comment "comment4"
189
+ -A chain4 -p tcp -m tcp --dport 7 -j ACCEPT
190
+ -A chain4 -p tcp -m tcp --dport 8 -j ACCEPT
191
+ COMMIT
192
+ *table3
193
+ :chain5 ACCEPT [0:0]
194
+ -A chain5 -m comment --comment "comment5"
195
+ -A chain5 -p tcp -m tcp --dport 9 -j ACCEPT
196
+ -A chain5 -p tcp -m tcp --dport 10 -j ACCEPT
197
+ :chain6 ACCEPT [0:0]
198
+ -A chain6 -m comment --comment "comment6"
199
+ -A chain6 -p tcp -m tcp --dport 11 -j ACCEPT
200
+ -A chain6 -p tcp -m tcp --dport 12 -j ACCEPT
201
+ COMMIT
202
+ EOS
203
+ )
204
+ comparison = IPTables::TablesComparison.new(@iptables1, iptables2)
205
+
206
+ assert_equal(
207
+ false,
208
+ comparison.equal?,
209
+ 'Set of tables with one having an additional table should evaluate as unequal.'
210
+ )
211
+ assert_equal(
212
+ comparison.as_array,
213
+ [
214
+ "New table: table3",
215
+ ":chain5 ACCEPT",
216
+ ":chain6 ACCEPT",
217
+ "-A chain5 -m comment --comment \"comment5\"",
218
+ "-A chain5 -p tcp -m tcp --dport 9 -j ACCEPT",
219
+ "-A chain5 -p tcp -m tcp --dport 10 -j ACCEPT",
220
+ "-A chain6 -m comment --comment \"comment6\"",
221
+ "-A chain6 -p tcp -m tcp --dport 11 -j ACCEPT",
222
+ "-A chain6 -p tcp -m tcp --dport 12 -j ACCEPT"
223
+ ],
224
+ 'Array output of tables with one having an additional table should evaluate to known values.'
225
+ )
226
+ end
227
+
228
+ def test_differing_table
229
+ iptables2 = IPTables::Tables.new(
230
+ <<-EOS.dedent
231
+ *table1
232
+ :chain1 ACCEPT [0:0]
233
+ -A chain1 -m comment --comment "comment1"
234
+ -A chain1 -p tcp -m tcp --dport 11 -j ACCEPT
235
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
236
+ :chain2 ACCEPT [0:0]
237
+ -A chain2 -m comment --comment "comment2"
238
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
239
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
240
+ COMMIT
241
+ *table2
242
+ :chain3 ACCEPT [0:0]
243
+ -A chain3 -m comment --comment "comment3"
244
+ -A chain3 -p tcp -m tcp --dport 5 -j ACCEPT
245
+ -A chain3 -p tcp -m tcp --dport 6 -j ACCEPT
246
+ :chain4 ACCEPT [0:0]
247
+ -A chain4 -m comment --comment "comment4"
248
+ -A chain4 -p tcp -m tcp --dport 7 -j ACCEPT
249
+ -A chain4 -p tcp -m tcp --dport 8 -j ACCEPT
250
+ COMMIT
251
+ EOS
252
+ )
253
+ comparison = IPTables::TablesComparison.new(@iptables1, iptables2)
254
+
255
+ assert_equal(
256
+ false,
257
+ comparison.equal?,
258
+ 'Set of tables with one having a differing rule should evaluate as unequal.'
259
+ )
260
+ assert_equal(
261
+ comparison.as_array,
262
+ [
263
+ "Changed table: table1",
264
+ "Changed chain: chain1",
265
+ "-1: -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT",
266
+ "+1: -A chain1 -p tcp -m tcp --dport 11 -j ACCEPT"
267
+ ],
268
+ 'Array output of tables with one having a differing rule should evaluate to known values.'
269
+ )
270
+ end
271
+
272
+ def test_differing_chain_comments
273
+ iptables2 = IPTables::Tables.new(
274
+ <<-EOS.dedent
275
+ *table1
276
+ :chain1 ACCEPT [0:0]
277
+ -A chain1 -m comment --comment "changed comment1"
278
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
279
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
280
+ :chain2 ACCEPT [0:0]
281
+ -A chain2 -m comment --comment "comment2"
282
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
283
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
284
+ COMMIT
285
+ *table2
286
+ :chain3 ACCEPT [0:0]
287
+ -A chain3 -m comment --comment "comment3"
288
+ -A chain3 -p tcp -m tcp --dport 5 -j ACCEPT
289
+ -A chain3 -p tcp -m tcp --dport 6 -j ACCEPT
290
+ :chain4 ACCEPT [0:0]
291
+ -A chain4 -m comment --comment "comment4"
292
+ -A chain4 -p tcp -m tcp --dport 7 -j ACCEPT
293
+ -A chain4 -p tcp -m tcp --dport 8 -j ACCEPT
294
+ COMMIT
295
+ EOS
296
+ )
297
+ comparison = IPTables::TablesComparison.new(@iptables1, iptables2)
298
+
299
+ comparison.ignore_comments
300
+ assert(
301
+ comparison.equal?,
302
+ 'Set of tables that differ only by comments should evaluate as equal when ignoring comments.'
303
+ )
304
+ assert_equal(
305
+ comparison.as_array,
306
+ [],
307
+ 'Array output of tables that differ only by comments should evaluate as empty when ignoring comments.'
308
+ )
309
+
310
+ comparison.include_comments
311
+ assert_equal(
312
+ false,
313
+ comparison.equal?,
314
+ 'Set of tables that differ only by comments should evaluate as unequal when including comments.'
315
+ )
316
+ assert_equal(
317
+ comparison.as_array,
318
+ [
319
+ "Changed table: table1",
320
+ "Changed chain: chain1",
321
+ "-0: -A chain1 -m comment --comment \"comment1\"",
322
+ "+0: -A chain1 -m comment --comment \"changed comment1\""
323
+ ],
324
+ 'Array output of tables that differ only by comments should evaluate to known values when ignoring comments.'
325
+ )
326
+ end
327
+ end
328
+
329
+ class TestTableComparison < Test::Unit::TestCase
330
+ def setup
331
+ @test_iptables =
332
+ <<-EOS.dedent
333
+ *table1
334
+ :chain1 ACCEPT [0:0]
335
+ -A chain1 -m comment --comment "comment1"
336
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
337
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
338
+ :chain2 ACCEPT [0:0]
339
+ -A chain2 -m comment --comment "comment2"
340
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
341
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
342
+ COMMIT
343
+ EOS
344
+ @table1 = IPTables::Tables.new( @test_iptables ).tables['table1']
345
+ end
346
+
347
+ def test_invalid
348
+ assert_raise( RuntimeError, 'should require valid IPTables::Table object as first parameter' ) {
349
+ IPTables::TableComparison.new(nil, @table1)
350
+ }
351
+ assert_raise( RuntimeError, 'should require valid IPTables::Table object as second parameter' ) {
352
+ IPTables::TableComparison.new(@table1, nil)
353
+ }
354
+ end
355
+
356
+ def test_equal
357
+ test_iptables2 = IPTables::Tables.new( @test_iptables )
358
+ table2 = test_iptables2.tables['table1']
359
+ comparison = IPTables::TableComparison.new(@table1, table2)
360
+
361
+ assert(
362
+ comparison.equal?,
363
+ 'Tables with same chains should evaluate as equal.'
364
+ )
365
+
366
+ assert_equal(
367
+ [],
368
+ comparison.as_array,
369
+ 'When compared as array, tables with identical chains should return empty array.'
370
+ )
371
+ end
372
+
373
+ def test_unequal_name
374
+ test_iptables2 = IPTables::Tables.new(
375
+ <<-EOS.dedent
376
+ *table2
377
+ :chain1 ACCEPT [0:0]
378
+ -A chain1 -m comment --comment "comment1"
379
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
380
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
381
+ :chain2 ACCEPT [0:0]
382
+ -A chain2 -m comment --comment "comment2"
383
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
384
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
385
+ COMMIT
386
+ EOS
387
+ )
388
+ table2 = test_iptables2.tables['table2']
389
+ assert_raise( RuntimeError, 'compared table names should match' ) {
390
+ IPTables::TableComparison.new(@table1, table2)
391
+ }
392
+ end
393
+
394
+ def test_missing_chain
395
+ test_iptables2 = IPTables::Tables.new(
396
+ <<-EOS.dedent
397
+ *table1
398
+ :chain1 ACCEPT [0:0]
399
+ -A chain1 -m comment --comment "comment1"
400
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
401
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
402
+ COMMIT
403
+ EOS
404
+ )
405
+ table2 = test_iptables2.tables['table1']
406
+ comparison = IPTables::TableComparison.new(@table1, table2)
407
+
408
+ assert_equal(
409
+ false,
410
+ comparison.equal?,
411
+ 'Tables with missing chains should evaluate as unequal.'
412
+ )
413
+
414
+ assert_equal(
415
+ [ 'chain2' ],
416
+ comparison.missing,
417
+ 'Two compared tables with one chain missing should show this.'
418
+ )
419
+
420
+ assert_equal(
421
+ [
422
+ 'Changed table: table1',
423
+ 'Missing chain:',
424
+ ':chain2 ACCEPT',
425
+ '-A chain2 -m comment --comment "comment2"',
426
+ '-A chain2 -p tcp -m tcp --dport 3 -j ACCEPT',
427
+ '-A chain2 -p tcp -m tcp --dport 4 -j ACCEPT'
428
+ ],
429
+ comparison.as_array,
430
+ 'When compared as array, two compared tables with one chain missing should show this.'
431
+ )
432
+ end
433
+
434
+ def test_additional_chain
435
+ test_iptables2 = IPTables::Tables.new(
436
+ <<-EOS.dedent
437
+ *table1
438
+ :chain1 ACCEPT [0:0]
439
+ -A chain1 -m comment --comment "comment1"
440
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
441
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
442
+ :chain2 ACCEPT [0:0]
443
+ -A chain2 -m comment --comment "comment2"
444
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
445
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
446
+ :chain3 ACCEPT [0:0]
447
+ -A chain3 -m comment --comment "comment3"
448
+ -A chain3 -p tcp -m tcp --dport 5 -j ACCEPT
449
+ -A chain3 -p tcp -m tcp --dport 6 -j ACCEPT
450
+ COMMIT
451
+ EOS
452
+ )
453
+ table2 = test_iptables2.tables['table1']
454
+ comparison = IPTables::TableComparison.new(@table1, table2)
455
+
456
+ assert_equal(
457
+ false,
458
+ comparison.equal?,
459
+ 'Tables with additional chains should evaluate as unequal.'
460
+ )
461
+
462
+ assert_equal(
463
+ [ 'chain3' ],
464
+ comparison.new,
465
+ 'Two compared tables with one additional chain should show this.'
466
+ )
467
+
468
+ assert_equal(
469
+ [
470
+ 'Changed table: table1',
471
+ 'New chain:',
472
+ ':chain3 ACCEPT',
473
+ '-A chain3 -m comment --comment "comment3"',
474
+ '-A chain3 -p tcp -m tcp --dport 5 -j ACCEPT',
475
+ '-A chain3 -p tcp -m tcp --dport 6 -j ACCEPT'
476
+ ],
477
+ comparison.as_array,
478
+ 'When compared as array, two compared tables with one additional chain should show this.'
479
+ )
480
+ end
481
+
482
+ def test_differing_chain
483
+ test_iptables2 = IPTables::Tables.new(
484
+ <<-EOS.dedent
485
+ *table1
486
+ :chain1 ACCEPT [0:0]
487
+ -A chain1 -m comment --comment "comment1"
488
+ -A chain1 -p tcp -m tcp --dport 11 -j ACCEPT
489
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
490
+ :chain2 ACCEPT [0:0]
491
+ -A chain2 -m comment --comment "comment2"
492
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
493
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
494
+ COMMIT
495
+ EOS
496
+ )
497
+ table2 = test_iptables2.tables['table1']
498
+ comparison = IPTables::TableComparison.new(@table1, table2)
499
+
500
+ assert_equal(
501
+ false,
502
+ comparison.equal?,
503
+ 'Tables with additional chains should evaluate as unequal.'
504
+ )
505
+
506
+ assert_equal(
507
+ [
508
+ 'Changed table: table1',
509
+ 'Changed chain: chain1',
510
+ '-1: -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT',
511
+ '+1: -A chain1 -p tcp -m tcp --dport 11 -j ACCEPT'
512
+ ],
513
+ comparison.as_array,
514
+ 'When compared as array, two compared tables with one changed chain rule should show this.'
515
+ )
516
+ end
517
+
518
+ def test_differing_chain_comments
519
+ test_iptables2 = IPTables::Tables.new(
520
+ <<-EOS.dedent
521
+ *table1
522
+ :chain1 ACCEPT [0:0]
523
+ -A chain1 -m comment --comment "comment1"
524
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
525
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
526
+ :chain2 ACCEPT [0:0]
527
+ -A chain2 -m comment --comment "changed comment2"
528
+ -A chain2 -p tcp -m tcp --dport 3 -j ACCEPT
529
+ -A chain2 -p tcp -m tcp --dport 4 -j ACCEPT
530
+ COMMIT
531
+ EOS
532
+ )
533
+ table2 = test_iptables2.tables['table1']
534
+ comparison = IPTables::TableComparison.new(@table1, table2)
535
+
536
+ comparison.ignore_comments
537
+ assert(
538
+ comparison.equal?,
539
+ 'Tables with chains that differ only by comments should evaluate as equal when ignoring comments.'
540
+ )
541
+
542
+ comparison.include_comments
543
+ assert_equal(
544
+ false,
545
+ comparison.equal?,
546
+ 'Tables with chains that differ only by comments should evaluate as unequal when including comments.'
547
+ )
548
+ end
549
+ end
550
+
551
+ class TestChainComparison < Test::Unit::TestCase
552
+ def setup
553
+ @iptables_text =
554
+ <<-EOS.dedent
555
+ *table1
556
+ :chain1 ACCEPT [0:0]
557
+ -A chain1 -m comment --comment "comment1"
558
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
559
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
560
+ COMMIT
561
+ EOS
562
+ @table1_chain = IPTables::Tables.new(@iptables_text).tables['table1'].chains['chain1']
563
+ end
564
+
565
+ def test_invalid
566
+ assert_raise( RuntimeError, 'should require valid IPTables::Chain object as first parameter' ) {
567
+ IPTables::ChainComparison.new(nil, @table1_chain)
568
+ }
569
+ assert_raise( RuntimeError, 'should require valid IPTables::Chain object as second parameter' ) {
570
+ IPTables::ChainComparison.new(@table1_chain, nil)
571
+ }
572
+ end
573
+
574
+ def test_equal
575
+ test_iptables2 = IPTables::Tables.new(@iptables_text)
576
+ table2_chain = test_iptables2.tables['table1'].chains['chain1']
577
+ comparison = IPTables::ChainComparison.new(@table1_chain, table2_chain)
578
+
579
+ assert(
580
+ comparison.equal?,
581
+ 'Chains with same rules and policies should evaluate as equal.'
582
+ )
583
+
584
+ assert_equal(
585
+ [],
586
+ comparison.as_array,
587
+ 'When compared as array, chains with same rules and policies should return empty array.'
588
+ )
589
+ end
590
+
591
+ def test_unequal_names
592
+ test_iptables2 = IPTables::Tables.new(
593
+ <<-EOS.dedent
594
+ *table1
595
+ :chain2 ACCEPT [0:0]
596
+ -A chain2 -m comment --comment "comment1"
597
+ -A chain2 -p tcp -m tcp --dport 1 -j ACCEPT
598
+ -A chain2 -p tcp -m tcp --dport 2 -j ACCEPT
599
+ COMMIT
600
+ EOS
601
+ )
602
+ table2_chain = test_iptables2.tables['table1'].chains['chain2']
603
+ assert_raise( RuntimeError, 'first and second chain should have same name' ) {
604
+ IPTables::ChainComparison.new(@table1_chain, table2_chain)
605
+ }
606
+ end
607
+
608
+ def test_unequal_comments
609
+ test_iptables2 = IPTables::Tables.new(
610
+ <<-EOS.dedent
611
+ *table1
612
+ :chain1 ACCEPT [0:0]
613
+ -A chain1 -m comment --comment "differing comment1"
614
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
615
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
616
+ COMMIT
617
+ EOS
618
+ )
619
+ table2_chain = test_iptables2.tables['table1'].chains['chain1']
620
+ comparison = IPTables::ChainComparison.new(@table1_chain, table2_chain)
621
+
622
+ comparison.ignore_comments
623
+ assert(
624
+ comparison.equal?,
625
+ 'When ignoring comments, chains with same rules/policies but differing comments should evaluate as equal.'
626
+ )
627
+
628
+ comparison.include_comments
629
+ assert_equal(
630
+ false,
631
+ comparison.equal?,
632
+ 'When including comments, chains with same rules/policies but differing comments should evaluate as unequal.'
633
+ )
634
+ assert_equal(
635
+ {0=>'-A chain1 -m comment --comment "comment1"'},
636
+ comparison.missing,
637
+ 'When including comments, chains with same rules/policies but differing comments should have one missing rule.'
638
+ )
639
+ assert_equal(
640
+ {0=>'-A chain1 -m comment --comment "differing comment1"'},
641
+ comparison.new,
642
+ 'When including comments, chains with same rules/policies but differing comments should have one new rule.'
643
+ )
644
+
645
+ assert_equal(
646
+ [
647
+ 'Changed chain: chain1',
648
+ '-0: -A chain1 -m comment --comment "comment1"',
649
+ '+0: -A chain1 -m comment --comment "differing comment1"',
650
+ ],
651
+ comparison.as_array,
652
+ 'When compared as array, chains with changed rules should show this.'
653
+ )
654
+ end
655
+
656
+ def test_missing_rules
657
+ test_iptables2 = IPTables::Tables.new(
658
+ <<-EOS.dedent
659
+ *table1
660
+ :chain1 ACCEPT [0:0]
661
+ -A chain1 -m comment --comment "comment1"
662
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
663
+ COMMIT
664
+ EOS
665
+ )
666
+ table2_chain = test_iptables2.tables['table1'].chains['chain1']
667
+ comparison = IPTables::ChainComparison.new(@table1_chain, table2_chain)
668
+
669
+ assert_equal(
670
+ {
671
+ 2=>"-A chain1 -p tcp -m tcp --dport 2 -j ACCEPT"
672
+ },
673
+ comparison.missing,
674
+ 'Chains with missing rules should show this.'
675
+ )
676
+
677
+ assert_equal(
678
+ [
679
+ 'Changed chain: chain1',
680
+ '-2: -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT'
681
+ ],
682
+ comparison.as_array,
683
+ 'When compared as array, chains with missing rules should show this.'
684
+ )
685
+ end
686
+
687
+ def test_additional_rules
688
+ test_iptables2 = IPTables::Tables.new(
689
+ <<-EOS.dedent
690
+ *table1
691
+ :chain1 ACCEPT [0:0]
692
+ -A chain1 -m comment --comment "comment1"
693
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
694
+ -A chain1 -p tcp -m tcp --dport 11 -j ACCEPT
695
+ -A chain1 -p tcp -m tcp --dport 12 -j ACCEPT
696
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
697
+ COMMIT
698
+ EOS
699
+ )
700
+ table2_chain = test_iptables2.tables['table1'].chains['chain1']
701
+ comparison = IPTables::ChainComparison.new(@table1_chain, table2_chain)
702
+
703
+ assert_equal(
704
+ {
705
+ 2=>"-A chain1 -p tcp -m tcp --dport 11 -j ACCEPT",
706
+ 3=>"-A chain1 -p tcp -m tcp --dport 12 -j ACCEPT"
707
+ },
708
+ comparison.new,
709
+ 'Chains with additional rules should show this.'
710
+ )
711
+
712
+ assert_equal(
713
+ [
714
+ 'Changed chain: chain1',
715
+ '+2: -A chain1 -p tcp -m tcp --dport 11 -j ACCEPT',
716
+ '+3: -A chain1 -p tcp -m tcp --dport 12 -j ACCEPT'
717
+ ],
718
+ comparison.as_array,
719
+ 'When compared as array, chains with additional rules should show this.'
720
+ )
721
+ end
722
+
723
+ def test_new_policy
724
+ test_iptables2 = IPTables::Tables.new(
725
+ <<-EOS.dedent
726
+ *table1
727
+ :chain1 REJECT [0:0]
728
+ -A chain1 -m comment --comment "comment1"
729
+ -A chain1 -p tcp -m tcp --dport 1 -j ACCEPT
730
+ -A chain1 -p tcp -m tcp --dport 2 -j ACCEPT
731
+ COMMIT
732
+ EOS
733
+ )
734
+ table2_chain = test_iptables2.tables['table1'].chains['chain1']
735
+ comparison = IPTables::ChainComparison.new(@table1_chain, table2_chain)
736
+
737
+ assert(
738
+ comparison.new_policy?,
739
+ 'When compared, chains with new policy should show this.'
740
+ )
741
+
742
+ assert_equal(
743
+ [
744
+ 'Changed chain: chain1',
745
+ 'New policy: REJECT'
746
+ ],
747
+ comparison.as_array,
748
+ 'When compared as array, chains with new policy should show this.'
749
+ )
750
+ end
751
+ end