aws_security_viz 0.1.2.pre.alpha.pre.58 → 0.1.2.pre.alpha.pre.59

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NmYxNzdmYTg5OTc1ODk0N2UwNzgwOWYwZTI5ZTdjZmZiNDg0MTk0Mg==
4
+ ZTU2ODBmNTYyYTNkYTUwZWVlNGM4ODQwNWUxOGI4ZWU0ZDlhMTIwMQ==
5
5
  data.tar.gz: !binary |-
6
- NWY5NTNkOWU4NDNmNjg5OWRhMjE5YjkxNzZlMzA0OGI1NWYxZWE0NQ==
6
+ YTMzYTFhODNlZjAyMWEwMjRiNjUzN2JjZDc1M2I0ZGNhODAwMDRjMg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NDJhODY3ZDBjYzNlMjE2NGFjMGYwNjQ0YWI1OTZjMTkxNGIzYjczMjllOGY2
10
- N2EwN2IxNGE1ZDZiZDZiZTE5MGUxYjczNTZhNjU4MTBkNTk1YWM0MGU2MDJl
11
- NDNmMTE1YWE4ZDE3ZmMyYmQ3MDFlMjRmMGM0ZjMyZDkyNThkOGI=
9
+ ZDNjMTcxMGU3ZDlhYjlmYzc4ZTExZTQ0MWI5NDlkMTNjYWFjYmY0ZDZhYmM3
10
+ YTIzMzIwNzQ0N2U5NjM3Njk3YmM5OGIzMjUwZjRmZjRlM2I4OWNlNzBlOGQy
11
+ M2YwZTYxZmE4NTkwNTQ4Y2VmZDQyNjBhYWVhZjY5ZDAzNDM4YWM=
12
12
  data.tar.gz: !binary |-
13
- Y2IyZDZkZDhjMDJkMmYyMjI2YzBkYzk0NmVkZGEzMDhkMDI3NTI3Mzg5MDgy
14
- MjZmMmRhMGM2MGU4MjA1MTlkOTg2OTYyZjkzMDM3NDIyY2VjZDM0YzdmY2I2
15
- YTg2ZjBkOTIwYTM1OGMwMzIzNGIzNDk1NjQzMDU1NzdmZTMxYzE=
13
+ YzIxOGFiZmMzNDYyMTNhZGZjYmMyNzBhZmZhOTYwYzE1ZDllOTU1NDM4NzVk
14
+ NzU3Njg1Y2RiMDcxNzlkNWU1MWRiYTdhNDE0NjQxYmZjNDYzMWM1N2U4MmU4
15
+ NDUzOTM0ZGEzMzM4OWFhYTBiYjAyNGJiZDk3ZTgzZTc0YThmYzc=
@@ -1,6 +1,8 @@
1
1
  require_relative 'ec2/security_groups'
2
2
  require_relative 'provider/json'
3
3
  require_relative 'provider/ec2'
4
+ require_relative 'renderer/graphviz'
5
+ require_relative 'renderer/json'
4
6
  require_relative 'graph'
5
7
  require_relative 'exclusions'
6
8
  require_relative 'debug_graph'
@@ -17,28 +19,25 @@ class VisualizeAws
17
19
 
18
20
  def unleash(output_file)
19
21
  g = build
20
- render(g, output_file)
22
+ renderer = output_file.end_with?('json') ? Renderer::Json.new(output_file, @config) : Renderer::GraphViz.new(output_file, @config)
23
+ g.output(renderer)
21
24
  end
22
25
 
23
26
  def build
24
- g = ENV["OBFUSCATE"] ? DebugGraph.new : Graph.new
27
+ g = ENV["OBFUSCATE"] ? DebugGraph.new(@config) : Graph.new(@config)
25
28
  @security_groups.each_with_index { |group, index|
26
29
  picker = ColorPicker.new(@options[:color])
27
30
  g.add_node(group.name)
28
31
  group.traffic.each { |traffic|
29
- if traffic.ingress
30
- g.add_edge(traffic.from, traffic.to, :color => picker.color(index, traffic.ingress), :style => 'bold', :label => traffic.port_range)
32
+ if traffic.ingress
33
+ g.add_edge(traffic.from, traffic.to, :color => picker.color(index, traffic.ingress), :label => traffic.port_range)
31
34
  else
32
- g.add_edge(traffic.to, traffic.from, :color => picker.color(index, traffic.ingress), :style => 'bold', :label => traffic.port_range)
35
+ g.add_edge(traffic.to, traffic.from, :color => picker.color(index, traffic.ingress), :label => traffic.port_range)
33
36
  end
34
37
  }
35
38
  }
