Compare commits
365 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f93b36e162 | ||
|
|
52955f9c6e | ||
|
|
581cfcc917 | ||
|
|
4ee29225bc | ||
|
|
095b6bc463 | ||
|
|
bd1fcdd68a | ||
|
|
98f6003069 | ||
|
|
583c3c6ca7 | ||
|
|
a5378b58f7 | ||
|
|
98b7df643a | ||
|
|
533f7cbd5a | ||
|
|
f4a1130c03 | ||
|
|
38c9187a5e | ||
|
|
c7827cdc80 | ||
|
|
33246a4dab | ||
|
|
7bc09fb1c8 | ||
|
|
950adb109f | ||
|
|
a98d095be0 | ||
|
|
a029296811 | ||
|
|
3e6c682fa1 | ||
|
|
ab06627ee8 | ||
|
|
5fe85aa2a5 | ||
|
|
ceac9eee60 | ||
|
|
24d8c05ae0 | ||
|
|
e6e7303640 | ||
|
|
a6b2ec42b8 | ||
|
|
d51fd0e997 | ||
|
|
9c8280d980 | ||
|
|
b27155790e | ||
|
|
ca554ad3ff | ||
|
|
b72e4a657c | ||
|
|
7371104194 | ||
|
|
96fc4c3383 | ||
|
|
ee178c2305 | ||
|
|
4dc2070853 | ||
|
|
e9670d7291 | ||
|
|
3aa28329d2 | ||
|
|
aa425077b7 | ||
|
|
eb7f56f512 | ||
|
|
a591f07bdf | ||
|
|
90e4bf7d69 | ||
|
|
a590ef52da | ||
|
|
011c6c4571 | ||
|
|
6c54e305d9 | ||
|
|
c7550d8902 | ||
|
|
cdd10a49f6 | ||
|
|
374567a858 | ||
|
|
c118e34ada | ||
|
|
d1632d71c2 | ||
|
|
d007555a64 | ||
|
|
0e71756db3 | ||
|
|
69166a0352 | ||
|
|
9923845f20 | ||
|
|
05d4338d83 | ||
|
|
db504965a1 | ||
|
|
a8c6d29679 | ||
|
|
9e934b8e87 | ||
|
|
248c7c51d6 | ||
|
|
ea4a3b4e11 | ||
|
|
2f57f1f594 | ||
|
|
716d38814f | ||
|
|
1971d19a5d | ||
|
|
3eb95a349e | ||
|
|
921cbb14d6 | ||
|
|
a9b7fc5e48 | ||
|
|
b0d33ce20c | ||
|
|
06a338f5fb | ||
|
|
f4eaf2d909 | ||
|
|
41a4750b45 | ||
|
|
114921ef8e | ||
|
|
8570493ff7 | ||
|
|
7fc19510a4 | ||
|
|
bf1616d705 | ||
|
|
db29c758ef | ||
|
|
6c632ddcf3 | ||
|
|
12f9f8a044 | ||
|
|
73b3484ce8 | ||
|
|
0f7c301896 | ||
|
|
6f3eca7249 | ||
|
|
7da7726fe9 | ||
|
|
53cfcff68e | ||
|
|
e3015c6af4 | ||
|
|
5cf4b638d5 | ||
|
|
4aedba71fd | ||
|
|
416e406394 | ||
|
|
378e1599ed | ||
|
|
c33c3e3e21 | ||
|
|
c6786881fb | ||
|
|
32c28572a4 | ||
|
|
d77fb51795 | ||
|
|
03530d3e0d | ||
|
|
4628b823cf | ||
|
|
8423e328ce | ||
|
|
923176796a | ||
|
|
d7c4a1c789 | ||
|
|
e73a533f41 | ||
|
|
4fbddd5b42 | ||
|
|
45ccd7e793 | ||
|
|
bc80edd586 | ||
|
|
5d2af9b9f7 | ||
|
|
6601b4231d | ||
|
|
6e88b260d0 | ||
|
|
ebe3c5db54 | ||
|
|
1df93b62df | ||
|
|
225e12be91 | ||
|
|
73b7d76219 | ||
|
|
e226cb06e0 | ||
|
|
d35fd463a2 | ||
|
|
c197aa8594 | ||
|
|
6f0dc44975 | ||
|
|
d9cf113882 | ||
|
|
b776a6414d | ||
|
|
4cfd4b3e31 | ||
|
|
1b083eec67 | ||
|
|
b4c04c7cfc | ||
|
|
5d1f40e104 | ||
|
|
7f105e4d7a | ||
|
|
c183a47637 | ||
|
|
9fd29ca5e4 | ||
|
|
b5d153948d | ||
|
|
1f49d6d74c | ||
|
|
d23c2a9be5 | ||
|
|
a03a5d147b | ||
|
|
a54a0dd7c5 | ||
|
|
b60354ec4d | ||
|
|
d4a079a559 | ||
|
|
eb05d637a2 | ||
|
|
b19b80008d | ||
|
|
5c263db5d4 | ||
|
|
808d87a0dd | ||
|
|
3162f6cd92 | ||
|
|
2fbb47d839 | ||
|
|
f26f5d3c72 | ||
|
|
eb35f60d6b | ||
|
|
cd0253e477 | ||
|
|
6ceb2c1e56 | ||
|
|
c67c23dd42 | ||
|
|
8b0bae1c57 | ||
|
|
c873f95743 | ||
|
|
ddd94e6f64 | ||
|
|
722554ad3f | ||
|
|
484cf6f49d | ||
|
|
e4154ed4a2 | ||
|
|
86cb9f5838 | ||
|
|
1622d0aa35 | ||
|
|
b54ecb50bf | ||
|
|
f16857fdf1 | ||
|
|
ab109c935c | ||
|
|
8e7e456431 | ||
|
|
46114cd5f4 | ||
|
|
275e509c8d | ||
|
|
12f135669f | ||
|
|
f004df673d | ||
|
|
3ed24b5d7a | ||
|
|
77eade01a2 | ||
|
|
a2158983f7 | ||
|
|
c0d57c9498 | ||
|
|
35c8ea5e3f | ||
|
|
b36152484d | ||
|
|
768ca3f0ce | ||
|
|
bedd05c075 | ||
|
|
721f73fdbe | ||
|
|
34c2128d88 | ||
|
|
14de3acdaa | ||
|
|
899b2f8eb6 | ||
|
|
27bb05fedc | ||
|
|
e1909b8ad9 | ||
|
|
0ed7a247b6 | ||
|
|
ee46bf3809 | ||
|
|
469254094b | ||
|
|
acac3fc693 | ||
|
|
022b7ef756 | ||
|
|
69d4f55734 | ||
|
|
a0bff4b859 | ||
|
|
23df599a03 | ||
|
|
c8d74ca350 | ||
|
|
8d6ba43ad0 | ||
|
|
44ca2f7a66 | ||
|
|
ec0be1c7fe | ||
|
|
fd732db91b | ||
|
|
67f45b7767 | ||
|
|
396e6a1c36 | ||
|
|
326c46defd | ||
|
|
7a1762be51 | ||
|
|
b466b476a3 | ||
|
|
e4652d4339 | ||
|
|
f1e4cd3938 | ||
|
|
e192a98079 | ||
|
|
833dc83922 | ||
|
|
ab1751c595 | ||
|
|
fff06f971e | ||
|
|
a138d2964e | ||
|
|
e6d7965453 | ||
|
|
ab714f0fc7 | ||
|
|
465b0f6a16 | ||
|
|
bd87351ea7 | ||
|
|
d79ec44e4c | ||
|
|
a2f84a12ea | ||
|
|
6fd71356ee | ||
|
|
a0a305d9b1 | ||
|
|
6396d90fa6 | ||
|
|
e324750ec2 | ||
|
|
5d99f020fa | ||
|
|
b82e928f58 | ||
|
|
da871897e6 | ||
|
|
81778f73e4 | ||
|
|
2623728518 | ||
|
|
97f1d1b476 | ||
|
|
2f6a837bc0 | ||
|
|
5e22c2d9a5 | ||
|
|
99bd637de4 | ||
|
|
b9177e5580 | ||
|
|
fc7ec184d9 | ||
|
|
7a6ca342af | ||
|
|
30b6e5e5c6 | ||
|
|
f8476decf7 | ||
|
|
49e238577c | ||
|
|
026fff79c6 | ||
|
|
36c3870c2f | ||
|
|
54c309dbda | ||
|
|
f00dd35f93 | ||
|
|
e040efb3c8 | ||
|
|
805d50586b | ||
|
|
a289a807c5 | ||
|
|
e9117f95ee | ||
|
|
82bd4e940f | ||
|
|
ad3b0b33f2 | ||
|
|
b2b664a5b0 | ||
|
|
571f3ebe1d | ||
|
|
c7f09df4e7 | ||
|
|
8758ecae97 | ||
|
|
f13c843ba6 | ||
|
|
e95f7dd540 | ||
|
|
693329b87e | ||
|
|
f1ad521f64 | ||
|
|
82fbba6513 | ||
|
|
66fba8e4cd | ||
|
|
417131fa36 | ||
|
|
9c9d270053 | ||
|
|
f7fab165ba | ||
|
|
93bdf43c95 | ||
|
|
b3866b5b71 | ||
|
|
2308084dee | ||
|
|
6eb5496c27 | ||
|
|
c5514fdb63 | ||
|
|
c78c3058fd | ||
|
|
10d9ef9906 | ||
|
|
43426041ef | ||
|
|
125eb9ac53 | ||
|
|
681407e0a2 | ||
|
|
082f3a8fe8 | ||
|
|
397cc26b2a | ||
|
|
331ae92843 | ||
|
|
06843cd41a | ||
|
|
28b5ef9ee9 | ||
|
|
63dcc057d3 | ||
|
|
0bc16ee5ff | ||
|
|
abcc9c2c80 | ||
|
|
daf2ad38bd | ||
|
|
3dc418df39 | ||
|
|
00aaafbc12 | ||
|
|
bd49a55f3d | ||
|
|
013975b7a6 | ||
|
|
392026286a | ||
|
|
29ef974565 | ||
|
|
06c8216092 | ||
|
|
03f04d24a5 | ||
|
|
7b45ed63cc | ||
|
|
6e4dd1d69c | ||
|
|
185b4cba0c | ||
|
|
8198ea4a2c | ||
|
|
aaf3e8a5cf | ||
|
|
ecef56fa8f | ||
|
|
349ce3f2d0 | ||
|
|
e3d4741213 | ||
|
|
9d6d5f1d76 | ||
|
|
3152d67f58 | ||
|
|
cb41c8d15b | ||
|
|
06590842d6 | ||
|
|
d4c22a0ca5 | ||
|
|
c6f9936292 | ||
|
|
eaa8900758 | ||
|
|
e1e95d8879 | ||
|
|
ef3a0f4878 | ||
|
|
64cc36e7e2 | ||
|
|
1e001bb0fd | ||
|
|
6ba123a003 | ||
|
|
36d0f2c23f | ||
|
|
63412e3645 | ||
|
|
191cf276c3 | ||
|
|
45978bd0bb | ||
|
|
9666652d18 | ||
|
|
ad2716d7c9 | ||
|
|
0a7939bea3 | ||
|
|
b8c50a7b45 | ||
|
|
175e8d2b05 | ||
|
|
046069a656 | ||
|
|
f9522da48f | ||
|
|
c03f959005 | ||
|
|
522aeebe5e | ||
|
|
5312f487f9 | ||
|
|
d9b6624d65 | ||
|
|
1506da54fc | ||
|
|
245512d320 | ||
|
|
487190b379 | ||
|
|
74aaeaa95c | ||
|
|
28e8f0de2b | ||
|
|
f60b5017e2 | ||
|
|
fe80821596 | ||
|
|
628a3c4e7b | ||
|
|
3d59c34ec9 | ||
|
|
35043c2dd6 | ||
|
|
ab815123c9 | ||
|
|
69ab84efe1 | ||
|
|
77823afa54 | ||
|
|
63cd6c1290 | ||
|
|
cab32d2f94 | ||
|
|
1f4316e9dd | ||
|
|
ade762a85e | ||
|
|
bda5d62c72 | ||
|
|
2176fff8c3 | ||
|
|
87893bd54b | ||
|
|
b539a888b1 | ||
|
|
d6b2b0ca13 | ||
|
|
58ee45b702 | ||
|
|
c62d97f23a | ||
|
|
d618c5ea12 | ||
|
|
d8e27f0d33 | ||
|
|
38496ff646 | ||
|
|
da1084907e | ||
|
|
3385b630e7 | ||
|
|
fc59183045 | ||
|
|
33242079f7 | ||
|
|
086148819c | ||
|
|
5df9fd881c | ||
|
|
bd17d36e7f | ||
|
|
be55fa22fd | ||
|
|
b48b3a5e2e | ||
|
|
fc03dd37f1 | ||
|
|
d8bb384689 | ||
|
|
0b32a10bb8 | ||
|
|
f0c027f54e | ||
|
|
b0f2f34d3b | ||
|
|
3e6b76df76 | ||
|
|
6197cf792d | ||
|
|
3c4e5a14f7 | ||
|
|
effc743b6e | ||
|
|
364a945d28 | ||
|
|
07b9354d18 | ||
|
|
8b1e537ca5 | ||
|
|
6a20e850bc | ||
|
|
636892bc9a | ||
|
|
b40f32ab57 | ||
|
|
14bab496b5 | ||
|
|
3cc367e0a3 | ||
|
|
36fc575e40 | ||
|
|
24efb34d91 | ||
|
|
c08e244c95 | ||
|
|
c2f8980f1f | ||
|
|
0ef85b3dee | ||
|
|
93a2431211 | ||
|
|
1fe74937c1 | ||
|
|
6ee016e577 | ||
|
|
f7248dfb1c | ||
|
|
856afb3966 |
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -27,7 +27,7 @@ body:
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Result with Screenshots or Logs
|
||||
description: If applicable, add screenshots to help explain your problem. Also, you can add logs (anonymize them first!). Here a command that may help to share a log `prowler <your arguments> --log-level DEBUG --log-file $(date +%F)_debug.log` then attach here the log file.
|
||||
description: If applicable, add screenshots to help explain your problem. Also, you can add logs (anonymize them first!). Here a command that may help to share a log `prowler <your arguments> --log-level ERROR --log-file $(date +%F)_error.log` then attach here the log file.
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
||||
26
.github/dependabot.yml
vendored
@@ -5,10 +5,11 @@
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "pip" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: master
|
||||
labels:
|
||||
- "dependencies"
|
||||
@@ -17,4 +18,25 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: master
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: v3
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "pip"
|
||||
- "v3"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: v3
|
||||
labels:
|
||||
- "github_actions"
|
||||
- "v3"
|
||||
|
||||
4
.github/labeler.yml
vendored
@@ -25,3 +25,7 @@ provider/kubernetes:
|
||||
github_actions:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ".github/workflows/*"
|
||||
|
||||
cli:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "cli/**"
|
||||
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
|
||||
- name: Build and push container image (latest)
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
tags: |
|
||||
@@ -130,7 +130,7 @@ jobs:
|
||||
|
||||
- name: Build and push container image (release)
|
||||
if: github.event_name == 'release'
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
# Use local context to get changes
|
||||
# https://github.com/docker/build-push-action#path-context
|
||||
|
||||
4
.github/workflows/find-secrets.yml
vendored
@@ -11,9 +11,9 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: TruffleHog OSS
|
||||
uses: trufflesecurity/trufflehog@v3.79.0
|
||||
uses: trufflesecurity/trufflehog@v3.76.3
|
||||
with:
|
||||
path: ./
|
||||
base: ${{ github.event.repository.default_branch }}
|
||||
head: HEAD
|
||||
extra_args: --only-verified
|
||||
extra_args: --only-verified
|
||||
2
.github/workflows/pull-request.yml
vendored
@@ -73,7 +73,7 @@ jobs:
|
||||
- name: Safety
|
||||
if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true'
|
||||
run: |
|
||||
poetry run safety check --ignore 67599 --ignore 70612
|
||||
poetry run safety check --ignore 67599
|
||||
- name: Vulture
|
||||
if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true'
|
||||
run: |
|
||||
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
token: ${{ secrets.PROWLER_ACCESS_TOKEN }}
|
||||
commit-message: "feat(regions_update): Update regions for AWS services."
|
||||
branch: "aws-services-regions-updated-${{ github.sha }}"
|
||||
labels: "status/waiting-for-revision, severity/low, provider/aws"
|
||||
labels: "status/waiting-for-revision, severity/low, provider/aws, backport-v3"
|
||||
title: "chore(regions_update): Changes in regions for AWS services."
|
||||
body: |
|
||||
### Description
|
||||
|
||||
6
.gitignore
vendored
@@ -9,8 +9,9 @@
|
||||
__pycache__
|
||||
venv/
|
||||
build/
|
||||
dist/
|
||||
/dist/
|
||||
*.egg-info/
|
||||
*/__pycache__/*.pyc
|
||||
|
||||
# Session
|
||||
Session.vim
|
||||
@@ -51,3 +52,6 @@ junit-reports/
|
||||
.coverage*
|
||||
.coverage
|
||||
coverage*
|
||||
|
||||
# Node
|
||||
node_modules
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
repos:
|
||||
## GENERAL
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: check-merge-conflict
|
||||
- id: check-yaml
|
||||
@@ -15,7 +15,7 @@ repos:
|
||||
|
||||
## TOML
|
||||
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
|
||||
rev: v2.12.0
|
||||
rev: v2.13.0
|
||||
hooks:
|
||||
- id: pretty-format-toml
|
||||
args: [--autofix]
|
||||
@@ -23,12 +23,13 @@ repos:
|
||||
|
||||
## BASH
|
||||
- repo: https://github.com/koalaman/shellcheck-precommit
|
||||
rev: v0.9.0
|
||||
rev: v0.10.0
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
exclude: contrib
|
||||
## PYTHON
|
||||
- repo: https://github.com/myint/autoflake
|
||||
rev: v2.2.1
|
||||
rev: v2.3.1
|
||||
hooks:
|
||||
- id: autoflake
|
||||
args:
|
||||
@@ -45,7 +46,7 @@ repos:
|
||||
args: ["--profile", "black"]
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 24.1.1
|
||||
rev: 24.4.2
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
@@ -57,14 +58,14 @@ repos:
|
||||
args: ["--ignore=E266,W503,E203,E501,W605"]
|
||||
|
||||
- repo: https://github.com/python-poetry/poetry
|
||||
rev: 1.7.0
|
||||
rev: 1.8.0
|
||||
hooks:
|
||||
- id: poetry-check
|
||||
- id: poetry-lock
|
||||
args: ["--no-update"]
|
||||
|
||||
- repo: https://github.com/hadolint/hadolint
|
||||
rev: v2.12.1-beta
|
||||
rev: v2.13.0-beta
|
||||
hooks:
|
||||
- id: hadolint
|
||||
args: ["--ignore=DL3013"]
|
||||
@@ -96,7 +97,7 @@ repos:
|
||||
- id: safety
|
||||
name: safety
|
||||
description: "Safety is a tool that checks your installed dependencies for known security vulnerabilities"
|
||||
entry: bash -c 'safety check --ignore 67599 --ignore 70612'
|
||||
entry: bash -c 'safety check --ignore 67599'
|
||||
language: system
|
||||
|
||||
- id: vulture
|
||||
|
||||
@@ -15,7 +15,8 @@ USER prowler
|
||||
|
||||
# Copy necessary files
|
||||
WORKDIR /home/prowler
|
||||
COPY prowler/ /home/prowler/prowler/
|
||||
COPY prowler/ /home/prowler/prowler/
|
||||
COPY dashboard/ /home/prowler/dashboard/
|
||||
COPY pyproject.toml /home/prowler
|
||||
COPY README.md /home/prowler
|
||||
|
||||
@@ -26,6 +27,10 @@ ENV PATH="$HOME/.local/bin:$PATH"
|
||||
RUN pip install --no-cache-dir --upgrade pip && \
|
||||
pip install --no-cache-dir .
|
||||
|
||||
# Remove deprecated dash dependencies
|
||||
RUN pip uninstall dash-html-components -y && \
|
||||
pip uninstall dash-core-components -y
|
||||
|
||||
# Remove Prowler directory and build files
|
||||
USER 0
|
||||
RUN rm -rf /home/prowler/prowler /home/prowler/pyproject.toml /home/prowler/README.md /home/prowler/build /home/prowler/prowler.egg-info
|
||||
|
||||
2
Makefile
@@ -27,7 +27,7 @@ lint: ## Lint Code
|
||||
@echo "Running black... "
|
||||
black --check .
|
||||
@echo "Running pylint..."
|
||||
pylint --disable=W,C,R,E -j 0 providers lib util config
|
||||
pylint --disable=W,C,R,E -j 0 prowler util
|
||||
|
||||
##@ PyPI
|
||||
pypi-clean: ## Delete the distribution files
|
||||
|
||||
225
README.md
@@ -1,6 +1,6 @@
|
||||
<p align="center">
|
||||
<img align="center" src="https://github.com/prowler-cloud/prowler/blob/master/docs/img/prowler-logo-black.png?raw=True#gh-light-mode-only" width="350" height="115">
|
||||
<img align="center" src="https://github.com/prowler-cloud/prowler/blob/master/docs/img/prowler-logo-white.png?raw=True#gh-dark-mode-only" width="350" height="115">
|
||||
<img align="center" src="https://github.com/prowler-cloud/prowler/blob/master/docs/img/prowler-logo-black.png#gh-light-mode-only" width="50%" height="50%">
|
||||
<img align="center" src="https://github.com/prowler-cloud/prowler/blob/master/docs/img/prowler-logo-white.png#gh-dark-mode-only" width="50%" height="50%">
|
||||
</p>
|
||||
<p align="center">
|
||||
<b><i>Prowler SaaS </b> and <b>Prowler Open Source</b> are as dynamic and adaptable as the environment they’re meant to protect. Trusted by the leaders in security.
|
||||
@@ -10,11 +10,10 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://join.slack.com/t/prowler-workspace/shared_invite/zt-1hix76xsl-2uq222JIXrC7Q8It~9ZNog"><img width="30" height="30" alt="Prowler community on Slack" src="https://github.com/prowler-cloud/prowler/assets/3985464/3617e470-670c-47c9-9794-ce895ebdb627"></a>
|
||||
<a href="https://join.slack.com/t/prowler-workspace/shared_invite/zt-1hix76xsl-2uq222JIXrC7Q8It~9ZNog"><img width="30" height="30" alt="Prowler community on Slack" src="https://github.com/prowler-cloud/prowler/assets/38561120/3c8b4ec5-6849-41a5-b5e1-52bbb94af73a"></a>
|
||||
<br>
|
||||
<a href="https://join.slack.com/t/prowler-workspace/shared_invite/zt-1hix76xsl-2uq222JIXrC7Q8It~9ZNog">Join our Prowler community!</a>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p align="center">
|
||||
<a href="https://join.slack.com/t/prowler-workspace/shared_invite/zt-1hix76xsl-2uq222JIXrC7Q8It~9ZNog"><img alt="Slack Shield" src="https://img.shields.io/badge/slack-prowler-brightgreen.svg?logo=slack"></a>
|
||||
@@ -41,25 +40,32 @@
|
||||
|
||||
# Description
|
||||
|
||||
`Prowler` is an Open Source security tool to perform AWS, GCP and Azure security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness.
|
||||
**Prowler** is an Open Source security tool to perform AWS, Azure, Google Cloud and Kubernetes security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness, and also remediations! We have Prowler CLI (Command Line Interface) that we call Prowler Open Source and a service on top of it that we call <a href="https://prowler.com">Prowler SaaS</a>.
|
||||
|
||||
## Prowler CLI
|
||||
|
||||
```console
|
||||
prowler <provider>
|
||||
```
|
||||

|
||||
|
||||
## Prowler Dashboard
|
||||
|
||||
```console
|
||||
prowler dashboard
|
||||
```
|
||||

|
||||
|
||||
It contains hundreds of controls covering CIS, NIST 800, NIST CSF, CISA, RBI, FedRAMP, PCI-DSS, GDPR, HIPAA, FFIEC, SOC2, GXP, AWS Well-Architected Framework Security Pillar, AWS Foundational Technical Review (FTR), ENS (Spanish National Security Scheme) and your custom security frameworks.
|
||||
|
||||
| Provider | Checks | Services | [Compliance Frameworks](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/compliance/) | [Categories](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/misc/#categories) |
|
||||
|---|---|---|---|---|
|
||||
| AWS | 304 | 61 -> `prowler aws --list-services` | 28 -> `prowler aws --list-compliance` | 6 -> `prowler aws --list-categories` |
|
||||
| GCP | 75 | 11 -> `prowler gcp --list-services` | 1 -> `prowler gcp --list-compliance` | 2 -> `prowler gcp --list-categories`|
|
||||
| AWS | 359 | 66 -> `prowler aws --list-services` | 28 -> `prowler aws --list-compliance` | 7 -> `prowler aws --list-categories` |
|
||||
| GCP | 77 | 13 -> `prowler gcp --list-services` | 1 -> `prowler gcp --list-compliance` | 2 -> `prowler gcp --list-categories`|
|
||||
| Azure | 127 | 16 -> `prowler azure --list-services` | 2 -> `prowler azure --list-compliance` | 2 -> `prowler azure --list-categories` |
|
||||
| Kubernetes | Work In Progress | - | CIS soon | - |
|
||||
| Kubernetes | 83 | 7 -> `prowler kubernetes --list-services` | 1 -> `prowler kubernetes --list-compliance` | 7 -> `prowler kubernetes --list-categories` |
|
||||
|
||||
# 📖 Documentation
|
||||
|
||||
The full documentation can now be found at [https://docs.prowler.com](https://docs.prowler.com/projects/prowler-open-source/en/latest/)
|
||||
|
||||
## Looking for Prowler v2 documentation?
|
||||
For Prowler v2 Documentation, please go to https://github.com/prowler-cloud/prowler/tree/2.12.1.
|
||||
|
||||
# ⚙️ Install
|
||||
# 💻 Installation
|
||||
|
||||
## Pip package
|
||||
Prowler is available as a project in [PyPI](https://pypi.org/project/prowler-cloud/), thus can be installed using pip with Python >= 3.9, < 3.13:
|
||||
@@ -74,9 +80,11 @@ More details at [https://docs.prowler.com](https://docs.prowler.com/projects/pro
|
||||
|
||||
The available versions of Prowler are the following:
|
||||
|
||||
- `latest`: in sync with master branch (bear in mind that it is not a stable version)
|
||||
- `latest`: in sync with `master` branch (bear in mind that it is not a stable version)
|
||||
- `v3-latest`: in sync with `v3` branch (bear in mind that it is not a stable version)
|
||||
- `<x.y.z>` (release): you can find the releases [here](https://github.com/prowler-cloud/prowler/releases), those are stable releases.
|
||||
- `stable`: this tag always point to the latest release.
|
||||
- `v3-stable`: this tag always point to the latest release for v3.
|
||||
|
||||
The container images are available here:
|
||||
|
||||
@@ -94,184 +102,33 @@ poetry shell
|
||||
poetry install
|
||||
python prowler.py -v
|
||||
```
|
||||
|
||||
???+ note
|
||||
If you want to clone Prowler from Windows, use `git config core.longpaths true` to allow long file paths.
|
||||
# 📐✏️ High level architecture
|
||||
|
||||
You can run Prowler from your workstation, an EC2 instance, Fargate or any other container, Codebuild, CloudShell and Cloud9.
|
||||
You can run Prowler from your workstation, a Kubernetes Job, a Google Compute Engine, an Azure VM, an EC2 instance, Fargate or any other container, CloudShell and many more.
|
||||
|
||||

|
||||

|
||||
|
||||
# 📝 Requirements
|
||||
# Deprecations from v3
|
||||
|
||||
Prowler has been written in Python using the [AWS SDK (Boto3)](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html#), [Azure SDK](https://azure.github.io/azure-sdk-for-python/) and [GCP API Python Client](https://github.com/googleapis/google-api-python-client/).
|
||||
## AWS
|
||||
## General
|
||||
- `Allowlist` now is called `Mutelist`.
|
||||
- The `--quiet` option has been deprecated, now use the `--status` flag to select the finding's status you want to get from PASS, FAIL or MANUAL.
|
||||
- All `INFO` finding's status has changed to `MANUAL`.
|
||||
- The CSV output format is common for all the providers.
|
||||
|
||||
Since Prowler uses AWS Credentials under the hood, you can follow any authentication method as described [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-precedence).
|
||||
Make sure you have properly configured your AWS-CLI with a valid Access Key and Region or declare AWS variables properly (or instance profile/role):
|
||||
|
||||
```console
|
||||
aws configure
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```console
|
||||
export AWS_ACCESS_KEY_ID="ASXXXXXXX"
|
||||
export AWS_SECRET_ACCESS_KEY="XXXXXXXXX"
|
||||
export AWS_SESSION_TOKEN="XXXXXXXXX"
|
||||
```
|
||||
|
||||
Those credentials must be associated to a user or role with proper permissions to do all checks. To make sure, add the following AWS managed policies to the user or role being used:
|
||||
|
||||
- `arn:aws:iam::aws:policy/SecurityAudit`
|
||||
- `arn:aws:iam::aws:policy/job-function/ViewOnlyAccess`
|
||||
|
||||
> Moreover, some read-only additional permissions are needed for several checks, make sure you attach also the custom policy [prowler-additions-policy.json](https://github.com/prowler-cloud/prowler/blob/master/permissions/prowler-additions-policy.json) to the role you are using.
|
||||
|
||||
> If you want Prowler to send findings to [AWS Security Hub](https://aws.amazon.com/security-hub), make sure you also attach the custom policy [prowler-security-hub.json](https://github.com/prowler-cloud/prowler/blob/master/permissions/prowler-security-hub.json).
|
||||
|
||||
## Azure
|
||||
|
||||
Prowler for Azure supports the following authentication types:
|
||||
|
||||
- Service principal authentication by environment variables (Enterprise Application)
|
||||
- Current az cli credentials stored
|
||||
- Interactive browser authentication
|
||||
- Managed identity authentication
|
||||
|
||||
### Service Principal authentication
|
||||
|
||||
To allow Prowler assume the service principal identity to start the scan, it is needed to configure the following environment variables:
|
||||
|
||||
```console
|
||||
export AZURE_CLIENT_ID="XXXXXXXXX"
|
||||
export AZURE_TENANT_ID="XXXXXXXXX"
|
||||
export AZURE_CLIENT_SECRET="XXXXXXX"
|
||||
```
|
||||
|
||||
If you try to execute Prowler with the `--sp-env-auth` flag and those variables are empty or not exported, the execution is going to fail.
|
||||
### AZ CLI / Browser / Managed Identity authentication
|
||||
|
||||
The other three cases do not need additional configuration, `--az-cli-auth` and `--managed-identity-auth` are automated options, `--browser-auth` needs the user to authenticate using the default browser to start the scan. Also `--browser-auth` needs the tenant id to be specified with `--tenant-id`.
|
||||
|
||||
### Permissions
|
||||
|
||||
To use each one, you need to pass the proper flag to the execution. Prowler for Azure handles two types of permission scopes, which are:
|
||||
|
||||
- **Azure Active Directory permissions**: Used to retrieve metadata from the identity assumed by Prowler and future AAD checks (not mandatory to have access to execute the tool)
|
||||
- **Subscription scope permissions**: Required to launch the checks against your resources, mandatory to launch the tool.
|
||||
|
||||
|
||||
#### Azure Active Directory scope
|
||||
|
||||
Azure Active Directory (AAD) permissions required by the tool are the following:
|
||||
|
||||
- `Directory.Read.All`
|
||||
- `Policy.Read.All`
|
||||
|
||||
|
||||
#### Subscriptions scope
|
||||
|
||||
Regarding the subscription scope, Prowler by default scans all the subscriptions that is able to list, so it is required to add the following RBAC builtin roles per subscription to the entity that is going to be assumed by the tool:
|
||||
|
||||
- `Security Reader`
|
||||
- `Reader`
|
||||
|
||||
|
||||
## Google Cloud Platform
|
||||
|
||||
Prowler will follow the same credentials search as [Google authentication libraries](https://cloud.google.com/docs/authentication/application-default-credentials#search_order):
|
||||
|
||||
1. [GOOGLE_APPLICATION_CREDENTIALS environment variable](https://cloud.google.com/docs/authentication/application-default-credentials#GAC)
|
||||
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
||||
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
||||
|
||||
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the `Viewer` role to the member associated with the credentials.
|
||||
|
||||
> By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
|
||||
|
||||
# 💻 Basic Usage
|
||||
|
||||
To run prowler, you will need to specify the provider (e.g aws or azure):
|
||||
|
||||
```console
|
||||
prowler <provider>
|
||||
```
|
||||
|
||||

|
||||
|
||||
> Running the `prowler` command without options will use your environment variable credentials.
|
||||
|
||||
By default, prowler will generate a CSV, a JSON and a HTML report, however you can generate JSON-ASFF (only for AWS Security Hub) report with `-M` or `--output-modes`:
|
||||
|
||||
```console
|
||||
prowler <provider> -M csv json json-asff html
|
||||
```
|
||||
|
||||
The html report will be located in the `output` directory as the other files and it will look like:
|
||||
|
||||

|
||||
|
||||
You can use `-l`/`--list-checks` or `--list-services` to list all available checks or services within the provider.
|
||||
|
||||
```console
|
||||
prowler <provider> --list-checks
|
||||
prowler <provider> --list-services
|
||||
```
|
||||
|
||||
For executing specific checks or services you can use options `-c`/`--checks` or `-s`/`--services`:
|
||||
|
||||
```console
|
||||
prowler aws --checks s3_bucket_public_access
|
||||
prowler aws --services s3 ec2
|
||||
```
|
||||
|
||||
Also, checks and services can be excluded with options `-e`/`--excluded-checks` or `--excluded-services`:
|
||||
|
||||
```console
|
||||
prowler aws --excluded-checks s3_bucket_public_access
|
||||
prowler aws --excluded-services s3 ec2
|
||||
```
|
||||
|
||||
You can always use `-h`/`--help` to access to the usage information and all the possible options:
|
||||
|
||||
```console
|
||||
prowler -h
|
||||
```
|
||||
|
||||
## Checks Configurations
|
||||
Several Prowler's checks have user configurable variables that can be modified in a common **configuration file**.
|
||||
This file can be found in the following path:
|
||||
```
|
||||
prowler/config/config.yaml
|
||||
```
|
||||
We have deprecated some of our outputs formats:
|
||||
- The native JSON is replaced for the JSON [OCSF](https://schema.ocsf.io/) v1.1.0, common for all the providers.
|
||||
|
||||
## AWS
|
||||
- Deprecate the AWS flag --sts-endpoint-region since we use AWS STS regional tokens.
|
||||
- To send only FAILS to AWS Security Hub, now use either `--send-sh-only-fails` or `--security-hub --status FAIL`.
|
||||
|
||||
Use a custom AWS profile with `-p`/`--profile` and/or AWS regions which you want to audit with `-f`/`--filter-region`:
|
||||
|
||||
```console
|
||||
prowler aws --profile custom-profile -f us-east-1 eu-south-2
|
||||
```
|
||||
> By default, `prowler` will scan all AWS regions.
|
||||
# 📖 Documentation
|
||||
|
||||
## Azure
|
||||
|
||||
With Azure you need to specify which auth method is going to be used:
|
||||
|
||||
```console
|
||||
prowler azure [--sp-env-auth, --az-cli-auth, --browser-auth, --managed-identity-auth]
|
||||
```
|
||||
> By default, `prowler` will scan all Azure subscriptions.
|
||||
|
||||
## Google Cloud Platform
|
||||
|
||||
Optionally, you can provide the location of an application credential JSON file with the following argument:
|
||||
|
||||
```console
|
||||
prowler gcp --credentials-file path
|
||||
```
|
||||
> By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
|
||||
Install, Usage, Tutorials and Developer Guide is at https://docs.prowler.com/
|
||||
|
||||
# 📃 License
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ As an **AWS Partner** and we have passed the [AWS Foundation Technical Review (F
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you would like to report a vulnerability or have a security concern regarding Prowler Open Source or ProwlerPro service, please submit the information by contacting to help@prowler.pro.
|
||||
If you would like to report a vulnerability or have a security concern regarding Prowler Open Source or ProwlerPro service, please submit the information by contacting to https://support.prowler.com.
|
||||
|
||||
The information you share with ProwlerPro as part of this process is kept confidential within ProwlerPro. We will only share this information with a third party if the vulnerability you report is found to affect a third-party product, in which case we will share this information with the third-party product's author or manufacturer. Otherwise, we will only share this information as permitted by you.
|
||||
|
||||
|
||||
6
cli/cli.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# CLI
|
||||
To show the banner, use:
|
||||
`python cli/cli.py banner`
|
||||
## Listing
|
||||
List services by provider.
|
||||
`python cli/cli.py <provider> list-services`
|
||||
63
cli/cli.py
Normal file
@@ -0,0 +1,63 @@
|
||||
import typer
|
||||
|
||||
from prowler.lib.banner import print_banner
|
||||
from prowler.lib.check.check import (
|
||||
list_fixers,
|
||||
list_services,
|
||||
print_fixers,
|
||||
print_services,
|
||||
)
|
||||
|
||||
app = typer.Typer()
|
||||
aws = typer.Typer(name="aws")
|
||||
azure = typer.Typer(name="azure")
|
||||
gcp = typer.Typer(name="gcp")
|
||||
kubernetes = typer.Typer(name="kubernetes")
|
||||
|
||||
app.add_typer(aws, name="aws")
|
||||
app.add_typer(azure, name="azure")
|
||||
app.add_typer(gcp, name="gcp")
|
||||
app.add_typer(kubernetes, name="kubernetes")
|
||||
|
||||
|
||||
def list_resources(provider: str, resource_type: str):
|
||||
if resource_type == "services":
|
||||
print_services(list_services(provider))
|
||||
elif resource_type == "fixers":
|
||||
print_fixers(list_fixers(provider))
|
||||
|
||||
|
||||
def create_list_commands(provider_typer: typer.Typer):
|
||||
provider_name = provider_typer.info.name
|
||||
|
||||
@provider_typer.command(
|
||||
"list-services",
|
||||
help=f"List the {provider_name} services that are supported by Prowler.",
|
||||
)
|
||||
def list_services_command():
|
||||
list_resources(provider_name, "services")
|
||||
|
||||
@provider_typer.command(
|
||||
"list-fixers",
|
||||
help=f"List the {provider_name} fixers that are supported by Prowler.",
|
||||
)
|
||||
def list_fixers_command():
|
||||
list_resources(provider_name, "fixers")
|
||||
|
||||
|
||||
create_list_commands(aws)
|
||||
create_list_commands(azure)
|
||||
create_list_commands(gcp)
|
||||
create_list_commands(kubernetes)
|
||||
|
||||
|
||||
@app.command("banner", help="Prints the banner of the tool.")
|
||||
def banner(show: bool = True):
|
||||
if show:
|
||||
print_banner(show)
|
||||
else:
|
||||
print("Banner is not shown.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app()
|
||||
@@ -14,4 +14,4 @@ cd ~ || exit
|
||||
python3.9 -m pip install prowler-cloud
|
||||
prowler -v
|
||||
# Run Prowler
|
||||
prowler
|
||||
prowler aws
|
||||
8
contrib/aws/cloudshell/cloudshell-installation.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
sudo bash
|
||||
adduser prowler
|
||||
su prowler
|
||||
pip install prowler
|
||||
cd /tmp
|
||||
prowler aws
|
||||
@@ -212,6 +212,7 @@ Resources:
|
||||
- appstream:Describe*
|
||||
- codeartifact:List*
|
||||
- codebuild:BatchGet*
|
||||
- cognito-idp:GetUserPoolMfaConfig
|
||||
- ds:Get*
|
||||
- ds:Describe*
|
||||
- ds:List*
|
||||
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Install system dependencies
|
||||
sudo yum -y install openssl-devel bzip2-devel libffi-devel gcc
|
||||
# Upgrade to Python 3.9
|
||||
cd /tmp && wget https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tgz
|
||||
tar zxf Python-3.9.13.tgz
|
||||
cd Python-3.9.13/ || exit
|
||||
./configure --enable-optimizations
|
||||
sudo make altinstall
|
||||
python3.9 --version
|
||||
# Install Prowler
|
||||
cd ~ || exit
|
||||
python3.9 -m pip install prowler-cloud
|
||||
prowler -v
|
||||
# Run Prowler
|
||||
prowler
|
||||
47
contrib/gcp/enable_apis_in_projects.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
|
||||
# List of project IDs
|
||||
PROJECT_IDS=(
|
||||
"project-id-1"
|
||||
"project-id-2"
|
||||
"project-id-3"
|
||||
# Add more project IDs as needed
|
||||
)
|
||||
|
||||
# List of Prowler APIs to enable
|
||||
APIS=(
|
||||
"apikeys.googleapis.com"
|
||||
"artifactregistry.googleapis.com"
|
||||
"bigquery.googleapis.com"
|
||||
"sqladmin.googleapis.com" # Cloud SQL
|
||||
"storage.googleapis.com" # Cloud Storage
|
||||
"compute.googleapis.com"
|
||||
"dataproc.googleapis.com"
|
||||
"dns.googleapis.com"
|
||||
"containerregistry.googleapis.com" # GCR (Google Container Registry)
|
||||
"container.googleapis.com" # GKE (Google Kubernetes Engine)
|
||||
"iam.googleapis.com"
|
||||
"cloudkms.googleapis.com" # KMS (Key Management Service)
|
||||
"logging.googleapis.com"
|
||||
)
|
||||
|
||||
# Function to enable APIs for a given project
|
||||
enable_apis_for_project() {
|
||||
local PROJECT_ID=$1
|
||||
|
||||
echo "Enabling APIs for project: ${PROJECT_ID}"
|
||||
|
||||
for API in "${APIS[@]}"; do
|
||||
echo "Enabling API: $API for project: ${PROJECT_ID}"
|
||||
if gcloud services enable "${API}" --project="${PROJECT_ID}"; then
|
||||
echo "Successfully enabled API $API for project ${PROJECT_ID}."
|
||||
else
|
||||
echo "Failed to enable API $API for project ${PROJECT_ID}."
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Loop over each project and enable the APIs
|
||||
for PROJECT_ID in "${PROJECT_IDS[@]}"; do
|
||||
enable_apis_for_project "${PROJECT_ID}"
|
||||
done
|
||||
2
dashboard/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
DASHBOARD_PORT = 11666
|
||||
DASHBOARD_ARGS = {"debug": True, "port": DASHBOARD_PORT, "use_reloader": False}
|
||||
179
dashboard/__main__.py
Normal file
@@ -0,0 +1,179 @@
|
||||
# Importing Packages
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import click
|
||||
import dash
|
||||
import dash_bootstrap_components as dbc
|
||||
from colorama import Fore, Style
|
||||
from dash import dcc, html
|
||||
from dash.dependencies import Input, Output
|
||||
|
||||
from dashboard.config import folder_path_overview
|
||||
from prowler.config.config import orange_color
|
||||
from prowler.lib.banner import print_banner
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
cli = sys.modules["flask.cli"]
|
||||
print_banner(verbose=False)
|
||||
print(
|
||||
f"{Fore.GREEN}Loading all CSV files from the folder {folder_path_overview} ...\n{Style.RESET_ALL}"
|
||||
)
|
||||
cli.show_server_banner = lambda *x: click.echo(
|
||||
f"{Fore.YELLOW}NOTE:{Style.RESET_ALL} If you are a {Fore.GREEN}{Style.BRIGHT}Prowler SaaS{Style.RESET_ALL} customer and you want to use your data from your S3 bucket,\nrun: `{orange_color}aws s3 cp s3://<your-bucket>/output/csv ./output --recursive{Style.RESET_ALL}`\nand then run `prowler dashboard` again to load the new files."
|
||||
)
|
||||
|
||||
# Initialize the app - incorporate css
|
||||
dashboard = dash.Dash(
|
||||
__name__,
|
||||
external_stylesheets=[dbc.themes.FLATLY],
|
||||
use_pages=True,
|
||||
suppress_callback_exceptions=True,
|
||||
title="Prowler Dashboard",
|
||||
)
|
||||
|
||||
# Logo
|
||||
prowler_logo = html.Img(
|
||||
src="https://prowler.com/wp-content/uploads/logo-dashboard.png", alt="Prowler Logo"
|
||||
)
|
||||
|
||||
menu_icons = {
|
||||
"overview": "/assets/images/icons/overview.svg",
|
||||
"compliance": "/assets/images/icons/compliance.svg",
|
||||
}
|
||||
|
||||
|
||||
# Function to generate navigation links
|
||||
def generate_nav_links(current_path):
|
||||
nav_links = []
|
||||
for page in dash.page_registry.values():
|
||||
# Gets the icon URL based on the page name
|
||||
icon_url = menu_icons.get(page["name"].lower())
|
||||
is_active = (
|
||||
" bg-prowler-stone-950 border-r-4 border-solid border-prowler-lime"
|
||||
if current_path == page["relative_path"]
|
||||
else ""
|
||||
)
|
||||
link_class = f"block hover:bg-prowler-stone-950 hover:border-r-4 hover:border-solid hover:border-prowler-lime{is_active}"
|
||||
|
||||
link_content = html.Span(
|
||||
[
|
||||
html.Img(src=icon_url, className="w-5"),
|
||||
html.Span(
|
||||
page["name"], className="font-medium text-base leading-6 text-white"
|
||||
),
|
||||
],
|
||||
className="flex justify-center lg:justify-normal items-center gap-x-3 py-2 px-3",
|
||||
)
|
||||
|
||||
nav_link = html.Li(
|
||||
dcc.Link(link_content, href=page["relative_path"], className=link_class)
|
||||
)
|
||||
nav_links.append(nav_link)
|
||||
return nav_links
|
||||
|
||||
|
||||
def generate_help_menu():
|
||||
help_links = [
|
||||
{
|
||||
"title": "Help",
|
||||
"url": "https://github.com/prowler-cloud/prowler/issues",
|
||||
"icon": "/assets/images/icons/help.png",
|
||||
},
|
||||
{
|
||||
"title": "Docs",
|
||||
"url": "https://docs.prowler.com",
|
||||
"icon": "/assets/images/icons/docs.png",
|
||||
},
|
||||
]
|
||||
|
||||
link_class = "block hover:bg-prowler-stone-950 hover:border-r-4 hover:border-solid hover:border-prowler-lime"
|
||||
|
||||
menu_items = []
|
||||
for link in help_links:
|
||||
menu_item = html.Li(
|
||||
html.A(
|
||||
html.Span(
|
||||
[
|
||||
html.Img(src=link["icon"], className="w-5"),
|
||||
html.Span(
|
||||
link["title"],
|
||||
className="font-medium text-base leading-6 text-white",
|
||||
),
|
||||
],
|
||||
className="flex items-center gap-x-3 py-2 px-3",
|
||||
),
|
||||
href=link["url"],
|
||||
target="_blank",
|
||||
className=link_class,
|
||||
)
|
||||
)
|
||||
menu_items.append(menu_item)
|
||||
|
||||
return menu_items
|
||||
|
||||
|
||||
# Layout
|
||||
dashboard.layout = html.Div(
|
||||
[
|
||||
dcc.Location(id="url", refresh=False),
|
||||
html.Link(rel="icon", href="assets/favicon.ico"),
|
||||
# Placeholder for dynamic navigation bar
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
id="navigation-bar", className="bg-prowler-stone-900 min-w-36 z-10"
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
dash.page_container,
|
||||
],
|
||||
id="content_select",
|
||||
className="bg-prowler-white w-full col-span-11 h-screen mx-auto overflow-y-scroll no-scrollbar px-10 py-7",
|
||||
),
|
||||
],
|
||||
className="grid custom-grid 2xl:custom-grid-large h-screen",
|
||||
),
|
||||
],
|
||||
className="h-screen mx-auto",
|
||||
)
|
||||
|
||||
|
||||
# Callback to update navigation bar
|
||||
@dashboard.callback(Output("navigation-bar", "children"), [Input("url", "pathname")])
|
||||
def update_nav_bar(pathname):
|
||||
return html.Div(
|
||||
[
|
||||
html.Div([prowler_logo], className="mb-8 px-3"),
|
||||
html.H6(
|
||||
"Dashboards",
|
||||
className="px-3 text-prowler-stone-500 text-sm opacity-90 font-regular mb-2",
|
||||
),
|
||||
html.Nav(
|
||||
[html.Ul(generate_nav_links(pathname), className="")],
|
||||
className="flex flex-col gap-y-6",
|
||||
),
|
||||
html.Nav(
|
||||
[
|
||||
html.A(
|
||||
[
|
||||
html.Span(
|
||||
[
|
||||
html.Img(src="assets/favicon.ico", className="w-5"),
|
||||
"Subscribe to prowler SaaS",
|
||||
],
|
||||
className="flex items-center gap-x-3 text-white",
|
||||
),
|
||||
],
|
||||
href="https://prowler.com/",
|
||||
target="_blank",
|
||||
className="block p-3 uppercase text-xs hover:bg-prowler-stone-950 hover:border-r-4 hover:border-solid hover:border-prowler-lime",
|
||||
),
|
||||
html.Ul(generate_help_menu(), className=""),
|
||||
],
|
||||
className="flex flex-col gap-y-6 mt-auto",
|
||||
),
|
||||
],
|
||||
className="flex flex-col bg-prowler-stone-900 py-7 h-full",
|
||||
)
|
||||
BIN
dashboard/assets/favicon.ico
Normal file
|
After Width: | Height: | Size: 28 KiB |
1
dashboard/assets/images/icons/arrows.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 443 511.62"><path fill-rule="nonzero" d="M152.93 286.97c0 17.1-13.87 30.97-30.97 30.97-17.11 0-30.98-13.87-30.98-30.97v-177.4l-37.45 40.31c-11.63 12.5-31.19 13.2-43.68 1.57-12.49-11.62-13.19-31.18-1.57-43.68L99.33 9.79l2.06-1.94c12.69-11.35 32.2-10.26 43.55 2.43l91.05 101.47c11.35 12.69 10.26 32.2-2.43 43.55-12.68 11.36-32.19 10.27-43.55-2.42l-37.08-41.33v175.42zm236.24 71.77c11.35-12.69 30.86-13.78 43.55-2.43 12.69 11.36 13.78 30.87 2.42 43.56L344.1 501.34c-11.36 12.69-30.87 13.78-43.55 2.42l-2.02-1.97-91.09-97.95c-11.63-12.49-10.93-32.05 1.57-43.67 12.49-11.63 32.05-10.93 43.67 1.57l37.46 40.31V231.53c0-17.11 13.87-30.97 30.97-30.97s30.97 13.86 30.97 30.97v168.54l37.09-41.33z"/></svg>
|
||||
|
After Width: | Height: | Size: 896 B |
4
dashboard/assets/images/icons/compliance.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="#FFF" aria-hidden="true" class="h-5 w-5" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M9 1.5H5.625c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0 0 16.5 9h-1.875a1.875 1.875 0 0 1-1.875-1.875V5.25A3.75 3.75 0 0 0 9 1.5zm6.61 10.936a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 14.47a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25z" clip-rule="evenodd"/>
|
||||
<path d="M12.971 1.816A5.23 5.23 0 0 1 14.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 0 1 3.434 1.279 9.768 9.768 0 0 0-6.963-6.963z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 650 B |
BIN
dashboard/assets/images/icons/docs.png
Normal file
|
After Width: | Height: | Size: 734 B |
1
dashboard/assets/images/icons/dropdown.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg class="svg-icon" style="width: 1.001953125em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1026 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M1013.7 90.8C997.8 75.5 972.4 76 957.1 92L510.9 557.1 73.2 90.8C58 74.7 32.7 73.9 16.6 89 0.5 104.1-0.3 129.4 14.8 145.5l466.6 497.1 1.5 1.5c0.2 0.2 0.4 0.4 0.7 0.6 0.3 0.3 0.6 0.5 0.9 0.8 0.3 0.3 0.6 0.5 0.9 0.7 0.2 0.2 0.4 0.4 0.7 0.6 0.3 0.2 0.6 0.5 0.9 0.7 0.2 0.2 0.5 0.4 0.7 0.5l0.9 0.6c0.3 0.2 0.5 0.4 0.8 0.5 0.3 0.2 0.6 0.3 0.9 0.5 0.3 0.2 0.6 0.3 0.9 0.5 0.3 0.2 0.5 0.3 0.8 0.4 0.3 0.2 0.6 0.3 1 0.5 0.3 0.1 0.5 0.3 0.8 0.4 0.3 0.2 0.7 0.3 1 0.5 0.2 0.1 0.5 0.2 0.7 0.3 0.4 0.2 0.7 0.3 1.1 0.4 0.2 0.1 0.5 0.2 0.7 0.3 0.4 0.1 0.8 0.3 1.2 0.4 0.2 0.1 0.5 0.1 0.7 0.2l1.2 0.3c0.2 0.1 0.4 0.1 0.7 0.2 0.4 0.1 0.8 0.2 1.3 0.3 0.2 0 0.4 0.1 0.6 0.1 0.4 0.1 0.9 0.2 1.3 0.2 0.2 0 0.4 0.1 0.6 0.1 0.5 0.1 0.9 0.1 1.4 0.2 0.2 0 0.4 0 0.6 0.1 0.5 0 1 0.1 1.5 0.1h4.6c0.5 0 1-0.1 1.5-0.1 0.2 0 0.4 0 0.5-0.1 0.5 0 0.9-0.1 1.4-0.2 0.2 0 0.4-0.1 0.6-0.1 0.4-0.1 0.9-0.1 1.3-0.2 0.2 0 0.4-0.1 0.6-0.1l1.2-0.3c0.2-0.1 0.4-0.1 0.7-0.2l1.2-0.3c0.2-0.1 0.5-0.1 0.7-0.2 0.4-0.1 0.8-0.2 1.1-0.4 0.2-0.1 0.5-0.2 0.7-0.3 0.4-0.1 0.7-0.3 1.1-0.4 0.3-0.1 0.5-0.2 0.8-0.3 0.3-0.1 0.7-0.3 1-0.5 0.3-0.1 0.5-0.2 0.8-0.4 0.3-0.2 0.6-0.3 0.9-0.5 0.3-0.1 0.6-0.3 0.8-0.4 0.3-0.2 0.6-0.3 0.8-0.5 0.3-0.2 0.6-0.3 0.9-0.5 0.3-0.2 0.5-0.3 0.8-0.5l0.9-0.6c0.2-0.2 0.4-0.3 0.7-0.5 0.3-0.2 0.6-0.5 1-0.7 0.2-0.1 0.4-0.3 0.6-0.5 0.3-0.3 0.7-0.5 1-0.8 0.2-0.1 0.3-0.3 0.5-0.5 0.5-0.5 1-0.9 1.5-1.4l0.9-0.9 475.4-495.6c15.3-15.7 14.7-41.1-1.2-56.3z" fill="#898989" /></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
dashboard/assets/images/icons/help-black.png
Normal file
|
After Width: | Height: | Size: 441 B |
BIN
dashboard/assets/images/icons/help.png
Normal file
|
After Width: | Height: | Size: 934 B |
4
dashboard/assets/images/icons/overview.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="#FFF" aria-hidden="true" class="h-5 w-5" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M2.25 13.5a8.25 8.25 0 0 1 8.25-8.25.75.75 0 0 1 .75.75v6.75H18a.75.75 0 0 1 .75.75 8.25 8.25 0 0 1-16.5 0z" clip-rule="evenodd"/>
|
||||
<path fill-rule="evenodd" d="M12.75 3a.75.75 0 0 1 .75-.75 8.25 8.25 0 0 1 8.25 8.25.75.75 0 0 1-.75.75h-7.5a.75.75 0 0 1-.75-.75V3z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 435 B |
BIN
dashboard/assets/images/providers/aws_provider.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
dashboard/assets/images/providers/azure_provider.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
dashboard/assets/images/providers/gcp_provider.png
Normal file
|
After Width: | Height: | Size: 245 KiB |
BIN
dashboard/assets/images/providers/k8s_provider.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
dashboard/assets/logo.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
1406
dashboard/assets/styles/dist/output.css
vendored
Normal file
2225
dashboard/common_methods.py
Normal file
23
dashboard/compliance/aws_account_security_onboarding_aws.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format2
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format2(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format1
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format1(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format1
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format1(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format1
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format1(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format2
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ATTRIBUTES_NAME",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
]
|
||||
return get_section_containers_format2(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_NAME", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format2
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ATTRIBUTES_NAME",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
]
|
||||
|
||||
return get_section_containers_format2(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ATTRIBUTES_NAME"
|
||||
)
|
||||
24
dashboard/compliance/cis_1_4_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
24
dashboard/compliance/cis_1_5_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
24
dashboard/compliance/cis_1_8_kubernetes.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
24
dashboard/compliance/cis_2_0_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
24
dashboard/compliance/cis_2_0_azure.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
24
dashboard/compliance/cis_2_0_gcp.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
24
dashboard/compliance/cis_2_1_azure.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
24
dashboard/compliance/cis_3_0_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_cis
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_cis(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION"
|
||||
)
|
||||
23
dashboard/compliance/cisa_aws.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format1
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format1(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
36
dashboard/compliance/ens_rd2022_aws.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_ens
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
# append the requirements_description to idgrupocontrol
|
||||
data["REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL"] = (
|
||||
data["REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL"]
|
||||
+ " - "
|
||||
+ data["REQUIREMENTS_DESCRIPTION"]
|
||||
)
|
||||
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ATTRIBUTES_MARCO",
|
||||
"REQUIREMENTS_ATTRIBUTES_CATEGORIA",
|
||||
"REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL",
|
||||
"REQUIREMENTS_ATTRIBUTES_TIPO",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
]
|
||||
|
||||
return get_section_containers_ens(
|
||||
aux,
|
||||
"REQUIREMENTS_ATTRIBUTES_MARCO",
|
||||
"REQUIREMENTS_ATTRIBUTES_CATEGORIA",
|
||||
"REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL",
|
||||
"REQUIREMENTS_ATTRIBUTES_TIPO",
|
||||
)
|
||||
24
dashboard/compliance/fedramp_low_revision_4_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
24
dashboard/compliance/fedramp_moderate_revision_4_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
24
dashboard/compliance/ffiec_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
23
dashboard/compliance/gdpr_aws.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format1
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format1(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
24
dashboard/compliance/gxp_21_cfr_part_11_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
23
dashboard/compliance/gxp_eu_annex_11_aws.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format1
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format1(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
24
dashboard/compliance/hipaa_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
23
dashboard/compliance/iso27001_2013_aws.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_container_iso
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ATTRIBUTES_CATEGORY",
|
||||
"REQUIREMENTS_ATTRIBUTES_OBJETIVE_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_OBJETIVE_NAME",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
]
|
||||
return get_section_container_iso(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_CATEGORY", "REQUIREMENTS_ATTRIBUTES_OBJETIVE_ID"
|
||||
)
|
||||
21
dashboard/compliance/mitre_attack_aws.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format4
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_NAME",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
]
|
||||
|
||||
return get_section_containers_format4(aux, "REQUIREMENTS_ID")
|
||||
21
dashboard/compliance/mitre_attack_azure.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format4
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_NAME",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
]
|
||||
|
||||
return get_section_containers_format4(aux, "REQUIREMENTS_ID")
|
||||
23
dashboard/compliance/mitre_attack_gcp.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format2
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_SUBTECHNIQUES",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format2(
|
||||
aux, "REQUIREMENTS_ID", "REQUIREMENTS_SUBTECHNIQUES"
|
||||
)
|
||||
24
dashboard/compliance/nist_800_171_revision_2_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
24
dashboard/compliance/nist_800_53_revision_4_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
24
dashboard/compliance/nist_800_53_revision_5_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
24
dashboard/compliance/nist_csf_1_1_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
20
dashboard/compliance/pci_3_2_1_aws.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format4
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
]
|
||||
|
||||
return get_section_containers_format4(aux, "REQUIREMENTS_ID")
|
||||
20
dashboard/compliance/rbi_cyber_security_framework_aws.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_rbi
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
]
|
||||
return get_section_containers_rbi(aux, "REQUIREMENTS_ID")
|
||||
24
dashboard/compliance/soc2_aws.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import warnings
|
||||
|
||||
from dashboard.common_methods import get_section_containers_format3
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_table(data):
|
||||
aux = data[
|
||||
[
|
||||
"REQUIREMENTS_ID",
|
||||
"REQUIREMENTS_DESCRIPTION",
|
||||
"REQUIREMENTS_ATTRIBUTES_SECTION",
|
||||
"CHECKID",
|
||||
"STATUS",
|
||||
"REGION",
|
||||
"ACCOUNTID",
|
||||
"RESOURCEID",
|
||||
]
|
||||
].copy()
|
||||
|
||||
return get_section_containers_format3(
|
||||
aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID"
|
||||
)
|
||||
33
dashboard/config.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import os
|
||||
|
||||
# Emojis to be used in the compliance table
|
||||
pass_emoji = "✅"
|
||||
fail_emoji = "❌"
|
||||
info_emoji = "ℹ️"
|
||||
manual_emoji = "✋🏽"
|
||||
|
||||
# Main colors
|
||||
fail_color = "#e67272"
|
||||
pass_color = "#54d283"
|
||||
info_color = "#2684FF"
|
||||
manual_color = "#636c78"
|
||||
|
||||
# Muted colors
|
||||
muted_fail_color = "#fca903"
|
||||
muted_pass_color = "#03fccf"
|
||||
muted_manual_color = "#b33696"
|
||||
|
||||
# Severity colors
|
||||
critical_color = "#951649"
|
||||
high_color = "#e11d48"
|
||||
medium_color = "#ee6f15"
|
||||
low_color = "#f9f5e6"
|
||||
informational_color = "#3274d9"
|
||||
|
||||
# Folder output path
|
||||
folder_path_overview = os.getcwd() + "/output"
|
||||
folder_path_compliance = os.getcwd() + "/output/compliance"
|
||||
|
||||
encoding_format = "utf-8"
|
||||
# Error action, it is recommended to use "ignore" or "replace"
|
||||
error_action = "ignore"
|
||||
5
dashboard/lib/arguments/arguments.py
Normal file
@@ -0,0 +1,5 @@
|
||||
def init_dashboard_parser(self):
|
||||
"""Init the Dashboard CLI parser"""
|
||||
# If we don't set `help="Dashboard"` this won't be rendered
|
||||
# We don't want the dashboard to inherit from the common providers parser since it's a different component
|
||||
self.subparsers.add_parser("dashboard")
|
||||
157
dashboard/lib/cards.py
Normal file
@@ -0,0 +1,157 @@
|
||||
from typing import List
|
||||
|
||||
from dash import html
|
||||
|
||||
|
||||
def create_provider_card(
|
||||
provider: str, provider_logo: str, account_type: str, filtered_data
|
||||
) -> List[html.Div]:
|
||||
"""
|
||||
Card to display the provider's name and icon.
|
||||
Args:
|
||||
provider (str): Name of the provider.
|
||||
provider_icon (str): Icon of the provider.
|
||||
Returns:
|
||||
html.Div: Card to display the provider's name and icon.
|
||||
"""
|
||||
accounts = len(
|
||||
filtered_data[filtered_data["PROVIDER"] == provider]["ACCOUNT_UID"].unique()
|
||||
)
|
||||
checks_executed = len(
|
||||
filtered_data[filtered_data["PROVIDER"] == provider]["CHECK_ID"].unique()
|
||||
)
|
||||
fails = len(
|
||||
filtered_data[
|
||||
(filtered_data["PROVIDER"] == provider)
|
||||
& (filtered_data["STATUS"] == "FAIL")
|
||||
]
|
||||
)
|
||||
passes = len(
|
||||
filtered_data[
|
||||
(filtered_data["PROVIDER"] == provider)
|
||||
& (filtered_data["STATUS"] == "PASS")
|
||||
]
|
||||
)
|
||||
# Take the values in the MUTED colum that are true for the provider
|
||||
if "MUTED" in filtered_data.columns:
|
||||
muted = len(
|
||||
filtered_data[
|
||||
(filtered_data["PROVIDER"] == provider)
|
||||
& (filtered_data["MUTED"] == "True")
|
||||
]
|
||||
)
|
||||
else:
|
||||
muted = 0
|
||||
|
||||
return [
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
[
|
||||
html.Div([provider_logo], className="w-8"),
|
||||
],
|
||||
className="p-2 shadow-box-up rounded-full",
|
||||
),
|
||||
html.H5(
|
||||
f"{provider.upper()} {account_type}",
|
||||
className="text-base font-semibold leading-snug tracking-normal text-gray-900",
|
||||
),
|
||||
],
|
||||
className="flex justify-between items-center mb-3",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
[
|
||||
html.Span(
|
||||
account_type,
|
||||
className="text-prowler-stone-900 inline-block text-3xs font-bold uppercase transition-all rounded-lg text-prowler-stone-900 shadow-box-up px-4 py-1 text-center col-span-6 flex justify-center items-center",
|
||||
),
|
||||
html.Div(
|
||||
accounts,
|
||||
className="inline-block text-xs text-prowler-stone-900 font-bold shadow-box-down px-4 py-1 rounded-lg text-center col-span-5 col-end-13",
|
||||
),
|
||||
],
|
||||
className="grid grid-cols-12",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Span(
|
||||
"Checks",
|
||||
className="text-prowler-stone-900 inline-block text-3xs font-bold uppercase transition-all rounded-lg text-prowler-stone-900 shadow-box-up px-4 py-1 text-center col-span-6 flex justify-center items-center",
|
||||
),
|
||||
html.Div(
|
||||
checks_executed,
|
||||
className="inline-block text-xs text-prowler-stone-900 font-bold shadow-box-down px-4 py-1 rounded-lg text-center col-span-5 col-end-13",
|
||||
),
|
||||
],
|
||||
className="grid grid-cols-12",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Span(
|
||||
"FAILED",
|
||||
className="text-prowler-stone-900 inline-block text-3xs font-bold uppercase transition-all rounded-lg text-prowler-stone-900 shadow-box-up px-4 py-1 text-center col-span-6 flex justify-center items-center",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
fails,
|
||||
className="m-[2px] px-4 py-1 rounded-lg bg-gradient-failed",
|
||||
),
|
||||
],
|
||||
className="inline-block text-xs font-bold shadow-box-down rounded-lg text-center col-span-5 col-end-13",
|
||||
),
|
||||
],
|
||||
className="grid grid-cols-12",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Span(
|
||||
"PASSED",
|
||||
className="text-prowler-stone-900 inline-block text-3xs font-bold uppercase transition-all rounded-lg text-prowler-stone-900 shadow-box-up px-4 py-1 text-center col-span-6 flex justify-center items-center",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
passes,
|
||||
className="m-[2px] px-4 py-1 rounded-lg bg-gradient-passed",
|
||||
),
|
||||
],
|
||||
className="inline-block text-xs font-bold shadow-box-down rounded-lg text-center col-span-5 col-end-13",
|
||||
),
|
||||
],
|
||||
className="grid grid-cols-12",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Span(
|
||||
"MUTED",
|
||||
className="text-prowler-stone-900 inline-block text-3xs font-bold uppercase transition-all rounded-lg text-prowler-stone-900 shadow-box-up px-4 py-1 text-center col-span-6 flex justify-center items-center",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
muted,
|
||||
className="m-[2px] px-4 py-1 rounded-lg bg-gradient-muted",
|
||||
),
|
||||
],
|
||||
className="inline-block text-xs font-bold shadow-box-down rounded-lg text-center col-span-5 col-end-13",
|
||||
),
|
||||
],
|
||||
className="grid grid-cols-12",
|
||||
),
|
||||
],
|
||||
className="grid gap-x-8 gap-y-4",
|
||||
),
|
||||
],
|
||||
className="px-4 py-3",
|
||||
),
|
||||
],
|
||||
className="relative flex flex-col bg-white shadow-provider rounded-xl w-full transition ease-in-out delay-100 hover:-translate-y-1 hover:scale-110 hover:z-50 hover:cursor-pointer",
|
||||
)
|
||||
]
|
||||
289
dashboard/lib/dropdowns.py
Normal file
@@ -0,0 +1,289 @@
|
||||
from dash import dcc, html
|
||||
|
||||
|
||||
def create_date_dropdown(assesment_times: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the date of the last available scan for each account.
|
||||
Args:
|
||||
assesment_times (list): List of dates of the last available scan for each account.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the date of the last available scan for each account.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Assessment date (last available scan) ",
|
||||
className="text-prowler-stone-900 font-bold text-sm",
|
||||
),
|
||||
html.Img(
|
||||
id="info-file-over",
|
||||
src="/assets/images/icons/help-black.png",
|
||||
className="w-5",
|
||||
title="The date of the last available scan for each account is displayed here. If you have not run prowler yet, the date will be empty.",
|
||||
),
|
||||
],
|
||||
style={"display": "inline-flex"},
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="report-date-filter",
|
||||
options=[
|
||||
{"label": account, "value": account} for account in assesment_times
|
||||
],
|
||||
value=assesment_times[0],
|
||||
clearable=False,
|
||||
multi=False,
|
||||
style={"color": "#000000", "width": "100%"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_date_dropdown_compliance(assesment_times: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the date of the last available scan for each account.
|
||||
Args:
|
||||
assesment_times (list): List of dates of the last available scan for each account.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the date of the last available scan for each account.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Assesment Date:", className="text-prowler-stone-900 font-bold text-sm"
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="date-filter-analytics",
|
||||
options=[
|
||||
{"label": account, "value": account} for account in assesment_times
|
||||
],
|
||||
value=assesment_times[0],
|
||||
clearable=False,
|
||||
multi=False,
|
||||
style={"color": "#000000", "width": "100%"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_region_dropdown(regions: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the region of the account.
|
||||
Args:
|
||||
regions (list): List of regions of the account.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the region of the account.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Region / Location / Namespace :",
|
||||
className="text-prowler-stone-900 font-bold text-sm",
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="region-filter",
|
||||
options=[{"label": region, "value": region} for region in regions],
|
||||
value=["All"], # Initial selection is ALL
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000", "width": "100%"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_region_dropdown_compliance(regions: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the region of the account.
|
||||
Args:
|
||||
regions (list): List of regions of the account.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the region of the account.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Region / Location / Namespace :",
|
||||
className="text-prowler-stone-900 font-bold text-sm",
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="region-filter-compliance",
|
||||
options=[{"label": region, "value": region} for region in regions],
|
||||
value=["All"], # Initial selection is ALL
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000", "width": "100%"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_account_dropdown(accounts: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the account.
|
||||
Args:
|
||||
accounts (list): List of accounts.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the account.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Account / Subscription / Project / Cluster :",
|
||||
className="text-prowler-stone-900 font-bold text-sm",
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="cloud-account-filter",
|
||||
options=[{"label": account, "value": account} for account in accounts],
|
||||
value=["All"], # Initial selection is ALL
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000", "width": "100%"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_account_dropdown_compliance(accounts: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the account.
|
||||
Args:
|
||||
accounts (list): List of accounts.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the account.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Account / Subscription / Project / Cluster :",
|
||||
className="text-prowler-stone-900 font-bold text-sm",
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="cloud-account-filter-compliance",
|
||||
options=[{"label": account, "value": account} for account in accounts],
|
||||
value=["All"], # Initial selection is ALL
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000", "width": "100%"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_compliance_dropdown(compliance: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the compliance.
|
||||
Args:
|
||||
compliance (list): List of compliance.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the compliance.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Compliance:", className="text-prowler-stone-900 font-bold text-sm"
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="report-compliance-filter",
|
||||
options=[{"label": i, "value": i} for i in compliance],
|
||||
value=compliance[0],
|
||||
clearable=False,
|
||||
style={"color": "#000000"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_severity_dropdown(severity: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the severity.
|
||||
Args:
|
||||
severity (list): List of severity.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the severity.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Severity:", className="text-prowler-stone-900 font-bold text-sm"
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="severity-filter",
|
||||
options=[{"label": i, "value": i} for i in severity],
|
||||
value=["All"],
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_service_dropdown(services: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the service.
|
||||
Args:
|
||||
services (list): List of services.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the service.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label(
|
||||
"Service:", className="text-prowler-stone-900 font-bold text-sm"
|
||||
),
|
||||
dcc.Dropdown(
|
||||
id="service-filter",
|
||||
options=[{"label": i, "value": i} for i in services],
|
||||
value=["All"],
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_status_dropdown(status: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the status.
|
||||
Args:
|
||||
status (list): List of status.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the status.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
html.Label("Status:", className="text-prowler-stone-900 font-bold text-sm"),
|
||||
dcc.Dropdown(
|
||||
id="status-filter",
|
||||
options=[{"label": i, "value": i} for i in status],
|
||||
value=["All"],
|
||||
clearable=False,
|
||||
multi=True,
|
||||
style={"color": "#000000"},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def create_table_row_dropdown(table_rows: list) -> html.Div:
|
||||
"""
|
||||
Dropdown to select the number of rows in the table.
|
||||
Args:
|
||||
table_rows (list): List of number of rows.
|
||||
Returns:
|
||||
html.Div: Dropdown to select the number of rows in the table.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
dcc.Dropdown(
|
||||
id="table-rows",
|
||||
options=[{"label": i, "value": i} for i in table_rows],
|
||||
value=table_rows[0],
|
||||
clearable=False,
|
||||
style={"color": "#000000", "margin-right": "10px"},
|
||||
),
|
||||
],
|
||||
)
|
||||
176
dashboard/lib/layouts.py
Normal file
@@ -0,0 +1,176 @@
|
||||
from dash import dcc, html
|
||||
|
||||
|
||||
def create_layout_overview(
|
||||
account_dropdown: html.Div,
|
||||
date_dropdown: html.Div,
|
||||
region_dropdown: html.Div,
|
||||
download_button_csv: html.Button,
|
||||
download_button_xlsx: html.Button,
|
||||
severity_dropdown: html.Div,
|
||||
service_dropdown: html.Div,
|
||||
table_row_dropdown: html.Div,
|
||||
status_dropdown: html.Div,
|
||||
table_div_header: html.Div,
|
||||
) -> html.Div:
|
||||
"""
|
||||
Create the layout of the dashboard.
|
||||
Args:
|
||||
account_dropdown (html.Div): Dropdown to select the account.
|
||||
date_dropdown (html.Div): Dropdown to select the date of the last available scan for each account.
|
||||
region_dropdown (html.Div): Dropdown to select the region of the account.
|
||||
Returns:
|
||||
html.Div: Layout of the dashboard.
|
||||
"""
|
||||
return html.Div(
|
||||
[
|
||||
dcc.Location(id="url", refresh=False),
|
||||
html.Div(
|
||||
[
|
||||
html.H1(
|
||||
"Scan Overview",
|
||||
className="text-prowler-stone-900 text-2xxl font-bold",
|
||||
),
|
||||
html.Div(className="d-flex flex-wrap", id="subscribe_card"),
|
||||
],
|
||||
className="flex justify-between border-b border-prowler-500 pb-3",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div([date_dropdown], className=""),
|
||||
html.Div([account_dropdown], className=""),
|
||||
html.Div([region_dropdown], className=""),
|
||||
],
|
||||
className="grid gap-x-4 mt-[30px] mb-[30px] sm:grid-cols-2 lg:grid-cols-3",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div([severity_dropdown], className=""),
|
||||
html.Div([service_dropdown], className=""),
|
||||
html.Div([status_dropdown], className=""),
|
||||
],
|
||||
className="grid gap-x-4 mb-[30px] sm:grid-cols-2 lg:grid-cols-3",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div(className="flex", id="aws_card", n_clicks=0),
|
||||
html.Div(className="flex", id="azure_card", n_clicks=0),
|
||||
html.Div(className="flex", id="gcp_card", n_clicks=0),
|
||||
html.Div(className="flex", id="k8s_card", n_clicks=0),
|
||||
],
|
||||
className="grid gap-x-4 mb-[30px] sm:grid-cols-2 lg:grid-cols-4",
|
||||
),
|
||||
html.H4(
|
||||
"Count of Findings by severity",
|
||||
className="text-prowler-stone-900 text-lg font-bold mb-[30px]",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
className="flex flex-col col-span-12 sm:col-span-6 lg:col-span-3 gap-y-4",
|
||||
id="status_graph",
|
||||
),
|
||||
html.Div(
|
||||
className="flex flex-col col-span-12 sm:col-span-6 lg:col-span-3 gap-y-4",
|
||||
id="two_pie_chart",
|
||||
),
|
||||
html.Div(
|
||||
className="flex flex-col col-span-12 sm:col-span-6 lg:col-span-6 col-end-13 gap-y-4",
|
||||
id="line_plot",
|
||||
),
|
||||
],
|
||||
className="grid gap-x-4 grid-cols-12 mb-[30px]",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.H4(
|
||||
"Top Findings by Severity",
|
||||
className="text-prowler-stone-900 text-lg font-bold",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
(
|
||||
html.Label(
|
||||
"Table Rows:",
|
||||
className="text-prowler-stone-900 font-bold text-sm",
|
||||
style={"margin-right": "10px"},
|
||||
)
|
||||
),
|
||||
table_row_dropdown,
|
||||
download_button_csv,
|
||||
download_button_xlsx,
|
||||
],
|
||||
className="flex justify-between items-center",
|
||||
),
|
||||
dcc.Download(id="download-data"),
|
||||
],
|
||||
className="flex justify-between items-center",
|
||||
),
|
||||
table_div_header,
|
||||
html.Div(id="table", className="grid"),
|
||||
],
|
||||
className="grid gap-x-8 2xl:container mx-auto",
|
||||
)
|
||||
|
||||
|
||||
def create_layout_compliance(
|
||||
account_dropdown: html.Div,
|
||||
date_dropdown: html.Div,
|
||||
region_dropdown: html.Div,
|
||||
compliance_dropdown: html.Div,
|
||||
) -> html.Div:
|
||||
return html.Div(
|
||||
[
|
||||
dcc.Location(id="url", refresh=False),
|
||||
html.Div(
|
||||
[
|
||||
html.H1(
|
||||
"Compliance",
|
||||
className="text-prowler-stone-900 text-2xxl font-bold",
|
||||
),
|
||||
html.A(
|
||||
[
|
||||
html.Img(src="assets/favicon.ico", className="w-5 mr-3"),
|
||||
html.Span("Subscribe to prowler SaaS"),
|
||||
],
|
||||
href="https://prowler.pro/",
|
||||
target="_blank",
|
||||
className="text-prowler-stone-900 inline-flex px-4 py-2 text-xs font-bold uppercase transition-all rounded-lg text-gray-900 hover:bg-prowler-stone-900/10 border-solid border-1 hover:border-prowler-stone-900/10 hover:border-solid hover:border-1 border-prowler-stone-900/10",
|
||||
),
|
||||
],
|
||||
className="flex justify-between border-b border-prowler-500 pb-3",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div([date_dropdown], className=""),
|
||||
html.Div([account_dropdown], className=""),
|
||||
html.Div([region_dropdown], className=""),
|
||||
html.Div([compliance_dropdown], className=""),
|
||||
],
|
||||
className="grid gap-x-4 gap-y-4 sm:grid-cols-2 lg:grid-cols-4 lg:gap-y-0",
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
html.Div(
|
||||
className="flex flex-col col-span-12 md:col-span-4 gap-y-4",
|
||||
id="overall_status_result_graph",
|
||||
),
|
||||
html.Div(
|
||||
className="flex flex-col col-span-12 md:col-span-7 md:col-end-13 gap-y-4",
|
||||
id="security_level_graph",
|
||||
),
|
||||
html.Div(
|
||||
className="flex flex-col col-span-12 md:col-span-2 gap-y-4",
|
||||
id="",
|
||||
),
|
||||
],
|
||||
className="grid gap-x-4 gap-y-4 grid-cols-12 lg:gap-y-0",
|
||||
),
|
||||
html.H4(
|
||||
"Details compliance:",
|
||||
className="text-prowler-stone-900 text-lg font-bold",
|
||||
),
|
||||
html.Div(className="flex flex-wrap", id="output"),
|
||||
],
|
||||
className="grid gap-x-8 gap-y-8 2xl:container mx-auto",
|
||||
)
|
||||