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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +59 -1
- data/README.md +120 -79
- data/exe/aws_security_viz +4 -40
- data/lib/aws_security_viz/aws_config.rb +80 -0
- data/lib/aws_security_viz/cli.rb +151 -0
- data/lib/aws_security_viz/cli_guard.rb +39 -0
- data/lib/aws_security_viz/directed_graph.rb +72 -0
- data/lib/aws_security_viz/ec2/security_groups.rb +74 -0
- data/lib/aws_security_viz/exclusions.rb +18 -0
- data/lib/aws_security_viz/export/html/viewer.html +222 -0
- data/lib/aws_security_viz/graph.rb +93 -0
- data/lib/aws_security_viz/graph_filter.rb +20 -0
- data/lib/aws_security_viz/logging.rb +18 -0
- data/lib/aws_security_viz/model.rb +87 -0
- data/lib/aws_security_viz/obfuscation.rb +45 -0
- data/lib/{opts.yml.sample → aws_security_viz/opts.yml.sample} +2 -0
- data/lib/aws_security_viz/port_label.rb +44 -0
- data/lib/aws_security_viz/provider/ec2.rb +84 -0
- data/lib/aws_security_viz/provider/json.rb +17 -0
- data/lib/aws_security_viz/renderer/all.rb +49 -0
- data/lib/aws_security_viz/renderer/graphviz.rb +119 -0
- data/lib/aws_security_viz/renderer/html.rb +46 -0
- data/lib/aws_security_viz/renderer/json.rb +29 -0
- data/lib/aws_security_viz/renderer/mermaid.rb +105 -0
- data/lib/aws_security_viz/risk.rb +18 -0
- data/lib/aws_security_viz/vendor/cytoscape/LICENSE +19 -0
- data/lib/aws_security_viz/vendor/cytoscape/README.md +15 -0
- data/lib/aws_security_viz/vendor/cytoscape/cytoscape.min.js +31 -0
- data/lib/aws_security_viz/version.rb +5 -0
- data/lib/aws_security_viz.rb +44 -37
- metadata +39 -232
- data/.dockerignore +0 -7
- data/.editorconfig +0 -17
- data/.github/dependabot.yml +0 -15
- data/.github/workflows/ruby.yml +0 -34
- data/.github/workflows/rubygem.yml +0 -29
- data/.github/workflows/rubygem_release.yml +0 -27
- data/.gitignore +0 -43
- data/.tool-versions +0 -1
- data/CODE_OF_CONDUCT.md +0 -46
- data/Dockerfile +0 -9
- data/Gemfile +0 -3
- data/Rakefile +0 -15
- data/Vagrantfile +0 -18
- data/aws_security_viz.gemspec +0 -40
- data/config/boot.rb +0 -4
- data/images/sample.png +0 -0
- data/lib/aws_config.rb +0 -44
- data/lib/color_picker.rb +0 -245
- data/lib/debug/parse_log.rb +0 -26
- data/lib/debug_graph.rb +0 -29
- data/lib/ec2/ip_permission.rb +0 -35
- data/lib/ec2/security_groups.rb +0 -78
- data/lib/ec2/traffic.rb +0 -32
- data/lib/exclusions.rb +0 -14
- data/lib/export/html/navigator.html +0 -84
- data/lib/export/html/view.html +0 -163
- data/lib/graph.rb +0 -45
- data/lib/graph_filter.rb +0 -38
- data/lib/provider/ec2.rb +0 -105
- data/lib/provider/json.rb +0 -104
- data/lib/renderer/all.rb +0 -18
- data/lib/renderer/graphviz.rb +0 -37
- data/lib/renderer/json.rb +0 -23
- data/lib/renderer/navigator.rb +0 -33
- data/lib/version.rb +0 -3
- data/spec/color_picker_spec.rb +0 -20
- data/spec/graph_filter_spec.rb +0 -85
- data/spec/integration/aws_expected.json +0 -1
- data/spec/integration/dummy.dot +0 -50
- data/spec/integration/dummy.json +0 -64
- data/spec/integration/expected.json +0 -1
- data/spec/integration/navigator.json +0 -1
- data/spec/integration/visualize_aws_spec.rb +0 -96
- data/spec/spec_helper.rb +0 -36
- data/spec/visualize_aws_spec.rb +0 -194
data/spec/integration/dummy.dot
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
digraph G {
|
|
2
|
-
graph [bb="0,0,388.31,144",
|
|
3
|
-
concentrate=true,
|
|
4
|
-
overlap=false,
|
|
5
|
-
rankdir=LR,
|
|
6
|
-
sep=1,
|
|
7
|
-
splines=true
|
|
8
|
-
];
|
|
9
|
-
node [label="\N"];
|
|
10
|
-
app [height=0.5,
|
|
11
|
-
label=app,
|
|
12
|
-
pos="222.32,72",
|
|
13
|
-
width=0.75];
|
|
14
|
-
db [height=0.5,
|
|
15
|
-
label=db,
|
|
16
|
-
pos="361.31,72",
|
|
17
|
-
width=0.75];
|
|
18
|
-
app -> db [color=blue,
|
|
19
|
-
label="5984/tcp",
|
|
20
|
-
lp="291.81,79",
|
|
21
|
-
pos="e,334.25,72 249.45,72 270.68,72 300.46,72 323.95,72",
|
|
22
|
-
style=bold];
|
|
23
|
-
"8.8.8.8/32" [height=0.5,
|
|
24
|
-
label="8.8.8.8/32",
|
|
25
|
-
pos="62.161,126",
|
|
26
|
-
width=1.2702];
|
|
27
|
-
"8.8.8.8/32" -> app [color=blue,
|
|
28
|
-
label="80/tcp",
|
|
29
|
-
lp="159.82,108",
|
|
30
|
-
pos="e,199.09,81.689 98.964,115.29 121.69,108.48 151.36,99.231 177.32,90 181.33,88.572 185.52,87.006 189.65,85.41",
|
|
31
|
-
style=bold];
|
|
32
|
-
"amazon-elb-sg" [height=0.5,
|
|
33
|
-
label="amazon-elb-sg",
|
|
34
|
-
pos="62.161,72",
|
|
35
|
-
width=1.7267];
|
|
36
|
-
"amazon-elb-sg" -> app [color=blue,
|
|
37
|
-
label="80/tcp",
|
|
38
|
-
lp="159.82,79",
|
|
39
|
-
pos="e,195.01,72 124.54,72 144.95,72 166.98,72 184.95,72",
|
|
40
|
-
style=bold];
|
|
41
|
-
"*" [height=0.5,
|
|
42
|
-
label="*",
|
|
43
|
-
pos="62.161,18",
|
|
44
|
-
width=0.75];
|
|
45
|
-
"*" -> app [color=blue,
|
|
46
|
-
label="22/tcp",
|
|
47
|
-
lp="159.82,61",
|
|
48
|
-
pos="e,199.09,62.311 87.055,25.175 110.5,32.076 146.53,43.049 177.32,54 181.33,55.428 185.52,56.994 189.65,58.59",
|
|
49
|
-
style=bold];
|
|
50
|
-
}
|
data/spec/integration/dummy.json
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
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
|
-
|
|
@@ -1 +0,0 @@
|
|
|
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":"app-db","source":"app","target":"db","label":"5984/tcp"},{"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"}]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"data":{"nodes":[{"id":"app","label":"app","categories":["default"],"info":"<b>Security group</b>: app, <br/><b>VPC:</b> default"},{"id":"8.8.8.8/32","label":"8.8.8.8/32","categories":["default"],"info":"<b>Security group</b>: 8.8.8.8/32, <br/><b>VPC:</b> default"},{"id":"amazon-elb-sg","label":"amazon-elb-sg","categories":["default"],"info":"<b>Security group</b>: amazon-elb-sg, <br/><b>VPC:</b> default"},{"id":"*","label":"*","categories":["default"],"info":"<b>Security group</b>: *, <br/><b>VPC:</b> default"},{"id":"db","label":"db","categories":["default"],"info":"<b>Security group</b>: db, <br/><b>VPC:</b> 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"}]},"categories":{"default":"default"}}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'tempfile'
|
|
3
|
-
|
|
4
|
-
RSpec::Matchers.define :be_graph_with do |nodes|
|
|
5
|
-
match do |graphv|
|
|
6
|
-
graphv.nodes.keys == nodes
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
describe VisualizeAws do
|
|
11
|
-
let(:opts) {
|
|
12
|
-
{
|
|
13
|
-
:source_file => source_file,
|
|
14
|
-
:filename => temp_file
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
let(:source_file) { File.join(File.dirname(__FILE__), 'dummy.json') }
|
|
18
|
-
let(:config) { AwsConfig.new({groups: {'0.0.0.0/0' => '*'}}) }
|
|
19
|
-
let(:expected_content) { File.read(expected_file) }
|
|
20
|
-
let(:actual_content) { temp_file.read }
|
|
21
|
-
|
|
22
|
-
context 'json to dot file' do
|
|
23
|
-
let(:expected_file) { File.join(File.dirname(__FILE__), 'dummy.dot') }
|
|
24
|
-
let(:temp_file) { Tempfile.new(%w(aws .dot)) }
|
|
25
|
-
|
|
26
|
-
def without_pos(data)
|
|
27
|
-
return data
|
|
28
|
-
.gsub(/pos=\"[a-z,0-9\.\s]*\"/, '')
|
|
29
|
-
.gsub(/\s{2,}/, ' ') # trim spaces
|
|
30
|
-
.gsub(/\t/, ' ') # remove tabs
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it 'should parse json input', :integration => true do
|
|
34
|
-
VisualizeAws.new(config, opts).unleash(temp_file.path)
|
|
35
|
-
expect(without_pos(expected_content)).to eq(without_pos(actual_content))
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it 'should parse json input with stubbed out graphviz' do
|
|
39
|
-
nodes = ["app", "8.8.8.8/32", "amazon-elb-sg", "*", "db"]
|
|
40
|
-
allow(Graphviz).to receive(:output).with(be_graph_with(nodes), path: temp_file.path, format: nil)
|
|
41
|
-
VisualizeAws.new(config, opts).unleash(temp_file.path)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
context 'json to json file' do
|
|
46
|
-
let(:expected_file) { File.join(File.dirname(__FILE__), 'expected.json') }
|
|
47
|
-
let(:temp_file) { Tempfile.new(%w(aws .json)) }
|
|
48
|
-
|
|
49
|
-
it 'should parse json input' do
|
|
50
|
-
expect(FileUtils).to receive(:copy)
|
|
51
|
-
VisualizeAws.new(config, opts.merge(:renderer => 'json')).unleash(temp_file.path)
|
|
52
|
-
expect(JSON.parse(expected_content)).to eq(JSON.parse(actual_content))
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
it 'should parse json input with obfuscation' do
|
|
56
|
-
config = AwsConfig.new({groups: {'0.0.0.0/0' => '*'}, obfuscate: true})
|
|
57
|
-
expect(FileUtils).to receive(:copy)
|
|
58
|
-
VisualizeAws.new(config, opts.merge(:renderer => 'json')).unleash(temp_file.path)
|
|
59
|
-
expect(actual_content).not_to include('"amazon-elb-sg"', '"app"', '"db"')
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
context 'json to navigator file' do
|
|
65
|
-
let(:expected_file) { File.join(File.dirname(__FILE__), 'navigator.json') }
|
|
66
|
-
let(:temp_file) { Tempfile.new(%w(aws .json)) }
|
|
67
|
-
|
|
68
|
-
it 'should parse json input' do
|
|
69
|
-
expect(FileUtils).to receive(:copy)
|
|
70
|
-
VisualizeAws.new(config, opts.merge(:renderer => 'navigator')).unleash(temp_file.path)
|
|
71
|
-
expect(JSON.parse(expected_content)).to eq(JSON.parse(actual_content))
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
if ENV['TEST_ACCESS_KEY']
|
|
76
|
-
context 'ec2 to json file' do
|
|
77
|
-
let(:expected_file) { File.join(File.dirname(__FILE__), 'aws_expected.json') }
|
|
78
|
-
let(:temp_file) { Tempfile.new(%w(aws .json)) }
|
|
79
|
-
let(:opts) {
|
|
80
|
-
{
|
|
81
|
-
:filename => temp_file,
|
|
82
|
-
:secret_key => ENV['TEST_SECRET_KEY'],
|
|
83
|
-
:access_key => ENV['TEST_ACCESS_KEY'],
|
|
84
|
-
:region => 'us-east-1'
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
it 'should read from ec2 account', :integration => true do
|
|
89
|
-
expect(FileUtils).to receive(:copy)
|
|
90
|
-
VisualizeAws.new(config, opts).unleash(temp_file.path)
|
|
91
|
-
expect(JSON.parse(expected_content)['edges']).to match_array(JSON.parse(actual_content)['edges'])
|
|
92
|
-
expect(JSON.parse(expected_content)['nodes']).to match_array(JSON.parse(actual_content)['nodes'])
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
end
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
if ENV['COVERAGE']
|
|
2
|
-
require 'simplecov'
|
|
3
|
-
|
|
4
|
-
SimpleCov.start do
|
|
5
|
-
add_filter '/spec/'
|
|
6
|
-
end
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
require 'bundler'
|
|
10
|
-
Bundler.require
|
|
11
|
-
require 'rspec'
|
|
12
|
-
require 'rubygems'
|
|
13
|
-
require File.expand_path(File.dirname(__FILE__) + "/../config/boot")
|
|
14
|
-
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
|
|
15
|
-
|
|
16
|
-
def group name, *ingress
|
|
17
|
-
{group_name: name, group_id: 'some group', ip_permissions: ingress, ip_permissions_egress: []}
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def group_ingress port, name
|
|
21
|
-
{user_id_group_pairs:[{user_id: "userId", group_id: "sg-groupId", group_name: name}], ip_ranges:[], ip_protocol: "tcp", from_port: port, to_port: port}
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def cidr_ingress port, cidr_ip
|
|
25
|
-
{ip_ranges:[{cidr_ip: cidr_ip}], ip_protocol: "tcp", from_port: port, to_port: port}
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def stub_security_groups groups
|
|
29
|
-
Aws.config[:ec2] = {
|
|
30
|
-
stub_responses: {
|
|
31
|
-
describe_security_groups: {
|
|
32
|
-
security_groups: groups
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
end
|
data/spec/visualize_aws_spec.rb
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
class DummyRenderer
|
|
4
|
-
attr_reader :output
|
|
5
|
-
|
|
6
|
-
def initialize
|
|
7
|
-
@output = []
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def add_node(name, opts)
|
|
11
|
-
@output << [:node, name]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def add_edge(from, to, opts)
|
|
15
|
-
@output << [:edge, from, to, opts]
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
describe VisualizeAws do
|
|
20
|
-
let(:visualize_aws) { VisualizeAws.new(AwsConfig.new) }
|
|
21
|
-
let(:renderer) { DummyRenderer.new }
|
|
22
|
-
|
|
23
|
-
it 'should add nodes, edges for each security group' do
|
|
24
|
-
stub_security_groups([group('Remote ssh', group_ingress(22, 'My machine')), group('My machine')])
|
|
25
|
-
graph = visualize_aws.build
|
|
26
|
-
|
|
27
|
-
expect(graph.output(renderer)).to contain_exactly(
|
|
28
|
-
[:node, 'Remote ssh'],
|
|
29
|
-
[:node, 'My machine'],
|
|
30
|
-
[:edge, 'My machine', 'Remote ssh', {:color => :blue, :label => '22/tcp'}],
|
|
31
|
-
)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
context 'groups' do
|
|
35
|
-
it 'should add nodes for external security groups defined through ingress' do
|
|
36
|
-
stub_security_groups([group('Web', group_ingress(80, 'ELB'))])
|
|
37
|
-
graph = visualize_aws.build
|
|
38
|
-
|
|
39
|
-
expect(graph.output(renderer)).to contain_exactly(
|
|
40
|
-
[:node, 'Web'],
|
|
41
|
-
[:node, 'ELB'],
|
|
42
|
-
[:edge, 'ELB', 'Web', {:color => :blue, :label => '80/tcp'}]
|
|
43
|
-
)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'should add an edge for each security ingress' do
|
|
47
|
-
stub_security_groups(
|
|
48
|
-
[
|
|
49
|
-
group('App', group_ingress(80, 'Web'), group_ingress(8983, 'Internal')),
|
|
50
|
-
group('Web', group_ingress(80, 'External')),
|
|
51
|
-
group('Db', group_ingress(7474, 'App'))
|
|
52
|
-
])
|
|
53
|
-
graph = visualize_aws.build
|
|
54
|
-
|
|
55
|
-
expect(graph.output(renderer)).to contain_exactly(
|
|
56
|
-
[:node, 'App'],
|
|
57
|
-
[:node, 'Web'],
|
|
58
|
-
[:edge, 'Web', 'App', {:color => :blue, :label => '80/tcp'}],
|
|
59
|
-
[:node, 'Internal'],
|
|
60
|
-
[:edge, 'Internal', 'App', {:color => :blue, :label => '8983/tcp'}],
|
|
61
|
-
[:node, 'External'],
|
|
62
|
-
[:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}],
|
|
63
|
-
[:node, 'Db'],
|
|
64
|
-
[:edge, 'App', 'Db', {:color => :blue, :label => '7474/tcp'}]
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
context 'cidr' do
|
|
71
|
-
|
|
72
|
-
it 'should add an edge for each cidr ingress' do
|
|
73
|
-
stub_security_groups(
|
|
74
|
-
[
|
|
75
|
-
group('Web', group_ingress(80, 'External')),
|
|
76
|
-
group('Db', group_ingress(7474, 'App'), cidr_ingress(22, '127.0.0.1/32'))
|
|
77
|
-
])
|
|
78
|
-
graph = visualize_aws.build
|
|
79
|
-
|
|
80
|
-
expect(graph.output(renderer)).to contain_exactly(
|
|
81
|
-
[:node, 'Web'],
|
|
82
|
-
[:node, 'External'],
|
|
83
|
-
[:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}],
|
|
84
|
-
[:node, 'Db'],
|
|
85
|
-
[:node, 'App'],
|
|
86
|
-
[:edge, 'App', 'Db', {:color => :blue, :label => '7474/tcp'}],
|
|
87
|
-
[:node, '127.0.0.1/32'],
|
|
88
|
-
[:edge, '127.0.0.1/32', 'Db', {:color => :blue, :label => '22/tcp'}]
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it 'should add map edges for cidr ingress' do
|
|
94
|
-
stub_security_groups(
|
|
95
|
-
[
|
|
96
|
-
group('Web', group_ingress(80, 'External')),
|
|
97
|
-
group('Db', group_ingress(7474, 'App'), cidr_ingress(22, '127.0.0.1/32'))
|
|
98
|
-
])
|
|
99
|
-
mapping = {'127.0.0.1/32' => 'Work'}
|
|
100
|
-
mapping = CidrGroupMapping.new([], mapping)
|
|
101
|
-
allow(CidrGroupMapping).to receive(:new).and_return(mapping)
|
|
102
|
-
|
|
103
|
-
graph = visualize_aws.build
|
|
104
|
-
|
|
105
|
-
expect(graph.output(renderer)).to contain_exactly(
|
|
106
|
-
[:node, 'Web'],
|
|
107
|
-
[:node, 'External'],
|
|
108
|
-
[:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}],
|
|
109
|
-
[:node, 'Db'],
|
|
110
|
-
[:node, 'App'],
|
|
111
|
-
[:edge, 'App', 'Db', {:color => :blue, :label => '7474/tcp'}],
|
|
112
|
-
[:node, 'Work'],
|
|
113
|
-
[:edge, 'Work', 'Db', {:color => :blue, :label => '22/tcp'}]
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
it 'should group mapped duplicate edges for cidr ingress' do
|
|
119
|
-
stub_security_groups(
|
|
120
|
-
[
|
|
121
|
-
group('ssh', cidr_ingress(22, '192.168.0.1/32'), cidr_ingress(22, '127.0.0.1/32'))
|
|
122
|
-
])
|
|
123
|
-
mapping = {'127.0.0.1/32' => 'Work', '192.168.0.1/32' => 'Work'}
|
|
124
|
-
mapping = CidrGroupMapping.new([], mapping)
|
|
125
|
-
allow(CidrGroupMapping).to receive(:new).and_return(mapping)
|
|
126
|
-
|
|
127
|
-
graph = visualize_aws.build
|
|
128
|
-
|
|
129
|
-
expect(graph.output(renderer)).to contain_exactly(
|
|
130
|
-
[:node, 'ssh'],
|
|
131
|
-
[:node, 'Work'],
|
|
132
|
-
[:edge, 'Work', 'ssh', {:color => :blue, :label => '22/tcp'}]
|
|
133
|
-
)
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
context "filter" do
|
|
138
|
-
it 'include cidr which do not match the pattern' do
|
|
139
|
-
stub_security_groups(
|
|
140
|
-
[
|
|
141
|
-
group('Web', cidr_ingress(22, '127.0.0.1/32')),
|
|
142
|
-
group('Db', cidr_ingress(22, '192.0.1.1/32'))
|
|
143
|
-
])
|
|
144
|
-
|
|
145
|
-
opts = {:exclude => ['127.*']}
|
|
146
|
-
graph = VisualizeAws.new(AwsConfig.new(opts)).build
|
|
147
|
-
|
|
148
|
-
expect(graph.output(renderer)).to contain_exactly(
|
|
149
|
-
[:node, 'Web'],
|
|
150
|
-
[:node, 'Db'],
|
|
151
|
-
[:node, '192.0.1.1/32'],
|
|
152
|
-
[:edge, '192.0.1.1/32', 'Db', {:color => :blue, :label => '22/tcp'}]
|
|
153
|
-
)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
it 'include groups which do not match the pattern' do
|
|
157
|
-
stub_security_groups(
|
|
158
|
-
[
|
|
159
|
-
group('Web', group_ingress(80, 'External')),
|
|
160
|
-
group('Db', group_ingress(7474, 'App'), cidr_ingress(22, '127.0.0.1/32'))
|
|
161
|
-
])
|
|
162
|
-
|
|
163
|
-
opts = {:exclude => ['D.*b', 'App']}
|
|
164
|
-
graph = VisualizeAws.new(AwsConfig.new(opts)).build
|
|
165
|
-
|
|
166
|
-
expect(graph.output(renderer)).to contain_exactly(
|
|
167
|
-
[:node, 'Web'],
|
|
168
|
-
[:node, 'External'],
|
|
169
|
-
[:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}]
|
|
170
|
-
)
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
it 'include derived groups which do not match the pattern' do
|
|
174
|
-
stub_security_groups(
|
|
175
|
-
[
|
|
176
|
-
group('Web', group_ingress(80, 'External')),
|
|
177
|
-
group('Db', group_ingress(7474, 'App'), cidr_ingress(22, '127.0.0.1/32'))
|
|
178
|
-
])
|
|
179
|
-
|
|
180
|
-
opts = {:exclude => ['App']}
|
|
181
|
-
graph = VisualizeAws.new(AwsConfig.new(opts)).build
|
|
182
|
-
|
|
183
|
-
expect(graph.output(renderer)).to contain_exactly(
|
|
184
|
-
[:node, 'Web'],
|
|
185
|
-
[:node, 'External'],
|
|
186
|
-
[:edge, 'External', 'Web', {:color => :blue, :label => '80/tcp'}],
|
|
187
|
-
[:node, 'Db'],
|
|
188
|
-
[:node, '127.0.0.1/32'],
|
|
189
|
-
[:edge, '127.0.0.1/32', 'Db', {:color => :blue, :label => '22/tcp'}]
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
end
|