fog-bouncer 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/fog-bouncer.gemspec CHANGED
@@ -19,8 +19,8 @@ Gem::Specification.new do |gem|
19
19
  gem.add_dependency "fog", "~> 1.2"
20
20
  gem.add_dependency "ipaddress", "~> 0.8.0"
21
21
  gem.add_dependency "jruby-openssl", "~> 0.7.6" if RUBY_PLATFORM == "java"
22
- gem.add_dependency "rake"
23
- gem.add_dependency "scrolls", "~> 0.0.5"
22
+ gem.add_dependency "rake", "~> 0.9.0"
23
+ gem.add_dependency "scrolls", "~> 0.1.0"
24
24
 
25
25
  gem.add_development_dependency "minitest"
26
26
  end
data/lib/fog/bouncer.rb CHANGED
@@ -9,8 +9,6 @@ require "fog/bouncer/ip_permissions"
9
9
  require "fog/bouncer/group_manager"
10
10
  require "fog/bouncer/source_manager"
11
11
 
12
- require "scrolls"
13
-
14
12
  module Fog
15
13
  module Bouncer
16
14
  # Public: An AWS account ID
@@ -54,54 +52,36 @@ module Fog
54
52
  )
55
53
  end
56
54
 
57
- # Public: Log data through Scrolls
55
+ # Public: Allows the user to specify a logger for the log messages that Fog::Bouncer
56
+ # produces.
58
57
  #
59
- # Example
58
+ # logger = The object you want logs to be sent too
60
59
  #
61
- # Fog::Bouncer.log(data_one: true, data_two: true)
60
+ # Examples
62
61
  #
63
- # Returns nothing
64
- def self.log(data, &block)
65
- log! unless logging?
66
- Scrolls.log({ 'fog-bouncer' => true, 'pretending' => pretending? }.merge(data), &block)
62
+ # Fog::Bouncer.instrument_with(STDOUT.method(:puts))
63
+ # # => #<Method: IO#puts>
64
+ #
65
+ # Returns the logger object
66
+ def self.instrument_with(logger)
67
+ @logger = logger
67
68
  end
68
69
 
69
- # Public: Start the Scrolls logger
70
- #
71
- # Example
70
+ # Internal: Top level log method for use by Fog::Bouncer
72
71
  #
73
- # Fog::Bouncer.log!
72
+ # data = Logging data (typically a hash)
73
+ # blk = block to execute
74
74
  #
75
- # Returns nothing
76
- def self.log!
77
- Scrolls::Log.start(logger)
78
- @logging = true
75
+ # Returns the response from calling the logger with the arguments
76
+ def self.log(data, &blk)
77
+ logger.call({ 'fog-bouncer' => true, 'pretending' => pretending? }.merge(data), &blk)
79
78
  end
80
79
 
81
80
  # Public: The logging location
82
81
  #
83
82
  # Returns an Object
84
83
  def self.logger
85
- @logger ||= STDOUT
86
- end
87
-
88
- # Public: Set the logging location
89
- #
90
- # Returns nothing
91
- def self.logger=(logger)
92
- @logger = logger
93
- end
94
-
95
- # Public: Check the logging state
96
- #
97
- # Example
98
- #
99
- # Fog::Bouncer.logging?
100
- # # => true
101
- #
102
- # Returns false or true if logging has been started
103
- def self.logging?
104
- @logging ||= false
84
+ @logger || STDOUT.method(:puts)
105
85
  end
106
86
 
107
87
  # Public: Load a file for evaluation
@@ -184,8 +164,16 @@ module Fog
184
164
  # Returns a Fog::Bouncer::Security object
185
165
  def self.security(name, &block)
186
166
  Fog::Bouncer.log(security: true, name: name) do
187
- doorlists[name] = Fog::Bouncer::Security.new(name, &block)
167
+ doorlists[name] = Fog::Bouncer::Security.new(name, specific_groups, &block)
188
168
  end
189
169
  end
170
+
171
+ def self.specific_groups
172
+ @specific_groups ||= []
173
+ end
174
+
175
+ def self.specific_groups=(groups)
176
+ @specific_groups = Array(groups)
177
+ end
190
178
  end
191
179
  end
@@ -1,23 +1,81 @@
1
1
  require "clamp"
2
-
3
2
  require "fog/bouncer"
3
+ require "scrolls"
4
4
 
5
5
  module Fog
6
6
  module Bouncer
7
7
  module CLI
8
+ class Logger
9
+ def self.log(data, &block)
10
+ Scrolls.log(data, &block)
11
+ end
12
+ end
13
+
8
14
  def self.run(*a)
9
15
  MainCommand.run(*a)
10
16
  end
11
17
 
