cisco_acl_intp 0.0.1

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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +13 -0
  5. data/.travis.yml +3 -0
  6. data/.yardopts +4 -0
  7. data/Gemfile +19 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +132 -0
  10. data/Rakefile +78 -0
  11. data/acl_examples/err-acl.txt +49 -0
  12. data/acl_examples/named-ext-acl.txt +12 -0
  13. data/acl_examples/named-std-acl.txt +6 -0
  14. data/acl_examples/numd-acl.txt +21 -0
  15. data/cisco_acl_intp.gemspec +31 -0
  16. data/lib/cisco_acl_intp/ace.rb +432 -0
  17. data/lib/cisco_acl_intp/ace_ip.rb +136 -0
  18. data/lib/cisco_acl_intp/ace_other_qualifiers.rb +102 -0
  19. data/lib/cisco_acl_intp/ace_port.rb +146 -0
  20. data/lib/cisco_acl_intp/ace_proto.rb +319 -0
  21. data/lib/cisco_acl_intp/ace_srcdst.rb +114 -0
  22. data/lib/cisco_acl_intp/ace_tcp_flags.rb +65 -0
  23. data/lib/cisco_acl_intp/acl.rb +272 -0
  24. data/lib/cisco_acl_intp/acl_base.rb +111 -0
  25. data/lib/cisco_acl_intp/parser.rb +3509 -0
  26. data/lib/cisco_acl_intp/parser.ry +1397 -0
  27. data/lib/cisco_acl_intp/scanner.rb +176 -0
  28. data/lib/cisco_acl_intp/scanner_special_token_handler.rb +66 -0
  29. data/lib/cisco_acl_intp/version.rb +5 -0
  30. data/lib/cisco_acl_intp.rb +9 -0
  31. data/spec/cisco_acl_intp/ace_ip_spec.rb +111 -0
  32. data/spec/cisco_acl_intp/ace_other_qualifier_spec.rb +63 -0
  33. data/spec/cisco_acl_intp/ace_port_spec.rb +214 -0
  34. data/spec/cisco_acl_intp/ace_proto_spec.rb +200 -0
  35. data/spec/cisco_acl_intp/ace_spec.rb +605 -0
  36. data/spec/cisco_acl_intp/ace_srcdst_spec.rb +296 -0
  37. data/spec/cisco_acl_intp/ace_tcp_flags_spec.rb +38 -0
  38. data/spec/cisco_acl_intp/acl_spec.rb +523 -0
  39. data/spec/cisco_acl_intp/cisco_acl_intp_spec.rb +7 -0
  40. data/spec/cisco_acl_intp/parser_spec.rb +53 -0
  41. data/spec/cisco_acl_intp/scanner_spec.rb +122 -0
  42. data/spec/conf/extacl_objgrp_token_seq.yml +36 -0
  43. data/spec/conf/extacl_token_seq.yml +88 -0
  44. data/spec/conf/extended_acl.yml +226 -0
  45. data/spec/conf/scanner_spec_data.yml +120 -0
  46. data/spec/conf/single_tokens.yml +235 -0
  47. data/spec/conf/stdacl_token_seq.yml +8 -0
  48. data/spec/conf/tokens1.yml +158 -0
  49. data/spec/conf/tokens2.yml +206 -0
  50. data/spec/parser_fullfill_patterns.rb +145 -0
  51. data/spec/spec_helper.rb +54 -0
  52. data/tools/check_acl.rb +48 -0
  53. metadata +159 -0