36
39
  g
37
40
  end
38
41
 
39
- def render(g, output_file)
40
- extension = File.extname(output_file)
41
- g.output(extension[1..-1].to_sym => output_file, :use => @config.format)
42
- end
43
42
  end
44
43
 
data/lib/debug_graph.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require 'digest'
2
+ require_relative 'graph'
2
3
 
3
4
  class DebugGraph
4
- def initialize
5
- @g = Graph.new
5
+ def initialize(config)
6
+ @g = Graph.new(config)
6
7
  end
7
8
 
8
9
  def add_node(name)
@@ -13,8 +14,8 @@ class DebugGraph
13
14
  @g.add_edge(h(from), h(to), opts.update(label: h(opts[:label])))
14
15
  end
15
16
 
16
- def output(opts)
17
- @g.output(opts)
17
+ def output(renderer)
18
+ @g.output(renderer)
18
19
  end
19
20
 
20
21
  private
@@ -1,36 +1,132 @@
1
- <html>
2
- <head>
3
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.min.css">
4
- <link rel="stylesheet" href="https://cdn.rawgit.com/mountainstorm/jquery.graphviz.svg/master/css/graphviz.svg.css">
5
- </head>
6
- <body>
7
- <div id="graph" style=""></div>
8
- <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
9
- <script type="text/javascript" src="https://cdn.rawgit.com/jquery/jquery-mousewheel/master/jquery.mousewheel.min.js"></script>
10
- <script type="text/javascript" src="https://cdn.rawgit.com/jquery/jquery-color/master/jquery.color.js"></script>
11
- <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/js/bootstrap.min.js"></script>
12
- <script type="text/javascript" src="https://cdn.rawgit.com/mountainstorm/jquery.graphviz.svg/master/js/jquery.graphviz.svg.js"></script>
13
- <script type="text/javascript">
14
- $(document).ready(function(){
15
- $("#graph").graphviz({
16
- url: "demo.svg",
17
- ready: function() {
18
- var gv = this
19
- gv.nodes().click(function () {
20
- var $set = $()
21
- $set.push(this)
22
- $set = $set.add(gv.linkedFrom(this, true))
23
- gv.highlight($set, true)
24
- gv.bringToFront($set)
25
- })
26
- $(document).keydown(function (evt) {
27
- if (evt.keyCode == 27) {
28
- gv.highlight()
29
- }
30
- })
31
- }
32
- });
1
+ <html>
2
+ <head>
3
+ <style type="text/css">
4
+ #container {
5
+ max-width: 100%;
6
+ height: 100%;
7
+ margin: auto;
8
+ }
9
+ </style>
10
+ </head>
11
+ <body>
12
+ <div id="container"></div>
13
+ <script src="https://rawgit.com/Linkurious/linkurious.js/develop/dist/sigma.min.js"></script>
14
+ <script src="https://rawgit.com/Linkurious/linkurious.js/develop/dist/plugins/sigma.parsers.json.min.js"></script>
15
+ <script src="https://rawgit.com/Linkurious/linkurious.js/develop/dist/plugins/sigma.layouts.forceLink.min.js"></script>
16
+ <script src="https://rawgit.com/Linkurious/linkurious.js/develop/dist/plugins/sigma.plugins.design.min.js"></script>
17
+ <script src="https://rawgit.com/Linkurious/linkurious.js/develop/dist/plugins/sigma.plugins.colorbrewer.min.js"></script>
18
+ <script src="https://rawgit.com/Linkurious/linkurious.js/develop/dist/plugins/sigma.renderers.edgeLabels.min.js"></script>
19
+ <script>
20
+ sigma.classes.graph.addMethod('neighbors', function (nodeId) {
21
+ var k,
22
+ neighbors = {},
23
+ index = this.allNeighborsIndex[nodeId] || {};
24
+
25
+ for (k in index)
26
+ neighbors[k] = this.nodesIndex[k];
27
+
28
+ return neighbors;
29
+ });
30
+ sigma.classes.graph.addMethod('neighborCount', function (nodeId) {
31
+ return this.allNeighborsCount[nodeId];
32
+ });
33
+ var config = {
34
+ renderer: {
35
+ container: 'container',
36
+ type: 'canvas'
37
+ },
38
+ settings: {
39
+ animationsTime: 1000,
40
+ borderSize: 1,
41
+ outerBorderSize: 1,
42
+ defaultNodeOuterBorderColor: 'rgb(236, 81, 72)',
43
+ enableEdgeHovering: true,
44
+ edgeHoverHighlightNodes: 'circle',
45
+ sideMargin: 1,
46
+ edgeHoverColor: 'edge',
47
+ defaultEdgeHoverColor: '#000',
48
+ edgeHoverExtremities: true,
49
+ scalingMode: 'outside',
50
+ edgeLabelThreshold: 2,
51
+ edgeHoverSizeRatio: 2,
52
+ edgeLabelSize: 'proportional'
53
+ }
54
+ };
55
+ sigma.parsers.json('/aws.json', config, function (s) {
56
+ s.graph.nodes().forEach(function (n) {
57
+ n.x = Math.random();
58
+ n.y = Math.random();
59
+ n.size = 1;
60
+ n.label = n.id;
61
+ n.data = {edgeCount: s.graph.neighborCount(n.id)};
62
+ });
63
+ var myStyles = {
64
+ nodes: {
65
+ color: {
66
+ by: 'data.edgeCount',
67
+ scheme: 'colorbrewer.nodes',
68
+ bins: 3
69
+ },
70
+ size: {
71
+ by: 'data.edgeCount',
72
+ bins: 7,
73
+ min: 2,
74
+ max: 10
75
+ }
76
+ }
77
+ };
78
+ var myPalette = {
79
+ colorbrewer: {
80
+ nodes: sigma.plugins.colorbrewer.Dark2
81
+ }
82
+ };
83
+ var design = sigma.plugins.design(s, {styles: myStyles, palette: myPalette});
84
+ design.apply();
85
+
86
+ s.graph.nodes().forEach(function (n) {
87
+ n.originalColor = n.color;
88
+ });
89
+ s.graph.edges().forEach(function (e) {
90
+ e.size = 1;
91
+ e.originalColor = e.color;
92
+ e.type = "arrow";
93
+ });
94
+ var fa = sigma.layouts.startForceLink(s, {autoStop: true, adjustSizes: true, randomize: true});
95
+
96
+ s.bind('clickNode', function (e) {
97
+ var nodeId = e.data.node.id,
98
+ toKeep = s.graph.neighbors(nodeId);
99
+ toKeep[nodeId] = e.data.node;
100
+
101
+ s.graph.nodes().forEach(function (n) {
102
+ if (toKeep[n.id])
103
+ n.color = n.originalColor;
104
+ else
105
+ n.color = '#eee';
33
106
  });
34
- </script>
35
- </body>
36
- </html>
107
+
108
+ s.graph.edges().forEach(function (e) {
109
+ if (toKeep[e.source] && toKeep[e.target])
110
+ e.color = e.originalColor;
111
+ else
112
+ e.color = '#eee';
113
+ });
114
+
115
+ s.refresh();
116
+ });
117
+ s.bind('clickStage', function (e) {
118
+ s.graph.nodes().forEach(function (n) {
119
+ n.color = n.originalColor;
120
+ });
121
+
122
+ s.graph.edges().forEach(function (e) {
123
+ e.color = e.originalColor;
124
+ });
125
+
126
+ s.refresh();
127
+ });
128
+ });
129
+ </script>
130
+ </body>
131
+ </html>
132
+
data/lib/graph.rb CHANGED
@@ -1,39 +1,46 @@
1
- require 'graphviz'
2
- require 'logger'
3
-
4
1
  class Graph
5
- def initialize
6
- @g = GraphViz::new('G', :type => 'strict digraph') { |g|
7
- g[:overlap] = :false
8
- g[:splines] = :true
9
- g[:sep] = 1
10
- g[:concentrate] = :true
11
- }
2
+ attr_reader :ops
3
+
4
+ def initialize(config)
5
+ @config = config
6
+ @ops = []
7
+ @nodes = Set.new
12
8
  end
13
9
 
14
10
  def add_node(name)
15
11
  log("node: #{name}")
16
- @g.add_node(name) if name
17
- end
18
-
19
- def get_node(name, &block)
20
- @g.get_node(name, &block)
12
+ uniquely_add(@ops, :node, name) {
13
+ [:node, name]
14
+ }
21
15
  end
16
+ #TODO : Dedup edge labels ?
17
+ #TODO : Remove env dependencies
22
18
 
23
19
  def add_edge(from, to, opts)
24
20
  log("edge: #{from} -> #{to}")
25
- @g.add_edge(from, to, opts)
21
+ add_node(from)
22
+ add_node(to)
23
+ uniquely_add(@ops, :edge, from, to) {
24
+ [:edge, from, to, opts]
25
+ }
26
26
  end
27
27
 
28
- def each_edge(&block)
29
- @g.each_edge(&block)
28
+ def output(renderer)
29
+ @ops.each { |op, *args|
30
+ renderer.add_node(*args) if op==:node
31
+ renderer.add_edge(*args) if op==:edge
32
+ }
33
+ renderer.output
30
34
  end
31
35
 
32
- def output(opts)
33
- log("output: #{opts}")
34
- @g.output(opts)
36
+ def uniquely_add(target, type, *opts, &block)
37
+ return if opts.compact.empty?
38
+ return if @nodes.include?([type, opts])
39
+ @nodes.add([type, opts])
40
+ target << yield
35
41
  end
36
42
 
43
+
37
44
  def log(msg)
38
45
  puts msg if ENV["DEBUG"]
39
46
  end
@@ -0,0 +1,30 @@
1
+ require 'graphviz'
2
+
3
+ module Renderer
4
+ class GraphViz
5
+ def initialize(file_name, config)
6
+ @g = ::GraphViz::new('G', :type => 'strict digraph') { |g|
7
+ g[:overlap] = :false
8
+ g[:splines] = :true
9
+ g[:sep] = 1
10
+ g[:concentrate] = :true
11
+ }
12
+ @file_name = file_name
13
+ @config = config
14
+ end
15
+
16
+ def add_node(name)
17
+ @g.add_node(name)
18
+ end
19
+
20
+ def add_edge(from, to, opts)
21
+ @g.add_edge(from, to, ({style: 'bold'}).merge(opts))
22
+ end
23
+
24
+ def output
25
+ extension = File.extname(@file_name)
26
+ opts = {extension[1..-1].to_sym => @file_name, :use => @config.format}
27
+ @g.output(opts)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ module Renderer
2
+ class Json
3
+ def initialize(file_name, config)
4
+ @nodes = []
5
+ @edges = []
6
+ @file_name = file_name
7
+ @config = config
8
+ end
9
+
10
+ def add_node(name)
11
+ @nodes << {id: name, label: name}
12
+ end
13
+
14
+ def add_edge(from, to, opts)
15
+ @edges << {id: "#{from}-#{to}", source: from, target: to, label: opts[:label]}
16
+ end
17
+
18
+ def output
19
+ IO.write(@file_name, {nodes: @nodes, edges: @edges}.to_json)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1 @@
1
+ {"nodes":[{"id":"app","label":"app"},{"id":"8.8.8.8/32","label":"8.8.8.8/32"},{"id":"amazon-elb-sg","label":"amazon-elb-sg"},{"id":"*","label":"*"},{"id":"db","label":"db"}],"edges":[{"id":"8.8.8.8/32-app","source":"8.8.8.8/32","target":"app","label":"80/tcp"},{"id":"amazon-elb-sg-app","source":"amazon-elb-sg","target":"app","label":"80/tcp"},{"id":"*-app","source":"*","target":"app","label":"22/tcp"},{"id":"app-db","source":"app","target":"db","label":"5984/tcp"}]}
@@ -1,17 +1,28 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe VisualizeAws do
4
- context 'json' do
5
- let(:opts) {
6
- {
4
+ let(:opts) {
5
+ {
7
6
  :source_file => source_file,
8
7
  :filename => temp_file
9
- }
10
8
  }
11
- let(:source_file) {File.join(File.dirname(__FILE__), 'dummy.json')}
12
- let(:expected_file) {File.join(File.dirname(__FILE__), 'dummy.dot')}
9
+ }
10
+ let(:source_file) { File.join(File.dirname(__FILE__), 'dummy.json') }
11
+ let(:config) { AwsConfig.new({groups: {'0.0.0.0/0' => '*'}}) }
12
+
13
+ context 'json to dot file' do
14
+ let(:expected_file) { File.join(File.dirname(__FILE__), 'dummy.dot') }
13
15
  let(:temp_file) { Tempfile.new(%w(aws .dot)) }
14
- let(:config) {AwsConfig.new({groups: {'0.0.0.0/0' => '*'}})}
16
+
17
+ it 'should parse json input', :integration => true do
18
+ VisualizeAws.new(config, opts).unleash(temp_file.path)
19
+ expect(File.read(expected_file)).to eq(temp_file.read)
20
+ end
21
+ end
22
+
23
+ context 'json to json file' do
24
+ let(:expected_file) { File.join(File.dirname(__FILE__), 'expected.json') }
25
+ let(:temp_file) { Tempfile.new(%w(aws .json)) }
15
26
 
16
27
  it 'should parse json input', :integration => true do
17
28
  VisualizeAws.new(config, opts).unleash(temp_file.path)
@@ -6,49 +6,52 @@ describe VisualizeAws do
6
6
  allow(Fog::Compute).to receive(:new).and_return(@ec2)
7
7
  end
8
8
 
9
- let(:visualize_aws) {VisualizeAws.new(AwsConfig.new)}
9
+ let(:visualize_aws) { VisualizeAws.new(AwsConfig.new) }
10
10
 
11
- it 'should add nodes for each security group' do
11
+ it 'should add nodes, edges for each security group' do
12
12
  expect(@ec2).to receive(:security_groups).and_return([group('Remote ssh', group_ingress('22', 'My machine')), group('My machine')])
13
13
  graph = visualize_aws.build
14
- node1 = graph.get_node('Remote ssh')
15
- node2 = graph.get_node('My machine')
16
14
 
17
- expect(node1).not_to be_nil
18
- expect(node2).not_to be_nil
19
- expect(graph.each_edge.size).to eq(1)
15
+ expect(graph.ops).to eq([
16
+ [:node, 'Remote ssh'],
17
+ [:node, 'My machine'],
18
+ [:edge, 'My machine', 'Remote ssh', {:color => :blue, :label => '22/tcp'}],
19
+ ])
20
20
  end
21
21
 
22
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
23
  it 'should add nodes for external security groups defined through ingress' do
32
24
  expect(@ec2).to receive(:security_groups).and_return([group('Web', group_ingress('80', 'ELB'))])
33
25
  graph = visualize_aws.build
34
26
 
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')
27
+ expect(graph.ops).to eq([
28
+ [:node, 'Web'],
29
+ [:node, 'ELB'],
30
+ [:edge, 'ELB', 'Web', {:color => :blue, :label => '80/tcp'}],
31
+ ])
39
32
  end
40
33
 
41
34
  it 'should add an edge for each security ingress' do
42
35
  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
- ])
36
+ [
37
+ group('App', group_ingress('80', 'Web'), group_ingress('8983', 'Internal')),
38
+ group('Web', group_ingress('80', 'External')),
39
+ group('Db', group_ingress('7474', 'App'))
40
+ ])
48
41
  graph = visualize_aws.build
