conpar 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +19 -0
  2. data/.travis.yml +7 -0
  3. data/Gemfile +4 -0
  4. data/Guardfile +24 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +43 -0
  7. data/Rakefile +25 -0
  8. data/conpar.gemspec +30 -0
  9. data/lib/conpar.rb +18 -0
  10. data/lib/conpar/_all.rb +9 -0
  11. data/lib/conpar/configuration.rb +19 -0
  12. data/lib/conpar/directive.rb +30 -0
  13. data/lib/conpar/directive/_all.rb +9 -0
  14. data/lib/conpar/directive/access_list.rb +33 -0
  15. data/lib/conpar/directive/access_list/_all.rb +11 -0
  16. data/lib/conpar/directive/access_list/base.rb +20 -0
  17. data/lib/conpar/directive/access_list/ether_type.rb +43 -0
  18. data/lib/conpar/directive/access_list/extended.rb +56 -0
  19. data/lib/conpar/directive/access_list/standard.rb +42 -0
  20. data/lib/conpar/directive/access_list/unknown_type.rb +16 -0
  21. data/lib/conpar/directive/access_list/web_type.rb +42 -0
  22. data/lib/conpar/directive/base.rb +52 -0
  23. data/lib/conpar/directive/comment.rb +13 -0
  24. data/lib/conpar/directive/empty.rb +12 -0
  25. data/lib/conpar/document.rb +24 -0
  26. data/lib/conpar/version.rb +3 -0
  27. data/spec/conpar_spec.rb +20 -0
  28. data/spec/lib/.keep +0 -0
  29. data/spec/lib/directive/access_list/base_spec.rb +5 -0
  30. data/spec/lib/directive/access_list/ether_type_spec.rb +32 -0
  31. data/spec/lib/directive/access_list/extended_spec.rb +71 -0
  32. data/spec/lib/directive/access_list/standard_spec.rb +32 -0
  33. data/spec/lib/directive/access_list/unknown_spec.rb +8 -0
  34. data/spec/lib/directive/access_list/web_type_spec.rb +27 -0
  35. data/spec/lib/directive/access_list_spec.rb +17 -0
  36. data/spec/lib/directive/base_spec.rb +46 -0
  37. data/spec/lib/directive/comment_spec.rb +13 -0
  38. data/spec/lib/directive/empty_spec.rb +13 -0
  39. data/spec/lib/directive_spec.rb +9 -0
  40. data/spec/lib/document_spec.rb +98 -0
  41. data/spec/samples/basic +3 -0
  42. data/spec/samples/sample2 +3 -0
  43. data/spec/samples/sample3 +4 -0
  44. data/spec/samples/sample4 +5 -0
  45. data/spec/samples/sample5 +8 -0
  46. data/spec/spec_helper.rb +7 -0
  47. metadata +247 -0
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ .DS_Store
2
+ *.gem
3
+ *.rbc
4
+ *.swp
5
+ .bundle
6
+ .config
7
+ .yardoc
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ script: "bundle exec rake"
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in conpar.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara features specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Ryan A. Johnson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Conpar [![Build Status](https://travis-ci.org/CITguy/conpar.png?branch=master)](https://travis-ci.org/CITguy/conpar)
2
+
3
+ Conpar (short for **Con**figuration **Par**ser) is designed to be a flexible and extendable library for parsing through a Firewall configuration file by tokenizing the configuration directives into ruby objects for evaluation.
4
+
5
+ **NOTE**: This gem is still in a very _alpha_ state. It currently only knows how to tokenize Comments and Access Lists for Cisco ASA firewall configurations.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'conpar'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install conpar
20
+
21
+ ## Supported Rubies
22
+
23
+ **MRE 1.9.2, 1.9.3, 2.0.0, 2.1.0**
24
+
25
+ Versions prior to 1.9.2 will **NOT** be supported with this gem.
26
+ Since 1.8.7 and ree are EOL, they no longer desirable to code against.
27
+
28
+ ## Usage
29
+
30
+ Conpar::Document.parse(config_string) #=> Array
31
+
32
+ The returned array will have parsed every line in the configuration string into Conpar::Directive (or descendant) objects.
33
+
34
+ ## Configuration
35
+ **NOTE:** While configuration _is_ functional, it is **not** advised to do any configuration for the current version of this gem.
36
+
37
+ ## Contributing
38
+
39
+ 1. Fork it
40
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
41
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
42
+ 4. Push to the branch (`git push origin my-new-feature`)
43
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new do |t|
6
+ t.rspec_opts = %w[-c]
7
+ end
8
+
9
+ task default: :spec
10
+ task test: :spec
11
+
12
+ task :console do
13
+ require 'irb'
14
+ require 'irb/completion'
15
+ require 'conpar'
16
+ ARGV.clear
17
+ IRB.start
18
+ end
19
+
20
+ task :pry do
21
+ require 'pry'
22
+ require 'conpar'
23
+ ARGV.clear
24
+ Pry.start
25
+ end
data/conpar.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'conpar/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "conpar"
8
+ spec.version = Conpar::VERSION
9
+ spec.authors = ["Ryan A. Johnson"]
10
+ spec.email = ["ryan.johnson@rackspace.com"]
11
+ spec.summary = %q{Firewall CONfig PARser}
12
+ spec.description = %q{Full-featured firewall configuration parser library.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rspec", ">= 2.4.0"
23
+ spec.add_development_dependency "rake"
24
+
25
+ spec.add_development_dependency "yard"
26
+ spec.add_development_dependency "redcarpet"
27
+ spec.add_development_dependency "guard"
28
+ spec.add_development_dependency "guard-rspec"
29
+ spec.add_development_dependency "pry"
30
+ end
data/lib/conpar.rb ADDED
@@ -0,0 +1,18 @@
1
+ require "conpar/_all"
2
+
3
+ # Gem Root Namespace
4
+ module Conpar
5
+ extend self
6
+
7
+ # Modify configuration for library
8
+ # @yield [Configuration]
9
+ def configure
10
+ yield self.config if block_given?
11
+ end
12
+
13
+
14
+ # @return [Configuration]
15
+ def config
16
+ @@config ||= Configuration.new
17
+ end#config
18
+ end
@@ -0,0 +1,9 @@
1
+ # Require all Conpar Classes
2
+ %w[
3
+ version
4
+ directive
5
+ configuration
6
+ document
7
+ ].each do |src|
8
+ require_relative "#{src}"
9
+ end
@@ -0,0 +1,19 @@
1
+ module Conpar
2
+ # Class for holding configuration values
3
+ class Configuration
4
+ # @!attribute [rw]
5
+ # @return [Module]
6
+ # Module Namespace to use with directive matching
7
+ # Namespace::MyModule.match_with must be defined
8
+ attr_accessor :parser
9
+
10
+
11
+ def initialize
12
+ # Set default values
13
+ @parser = Conpar::Directive
14
+
15
+ # return config object after default values applied
16
+ self
17
+ end#initialize
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ require 'conpar/directive/_all'
2
+
3
+ module Conpar
4
+ # Namespace for any type of configuration directive
5
+ module Directive
6
+ extend self
7
+
8
+ # @param [String] line
9
+ # This is the current line being iterated
10
+ # @param [Hash] options (common options among all Directives)
11
+ # @option [Integer] line_number
12
+ # On which line number does the directive appear
13
+ def new(line, options={})
14
+ [
15
+ Empty,
16
+ Comment,
17
+ # Additional directive classes/modules below
18
+ AccessList
19
+ ].each do |klass|
20
+ if line =~ klass::SIGNATURE
21
+ return klass.new(line, options)
22
+ end
23
+ end
24
+
25
+ # Catch-all Directive
26
+ return Base.new(line, options)
27
+ end#new
28
+
29
+ end#Directive
30
+ end
@@ -0,0 +1,9 @@
1
+ # Require all Directive Classes
2
+ %w[
3
+ base
4
+ empty
5
+ comment
6
+ access_list
7
+ ].each do |src|
8
+ require_relative "#{src}"
9
+ end
@@ -0,0 +1,33 @@
1
+ require 'conpar/directive/access_list/_all'
2
+
3
+ module Conpar
4
+ module Directive
5
+ # Module for ACL line classes
6
+ # See http://www.cisco.com/c/en/us/td/docs/security/asa/asa91/configuration/general/asa_91_general_config/acl_overview.html
7
+ module AccessList
8
+ extend self
9
+
10
+ SIGNATURE = Base::SIGNATURE
11
+
12
+ def new(line, options={})
13
+ # Shallow ACL Test - Is the line any type of ACL?
14
+ if line =~ SIGNATURE
15
+ # Deeper ACL Testing - Which type of ACL is it?
16
+ [
17
+ Standard,
18
+ Extended,
19
+ WebType,
20
+ EtherType
21
+ ].each do |klass|
22
+ if line =~ klass::SIGNATURE
23
+ return klass.new(line, options)
24
+ end
25
+ end
26
+ # If no match yet, use base ACL type
27
+ return UnknownType.new(line, options)
28
+ end
29
+ end#new
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ # Require all AccessList Classes
2
+ %w[
3
+ base
4
+ standard
5
+ extended
6
+ ether_type
7
+ web_type
8
+ unknown_type
9
+ ].each do |src|
10
+ require_relative "#{src}"
11
+ end
@@ -0,0 +1,20 @@
1
+ module Conpar
2
+ module Directive
3
+ module AccessList
4
+ # Base class for all AccessList classes
5
+ class Base < Conpar::Directive::Base
6
+ SIGNATURE = /^(access-list)\b/
7
+
8
+ def initialize(content="", options={})
9
+ super
10
+ @ilk = :access_list
11
+ @sub_ilk = :base
12
+ end#initialize
13
+
14
+ def to_s
15
+ @content
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,43 @@
1
+ module Conpar
2
+ module Directive
3
+ module AccessList
4
+ # Class that maps directly to Cisco ethertype ACL definition
5
+ # See http://www.cisco.com/c/en/us/td/docs/security/asa/asa91/configuration/general/asa_91_general_config/acl_ethertype.html
6
+ class EtherType < Base
7
+ SIGNATURE = /^(access-list)\b.*\b(ethertype)\b/i
8
+
9
+ def initialize(content="", options={})
10
+ super
11
+
12
+ @sub_ilk = "ethertype"
13
+
14
+ parse_regex = %r/
15
+ (access-list)\s* # Directive Signature
16
+ (?<name>[\-\w]+)\s* # ACL Name
17
+ (?<type>(ethertype))\s* # Ethertype ACL Type
18
+ (?<permission>(permit|deny))?\s* # permit or deny
19
+ (?<rule>.+)
20
+ /x
21
+ @match_data = parse_regex.match(@content)
22
+
23
+ self
24
+ end#initialize
25
+
26
+ # Method for each match name in the parsed match data (see regex above)
27
+ [ :name,
28
+ :permission,
29
+ :rule
30
+ ].each do |m|
31
+ define_method(m) do
32
+ begin
33
+ @match_data[m]
34
+ rescue IndexError
35
+ nil
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end#Conpar
@@ -0,0 +1,56 @@
1
+ module Conpar
2
+ module Directive
3
+ module AccessList
4
+ # Class that maps directly to Cisco extended ACL definition
5
+ # See http://www.cisco.com/c/en/us/td/docs/security/asa/asa91/configuration/general/asa_91_general_config/acl_extended.html
6
+ class Extended < Base
7
+ SIGNATURE = /^(access-list)\b.*\b(extended)\b/i
8
+
9
+ def initialize(content="", options={})
10
+ super
11
+
12
+ @sub_ilk = "extended"
13
+
14
+ # host (ipaddr) mask (ipaddr)
15
+ ipaddr_regex = %r/
16
+ (?<octet>1?[0-9]{1,2}|2([0-4][0-9]|5[0-5]))\.\k<octet>\.\k<octet>\.\k<octet>
17
+ /x
18
+
19
+ # access-list access_list_name [line line_number] extended
20
+ # {deny | permit} protocol_argument source_address_argument dest_address_argument
21
+ # [log [[level] [interval secs] | disable | default]]
22
+ # [inactive | time-range time_range_name]
23
+ parse_regex = %r/
24
+ (access-list)\s* # Directive Signature
25
+ (?<name>[\-\w]+)\s* # ACL Name
26
+ (line\s+(?<line>\d+))?\s* # (optional) line number
27
+ (?<type>extended)\s* # ACL type
28
+ (?<permission>(permit|deny))?\s* # permit or deny
29
+ (?<protocol>\w+)\s* # Protocol Argument
30
+ (?<rule>.+) # Everything else on line
31
+ $/x
32
+ @match_data = parse_regex.match(@content)
33
+
34
+ self
35
+ end#initialize
36
+
37
+ # Method for each match name in the parsed match data (see regex above)
38
+ [ :name,
39
+ :permission,
40
+ :rule,
41
+ # Additional for :extended ACL directive
42
+ :line,
43
+ :protocol
44
+ ].each do |m|
45
+ define_method(m) do
46
+ begin
47
+ @match_data[m]
48
+ rescue IndexError
49
+ nil
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end