aws_security_viz 0.1.7.pre.alpha.pre.145 → 0.2.0.pre.alpha.pre.152
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +1 -1
- data/exe/aws_security_viz +2 -0
- data/lib/aws_config.rb +2 -0
- data/lib/aws_security_viz.rb +3 -10
- data/lib/debug/parse_log.rb +1 -1
- data/lib/debug_graph.rb +2 -2
- data/lib/ec2/security_groups.rb +1 -1
- data/lib/export/html/navigator.html +84 -0
- data/lib/graph.rb +5 -3
- data/lib/provider/ec2.rb +1 -1
- data/lib/provider/json.rb +8 -0
- data/lib/renderer/all.rb +18 -0
- data/lib/renderer/graphviz.rb +2 -2
- data/lib/renderer/json.rb +2 -2
- data/lib/renderer/navigator.rb +32 -0
- data/lib/version.rb +1 -1
- data/spec/integration/navigator.json +1 -0
- data/spec/integration/visualize_aws_spec.rb +12 -1
- data/spec/visualize_aws_spec.rb +1 -1
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be9db3036820a8e139ef5efdce90c341df24e582dbd8aa7ef7db4b5cfe569926
|
4
|
+
data.tar.gz: 3c64a76b19594f12c42c90afac0fb4577c8be33cf7e1c66bcdf2a85eef7aee24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 378d4705ee99b1b4a8cef8384205d99ccbf8865d3926a83a009c0eb343e9940c88acac971fd8321a93aea622ca3e20832b3a19d87c18d7d5711ab2462c0b7d86
|
7
|
+
data.tar.gz: bf04ed0f86ecef83e8286d97138fca3e485d1d7eeb0333344ecb5ff819b109497b8af687529c6b04122b87d22380afea3e21a052f1df4ba2705a8e31905b3810
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
4
|
|
5
5
|
## [Unreleased]
|
6
|
+
### Added
|
7
|
+
- Add graph navigator renderer using https://grapheco.github.io/InteractiveGraph/
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- Renderer no longer identified automatically based on json file extension.
|
6
11
|
|
7
12
|
## [0.1.6] - 2019-01-14
|
8
13
|
### Added
|
data/README.md
CHANGED
@@ -42,7 +42,7 @@ To generate the graph using an existing security_groups.json (created using aws-
|
|
42
42
|
To generate a web view
|
43
43
|
|
44
44
|
```
|
45
|
-
$ aws_security_viz -a your_aws_key -s your_aws_secret_key -f aws.json
|
45
|
+
$ aws_security_viz -a your_aws_key -s your_aws_secret_key -f aws.json --renderer navigator
|
46
46
|
```
|
47
47
|
|
48
48
|
* Generates two files: aws.json and view.html.
|
data/exe/aws_security_viz
CHANGED
@@ -13,6 +13,7 @@ opts = Optimist::options do
|
|
13
13
|
opt :filename, 'Output file name', :type => :string, :default => 'aws-security-viz.png'
|
14
14
|
opt :config, 'Config file (opts.yml)', :type => :string, :default => 'opts.yml'
|
15
15
|
opt :color, 'Colored node edges', :default => false
|
16
|
+
opt :renderer, "Renderer (#{Renderer.all.join('|')})", :default => 'graphviz'
|
16
17
|
opt :source_filter, 'Source filter', :default => nil, :type => :string
|
17
18
|
opt :target_filter, 'Target filter', :default => nil, :type => :string
|
18
19
|
end
|
@@ -29,5 +30,6 @@ begin
|
|
29
30
|
VisualizeAws.new(config, opts).unleash(opts[:filename])
|
30
31
|
rescue Exception => e
|
31
32
|
puts "[ERROR] #{e.message}"
|
33
|
+
raise e if config.debug?
|
32
34
|
exit 1
|
33
35
|
end
|
data/lib/aws_config.rb
CHANGED
data/lib/aws_security_viz.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require_relative 'ec2/security_groups'
|
2
2
|
require_relative 'provider/json'
|
3
3
|
require_relative 'provider/ec2'
|
4
|
-
require_relative 'renderer/
|
5
|
-
require_relative 'renderer/json'
|
4
|
+
require_relative 'renderer/all'
|
6
5
|
require_relative 'graph'
|
7
6
|
require_relative 'graph_filter'
|
8
7
|
require_relative 'exclusions'
|
@@ -21,20 +20,14 @@ class VisualizeAws
|
|
21
20
|
def unleash(output_file)
|
22
21
|
g = build
|
23
22
|
g.filter(@options[:source_filter], @options[:target_filter])
|
24
|
-
|
25
|
-
g.output(Renderer::Json.new(output_file, @config))
|
26
|
-
FileUtils.copy(File.expand_path('../export/html/view.html', __FILE__),
|
27
|
-
File.expand_path('../view.html', output_file))
|
28
|
-
else
|
29
|
-
g.output(Renderer::GraphViz.new(output_file, @config))
|
30
|
-
end
|
23
|
+
g.output(Renderer.pick(@options[:renderer], output_file, @config))
|
31
24
|
end
|
32
25
|
|
33
26
|
def build
|
34
27
|
g = @config.obfuscate? ? DebugGraph.new(@config) : Graph.new(@config)
|
35
28
|
@security_groups.each_with_index { |group, index|
|
36
29
|
picker = ColorPicker.new(@options[:color])
|
37
|
-
g.add_node(group.name)
|
30
|
+
g.add_node(group.name, {vpc_id: group.vpc_id, group_id: group.group_id})
|
38
31
|
group.traffic.each { |traffic|
|
39
32
|
if traffic.ingress
|
40
33
|
g.add_edge(traffic.from, traffic.to, :color => picker.color(index, traffic.ingress), :label => traffic.port_range)
|
data/lib/debug/parse_log.rb
CHANGED
data/lib/debug_graph.rb
CHANGED
data/lib/ec2/security_groups.rb
CHANGED
@@ -0,0 +1,84 @@
|
|
1
|
+
<html>
|
2
|
+
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
5
|
+
<title>GraphNavigator</title>
|
6
|
+
<script type="text/javascript" src="https://rawcdn.githack.com/grapheco/InteractiveGraph/0.1.1/dist/igraph/interactive-graph.min.js"></script>
|
7
|
+
<link type="text/css" rel="stylesheet" href="https://rawcdn.githack.com/grapheco/InteractiveGraph/0.1.1/dist/igraph/interactive-graph.min.css">
|
8
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
|
9
|
+
crossorigin="anonymous"></script>
|
10
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css" integrity="sha256-p6xU9YulB7E2Ic62/PX+h59ayb3PBJ0WFTEQxq0EjHw="
|
11
|
+
crossorigin="anonymous" />
|
12
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha256-KM512VNnjElC30ehFwehXjx1YCHPiQkOPmqnrWtpccM="
|
13
|
+
crossorigin="anonymous"></script>
|
14
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
15
|
+
integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
|
16
|
+
<style type="text/css">
|
17
|
+
body {
|
18
|
+
margin: 0px;
|
19
|
+
font-size: 14px;
|
20
|
+
}
|
21
|
+
|
22
|
+
#graphArea {
|
23
|
+
height: 100%;
|
24
|
+
border: 1px solid lightgray;
|
25
|
+
}
|
26
|
+
div.vis-configuration.vis-config-item.vis-config-s3, div.vis-configuration.vis-config-item.vis-config-s2,div.vis-configuration.vis-config-item.vis-config-s0 {
|
27
|
+
background-color: #f7f8fa
|
28
|
+
}
|
29
|
+
.configure {
|
30
|
+
padding: 4px;
|
31
|
+
position: absolute;
|
32
|
+
bottom: 10px;
|
33
|
+
right: 10px;
|
34
|
+
background: #f7f8fa;
|
35
|
+
width: 520px;
|
36
|
+
box-shadow: rgba(116, 112, 112, .555) 1px 1px 10px;
|
37
|
+
z-index: 900
|
38
|
+
}
|
39
|
+
</style>
|
40
|
+
|
41
|
+
</head>
|
42
|
+
|
43
|
+
<body>
|
44
|
+
<div style="height:100%">
|
45
|
+
<div id="graphArea"></div>
|
46
|
+
<div class="configure">
|
47
|
+
<span class="fa fa-cogs"></span>
|
48
|
+
<a href="#" class="toggle-config">Configure</a>
|
49
|
+
<div id="configOptions" style="display:none"></div>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
|
53
|
+
<script type="text/javascript">
|
54
|
+
$('.toggle-config').click(function () {
|
55
|
+
$('#configOptions').slideToggle('slow');
|
56
|
+
});
|
57
|
+
function trackAndNavigate(e) {
|
58
|
+
e.nodes.forEach(element => {
|
59
|
+
var deleted = window.nodes.delete(element)
|
60
|
+
if (!deleted) {
|
61
|
+
window.nodes.add(element);
|
62
|
+
}
|
63
|
+
});
|
64
|
+
if (window.nodes.size >= 2) {
|
65
|
+
var [from, to] = window.nodes;
|
66
|
+
window.location.search = `from=${from}&to=${to}`;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
var file = location.hash.replace(/^#/, '/');
|
70
|
+
var app = new igraph.GraphNavigator(document.getElementById('graphArea'));
|
71
|
+
app.loadGson(file);
|
72
|
+
app._frame._networkOptions.configure = {
|
73
|
+
filter: (option, path) => path.indexOf('physics') !== -1,
|
74
|
+
container: document.getElementById('configOptions'),
|
75
|
+
showButton: false
|
76
|
+
}
|
77
|
+
app._frame.updateNetworkOptions(app._frame._networkOptions)
|
78
|
+
|
79
|
+
window.nodes = new Set();
|
80
|
+
app._frame.on('NETWORK_DBLCLICK', trackAndNavigate);
|
81
|
+
</script>
|
82
|
+
</body>
|
83
|
+
|
84
|
+
</html>
|
data/lib/graph.rb
CHANGED
@@ -7,11 +7,13 @@ class Graph
|
|
7
7
|
@config = config
|
8
8
|
@underlying = underlying
|
9
9
|
@edge_properties = {}
|
10
|
+
@node_properties = {}
|
10
11
|
end
|
11
12
|
|
12
|
-
def add_node(name)
|
13
|
-
log("node: #{name}")
|
13
|
+
def add_node(name, opts)
|
14
|
+
log("node: #{name}, opts: #{opts}")
|
14
15
|
@underlying.add_vertex(name)
|
16
|
+
@node_properties[name] = opts
|
15
17
|
end
|
16
18
|
|
17
19
|
def add_edge(from, to, opts)
|
@@ -25,7 +27,7 @@ class Graph
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def output(renderer)
|
28
|
-
@underlying.each_vertex { |v| renderer.add_node(v) }
|
30
|
+
@underlying.each_vertex { |v| renderer.add_node(v, @node_properties[v] || {}) }
|
29
31
|
@underlying.each_edge { |u, v|
|
30
32
|
renderer.add_edge(u, v, opts(u, v))
|
31
33
|
}
|
data/lib/provider/ec2.rb
CHANGED
data/lib/provider/json.rb
CHANGED
data/lib/renderer/all.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'navigator'
|
2
|
+
require_relative 'json'
|
3
|
+
require_relative 'graphviz'
|
4
|
+
module Renderer
|
5
|
+
ALL = {graphviz: Renderer::GraphViz, json: Renderer::Json, navigator: Renderer::Navigator}
|
6
|
+
def self.pick(r, output_file, config)
|
7
|
+
(ALL[(r || 'graphviz').to_sym]).new(output_file, config)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.copy_asset(asset, file_name)
|
11
|
+
FileUtils.copy(File.expand_path("../../export/html/#{asset}", __FILE__),
|
12
|
+
File.expand_path(asset, @file_name))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.all
|
16
|
+
ALL.keys
|
17
|
+
end
|
18
|
+
end
|
data/lib/renderer/graphviz.rb
CHANGED
@@ -14,7 +14,7 @@ module Renderer
|
|
14
14
|
@config = config
|
15
15
|
end
|
16
16
|
|
17
|
-
def add_node(name)
|
17
|
+
def add_node(name, opts)
|
18
18
|
@g.add_node(name, label: name)
|
19
19
|
end
|
20
20
|
|
@@ -27,7 +27,7 @@ module Renderer
|
|
27
27
|
|
28
28
|
def create_if_missing(name)
|
29
29
|
n = @g.get_node(name).first
|
30
|
-
n.nil? ? add_node(name) : n
|
30
|
+
n.nil? ? add_node(name, {}) : n
|
31
31
|
end
|
32
32
|
|
33
33
|
def output
|
data/lib/renderer/json.rb
CHANGED
@@ -7,7 +7,7 @@ module Renderer
|
|
7
7
|
@config = config
|
8
8
|
end
|
9
9
|
|
10
|
-
def add_node(name)
|
10
|
+
def add_node(name, opts)
|
11
11
|
@nodes << {id: name, label: name}
|
12
12
|
end
|
13
13
|
|
@@ -17,7 +17,7 @@ module Renderer
|
|
17
17
|
|
18
18
|
def output
|
19
19
|
IO.write(@file_name, {nodes: @nodes, edges: @edges}.to_json)
|
20
|
+
Renderer.copy_asset('view.html', @file_name)
|
20
21
|
end
|
21
|
-
|
22
22
|
end
|
23
23
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Renderer
|
4
|
+
class Navigator
|
5
|
+
def initialize(file_name, config)
|
6
|
+
@nodes = []
|
7
|
+
@edges = []
|
8
|
+
@file_name = file_name
|
9
|
+
@config = config
|
10
|
+
@categories = Set.new()
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_node(name, opts)
|
14
|
+
vpc = opts[:vpc_id] || 'default'
|
15
|
+
@nodes << {id: name, label: name, categories: [vpc]}
|
16
|
+
@categories.add(vpc)
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_edge(from, to, opts)
|
20
|
+
@edges << {id: "#{from}-#{to}", from: from, to: to, label: opts[:label]}
|
21
|
+
end
|
22
|
+
|
23
|
+
def output
|
24
|
+
IO.write(@file_name, {
|
25
|
+
data: {nodes: @nodes, edges: @edges},
|
26
|
+
categories: Hash[@categories.map{|c| [c, c]}]
|
27
|
+
}.to_json)
|
28
|
+
Renderer.copy_asset('navigator.html', @file_name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
data/lib/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
{"categories": {"default":"default"}, "data": {"nodes":[{"id":"app", "label":"app", "categories":["default"]}, {"id":"8.8.8.8/32", "label":"8.8.8.8/32", "categories":["default"]}, {"id":"amazon-elb-sg", "label":"amazon-elb-sg", "categories":["default"]}, {"id":"*", "label":"*", "categories":["default"]}, {"id":"db", "label":"db", "categories":["default"]}], "edges":[{"id":"app-db", "from":"app", "to":"db", "label":"5984/tcp"}, {"id":"8.8.8.8/32-app", "from":"8.8.8.8/32", "to":"app", "label":"80/tcp"}, {"id":"amazon-elb-sg-app", "from":"amazon-elb-sg", "to":"app", "label":"80/tcp"}, {"id":"*-app", "from":"*", "to":"app", "label":"22/tcp"}]}}
|
@@ -29,7 +29,18 @@ describe VisualizeAws do
|
|
29
29
|
|
30
30
|
it 'should parse json input', :integration => true do
|
31
31
|
expect(FileUtils).to receive(:copy)
|
32
|
-
VisualizeAws.new(config, opts).unleash(temp_file.path)
|
32
|
+
VisualizeAws.new(config, opts.merge(:renderer => 'json')).unleash(temp_file.path)
|
33
|
+
expect(JSON.parse(expected_content)).to eq(JSON.parse(actual_content))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'json to navigator file' do
|
38
|
+
let(:expected_file) { File.join(File.dirname(__FILE__), 'navigator.json') }
|
39
|
+
let(:temp_file) { Tempfile.new(%w(aws .json)) }
|
40
|
+
|
41
|
+
it 'should parse json input', :integration => true do
|
42
|
+
expect(FileUtils).to receive(:copy)
|
43
|
+
VisualizeAws.new(config, opts.merge(:renderer => 'navigator')).unleash(temp_file.path)
|
33
44
|
expect(JSON.parse(expected_content)).to eq(JSON.parse(actual_content))
|
34
45
|
end
|
35
46
|
end
|
data/spec/visualize_aws_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws_security_viz
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0.pre.alpha.pre.152
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anay Nayak
|
@@ -191,14 +191,17 @@ files:
|
|
191
191
|
- lib/ec2/security_groups.rb
|
192
192
|
- lib/ec2/traffic.rb
|
193
193
|
- lib/exclusions.rb
|
194
|
+
- lib/export/html/navigator.html
|
194
195
|
- lib/export/html/view.html
|
195
196
|
- lib/graph.rb
|
196
197
|
- lib/graph_filter.rb
|
197
198
|
- lib/opts.yml.sample
|
198
199
|
- lib/provider/ec2.rb
|
199
200
|
- lib/provider/json.rb
|
201
|
+
- lib/renderer/all.rb
|
200
202
|
- lib/renderer/graphviz.rb
|
201
203
|
- lib/renderer/json.rb
|
204
|
+
- lib/renderer/navigator.rb
|
202
205
|
- lib/version.rb
|
203
206
|
- spec/color_picker_spec.rb
|
204
207
|
- spec/graph_filter_spec.rb
|
@@ -206,6 +209,7 @@ files:
|
|
206
209
|
- spec/integration/dummy.dot
|
207
210
|
- spec/integration/dummy.json
|
208
211
|
- spec/integration/expected.json
|
212
|
+
- spec/integration/navigator.json
|
209
213
|
- spec/integration/visualize_aws_spec.rb
|
210
214
|
- spec/spec_helper.rb
|
211
215
|
- spec/visualize_aws_spec.rb
|
@@ -239,6 +243,7 @@ test_files:
|
|
239
243
|
- spec/integration/dummy.dot
|
240
244
|
- spec/integration/dummy.json
|
241
245
|
- spec/integration/expected.json
|
246
|
+
- spec/integration/navigator.json
|
242
247
|
- spec/integration/visualize_aws_spec.rb
|
243
248
|
- spec/spec_helper.rb
|
244
249
|
- spec/visualize_aws_spec.rb
|