49
42
 
50
- expect(graph.each_edge.size).to eq(4)
51
- expect(graph).to have_edge('Internal'=>'App', 'External' => 'Web', 'App'=> 'Db')
43
+ expect(graph.ops).to eq([
44
+ [:node, 'App'],
45
+ [:node, 'Web'],
46
+ [:edge, 'Web', 'App', {:color => :blue, :label => '80/tcp'}],
47
+ [:node, 'Internal'],
48
+ [:edge, 'Internal', 'App', {:color => :blue, :label => '8983/tcp'}],
49
+ [:node, 'External'],
50
+ [:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}],
51
+ [:node, 'Db'],
52
+ [:edge, 'App', 'Db', {:color => :blue, :label => '7474/tcp'}],
53
+ ])
54
+
52
55
  end
53
56
  end
54
57
 
@@ -56,92 +59,124 @@ describe VisualizeAws do
56
59
 
57
60
  it 'should add an edge for each cidr ingress' do
58
61
  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
- ])
62
+ [
63
+ group('Web', group_ingress('80', 'External')),
64
+ group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
65
+ ])
63
66
  graph = visualize_aws.build
64
67
 
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
+ expect(graph.ops).to eq([
69
+ [:node, 'Web'],
70
+ [:node, 'External'],
71
+ [:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}],
72
+ [:node, 'Db'],
73
+ [:node, 'App'],
74
+ [:edge, 'App', 'Db', {:color => :blue, :label => '7474/tcp'}],
75
+ [:node, '127.0.0.1/32'],
76
+ [:edge, '127.0.0.1/32', 'Db', {:color => :blue, :label => '22/tcp'}],
77
+ ])
78
+
68
79
  end