12
18
  class AbstractCommand < Clamp::Command
19
+ option "--aws-account-id", "AWS_ACCOUNT_ID", "AWS Account ID" do |id|
20
+ ENV['AWS_ACCOUNT_ID'] = id
21
+ end
22
+ option "--aws-access-key-id", "AWS_ACCESS_KEY_ID", "AWS Access Key ID" do |key|
23
+ ENV['AWS_ACCESS_KEY_ID'] = key
24
+ end
25
+ option "--aws-secret-access-key", "AWS_SECRET_ACCESS_KEY", "AWS Secret Access Key" do |key|
26
+ ENV['AWS_SECRET_ACCESS_KEY'] = key
27
+ end
28
+
29
+ option ["--confirm"], "CONFIRMATION", "Confirm dangerous action", :attribute_name => :confirmation
30
+
31
+ option ["--file", "-f"], "FILE", "Doorlist"
32
+
33
+ option ["--groups", "-g"], "GROUPS", "Comma separated list of groups", :default => [] do |groups|
34
+ Fog::Bouncer.specific_groups = groups.split(',')
35
+ end
36
+
37
+ option ["--pretend"], :flag, "Run in pretend mode" do
38
+ Fog::Bouncer.pretend!
39
+ end
40
+
13
41
  option "--version", :flag, "show version" do
14
- puts "fog-bounder #{Fog::Bouncer::VERSION}"
42
+ puts "fog-bouncer #{Fog::Bouncer::VERSION}"
15
43
  exit 0
16
44
  end
45
+
46
+ def confirm
47
+ unless confirmation
48
+ puts
49
+ puts " ! WARNING: This action is not marked as being safe."
50
+ puts " ! To proceed, enter \"confirmation\" or re-run this command with --confirm confirmation"
51
+ puts
52
+ print "> "
53
+
54
+ confirmation = $stdin.gets.chomp
55
+ end
56
+
57
+ confirmation == "confirmation" || raise("Confirmation failed")
58
+ end
59
+
60
+ def file
61
+ if @file && File.exists?(File.expand_path(@file))
62
+ File.expand_path(@file)
63
+ elsif File.exists?(File.expand_path("Doorlist"))
64
+ File.expand_path("Doorlist")
65
+ else
66
+ raise("Doorlist not found")
67
+ end
68
+ end
17
69
  end
18
70
 
71
+ require "fog/bouncer/cli/diff"
72
+
19
73
  class MainCommand < AbstractCommand
74
+ subcommand "diff", "Generate a diff between local and remote", DiffCommand
20
75
  end
21
76
  end
22
77
  end
23
78
  end
79
+
80
+ Scrolls::Log.start(STDOUT)
81
+ Fog::Bouncer.instrument_with(Fog::Bouncer::CLI::Logger.method(:log))
@@ -0,0 +1,76 @@
1
+ module Fog
2
+ module Bouncer
3
+ module CLI
4
+ class DiffCommand < AbstractCommand
5
+ option ["--diff-format"], "DIFF_FORMAT", "The diff output format (ec2)", :default => :ec2
6
+ option ["--apply"], :flag, "Apply the differences"
7
+
8
+ def execute
9
+ doorlist = Fog::Bouncer.load(file)
10
+ doorlist.import_remote_groups
11
+ groups = doorlist.groups
12
+
13
+ Fog::Bouncer::CLI::Diff.for(doorlist, diff_format)
14
+
15
+ if apply? && confirm
16
+ doorlist.sync
17
+ end
18
+ end
19
+ end
20
+
21
+ class Diff
22
+ class EC2
23
+ def self.diff(doorlist)
24
+ doorlist.groups.each do |group|
25
+ if group.local? && !group.remote?
26
+ puts "ec2-create-group #{group.name} -d '#{group.description}'"
27
+ end
28
+
29
+ group.sources.each do |source|
30
+ source.protocols.each do |protocol|
31
+ if protocol.local? && !protocol.remote?
32
+ authorize_cmd = "ec2-authorize #{protocol.group.name} -P #{protocol.type}"
33
+ if protocol.type == "icmp"
34
+ authorize_cmd << " -t #{protocol.from}:#{protocol.to}"
35
+ else
36
+ authorize_cmd << " -p #{protocol.from}-#{protocol.to}"
37
+ end
38
+
39
+ if source.is_a?(Fog::Bouncer::Sources::CIDR)
40
+ authorize_cmd << " -s #{source.range}"
41
+ else
42
+ authorize_cmd << " -u #{source.user_id} -o #{source.name}"
43
+ end
44
+
45
+ puts authorize_cmd
46
+ elsif !protocol.local? && protocol.remote?
47
+ revoke_cmd = "ec2-revoke #{protocol.group.name} -P #{protocol.type}"
48
+ if protocol.type == "icmp"
49
+ revoke_cmd << " -t #{protocol.from}:#{protocol.to}"
50
+ else
51
+ revoke_cmd << " -p #{protocol.from}-#{protocol.to}"
52
+ end
53
+
54
+ puts revoke_cmd
55
+ end
56
+ end
57
+ end
58
+
59
+ if group.remote? && !group.local?
60
+ puts "ec2-delete-group #{group.name}"
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ FORMATS = {
67
+ :ec2 => Fog::Bouncer::CLI::Diff::EC2
68
+ }
69
+
70
+ def self.for(doorlist, diff_format)
71
+ FORMATS[diff_format.to_sym].diff(doorlist)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -18,6 +18,10 @@ module Fog
18
18
  validate
