conpar 0.1.0

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 (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