69
80
 
70
81
  it 'should add map edges for cidr ingress' do
71
82
  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
- ])
83
+ [
84
+ group('Web', group_ingress('80', 'External')),
85
+ group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
86
+ ])
76
87
  mapping = {'127.0.0.1/32' => 'Work'}
77
88
  mapping = CidrGroupMapping.new([], mapping)
78
89
  allow(CidrGroupMapping).to receive(:new).and_return(mapping)
79
90
 
80
91
  graph = visualize_aws.build
81
92
 
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' )
93
+ expect(graph.ops).to eq([
94
+ [:node, 'Web'],
95
+ [:node, 'External'],
96
+ [:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}],
97
+ [:node, 'Db'],
98
+ [:node, 'App'],
99
+ [:edge, 'App', 'Db', {:color => :blue, :label => '7474/tcp'}],
100
+ [:node, 'Work'],
101
+ [:edge, 'Work', 'Db', {:color => :blue, :label => '22/tcp'}],
102
+ ])
103
+
85
104
  end
105
+
86
106
  it 'should group mapped duplicate edges for cidr ingress' do
87
107
  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
- ])
108
+ [
109
+ group('ssh', cidr_ingress('22', '192.168.0.1/32'), cidr_ingress('22', '127.0.0.1/32'))
110
+ ])
91
111
  mapping = {'127.0.0.1/32' => 'Work', '192.168.0.1/32' => 'Work'}
