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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ae64213f8b71718599133461e12d9675934f87c19ccc4374402b582ad439e01
4
- data.tar.gz: 62c18a94dc4007888f44f1ba3dfcf327a462ef8ec81e424b94e310fc0911cc85
3
+ metadata.gz: 57eea04dcfb8bce81f204b046fbb01525194362bf046a7754fb2c26704ad2e4f
4
+ data.tar.gz: b73a6510229a8fdb6f0697518b4790fe4cf1400b6ac1dcc44f50f4fb4899267f
5
5
  SHA512:
6
- metadata.gz: 8f5485c18d23a47d690b6e2efac55739e824721a14e388e1dd3f47b8fb7544f7bdc47d42c796f4e4b3b780c52385b7ddb558f054b53bd5c29e9dc9ada3287ad1
7
- data.tar.gz: 4e1b6817c3fc74f8c4b2325b3e9725d90c9a66aa62aa02c821f7fa3bd6c9596cb111ea859ec8748f3a2711ef9dfd0e89daef2a2e18563b575825a58e72b7b66c
6
+ metadata.gz: c85a2f7002c23a0d3676fd7116646c5846e9497b9a10a59fe49c98a1d4b848971627e4ab10a3b009984c5ea4d9e192a08d1f27bfe3d5faee1966cca94a425536
7
+ data.tar.gz: 2ff0af0aeeaa6fa4e35f760ce6a8f489666e9d2a21bf63cc42812608e08b19de80a43900b1a641f187d8c4170e92ba6c1816c345055ae8cb545caf8af716260f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,63 @@
2
2
  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
