awsutils 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +58 -0
- data/Rakefile +11 -0
- data/awsutils.gemspec +33 -0
- data/bin/ec2addsg +14 -0
- data/bin/ec2delsg +14 -0
- data/bin/ec2info +13 -0
- data/bin/ec2latestimage +12 -0
- data/bin/ec2listmachines +13 -0
- data/bin/ec2lsgrp +25 -0
- data/bin/elbls +13 -0
- data/bin/r53ls +14 -0
- data/lib/awsutils.rb +1 -0
- data/lib/awsutils/ec2addsg.rb +200 -0
- data/lib/awsutils/ec2delsg.rb +96 -0
- data/lib/awsutils/ec2info.rb +701 -0
- data/lib/awsutils/ec2latestimage.rb +84 -0
- data/lib/awsutils/ec2listmachines.rb +406 -0
- data/lib/awsutils/ec2lsgrp.rb +91 -0
- data/lib/awsutils/ec2sg.rb +77 -0
- data/lib/awsutils/elbls.rb +51 -0
- data/lib/awsutils/r53addrr.rb +28 -0
- data/lib/awsutils/r53ls.rb +92 -0
- data/lib/awsutils/version.rb +3 -0
- data/spec/lib/awsutils/ec2addsg_spec.rb +11 -0
- data/spec/lib/awsutils/ec2lsgrp_spec.rb +178 -0
- data/spec/spec_helper.rb +10 -0
- metadata +238 -0
@@ -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,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
|