92
112
  mapping = CidrGroupMapping.new([], mapping)
93
113
  allow(CidrGroupMapping).to receive(:new).and_return(mapping)
94
114
 
95
115
  graph = visualize_aws.build
96
116
 
97
- expect(graph.each_edge.size).to eq(1)
98
- expect(graph).to have_edge('Work' => 'ssh' )
117
+ expect(graph.ops).to eq([
118
+ [:node, 'ssh'],
119
+ [:node, 'Work'],
120
+ [:edge, 'Work', 'ssh', {:color => :blue, :label => '22/tcp'}],
121
+ ])
99
122
  end
100
123
  end
124
+
101
125
  context "filter" do
102
126
  it 'include cidr which do not match the pattern' do
103
127
  expect(@ec2).to receive(:security_groups).and_return(
104
- [
105
- group('Web', cidr_ingress('22', '127.0.0.1/32')),
106
- group('Db', cidr_ingress('22', '192.0.1.1/32'))
107
- ])
128
+ [
129
+ group('Web', cidr_ingress('22', '127.0.0.1/32')),
130
+ group('Db', cidr_ingress('22', '192.0.1.1/32'))
131
+ ])
108
132
 
109
133
  opts = {:exclude => ['127.*']}
110
134
  graph = VisualizeAws.new(AwsConfig.new(opts)).build