19
19
  end
20
20
 
21
+ def group
22
+ source.group
23
+ end
24
+
21
25
  def local
22
26
  @local ||= false
23
27
  end
@@ -5,9 +5,10 @@ module Fog
5
5
  class Security
6
6
  attr_reader :name, :description
7
7
 
8
- def initialize(name, &block)
8
+ def initialize(name, specific_groups = [], &block)
9
9
  @name = name
10
10
  @definitions = {}
11
+ @specific_groups = specific_groups
11
12
  @using = []
12
13
  instance_eval(&block)
13
14
  apply_definitions
@@ -36,6 +37,7 @@ module Fog
36
37
 
37
38
  def import_remote_groups
38
39
  Fog::Bouncer.fog.security_groups.each do |remote_group|
40
+ next if @specific_groups.any? && !@specific_groups.include?(remote_group.name)
39
41
  group = group(remote_group.name, remote_group.description)
40
42
  group.remote = remote_group
41
43
  IPPermissions.to(group, remote_group.ip_permissions) if remote_group.ip_permissions
@@ -77,6 +79,7 @@ module Fog
77
79
  end
78
80
 
79
81
  def group(name, description, &block)
82
+ return if @specific_groups.any? && !@specific_groups.include?(name)
80
83
  group = groups.find { |group| group.name == name }
81
84
  if group.nil?
82
85
  group = Group.new(name, description, self, &block)
@@ -1,5 +1,5 @@
1
1
  module Fog
2
2
  module Bouncer
3
- VERSION = "0.1.1"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
data/spec/helper.rb CHANGED
@@ -6,8 +6,17 @@ ENV['AWS_SECRET_ACCESS_KEY'] ||= "abcde1234"
6
6
  ENV['AWS_ACCOUNT_ID'] ||= "1234567890"
7
7
 
8
8
  require "fog/bouncer"
9
+ require "scrolls"
9
10
 
10
- Fog::Bouncer.logger = File.open(File.dirname(__FILE__) + '/../logs/test.log', 'w')
11
+ Scrolls::Log.start(File.open(File.dirname(__FILE__) + '/../logs/test.log', 'w'))
12
+
13
+ module TestLogger
14
+ def self.log(data, &blk)
15
+ Scrolls.log(data, &blk)
16
+ end
17
+ end
18
+
19
+ Fog::Bouncer.instrument_with(TestLogger.method(:log))
11
20
 
12
21
  def load_security(security)
13
22
  Fog::Bouncer.load File.dirname(__FILE__) + "/support/security/#{security}.rb"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fog-bouncer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-17 00:00:00.000000000 Z
12
+ date: 2012-05-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: clamp
@@ -64,17 +64,17 @@ dependencies:
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
67
- - - ! '>='
67
+ - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: '0'
69
+ version: 0.9.0
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
- - - ! '>='
75
+ - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: '0'
77
+ version: 0.9.0
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: scrolls
80
80
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +82,7 @@ dependencies:
82
82
  requirements:
83
83
  - - ~>
84
84
  - !ruby/object:Gem::Version
85
- version: 0.0.5
85
+ version: 0.1.0
86
86
  type: :runtime
87
87
  prerelease: false
88
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,7 +90,7 @@ dependencies:
90
90
  requirements:
91
91
  - - ~>
92
92
  - !ruby/object:Gem::Version
93
- version: 0.0.5
93
+ version: 0.1.0
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: minitest
96
96
  requirement: !ruby/object:Gem::Requirement
@@ -128,6 +128,7 @@ files:
128
128
  - fog-bouncer.gemspec
129
129
  - lib/fog/bouncer.rb
130
130
  - lib/fog/bouncer/cli.rb
131
+ - lib/fog/bouncer/cli/diff.rb
131
132
  - lib/fog/bouncer/group.rb
132
133
  - lib/fog/bouncer/group_manager.rb
133
134
  - lib/fog/bouncer/ip_permissions.rb