aws_security_viz 0.1.7.pre.alpha.pre.145 → 0.2.0.pre.alpha.pre.152
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|