111
135
 
112
- expect(graph.each_edge.size).to eq(1)
113
- expect(graph).to have_edge('192.0.1.1/32' => 'Db')
114
- expect(graph).to_not have_edge('127.0.0.1/32' => 'Web')
136
+ expect(graph.ops).to eq([
137
+ [:node, 'Web'],
138
+ [:node, 'Db'],
139
+ [:node, '192.0.1.1/32'],
140
+ [:edge, '192.0.1.1/32', 'Db', {:color => :blue, :label => '22/tcp'}],
141
+ ])
115
142
  end
116
143
 
117
144
  it 'include groups which do not match the pattern' do
118
145
  expect(@ec2).to receive(:security_groups).and_return(
119
- [
120
- group('Web', group_ingress('80', 'External')),
121
- group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
122
- ])
146
+ [
147
+ group('Web', group_ingress('80', 'External')),
148
+ group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
149
+ ])
123
150
 
124
151
  opts = {:exclude => ['D.*b', 'App']}
125
152
  graph = VisualizeAws.new(AwsConfig.new(opts)).build
126
153
 
127
- expect(graph.each_edge.size).to eq(1)
128
- expect(graph).to have_edge('External' => 'Web')
154
+ expect(graph.ops).to eq([
155
+ [:node, 'Web'],
156
+ [:node, 'External'],
157
+ [:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}],
158
+ ])
129
159
  end
