iptables-ruby 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
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