aws_security_viz 0.2.5.pre.alpha.pre.35 → 1.0.0

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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +59 -1
  3. data/README.md +120 -79
  4. data/exe/aws_security_viz +4 -40
  5. data/lib/aws_security_viz/aws_config.rb +80 -0
  6. data/lib/aws_security_viz/cli.rb +151 -0
  7. data/lib/aws_security_viz/cli_guard.rb +39 -0
  8. data/lib/aws_security_viz/directed_graph.rb +72 -0
  9. data/lib/aws_security_viz/ec2/security_groups.rb +74 -0
  10. data/lib/aws_security_viz/exclusions.rb +18 -0
  11. data/lib/aws_security_viz/export/html/viewer.html +222 -0
  12. data/lib/aws_security_viz/graph.rb +93 -0
  13. data/lib/aws_security_viz/graph_filter.rb +20 -0
  14. data/lib/aws_security_viz/logging.rb +18 -0
  15. data/lib/aws_security_viz/model.rb +87 -0
  16. data/lib/aws_security_viz/obfuscation.rb +45 -0
  17. data/lib/{opts.yml.sample → aws_security_viz/opts.yml.sample} +2 -0
  18. data/lib/aws_security_viz/port_label.rb +44 -0
  19. data/lib/aws_security_viz/provider/ec2.rb +84 -0
  20. data/lib/aws_security_viz/provider/json.rb +17 -0
  21. data/lib/aws_security_viz/renderer/all.rb +49 -0
  22. data/lib/aws_security_viz/renderer/graphviz.rb +119 -0
  23. data/lib/aws_security_viz/renderer/html.rb +46 -0
  24. data/lib/aws_security_viz/renderer/json.rb +29 -0
  25. data/lib/aws_security_viz/renderer/mermaid.rb +105 -0
  26. data/lib/aws_security_viz/risk.rb +18 -0
  27. data/lib/aws_security_viz/vendor/cytoscape/LICENSE +19 -0
  28. data/lib/aws_security_viz/vendor/cytoscape/README.md +15 -0
  29. data/lib/aws_security_viz/vendor/cytoscape/cytoscape.min.js +31 -0
  30. data/lib/aws_security_viz/version.rb +5 -0
  31. data/lib/aws_security_viz.rb +44 -37
  32. metadata +39 -232
  33. data/.dockerignore +0 -7
  34. data/.editorconfig +0 -17
  35. data/.github/dependabot.yml +0 -15
  36. data/.github/workflows/ruby.yml +0 -34
  37. data/.github/workflows/rubygem.yml +0 -29
  38. data/.github/workflows/rubygem_release.yml +0 -27
  39. data/.gitignore +0 -43
  40. data/.tool-versions +0 -1
  41. data/CODE_OF_CONDUCT.md +0 -46
  42. data/Dockerfile +0 -9
  43. data/Gemfile +0 -3
  44. data/Rakefile +0 -15
  45. data/Vagrantfile +0 -18
  46. data/aws_security_viz.gemspec +0 -40
  47. data/config/boot.rb +0 -4
  48. data/images/sample.png +0 -0
  49. data/lib/aws_config.rb +0 -44
  50. data/lib/color_picker.rb +0 -245
  51. data/lib/debug/parse_log.rb +0 -26
  52. data/lib/debug_graph.rb +0 -29
  53. data/lib/ec2/ip_permission.rb +0 -35
  54. data/lib/ec2/security_groups.rb +0 -78
  55. data/lib/ec2/traffic.rb +0 -32
  56. data/lib/exclusions.rb +0 -14
  57. data/lib/export/html/navigator.html +0 -84
  58. data/lib/export/html/view.html +0 -163
  59. data/lib/graph.rb +0 -45
  60. data/lib/graph_filter.rb +0 -38
  61. data/lib/provider/ec2.rb +0 -105
  62. data/lib/provider/json.rb +0 -104
  63. data/lib/renderer/all.rb +0 -18
  64. data/lib/renderer/graphviz.rb +0 -37
  65. data/lib/renderer/json.rb +0 -23
  66. data/lib/renderer/navigator.rb +0 -33
  67. data/lib/version.rb +0 -3
  68. data/spec/color_picker_spec.rb +0 -20
  69. data/spec/graph_filter_spec.rb +0 -85
  70. data/spec/integration/aws_expected.json +0 -1
  71. data/spec/integration/dummy.dot +0 -50
  72. data/spec/integration/dummy.json +0 -64
  73. data/spec/integration/expected.json +0 -1
  74. data/spec/integration/navigator.json +0 -1
  75. data/spec/integration/visualize_aws_spec.rb +0 -96
  76. data/spec/spec_helper.rb +0 -36
  77. data/spec/visualize_aws_spec.rb +0 -194
