aws_security_viz 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module AwsSecurityViz
2
+ VERSION = "0.1.0"
3
+ end
data/opts.yml.sample ADDED
@@ -0,0 +1,10 @@
1
+ ---
2
+ :format: dot
3
+ :exclude:
4
+ - .*test.*
5
+ - .*perf.*
6
+ :groups:
7
+ '0.0.0.0/0': '*'
8
+ 'x.x.x.x/0': 'External'
9
+ 'y.y.y.y/0': 'External'
10
+
@@ -0,0 +1,49 @@
1
+ strict digraph G {
2
+ graph [bb="0,0,305.73,208",
3
+ concentrate=true,
4
+ overlap=false,
5
+ sep=1,
6
+ splines=true
7
+ ];
8
+ node [label="\N"];
9
+ app [height=0.5,
10
+ label=app,
11
+ pos="171.73,104",
12
+ width=0.75];
13
+ db [height=0.5,
14
+ label=db,
15
+ pos="171.73,18",
16
+ width=0.75];
17
+ app -> db [color=blue,
18
+ label="5984/tcp",
19
+ lp="196.22,61",
20
+ pos="e,171.73,36.095 171.73,85.595 171.73,74.257 171.73,59.227 171.73,46.315",
21
+ style=bold];
22
+ "8.8.8.8/32" [height=0.5,
23
+ label="8.8.8.8/32",
24
+ pos="45.727,190",
25
+ width=1.2702];
26
+ "8.8.8.8/32" -> app [color=blue,
27
+ label="80/tcp",
28
+ lp="134.22,147",
29
+ pos="e,153.39,117.22 67.963,174.18 89.418,159.87 121.93,138.2 144.83,122.93",
30
+ style=bold];
31
+ "amazon-elb-sg" [height=0.5,
32
+ label="amazon-elb-sg",
33
+ pos="171.73,190",
34
+ width=1.7267];
35
+ "amazon-elb-sg" -> app [color=blue,
36
+ label="80/tcp",
37
+ lp="189.22,147",
38
+ pos="e,171.73,122.1 171.73,171.6 171.73,160.26 171.73,145.23 171.73,132.32",
39
+ style=bold];
40
+ "*" [height=0.5,
41
+ label="*",
42
+ pos="278.73,190",
43
+ width=0.75];
44
+ "*" -> app [color=blue,
45
+ label="22/tcp",
46
+ lp="249.22,147",
47
+ pos="e,188.52,118.19 261.54,175.5 243.96,161.71 216.49,140.14 196.55,124.49",
48
+ style=bold];
49
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "SecurityGroups": [
3
+ {
4
+ "IpPermissionsEgress": [],
5
+ "Description": "app",
6
+ "IpPermissions": [
7
+ {
8
+ "ToPort": 80,
9
+ "IpProtocol": "tcp",
10
+ "IpRanges": [
11
+ {
12
+ "CidrIp": "8.8.8.8/32"
13
+ }
14
+ ],
15
+ "UserIdGroupPairs": [
16
+ {
17
+ "GroupName": "amazon-elb-sg",
18
+ "UserId": "amazon-elb",
19
+ "GroupId": "sg-amzelb"
20
+ }
21
+ ],
22
+ "FromPort": 80
23
+ },
24
+ {
25
+ "ToPort": 22,
26
+ "IpProtocol": "tcp",
27
+ "IpRanges": [
28
+ {
29
+ "CidrIp": "0.0.0.0/0"
30
+ }
31
+ ],
32
+ "UserIdGroupPairs": [],
33
+ "FromPort": 22
34
+ }
35
+ ],
36
+ "GroupName": "app",
37
+ "OwnerId": "owner1",
38
+ "GroupId": "sg-appgrp"
39
+ },
40
+ {
41
+ "IpPermissionsEgress": [],
42
+ "Description": "db",
43
+ "IpPermissions": [
44
+ {
45
+ "ToPort": 5984,
46
+ "IpProtocol": "tcp",
47
+ "IpRanges": [],
48
+ "UserIdGroupPairs": [
49
+ {
50
+ "GroupName": "app",
51
+ "UserId": "owner1",
52
+ "GroupId": "sg-appgrp"
53
+ }
54
+ ],
55
+ "FromPort": 5984
56
+ }
57
+ ],
58
+ "GroupName": "db",
59
+ "OwnerId": "owner1",
60
+ "GroupId": "sg-dbgrp"
61
+ }
62
+ ]
63
+ }
64
+
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe VisualizeAws do
4
+ context 'json' do
5
+ let(:opts) {
6
+ {
7
+ :source_file => source_file,
8
+ :filename => temp_file
9
+ }
10
+ }
11
+ let(:source_file) {File.join(File.dirname(__FILE__), 'dummy.json')}
12
+ let(:expected_file) {File.join(File.dirname(__FILE__), 'dummy.dot')}
13
+ let(:temp_file) { Tempfile.new(%w(aws .dot)) }
14
+ let(:config) {AwsConfig.new({groups: {'0.0.0.0/0' => '*'}})}
15
+
16
+ it 'should parse json input', :integration => true do
17
+ VisualizeAws.new(config, opts).unleash(temp_file.path)
18
+ expect(File.read(expected_file)).to eq(temp_file.read)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+ require 'rspec'
4
+ require 'rubygems'
5
+
6
+ require File.expand_path(File.dirname(__FILE__) + "/../config/boot")
7
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
8
+
9
+ def group name, *ingress
10
+ group = double("Group")
11
+ allow(group).to receive(:ip_permissions).and_return(ingress)
12
+ allow(group).to receive(:ip_permissions_egress).and_return([])
13
+ allow(group).to receive(:name).and_return(name)
14
+ allow(group).to receive(:group_id).and_return('some group')
15
+ group
16
+ end
17
+
18
+ def group_ingress port, name
19
+ {"groups"=>[{"userId"=>"userId", "groupId"=>"sg-groupId", "groupName"=>name}], "ipRanges"=>[], "ipProtocol"=>"tcp", "fromPort"=>port, "toPort"=>port}
20
+ end
21
+
22
+ def cidr_ingress port, cidr_ip
23
+ {"groups"=>[], "ipRanges"=>[{"cidrIp"=> cidr_ip}], "ipProtocol"=>"tcp", "fromPort"=>port, "toPort"=>port}
24
+ end
@@ -0,0 +1,8 @@
1
+ RSpec::Matchers.define :have_edge do |edge|
2
+ match do |actual|
3
+ edges = actual.each_edge
4
+ edge.each do |k,v|
5
+ expect(edges.any? {|e| e.node_one == GraphViz.escape(k) && e.node_two == GraphViz.escape(v)}).to eq(true)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,132 @@
1
+ require 'spec_helper'
2
+
3
+ describe VisualizeAws do
4
+ before do
5
+ @ec2 = double(Fog::Compute)
6
+ allow(Fog::Compute).to receive(:new).and_return(@ec2)
7
+ end
8
+
9
+ let(:visualize_aws) {VisualizeAws.new(AwsConfig.new)}
10
+
11
+ it 'should add nodes for each security group' do
12
+ expect(@ec2).to receive(:security_groups).and_return([group('Remote ssh', group_ingress('22', 'My machine')), group('My machine')])
13
+ graph = visualize_aws.build
14
+ node1 = graph.get_node('Remote ssh')
15
+ node2 = graph.get_node('My machine')
16
+
17
+ expect(node1).not_to be_nil
18
+ expect(node2).not_to be_nil
19
+ expect(graph.each_edge.size).to eq(1)
20
+ end
21
+
22
+ context 'groups' do
23
+ it 'should add an edge for each security ingress' do
24
+ expect(@ec2).to receive(:security_groups).and_return([group('Remote ssh', group_ingress('22', 'My machine')), group('My machine')])
25
+ graph = visualize_aws.build
26
+
27
+ expect(graph.each_edge.size).to eq(1)
28
+ expect(graph).to have_edge "My machine" => 'Remote ssh'
29
+ end
30
+
31
+ it 'should add nodes for external security groups defined through ingress' do
32
+ expect(@ec2).to receive(:security_groups).and_return([group('Web', group_ingress('80', 'ELB'))])
33
+ graph = visualize_aws.build
34
+
35
+ expect(graph.get_node('Web')).to_not be_nil
36
+ expect(graph.get_node('ELB')).to_not be_nil
37
+ expect(graph.each_edge.size).to eq(1)
38
+ expect(graph).to have_edge("ELB" => 'Web')
39
+ end
40
+
41
+ it 'should add an edge for each security ingress' do
42
+ expect(@ec2).to receive(:security_groups).and_return(
43
+ [
44
+ group('App', group_ingress('80', 'Web'), group_ingress('8983', 'Internal')),
45
+ group('Web', group_ingress('80', 'External')),
46
+ group('Db', group_ingress('7474', 'App'))
47
+ ])
48
+ graph = visualize_aws.build
49
+
50
+ expect(graph.each_edge.size).to eq(4)
51
+ expect(graph).to have_edge('Internal'=>'App', 'External' => 'Web', 'App'=> 'Db')
52
+ end
53
+ end
54
+
55
+ context 'cidr' do
56
+
57
+ it 'should add an edge for each cidr ingress' do
58
+ expect(@ec2).to receive(:security_groups).and_return(
59
+ [
60
+ group('Web', group_ingress('80', 'External')),
61
+ group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
62
+ ])
63
+ graph = visualize_aws.build
64
+
65
+ expect(graph.each_edge.size).to eq(3)
66
+ expect(graph).to have_edge('External' => 'Web', 'App'=> 'Db')
67
+ expect(graph).to have_edge('127.0.0.1/32' => 'Db' )
68
+ end
69
+
70
+ it 'should add map edges for cidr ingress' do
71
+ expect(@ec2).to receive(:security_groups).and_return(
72
+ [
73
+ group('Web', group_ingress('80', 'External')),
74
+ group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
75
+ ])
76
+ mapping = {'127.0.0.1/32' => 'Work'}
77
+ mapping = CidrGroupMapping.new([], mapping)
78
+ allow(CidrGroupMapping).to receive(:new).and_return(mapping)
79
+
80
+ graph = visualize_aws.build
81
+
82
+ expect(graph.each_edge.size).to eq(3)
83
+ expect(graph).to have_edge('External' => 'Web', 'App'=> 'Db')
84
+ expect(graph).to have_edge('Work' => 'Db' )
85
+ end
86
+ it 'should group mapped duplicate edges for cidr ingress' do
87
+ expect(@ec2).to receive(:security_groups).and_return(
88
+ [
89
+ group('ssh', cidr_ingress('22', '192.168.0.1/32'), cidr_ingress('22', '127.0.0.1/32'))
90
+ ])
91
+ mapping = {'127.0.0.1/32' => 'Work', '192.168.0.1/32' => 'Work'}
92
+ mapping = CidrGroupMapping.new([], mapping)
93
+ allow(CidrGroupMapping).to receive(:new).and_return(mapping)
94
+
95
+ graph = visualize_aws.build
96
+
97
+ expect(graph.each_edge.size).to eq(1)
98
+ expect(graph).to have_edge('Work' => 'ssh' )
99
+ end
100
+ end
101
+ context "filter" do
102
+ it 'include groups which do not match the pattern' do
103
+ expect(@ec2).to receive(:security_groups).and_return(
104
+ [
105
+ group('Web', group_ingress('80', 'External')),
106
+ group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
107
+ ])
108
+
109
+ opts = {:exclude => ['D.*b', 'App']}
110
+ graph = VisualizeAws.new(AwsConfig.new(opts)).build
111
+
112
+ expect(graph.each_edge.size).to eq(1)
113
+ expect(graph).to have_edge('External' => 'Web')
114
+ end
115
+
116
+ it 'include derived groups which do not match the pattern' do
117
+ expect(@ec2).to receive(:security_groups).and_return(
118
+ [
119
+ group('Web', group_ingress('80', 'External')),
120
+ group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
121
+ ])
122
+
123
+ opts = {:exclude => ['App']}
124
+ graph = VisualizeAws.new(AwsConfig.new(opts)).build
125
+
126
+ expect(graph.each_edge.size).to eq(2)
127
+ expect(graph).to have_edge('External' => 'Web')
128
+ expect(graph).to have_edge('127.0.0.1/32' => 'Db' )
129
+ end
130
+
131
+ end
132
+ end
metadata ADDED
@@ -0,0 +1,210 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aws_security_viz
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Anay Nayak
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-10-15 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.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
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: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.1.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.1.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: ruby-graphviz
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.2.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.2.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: fog
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.26.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.26.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: unf
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.1.4
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.1.4
97
+ - !ruby/object:Gem::Dependency
98
+ name: json
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 1.8.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.8.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: trollop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 2.1.1
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 2.1.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: organic_hash
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 1.0.2
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 1.0.2
139
+ description: Provides a quick mechanism to visualize your EC2 security groups in multiple
140
+ formats
141
+ email: anayak007+rubygems@gmail.com
142
+ executables:
143
+ - aws_security_viz
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".gitignore"
148
+ - ".travis.yml"
149
+ - Gemfile
150
+ - Gemfile.lock
151
+ - LICENSE.md
152
+ - README.md
153
+ - Rakefile
154
+ - Vagrantfile
155
+ - aws_security_viz.gemspec
156
+ - config/boot.rb
157
+ - exe/aws_security_viz
158
+ - images/sample.png
159
+ - lib/aws_config.rb
160
+ - lib/aws_security_viz.rb
161
+ - lib/color_picker.rb
162
+ - lib/debug/parse_log.rb
163
+ - lib/debug_graph.rb
164
+ - lib/ec2/ip_permission.rb
165
+ - lib/ec2/security_groups.rb
166
+ - lib/ec2/traffic.rb
167
+ - lib/exclusions.rb
168
+ - lib/export/html/view.html
169
+ - lib/graph.rb
170
+ - lib/provider/ec2.rb
171
+ - lib/provider/json.rb
172
+ - lib/version.rb
173
+ - opts.yml.sample
174
+ - spec/integration/dummy.dot
175
+ - spec/integration/dummy.json
176
+ - spec/integration/visualize_aws_spec.rb
177
+ - spec/spec_helper.rb
178
+ - spec/support/matchers/graph.rb
179
+ - spec/visualize_aws_spec.rb
180
+ homepage: https://github.com/anaynayak/aws-security-viz
181
+ licenses:
182
+ - MIT
183
+ metadata: {}
184
+ post_install_message:
185
+ rdoc_options: []
186
+ require_paths:
187
+ - lib
188
+ required_ruby_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ required_rubygems_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ requirements: []
199
+ rubyforge_project:
200
+ rubygems_version: 2.2.2
201
+ signing_key:
202
+ specification_version: 4
203
+ summary: Visualize your aws security groups
204
+ test_files:
205
+ - spec/integration/dummy.dot
206
+ - spec/integration/dummy.json
207
+ - spec/integration/visualize_aws_spec.rb
208
+ - spec/spec_helper.rb
209
+ - spec/support/matchers/graph.rb
210
+ - spec/visualize_aws_spec.rb