sgviz 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b5fb5e9336b59957898dee4d98ae5e9f25a04b49
4
+ data.tar.gz: 38da4f2f906e141d05e4e99f01dfb11de18f1605
5
+ SHA512:
6
+ metadata.gz: 908045418f324d4094d2b69c681cf189235a8d3d9f5daf2fe9ed75291e12f16524cde17b78ccd0666778c8b2049e1ee47518ddead734975847e9127934b49461
7
+ data.tar.gz: 2ebcda6849078ddca64d553a8467a06f7da75d53148a764fea7d23288d8bfa00b6ff3a55220d6ba92563404ac7147e35bbad7ab8dfc870ac94a7f9721b2e2af2
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ vendor
16
+ result.json
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sgviz.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 y13i
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # Sgviz
2
+
3
+ A visualization tool for AWS VPC Security Groups.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'sgviz'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```bash
22
+ $ gem install sgviz
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ```bash
28
+ $ sgviz generate --output-path myvpc --region ap-northeast-1 --vpc-ids vpc-146fad71
29
+ ```
30
+
31
+ will generate
32
+
33
+ ![myvpc](docs/images/1.png)
34
+
35
+ If you're using OSX, run `sgviz open` to view the graph instantly.
36
+
37
+ Run `sgviz help` to view more usage.
38
+
39
+ ## CloudFormation Template
40
+
41
+ You can create example stack using bundled CloudFormation template.
42
+
43
+ ```bash
44
+ $ aws cloudformation create-stack --stack-name example --template-body file:////path/to/this/repo/docs/cfn/example.json
45
+ ```
46
+
47
+ Or use [Kumogata](https://github.com/winebarrel/kumogata), powerful Ruby-CFn integration tool.
48
+
49
+ ```bash
50
+ $ kumogata create docs/cfn/example.rb example
51
+ ```
52
+
53
+ ## TODO, Known Bugs
54
+
55
+ * Bug: Problem with outbound edges (duplicate with inbound?).
56
+ * TODO: Internal IP address nodes.
57
+ * TODO: VPC Peerings.
58
+ * TODO: Add spec. (No test code now. Sorry.)
59
+ * TODO: Integrate EC2/ELB/RDS/ElastiCache/Redshift components in graph.
60
+ * etc...
61
+
62
+ ## Contributing
63
+
64
+ 1. Fork it ( https://github.com/y13i/sgviz/fork )
65
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
66
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
67
+ 4. Push to the branch (`git push origin my-new-feature`)
68
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/sgviz ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "sgviz"
4
+
5
+ Sgviz::CLI.start
@@ -0,0 +1,222 @@
1
+ {
2
+ "AWSTemplateFormatVersion": "2010-09-09",
3
+ "Description": "Sgviz example security group set template (Donburi version).\n",
4
+ "Resources": {
5
+ "Vpc": {
6
+ "Type": "AWS::EC2::VPC",
7
+ "Properties": {
8
+ "CidrBlock": "10.0.0.0/16"
9
+ }
10
+ },
11
+ "ManageSecurityGroup": {
12
+ "Type": "AWS::EC2::SecurityGroup",
13
+ "Properties": {
14
+ "GroupDescription": "Security group for manage role EC2 instances.",
15
+ "VpcId": {
16
+ "Ref": "Vpc"
17
+ },
18
+ "SecurityGroupIngress": [
19
+ {
20
+ "CidrIp": "123.45.67.89/32",
21
+ "IpProtocol": "tcp",
22
+ "FromPort": "22",
23
+ "ToPort": "22"
24
+ },
25
+ {
26
+ "CidrIp": "123.45.67.89/32",
27
+ "IpProtocol": "tcp",
28
+ "FromPort": "80",
29
+ "ToPort": "80"
30
+ },
31
+ {
32
+ "CidrIp": "123.45.67.89/32",
33
+ "IpProtocol": "tcp",
34
+ "FromPort": "443",
35
+ "ToPort": "443"
36
+ },
37
+ {
38
+ "CidrIp": "234.56.78.90/32",
39
+ "IpProtocol": "tcp",
40
+ "FromPort": "22",
41
+ "ToPort": "22"
42
+ },
43
+ {
44
+ "CidrIp": "234.56.78.90/32",
45
+ "IpProtocol": "tcp",
46
+ "FromPort": "80",
47
+ "ToPort": "80"
48
+ },
49
+ {
50
+ "CidrIp": "234.56.78.90/32",
51
+ "IpProtocol": "tcp",
52
+ "FromPort": "443",
53
+ "ToPort": "443"
54
+ }
55
+ ],
56
+ "Tags": [
57
+ {
58
+ "Key": "Name",
59
+ "Value": "manage"
60
+ }
61
+ ]
62
+ }
63
+ },
64
+ "AppLoadBalancerSecurityGroup": {
65
+ "Type": "AWS::EC2::SecurityGroup",
66
+ "Properties": {
67
+ "GroupDescription": "Security group for application load balancer.",
68
+ "VpcId": {
69
+ "Ref": "Vpc"
70
+ },
71
+ "SecurityGroupIngress": [
72
+ {
73
+ "CidrIp": "0.0.0.0/0",
74
+ "IpProtocol": "tcp",
75
+ "FromPort": "80",
76
+ "ToPort": "80"
77
+ },
78
+ {
79
+ "CidrIp": "0.0.0.0/0",
80
+ "IpProtocol": "tcp",
81
+ "FromPort": "443",
82
+ "ToPort": "443"
83
+ }
84
+ ],
85
+ "Tags": [
86
+ {
87
+ "Key": "Name",
88
+ "Value": "app_load_balancer"
89
+ }
90
+ ]
91
+ }
92
+ },
93
+ "AppSecurityGroup": {
94
+ "Type": "AWS::EC2::SecurityGroup",
95
+ "Properties": {
96
+ "GroupDescription": "Security group for application EC2 instances.",
97
+ "VpcId": {
98
+ "Ref": "Vpc"
99
+ },
100
+ "SecurityGroupIngress": [
101
+ {
102
+ "SourceSecurityGroupId": {
103
+ "Ref": "AppLoadBalancerSecurityGroup"
104
+ },
105
+ "IpProtocol": "tcp",
106
+ "FromPort": "80",
107
+ "ToPort": "80"
108
+ },
109
+ {
110
+ "SourceSecurityGroupId": {
111
+ "Ref": "ManageSecurityGroup"
112
+ },
113
+ "IpProtocol": "tcp",
114
+ "FromPort": "22",
115
+ "ToPort": "22"
116
+ },
117
+ {
118
+ "SourceSecurityGroupId": {
119
+ "Ref": "ManageSecurityGroup"
120
+ },
121
+ "IpProtocol": "tcp",
122
+ "FromPort": "10050",
123
+ "ToPort": "10050"
124
+ }
125
+ ],
126
+ "Tags": [
127
+ {
128
+ "Key": "Name",
129
+ "Value": "app"
130
+ }
131
+ ]
132
+ }
133
+ },
134
+ "Port10051IngressFromAppToManage": {
135
+ "Type": "AWS::EC2::SecurityGroupIngress",
136
+ "Properties": {
137
+ "GroupId": {
138
+ "Ref": "ManageSecurityGroup"
139
+ },
140
+ "SourceSecurityGroupId": {
141
+ "Ref": "AppSecurityGroup"
142
+ },
143
+ "IpProtocol": "tcp",
144
+ "FromPort": "10051",
145
+ "ToPort": "10051"
146
+ }
147
+ },
148
+ "RedisSecurityGroup": {
149
+ "Type": "AWS::EC2::SecurityGroup",
150
+ "Properties": {
151
+ "GroupDescription": "Security group for ElastiCache Redis clusters.",
152
+ "VpcId": {
153
+ "Ref": "Vpc"
154
+ },
155
+ "SecurityGroupIngress": [
156
+ {
157
+ "SourceSecurityGroupId": {
158
+ "Ref": "ManageSecurityGroup"
159
+ },
160
+ "IpProtocol": "tcp",
161
+ "FromPort": "6379",
162
+ "ToPort": "6379"
163
+ },
164
+ {
165
+ "SourceSecurityGroupId": {
166
+ "Ref": "AppSecurityGroup"
167
+ },
168
+ "IpProtocol": "tcp",
169
+ "FromPort": "6379",
170
+ "ToPort": "6379"
171
+ }
172
+ ],
173
+ "Tags": [
174
+ {
175
+ "Key": "Name",
176
+ "Value": "redis"
177
+ }
178
+ ]
179
+ }
180
+ },
181
+ "MysqlSecurityGroup": {
182
+ "Type": "AWS::EC2::SecurityGroup",
183
+ "Properties": {
184
+ "GroupDescription": "Security group for RDS MySQL DB instances.",
185
+ "VpcId": {
186
+ "Ref": "Vpc"
187
+ },
188
+ "SecurityGroupIngress": [
189
+ {
190
+ "SourceSecurityGroupId": {
191
+ "Ref": "ManageSecurityGroup"
192
+ },
193
+ "IpProtocol": "tcp",
194
+ "FromPort": "3306",
195
+ "ToPort": "3306"
196
+ },
197
+ {
198
+ "SourceSecurityGroupId": {
199
+ "Ref": "AppSecurityGroup"
200
+ },
201
+ "IpProtocol": "tcp",
202
+ "FromPort": "3306",
203
+ "ToPort": "3306"
204
+ }
205
+ ],
206
+ "Tags": [
207
+ {
208
+ "Key": "Name",
209
+ "Value": "mysql"
210
+ }
211
+ ]
212
+ }
213
+ }
214
+ },
215
+ "Outputs": {
216
+ "Vpc": {
217
+ "Value": {
218
+ "Ref": "Vpc"
219
+ }
220
+ }
221
+ }
222
+ }
@@ -0,0 +1,177 @@
1
+ AWSTemplateFormatVersion "2010-09-09"
2
+
3
+ Description <<-EOS.undent
4
+ Sgviz example security group set template (Donburi version).
5
+ EOS
6
+
7
+ Resources do
8
+ Vpc do
9
+ Type "AWS::EC2::VPC"
10
+
11
+ Properties do
12
+ CidrBlock "10.0.0.0/16"
13
+ end
14
+ end
15
+
16
+ ManageSecurityGroup do
17
+ Type "AWS::EC2::SecurityGroup"
18
+
19
+ Properties do
20
+ GroupDescription "Security group for manage role EC2 instances."
21
+ VpcId {Ref "Vpc"}
22
+
23
+ SecurityGroupIngress(
24
+ ["123.45.67.89/32", "234.56.78.90/32", ].product([22, 80, 443]).map do |my_ip, port|
25
+ _{
26
+ CidrIp my_ip
27
+ IpProtocol "tcp"
28
+ FromPort port
29
+ ToPort port
30
+ }
31
+ end
32
+ )
33
+
34
+ Tags [
35
+ _{
36
+ Key "Name"
37
+ Value "manage"
38
+ }
39
+ ]
40
+ end
41
+ end
42
+
43
+ AppLoadBalancerSecurityGroup do
44
+ Type "AWS::EC2::SecurityGroup"
45
+
46
+ Properties do
47
+ GroupDescription "Security group for application load balancer."
48
+ VpcId {Ref "Vpc"}
49
+
50
+ SecurityGroupIngress(
51
+ [80, 443].map do |port|
52
+ _{
53
+ CidrIp "0.0.0.0/0"
54
+ IpProtocol "tcp"
55
+ FromPort port
56
+ ToPort port
57
+ }
58
+ end
59
+ )
60
+
61
+ Tags [
62
+ _{
63
+ Key "Name"
64
+ Value "app_load_balancer"
65
+ }
66
+ ]
67
+ end
68
+ end
69
+
70
+ AppSecurityGroup do
71
+ Type "AWS::EC2::SecurityGroup"
72
+
73
+ Properties do
74
+ GroupDescription "Security group for application EC2 instances."
75
+ VpcId {Ref "Vpc"}
76
+
77
+ SecurityGroupIngress [
78
+ _{
79
+ SourceSecurityGroupId {Ref "AppLoadBalancerSecurityGroup"}
80
+ IpProtocol "tcp"
81
+ FromPort 80
82
+ ToPort 80
83
+ },
84
+
85
+ *[22, 10050].map do |port|
86
+ _{
87
+ SourceSecurityGroupId {Ref "ManageSecurityGroup"}
88
+ IpProtocol "tcp"
89
+ FromPort port
90
+ ToPort port
91
+ }
92
+ end
93
+ ]
94
+
95
+ Tags [
96
+ _{
97
+ Key "Name"
98
+ Value "app"
99
+ }
100
+ ]
101
+ end
102
+ end
103
+
104
+ Port10051IngressFromAppToManage do
105
+ Type "AWS::EC2::SecurityGroupIngress"
106
+
107
+ Properties do
108
+ GroupId {Ref "ManageSecurityGroup"}
109
+ SourceSecurityGroupId {Ref "AppSecurityGroup"}
110
+ IpProtocol "tcp"
111
+ FromPort 10051
112
+ ToPort 10051
113
+ end
114
+ end
115
+
116
+ RedisSecurityGroup do
117
+ Type "AWS::EC2::SecurityGroup"
118
+
119
+ Properties do
120
+ GroupDescription "Security group for ElastiCache Redis clusters."
121
+ VpcId {Ref "Vpc"}
122
+
123
+ SecurityGroupIngress(
124
+ ["Manage", "App"].map do |role|
125
+ _{
126
+ SourceSecurityGroupId {Ref "#{role}SecurityGroup"}
127
+ IpProtocol "tcp"
128
+ FromPort 6379
129
+ ToPort 6379
130
+ }
131
+ end
132
+ )
133
+
134
+ Tags [
135
+ _{
136
+ Key "Name"
137
+ Value "redis"
138
+ }
139
+ ]
140
+ end
141
+ end
142
+
143
+ MysqlSecurityGroup do
144
+ Type "AWS::EC2::SecurityGroup"
145
+
146
+ Properties do
147
+ GroupDescription "Security group for RDS MySQL DB instances."
148
+ VpcId {Ref "Vpc"}
149
+
150
+ SecurityGroupIngress(
151
+ ["Manage", "App"].map do |role|
152
+ _{
153
+ SourceSecurityGroupId {Ref "#{role}SecurityGroup"}
154
+ IpProtocol "tcp"
155
+ FromPort 3306
156
+ ToPort 3306
157
+ }
158
+ end
159
+ )
160
+
161
+ Tags [
162
+ _{
163
+ Key "Name"
164
+ Value "mysql"
165
+ }
166
+ ]
167
+ end
168
+ end
169
+ end
170
+
171
+ Outputs do
172
+ Vpc do
173
+ Value do
174
+ Ref "Vpc"
175
+ end
176
+ end
177
+ end
data/docs/images/1.png ADDED
Binary file
data/lib/sgviz/cli.rb ADDED
@@ -0,0 +1,80 @@
1
+ require "thor"
2
+
3
+ class Sgviz::CLI < Thor
4
+ class_option :profile,
5
+ desc: "Load credentials by profile name from shared credentials file (~/.aws/credentials).",
6
+ aliases: [:p]
7
+
8
+ class_option :access_key_id,
9
+ desc: "AWS access key id.",
10
+ aliases: [:k]
11
+
12
+ class_option :secret_access_key,
13
+ desc: "AWS secret access key.",
14
+ aliases: [:s]
15
+
16
+ class_option :region,
17
+ desc: "AWS region.",
18
+ aliases: [:r]
19
+
20
+ class_option :format,
21
+ desc: "Output file format",
22
+ aliases: [:f],
23
+ default: "png"
24
+
25
+ class_option :output_path,
26
+ desc: "Output file path.",
27
+ aliases: [:output, :o]
28
+
29
+ class_option :vpc_ids,
30
+ desc: "AWS VPC IDs (If specified, graph will include security groups in the VPCs).",
31
+ aliases: [:vpcs, :vpc, :v],
32
+ type: :array
33
+
34
+ class_option :inbound_only,
35
+ desc: "If specified, graph will exclude outbound rules.",
36
+ type: :boolean,
37
+ default: true
38
+
39
+ class_option :global_label,
40
+ desc: "Label of the diagram.",
41
+ default: ""
42
+
43
+ class_option :fontname,
44
+ desc: "Font name used on labels.",
45
+ default: "Futura"
46
+
47
+ class_option :fontsize,
48
+ desc: "Font size used on labels.",
49
+ type: :numeric,
50
+ default: 15
51
+
52
+ desc "version", "Puts sgviz version."
53
+ def version
54
+ puts Sgviz::VERSION
55
+ end
56
+
57
+ desc "open", "Generate and open a graph file."
58
+ method_option :output_path, required: true
59
+ def open
60
+ unless system "which open > /dev/null"
61
+ abort "`open` command not found."
62
+ end
63
+
64
+ generate
65
+ system "open #{options.output_path}.#{options.format}"
66
+ end
67
+
68
+ desc "generate", "Generate a graph file."
69
+ method_option :output_path, required: true
70
+ def generate
71
+ generator.generate
72
+ puts "Graph generated to `#{options.output_path}.#{options.format}`."
73
+ end
74
+
75
+ private
76
+
77
+ def generator
78
+ @generator ||= Sgviz::Generator.new :G, :digraph, options
79
+ end
80
+ end
@@ -0,0 +1,251 @@
1
+ require "gviz"
2
+ require "aws-sdk-resources"
3
+
4
+ class Sgviz::Generator < Gviz
5
+ def initialize name = :G, type = :digraph, options = {}
6
+ @options = options
7
+ super(name, type)
8
+ end
9
+
10
+ def subgraph(name=:"cluster#{subgraphs.size}", &blk)
11
+ self.class.new(name, :subgraph, options).tap do |graph|
12
+ subgraphs << graph
13
+ graph.instance_eval &blk
14
+ end
15
+ end
16
+
17
+ def generate
18
+ global(
19
+ layout: "dot",
20
+ label: options.global_label,
21
+ labelloc: "b",
22
+ fontsize: options.fontsize,
23
+ fontname: options.fontname,
24
+ fontcolor: "#54523F",
25
+ margin: 20,
26
+ )
27
+
28
+ nodes(
29
+ fontsize: options.fontsize,
30
+ fontname: options.fontname,
31
+ )
32
+
33
+ vpc_security_groups.each do |vpc_id, security_groups|
34
+ security_groups.each do |security_group|
35
+ subgraph :clusterAWS do
36
+ global(
37
+ label: aws_configuration[:region],
38
+ labelloc: "b",
39
+ style: "rounded",
40
+ color: "#999999",
41
+ fontsize: options.fontsize,
42
+ fontname: options.fontname,
43
+ fontcolor: "#54523F",
44
+ margin: 20,
45
+ )
46
+
47
+ node :aws,
48
+ label: "",
49
+ image: "#{__dir__}/images/aws.png",
50
+ peripheries: 0,
51
+ fixedsize: true,
52
+ imagescale: true,
53
+ shape: "circle",
54
+ width: 1.5
55
+
56
+ subgraph :"cluster#{vpc_id[4..-1]}" do
57
+ global(
58
+ label: vpc_id,
59
+ labelloc: "b",
60
+ style: "rounded",
61
+ color: "#999999",
62
+ fontsize: options.fontsize,
63
+ fontname: options.fontname,
64
+ fontcolor: "#54523F",
65
+ margin: 20,
66
+ )
67
+
68
+ node vpc_id.to_id,
69
+ label: "",
70
+ image: "#{__dir__}/images/vpc.png",
71
+ peripheries: 0,
72
+ fixedsize: true,
73
+ imagescale: true,
74
+ shape: "circle",
75
+ width: 1.5
76
+
77
+ name_tag = security_group.tags.find {|tag| tag.key == "Name"}
78
+
79
+ node security_group.id.to_id,
80
+ shape: "note",
81
+ style: "filled",
82
+ color: "#EDEAD2",
83
+ fillcolor: "#EDEAD2",
84
+ label: "#{name_tag ? name_tag.value : security_group.group_name}\n(#{security_group.id})",
85
+ fontsize: options.fontsize,
86
+ fontname: options.fontname,
87
+ fontcolor: "#54523F",
88
+ margin: 0.2
89
+ end
90
+ end
91
+
92
+ security_group.ip_permissions.each do |ip_permission|
93
+ to = security_group.id.to_id
94
+
95
+ ip_permission.ip_ranges.each do |ip_range|
96
+ from = ip_range.cidr_ip.to_id
97
+
98
+ node from,
99
+ shape: "ellipse",
100
+ style: "filled",
101
+ color: "#E7FAFF",
102
+ fillcolor: "#E7FAFF",
103
+ label: ip_range.cidr_ip,
104
+ fontsize: options.fontsize,
105
+ fontname: options.fontname,
106
+ fontcolor: "#003E2F"
107
+
108
+ add_route :inbound, from, to, ip_permission
109
+ end
110
+
111
+ ip_permission.user_id_group_pairs.each do |user_id_group_pair|
112
+ from = if user_id_group_pair.user_id == security_group.owner_id
113
+ user_id_group_pair.group_id.to_id
114
+ else
115
+ node xaccount_sg(user_id_group_pair).to_id, xaccount_sg(user_id_group_pair)
116
+ xaccount_sg(user_id_group_pair).to_id
117
+ end
118
+
119
+ add_route :inbound, from, to, ip_permission
120
+ end
121
+ end
122
+
123
+ unless options.inbound_only
124
+ security_group.ip_permissions_egress.each do |ip_permission|
125
+ from = security_group.id.to_id
126
+
127
+ ip_permission.ip_ranges.each do |ip_range|
128
+ to = ip_range.cidr_ip.to_id
129
+
130
+ node to,
131
+ shape: "ellipse",
132
+ style: "filled",
133
+ color: "#E7FAFF",
134
+ fillcolor: "#E7FAFF",
135
+ label: ip_range.cidr_ip,
136
+ fontsize: options.fontsize,
137
+ fontname: options.fontname,
138
+ fontcolor: "#003E2F"
139
+
140
+ add_route :outbound, from, to, ip_permission
141
+ end
142
+
143
+ ip_permission.user_id_group_pairs.each do |user_id_group_pair|
144
+ to = if user_id_group_pair.user_id == security_group.owner_id
145
+ user_id_group_pair.group_id.to_id
146
+ else
147
+ node xaccount_sg(user_id_group_pair).to_id, xaccount_sg(user_id_group_pair)
148
+ xaccount_sg(user_id_group_pair).to_id
149
+ end
150
+
151
+ add_route :outbound, from, to, ip_permission
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ node "0.0.0.0/0".to_id,
159
+ label: "",
160
+ image: "#{__dir__}/images/internet.png",
161
+ peripheries: 0,
162
+ fixedsize: true,
163
+ imagescale: true,
164
+ shape: "circle",
165
+ width: 1.67
166
+
167
+ save options.output_path, options.format
168
+ end
169
+
170
+ private
171
+
172
+ def options
173
+ @options
174
+ end
175
+
176
+ def aws_configuration
177
+ hash = {}
178
+
179
+ [:profile, :access_key_id, :secret_access_key, :region].each do |option|
180
+ hash.update(option => options[option]) if options[option]
181
+ end
182
+
183
+ hash.update(region: own_region) if hash[:region].nil?
184
+ hash
185
+ end
186
+
187
+ def own_region
188
+ @own_region ||= begin
189
+ require "net/http"
190
+
191
+ timeout 3 do
192
+ Net::HTTP.get("169.254.169.254", "/latest/meta-data/placement/availability-zone").chop
193
+ end
194
+ rescue
195
+ nil
196
+ end
197
+ end
198
+
199
+ def ec2
200
+ @ec2 ||= Aws::EC2::Resource.new aws_configuration
201
+ end
202
+
203
+ # returns Hash like `{"vpc-1111111" => [sg1, sg2, ...], "vpc-11111112" => [sg3, sg4, ...], ...}`
204
+ def vpc_security_groups
205
+ ec2.security_groups.group_by(&:vpc_id).select do |vpc_id|
206
+ if options.vpc_ids
207
+ options.vpc_ids.include? vpc_id
208
+ else
209
+ true
210
+ end
211
+ end
212
+ end
213
+
214
+ def xaccount_sg user_id_group_pair
215
+ "#{user_id_group_pair.user_id}/#{user_id_group_pair.group_id}"
216
+ end
217
+
218
+ def add_route in_or_out = :inbound, from, to, ip_permission
219
+ id = :"#{from}_#{to}"
220
+ color = (in_or_out == :inbound ? "#003E2F" : "#045280")
221
+
222
+ traffic_map[id] = if traffic_map[id]
223
+ [traffic_map[id], route_label(ip_permission)].join("\\n")
224
+ else
225
+ route_label(ip_permission)
226
+ end
227
+
228
+ edge id,
229
+ label: traffic_map[id],
230
+ style: "bold",
231
+ arrowhead: (in_or_out == :inbound ? "normal" : "onormal"),
232
+ color: color,
233
+ fontname: options.fontname,
234
+ fontsize: (options.fontsize * 0.75),
235
+ fontcolor: color
236
+ end
237
+
238
+ def traffic_map
239
+ @traffic_map ||= {}
240
+ end
241
+
242
+ def route_label ip_permission
243
+ if ip_permission.ip_protocol == "-1"
244
+ "All Traffic"
245
+ elsif ip_permission.from_port == ip_permission.to_port
246
+ "#{ip_permission.ip_protocol.upcase}:#{ip_permission.to_port}"
247
+ else
248
+ "#{ip_permission.ip_protocol.upcase}:#{ip_permission.from_port}-#{ip_permission.to_port}"
249
+ end
250
+ end
251
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ module Sgviz
2
+ VERSION = "0.0.1"
3
+ end
data/lib/sgviz.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "sgviz/version"
2
+ require "sgviz/generator"
3
+ require "sgviz/cli"
data/sgviz.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sgviz/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sgviz"
8
+ spec.version = Sgviz::VERSION
9
+ spec.authors = ["y13i"]
10
+ spec.email = ["email@y13i.com"]
11
+ spec.summary = %(Visualize VPC Security Groups.)
12
+ spec.description = %(A visualization tool for AWS VPC Security Groups.)
13
+ spec.homepage = "https://github.com/y13i/sgviz"
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.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+
24
+ spec.add_dependency "gviz"
25
+ spec.add_dependency "thor"
26
+ spec.add_dependency "aws-sdk-resources"
27
+ spec.add_dependency "aws-sdk-core"
28
+
29
+ spec.add_development_dependency "pry"
30
+ spec.add_development_dependency "awesome_print"
31
+ spec.add_development_dependency "kumogata"
32
+ end
metadata ADDED
@@ -0,0 +1,188 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sgviz
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - y13i
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-02 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.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: gviz
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: aws-sdk-resources
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
+ - !ruby/object:Gem::Dependency
84
+ name: aws-sdk-core
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: awesome_print
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: kumogata
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: A visualization tool for AWS VPC Security Groups.
140
+ email:
141
+ - email@y13i.com
142
+ executables:
143
+ - sgviz
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".gitignore"
148
+ - Gemfile
149
+ - LICENSE.txt
150
+ - README.md
151
+ - Rakefile
152
+ - bin/sgviz
153
+ - docs/cfn/example.json
154
+ - docs/cfn/example.rb
155
+ - docs/images/1.png
156
+ - lib/sgviz.rb
157
+ - lib/sgviz/cli.rb
158
+ - lib/sgviz/generator.rb
159
+ - lib/sgviz/images/aws.png
160
+ - lib/sgviz/images/internet.png
161
+ - lib/sgviz/images/vpc.png
162
+ - lib/sgviz/version.rb
163
+ - sgviz.gemspec
164
+ homepage: https://github.com/y13i/sgviz
165
+ licenses:
166
+ - MIT
167
+ metadata: {}
168
+ post_install_message:
169
+ rdoc_options: []
170
+ require_paths:
171
+ - lib
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ required_rubygems_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ requirements: []
183
+ rubyforge_project:
184
+ rubygems_version: 2.4.5
185
+ signing_key:
186
+ specification_version: 4
187
+ summary: Visualize VPC Security Groups.
188
+ test_files: []