aws-graph 0.0.2
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 +4 -0
- data/README.md +39 -0
- data/Rakefile +1 -0
- data/aws-graph.gemspec +27 -0
- data/bin/aws-graph +5 -0
- data/lib/aws-graph/version.rb +3 -0
- data/lib/aws-graph.rb +208 -0
- data/lib/ec2.png +0 -0
- data/lib/ec2_disactive.png +0 -0
- data/lib/elb.png +0 -0
- data/lib/rds.png +0 -0
- data/sample.png +0 -0
- metadata +128 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 98684500355629aba642dc7d73f4b88f01d40825
|
4
|
+
data.tar.gz: b85e7d15a321c9d25ac7410007bbe6b8efc7eae8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a0c17fbc993ad3773b65783e9071d79c130d9c05c019f2f6a6a2c0f3ef67652871ff3bc8109cbcf2c5ba851cafd690569a0729d33c35a40cf19329db852ed391
|
7
|
+
data.tar.gz: 9915d7062faed34d1413a3e091303b1ad7bdcbfd324777bd1e49969b45b843637f5b9a28ece89ec59c25f30889ac015c8fd1dd6a91298616dbb6e46d995de739
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# aws-graph
|
2
|
+
|
3
|
+
Draw AWS network graph with Graphviz.
|
4
|
+
|
5
|
+
![sample](http://github.com/k1LoW/aws-graph/raw/master/sample.png)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'aws-graph'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install aws-graph
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Make config.yml
|
24
|
+
|
25
|
+
aws_access_key_id: XXXXXXXXXXXXXXXXXXXX
|
26
|
+
aws_secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
27
|
+
aws_region: ap-northeast-1
|
28
|
+
|
29
|
+
And draw graph
|
30
|
+
|
31
|
+
$ aws-graph draw -c config.yml -o output.png
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
1. Fork it ( http://github.com/<my-github-username>/aws-graph/fork )
|
36
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
37
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
38
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
39
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/aws-graph.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'aws-graph/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "aws-graph"
|
8
|
+
spec.version = AwsGraph::VERSION
|
9
|
+
spec.authors = ["k1LoW"]
|
10
|
+
spec.email = ["k1lowxb@gmail.com"]
|
11
|
+
spec.summary = %q{Draw AWS network graph with Graphviz}
|
12
|
+
spec.description = %q{Draw AWS security based network graph with Graphviz}
|
13
|
+
spec.homepage = "https://github.com/k1LoW/aws-graph"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
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.5"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
|
24
|
+
spec.add_dependency "aws-sdk"
|
25
|
+
spec.add_dependency "thor"
|
26
|
+
spec.add_dependency "gviz"
|
27
|
+
end
|
data/bin/aws-graph
ADDED
data/lib/aws-graph.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
require "aws-graph/version"
|
2
|
+
require "thor"
|
3
|
+
require 'aws-sdk'
|
4
|
+
require 'gviz'
|
5
|
+
|
6
|
+
module AwsGraph
|
7
|
+
class CLI < Thor
|
8
|
+
|
9
|
+
desc "draw [config.yml]", "Draw AWS network graph"
|
10
|
+
method_option :config, :type => :string, :aliases => '-c', :default => 'config.yml', :banner => 'AWS config.yml'
|
11
|
+
method_option :output, :type => :string, :aliases => '-o', :default => 'output.png', :banner => 'output file path'
|
12
|
+
method_option :secret, :type => :boolean, :aliases => '-s', :default => false, :banner => 'mask label'
|
13
|
+
def draw()
|
14
|
+
yml = options[:config]
|
15
|
+
self.load(yml)
|
16
|
+
self.sg()
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
def sg()
|
21
|
+
gv = Gviz.new(:AWS, :digraph)
|
22
|
+
|
23
|
+
ec2_instances = @ec2.instances # EC2 instances
|
24
|
+
vpcs = @ec2.vpcs # VPC Collection
|
25
|
+
security_groups = @ec2.security_groups # EC2 security groups
|
26
|
+
rds_client = @rds.client # RDS low level client
|
27
|
+
db_instances = rds_client.describe_db_instances
|
28
|
+
db_security_groups = rds_client.describe_db_security_groups
|
29
|
+
lbs = @elb.load_balancers # ELB
|
30
|
+
|
31
|
+
secret = options[:secret]
|
32
|
+
|
33
|
+
gv.graph do
|
34
|
+
global layout:'fdp', overlap:false, compound:true, rankdir:'LR'
|
35
|
+
edges lhead: '', ltail: ''
|
36
|
+
nodes shape: 'box'
|
37
|
+
|
38
|
+
sg_hash = {}
|
39
|
+
|
40
|
+
# Create EC2 security group cluster
|
41
|
+
security_groups.each do | sg |
|
42
|
+
print "."
|
43
|
+
cluster_id = 'cluster' + sg.id.gsub(/[-\/]/,'')
|
44
|
+
sg_hash[sg.id] = cluster_id
|
45
|
+
subgraph(cluster_id.to_sym) do
|
46
|
+
global label: Util.new.label(sg.name + '[' + sg.id + ']', secret), style: 'rounded'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Create RDS security group cluster
|
51
|
+
db_security_groups[:db_security_groups].each do | db_sg |
|
52
|
+
print "."
|
53
|
+
cluster_id = 'cluster' + db_sg[:db_security_group_name].gsub(/[-\/]/,'')
|
54
|
+
subgraph(cluster_id.to_sym) do
|
55
|
+
global label: Util.new.label(db_sg[:db_security_group_name], secret), style: 'rounded'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Append EC2 to EC2 security group
|
60
|
+
ec2_instances.each do | e |
|
61
|
+
if e.status == :running
|
62
|
+
image_path = File.dirname(__FILE__) + '/ec2.png'
|
63
|
+
else
|
64
|
+
image_path = File.dirname(__FILE__) + '/ec2_disactive.png'
|
65
|
+
end
|
66
|
+
e.security_groups.each do | sg |
|
67
|
+
print "."
|
68
|
+
cluster_id = 'cluster' + sg.id.gsub(/[-\/]/,'')
|
69
|
+
subgraph(cluster_id.to_sym) do
|
70
|
+
node (sg.id + ':' + e.id).gsub(/[-\/]/, '').to_sym, label: Util.new.label(e.id, secret), shape: :none, image: image_path
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Append VPC EC2 to EC2 security group
|
76
|
+
vpcs.each do | vpc |
|
77
|
+
vpc.instances.each do | e |
|
78
|
+
if e.status == :running
|
79
|
+
image_path = File.dirname(__FILE__) + '/ec2.png'
|
80
|
+
else
|
81
|
+
image_path = File.dirname(__FILE__) + '/ec2_disactive.png'
|
82
|
+
end
|
83
|
+
e.security_groups.each do | sg |
|
84
|
+
print "v"
|
85
|
+
cluster_id = 'cluster' + sg.id.gsub(/[-\/]/,'')
|
86
|
+
subgraph(cluster_id.to_sym) do
|
87
|
+
node (sg.id + ':' + e.id).gsub(/[-\/]/, '').to_sym, label: Util.new.label(e.id, secret), shape: :none, image: image_path
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Append RDS to RDS security group
|
94
|
+
db_instancesa = {}
|
95
|
+
db_instances[:db_instances].each do | r |
|
96
|
+
r[:db_security_groups].each do | db_sg |
|
97
|
+
print "."
|
98
|
+
cluster_id = 'cluster' + db_sg[:db_security_group_name].gsub(/[-\/]/,'')
|
99
|
+
image_path = File.dirname(__FILE__) + '/rds.png'
|
100
|
+
subgraph(cluster_id.to_sym) do
|
101
|
+
node (r[:db_instance_identifier]).gsub(/[-\/]/, '').to_sym, label: Util.new.label(r[:db_instance_identifier], secret), shape: :none, image: image_path
|
102
|
+
end
|
103
|
+
end
|
104
|
+
r[:vpc_security_groups].each do | sg |
|
105
|
+
print "v"
|
106
|
+
cluster_id = 'cluster' + sg[:vpc_security_group_id].gsub(/[-\/]/,'')
|
107
|
+
image_path = File.dirname(__FILE__) + '/rds.png'
|
108
|
+
subgraph(cluster_id.to_sym) do
|
109
|
+
node (r[:db_instance_identifier]).gsub(/[-\/]/, '').to_sym, label: Util.new.label(r[:db_instance_identifier], secret), shape: :none, image: image_path
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Add edges EC2 security group
|
115
|
+
security_groups.each do | sg |
|
116
|
+
ips = sg.ingress_ip_permissions # inbound permissions
|
117
|
+
ips.each do | ip |
|
118
|
+
|
119
|
+
# EC2 security group -> EC2 security group
|
120
|
+
ip.groups.each do | fromsg |
|
121
|
+
next if fromsg.id == sg.id
|
122
|
+
print "-"
|
123
|
+
unless sg_hash[fromsg.id]
|
124
|
+
# Unknown security group is amazon-elb/amazon-elb-sg
|
125
|
+
unknown = AWS::EC2::SecurityGroup.new(fromsg.id)
|
126
|
+
cluster_id = 'cluster' + fromsg.id.gsub(/[-\/]/,'')
|
127
|
+
sg_hash['amazon-elb/amazon-elb-sg'] = cluster_id
|
128
|
+
subgraph(cluster_id.to_sym) do
|
129
|
+
global label: Util.new.label('amazon-elb/amazon-elb-sg', false), style: 'rounded'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
from_cluster_id = 'cluster' + fromsg.id.gsub(/[-\/]/,'')
|
133
|
+
to_cluster_id = 'cluster' + sg.id.gsub(/[-\/]/,'')
|
134
|
+
route from_cluster_id.to_sym => to_cluster_id.to_sym
|
135
|
+
edge (from_cluster_id + '_' + to_cluster_id).to_sym, label: Util.new.label(ip.port_range.to_s + '[' + ip.protocol.to_s + ']', secret)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# EC2 security group -> RDS security group
|
141
|
+
db_security_groups[:db_security_groups].each do | db_sg |
|
142
|
+
print "-"
|
143
|
+
db_sg[:ec2_security_groups].each do | sg |
|
144
|
+
if sg[:ec2_security_group_id]
|
145
|
+
from_cluster_id = 'cluster' + sg[:ec2_security_group_id].gsub(/[-\/]/,'')
|
146
|
+
to_cluster_id = 'cluster' + db_sg[:db_security_group_name].gsub(/[-\/]/,'')
|
147
|
+
route from_cluster_id.to_sym => to_cluster_id.to_sym
|
148
|
+
edge (from_cluster_id + '_' + to_cluster_id).to_sym, label: 'RDS'
|
149
|
+
else
|
150
|
+
# なぜかdb_security_group_idが存在しないものがある
|
151
|
+
security_groups.each do | s |
|
152
|
+
if s.name == sg[:ec2_security_group_name]
|
153
|
+
from_cluster_id = 'cluster' + s.id.gsub(/[-\/]/,'')
|
154
|
+
to_cluster_id = 'cluster' + db_sg[:db_security_group_name].gsub(/[-\/]/,'')
|
155
|
+
route from_cluster_id.to_sym => to_cluster_id.to_sym
|
156
|
+
edge (from_cluster_id + '_' + to_cluster_id).to_sym, label: 'RDS'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Append ELB to ELB security group
|
164
|
+
lbs.each do | lb |
|
165
|
+
break unless sg_hash['amazon-elb/amazon-elb-sg']
|
166
|
+
cluster_id = sg_hash['amazon-elb/amazon-elb-sg']
|
167
|
+
image_path = File.dirname(__FILE__) + '/elb.png'
|
168
|
+
subgraph(cluster_id.to_sym) do
|
169
|
+
node lb.name.gsub('-', '').to_sym, label: Util.new.label(lb.name, secret), shape: :none, image: image_path
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
puts ''
|
174
|
+
end
|
175
|
+
gv.save(options[:output].sub(/\.png$/,''), :png)
|
176
|
+
end
|
177
|
+
|
178
|
+
protected
|
179
|
+
def load(yml)
|
180
|
+
@config = YAML.load_file(yml)
|
181
|
+
@ec2 = AWS::EC2.new(
|
182
|
+
:access_key_id => @config['aws_access_key_id'],
|
183
|
+
:secret_access_key => @config['aws_secret_access_key'],
|
184
|
+
:region => @config['aws_region'],
|
185
|
+
)
|
186
|
+
@rds = AWS::RDS.new(
|
187
|
+
:access_key_id => @config['aws_access_key_id'],
|
188
|
+
:secret_access_key => @config['aws_secret_access_key'],
|
189
|
+
:region => @config['aws_region'],
|
190
|
+
)
|
191
|
+
@elb = AWS::ELB.new(
|
192
|
+
:access_key_id => @config['aws_access_key_id'],
|
193
|
+
:secret_access_key => @config['aws_secret_access_key'],
|
194
|
+
:region => @config['aws_region'],
|
195
|
+
)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
class Util
|
200
|
+
def label(text, secret)
|
201
|
+
if secret
|
202
|
+
return text.gsub(/[^\[\]]/,'*')
|
203
|
+
else
|
204
|
+
return text
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
data/lib/ec2.png
ADDED
Binary file
|
Binary file
|
data/lib/elb.png
ADDED
Binary file
|
data/lib/rds.png
ADDED
Binary file
|
data/sample.png
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aws-graph
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- k1LoW
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: aws-sdk
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: gviz
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Draw AWS security based network graph with Graphviz
|
84
|
+
email:
|
85
|
+
- k1lowxb@gmail.com
|
86
|
+
executables:
|
87
|
+
- aws-graph
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- .gitignore
|
92
|
+
- Gemfile
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- aws-graph.gemspec
|
96
|
+
- bin/aws-graph
|
97
|
+
- lib/aws-graph.rb
|
98
|
+
- lib/aws-graph/version.rb
|
99
|
+
- lib/ec2.png
|
100
|
+
- lib/ec2_disactive.png
|
101
|
+
- lib/elb.png
|
102
|
+
- lib/rds.png
|
103
|
+
- sample.png
|
104
|
+
homepage: https://github.com/k1LoW/aws-graph
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.0.14
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Draw AWS network graph with Graphviz
|
128
|
+
test_files: []
|