+ ## [Unreleased]
6
+
7
+ ## [1.0.0] - 2026-10-03
8
+ This release also covers the 0.3.0 work, which was never tagged or published.
9
+
10
+ ### Breaking changes
11
+ - Ruby 3.3 or newer is required (it was 3.0 or newer in 0.2.4)
12
+ - The default output is now `aws-security-viz.html`, a self-contained page, instead of `aws-security-viz.png` (`.json` for json and navigator output). The output format is inferred from the -f/--output extension (.html, .json, .mmd, .dot/.gv, or an image such as .png/.svg). Image output still needs the Graphviz `dot` binary
13
+ - The old html viewers and the navigator renderer are removed, along with `--serve`
14
+ - There is no default region (it used to be us-east-1); the region comes from the AWS SDK credential/config chain (AWS_REGION, profile, ...) or -r, and a missing region fails with an error
15
+ - --profile no longer defaults to AWS_PROFILE, so explicit access keys are kept
16
+ - Node ids in JSON output are now security group ids; names are labels, and groups are clustered by VPC (and by region when several are queried)
17
+ - Edges are blue for ingress and red for egress; the per-group colour palette is gone and `--color` is ignored
18
+ - All library code is under the `AwsSecurityViz` namespace and moved to `lib/aws_security_viz/`; the top-level `VisualizeAws`, `Renderer`, `Ec2Provider` and similar constants no longer exist. Use the `aws_security_viz` executable, or `AwsSecurityViz::CLI`
19
+ - Obfuscation hashes are shorter (10 hex characters)
20
+ - Runtime dependencies are now only `aws-sdk-ec2` (>= 1.400, no upper cap) and `rexml`. `graphviz`, `rgl`, `optimist`, `webrick` and `organic_hash` are gone
21
+
22
+ ### Deprecated
23
+ - --renderer: still works but prints a warning; use the -f extension instead. `--renderer navigator` now writes the html viewer
24
+ - --color: ignored, prints a warning
25
+
26
+ ### Added
27
+ - Self-contained HTML viewer (`-f out.html`, the default): one file with Cytoscape.js 3.34.3 vendored and the graph data inlined, a Content-Security-Policy, no CDN or server, works from `file://`
28
+ - Mermaid flowchart output (`-f out.mmd`), with a warning when the diagram exceeds Mermaid's default edge or text limits
29
+ - Multi-region support: `--region us-east-1,eu-west-1` or `--all-regions` (needs `ec2:DescribeRegions`); regions that fail with an authorisation error are skipped with a warning
30
+ - Risky ingress highlighting: 0.0.0.0/0 or ::/0 reaching a sensitive port (22, 3389, 3306, 5432, 1433, 6379, 9200, 27017, configurable with `risky_ports` in opts.yml) or allowing all traffic is drawn distinctly and flagged `risky` in JSON and HTML output. --fail-on-risk exits 2 when any is found
31
+ - --show-unused marks security groups with no attached network interface (dashed grey in DOT, `unused` class in Mermaid, `unused: true` in JSON and HTML output); it needs `ec2:DescribeNetworkInterfaces` and is ignored with --source-file
32
+ - Rule descriptions are kept: JSON edges carry a `descriptions` list and DOT edges a `tooltip` (hashed under --obfuscate)
33
+ - --input and --output aliases for -o/--source-file and -f/--filename; `init` alias for `setup`
34
+ - --layout picks the Graphviz layout engine (overrides `format` in opts.yml; unknown engines are rejected)
35
+ - --debug (or DEBUG=true) for verbose output and stack traces, --obfuscate (or OBFUSCATE=true) to hash group names, ports and ids
36
+ - IPv6 ranges and prefix lists are drawn as rule peers
37
+ - --vpc-id is honoured for --source-file input
38
+ - Tag-triggered release workflow using RubyGems trusted publishing, which also pushes a multi-arch (amd64 and arm64) image to ghcr.io/anaynayak/aws-security-viz tagged `<version>`, `<major>.<minor>` and `latest`. The image is built from this source and runs as a non-root user. Not yet verified locally (task-17: the Docker build and the release workflow have not been run)
39
+
40
+ ### Changed
41
+ - CLI moved into `AwsSecurityViz::CLI` on stdlib OptionParser
42
+ - Warnings, errors and debug output go to stderr through a Logger, keeping stdout clean
43
+ - Exit codes: 0 on success, 1 on error, 2 for --fail-on-risk, 130 on Ctrl-C
44
+ - Graph building uses a small adjacency-list graph and DOT is generated directly; Graphviz is only needed for image formats
45
+ - Rules that allow all traffic, ICMP, or a numeric protocol get readable labels, and all-traffic is labelled "all"
46
+ - Boolean environment variables (DEBUG, OBFUSCATE) are parsed as booleans
47
+ - The html asset is written next to the output file, not the current directory
48
+ - Gemfile.lock is committed, the gemspec has no upper version caps, and CI tests Ruby 3.3, 3.4 and 4.0
49
+
50
+ ### Removed
51
+ - The navigator renderer, the old view.html and navigator.html viewers, --serve and the webrick dependency
52
+ - The `rake docker:push` task and the per-push alpha gem workflow, replaced by the tag-triggered release workflow
53
+ - Support for Ruby older than 3.3
54
+
55
+ ### Fixed
56
+ - Security groups sharing a name in different VPCs no longer collapse into one node
57
+ - Several rules between the same two groups are merged into a single edge with merged port labels
58
+ - DescribeSecurityGroups is paginated and the VPC filter is applied server-side
59
+ - Unknown renderers and layout engines are rejected, and errors are reported cleanly (exit 1, Ctrl-C exits 130)
60
+ - The test suite loads on Ruby 4.0
61
+
5
62
  ## [0.2.4] - 2023-06-10
6
63
  - Matrix builds for Ruby v3.0 onwards only
7
64
  - Remove support for Ruby v2.x