@@ -1,163 +0,0 @@
1
- <html>
2
- <head>
3
- <style type="text/css">
4
- #container {
5
- max-width: 100%;
6
- height: 100%;
7
- margin: auto;
8
- }
9
-
10
- #error {
11
- color: #31708f;
12
- background-color: #d9edf7;
13
- padding: 15px;
14
- margin-bottom: 20px;
15
- border: 1px solid transparent;
16
- border-radius: 4px;
17
- }
18
- </style>
19
- </head>
20
- <body>
21
- <div id="error" style="display:none"></div>
22
- <div id="container"></div>
23
- <script src="https://cdnjs.cloudflare.com/ajax/libs/linkurious.js/1.5.0/sigma.min.js"></script>
24
- <script src="https://cdnjs.cloudflare.com/ajax/libs/linkurious.js/1.5.0/plugins/sigma.parsers.json.min.js"></script>
25
- <script src="https://cdnjs.cloudflare.com/ajax/libs/linkurious.js/1.5.0/plugins/sigma.layouts.forceLink.min.js"></script>
26
- <script src="https://cdnjs.cloudflare.com/ajax/libs/linkurious.js/1.5.0/plugins/sigma.plugins.design.min.js"></script>
27
- <script src="https://cdnjs.cloudflare.com/ajax/libs/linkurious.js/1.5.0/plugins/sigma.plugins.colorbrewer.min.js"></script>
28
- <script src="https://cdnjs.cloudflare.com/ajax/libs/linkurious.js/1.5.0/plugins/sigma.renderers.edgeLabels.min.js"></script>
29
- <script>
30
- sigma.classes.graph.addMethod('neighbors', function (nodeId) {
31
- var k,
32
- neighbors = {},
33
- index = this.allNeighborsIndex[nodeId] || {};
34
-
35
- for (k in index)
36
- neighbors[k] = this.nodesIndex[k];
37
-
38
- return neighbors;
39
- });
40
- sigma.classes.graph.addMethod('neighborCount', function (nodeId) {
41
- return this.allNeighborsCount[nodeId];
42
- });
43
- var config = {
44
- renderer: {
45
- container: 'container',
46
- type: 'canvas'
47
- },
48
- settings: {
49
- animationsTime: 1000,
50
- borderSize: 1,
51
- outerBorderSize: 1,
52
- defaultNodeOuterBorderColor: 'rgb(236, 81, 72)',
53
- enableEdgeHovering: true,
54
- edgeHoverHighlightNodes: 'circle',
55
- sideMargin: 1,
56
- edgeHoverColor: 'edge',
57
- defaultEdgeHoverColor: '#000',
58
- edgeHoverExtremities: true,
59
- scalingMode: 'outside',
60
- edgeLabelThreshold: 2,
61
- edgeHoverSizeRatio: 2,
62
- edgeLabelSize: 'proportional'
63
- }
64
- };
65
- var graphUrl = function () {
66
- return window.location.hash.replace(/^#/, '/');
67
- };
68
- var errorElement = document.getElementById("error");
69
- window.onhashchange = function () {
70
- loadGraph(graphUrl());
71
- };
72
-
73
- function loadGraph(url) {
74
- errorElement.style.display = "none";
75
- var initializeGraph = function (s) {
76
- s.graph.nodes().forEach(function (n) {
77
- n.x = Math.random();
78
- n.y = Math.random();
79
- n.size = 1;
80
- n.label = n.id;
81
- n.data = {edgeCount: s.graph.neighborCount(n.id)};
82
- });
83
- var myStyles = {
84
- nodes: {
85
- color: {
86
- by: 'data.edgeCount',
87
- scheme: 'colorbrewer.nodes',
88
- bins: 3
89
- },
90
- size: {
91
- by: 'data.edgeCount',
92
- bins: 7,
93
- min: 2,
94
- max: 10
95
- }
96
- }
97
- };
98
- var myPalette = {
99
- colorbrewer: {
100
- nodes: sigma.plugins.colorbrewer.Dark2
101
- }
102
- };
103
- var design = sigma.plugins.design(s, {styles: myStyles, palette: myPalette});
104
- design.apply();
105
-
106
- s.graph.nodes().forEach(function (n) {
107
- n.originalColor = n.color;
108
- });
109
- s.graph.edges().forEach(function (e) {
110
- e.size = 1;
111
- e.originalColor = e.color;
112
- e.type = "arrow";
113
- });
114
- var fa = sigma.layouts.startForceLink(s, {autoStop: true, adjustSizes: true, randomize: true});
115
-
116
- s.bind('clickNode', function (e) {
117
- var nodeId = e.data.node.id,
118
- toKeep = s.graph.neighbors(nodeId);
119
- toKeep[nodeId] = e.data.node;
120
-
121
- s.graph.nodes().forEach(function (n) {
122
- if (toKeep[n.id])
123
- n.color = n.originalColor;
124
- else
125
- n.color = '#eee';
126
- });
127
-
128
- s.graph.edges().forEach(function (e) {
129
- if (toKeep[e.source] && toKeep[e.target])
130
- e.color = e.originalColor;
131
- else
132
- e.color = '#eee';
133
- });
134
-
135
- s.refresh();
136
- });
137
- s.bind('clickStage', function (e) {
138
- s.graph.nodes().forEach(function (n) {
139
- n.color = n.originalColor;
140
- });
141
-
142
- s.graph.edges().forEach(function (e) {
143
- e.color = e.originalColor;
144
- });
145
-
146
- s.refresh();
147
- });
148
- };
149
- sigma.parsers.json(url, config, initializeGraph);
150
- }
151
-
152
- var url = graphUrl();
153
- if (url) {
154
- loadGraph(graphUrl());
155
- } else {
156
- var link = '<a href="' + location.href + '#test.json">' + location.href + '#test.json</a>';
157
- errorElement.innerHTML = "Please pass in a datasource via html fragment identifier. For e.g. " + link;
158
- errorElement.style.display = "";
159
- }
160
- </script>
161
- </body>
162
- </html>
163
-
data/lib/graph.rb DELETED
@@ -1,45 +0,0 @@
1
- require 'rgl/adjacency'
2
-
3
- class Graph
4
- attr_reader :underlying
5
-
6
- def initialize(config, underlying=RGL::DirectedAdjacencyGraph.new)
7
- @config = config
8
- @underlying = underlying
9
- @edge_properties = {}
10
- @node_properties = {}
11
- end
12
-
13
- def add_node(name, opts)
14
- log("node: #{name}, opts: #{opts}")
15
- @underlying.add_vertex(name)
16
- @node_properties[name] = opts
17
- end
18
-
19
- def add_edge(from, to, opts)
20
- log("edge: #{from} -> #{to}")
21
- @underlying.add_edge(from, to)
22
- @edge_properties[[from, to]] = opts
23
- end
24
-
25
- def filter(source, destination)
26
- @underlying = GraphFilter.new(underlying).filter(source, destination)
27
- end
28
-
29
- def output(renderer)
30
- @underlying.each_vertex { |v| renderer.add_node(v, @node_properties[v] || {}) }
31
- @underlying.each_edge { |u, v|
32
- renderer.add_edge(u, v, opts(u, v))
33
- }
34
- renderer.output
35
- end
36
-
37
- def log(msg)
38
- puts msg if @config.debug?
39
- end
40
-
41
- private
42
- def opts(u, v)
43
- @edge_properties[[u, v]]
44
- end
45
- end
data/lib/graph_filter.rb DELETED
@@ -1,38 +0,0 @@
1
- require 'rgl/traversal'
2
- require 'rgl/implicit'
3
-
4
- class GraphFilter
5
- def initialize(graph)
6
- @graph = graph
7
- end
8
-
9
- def filter(source, destination)
10
- return @graph if source.nil? && destination.nil?
11
- if !source.nil? && destination.nil?
12
- return reduce(@graph, source)
13
- end
14
- if !destination.nil? && source.nil?
15
- return reduce(@graph.reverse, destination).reverse
16
- end
17
- search(@graph, source, destination)
18
- end
19
-
20
- private
21
- def reduce(graph, source)
22
- tree = graph.bfs_search_tree_from(source)
23
- graph.vertices_filtered_by { |v| tree.has_vertex? v }
24
- end
25
-
26
- def search(graph, source, destination)
27
- visitor = RGL::DFSVisitor.new(graph)
28
- path = []
29
- paths = []
30
- visitor.set_examine_vertex_event_handler { |x| path << x }
31
- visitor.set_finish_vertex_event_handler { |x| path.pop }
32
- visitor.set_examine_edge_event_handler { |x, y| paths << path.clone + [y] if y == destination }
33
- graph.depth_first_visit(source, visitor) { |x|}
34
- to_remove = graph.vertices - paths.flatten
35
- graph.remove_vertices(*to_remove)
36
- graph
37
- end
38
- end
data/lib/provider/ec2.rb DELETED
@@ -1,105 +0,0 @@
1
- require 'aws-sdk-ec2'
2
-
3
- class Ec2Provider
4
-
5
- def initialize(options)
6
- @options = options
7
- conn_opts = {
8
- region: options[:region],
9
- access_key_id: options[:access_key],
10
- secret_access_key: options[:secret_key],
11
- session_token: options[:session_token]
12
- }.delete_if {|k,v| v.nil?}
13
-
14
- @client = Aws::EC2::Client.new(conn_opts)
15
- end
16
-
17
- def security_groups
18
- @client.describe_security_groups.security_groups.reject { |sg|
19
- @options[:vpc_id] && sg.vpc_id != @options[:vpc_id]
20
- }.collect { |sg|
21
- Ec2::SecurityGroup.new(sg)
22
- }
23
- end
24
- end
25
-
26
- module Ec2
27
- class SecurityGroup
28
- extend Forwardable
29
- def_delegators :@sg, :name, :group_id, :vpc_id
30
- def initialize(sg)
31
- @sg = sg
32
- end
33
-
34
- def name
35
- @sg.group_name
36
- end
37
-
38
- def ip_permissions
39
- @sg.ip_permissions.collect { |ip|
40
- Ec2::IpPermission.new(ip)
41
- }
42
- end
43
-
44
- def ip_permissions_egress
45
- @sg.ip_permissions_egress.collect { |ip|
46
- Ec2::IpPermission.new(ip)
47
- }
48
- end
49
- end
50
-
51
- class IpPermission
52
- def initialize(ip)
53
- @ip = ip
54
- end
55
-
56
- def protocol
57
- @ip['ip_protocol']
58
- end
59
-
60
- def from
61
- @ip['from_port']
62
- end
63
-
64
- def to
65
- @ip['to_port']
66
- end
67
-
68
- def ip_ranges
69
- @ip['ip_ranges'].collect {|gp|
70
- Ec2::IpPermissionRange.new(gp)
71
- }
72
- end
73
-
74
- def groups
75
- @ip['user_id_group_pairs'].collect {|gp|
76
- Ec2::IpPermissionGroup.new(gp)
77
- }
78
- end
79
- end
80
-
81
- class IpPermissionRange
82
- def initialize(range)
83
- @range = range
84
- end
85
-
86
- def cidr_ip
87
- @range['cidr_ip']
88
- end
89
-
90
- def to_str
91
- cidr_ip
92
- end
93
- end
94
-
95
- class IpPermissionGroup
96
- def initialize(gp)
97
- @gp = gp
98
- end
99
-
100
- def name
101
- @gp['group_name'] || @gp['group_id']
102
- end
103
- end
104
-
105
- end
data/lib/provider/json.rb DELETED
@@ -1,104 +0,0 @@
1
- require 'json'
2
-
3
- class JsonProvider
4
- def initialize(options)
5
- @groups = JSON.parse(File.read(options[:source_file]))['SecurityGroups']
6
- end
7
-
8
- def security_groups
9
- @groups.collect { |sg|
10
- Json::SecurityGroup.new(sg)
11
- }
12
- end
13
- end
14
-
15
- module Json
16
- class SecurityGroup
17
- def initialize(sg)
18
- @sg = sg
19
- end
20
-
21
- def name
22
- @sg['GroupName']
23
- end
24
-
25
- def group_id
26
- @sg['GroupId']
27
- end
28
-
29
- def vpc_id
30
- @sg['VpcId']
31
- end
32
-
33
- def ip_permissions
34
- @sg['IpPermissions'].collect { |ip|
35
- Json::IpPermission.new(ip)
36
- }
37
- end
38
-
39
- def group_id
40
- @sg['GroupId']
41
- end
42
-
43
- def ip_permissions_egress
44
- @sg['IpPermissionsEgress'].collect { |ip|
45
- Json::IpPermission.new(ip)
46
- }
47
- end
48
- end
49
-
50
- class IpPermission
51
- def initialize(ip)
52
- @ip = ip
53
- end
54
-
55
- def protocol
56
- @ip['IpProtocol']
57
- end
58
-
59
- def from
60
- @ip['FromPort']
61
- end
62
-
63
- def to
64
- @ip['ToPort']
65
- end
66
-
67
- def ip_ranges
68
- @ip['IpRanges'].collect { |gp|
69
- Json::IpPermissionRange.new(gp)
70
- }
71
- end
72
-
73
- def groups
74
- @ip['UserIdGroupPairs'].collect { |pair|
75
- Json::IpPermissionGroup.new(pair)
76
- }
77
- end
78
-
79
- end
80
-
81
- class IpPermissionRange
82
- def initialize(range)
83
- @range = range
84
- end
85
-
86
- def cidr_ip
87
- @range['CidrIp']
88
- end
89
-
90
- def to_str
91
- cidr_ip
92
- end
93
- end
94
-
95
- class IpPermissionGroup
96
- def initialize(gp)
97
- @gp = gp
98
- end
99
-
100
- def name
101
- @gp['GroupName'] || @gp['GroupId']
102
- end
103
- end
104
- end
data/lib/renderer/all.rb DELETED
@@ -1,18 +0,0 @@
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
@@ -1,37 +0,0 @@
1
- require 'graphviz'
2
-
3
- module Renderer
4
- class GraphViz
5
- def initialize(file_name, config)
6
- @g = Graphviz::Graph.new('G', **{
7
- overlap: false,
8
- splines: true,
9
- sep: 1,
10
- concentrate: true,
11
- rankdir: "LR"
12
- })
13
- @file_name = file_name
14
- @config = config
15
- end
16
-
17
- def add_node(name, opts)
18
- @g.add_node(name, label: name)
19
- end
20
-
21
- def add_edge(from, to, opts)
22
- from_node = create_if_missing(from)
23
- to_node = create_if_missing(to)
24
- options = ({style: 'bold'}).merge(opts)
25
- from_node.connect(to_node, options)
26
- end
27
-
28
- def create_if_missing(name)
29
- n = @g.get_node(name).first
30
- n.nil? ? add_node(name, {}) : n
31
- end
32
-
33
- def output
34
- Graphviz::output(@g, path: @file_name, format: nil) #format: nil to force detection based on extension.
35
- end
36
- end
37
- end
data/lib/renderer/json.rb DELETED
@@ -1,23 +0,0 @@
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, opts)
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
- Renderer.copy_asset('view.html', @file_name)
21
- end
22
- end
23
- end
@@ -1,33 +0,0 @@
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
- info = "<b>Security group</b>: #{name}, <br/><b>VPC:</b> #{vpc}"
16
- @nodes << {id: name, label: name, categories: [vpc], info: info}
17
- @categories.add(vpc)
18
- end
19
-
20
- def add_edge(from, to, opts)
21
- @edges << {id: "#{from}-#{to}", from: from, to: to, label: opts[:label]}
22
- end
23
-
24
- def output
25
- IO.write(@file_name, {
26
- data: {nodes: @nodes, edges: @edges},
27
- categories: Hash[@categories.map{|c| [c, c]}]
28
- }.to_json)
29
- Renderer.copy_asset('navigator.html', @file_name)
30
- end
31
- end
32
- end
33
-
data/lib/version.rb DELETED
@@ -1,3 +0,0 @@
1
- module AwsSecurityViz
2
- VERSION = '0.2.5'
3
- end
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ColorPicker do
4
- context 'default picker' do
5
- let(:picker) { ColorPicker.new(false) }
6
-
7
- it 'should add default colors for edges' do
8
- expect(picker.color(0, true)).to eq(:blue)
9
- expect(picker.color(0, false)).to eq(:red)
10
- end
11
- end
12
- context 'color picker' do
13
- let(:picker) { ColorPicker.new(true) }
14
-
15
- it 'should add default colors for edges' do
16
- expect(picker.color(0, 'ignore')).to eq('#00004c')
17
- expect(picker.color(10000, 'ignore')).to eq('#C76F5B')
18
- end
19
- end
20
- end
@@ -1,85 +0,0 @@
1
- require 'spec_helper'
2
- require 'ostruct'
3
-
4
- describe GraphFilter do
5
- it 'should include nodes reachable from source' do
6
- graph = GraphFilter.new(RGL::DirectedAdjacencyGraph[1, 2, 2, 3, 2, 4, 4, 5])
7
-
8
- expect(graph.filter(2, nil).to_s).to eq('(2-3)(2-4)(4-5)')
9
- end
10
- it 'should remove nodes not reachable from source' do
11
- graph = GraphFilter.new(RGL::DirectedAdjacencyGraph[1, 2, 2, 3, 2, 4, 4, 5, 3, 5])
12
-
13
- expect(graph.filter(3, nil).to_s).to eq('(3-5)')
14
- end
15
- it 'should remove nodes not reachable to destination' do
16
- graph = GraphFilter.new(RGL::DirectedAdjacencyGraph[
17
- 1, 2,
18
- 1, 3,
19
- 1, 4,
20
- 2, 3,
21
- 2, 4,
22
- 3, 4,
23
- ])
24
-
25
- expect(graph.filter(nil, 3).to_s).to eq('(1-2)(1-3)(2-3)')
26
- end
27
- it 'should remove nodes not reachable to destination from source' do
28
- graph = GraphFilter.new(RGL::DirectedAdjacencyGraph[
29
- 1, 2,
30
- 1, 3,
31
- 1, 4,
32
- 2, 3,
33
- 2, 4,
34
- ])
35
-
36
- expect(graph.filter(2, 4).to_s).to eq('(2-4)')
37
- end
38
- it 'should retain edges which pass through intermediate nodes' do
39
- graph = GraphFilter.new(RGL::DirectedAdjacencyGraph[
40
- 1, 2,
41
- 1, 3,
42
- 1, 4,
43
- 2, 3,
44
- 2, 4,
45
- 3, 4,
46
- ])
47
- expect(graph.filter(2, 4).to_s).to eq('(2-3)(2-4)(3-4)')
48
- end
49
- it 'should remove nodes not reachable to destination from source #1' do
50
- graph = GraphFilter.new(RGL::DirectedAdjacencyGraph[
51
- 1, 2,
52
- 1, 3,
53
- 1, 4,
54
- 2, 3,
55
- 2, 4,
56
- 3, 5,
57
- 5, 4
58
- ])
59
- expect(graph.filter(1, 5).to_s).to eq('(1-2)(1-3)(2-3)(3-5)')
60
- end
61
- it 'should remove nodes not reachable to destination from source #2' do
62
- graph = GraphFilter.new(RGL::DirectedAdjacencyGraph[
63
- 1, 2,
64
- 1, 3,
65
- 1, 4,
66
- 2, 3,
67
- 2, 4,
68
- 3, 5,
69
- 5, 4
70
- ])
71
- expect(graph.filter(1, 4).to_s).to eq('(1-2)(1-3)(1-4)(2-3)(2-4)(3-5)(5-4)')
72
- end
73
- it 'should remove nodes not reachable to destination from source #3' do
74
- graph = GraphFilter.new(RGL::DirectedAdjacencyGraph[
75
- 1, 2,
76
- 1, 3,
77
- 1, 4,
78
- 2, 3,
79
- 2, 4,
80
- 3, 5,
81
- 5, 4
82
- ])
83
- expect(graph.filter(2, 4).to_s).to eq('(2-3)(2-4)(3-5)(5-4)')
84
- end
85
- end
@@ -1 +0,0 @@
1
- {"nodes":[{"id":"asv-app","label":"asv-app"},{"id":"asv-bastion","label":"asv-bastion"},{"id":"*","label":"*"},{"id":"asv-db","label":"asv-db"},{"id":"asv-solr","label":"asv-solr"},{"id":"default","label":"default"}],"edges":[{"id":"asv-bastion-asv-app","source":"asv-bastion","target":"asv-app","label":"22/tcp"},{"id":"*-asv-app","source":"*","target":"asv-app","label":"80/tcp"},{"id":"*-asv-bastion","source":"*","target":"asv-bastion","label":"22/tcp"},{"id":"asv-app-asv-db","source":"asv-app","target":"asv-db","label":"5432/tcp"},{"id":"asv-bastion-asv-db","source":"asv-bastion","target":"asv-db","label":"22/tcp"},{"id":"asv-app-asv-solr","source":"asv-app","target":"asv-solr","label":"8983/tcp"},{"id":"asv-bastion-asv-solr","source":"asv-bastion","target":"asv-solr","label":"22/tcp"},{"id":"default-default","source":"default","target":"default","label":"*"},{"id":"*-default","source":"*","target":"default","label":"22/tcp"},{"id":"default-*","source":"default","target":"*","label":"*"}]}