firewall-agent 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Max M. Petrov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,113 @@
1
+ = firewall-agent
2
+
3
+ Firewall Agent
4
+
5
+ Firewall Agent is a utility to simplify firewall configuration for clouds and clusters, especially when hosted with 3rd party VPS services.
6
+
7
+ Key Features
8
+ - Human readable/writable policy files
9
+ - Dynamic policy updates
10
+ - IPTables compatible
11
+ - Written in Ruby
12
+
13
+ What Are Dynamic Policy Updates?
14
+ IPTables uses a static config file to specify the allowed ports, hosts and connections allowed at any given time. Firewall-agent with Dynamic Policy Updates
15
+ allows you to go beyond static files to update your policy file as needed, based on changing network conditions, dynmic host or service lists, or time-based
16
+ criteria. Examples of several of the applications of this feature can be seen below in the policy examples.
17
+
18
+
19
+ Getting Started
20
+ sudo gem install firewall-agent
21
+ sudo firewall-agent bootstrap
22
+ sudo firewall-agent
23
+
24
+ To Run as a Service (TBD)
25
+ service start firewall-agent
26
+
27
+ Writing a Policy File
28
+
29
+ Policy files are simple ruby files, and as such, can have any ruby syntax necessary. Policy files are required to
30
+ have a 'policy' block. To get started create a policy file using one of the templates below, then cusotmize it to your needs.
31
+
32
+ The command 'firewall-agent bootstrap' creates a policy.rb file in the /etc/firewall-agent directory using the same 'standard' policy shown in this README.
33
+
34
+ Basic Policy
35
+
36
+ policy :standard_policy do
37
+ deny_all # deny all connections from all hosts
38
+ allow_listen 'http' # let HTTP connections in
39
+ allow_established # allow all established TCP connections
40
+ allow_ping # let any host ping this server
41
+ allow_ssh # allow SSH connections
42
+ end
43
+
44
+ Dynamic Policy
45
+
46
+ policy :dynamic_policy do
47
+ deny_all
48
+ allow_listen 'http', 'https' # list multiple services or ports as needed
49
+
50
+ # Firewall-agent will whitelist all slices in your account, enabling a Virtual Private Network for your slices
51
+ update :each => 5.minutes do
52
+ allow_ips slicehost_get_ips('https://8fff02f2853@api.slicehost.com/')
53
+ end
54
+
55
+ allow_established
56
+ allow_ping
57
+ allow_ssh
58
+ end
59
+
60
+
61
+ Super Advanced Policy
62
+
63
+ require 'resolve'
64
+ policy :advanced_policy do
65
+ deny_all
66
+ allow_listen 'http', 'https'
67
+
68
+ update :each => 5.minutes do
69
+ allow_ips slicehost_get_ips('https://8fff02f2853@api.slicehost.com/')
70
+ end
71
+
72
+ # 3 different schedules for different types of policy elememnts
73
+ # this block will enable you to always access all services on
74
+ # this host - even when your IP changes, via a Dynamic DNS service
75
+ update :each => 10.minutes do
76
+ allow_ips Resolv.getaddress('your-desktop.dyndns.org')
77
+ allow_ips Resolv.getaddress('your-laptop.dyndns.org')
78
+ end
79
+
80
+ # disable printing using CUPS/IPP outside of business hours
81
+ update :each => 1.minutes do
82
+ now = Time.now
83
+ allow_listen 631 unless now.hour < 8 || now.hour > 18
84
+ end
85
+
86
+ allow_established
87
+ allow_ping
88
+ allow_ssh
89
+ end
90
+
91
+
92
+ Extending Firewall Agent
93
+ Firewall-agent includes a simple Slicehost extension which uses the Slicehost API to get a list of all slices in your account, then updates the
94
+ policy to allow access from any of these nodes - for all ports - on the firewall-agent host. You can use this as a model to create similar extensions
95
+ for other VPS provides such as Linode, etc.
96
+
97
+ In addition, we believe there are lots of opportunities for extensions to integrate dynamic whitelist and blacklist services. Please share your
98
+ creations with the community. Well documented and tested extensios will be added to the firewall-agent - please contact us on GitHub.
99
+
100
+
101
+ == Note on Patches/Pull Requests
102
+
103
+ * Fork the project.
104
+ * Make your feature addition or bug fix.
105
+ * Add tests for it. This is important so I don't break it in a
106
+ future version unintentionally.
107
+ * Commit, do not mess with rakefile, version, or history.
108
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
109
+ * Send me a pull request. Bonus points for topic branches.
110
+
111
+ == Copyright
112
+
113
+ Copyright (c) 2010 Powcloud Inc. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "firewall-agent"
8
+ gem.summary = %Q{Firewall Agent is a utility to simplify firewall configuration}
9
+ gem.description = %Q{Firewall Agent is a utility to simplify firewall configuration for clouds and clusters, especially when hosted with 3rd party VPS services.}
10
+ gem.email = "maxmpz@gmail.com"
11
+ gem.homepage = "http://github.com/powcloud/firewall-agent"
12
+ gem.authors = ["Darren Rush", "Max M. Petrov"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.files = FileList["[A-Z_.]*", "{bin,lib,test}/**/*", 'lib/jeweler/templates/.gitignore']
15
+
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ gem.add_dependency('activesupport', '>= 2.3.4')
18
+ gem.add_dependency('eventmachine', '>= 0.12.10')
19
+ gem.add_dependency('log4r', '>= 1.1.2')
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'rake/testtask'
27
+ Rake::TestTask.new(:test) do |test|
28
+ test.libs << 'lib' << 'test'
29
+ test.pattern = 'test/**/test_*.rb'
30
+ test.verbose = true
31
+ end
32
+
33
+ begin
34
+ require 'rcov/rcovtask'
35
+ Rcov::RcovTask.new do |test|
36
+ test.libs << 'test'
37
+ test.pattern = 'test/**/test_*.rb'
38
+ test.verbose = true
39
+ end
40
+ rescue LoadError
41
+ task :rcov do
42
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
43
+ end
44
+ end
45
+
46
+ task :test => :check_dependencies
47
+
48
+ task :default => :test
49
+
50
+ require 'rake/rdoctask'
51
+ Rake::RDocTask.new do |rdoc|
52
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
53
+
54
+ rdoc.rdoc_dir = 'rdoc'
55
+ rdoc.title = "firewall-agent #{version}"
56
+ rdoc.rdoc_files.include('README*')
57
+ rdoc.rdoc_files.include('lib/**/*.rb')
58
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'rubygems'
5
+ rescue LoadError
6
+ end
7
+
8
+ require File.dirname(__FILE__) + '/../lib/firewall_agent'
9
+
10
+ Log4r::Logger.root.level = Log4r::WARN
11
+
12
+
13
+ if ARGV.length > 0
14
+ if ARGV[0] == 'bootstrap'
15
+ require 'fileutils'
16
+ FileUtils.mkdir_p('/etc/firewall-agent')
17
+ FileUtils.cp(File.join(File.dirname(__FILE__), '..', 'examples', 'standard_policy.rb'), FirewallAgent::DEFAULT_POLICY_FILE)
18
+ puts "Created #{FirewallAgent::DEFAULT_POLICY_FILE}"
19
+ else
20
+ FirewallAgent.start ARGV[0]
21
+ end
22
+ else
23
+ FirewallAgent.start
24
+ end
25
+
@@ -0,0 +1,27 @@
1
+ require 'resolve'
2
+ policy :advanced_policy do
3
+ deny_all
4
+ allow_listen 'http', 'https'
5
+
6
+ update :each => 5.minutes do
7
+ allow_ips slicehost_get_ips('https://8fff02f2853@api.slicehost.com/')
8
+ end
9
+
10
+ # 3 different schedules for different types of policy elememnts
11
+ # this block will enable you to always access all services on
12
+ # this host - even when your IP changes, via a Dynamic DNS service
13
+ update :each => 10.minutes do
14
+ allow_ips Resolv.getaddress('your-desktop.dyndns.org')
15
+ allow_ips Resolv.getaddress('your-laptop.dyndns.org')
16
+ end
17
+
18
+ # disable printing using CUPS/IPP outside of business hours
19
+ update :each => 1.minutes do
20
+ now = Time.now
21
+ allow_listen 631 unless now.hour < 8 || now.hour > 18
22
+ end
23
+
24
+ allow_established
25
+ allow_ping
26
+ allow_ssh
27
+ end
@@ -0,0 +1,13 @@
1
+ policy :dynamic_policy do
2
+ deny_all
3
+ allow_listen 'http', 'https' # list multiple services or ports as needed
4
+
5
+ # Firewall-agent will whitelist all slices in your account, enabling a Virtual Private Network for your slices
6
+ update :each => 5.minutes do
7
+ allow_ips slicehost_get_ips('https://8fff02f2853....@api.slicehost.com/')
8
+ end
9
+
10
+ allow_established
11
+ allow_ping
12
+ allow_ssh
13
+ end
@@ -0,0 +1,7 @@
1
+ policy :standard_policy do
2
+ deny_all # deny all connections from all hosts
3
+ allow_listen 'http' # let HTTP connections in
4
+ allow_established # allow all established TCP connections
5
+ allow_ping # let any host ping this server
6
+ allow_ssh # allow SSH connections
7
+ end
@@ -0,0 +1,70 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{firewall-agent}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Darren Rush", "Max M. Petrov"]
12
+ s.date = %q{2010-02-05}
13
+ s.default_executable = %q{firewall-agent}
14
+ s.description = %q{Firewall Agent is a utility to simplify firewall configuration for clouds and clusters, especially when hosted with 3rd party VPS services.}
15
+ s.email = %q{maxmpz@gmail.com}
16
+ s.executables = ["firewall-agent"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "bin/firewall-agent",
27
+ "firewall-agent.gemspec",
28
+ "lib/firewall_agent.rb",
29
+ "lib/iptables_generator.rb",
30
+ "lib/policy.rb",
31
+ "lib/slicehost_support.rb",
32
+ "test/helper.rb",
33
+ "test/test_firewall-agent.rb"
34
+ ]
35
+ s.homepage = %q{http://github.com/powcloud/firewall-agent}
36
+ s.rdoc_options = ["--charset=UTF-8"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = %q{1.3.5}
39
+ s.summary = %q{Firewall Agent is a utility to simplify firewall configuration}
40
+ s.test_files = [
41
+ "test/helper.rb",
42
+ "test/test_firewall-agent.rb",
43
+ "examples/advanced_policy.rb",
44
+ "examples/dynamic_policy.rb",
45
+ "examples/standard_policy.rb"
46
+ ]
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
53
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
54
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.3.4"])
55
+ s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.10"])
56
+ s.add_runtime_dependency(%q<log4r>, [">= 1.1.2"])
57
+ else
58
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
59
+ s.add_dependency(%q<activesupport>, [">= 2.3.4"])
60
+ s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
61
+ s.add_dependency(%q<log4r>, [">= 1.1.2"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
65
+ s.add_dependency(%q<activesupport>, [">= 2.3.4"])
66
+ s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
67
+ s.add_dependency(%q<log4r>, [">= 1.1.2"])
68
+ end
69
+ end
70
+
@@ -0,0 +1,98 @@
1
+ require 'log4r'
2
+ require 'log4r/outputter/syslogoutputter'
3
+ require 'eventmachine'
4
+
5
+ this_dir = File.dirname(__FILE__)
6
+ require "#{this_dir}/iptables_generator"
7
+ require "#{this_dir}/slicehost_support"
8
+ require "#{this_dir}/policy"
9
+
10
+ class FirewallAgent
11
+ attr_reader :logger
12
+
13
+ IPTABLES_FILE = "/etc/sysconfig/iptables"
14
+ DEFAULT_POLICY_FILE = '/etc/firewall-agent/policy.rb'
15
+
16
+ def initialize
17
+ @logger = Log4r::Logger.new File.basename(__FILE__)
18
+ end
19
+
20
+ def stop
21
+ logger.warn "Stopping..."
22
+ EM.stop
23
+ end
24
+
25
+ def start(policy_filename)
26
+ unless File.exists? policy_filename
27
+ logger.error "Policy file (#{policy_filename}) not found, exiting..."
28
+ exit 1
29
+ end
30
+
31
+ EM.run do
32
+ Signal.trap('INT') { stop }
33
+ Signal.trap('TERM'){ stop }
34
+
35
+ policy = Policy.new policy_filename, logger
36
+
37
+ logger.warn "Starting agent"
38
+ logger.warn "Applying dynamic firewall policy #{policy.name.to_s} from #{policy_filename}"
39
+
40
+ apply_policy(policy)
41
+
42
+ EM.add_periodic_timer 5 do
43
+ apply_policy(policy) if policy.dirty?
44
+ end
45
+ end
46
+ end
47
+
48
+ def self.start(policy_filename = DEFAULT_POLICY_FILE)
49
+ agent = self.new
50
+
51
+ formatter = Log4r::PatternFormatter.new(:pattern => "[%5l] %d %C - %m")
52
+ Log4r::StdoutOutputter.new('console', :formatter => formatter)
53
+ Log4r::SyslogOutputter.new('syslog', :ident => File.basename(__FILE__))
54
+ agent.logger.outputters = ['syslog', 'console']
55
+
56
+ agent.start(policy_filename)
57
+ end
58
+
59
+ private
60
+
61
+ def apply_policy(policy)
62
+ logger.debug "apply_policy"
63
+
64
+ iptables = generate_iptables(policy)
65
+ policy.clean
66
+
67
+ # Read in old file
68
+ if File.exists?(IPTABLES_FILE)
69
+ begin
70
+ old_iptables = File.read(IPTABLES_FILE)
71
+ rescue Exception => ex
72
+ log_exception ex
73
+ exit 1
74
+ end
75
+ else
76
+ old_iptables = ''
77
+ end
78
+
79
+ # Restart service if changed
80
+ if old_iptables != iptables
81
+ logger.warn "Updating and restarting IPTables..."
82
+ open(IPTABLES_FILE , 'w') { |f| f.puts iptables }
83
+ system 'service iptables restart > /dev/null'
84
+ logger.warn "Policy enabled"
85
+ else
86
+ logger.debug "apply_policy - no changes"
87
+ end
88
+ end
89
+
90
+ def generate_iptables(policy)
91
+ policy.rules.flatten.join("\n") + "\nCOMMIT\n"
92
+ end
93
+
94
+ def log_exception(ex)
95
+ logger.error ex.to_s + (ex.backtrace.length > 0 ? ' ' + ex.backtrace.first : '')
96
+ end
97
+ end
98
+
@@ -0,0 +1,54 @@
1
+ module IptablesGenerator
2
+ class << self
3
+
4
+ def deny_all
5
+ # Default to dropping unmatched input, Default to dropping unmatched forward requests, Allow all outgoing requests, Allow everything on loopback
6
+ <<EOS_DENY_ALL
7
+ *filter
8
+ :INPUT DROP [0:0]
9
+ :FORWARD ACCEPT [0:0]
10
+ :OUTPUT ACCEPT [0:0]
11
+ -A INPUT -i lo -j ACCEPT
12
+ EOS_DENY_ALL
13
+ end
14
+
15
+ def allow_established
16
+ "-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT\n"
17
+ end
18
+
19
+ def allow_ping
20
+ "-A INPUT -p icmp --icmp-type any -j ACCEPT\n"
21
+ end
22
+
23
+ def allow_ssh
24
+ "-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT\n"
25
+ end
26
+
27
+ def allow_ip(ip)
28
+ "-A INPUT -s #{ip} -j ACCEPT\n"
29
+ end
30
+
31
+ def allow_ips(ips)
32
+ ips.map{ |ip| allow_ip(ip) }.join ''
33
+ end
34
+
35
+ # Rule to open a given port(s)
36
+ def allow_listen(ports, prot = 'tcp', nic = 'all')
37
+ if ports.empty?
38
+ return ''
39
+ end
40
+
41
+ # -A INPUT -p tcp -m multiport --dport 80,443 -j ACCEPT
42
+ result = "-A INPUT"
43
+
44
+ # Did we want a specific nics?
45
+ #TODO: Convert this to an options hash
46
+ if (nic != 'all' )
47
+ result << " -i #{nic}"
48
+ end
49
+
50
+ result << " -p #{prot} -m multiport --dport #{ports.join(",")} -j ACCEPT\n"
51
+ result
52
+ end
53
+ end
54
+ end
data/lib/policy.rb ADDED
@@ -0,0 +1,96 @@
1
+ require "active_support/core_ext/integer"
2
+
3
+ class Policy
4
+ include SlicehostSupport
5
+
6
+ attr_reader :name, :logger
7
+
8
+ def initialize(dsl_file, logger)
9
+ @stack = []
10
+ @top = []
11
+ @stack.push(@top)
12
+ @dirty = false
13
+ @logger = logger
14
+
15
+ instance_eval File.open(dsl_file).read, dsl_file
16
+ end
17
+
18
+ def rules
19
+ @top
20
+ end
21
+
22
+ def dirty?
23
+ @dirty
24
+ end
25
+
26
+ def clean
27
+ @dirty = false
28
+ end
29
+
30
+ def config
31
+ yield
32
+ end
33
+
34
+ def policy(name = :unnamed)
35
+ @name = name
36
+ yield
37
+ end
38
+
39
+ def allow_ip(ip)
40
+ add_rule IptablesGenerator.allow_ip ip
41
+ end
42
+
43
+ def allow_ips(*hosts)
44
+ hosts = hosts.first if hosts.length == 1 && hosts.first.instance_of?(Array)
45
+ add_rule IptablesGenerator.allow_ips hosts
46
+ end
47
+
48
+ def allow_listen(*ports)
49
+ ports = ports.first if ports.length == 1 && ports.first.instance_of?(Array)
50
+ add_rule IptablesGenerator.allow_listen(ports)
51
+ end
52
+
53
+ def allow_slicehost_slices(key)
54
+ add_rule IptablesGenerator.allow_slicehost_slices(key)
55
+ end
56
+
57
+ def allow_established
58
+ add_rule IptablesGenerator.allow_established
59
+ end
60
+
61
+ def allow_ping
62
+ add_rule IptablesGenerator.allow_ping
63
+ end
64
+
65
+ def allow_ssh
66
+ add_rule IptablesGenerator.allow_ssh
67
+ end
68
+
69
+ def deny_all
70
+ add_rule IptablesGenerator.deny_all
71
+ end
72
+
73
+ def add_rule(rule)
74
+ @dirty = true
75
+ @stack.last << rule
76
+ end
77
+
78
+ def update(options = {})
79
+ index = @stack.last.length
80
+
81
+ @stack.push([])
82
+ yield
83
+ rules = @stack.pop
84
+ @stack.last[index] = rules
85
+
86
+ period = options[:each].to_i
87
+ if period > 0
88
+ EM.add_periodic_timer period do
89
+ rules.clear
90
+ @stack.push(rules)
91
+ yield
92
+ @stack.pop
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,21 @@
1
+ require 'active_resource'
2
+
3
+ module SlicehostSupport
4
+ class Slice < ActiveResource::Base
5
+ end
6
+
7
+ def slicehost_get_ips(api_key)
8
+ Slice.site = api_key
9
+ slices = Slice.find(:all)
10
+
11
+ ips = []
12
+
13
+ for slice in slices
14
+ for address in slice.addresses
15
+ ips << address
16
+ end
17
+ end
18
+
19
+ ips
20
+ end
21
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ #require 'rubygems'
2
+ #require 'test/unit'
3
+ #require 'shoulda'
4
+ #
5
+ #$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ #$LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ #require 'firewall_agent'
8
+ #
9
+ #class Test::Unit::TestCase
10
+ #end
@@ -0,0 +1,7 @@
1
+ #require 'helper'
2
+ #
3
+ #class TestFirewallAgent < Test::Unit::TestCase
4
+ # should "probably rename this file and start testing for real" do
5
+ # flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ # end
7
+ #end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: firewall-agent
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Darren Rush
8
+ - Max M. Petrov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2010-02-05 00:00:00 +03:00
14
+ default_executable: firewall-agent
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: thoughtbot-shoulda
18
+ type: :development
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: activesupport
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 2.3.4
35
+ version:
36
+ - !ruby/object:Gem::Dependency
37
+ name: eventmachine
38
+ type: :runtime
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 0.12.10
45
+ version:
46
+ - !ruby/object:Gem::Dependency
47
+ name: log4r
48
+ type: :runtime
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.1.2
55
+ version:
56
+ description: Firewall Agent is a utility to simplify firewall configuration for clouds and clusters, especially when hosted with 3rd party VPS services.
57
+ email: maxmpz@gmail.com
58
+ executables:
59
+ - firewall-agent
60
+ extensions: []
61
+
62
+ extra_rdoc_files:
63
+ - LICENSE
64
+ - README.rdoc
65
+ files:
66
+ - LICENSE
67
+ - README.rdoc
68
+ - Rakefile
69
+ - VERSION
70
+ - bin/firewall-agent
71
+ - firewall-agent.gemspec
72
+ - lib/firewall_agent.rb
73
+ - lib/iptables_generator.rb
74
+ - lib/policy.rb
75
+ - lib/slicehost_support.rb
76
+ - test/helper.rb
77
+ - test/test_firewall-agent.rb
78
+ has_rdoc: true
79
+ homepage: http://github.com/powcloud/firewall-agent
80
+ licenses: []
81
+
82
+ post_install_message:
83
+ rdoc_options:
84
+ - --charset=UTF-8
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ version:
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: "0"
98
+ version:
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.3.5
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Firewall Agent is a utility to simplify firewall configuration
106
+ test_files:
107
+ - test/helper.rb
108
+ - test/test_firewall-agent.rb
109
+ - examples/advanced_policy.rb
110
+ - examples/dynamic_policy.rb
111
+ - examples/standard_policy.rb