130
160
 
131
161
  it 'include derived groups which do not match the pattern' do
132
162
  expect(@ec2).to receive(:security_groups).and_return(
133
- [
134
- group('Web', group_ingress('80', 'External')),
135
- group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
136
- ])
163
+ [
164
+ group('Web', group_ingress('80', 'External')),
165
+ group('Db', group_ingress('7474', 'App'), cidr_ingress('22', '127.0.0.1/32'))
166
+ ])
137
167
 
138
168
  opts = {:exclude => ['App']}
139
169
  graph = VisualizeAws.new(AwsConfig.new(opts)).build
140
170
 
141
- expect(graph.each_edge.size).to eq(2)
142
- expect(graph).to have_edge('External' => 'Web')
143
- expect(graph).to have_edge('127.0.0.1/32' => 'Db' )
144
- end
171
+ expect(graph.ops).to eq([
172
+ [:node, 'Web'],
173
+ [:node, 'External'],
174
+ [:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}],
175
+ [:node, 'Db'],
176
+ [:node, '127.0.0.1/32'],
177
+ [:edge, '127.0.0.1/32', 'Db', {:color => :blue, :label => '22/tcp'}],
178
+ ])
145
179
 
180
+ end
146
181
  end
147
182
  end
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.1.2.pre.alpha.pre.58
4
+ version: 0.1.2.pre.alpha.pre.59
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anay Nayak
@@ -169,12 +169,14 @@ files:
169
169
  - lib/opts.yml.sample
170
170
  - lib/provider/ec2.rb
171
171
  - lib/provider/json.rb
172
+ - lib/renderer/graphviz.rb
173
+ - lib/renderer/json.rb
172
174
  - lib/version.rb
173
175
  - spec/integration/dummy.dot
174
176
  - spec/integration/dummy.json
177
+ - spec/integration/expected.json
175
178
  - spec/integration/visualize_aws_spec.rb
176
179
  - spec/spec_helper.rb
177
- - spec/support/matchers/graph.rb
178
180
  - spec/visualize_aws_spec.rb
179
181
  homepage: https://github.com/anaynayak/aws-security-viz
180
182
  licenses:
@@ -203,7 +205,7 @@ summary: Visualize your aws security groups
203
205
  test_files:
204
206
  - spec/integration/dummy.dot
205
207
  - spec/integration/dummy.json
208
+ - spec/integration/expected.json
206
209
  - spec/integration/visualize_aws_spec.rb
207
210
  - spec/spec_helper.rb
208
- - spec/support/matchers/graph.rb
209
211
  - spec/visualize_aws_spec.rb
@@ -1,8 +0,0 @@
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