awsutils 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,91 @@
1
+ require 'awsutils/ec2sg'
2
+ require 'trollop'
3
+
4
+ gem 'fog-aws', '>= 0.7.6'
5
+
6
+ module AwsUtils
7
+ class GroupDoesNotExist < StandardError; end
8
+
9
+ class Ec2LsGrp < Ec2SecurityGroup
10
+ attr_reader :search, :opts, :owner_id
11
+
12
+ def msg_pair(key, value)
13
+ puts("#{key} #{value}")
14
+ end
15
+
16
+ def perms_out(direction, perms)
17
+ puts "#{direction.upcase} RULES"
18
+ perms.to_enum.with_index(1) do |perm, index|
19
+ print " #{index} "
20
+ print "groups: #{group_perm_string(perm['groups'])}; " if perm['groups'].count > 0
21
+ print "ip_ranges: #{perm['ipRanges'].join(', ')}; " if perm['ipRanges'].count > 0
22
+ print "ipProtocol: #{perm['ipProtocol']}; "
23
+ print "fromPort: #{perm['fromPort']}; " if perm['fromPort']
24
+ print "toPort: #{perm['toPort']}" if perm['toPort']
25
+ print "\n"
26
+ end
27
+ end
28
+
29
+ def group_details(g)
30
+ @owner_id = g.owner_id
31
+
32
+ msg_pair('ID', g.group_id)
33
+ msg_pair('NAME', g.name)
34
+ msg_pair('OWNER_ID', owner_id)
35
+ msg_pair('DESCRIPTION', g.description)
36
+ msg_pair('VPC_ID', g.vpc_id) if g.vpc_id
37
+
38
+ perms_out('incoming', g.ip_permissions)
39
+ perms_out('egress', g.ip_permissions_egress) if g.vpc_id
40
+ end
41
+
42
+ def run
43
+ fail ArgumentError, 'Please specify a security group' unless search
44
+ unless group_o = group(search) # rubocop:disable Lint/AssignmentInCondition
45
+ fail GroupDoesNotExist
46
+ end
47
+ return group_details(group_o) unless opts[:list_refs]
48
+ refs = references(group_o.group_id)
49
+ if refs.empty?
50
+ puts 'No references'
51
+ else
52
+ puts "References: #{refs.keys.join(', ')}"
53
+ puts refs.to_yaml if opts[:verbose]
54
+ end
55
+ end
56
+
57
+ def initialize
58
+ @opts = parse_opts
59
+ @search = ARGV.last
60
+ end
61
+
62
+ private
63
+
64
+ def group_perm_string(group_perm)
65
+ group_perm.map do |g|
66
+ if g['userId'] == owner_id
67
+ "#{g['groupId']} (#{group(g['groupId']).name})"
68
+ else
69
+ "#{g['groupId']} (#{g['groupName']}, owner: #{g['userId']})"
70
+ end
71
+ end.join(', ')
72
+ end
73
+
74
+ def parse_opts
75
+ Trollop.options do
76
+ opt :list_refs,
77
+ 'List groups referencing this group',
78
+ short: 'r',
79
+ default: false
80
+ opt :verbose,
81
+ 'Verbose output (currently only used with -r output)',
82
+ short: 'v',
83
+ default: false
84
+ end
85
+ end
86
+
87
+ def group(search)
88
+ groups.find { |g| (search =~ /^sg-/ && g.group_id == search) || g.name == search }
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,77 @@
1
+ require 'rubygems'
2
+ require 'fog/aws'
3
+
4
+ module AwsUtils
5
+ class Ec2SecurityGroup
6
+ def connection
7
+ @connection ||= begin
8
+ options = {}
9
+
10
+ if ENV['AWS_ACCESS_KEY']
11
+ options = {
12
+ aws_access_key_id: ENV['AWS_ACCESS_KEY'],
13
+ aws_secret_access_key: ENV['AWS_SECRET_KEY']
14
+ }
15
+ end
16
+
17
+ Fog::Compute::AWS.new options
18
+ end
19
+ end
20
+
21
+ def references(search)
22
+ if search =~ /^sg-/
23
+ search_id = search
24
+ else
25
+ search_id = groups.find { |g| g.name == search }.group_id
26
+ end
27
+
28
+ groups.each_with_object({}) do |grp, m|
29
+ assoc_p = grp.ip_permissions.select do |ip_perm|
30
+ !ip_perm['groups'].select { |src_grp|
31
+ src_grp['groupName'] == search ||
32
+ src_grp['groupId'] == search_id
33
+ }.empty?
34
+ end
35
+ if assoc_p.empty?
36
+ next
37
+ else
38
+ m[grp.name] = {
39
+ 'groupId' => grp.group_id,
40
+ 'ipPermissions' => assoc_p.map do |ap|
41
+ ap.delete('ipRanges')
42
+ ap
43
+ end
44
+ }
45
+ end
46
+ end
47
+ end
48
+
49
+ def groups
50
+ @groups ||= connection.security_groups
51
+ end
52
+
53
+ def assigned?
54
+ servers_using_group = connection.servers.map do |server|
55
+ next unless server.state != 'terminated' &&
56
+ server.groups.include?(@opts[:security_group])
57
+ server.tags['Name'] ? server.tags['Name'] : server.id
58
+ end.compact
59
+
60
+ return false unless servers_using_group.length > 0
61
+ print 'The following servers are still using this group: '
62
+ puts servers_using_group.join(',')
63
+
64
+ true
65
+ end
66
+
67
+ def exist?
68
+ current_groups.include?(@opts[:security_group])
69
+ end
70
+
71
+ def current_groups
72
+ @current_groups ||= begin
73
+ connection.security_groups.map { |g| [g.name, g.group_id] }.flatten.uniq
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,51 @@
1
+ require 'fog/aws/elb'
2
+ require 'fog/core/parser'
3
+ require 'facets/string/titlecase'
4
+ require 'rainbow'
5
+
6
+ module AwsUtils
7
+ class ElbLs
8
+ attr_reader :args
9
+
10
+ def run(args)
11
+ @args = args
12
+
13
+ if args.empty?
14
+ puts connection.load_balancers.map(&:id).sort
15
+ else
16
+ args.each do |lb|
17
+ puts colorize_yaml(attributes(lb).to_yaml)
18
+ puts '---' if args.count > 1
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def colorize_yaml(yaml_string)
26
+ yaml_string.split("\n").map do |line|
27
+ if line =~ /:/
28
+ key, val = line.split(':', 2)
29
+ [Rainbow(key).bright, val].join(':')
30
+ else
31
+ line
32
+ end
33
+ end.join("\n")
34
+ end
35
+
36
+ def attributes(lb)
37
+ Hash[connection.load_balancers.get(lb).attributes.map do |key, val|
38
+ case key
39
+ when Symbol
40
+ [key.to_s.titlecase, val]
41
+ when String
42
+ [key.split(/(?=[A-Z])/).join(' '), val]
43
+ end
44
+ end]
45
+ end
46
+
47
+ def connection
48
+ @connection ||= Fog::AWS::ELB.new
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'fog'
3
+ require 'trollop'
4
+
5
+ module AwsUtils
6
+
7
+ class Route53AddResourceRecord
8
+
9
+ def connection
10
+ @connection ||= Fog::DNS::AWS.new
11
+ end # def connection
12
+
13
+ def parse_opts
14
+ opts = Trollop::options do
15
+ opt :name, "The name", :short => 'n', :type => String, :required => true
16
+ opt :type, "Record type (e.g. CNAME or A)", :short => 'T', :type => String, :required => true
17
+ opt :ttl, "Time-to-live", :short => 't', :type => String, :default => "300"
18
+ opt :value, "Record Value", :short => 'v', :type => String, :required => true
19
+ end # opts = Trollop::options
20
+ end # def parse_opts
21
+
22
+ def initialize
23
+ @opts = parse_opts
24
+ end # def initialize
25
+
26
+ end # class Route53AddResourceRecord
27
+
28
+ end # module AwsUtils
@@ -0,0 +1,92 @@
1
+ require 'rubygems'
2
+ require 'fog'
3
+ require 'trollop'
4
+ require 'json'
5
+
6
+ module AwsUtils
7
+ class Route53ListResourceRecord
8
+ def connection
9
+ @connection ||= Fog::DNS::AWS.new
10
+ end # def connection
11
+
12
+ def parse_opts
13
+ opts = Trollop.options do
14
+ opt :format, 'Output format', default: 'table'
15
+ end
16
+ opts[:name] = ARGV.last
17
+ opts
18
+ end # def parse_opts( args )
19
+
20
+ def zone
21
+ @zone ||= connection.zones.all('domain' => zone_name).first
22
+ end
23
+
24
+ def zone_name
25
+ @zone_name ||= @opts[:name].split('.')[-2..-1].join('.') + '.'
26
+ end
27
+
28
+ def apex?
29
+ @opts[:name].split('.')[-3].nil? ? true : false
30
+ end
31
+
32
+ def initialize
33
+ @opts = parse_opts
34
+ end # def initialize( args )
35
+
36
+ def display_record(record)
37
+ if @opts[:format] == 'json'
38
+ puts JSON.pretty_generate(zone_to_json([record]).first)
39
+ else
40
+ puts 'Name: ' + record.name
41
+ puts 'Type: ' + record.type
42
+ puts 'TTL: ' + record.ttl
43
+ puts record.value.count < 2 ? 'Value:' : 'Values:'
44
+ record.value.each { |rr| puts " #{rr}" }
45
+ end
46
+ end
47
+
48
+ def record_by_name
49
+ name = @opts[:name].split('.').join('.') + '.'
50
+ zone.records.find { |r| r.name == name }
51
+ end
52
+
53
+ def zone_to_json(zone_records)
54
+ zone_records.map do |r|
55
+ {
56
+ 'name' => r.name,
57
+ 'type' => r.type,
58
+ 'ttl' => r.ttl,
59
+ 'value' => r.value
60
+ }
61
+ end
62
+ end
63
+
64
+ def print_table
65
+ zone.records.each do |r|
66
+ printf(
67
+ "%-40s%-8s%-8s%-40s\n",
68
+ r.name,
69
+ r.type,
70
+ r.ttl,
71
+ r.value.join(' ')
72
+ )
73
+ end
74
+ end
75
+
76
+ def list_all
77
+ if @opts[:format] == 'json'
78
+ puts JSON.pretty_generate(zone_to_json(zone.records))
79
+ else
80
+ print_table
81
+ end
82
+ end
83
+
84
+ def run
85
+ if apex?
86
+ list_all
87
+ else
88
+ display_record(record_by_name)
89
+ end
90
+ end
91
+ end # class Route53AddResourceRecord
92
+ end # module AwsUtils
@@ -0,0 +1,3 @@
1
+ module AwsUtils
2
+ VERSION = '1.4.3'
3
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+ require 'awsutils/ec2addsg'
3
+
4
+ describe AwsUtils::Ec2AddSecurityGroup do
5
+ it "takes security_group name" do
6
+ group_name = 'rspec_test_group'
7
+ ARGV = ['-N', group_name, '-d', 'rspec test group description']
8
+ sg = AwsUtils::Ec2AddSecurityGroup.new
9
+ expect(sg.name).to eq(group_name)
10
+ end
11
+ end
@@ -0,0 +1,178 @@
1
+ require 'spec_helper'
2
+ require 'awsutils/ec2lsgrp'
3
+ require 'byebug'
4
+
5
+ describe AwsUtils::Ec2LsGrp do
6
+ let(:ec2lsgrp) { AwsUtils::Ec2LsGrp.new }
7
+ let(:fog) { Fog::Compute::AWS.new }
8
+ let(:local_group_name) { 'test_group' }
9
+
10
+ before(:each) do
11
+ Fog.mock!
12
+ Fog::Mock.reset
13
+ allow(ec2lsgrp).to receive(:puts)
14
+ end
15
+
16
+ describe '#group' do
17
+ let(:group_set) do
18
+ [
19
+ object_double(
20
+ 'security_groups',
21
+ name: 'test_group',
22
+ group_id: 'sg-a1b2c3d4'
23
+ )
24
+ ]
25
+ end
26
+
27
+ before { allow(ec2lsgrp).to receive(:groups).and_return group_set }
28
+
29
+ context 'search by valid name' do
30
+ it 'return the group object' do
31
+ expect(ec2lsgrp.send('group', 'test_group')).to eq group_set.first
32
+ end
33
+ end
34
+
35
+ context 'search by valid ID' do
36
+ it 'return the group object' do
37
+ expect(ec2lsgrp.send('group', 'sg-a1b2c3d4')).to eq group_set.first
38
+ end
39
+ end
40
+
41
+ context 'search by invalid name' do
42
+ it 'return nil' do
43
+ expect(ec2lsgrp.send('group', 'invalid_group')).to eq nil
44
+ end
45
+ end
46
+
47
+ context 'search by invalid ID' do
48
+ it 'return nil' do
49
+ expect(ec2lsgrp.send('group', 'sg-00000000')).to eq nil
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'specify no arguments' do
55
+ before do
56
+ allow(ec2lsgrp).to receive(:search).and_return nil
57
+ end
58
+
59
+ it 'raise ArgumentError' do
60
+ expect { ec2lsgrp.run }.to raise_error(
61
+ ArgumentError,
62
+ 'Please specify a security group'
63
+ )
64
+ end
65
+ end
66
+
67
+ context 'search for a group' do
68
+ context 'by a name that does not exist' do
69
+ before do
70
+ allow(ec2lsgrp).to receive(:search).and_return 'bad-group-name'
71
+ end
72
+
73
+ it 'should raise GroupDoesNotExist exception' do
74
+ expect { ec2lsgrp.run }.to raise_error AwsUtils::GroupDoesNotExist
75
+ end
76
+ end
77
+
78
+ context 'by an id that does not exist' do
79
+ before do
80
+ allow(ec2lsgrp).to receive(:search).and_return 'sg-a1b2c3d4'
81
+ end
82
+
83
+ it 'should raise GroupDoesNotExist exception' do
84
+ expect { ec2lsgrp.run }.to raise_error AwsUtils::GroupDoesNotExist
85
+ end
86
+ end
87
+
88
+ context 'with no permissions' do
89
+ let(:local_group_obj) do
90
+ group_obj = fog.security_groups.create(
91
+ 'description' => '',
92
+ 'name' => local_group_name)
93
+ fog.security_groups.get_by_id(group_obj.group_id)
94
+ end
95
+
96
+ before do
97
+ allow(ec2lsgrp).to receive(:search).and_return local_group_name
98
+ end
99
+
100
+ it 'searches for the group by id' do
101
+ expect(ec2lsgrp).to receive(:group).with(local_group_name)
102
+ .and_return(local_group_obj)
103
+ ec2lsgrp.run
104
+ end
105
+ end
106
+
107
+ context 'with source group belonging to same userid' do
108
+ let(:dummy_group_name) { 'dummy_group' }
109
+
110
+ let(:dummy_group_obj) do
111
+ group_obj = fog.security_groups.create(
112
+ 'description' => 'Dummy Group',
113
+ 'name' => dummy_group_name
114
+ )
115
+ fog.security_groups.get_by_id(group_obj.group_id)
116
+ end
117
+
118
+ let(:local_group_obj) do
119
+ group_obj = fog.security_groups.create(
120
+ 'description' => '',
121
+ 'name' => local_group_name
122
+ )
123
+ group_obj.authorize_port_range(
124
+ 8080..8080,
125
+ group: { dummy_group_obj.owner_id => dummy_group_obj.group_id }
126
+ )
127
+ fog.security_groups.get_by_id(group_obj.group_id)
128
+ end
129
+
130
+ before do
131
+ allow(ec2lsgrp).to receive(:search).and_return local_group_name
132
+ end
133
+
134
+ it 'prints a source group list containing only groupName' do
135
+ allow(ec2lsgrp).to receive(:owner_id).and_return local_group_obj.owner_id
136
+ expect do
137
+ ec2lsgrp.perms_out('incoming', local_group_obj.ip_permissions)
138
+ end.to output(/ \d+ groups: #{dummy_group_obj.group_id} \(#{dummy_group_name}\); /).to_stdout
139
+ end
140
+ end
141
+
142
+ context 'with source group belonging to another userid' do
143
+ let(:dummy_group_obj) do
144
+ group_obj = fog.security_groups.create(
145
+ 'description' => 'Dummy Group',
146
+ 'name' => 'dummy_group'
147
+ )
148
+ fog.security_groups.get_by_id(group_obj.group_id)
149
+ end
150
+
151
+ let(:dummy_group_name) do
152
+ fog.security_groups.get_by_id(dummy_group_obj.group_id).name
153
+ end
154
+
155
+ let(:local_group_obj) do
156
+ group_obj = fog.security_groups.create(
157
+ 'description' => '',
158
+ 'name' => local_group_name
159
+ )
160
+ group_obj.authorize_port_range(
161
+ 8080..8080,
162
+ group: { 'amazon-elb' => dummy_group_obj.group_id }
163
+ )
164
+ fog.security_groups.get_by_id(group_obj.group_id)
165
+ end
166
+
167
+ before do
168
+ allow(ec2lsgrp).to receive(:search).and_return local_group_name
169
+ end
170
+
171
+ it 'prints a source group list containing userId and groupName' do
172
+ expect do
173
+ ec2lsgrp.perms_out('incoming', local_group_obj.ip_permissions)
174
+ end.to output(/ \d+ groups: #{dummy_group_obj.group_id} \(#{dummy_group_name}, owner: amazon-elb\); /).to_stdout
175
+ end
176
+ end
177
+ end
178
+ end