@@ -95,7 +152,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
95
152
  - Begin life as the gem [aws_security_viz](https://rubygems.org/gems/aws_security_viz)
96
153
 
97
154
 
98
- [Unreleased]: https://github.com/anaynayak/aws-security-viz/compare/v0.1.3...HEAD
155
+ [Unreleased]: https://github.com/anaynayak/aws-security-viz/compare/v1.0.0...HEAD
156
+ [1.0.0]: https://github.com/anaynayak/aws-security-viz/compare/v0.2.4...v1.0.0
99
157
  [0.1.3]: https://github.com/anaynayak/aws-security-viz/compare/v0.1.2...v0.1.3
100
158
  [0.1.2]: https://github.com/anaynayak/aws-security-viz/compare/v0.1.1...v0.1.2
101
159
  [0.1.1]: https://github.com/anaynayak/aws-security-viz/compare/v0.1.0...v0.1.1
data/README.md CHANGED
@@ -2,105 +2,150 @@ aws-security-viz -- A tool to visualize aws security groups
2
2
  ============================================================
3
3
  [![Build Status](https://github.com/anaynayak/aws-security-viz/workflows/Ruby/badge.svg)](https://github.com/anaynayak/aws-security-viz/actions?query=workflow%3ARuby)
4
4
  [![License](https://img.shields.io/github/license/anaynayak/aws-security-viz.svg?maxAge=2592000)]()
5
- [![Docker Pulls](https://img.shields.io/docker/pulls/anay/aws-security-viz)](https://hub.docker.com/r/anay/aws-security-viz/)
6
- [![Dependency Status](https://img.shields.io/librariesio/github/anaynayak/aws-security-viz.png?maxAge=259200)](https://libraries.io/github/anaynayak/aws-security-viz)
5
+ [![Docker image](https://img.shields.io/badge/ghcr.io-aws--security--viz-blue)](https://github.com/anaynayak/aws-security-viz/pkgs/container/aws-security-viz)
7
6
  ![Gem Downloads (for latest version)](https://img.shields.io/gem/dtv/aws_security_viz)
8
7
 
9
-
10
8
  ## DESCRIPTION
11
9
  Need a quick way to visualize your current aws/amazon ec2 security group configuration? aws-security-viz does just that based on the EC2 security group ingress configuration.
12
10
 
11
+ ![](https://github.com/anaynayak/aws-security-viz/raw/main/images/sample.png)
12
+
13
13
  ## FEATURES
14
14
 
15
- * Output to any of the formats that Graphviz supports.
16
- * EC2 classic and VPC security groups
15
+ * Reads the live AWS API, or the JSON from `aws ec2 describe-security-groups`.
16
+ * Output formats: a self-contained HTML viewer, JSON, Mermaid, DOT, and any image format Graphviz supports (png, svg, pdf and others).
17
+ * One region, several regions, or all regions in a single graph; groups are clustered by region and VPC.
18
+ * Risky public ingress (`0.0.0.0/0` or `::/0` on a sensitive port) is drawn as a dashed crimson edge, and `--fail-on-risk` turns it into a failing exit code for CI.
19
+ * `--show-unused` marks security groups that no network interface uses.
17
20
 
18
21
  ## INSTALLATION
22
+
23
+ From RubyGems:
24
+
19
25
  ```
20
26
  $ gem install aws_security_viz
21
27
  $ aws_security_viz --help
22
28
  ```
23
29
 
30
+ Or run the published image, which has Ruby and Graphviz built in (see [Docker usage](#docker-usage)):
31
+
32
+ ```
33
+ $ docker pull ghcr.io/anaynayak/aws-security-viz:<version>
34
+ ```
35
+
24
36
  ## DEPENDENCIES
25
37
 
26
- * graphviz `brew install graphviz`
38
+ * Ruby 3.3 or newer.
39
+ * Graphviz (`brew install graphviz`), only for image formats (png, svg, pdf and so on). The HTML, JSON, Mermaid and DOT outputs do not need it.
40
+
41
+ ## USAGE
27
42
 
28
- ## USAGE (See Examples section below for more)
43
+ The output format follows the extension of `-f/--output`: `.html` (the default is `aws-security-viz.html`), `.json`, `.mmd`, `.dot` or `.gv`, or an image such as `.png` or `.svg`. The older `--renderer` flag is deprecated; it still works and prints a warning.
29
44
 
30
- To generate the graph directly using AWS keys
45
+ To generate a graph from an existing security_groups.json (created using aws-cli, see [Debugging](#debugging))
31
46
 
32
47
  ```
33
- $ aws_security_viz -a your_aws_key -s your_aws_secret_key -f viz.svg --color=true
48
+ $ aws_security_viz -o security_groups.json -f viz.svg
34
49
  ```
35
50
 
36
- To generate the graph using an existing security_groups.json (created using aws-cli)
51
+ To query AWS directly with a shared-config profile (`--profile` also works with SSO profiles after `aws sso login --profile <profile_name>`)
37
52
 
38
53
  ```
39
- $ aws_security_viz -o data/security_groups.json -f viz.svg --color
54
+ $ aws_security_viz --profile <profile_name> --region us-west-1 -f viz.html
40
55
  ```
41
56
 
42
- To generate a web view
57
+ The credentials and region otherwise come from the standard AWS SDK chain (`AWS_PROFILE`, `AWS_REGION`, environment variables, SSO, instance roles). There is no built-in default region, so a missing region fails with `MissingRegionError`.
58
+
59
+ With [aws-vault](https://github.com/99designs/aws-vault/) and short lived temporary credentials
43
60
 
44
61
  ```
45
- $ aws_security_viz -a your_aws_key -s your_aws_secret_key -f aws.json --renderer navigator
62
+ $ aws-vault exec <profile_name> -- aws_security_viz --region us-west-1 -f viz.html
46
63
  ```
47
64
 
48
- * Generates two files: aws.json and navigator.html.
49
- * The json file name needs to be passed in as a html fragment identifier.
50
- * The generated graph can be viewed in a webserver e.g. http://localhost:3000/navigator.html#aws.json by using `ruby -run -e httpd -- -p 3000`
65
+ With explicit keys (`-a/--access-key`, `-s/--secret-key`, `-e/--session-token`). Prefer a profile, aws-vault or SSO, because keys passed on the command line end up in your shell history.
66
+
67
+ ### Regions
68
+
69
+ With several regions (`--region us-east-1,eu-west-1` or `--all-regions`) nodes are grouped by region, then VPC. With `--all-regions`, `-r` (first name if a list) is only the region used to call `DescribeRegions`. A region that fails with `UnauthorizedOperation`, `AuthFailure` or `OptInRequired` is skipped with a warning; the run fails only if every region fails. The JSON and HTML outputs carry the region on each node. `--region` and `--all-regions` are ignored (with a warning) when `--source-file` is used.
70
+
71
+ ### Risky ingress
72
+
73
+ Ingress from `0.0.0.0/0` or `::/0` on a sensitive port (22, 3389, 3306, 5432, 1433, 6379, 9200, 27017) or on all traffic is flagged on stderr and drawn as a dashed crimson edge. Change the ports with `risky_ports` in opts.yml. `--fail-on-risk` exits with status 2 when any such edge exists; the output file is still written.
51
74
 
52
75
  ## DOCKER USAGE
53
76
 
54
- If you don't want to install the dependencies and ruby libs you can execute aws-security-viz inside a docker container. To do so, follow these steps:
77
+ Run aws-security-viz from the published image instead of installing Ruby and Graphviz. Releases push a multi-arch (amd64 and arm64) image to `ghcr.io/anaynayak/aws-security-viz`, tagged `<version>` (for example `1.0.0`), `<major>.<minor>` (for example `1.0`) and `latest` (stable releases only). Pin a version tag for reproducible runs. The image's entrypoint is `bundle exec aws_security_viz`, so everything after the image name is a normal CLI argument. It runs as a non-root user with `/work` as the working directory; mount a local directory there to get the output files.
55
78
 
56
- 1. Clone this repository, open it in a console.
57
- 2. Build the docker container: `docker build -t sec-viz .`
79
+ 1. With aws-vault (recommended):
58
80
 
59
- 3.a With aws-vault (Recommended):
81
+ ```
82
+ aws-vault exec <profile_name> -- docker run --rm --user $(id -u):$(id -g) \
83
+ -e AWS_REGION -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e AWS_SECURITY_TOKEN \
84
+ -v "$(pwd)/aws-viz:/work" ghcr.io/anaynayak/aws-security-viz:<version> -f /work/aws.svg
85
+ ```
60
86
 
61
- ```aws-vault exec <profile_name> -- docker run -i -e AWS_REGION -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e AWS_SECURITY_TOKEN --rm -t -p 3000:3000 -v (pwd)/aws-viz:/aws-security-viz --name sec-viz sec-viz /usr/local/bundle/bin/aws_security_viz --renderer navigator --serve 3000``` .
87
+ 2. With an SSO profile, mounting your AWS config (run `aws sso login --profile <profile_name>` first):
62
88
 
63
- You can open it with your local browser at `http://localhost:3000/navigator.html#aws-security-viz.png`.
89
+ ```
90
+ docker run --rm --user $(id -u):$(id -g) -e HOME=/home/viz -e AWS_PROFILE=<profile_name> -e AWS_REGION \
91
+ -v "$HOME/.aws:/home/viz/.aws" -v "$(pwd)/aws-viz:/work" \
92
+ ghcr.io/anaynayak/aws-security-viz:<version> -f /work/aws.svg
93
+ ```
64
94
 
65
- 3.b With AWS credentials passed as parameters:
95
+ 3. With AWS credentials passed as parameters:
66
96
 
67
- ```docker run -i --rm -t -p 3000:3000 -v (pwd)/aws-viz:/aws-security-viz --name sec-viz sec-viz /usr/local/bundle/bin/aws_security_viz -a REPLACE_AWS_ACCESS_KEY_ID -s REPLACE_SECRET --renderer navigator --serve 3000```.
97
+ ```
98
+ docker run --rm --user $(id -u):$(id -g) -v "$(pwd)/aws-viz:/work" ghcr.io/anaynayak/aws-security-viz:<version> \
99
+ -a REPLACE_AWS_ACCESS_KEY_ID -s REPLACE_SECRET -r REPLACE_REGION -f /work/aws.svg
100
+ ```
68
101
 
69
- You can open it with your local browser at `http://localhost:3000/navigator.html#aws-security-viz.png`.
102
+ 4. To build the image from a checkout instead: `docker build -t sec-viz .` and use `sec-viz` in place of the ghcr.io name.
70
103
 
71
- Parameters passed to the docker command:
72
- * `-v $(pwd)/aws-viz:aws-security-viz` local directory where output will be generated.
73
- * `-i` interactive shell
74
- * `--rm` remove the container after usage
75
- * `-t` attach this terminal to it
76
- * `-p 3000:3000` we expose port 3000 for the HTTP server
77
- * `-name sec-viz` the container will have the same name as the image we will start
104
+ Notes:
105
+ * `-v "$(pwd)/aws-viz:/work"` is the local directory where output is written. Create it first (`mkdir aws-viz`).
106
+ * `--user $(id -u):$(id -g)` matters on Linux: bind mounts keep the host's ownership, so the container's non-root
107
+ user cannot write to a directory owned by you and the run fails with "Permission denied". Running as your own
108
+ uid/gid fixes that and leaves the output files owned by you. Docker Desktop on macOS does not need it.
109
+ * `--rm` removes the container after the run.
78
110
 
79
- You can also use other parameters as specified in [usage](#USAGE)
111
+ You can also use any other option from the [help](#help) below.
80
112
 
81
113
  ### Help
82
114
 
83
115
  ```
84
116
  $ aws_security_viz --help
85
- Options:
86
- -a, --access-key=<s> AWS access key
87
- -s, --secret-key=<s> AWS secret key
88
- -e, --session-token=<s> AWS session token
89
- -r, --region=<s> AWS region to query (default: us-east-1)
90
- -v, --vpc-id=<s> AWS VPC id to show
91
- -o, --source-file=<s> JSON source file containing security groups
92
- -f, --filename=<s> Output file name (default: aws-security-viz.png)
93
- -c, --config=<s> Config file (opts.yml) (default: opts.yml)
94
- -l, --color Colored node edges
95
- -u, --source-filter=<s> Source filter
96
- -t, --target-filter=<s> Target filter
97
- --serve=<i> Serve a HTTP server at specified port
98
- -h, --help Show this message
99
- ```
100
-
101
- #### Configuration
102
-
103
- aws-security-viz only uses the `ec2:DescribeSecurityGroups` api so a minimal IAM policy which grants only `ec2:DescribeSecurityGroups` access should be enough.
117
+ Usage: aws_security_viz [options] [setup|init]
118
+ -a, --access-key=KEY AWS access key
119
+ -s, --secret-key=KEY AWS secret key
120
+ -e, --session-token=TOKEN AWS session token
121
+ -r, --region=REGION AWS region(s) to query, comma-separated (default: SDK chain, e.g. AWS_REGION or profile)
122
+ --all-regions Query every region returned by DescribeRegions
123
+ -p, --profile=NAME AWS shared-config profile to use (AWS_PROFILE is read by the SDK)
124
+ -v, --vpc-id=ID AWS VPC id to show
125
+ -o, --source-file, --input=FILE JSON source file containing security groups
126
+ -f, --filename, --output=FILE Output file; the format follows the extension: .html, .json, .mmd, .dot/.gv or an image such as .png/.svg (default: aws-security-viz.html)
127
+ -c, --config=FILE Config file (opts.yml)
128
+ -l, --[no-]color Deprecated, ignored: edges are blue for ingress and red for egress, risky public ingress is dashed crimson
129
+ -n, --renderer=NAME Deprecated, use the -f extension instead: renderer (graphviz|json|html|mermaid)
130
+ -y, --layout=ENGINE Graphviz layout engine (dot|neato|sfdp|fdp|twopi|circo); overrides opts.yml format
131
+ -d, --[no-]debug Verbose output and stack traces (or DEBUG=true)
132
+ -b, --[no-]obfuscate Hash group names and ports (or OBFUSCATE=true)
133
+ -u, --source-filter=FILTER Source filter
134
+ -t, --target-filter=FILTER Target filter
135
+ --show-unused Mark groups with no attached network interfaces (needs ec2:DescribeNetworkInterfaces; ignored with --source-file)
136
+ --fail-on-risk Exit 2 when 0.0.0.0/0 or ::/0 can reach a sensitive port (the output is still written)
137
+ -i, --version Print version and exit
138
+ -h, --help Show this message
139
+ ```
140
+
141
+ #### Configuration
142
+
143
+ aws-security-viz only uses the `ec2:DescribeSecurityGroups` api, so a minimal IAM policy which grants only that action should be enough. Two flags call more:
144
+
145
+ 1. `--all-regions` calls `ec2:DescribeRegions`.
146
+ 2. `--show-unused` calls `ec2:DescribeNetworkInterfaces` (paginated, per region). Without the permission the run still succeeds and logs a warning, but no groups are marked unused.
147
+
148
+ Add an action to the policy only if you use its flag.
104
149
 
105
150
  ```json
106
151
  {
@@ -108,20 +153,20 @@ aws-security-viz only uses the `ec2:DescribeSecurityGroups` api so a minimal IAM
108
153
  "Statement": [
109
154
  {
110
155
  "Effect": "Allow",
111
- "Action": "ec2:DescribeSecurityGroups",
156
+ "Action": [
157
+ "ec2:DescribeSecurityGroups",
158
+ "ec2:DescribeRegions",
159
+ "ec2:DescribeNetworkInterfaces"
160
+ ],
112
161
  "Resource": "*"
113
162
  }
114
163
  ]
115
164
  }
116
165
  ```
117
166
 
118
- Alternatively you can use [aws-vault](https://github.com/99designs/aws-vault/) and run it using short lived temporary credentials.
119
-
120
- `$ aws-vault exec <profile> -- aws_security_viz -f aws.json --renderer navigator --serve 9091`
121
-
122
167
  #### Advanced configuration
123
168
 
124
- You can generate a configuration file using the following command:
169
+ You can generate a configuration file using the following command (`init` is an alias for `setup`):
125
170
  ```
126
171
  $ aws_security_viz setup [-c opts.yml]
127
172
  ```
@@ -131,26 +176,25 @@ The opts.yml file lets you define the following options:
131
176
  * Grouping of CIDR ips
132
177
  * Define exclusion patterns
133
178
  * Change graphviz format (neato, dot, sfdp etc)
179
+ * Change the ports flagged as risky (`risky_ports`)
134
180
 
135
181
  ## DEBUGGING
136
182
 
137
- To generate the graph with debug statements, execute the following command
183
+ To generate the graph with debug statements, pass `--debug` (or set `DEBUG=true`). Debug output goes to stderr.
138
184
 
139
185
  ```
140
- $ DEBUG=true aws_security_viz -a your_aws_key -s your_aws_secret_key -f viz.svg
186
+ $ aws_security_viz --debug --profile <profile_name> --region us-west-1 -f viz.svg
141
187
  ```
142
188
 
143
- If it doesn't indicate the problem, please share the generated json file with me @ whynospam-awsviz@yahoo.co.in
144
-
145
- You can send me an obfuscated version using the following command:
189
+ If it doesn't indicate the problem, please open an issue on [GitHub](https://github.com/anaynayak/aws-security-viz/issues) and attach the security group JSON. Obfuscate it first with `--obfuscate` (or `OBFUSCATE=true`), which hashes group names and ports in the output:
146
190
 
147
191
  ```
148
- $ DEBUG=true OBFUSCATE=true aws_security_viz -a your_aws_key -s your_aws_secret_key -f viz.svg
192
+ $ aws_security_viz --debug --obfuscate --profile <profile_name> --region us-west-1 -f viz.json
149
193
  ```
150
194
 
151
- Execute the following command to generate the json. You will need [aws-cli](https://github.com/aws/aws-cli) to execute the command
195
+ Execute the following command to generate the JSON input for `--source-file`. You will need [aws-cli](https://github.com/aws/aws-cli) to execute the command
152
196
 
153
- `aws ec2 describe-security-groups`
197
+ `aws ec2 describe-security-groups > security_groups.json`
154
198
 
155
199
 
156
200
  ## EXAMPLES
@@ -159,13 +203,11 @@ Execute the following command to generate the json. You will need [aws-cli](http
159
203
 
160
204
  ![](https://github.com/anaynayak/aws-security-viz/raw/main/images/sample.png)
161
205
 
162
- #### Navigator view (useful with very large number of nodes)
163
- Via navigator renderer `aws_security_viz -a your_aws_key -s your_aws_secret_key -f aws.json --renderer navigator`
164
- ![](https://user-images.githubusercontent.com/416211/51426583-bb5e0180-1c12-11e9-903b-7b2a2d354ede.png)
206
+ Generated from `spec/integration/dummy.json` with `aws_security_viz -o spec/integration/dummy.json -f images/sample.png`.
207
+
208
+ #### HTML viewer (useful with very large number of nodes)
165
209
 
166
- #### JSON view
167
- Via json renderer `aws_security_viz -a your_aws_key -s your_aws_secret_key -f aws.json --renderer json`
168
- ![](https://cloud.githubusercontent.com/assets/416211/11912582/0e66cdbc-a669-11e5-82ab-1e26e3c6949b.png)
210
+ `aws_security_viz --profile <profile_name> --region us-west-1 -f aws.html` writes one self-contained file with the graph data inlined. Open it from disk in a browser; no web server is needed.
169
211
 
170
212
  ## Additional examples
171
213
 
@@ -178,21 +220,20 @@ Via json renderer `aws_security_viz -a your_aws_key -s your_aws_secret_key -f aw
178
220
  #### Generate visualization for `us-west-1` with target filter as `sec-group-1`. This will display all routes through which we can arrive at `sec-group-1`
179
221
 
180
222
  ```
181
- $ aws_security_viz --region us-west-1 --target-filter=sec-group-1
223
+ $ aws_security_viz --region us-west-1 -f aws.html --target-filter=sec-group-1
182
224
  ```
183
225
 
184
226
  #### Generate visualization for `us-west-1` restricted to vpc-id `vpc-12345`
185
227
  ```
186
- $ aws_security_viz --region us-west-1 --vpc-id=vpc-12345
228
+ $ aws_security_viz --region us-west-1 -f aws.html --vpc-id=vpc-12345
187
229
  ```
188
230
 
189
- #### Generate visualization for `us-west-1` restricted to vpc-id `vpc-12345`
231
+ #### Fail a CI job when a sensitive port is open to the internet
190
232
  ```
191
- $ aws_security_viz --region us-west-1 --vpc-id=vpc-12345
233
+ $ aws_security_viz --all-regions --fail-on-risk -f aws.json
192
234
  ```
193
235
 
194
- #### Serve webserver for the navigator view at port 3000
236
+ #### Generate a Mermaid diagram
195
237
  ```
196
- $ aws_security_viz -a your_aws_key -s your_aws_secret_key -f aws.json --renderer navigator --serve 3000
238
+ $ aws_security_viz --region us-west-1 -f aws.mmd
197
239
  ```
198
- The browser link to the view is printed on the CLI
data/exe/aws_security_viz CHANGED
@@ -1,43 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require 'aws_security_viz'
4
- require 'optimist'
5
- require 'webrick'
6
- require 'version'
4
+ require "aws_security_viz"
5
+ require "aws_security_viz/cli"
7
6
 
8
- opts = Optimist::options do
9
- version "aws_security_viz v#{AwsSecurityViz::VERSION}"
10
- opt :access_key, 'AWS access key', :default => ENV['AWS_ACCESS_KEY'] || ENV['AWS_ACCESS_KEY_ID'], :type => :string
11
- opt :secret_key, 'AWS secret key', :default => ENV['AWS_SECRET_KEY'] || ENV['AWS_SECRET_ACCESS_KEY'], :type => :string
12
- opt :session_token, 'AWS session token', :default => ENV['AWS_SESSION_TOKEN'] || nil, :type => :string
13
- opt :region, 'AWS region to query', :default => 'us-east-1', :type => :string
14
- opt :vpc_id, 'AWS VPC id to show', :type => :string
15
- opt :source_file, 'JSON source file containing security groups', :type => :string
16
- opt :filename, 'Output file name', :type => :string, :default => 'aws-security-viz.png'
17
- opt :config, 'Config file (opts.yml)', :type => :string, :default => 'opts.yml'
18
- opt :color, 'Colored node edges', :default => false
19
- opt :renderer, "Renderer (#{Renderer.all.join('|')})", :default => 'graphviz'
20
- opt :source_filter, 'Source filter', :default => nil, :type => :string
21
- opt :target_filter, 'Target filter', :default => nil, :type => :string
22
- opt :serve, 'Serve a HTTP server', :default => nil, :type => :integer
23
- end
24
-
25
- cmd = ARGV.shift
26
- if cmd=="setup"
27
- AwsConfig.write(opts[:config])
28
- puts "#{opts[:config]} created in current directory."
29
- exit
30
- end
31
-
32
- config = AwsConfig.load(opts[:config]).merge(obfuscate: ENV['OBFUSCATE'], debug: ENV['DEBUG'])
33
- begin
34
- VisualizeAws.new(config, opts).unleash(opts[:filename])
35
- if opts[:serve]
36
- puts "Navigate to http://localhost:#{opts[:serve]}/navigator.html##{opts[:filename]}"
37
- WEBrick::HTTPServer.new({Port: opts[:serve], DocumentRoot: '.'}).start
38
- end
39
- rescue Exception => e
40
- puts "[ERROR] #{e.message}"
41
- raise e if config.debug?
42
- exit 1
43
- end
7
+ exit AwsSecurityViz::CLI.new(ARGV).run
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require_relative "risk"
5
+
6
+ module AwsSecurityViz
7
+ class AwsConfig
8
+ def initialize(opts = {})
9
+ @opts = opts
10
+ @risky_ports = parse_risky_ports(opts[:risky_ports])
11
+ end
12
+
13
+ def exclusions
14
+ @exclusions ||= Exclusions.new(@opts[:exclude])
15
+ end
16
+
17
+ def egress?
18
+ @opts.key?(:egress) ? @opts[:egress] : true
19
+ end
20
+
21
+ def groups
22
+ @opts[:groups] || {}
23
+ end
24
+
25
+ # Ports whose exposure to 0.0.0.0/0 or ::/0 is flagged (opts.yml :risky_ports); all traffic always is.
26
+ # Validated once when the config is built.
27
+ attr_reader :risky_ports
28
+
29
+ LAYOUTS = %w[dot neato sfdp fdp twopi circo].freeze
30
+
31
+ # Graphviz layout engine: --layout, else `format` in opts.yml, else dot.
32
+ def layout
33
+ engine = (@opts[:layout] || @opts[:format] || "dot").to_s
34
+ return engine if LAYOUTS.include?(engine)
35
+ raise ArgumentError, "unknown layout engine '#{engine}' (choose from: #{LAYOUTS.join(", ")})"
36
+ end
37
+
38
+ def debug?
39
+ @opts[:debug] || false
40
+ end
41
+
42
+ def obfuscate?
43
+ @opts[:obfuscate] || false
44
+ end
45
+
46
+ # Parses an env-style flag: nil/empty is unset, true/1/yes/on and false/0/no/off are booleans.
47
+ def self.boolean(value, name = "value")
48
+ text = value.to_s.strip.downcase
49
+ return nil if text.empty?
50
+ return true if %w[true 1 yes on].include?(text)
51
+ return false if %w[false 0 no off].include?(text)
52
+ raise ArgumentError, "#{name} must be true, false, 1 or 0 (got '#{value}')"
53
+ end
54
+
55
+ def self.load(file)
56
+ config_opts = File.exist?(file) ? YAML.load_file(file) : {}
57
+ AwsConfig.new(config_opts)
58
+ end
59
+
60
+ def merge(opts)
61
+ AwsConfig.new(@opts.merge!(opts))
62
+ end
63
+
64
+ def self.write(file)
65
+ FileUtils.cp(File.expand_path("../opts.yml.sample", __FILE__), file)
66
+ end
67
+
68
+ private
69
+
70
+ # Decimal integers 1-65535 only (an Integer, or a string of digits); anything else is an error.
71
+ def parse_risky_ports(entries)
72
+ return Risk::DEFAULT_PORTS if entries.nil?
73
+ Array(entries).map do |entry|
74
+ port = Integer(entry.to_s, 10) if entry.to_s.match?(/\A\d+\z/)
75
+ raise ArgumentError, "risky_ports: invalid entry '#{entry}' (expected a port number 1-65535)" unless port&.between?(1, 65535)
76
+ port
77
+ end.freeze
78
+ end
79
+ end
80
+ end