@@ -0,0 +1,605 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe StandardAce do
5
+ describe '#to_s' do
6
+ context 'Normal case' do
7
+
8
+ it 'should be permit action and set ip/wildcard' do
9
+ sa = StandardAce.new(
10
+ action: 'permit',
11
+ src: {
12
+ ipaddr: '192.168.15.15',
13
+ wildcard: '0.0.7.6'
14
+ }
15
+ )
16
+ sa.to_s.should be_aclstr('permit 192.168.8.9 0.0.7.6')
17
+ end
18
+
19
+ it 'should be deny action and set ip/wildcard' do
20
+ sa = StandardAce.new(
21
+ action: 'deny',
22
+ src: {
23
+ ipaddr: '192.168.15.15',
24
+ wildcard: '0.0.0.127'
25
+ }
26
+ )
27
+ sa.to_s.should be_aclstr('deny 192.168.15.0 0.0.0.127')
28
+ end
29
+
30
+ it 'should be able set with AceSrcDstSpec object' do
31
+ asds = AceSrcDstSpec.new(
32
+ ipaddr: '192.168.3.144',
33
+ wildcard: '0.0.0.127'
34
+ )
35
+ sa = StandardAce.new(
36
+ action: 'permit',
37
+ src: asds
38
+ )
39
+ sa.to_s.should be_aclstr('permit 192.168.3.128 0.0.0.127')
40
+ end
41
+
42
+ end
43
+
44
+ context 'Argument error case' do
45
+
46
+ it 'should be rased exception when :action not specified' do
47
+ lambda do
48
+ StandardAce.new(
49
+ src: {
50
+ ipaddr: '192.168.3.3',
51
+ wildcard: '0.0.0.127'
52
+ }
53
+ )
54
+ end.should raise_error(AclArgumentError)
55
+ end
56
+
57
+ end
58
+ end
59
+
60
+ describe '#matches' do
61
+ before do
62
+ @sa = StandardAce.new(
63
+ action: 'permit',
64
+ src: {
65
+ ipaddr: '192.168.15.15',
66
+ wildcard: '0.0.7.6'
67
+ }
68
+ )
69
+ @ip_match = '192.168.9.11'
70
+ @ip_unmatch = '192.168.9.12'
71
+ end
72
+
73
+ it 'shoud be true with match ip addr' do
74
+ @sa.matches?(
75
+ src_ip: @ip_match
76
+ ).should be_true
77
+ end
78
+
79
+ it 'should be false with unmatch ip addr' do
80
+ @sa.matches?(
81
+ src_ip: @ip_unmatch
82
+ ).should be_false
83
+ end
84
+
85
+ it 'should raise error when not specified ip_src' do
86
+ lambda do
87
+ @sa.matches?(
88
+ dst_ip: @ip_match)
89
+ end.should raise_error(AclArgumentError)
90
+ end
91
+
92
+ end
93
+ end
94
+
95
+ describe ExtendedAce do
96
+ describe '#to_s' do
97
+ context 'Normal case' do
98
+ before do
99
+ @src = AceSrcDstSpec.new(
100
+ ipaddr: '192.168.15.15',
101
+ wildcard: '0.0.7.6'
102
+ )
103
+ @dst = AceSrcDstSpec.new(
104
+ ipaddr: '192.168.30.3',
105
+ wildcard: '0.0.0.0',
106
+ operator: 'range',
107
+ begin_port: AceTcpProtoSpec.new(
108
+ number: 1_024
109
+ ),
110
+ end_port: AceTcpProtoSpec.new(
111
+ number: 65_535
112
+ )
113
+ )
114
+ end
115
+
116
+ it 'should be protocol tcp, action permit' do
117
+ ea = ExtendedAce.new(
118
+ action: 'permit',
119
+ protocol: 'tcp',
120
+ src: @src,
121
+ dst: @dst
122
+ )
123
+ ea.to_s.should be_aclstr(
124
+ 'permit tcp 192.168.8.9 0.0.7.6 host 192.168.30.3 range 1024 65535'
125
+ )
126
+ end
127
+
128
+ it 'should be protocol tcp, action deny' do
129
+ ea = ExtendedAce.new(
130
+ action: 'deny',
131
+ protocol: 'tcp',
132
+ src: @src,
133
+ dst: @dst
134
+ )
135
+ ea.to_s.should be_aclstr(
136
+ 'deny tcp 192.168.8.9 0.0.7.6 host 192.168.30.3 range 1024 65535'
137
+ )
138
+ end
139
+
140
+ end
141
+
142
+ context 'Argument error case' do
143
+ before do
144
+ @src = AceSrcDstSpec.new(
145
+ ipaddr: '192.168.15.15',
146
+ wildcard: '0.0.7.6'
147
+ )
148
+ @dst = AceSrcDstSpec.new(
149
+ ipaddr: '192.168.30.3',
150
+ wildcard: '0.0.0.0',
151
+ operator: 'range',
152
+ begin_port: AceTcpProtoSpec.new(
153
+ number: 1_024
154
+ ),
155
+ end_port: AceTcpProtoSpec.new(
156
+ number: 65_535
157
+ )
158
+ )
159
+ end
160
+
161
+ it 'should be rased exception when :action not specified' do
162
+ lambda do
163
+ ExtendedAce.new(
164
+ protocol: 'tcp',
165
+ src: @src,
166
+ dst: @dst
167
+ )
168
+ end.should raise_error(AclArgumentError)
169
+ end
170
+
171
+ it 'should be rased exception when :protocol not specified' do
172
+ lambda do
173
+ ExtendedAce.new(
174
+ action: 'deny',
175
+ src: @src,
176
+ dst: @dst
177
+ )
178
+ end.should raise_error(AclArgumentError)
179
+ end
180
+
181
+ it 'should be rased exception when :src not specified' do
182
+ lambda do
183
+ ExtendedAce.new(
184
+ action: 'deny',
185
+ protocol: 'tcp',
186
+ dst: @dst
187
+ )
188
+ end.should raise_error(AclArgumentError)
189
+ end
190
+
191
+ it 'should be rased exception when :dst not specified' do
192
+ lambda do
193
+ ExtendedAce.new(
194
+ action: 'deny',
195
+ protocol: 'tcp',
196
+ src: @src
197
+ )
198
+ end.should raise_error(AclArgumentError)
199
+ end
200
+
201
+ end
202
+ end
203
+
204
+ describe '#matches?' do
205
+ context 'tcp src/dst ip/port full spec test' do
206
+ before do
207
+ src = AceSrcDstSpec.new(
208
+ ipaddr: '192.168.15.15',
209
+ wildcard: '0.0.7.6',
210
+ operator: 'gt',
211
+ port: AceTcpProtoSpec.new(
212
+ number: 32_767
213
+ )
214
+ )
215
+ dst = AceSrcDstSpec.new(
216
+ ipaddr: '192.168.30.3',
217
+ wildcard: '0.0.0.0',
218
+ operator: 'range',
219
+ begin_port: AceTcpProtoSpec.new(
220
+ number: 1_024
221
+ ),
222
+ end_port: AceTcpProtoSpec.new(
223
+ number: 65_535
224
+ )
225
+ )
226
+ @ea = ExtendedAce.new(
227
+ action: 'permit',
228
+ protocol: 'tcp',
229
+ src: src,
230
+ dst: dst
231
+ )
232
+ end # before
233
+
234
+ ## generate test pattern data
235
+ data_table = {
236
+ protocol_match: 'tcp',
237
+ protocol_unmatch: 'udp',
238
+ src_ip_match: '192.168.9.11',
239
+ src_ip_unmatch: '192.168.9.12',
240
+ src_port_match: 32_768,
241
+ src_port_unmatch: 8_080,
242
+ dst_ip_match: '192.168.30.3',
243
+ dst_ip_unmatch: '192.168.30.4',
244
+ dst_port_match: 3_366,
245
+ dst_port_unmatch: 100
246
+ }
247
+
248
+ bit = 5
249
+ test_data = [
250
+ :dst_port,
251
+ :dst_ip,
252
+ :src_port,
253
+ :src_ip,
254
+ :protocol
255
+ ]
256
+
257
+ tests = []
258
+ (0..(2**bit - 1)).each do |num|
259
+ opts = {}
260
+ flag = 1
261
+ (0...bit).each do |b|
262
+ pstr = ((num & flag) == 0 ? '_match' : '_unmatch')
263
+ key = test_data[b].to_s.concat(pstr)
264
+ opts[test_data[b]] = data_table[key.to_sym]
265
+ flag = flag << 1
266
+ end
267
+ tests.push(
268
+ opts: opts,
269
+ res: num > 0 ? false : true
270
+ )
271
+ end
272
+
273
+ tests.each do |each|
274
+ # run test
275
+ it "should be #{each[:res]}, \
276
+ when #{each[:opts][:protocol]};\
277
+ #{each[:opts][:src_ip]}/#{each[:opts][:src_port]} > \
278
+ #{each[:opts][:dst_ip]}/#{each[:opts][:dst_port]}" do
279
+ if each[:res]
280
+ @ea.matches?(each[:opts]).should be_true
281
+ else
282
+ @ea.matches?(each[:opts]).should be_false
283
+ end
284
+ end # it
285
+ end # tests.each
286
+
287
+ end # context full spec test
288
+
289
+ context 'ANY ip/port port exists case' do
290
+ before do
291
+ ip_any = AceIpSpec.new(
292
+ ipaddr: '0.0.0.0',
293
+ wildcard: '255.255.255.255'
294
+ )
295
+ port_any = AcePortSpec.new(
296
+ operator: 'any'
297
+ )
298
+ src_ip = AceIpSpec.new(
299
+ ipaddr: '192.168.15.15',
300
+ wildcard: '0.0.7.6'
301
+ )
302
+ src_port = AcePortSpec.new(
303
+ operator: 'gt',
304
+ port: AceTcpProtoSpec.new(
305
+ number: 32_767
306
+ )
307
+ )
308
+
309
+ dst_ip = AceIpSpec.new(
310
+ ipaddr: '192.168.30.3',
311
+ wildcard: '0.0.0.0'
312
+ )
313
+ dst_port = AcePortSpec.new(
314
+ operator: 'range',
315
+ begin_port: AceTcpProtoSpec.new(
316
+ number: 1_024
317
+ ),
318
+ end_port: AceTcpProtoSpec.new(
319
+ number: 65_535
320
+ )
321
+ )
322
+
323
+ @src0 = AceSrcDstSpec.new(
324
+ ip_spec: src_ip,
325
+ port_spec: src_port
326
+ )
327
+ @src1 = AceSrcDstSpec.new(
328
+ ip_spec: ip_any,
329
+ port_spec: src_port
330
+ )
331
+ @src2 = AceSrcDstSpec.new(
332
+ ip_spec: src_ip,
333
+ port_spec: port_any
334
+ )
335
+ @dst0 = AceSrcDstSpec.new(
336
+ ip_spec: dst_ip,
337
+ port_spec: dst_port
338
+ )
339
+ @dst1 = AceSrcDstSpec.new(
340
+ ip_spec: ip_any,
341
+ port_spec: dst_port
342
+ )
343
+ @dst2 = AceSrcDstSpec.new(
344
+ ip_spec: dst_ip,
345
+ port_spec: port_any
346
+ )
347
+
348
+ @src_ip_match = '192.168.9.11'
349
+ @src_ip_unmatch = '192.168.9.12'
350
+ @src_port_match = 32_768
351
+ @src_port_unmatch = 8_080
352
+ @dst_ip_match = '192.168.30.3'
353
+ @dst_ip_unmatch = '192.168.30.4'
354
+ @dst_port_match = 3_366
355
+ @dst_port_unmatch = 100
356
+ end
357
+
358
+ it 'should be true when any source ip' do
359
+ ea = ExtendedAce.new(
360
+ action: 'permit',
361
+ protocol: 'tcp',
362
+ src: @src1,
363
+ dst: @dst0
364
+ )
365
+ ea.matches?(
366
+ protocol: 'tcp',
367
+ src_ip: @src_ip_match,
368
+ src_port: @src_port_match,
369
+ dst_ip: @dst_ip_match,
370
+ dst_port: @dst_port_match
371
+ ).should be_true
372
+ ea.matches?(
373
+ protocol: 'tcp',
374
+ src_ip: @src_ip_unmatch,
375
+ src_port: @src_port_match,
376
+ dst_ip: @dst_ip_match,
377
+ dst_port: @dst_port_match
378
+ ).should be_true
379
+ end
380
+
381
+ it 'should be false when any source ip and unmatch port' do
382
+ ea = ExtendedAce.new(
383
+ action: 'permit',
384
+ protocol: 'tcp',
385
+ src: @src1,
386
+ dst: @dst0
387
+ )
388
+ ea.matches?(
389
+ protocol: 'tcp',
390
+ src_ip: @src_ip_match,
391
+ src_port: @src_port_unmatch,
392
+ dst_ip: @dst_ip_match,
393
+ dst_port: @dst_port_match
394
+ ).should be_false
395
+ ea.matches?(
396
+ protocol: 'tcp',
397
+ src_ip: @src_ip_unmatch,
398
+ src_port: @src_port_unmatch,
399
+ dst_ip: @dst_ip_match,
400
+ dst_port: @dst_port_match
401
+ ).should be_false
402
+ end
403
+
404
+ it 'should be true when any source port' do
405
+ ea = ExtendedAce.new(
406
+ action: 'permit',
407
+ protocol: 'tcp',
408
+ src: @src2,
409
+ dst: @dst0
410
+ )
411
+ ea.matches?(
412
+ protocol: 'tcp',
413
+ src_ip: @src_ip_match,
414
+ src_port: @src_port_match,
415
+ dst_ip: @dst_ip_match,
416
+ dst_port: @dst_port_match
417
+ ).should be_true
418
+ ea.matches?(
419
+ protocol: 'tcp',
420
+ src_ip: @src_ip_match,
421
+ src_port: @src_port_unmatch,
422
+ dst_ip: @dst_ip_match,
423
+ dst_port: @dst_port_match
424
+ ).should be_true
425
+ end
426
+
427
+ it 'should be false when any source port and unmatch ip' do
428
+ ea = ExtendedAce.new(
429
+ action: 'permit',
430
+ protocol: 'tcp',
431
+ src: @src2,
432
+ dst: @dst0
433
+ )
434
+ ea.matches?(
435
+ protocol: 'tcp',
436
+ src_ip: @src_ip_unmatch,
437
+ src_port: @src_port_match,
438
+ dst_ip: @dst_ip_match,
439
+ dst_port: @dst_port_match
440
+ ).should be_false
441
+ ea.matches?(
442
+ protocol: 'tcp',
443
+ src_ip: @src_ip_unmatch,
444
+ src_port: @src_port_unmatch,
445
+ dst_ip: @dst_ip_match,
446
+ dst_port: @dst_port_match
447
+ ).should be_false
448
+ end
449
+
450
+ it 'should be true when any destination ip' do
451
+ ea = ExtendedAce.new(
452
+ action: 'permit',
453
+ protocol: 'tcp',
454
+ src: @src0,
455
+ dst: @dst1
456
+ )
457
+ ea.matches?(
458
+ protocol: 'tcp',
459
+ src_ip: @src_ip_match,
460
+ src_port: @src_port_match,
461
+ dst_ip: @dst_ip_match,
462
+ dst_port: @dst_port_match
463
+ ).should be_true
464
+ ea.matches?(
465
+ protocol: 'tcp',
466
+ src_ip: @src_ip_match,
467
+ src_port: @src_port_match,
468
+ dst_ip: @dst_ip_unmatch,
469
+ dst_port: @dst_port_match
470
+ ).should be_true
471
+ end
472
+
473
+ it 'should be false when any destination ip and unmatch port' do
474
+ ea = ExtendedAce.new(
475
+ action: 'permit',
476
+ protocol: 'tcp',
477
+ src: @src0,
478
+ dst: @dst1
479
+ )
480
+ ea.matches?(
481
+ protocol: 'tcp',
482
+ src_ip: @src_ip_match,
483
+ src_port: @src_port_match,
484
+ dst_ip: @dst_ip_match,
485
+ dst_port: @dst_port_unmatch
486
+ ).should be_false
487
+ ea.matches?(
488
+ protocol: 'tcp',
489
+ src_ip: @src_ip_match,
490
+ src_port: @src_port_match,
491
+ dst_ip: @dst_ip_unmatch,
492
+ dst_port: @dst_port_unmatch
493
+ ).should be_false
494
+ end
495
+
496
+ it 'should be true when any destination port' do
497
+ ea = ExtendedAce.new(
498
+ action: 'permit',
499
+ protocol: 'tcp',
500
+ src: @src0,
501
+ dst: @dst2
502
+ )
503
+ ea.matches?(
504
+ protocol: 'tcp',
505
+ src_ip: @src_ip_match,
506
+ src_port: @src_port_match,
507
+ dst_ip: @dst_ip_match,
508
+ dst_port: @dst_port_match
509
+ ).should be_true
510
+ ea.matches?(
511
+ protocol: 'tcp',
512
+ src_ip: @src_ip_match,
513
+ src_port: @src_port_match,
514
+ dst_ip: @dst_ip_match,
515
+ dst_port: @dst_port_unmatch
516
+ ).should be_true
517
+ end
518
+
519
+ it 'should be false when any destination port and unmatch ip' do
520
+ ea = ExtendedAce.new(
521
+ action: 'permit',
522
+ protocol: 'tcp',
523
+ src: @src0,
524
+ dst: @dst2
525
+ )
526
+ ea.matches?(
527
+ protocol: 'tcp',
528
+ src_ip: @src_ip_match,
529
+ src_port: @src_port_match,
530
+ dst_ip: @dst_ip_unmatch,
531
+ dst_port: @dst_port_match
532
+ ).should be_false
533
+ ea.matches?(
534
+ protocol: 'tcp',
535
+ src_ip: @src_ip_match,
536
+ src_port: @src_port_match,
537
+ dst_ip: @dst_ip_unmatch,
538
+ dst_port: @dst_port_unmatch
539
+ ).should be_false
540
+ end
541
+ end # context exists any ip/port
542
+
543
+ end # describe matches?
544
+
545
+ end # describe ExtendedAce
546
+
547
+ describe RemarkAce do
548
+ describe '#to_s' do
549
+ it 'should be remark string' do
550
+ rmk = RemarkAce.new(' foo-bar _ baz @@ COMMENT')
551
+ rmk.to_s.should eq ' remark foo-bar _ baz @@ COMMENT'
552
+ end
553
+ end
554
+ describe '#matches?' do
555
+ it 'should be always false' do
556
+ rmk = RemarkAce.new('asdfjklj;')
557
+ rmk.matches?(
558
+ src_ip: '192.168.4.4',
559
+ dst_ip: '172.30.240.33'
560
+ ).should be_false
561
+ # with empty argments
562
+ rmk.matches?.should be_false
563
+ end
564
+ end
565
+ end
566
+
567
+ describe EvaluateAce do
568
+ describe '#to_s' do
569
+ it 'should be evaluate term' do
570
+ evl = EvaluateAce.new(
571
+ recursive_name: 'foobar_baz'
572
+ )
573
+ evl.to_s.should be_aclstr('evaluate foobar_baz')
574
+ end
575
+
576
+ it 'raise error if not specified recursive name' do
577
+ lambda do
578
+ EvaluateAce.new(
579
+ number: 30
580
+ )
581
+ end.should raise_error(AclArgumentError)
582
+ end
583
+ end
584
+ describe '#matches?' do
585
+ it 'should be always false' do
586
+ pending('not implemented yet')
587
+
588
+ evl = EvaluateAce.new(
589
+ recursive_name: 'asdf_0-98'
590
+ )
591
+ evl.matches?(
592
+ src_ip: '192.168.4.4',
593
+ dst_ip: '172.30.240.33'
594
+ ).should be_false
595
+ # with empty argments
596
+ evl.matches?.should be_false
597
+ end
598
+ end
599
+ end
600
+
601
+ ### Local variables:
602
+ ### mode: Ruby
603
+ ### coding: utf-8-unix
604
+ ### indent-tabs-mode: nil
605
+ ### End: