mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-06-11 05:46:05 +00:00
Compare commits
264 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4dcb1145a5 | |||
| c88663b7ef | |||
| 6197e7b342 | |||
| e4a596696b | |||
| 7dd436c971 | |||
| c76fbaef3b | |||
| 6b329b1835 | |||
| d111781387 | |||
| 6f68c5cacc | |||
| a1cfc2d3df | |||
| 958ca6da65 | |||
| a140007ecb | |||
| 75dec160bb | |||
| df16872333 | |||
| 40a1e8abbd | |||
| d623d26e64 | |||
| ca2b6f3ffc | |||
| c572c8a56d | |||
| 797abe634a | |||
| a18b5ff49f | |||
| 0e1c6c2d3a | |||
| fc5b484b27 | |||
| 2d225de838 | |||
| a332c806bb | |||
| e236bcecf5 | |||
| 5bf309117a | |||
| 6cfb68773f | |||
| 902d82485a | |||
| 5b51a4b2ad | |||
| 9a5aa8ec06 | |||
| e2d5490700 | |||
| 8429c1c36d | |||
| 882cd3c25e | |||
| 0204d24f5e | |||
| 27fe201a48 | |||
| a154fb46b8 | |||
| 530c627ca7 | |||
| 9861c22fe0 | |||
| 0a9ea21e11 | |||
| a591beb1bb | |||
| 967969288f | |||
| ddb72cff0f | |||
| 240f57278a | |||
| b2e322fab7 | |||
| 6a38d22634 | |||
| 6525c2f17a | |||
| e0698b28d1 | |||
| 49146ffddf | |||
| b41e23415b | |||
| 55688eaab0 | |||
| 9c89b13c13 | |||
| 4db961bad3 | |||
| e4bf049d06 | |||
| 184b4c3f70 | |||
| e1620bcb0f | |||
| a2f3fab936 | |||
| 0cd2ad5636 | |||
| 6fab9a89fd | |||
| 87f5d32bb3 | |||
| 6540facaea | |||
| d11b5f8f12 | |||
| 8a982afe21 | |||
| f3303974d3 | |||
| c69f0a0085 | |||
| 9c9df486f0 | |||
| e12aa389a3 | |||
| e8db8525ab | |||
| 87e9b0f807 | |||
| 65b2a81226 | |||
| ad63b6991e | |||
| b536be1c56 | |||
| 6b078fd668 | |||
| 436521d932 | |||
| ee09ccb4aa | |||
| 52406f6df2 | |||
| 7687148a27 | |||
| 44b7fc4624 | |||
| 68050d3df3 | |||
| 47fe1b77e2 | |||
| 04057e8911 | |||
| 401fdec1fb | |||
| 4e556c86ef | |||
| 72c8de3e67 | |||
| 3786cbcd5f | |||
| 1084b00ef7 | |||
| 7f5ddcc215 | |||
| 60b8f9d3b9 | |||
| 4c4f12ffda | |||
| 4c0729378d | |||
| fda49bec18 | |||
| 9606cf21eb | |||
| d3da9dd90e | |||
| 4fb010847f | |||
| 8eac17d826 | |||
| 8a1abb60c9 | |||
| 74776bed06 | |||
| 3373a8e6c8 | |||
| 7db74516b3 | |||
| 3ae2f9e0bf | |||
| 91a8a13dc6 | |||
| 700ed5ecec | |||
| 50aebcaf88 | |||
| ad96963706 | |||
| 95832bdb12 | |||
| d7bdc0aaef | |||
| 1c0c836286 | |||
| 822252d03b | |||
| a20fdb30f9 | |||
| 2e339f964a | |||
| bb4498a3d5 | |||
| dae4392efc | |||
| 8b3a1608c2 | |||
| 148bdacebe | |||
| b60edc1f6b | |||
| d28462b642 | |||
| ef9b37d5c0 | |||
| 764f260cea | |||
| e771218bba | |||
| c627a3e9aa | |||
| 1c58644118 | |||
| 398fa37a23 | |||
| 412d948585 | |||
| 6bc0432ed5 | |||
| b2ebc8410a | |||
| 94b6fbda91 | |||
| 3ce785a7b4 | |||
| e4ecc98aae | |||
| 53a4befb01 | |||
| fee0bf3ea1 | |||
| 6811a22651 | |||
| fe2dd69b08 | |||
| 26a9748700 | |||
| cef0a54bc3 | |||
| 553a51ddc2 | |||
| 61dc09d15d | |||
| 9b91ba2b91 | |||
| 18d60c98d7 | |||
| 00054b5cd9 | |||
| 24fc86cbb3 | |||
| 861fb22257 | |||
| 7e14204be8 | |||
| 09ea6ba6c4 | |||
| a83725fbed | |||
| 34210cfc06 | |||
| 2e20d52030 | |||
| 9b0b61ef02 | |||
| 0203aec9e0 | |||
| 862a4ad76c | |||
| 4b7883c464 | |||
| 2bf835d3d2 | |||
| 09733eb298 | |||
| 096749a455 | |||
| b06e549d81 | |||
| a5f5967bb2 | |||
| 7a4f5f34f7 | |||
| e33b081dc6 | |||
| c8fdaa3923 | |||
| 8a491bcf7d | |||
| f5e71db5e0 | |||
| 456f79d80c | |||
| 9f728833a7 | |||
| f01ce849dc | |||
| 572d5a1f2e | |||
| c69571abcd | |||
| 8ddb9fbb84 | |||
| 193b79c221 | |||
| a25a6148f2 | |||
| 0a63e707c2 | |||
| f53a887291 | |||
| ca35510d74 | |||
| 5d7c8d9cd2 | |||
| 0d01790b22 | |||
| 78b518e22b | |||
| 17af724995 | |||
| c9898d6d01 | |||
| 259538d5e4 | |||
| 4785feae0e | |||
| 8be83fc632 | |||
| 005d251106 | |||
| b6c8adfc64 | |||
| 7a711095cd | |||
| b0bb348480 | |||
| c1b050b8b9 | |||
| 28c7e803ac | |||
| 919acfd548 | |||
| 1586cdae5e | |||
| cb74dae296 | |||
| 3608aa3536 | |||
| c59b08c40b | |||
| 73361a1cea | |||
| 794268cec5 | |||
| 06b41cf8e6 | |||
| a419b4b898 | |||
| 622bc48688 | |||
| c0659f712a | |||
| 796983a530 | |||
| 8dc042e594 | |||
| e881a0f274 | |||
| 5641160177 | |||
| dca49b1972 | |||
| b8b60e6bc5 | |||
| 9d65b49cb4 | |||
| f1334190d8 | |||
| c434181dfd | |||
| f3cfacae9a | |||
| 77c7986797 | |||
| 2ac716d6db | |||
| daee5fb4d2 | |||
| d587d40451 | |||
| f0cd88bd0e | |||
| aca17904fa | |||
| 0157802ac1 | |||
| 10766d708d | |||
| f231d8b080 | |||
| 590a7b2697 | |||
| 3c3421644f | |||
| f1f68da25d | |||
| 48df7fdebf | |||
| f2e8691bf4 | |||
| 344d54155a | |||
| 8ecffa3039 | |||
| efbbfc1c68 | |||
| dc68c1b955 | |||
| 5de13bdd8a | |||
| 5d0f498425 | |||
| 716558ffcb | |||
| 23929b3e68 | |||
| a5612abc8c | |||
| 78dddc1e03 | |||
| 76020d4d47 | |||
| b0af1390b5 | |||
| bc3cd43126 | |||
| 087dae07d8 | |||
| 0baf4fb224 | |||
| 0f8ea48f2f | |||
| ec207c50ce | |||
| b59b40b822 | |||
| aa51045329 | |||
| 1a9f854063 | |||
| 6bdcb509e1 | |||
| ce1e9de104 | |||
| 2471bc569a | |||
| d0ef75d8d9 | |||
| aa79a289ce | |||
| 0340ab9570 | |||
| a2929f2efb | |||
| bf4db86dec | |||
| a339dafcc6 | |||
| f376516aad | |||
| 816b49fac5 | |||
| 6851350093 | |||
| d5873c0437 | |||
| a2dba30869 | |||
| 0662dff13f | |||
| 0ae26bddfc | |||
| 43efabef6c | |||
| e73fc14f62 | |||
| 89fe8fa8e2 | |||
| 634ef2e599 | |||
| 4efb70a508 | |||
| c3ae0aa873 | |||
| a109cd2816 | |||
| 78fb540bbb | |||
| 5b543bf058 |
+39
-2
@@ -5,6 +5,7 @@
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
# v5
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
@@ -14,6 +15,7 @@ updates:
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "pip"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
@@ -24,20 +26,55 @@ updates:
|
||||
- "dependencies"
|
||||
- "github_actions"
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: master
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "npm"
|
||||
|
||||
# v4.6
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: v4.6
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "pip"
|
||||
- "v4"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: v4.6
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "github_actions"
|
||||
- "v4"
|
||||
|
||||
# v3
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: v3
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "pip"
|
||||
- "v3"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: v3
|
||||
labels:
|
||||
|
||||
@@ -79,3 +79,10 @@ output/csv:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "prowler/lib/outputs/csv/**"
|
||||
- any-glob-to-any-file: "tests/lib/outputs/csv/**"
|
||||
|
||||
compliance:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "prowler/lib/outputs/compliance/**"
|
||||
- any-glob-to-any-file: "tests/lib/outputs/compliance/**"
|
||||
- any-glob-to-any-file: "prowler/compliance/**"
|
||||
|
||||
|
||||
@@ -3,7 +3,11 @@ name: build-lint-push-containers
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
# For `v3-latest`
|
||||
- "v3"
|
||||
# For `v4-latest`
|
||||
- "v4.6"
|
||||
# For `latest`
|
||||
- "master"
|
||||
paths-ignore:
|
||||
- ".github/**"
|
||||
@@ -58,7 +62,7 @@ jobs:
|
||||
|
||||
- name: Install Poetry
|
||||
run: |
|
||||
pipx install poetry
|
||||
pipx install poetry==1.8.5
|
||||
pipx inject poetry poetry-bumpversion
|
||||
|
||||
- name: Get Prowler version
|
||||
@@ -80,8 +84,8 @@ jobs:
|
||||
;;
|
||||
|
||||
4)
|
||||
echo "LATEST_TAG=latest" >> "${GITHUB_ENV}"
|
||||
echo "STABLE_TAG=stable" >> "${GITHUB_ENV}"
|
||||
echo "LATEST_TAG=v4-latest" >> "${GITHUB_ENV}"
|
||||
echo "STABLE_TAG=v4-stable" >> "${GITHUB_ENV}"
|
||||
;;
|
||||
|
||||
*)
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: TruffleHog OSS
|
||||
uses: trufflesecurity/trufflehog@v3.83.2
|
||||
uses: trufflesecurity/trufflehog@v3.88.6
|
||||
with:
|
||||
path: ./
|
||||
base: ${{ github.event.repository.default_branch }}
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true'
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pipx install poetry
|
||||
pipx install poetry==1.8.5
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true'
|
||||
uses: actions/setup-python@v5
|
||||
@@ -91,6 +91,6 @@ jobs:
|
||||
poetry run pytest -n auto --cov=./prowler --cov-report=xml tests
|
||||
- name: Upload coverage reports to Codecov
|
||||
if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true'
|
||||
uses: codecov/codecov-action@v4
|
||||
uses: codecov/codecov-action@v5
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pipx install poetry
|
||||
pipx install poetry==1.8.5
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
FROM python:3.12-alpine
|
||||
FROM python:3.12.8-alpine3.20
|
||||
|
||||
LABEL maintainer="https://github.com/prowler-cloud/prowler"
|
||||
|
||||
@@ -6,7 +6,7 @@ LABEL maintainer="https://github.com/prowler-cloud/prowler"
|
||||
#hadolint ignore=DL3018
|
||||
RUN apk --no-cache upgrade && apk --no-cache add curl git
|
||||
|
||||
# Create nonroot user
|
||||
# Create non-root user
|
||||
RUN mkdir -p /home/prowler && \
|
||||
echo 'prowler:x:1000:1000:prowler:/home/prowler:' > /etc/passwd && \
|
||||
echo 'prowler:x:1000:' > /etc/group && \
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
</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/38561120/3c8b4ec5-6849-41a5-b5e1-52bbb94af73a"></a>
|
||||
<a href="https://goto.prowler.com/slack"><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-2oinmgmw6-cl7gOrljSEqo_aoripVPFA">Join our Prowler community!</a>
|
||||
<a href="https://goto.prowler.com/slack">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>
|
||||
<a href="https://goto.prowler.com/slack"><img alt="Slack Shield" src="https://img.shields.io/badge/slack-prowler-brightgreen.svg?logo=slack"></a>
|
||||
<a href="https://pypi.org/project/prowler/"><img alt="Python Version" src="https://img.shields.io/pypi/v/prowler.svg"></a>
|
||||
<a href="https://pypi.python.org/pypi/prowler/"><img alt="Python Version" src="https://img.shields.io/pypi/pyversions/prowler.svg"></a>
|
||||
<a href="https://pypistats.org/packages/prowler"><img alt="PyPI Prowler Downloads" src="https://img.shields.io/pypi/dw/prowler.svg?label=prowler%20downloads"></a>
|
||||
@@ -63,9 +63,9 @@ It contains hundreds of controls covering CIS, NIST 800, NIST CSF, CISA, RBI, Fe
|
||||
|
||||
| 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 | 457 | 67 -> `prowler aws --list-services` | 30 -> `prowler aws --list-compliance` | 9 -> `prowler aws --list-categories` |
|
||||
| GCP | 77 | 13 -> `prowler gcp --list-services` | 2 -> `prowler gcp --list-compliance` | 2 -> `prowler gcp --list-categories`|
|
||||
| Azure | 136 | 17 -> `prowler azure --list-services` | 3 -> `prowler azure --list-compliance` | 2 -> `prowler azure --list-categories` |
|
||||
| AWS | 553 | 77 -> `prowler aws --list-services` | 30 -> `prowler aws --list-compliance` | 9 -> `prowler aws --list-categories` |
|
||||
| GCP | 77 | 13 -> `prowler gcp --list-services` | 3 -> `prowler gcp --list-compliance` | 2 -> `prowler gcp --list-categories`|
|
||||
| Azure | 138 | 17 -> `prowler azure --list-services` | 4 -> `prowler azure --list-compliance` | 2 -> `prowler azure --list-categories` |
|
||||
| Kubernetes | 83 | 7 -> `prowler kubernetes --list-services` | 1 -> `prowler kubernetes --list-compliance` | 7 -> `prowler kubernetes --list-categories` |
|
||||
|
||||
# 💻 Installation
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
@@ -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",
|
||||
)
|
||||
@@ -148,6 +148,7 @@ else:
|
||||
select_account_dropdown_list = ["All"]
|
||||
# Append to the list the unique values of the columns ACCOUNTID, PROJECTID and SUBSCRIPTIONID if they exist
|
||||
if "ACCOUNTID" in data.columns:
|
||||
data["ACCOUNTID"] = data["ACCOUNTID"].astype(str)
|
||||
select_account_dropdown_list = select_account_dropdown_list + list(
|
||||
data["ACCOUNTID"].unique()
|
||||
)
|
||||
@@ -246,9 +247,11 @@ def display_data(
|
||||
dfs = []
|
||||
for file in files:
|
||||
df = pd.read_csv(
|
||||
file, sep=";", on_bad_lines="skip", encoding=encoding_format
|
||||
file, sep=";", on_bad_lines="skip", encoding=encoding_format, dtype=str
|
||||
)
|
||||
dfs.append(df.astype(str))
|
||||
df = df.astype(str).fillna("nan")
|
||||
df.columns = df.columns.astype(str)
|
||||
dfs.append(df)
|
||||
return pd.concat(dfs, ignore_index=True)
|
||||
|
||||
data = load_csv_files(files)
|
||||
@@ -274,17 +277,24 @@ def display_data(
|
||||
data.rename(columns={"PROJECTID": "ACCOUNTID"}, inplace=True)
|
||||
data["REGION"] = "-"
|
||||
# Rename the column SUBSCRIPTIONID to ACCOUNTID for Azure
|
||||
if data.columns.str.contains("SUBSCRIPTIONID").any():
|
||||
if (
|
||||
data.columns.str.contains("SUBSCRIPTIONID").any()
|
||||
and not data.columns.str.contains("ACCOUNTID").any()
|
||||
):
|
||||
data.rename(columns={"SUBSCRIPTIONID": "ACCOUNTID"}, inplace=True)
|
||||
data["REGION"] = "-"
|
||||
# Handle v3 azure cis compliance
|
||||
if data.columns.str.contains("SUBSCRIPTION").any():
|
||||
if (
|
||||
data.columns.str.contains("SUBSCRIPTION").any()
|
||||
and not data.columns.str.contains("ACCOUNTID").any()
|
||||
):
|
||||
data.rename(columns={"SUBSCRIPTION": "ACCOUNTID"}, inplace=True)
|
||||
data["REGION"] = "-"
|
||||
|
||||
# Filter ACCOUNT
|
||||
if account_filter == ["All"]:
|
||||
updated_cloud_account_values = data["ACCOUNTID"].unique()
|
||||
|
||||
elif "All" in account_filter and len(account_filter) > 1:
|
||||
# Remove 'All' from the list
|
||||
account_filter.remove("All")
|
||||
@@ -299,9 +309,11 @@ def display_data(
|
||||
|
||||
account_filter_options = list(data["ACCOUNTID"].unique())
|
||||
account_filter_options = account_filter_options + ["All"]
|
||||
for item in account_filter_options:
|
||||
if "nan" in item or item.__class__.__name__ != "str" or item is None:
|
||||
account_filter_options.remove(item)
|
||||
account_filter_options = [
|
||||
item
|
||||
for item in account_filter_options
|
||||
if isinstance(item, str) and item.lower() != "nan"
|
||||
]
|
||||
|
||||
# Filter REGION
|
||||
if region_filter_analytics == ["All"]:
|
||||
@@ -520,8 +532,8 @@ def get_bar_graph(df, column_name):
|
||||
|
||||
# Cut the text if it is too long
|
||||
for i in range(len(colums)):
|
||||
if len(colums[i]) > 15:
|
||||
colums[i] = colums[i][:15] + "..."
|
||||
if len(colums[i]) > 43:
|
||||
colums[i] = colums[i][:43] + "..."
|
||||
|
||||
fig = px.bar(
|
||||
df,
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
For technical support or any type of inquiries, you are very welcome to:
|
||||
|
||||
- Reach out to community members on the [**Prowler Slack channel**](https://join.slack.com/t/prowler-workspace/shared_invite/zt-1hix76xsl-2uq222JIXrC7Q8It~9ZNog)
|
||||
- Reach out to community members on the [**Prowler Slack channel**](https://goto.prowler.com/slack)
|
||||
|
||||
- Open an Issue or a Pull Request in our [**GitHub repository**](https://github.com/prowler-cloud/prowler).
|
||||
|
||||
|
||||
@@ -160,14 +160,20 @@ else:
|
||||
All the checks MUST fill the `report.resource_id` and `report.resource_arn` with the following criteria:
|
||||
|
||||
- AWS
|
||||
- Resource ID -- `report.resource_id`
|
||||
- AWS Account --> Account Number `123456789012`
|
||||
- AWS Resource --> Resource ID / Name
|
||||
- Root resource --> `<root_account>`
|
||||
- Resource ARN -- `report.resource_arn`
|
||||
- AWS Account --> Root ARN `arn:aws:iam::123456789012:root`
|
||||
- AWS Resource --> Resource ARN
|
||||
- Root resource --> Resource Type ARN `f"arn:{service_client.audited_partition}:<service_name>:{service_client.region}:{service_client.audited_account}:<resource_type>"`
|
||||
- Resouce ID and resource ARN:
|
||||
- If the resource audited is the AWS account:
|
||||
- `resource_id` -> AWS Account Number
|
||||
- `resource_arn` -> AWS Account Root ARN
|
||||
- If we can’t get the ARN from the resource audited, we create a valid ARN with the `resource_id` part as the resource audited. Examples:
|
||||
- Bedrock -> `arn:<partition>:bedrock:<region>:<account-id>:model-invocation-logging`
|
||||
- DirectConnect -> `arn:<partition>:directconnect:<region>:<account-id>:dxcon`
|
||||
- If there is no real resource to audit we do the following:
|
||||
- resource_id -> `resource_type/unknown`
|
||||
- resource_arn -> `arn:<partition>:<service>:<region>:<account-id>:<resource_type>/unknown`
|
||||
- Examples:
|
||||
- AWS Security Hub -> `arn:<partition>:security-hub:<region>:<account-id>:hub/unknown`
|
||||
- Access Analyzer -> `arn:<partition>:access-analyzer:<region>:<account-id>:analyzer/unknown`
|
||||
- GuardDuty -> `arn:<partition>:guardduty:<region>:<account-id>:detector/unknown`
|
||||
- GCP
|
||||
- Resource ID -- `report.resource_id`
|
||||
- GCP Resource --> Resource ID
|
||||
|
||||
@@ -67,4 +67,4 @@ If you create or review a PR in https://github.com/prowler-cloud/prowler please
|
||||
|
||||
## Want some swag as appreciation for your contribution?
|
||||
|
||||
If you are like us and you love swag, we are happy to thank you for your contribution with some laptop stickers or whatever other swag we may have at that time. Please, tell us more details and your pull request link in our [Slack workspace here](https://join.slack.com/t/prowler-workspace/shared_invite/zt-1hix76xsl-2uq222JIXrC7Q8It~9ZNog). You can also reach out to Toni de la Fuente on Twitter [here](https://twitter.com/ToniBlyx), his DMs are open.
|
||||
If you are like us and you love swag, we are happy to thank you for your contribution with some laptop stickers or whatever other swag we may have at that time. Please, tell us more details and your pull request link in our [Slack workspace here](https://goto.prowler.com/slack). You can also reach out to Toni de la Fuente on Twitter [here](https://twitter.com/ToniBlyx), his DMs are open.
|
||||
|
||||
@@ -190,18 +190,18 @@ from prowler.providers.common.models import Audit_Metadata
|
||||
from prowler.providers.common.provider import Provider
|
||||
from prowler.providers.<new_provider_name>.models import (
|
||||
# All providers models needed
|
||||
ProvierSessionModel,
|
||||
ProvierIdentityModel,
|
||||
ProvierOutputOptionsModel
|
||||
ProviderSessionModel,
|
||||
ProviderIdentityModel,
|
||||
ProviderOutputOptionsModel
|
||||
)
|
||||
|
||||
class NewProvider(Provider):
|
||||
# All properties from the class, some of this are properties in the base class
|
||||
_type: str = "<provider_name>"
|
||||
_session: <ProvierSessionModel>
|
||||
_identity: <ProvierIdentityModel>
|
||||
_session: <ProviderSessionModel>
|
||||
_identity: <ProviderIdentityModel>
|
||||
_audit_config: dict
|
||||
_output_options: ProvierOutputOptionsModel
|
||||
_output_options: ProviderOutputOptionsModel
|
||||
_mutelist: dict
|
||||
audit_metadata: Audit_Metadata
|
||||
|
||||
@@ -212,13 +212,13 @@ class NewProvider(Provider):
|
||||
arguments (dict): A dictionary containing configuration arguments.
|
||||
"""
|
||||
logger.info("Setting <NewProviderName> provider ...")
|
||||
# First get from arguments the necesary from the cloud acount (subscriptions or projects or whatever the provider use for storing services)
|
||||
# First get from arguments the necessary from the cloud account (subscriptions or projects or whatever the provider use for storing services)
|
||||
|
||||
# Set the session with the method enforced by parent class
|
||||
self._session = self.setup_session(credentials_file)
|
||||
|
||||
# Set the Identity class normaly the provider class give by Python provider library
|
||||
self._identity = <ProvierIdentityModel>()
|
||||
self._identity = <ProviderIdentityModel>()
|
||||
|
||||
# Set the provider configuration
|
||||
self._audit_config = load_and_validate_config_file(
|
||||
@@ -254,7 +254,7 @@ class NewProvider(Provider):
|
||||
<all_needed_for_auth> Can include all necessary arguments to setup the session
|
||||
|
||||
Returns:
|
||||
Credentials necesary to communicate with the provider.
|
||||
Credentials necessary to communicate with the provider.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@ The following list includes all the AWS checks with configurable variables that
|
||||
| `cloudtrail_threat_detection_privilege_escalation` | `threat_detection_privilege_escalation_entropy` | Integer |
|
||||
| `cloudtrail_threat_detection_privilege_escalation` | `threat_detection_privilege_escalation_minutes` | Integer |
|
||||
| `cloudwatch_log_group_no_secrets_in_logs` | `secrets_ignore_patterns` | List of Strings |
|
||||
| `cloudwatch_log_group_no_critical_pii_in_logs` | `critical_pii_entities` | List of Strings |
|
||||
| `cloudwatch_log_group_no_critical_pii_in_logs` | `pii_language` | String |
|
||||
| `cloudwatch_log_group_retention_policy_specific_days_enabled` | `log_group_retention_days` | Integer |
|
||||
| `codebuild_project_no_secrets_in_variables` | `excluded_sensitive_environment_variables` | List of Strings |
|
||||
| `codebuild_project_no_secrets_in_variables` | `secrets_ignore_patterns` | List of Strings |
|
||||
|
||||
@@ -125,5 +125,5 @@ prowler <provider> --list-categories
|
||||
```
|
||||
- Execute specific category(s):
|
||||
```console
|
||||
prowler <provider> --categories
|
||||
prowler <provider> --categories secrets
|
||||
```
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
# Prowler Check Kreator
|
||||
|
||||
???+ note
|
||||
Currently, this tool is only available for creating checks for the AWS provider.
|
||||
|
||||
**Prowler Check Kreator** is a utility designed to streamline the creation of new checks for Prowler. This tool generates all necessary files required to add a new check to the Prowler repository. Specifically, it creates:
|
||||
|
||||
- A dedicated folder for the check.
|
||||
- The main check script.
|
||||
- A metadata file with essential details.
|
||||
- A folder and file structure for testing the check.
|
||||
|
||||
## Usage
|
||||
|
||||
To use the tool, execute the main script with the following command:
|
||||
|
||||
```bash
|
||||
python util/prowler_check_kreator/prowler_check_kreator.py <prowler_provider> <check_name>
|
||||
```
|
||||
Parameters:
|
||||
|
||||
- `<prowler_provider>`: Currently only AWS is supported.
|
||||
- `<check_name>`: The name you wish to assign to the new check.
|
||||
|
||||
## AI integration
|
||||
|
||||
This tool optionally integrates AI to assist in generating the check code and metadata file content. When AI assistance is chosen, the tool uses [Gemini](https://gemini.google.com/) to produce preliminary code and metadata.
|
||||
|
||||
???+ note
|
||||
For this feature to work, you must have the library `google-generativeai` installed in your Python environment.
|
||||
|
||||
???+ warning
|
||||
AI-generated code and metadata might contain errors or require adjustments to align with specific Prowler requirements. Carefully review all AI-generated content before committing.
|
||||
|
||||
To enable AI assistance, simply confirm when prompted by the tool. Additionally, ensure that the `GEMINI_API_KEY` environment variable is set with a valid Gemini API key. For instructions on obtaining your API key, refer to the [Gemini documentation](https://ai.google.dev/gemini-api/docs/api-key).
|
||||
@@ -65,6 +65,7 @@ nav:
|
||||
- Pentesting: tutorials/pentesting.md
|
||||
- Parallel Execution: tutorials/parallel-execution.md
|
||||
- Developer Guide: developer-guide/introduction.md
|
||||
- Prowler Check Kreator: tutorials/prowler-check-kreator.md
|
||||
- AWS:
|
||||
- Authentication: tutorials/aws/authentication.md
|
||||
- Assume Role: tutorials/aws/role-assumption.md
|
||||
|
||||
@@ -91,6 +91,8 @@ Resources:
|
||||
- 'shield:GetSubscriptionState'
|
||||
- 'securityhub:BatchImportFindings'
|
||||
- 'securityhub:GetFindings'
|
||||
- 'servicecatalog:Describe*'
|
||||
- 'servicecatalog:List*'
|
||||
- 'ssm:GetDocument'
|
||||
- 'ssm-incidents:List*'
|
||||
- 'support:Describe*'
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
"shield:GetSubscriptionState",
|
||||
"securityhub:BatchImportFindings",
|
||||
"securityhub:GetFindings",
|
||||
"servicecatalog:Describe*",
|
||||
"servicecatalog:List*",
|
||||
"ssm:GetDocument",
|
||||
"ssm-incidents:List*",
|
||||
"support:Describe*",
|
||||
|
||||
Generated
+1561
-2083
File diff suppressed because it is too large
Load Diff
@@ -53,6 +53,8 @@ from prowler.lib.outputs.compliance.cis.cis_gcp import GCPCIS
|
||||
from prowler.lib.outputs.compliance.cis.cis_kubernetes import KubernetesCIS
|
||||
from prowler.lib.outputs.compliance.compliance import display_compliance_table
|
||||
from prowler.lib.outputs.compliance.ens.ens_aws import AWSENS
|
||||
from prowler.lib.outputs.compliance.ens.ens_azure import AzureENS
|
||||
from prowler.lib.outputs.compliance.ens.ens_gcp import GCPENS
|
||||
from prowler.lib.outputs.compliance.generic.generic import GenericCompliance
|
||||
from prowler.lib.outputs.compliance.iso27001.iso27001_aws import AWSISO27001
|
||||
from prowler.lib.outputs.compliance.kisa_ismsp.kisa_ismsp_aws import AWSKISAISMSP
|
||||
@@ -511,6 +513,20 @@ def prowler():
|
||||
)
|
||||
generated_outputs["compliance"].append(mitre_attack)
|
||||
mitre_attack.batch_write_data_to_file()
|
||||
elif compliance_name.startswith("ens_"):
|
||||
# Generate ENS Finding Object
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
f"{output_options.output_filename}_{compliance_name}.csv"
|
||||
)
|
||||
ens = AzureENS(
|
||||
findings=finding_outputs,
|
||||
compliance=bulk_compliance_frameworks[compliance_name],
|
||||
create_file_descriptor=True,
|
||||
file_path=filename,
|
||||
)
|
||||
generated_outputs["compliance"].append(ens)
|
||||
ens.batch_write_data_to_file()
|
||||
else:
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
@@ -555,6 +571,20 @@ def prowler():
|
||||
)
|
||||
generated_outputs["compliance"].append(mitre_attack)
|
||||
mitre_attack.batch_write_data_to_file()
|
||||
elif compliance_name.startswith("ens_"):
|
||||
# Generate ENS Finding Object
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
f"{output_options.output_filename}_{compliance_name}.csv"
|
||||
)
|
||||
ens = GCPENS(
|
||||
findings=finding_outputs,
|
||||
compliance=bulk_compliance_frameworks[compliance_name],
|
||||
create_file_descriptor=True,
|
||||
file_path=filename,
|
||||
)
|
||||
generated_outputs["compliance"].append(ens)
|
||||
ens.batch_write_data_to_file()
|
||||
else:
|
||||
filename = (
|
||||
f"{output_options.output_directory}/compliance/"
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
"Service": "ebs"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
"Checks": [
|
||||
"ec2_ebs_volume_snapshots_exists"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "1.0.3",
|
||||
@@ -42,7 +44,8 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_ebs_default_encryption"
|
||||
"ec2_ebs_default_encryption",
|
||||
"ec2_ebs_volume_encryption"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -87,7 +90,9 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_user_mfa_enabled_console_access"
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_user_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -102,7 +107,9 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_user_mfa_enabled_console_access"
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_user_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -117,7 +124,9 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_root_mfa_enabled"
|
||||
"iam_root_mfa_enabled",
|
||||
"iam_root_hardware_mfa_enabled",
|
||||
"iam_user_mfa_enabled_console_access"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -162,7 +171,10 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_no_public_access"
|
||||
"rds_instance_no_public_access",
|
||||
"s3_bucket_public_access",
|
||||
"s3_bucket_public_list_acl",
|
||||
"s3_account_level_public_access_blocks"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -192,7 +204,8 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_storage_encrypted"
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_instance_transport_encrypted"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -485,7 +485,7 @@
|
||||
"codeartifact_packages_external_public_publishing_disabled",
|
||||
"ecr_repositories_not_publicly_accessible",
|
||||
"efs_not_publicly_accessible",
|
||||
"eks_endpoints_not_publicly_accessible",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"elb_internet_facing",
|
||||
"elbv2_internet_facing",
|
||||
"s3_account_level_public_access_blocks",
|
||||
@@ -664,7 +664,7 @@
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"apigateway_restapi_waf_acl_attached",
|
||||
"cloudfront_distributions_using_waf",
|
||||
"eks_control_plane_endpoint_access_restricted",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"sagemaker_models_network_isolation_enabled",
|
||||
"sagemaker_models_vpc_settings_configured",
|
||||
"sagemaker_notebook_instance_vpc_settings_configured",
|
||||
|
||||
@@ -455,7 +455,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides a variety of no, or low, cost encryption options to protect data at rest.",
|
||||
@@ -476,7 +477,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "At the Amazon S3 bucket level, you can configure permissions through a bucket policy making the objects accessible only through HTTPS.",
|
||||
@@ -497,7 +499,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
@@ -518,7 +521,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Amazon S3 buckets can contain sensitive data, that for security purposes should be discovered, monitored, classified and protected. Macie along with other 3rd party tools can automatically provide an inventory of Amazon S3 buckets.",
|
||||
@@ -540,7 +544,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides `Block public access (bucket settings)` and `Block public access (account settings)` to help you manage public access to Amazon S3 resources. By default, S3 buckets and objects are created with public access disabled. However, an IAM principal with sufficient S3 permissions can enable public access at the bucket and/or object level. While enabled, `Block public access (bucket settings)` prevents an individual bucket, and its contained objects, from becoming publicly accessible. Similarly, `Block public access (account settings)` prevents all buckets, and contained objects, from becoming publicly accessible across the entire account.",
|
||||
@@ -561,7 +566,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Elastic Compute Cloud (EC2) supports encryption at rest when using the Elastic Block Store (EBS) service. While disabled by default, forcing encryption at EBS volume creation is supported.",
|
||||
@@ -578,11 +584,13 @@
|
||||
"Id": "2.3.1",
|
||||
"Description": "Ensure that encryption is enabled for RDS Instances",
|
||||
"Checks": [
|
||||
"rds_instance_storage_encrypted"
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_instance_transport_encrypted"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon RDS encrypted DB instances use the industry standard AES-256 encryption algorithm to encrypt your data on the server that hosts your Amazon RDS DB instances. After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently with a minimal impact on performance.",
|
||||
|
||||
@@ -455,7 +455,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides a variety of no, or low, cost encryption options to protect data at rest.",
|
||||
@@ -476,7 +477,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "At the Amazon S3 bucket level, you can configure permissions through a bucket policy making the objects accessible only through HTTPS.",
|
||||
@@ -497,7 +499,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
@@ -518,7 +521,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Amazon S3 buckets can contain sensitive data, that for security purposes should be discovered, monitored, classified and protected. Macie along with other 3rd party tools can automatically provide an inventory of Amazon S3 buckets.",
|
||||
@@ -540,7 +544,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides `Block public access (bucket settings)` and `Block public access (account settings)` to help you manage public access to Amazon S3 resources. By default, S3 buckets and objects are created with public access disabled. However, an IAM principal with sufficient S3 permissions can enable public access at the bucket and/or object level. While enabled, `Block public access (bucket settings)` prevents an individual bucket, and its contained objects, from becoming publicly accessible. Similarly, `Block public access (account settings)` prevents all buckets, and contained objects, from becoming publicly accessible across the entire account.",
|
||||
@@ -561,7 +566,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Elastic Compute Cloud (EC2) supports encryption at rest when using the Elastic Block Store (EBS) service. While disabled by default, forcing encryption at EBS volume creation is supported.",
|
||||
@@ -578,11 +584,13 @@
|
||||
"Id": "2.3.1",
|
||||
"Description": "Ensure that encryption is enabled for RDS Instances",
|
||||
"Checks": [
|
||||
"rds_instance_storage_encrypted"
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_instance_transport_encrypted"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon RDS encrypted DB instances use the industry standard AES-256 encryption algorithm to encrypt your data on the server that hosts your Amazon RDS DB instances. After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently with a minimal impact on performance.",
|
||||
@@ -603,7 +611,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure that RDS database instances have the Auto Minor Version Upgrade flag enabled in order to receive automatically minor engine upgrades during the specified maintenance window. So, RDS instances can get the new features, bug fixes, and security patches for their database engines.",
|
||||
@@ -624,7 +633,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure and verify that RDS database instances provisioned in your AWS account do restrict unauthorized access in order to minimize security risks. To restrict access to any publicly accessible RDS database instance, you must disable the database Publicly Accessible flag and update the VPC security group associated with the instance.",
|
||||
@@ -645,7 +655,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.4 Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.4 Elastic File System (EFS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "EFS data should be encrypted at rest using AWS KMS (Key Management Service).",
|
||||
|
||||
@@ -303,7 +303,9 @@
|
||||
{
|
||||
"Id": "1.22",
|
||||
"Description": "Ensure access to AWSCloudShellFullAccess is restricted",
|
||||
"Checks": [],
|
||||
"Checks": [
|
||||
"iam_policy_cloudshell_admin_not_attached"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1. Identity and Access Management",
|
||||
@@ -474,7 +476,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "At the Amazon S3 bucket level, you can configure permissions through a bucket policy making the objects accessible only through HTTPS.",
|
||||
@@ -491,11 +494,13 @@
|
||||
"Id": "2.1.2",
|
||||
"Description": "Ensure MFA Delete is enabled on S3 buckets",
|
||||
"Checks": [
|
||||
"s3_bucket_no_mfa_delete"
|
||||
"s3_bucket_no_mfa_delete",
|
||||
"cloudtrail_bucket_requires_mfa_delete"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
@@ -516,7 +521,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Amazon S3 buckets can contain sensitive data, that for security purposes should be discovered, monitored, classified and protected. Macie along with other 3rd party tools can automatically provide an inventory of Amazon S3 buckets.",
|
||||
@@ -538,7 +544,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides `Block public access (bucket settings)` and `Block public access (account settings)` to help you manage public access to Amazon S3 resources. By default, S3 buckets and objects are created with public access disabled. However, an IAM principal with sufficient S3 permissions can enable public access at the bucket and/or object level. While enabled, `Block public access (bucket settings)` prevents an individual bucket, and its contained objects, from becoming publicly accessible. Similarly, `Block public access (account settings)` prevents all buckets, and contained objects, from becoming publicly accessible across the entire account.",
|
||||
@@ -559,7 +566,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Elastic Compute Cloud (EC2) supports encryption at rest when using the Elastic Block Store (EBS) service. While disabled by default, forcing encryption at EBS volume creation is supported.",
|
||||
@@ -576,11 +584,13 @@
|
||||
"Id": "2.3.1",
|
||||
"Description": "Ensure that encryption is enabled for RDS Instances",
|
||||
"Checks": [
|
||||
"rds_instance_storage_encrypted"
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_instance_transport_encrypted"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon RDS encrypted DB instances use the industry standard AES-256 encryption algorithm to encrypt your data on the server that hosts your Amazon RDS DB instances. After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently with a minimal impact on performance.",
|
||||
@@ -601,7 +611,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure that RDS database instances have the Auto Minor Version Upgrade flag enabled in order to receive automatically minor engine upgrades during the specified maintenance window. So, RDS instances can get the new features, bug fixes, and security patches for their database engines.",
|
||||
@@ -622,7 +633,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure and verify that RDS database instances provisioned in your AWS account do restrict unauthorized access in order to minimize security risks. To restrict access to any publicly accessible RDS database instance, you must disable the database Publicly Accessible flag and update the VPC security group associated with the instance.",
|
||||
@@ -643,7 +655,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.4 Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.4 Elastic File System (EFS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "EFS data should be encrypted at rest using AWS KMS (Key Management Service).",
|
||||
@@ -1338,7 +1351,8 @@
|
||||
"Id": "5.6",
|
||||
"Description": "Ensure that EC2 Metadata Service only allows IMDSv2",
|
||||
"Checks": [
|
||||
"ec2_instance_imdsv2_enabled"
|
||||
"ec2_instance_imdsv2_enabled",
|
||||
"ec2_instance_account_imdsv2_enabled"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
@@ -474,7 +474,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "At the Amazon S3 bucket level, you can configure permissions through a bucket policy making the objects accessible only through HTTPS.",
|
||||
@@ -495,7 +496,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Once MFA Delete is enabled on your sensitive and classified S3 bucket it requires the user to have two forms of authentication.",
|
||||
@@ -516,7 +518,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Amazon S3 buckets can contain sensitive data, that for security purposes should be discovered, monitored, classified and protected. Macie along with other 3rd party tools can automatically provide an inventory of Amazon S3 buckets.",
|
||||
@@ -538,7 +541,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1. Simple Storage Service (S3)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.1. Simple Storage Service (S3)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon S3 provides `Block public access (bucket settings)` and `Block public access (account settings)` to help you manage public access to Amazon S3 resources. By default, S3 buckets and objects are created with public access disabled. However, an IAM principal with sufficient S3 permissions can enable public access at the bucket and/or object level. While enabled, `Block public access (bucket settings)` prevents an individual bucket, and its contained objects, from becoming publicly accessible. Similarly, `Block public access (account settings)` prevents all buckets, and contained objects, from becoming publicly accessible across the entire account.",
|
||||
@@ -559,7 +563,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.2. Elastic Compute Cloud (EC2)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Elastic Compute Cloud (EC2) supports encryption at rest when using the Elastic Block Store (EBS) service. While disabled by default, forcing encryption at EBS volume creation is supported.",
|
||||
@@ -580,7 +585,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Amazon RDS encrypted DB instances use the industry standard AES-256 encryption algorithm to encrypt your data on the server that hosts your Amazon RDS DB instances. After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently with a minimal impact on performance.",
|
||||
@@ -601,7 +607,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure that RDS database instances have the Auto Minor Version Upgrade flag enabled in order to receive automatically minor engine upgrades during the specified maintenance window. So, RDS instances can get the new features, bug fixes, and security patches for their database engines.",
|
||||
@@ -622,7 +629,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.3. Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.3. Relational Database Service (RDS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure and verify that RDS database instances provisioned in your AWS account do restrict unauthorized access in order to minimize security risks. To restrict access to anypublicly accessible RDS database instance, you must disable the database PubliclyAccessible flag and update the VPC security group associated with the instance",
|
||||
@@ -643,7 +651,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.4 Relational Database Service (RDS)",
|
||||
"Section": "2. Storage",
|
||||
"SubSection": "2.4 Elastic File System (EFS)",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "EFS data should be encrypted at rest using AWS KMS (Key Management Service).",
|
||||
|
||||
@@ -1509,9 +1509,9 @@
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"networkfirewall_in_all_vpc",
|
||||
"eks_cluster_network_policy_enabled",
|
||||
"eks_control_plane_endpoint_access_restricted",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"eks_cluster_private_nodes_enabled",
|
||||
"eks_endpoints_not_publicly_accessible",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"kafka_cluster_is_public",
|
||||
"kafka_cluster_unrestricted_access_disabled",
|
||||
"vpc_peering_routing_tables_with_least_privilege",
|
||||
|
||||
@@ -1509,9 +1509,9 @@
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"networkfirewall_in_all_vpc",
|
||||
"eks_cluster_network_policy_enabled",
|
||||
"eks_control_plane_endpoint_access_restricted",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"eks_cluster_private_nodes_enabled",
|
||||
"eks_endpoints_not_publicly_accessible",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"kafka_cluster_is_public",
|
||||
"kafka_cluster_unrestricted_access_disabled",
|
||||
"vpc_peering_routing_tables_with_least_privilege",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_instance_profile_attached",
|
||||
"ec2_instance_public_ip",
|
||||
"eks_endpoints_not_publicly_accessible",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
@@ -61,7 +61,7 @@
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_instance_profile_attached",
|
||||
"ec2_instance_public_ip",
|
||||
"eks_endpoints_not_publicly_accessible",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
@@ -102,7 +102,7 @@
|
||||
"Checks": [
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_instance_public_ip",
|
||||
"eks_endpoints_not_publicly_accessible",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"awslambda_function_url_public",
|
||||
|
||||
@@ -971,7 +971,7 @@
|
||||
"Checks": [
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_instance_public_ip",
|
||||
"eks_endpoints_not_publicly_accessible",
|
||||
"eks_cluster_not_publicly_accessible",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"awslambda_function_url_public",
|
||||
"rds_instance_no_public_access",
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.1 Security Defaults",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.1 Security Defaults",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Security defaults in Azure Active Directory (Azure AD) make it easier to be secure and help protect your organization. Security defaults contain preconfigured security settings for common attacks. Security defaults is available to everyone. The goal is to ensure that all organizations have a basic level of security",
|
||||
@@ -34,7 +35,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.1 Security Defaults",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.1 Security Defaults",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable multi-factor authentication for all roles, groups, and users that have write access or permissions to Azure resources. These include custom created objects or built-in roles such as; • Service Co-Administrators • Subscription Owners • Contributors",
|
||||
@@ -56,7 +58,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.1 Security Defaults",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.1 Security Defaults",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable multi-factor authentication for all non-privileged users.",
|
||||
@@ -76,7 +79,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.1 Security Defaults",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.1 Security Defaults",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Do not allow users to remember multi-factor authentication on devices.",
|
||||
@@ -98,7 +102,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Azure Active Directory Conditional Access allows an organization to configure Named locations and configure whether those locations are trusted or untrusted. These settings provide organizations the means to specify Geographical locations for use in conditional access policies, or define actual IP addresses and IP ranges and whether or not those IP addresses and/or ranges are trusted by the organization.",
|
||||
@@ -118,7 +123,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "CAUTION: If these policies are created without first auditing and testing the result, misconfiguration can potentially lock out administrators or create undesired access issues. Conditional Access Policies can be used to block access from geographic locations that are deemed out-of-scope for your organization or application. The scope and variables for this policy should be carefully examined and defined.",
|
||||
@@ -138,7 +144,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "For designated users, they will be prompted to use their multi-factor authentication (MFA) process on login.",
|
||||
@@ -158,7 +165,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "For designated users, they will be prompted to use their multi-factor authentication (MFA) process on logins.",
|
||||
@@ -178,7 +186,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "For designated users, they will be prompted to use their multi-factor authentication (MFA) process on login.",
|
||||
@@ -198,7 +207,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "For designated users, they will be prompted to use their multi-factor authentication (MFA) process on logins.",
|
||||
@@ -220,7 +230,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Require administrators or appropriately delegated users to create new tenants.",
|
||||
@@ -240,7 +250,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "This recommendation extends guest access review by utilizing the Azure AD Privileged Identity Management feature provided in Azure AD Premium P2. Azure AD is extended to include Azure AD B2B collaboration, allowing you to invite people from outside your organization to be guest users in your cloud account and sign in with their own work, school, or social identities. Guest users allow you to share your company's applications and services with users from any other organization, while maintaining control over your own corporate data. Work with external partners, large or small, even if they don't have Azure AD or an IT department. A simple invitation and redemption process lets partners use their own credentials to access your company's resources a a guest user.",
|
||||
@@ -260,7 +270,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Azure AD is extended to include Azure AD B2B collaboration, allowing you to invite people from outside your organization to be guest users in your cloud account and sign in with their own work, school, or social identities. Guest users allow you to share your company's applications and services with users from any other organization, while maintaining control over your own corporate data. Work with external partners, large or small, even if they don't have Azure AD or an IT department. A simple invitation and redemption process lets partners use their own credentials to access your company's resources as a guest user. Guest users in every subscription should be review on a regular basis to ensure that inactive and unneeded accounts are removed.",
|
||||
@@ -280,7 +290,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensures that two alternate forms of identification are provided before allowing a password reset.",
|
||||
@@ -300,7 +310,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Microsoft Azure provides a Global Banned Password policy that applies to Azure administrative and normal user accounts. This is not applied to user accounts that are synced from an on-premise Active Directory unless Azure AD Connect is used and you enable EnforceCloudPasswordPolicyForPasswordSyncedUsers. Please see the list in default values on the specifics of this policy. To further password security, it is recommended to further define a custom banned password policy.",
|
||||
@@ -320,7 +330,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure that the number of days before users are asked to re-confirm their authentication information is not set to 0.",
|
||||
@@ -340,7 +350,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure that users are notified on their primary and secondary emails on password resets.",
|
||||
@@ -360,7 +370,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure that all Global Administrators are notified if any other administrator resets their password.",
|
||||
@@ -382,7 +392,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Require administrators to provide consent for applications before use.",
|
||||
@@ -404,7 +414,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Allow users to provide consent for selected permissions when a request is coming from a verified publisher.",
|
||||
@@ -424,7 +434,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Require administrators to provide consent for the apps before use.",
|
||||
@@ -446,7 +456,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Require administrators or appropriately delegated users to register third-party applications.",
|
||||
@@ -468,7 +478,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Limit guest user permissions.",
|
||||
@@ -490,7 +500,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Restrict invitations to users with specific administrative roles only.",
|
||||
@@ -510,7 +520,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Restrict access to the Azure AD administration portal to administrators only. NOTE: This only affects access to the Azure AD administrator's web portal. This setting does not prohibit privileged users from using other methods such as Rest API or Powershell to obtain sensitive information from Azure AD.",
|
||||
@@ -530,7 +540,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Restricts group creation to administrators with permissions only.",
|
||||
@@ -552,7 +562,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Restrict security group creation to administrators only.",
|
||||
@@ -572,7 +582,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Restrict security group management to administrators only.",
|
||||
@@ -594,7 +604,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Restrict Microsoft 365 group creation to administrators only.",
|
||||
@@ -614,7 +624,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Joining or registering devices to the active directory should require Multi-factor authentication.",
|
||||
@@ -636,7 +646,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The principle of least privilege should be followed and only necessary privileges should be assigned instead of allowing full administrative access.",
|
||||
@@ -658,7 +668,7 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Resource locking is a powerful protection mechanism that can prevent inadvertent modification/deletion of resources within Azure subscriptions/Resource Groups and is a recommended NIST configuration.",
|
||||
@@ -678,7 +688,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1. Identity and Access Management",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Users who are set as subscription owners are able to make administrative changes to the subscriptions and move them into and out of Azure Active Directories.",
|
||||
@@ -700,7 +710,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Turning on Microsoft Defender for Servers enables threat detection for Servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -722,7 +733,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Turning on Microsoft Defender for App Service enables threat detection for App Service, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -744,7 +756,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Turning on Microsoft Defender for Databases enables threat detection for the instances running your database software. This provides threat intelligence, anomaly detection, and behavior analytics in the Azure Microsoft Defender for Cloud. Instead of being enabled on services like Platform as a Service (PaaS), this implementation will run within your instances as Infrastructure as a Service (IaaS) on the Operating Systems hosting your databases.",
|
||||
@@ -766,7 +779,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Turning on Microsoft Defender for Azure SQL Databases enables threat detection for Azure SQL database servers, providing threat intelligence, anomaly detection, andbehavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -788,7 +802,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Turning on Microsoft Defender for SQL servers on machines enables threat detection for SQL servers on machines, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -810,7 +825,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Turning on Microsoft Defender for Open-source relational databases enables threat detection for Open-source relational databases, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -832,7 +848,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Turning on Microsoft Defender for Storage enables threat detection for Storage, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -854,7 +871,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Turning on Microsoft Defender for Containers enables threat detection for Container Registries including Kubernetes, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -876,7 +894,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Microsoft Defender for Azure Cosmos DB scans all incoming network requests for threats to your Azure Cosmos DB resources.",
|
||||
@@ -898,7 +917,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Turning on Microsoft Defender for Key Vault enables threat detection for Key Vault, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -920,7 +940,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Microsoft Defender for DNS scans all network traffic exiting from within a subscription.",
|
||||
@@ -942,7 +963,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Microsoft Defender for Resource Manager scans incoming administrative requests to change your infrastructure from both CLI and the Azure portal.",
|
||||
@@ -964,7 +986,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure that the latest OS patches for all virtual machines are applied.",
|
||||
@@ -986,7 +1009,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "None of the settings offered by ASC Default policy should be set to effect Disabled.",
|
||||
@@ -1008,7 +1032,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable automatic provisioning of the monitoring agent to collect security data.",
|
||||
@@ -1030,7 +1055,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable automatic provisioning of vulnerability assessment for machines on both Azure and hybrid (Arc enabled) machines.",
|
||||
@@ -1050,7 +1076,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable automatic provisioning of the Microsoft Defender for Containers components.",
|
||||
@@ -1072,7 +1099,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable security alert emails to subscription owners.",
|
||||
@@ -1094,7 +1122,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Microsoft Defender for Cloud emails the subscription owners whenever a high-severity alert is triggered for their subscription. You should provide a security contact email address as an additional email address.",
|
||||
@@ -1116,7 +1145,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enables emailing security alerts to the subscription owner or other designated security contact.",
|
||||
@@ -1138,7 +1168,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "This integration setting enables Microsoft Defender for Cloud Apps (formerly 'Microsoft Cloud App Security' or 'MCAS' - see additional info) to communicate with Microsoft Defender for Cloud.",
|
||||
@@ -1160,7 +1191,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "This integration setting enables Microsoft Defender for Endpoint (formerly 'Advanced Threat Protection' or 'ATP' or 'WDATP' - see additional info) to communicate with Microsoft Defender for Cloud. IMPORTANT: When enabling integration between DfE & DfC it needs to be taken into account that this will have some side effects that may be undesirable. 1. For server 2019 & above if defender is installed (default for these server SKU's) this will trigger a deployment of the new unified agent and link to any of the extended configuration in the Defender portal. 2. If the new unified agent is required for server SKU's of Win 2016 or Linux and lower there is additional integration that needs to be switched on and agents need to be aligned.",
|
||||
@@ -1182,7 +1214,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.2 Microsoft Defender for IoT",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.2 Microsoft Defender for IoT",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Microsoft Defender for IoT acts as a central security hub for IoT devices within your organization.",
|
||||
@@ -1524,7 +1557,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable auditing on SQL Servers.",
|
||||
@@ -1546,7 +1580,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure that no SQL Databases allow ingress from 0.0.0.0/0 (ANY IP).",
|
||||
@@ -1568,7 +1603,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Transparent Data Encryption (TDE) with Customer-managed key support provides increased transparency and control over the TDE Protector, increased security with an HSM-backed external service, and promotion of separation of duties. With TDE, data is encrypted at rest with a symmetric key (called the database encryption key) stored in the database or data warehouse distribution. To protect this data encryption key (DEK) in the past, only a certificate that the Azure SQL Service managed could be used. Now, with Customer-managed key support for TDE, the DEK can be protected with an asymmetric key that is stored in the Azure Key Vault. The Azure Key Vault is a highly available and scalable cloud-based key store which offers central key management, leverages FIPS 140-2 Level 2 validated hardware security modules (HSMs), and allows separation of management of keys and data for additional security. Based on business needs or criticality of data/databases hosted on a SQL server, it is recommended that the TDE protector is encrypted by a key that is managed by the data owner (Customer-managed key).",
|
||||
@@ -1590,7 +1626,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Use Azure Active Directory Authentication for authentication with SQL Database to manage credentials in a single place.",
|
||||
@@ -1612,7 +1649,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable Transparent Data Encryption on every SQL server.",
|
||||
@@ -1634,7 +1672,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "SQL Server Audit Retention should be configured to be greater than 90 days.",
|
||||
@@ -1656,7 +1695,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable 'Microsoft Defender for SQL' on critical SQL Servers.",
|
||||
@@ -1678,7 +1718,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable Vulnerability Assessment (VA) service scans for critical SQL servers and corresponding SQL databases.",
|
||||
@@ -1700,7 +1741,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable Vulnerability Assessment (VA) service scans for critical SQL servers and corresponding SQL databases.",
|
||||
@@ -1722,7 +1764,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Configure 'Send scan reports to' with email addresses of concerned data owners/stakeholders for a critical SQL servers",
|
||||
@@ -1744,7 +1787,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.2 SQL Server - Microsoft Defender for SQL",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable Vulnerability Assessment (VA) setting 'Also send email notifications to admins and subscription owners'.",
|
||||
@@ -1766,7 +1810,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable SSL connection on PostgreSQL Servers.",
|
||||
@@ -1788,7 +1833,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable log_checkpoints on PostgreSQL Servers.",
|
||||
@@ -1810,7 +1856,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable log_connections on PostgreSQL Servers.",
|
||||
@@ -1832,7 +1879,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable log_disconnections on PostgreSQL Servers.",
|
||||
@@ -1854,7 +1902,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable connection_throttling on PostgreSQL Servers.",
|
||||
@@ -1876,7 +1925,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure log_retention_days on PostgreSQL Servers is set to an appropriate value.",
|
||||
@@ -1898,7 +1948,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Disable access from Azure services to PostgreSQL Database Server.",
|
||||
@@ -1918,7 +1969,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Azure Database for PostgreSQL servers should be created with 'infrastructure double encryption' enabled.",
|
||||
@@ -1940,7 +1992,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.4 MySQL Database",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.4 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable SSL connection on MYSQL Servers.",
|
||||
@@ -1962,7 +2015,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.4 MySQL Database",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.4 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure TLS version on MySQL flexible servers is set to the default value.",
|
||||
@@ -1984,7 +2038,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.4 MySQL Database",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.4 MySQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable audit_log_enabled on MySQL Servers.",
|
||||
@@ -2006,7 +2061,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.4 MySQL Database",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.4 MySQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Set audit_log_enabled to include CONNECTION on MySQL Servers.",
|
||||
@@ -2028,7 +2084,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.5 Cosmos DB",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.5 Cosmos DB",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Limiting your Cosmos DB to only communicate on whitelisted networks lowers its attack footprint.",
|
||||
@@ -2050,7 +2107,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.5 Cosmos DB",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.5 Cosmos DB",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Private endpoints limit network traffic to approved sources.",
|
||||
@@ -2072,7 +2130,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.5 Cosmos DB",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.5 Cosmos DB",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Cosmos DB can use tokens or AAD for client authentication which in turn will use Azure RBAC for authorization. Using AAD is significantly more secure because AAD handles the credentials and allows for MFA and centralized management, and the Azure RBAC better integrated with the rest of Azure.",
|
||||
@@ -2094,7 +2153,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable Diagnostic settings for exporting activity logs. Diagnos tic settings are available for each individual resource within a subscription. Settings should be configured for allappropriate resources for your environment.",
|
||||
@@ -2116,7 +2176,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Prerequisite: A Diagnostic Setting must exist. If a Diagnostic Setting does not exist, the navigation and options within this recommendation will not be available. Please review the recommendation at the beginning of this subsection titled: 'Ensure that a 'Diagnostic Setting' exists.' The diagnostic setting should be configured to log the appropriate activities from the control/management plane.",
|
||||
@@ -2138,7 +2199,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The storage account container containing the activity log export should not be publicly accessible.",
|
||||
@@ -2160,7 +2222,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Storage accounts with the activity log exports can be configured to use Customer Managed Keys (CMK).",
|
||||
@@ -2182,7 +2245,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable AuditEvent logging for key vault instances to ensure interactions with key vaults are logged and available.",
|
||||
@@ -2204,7 +2268,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure that network flow logs are captured and fed into a central log analytics workspace.",
|
||||
@@ -2226,7 +2291,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable AppServiceHTTPLogs diagnostic log category for Azure App Service instances to ensure all http requests are captured and centrally logged.",
|
||||
@@ -2248,7 +2314,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Create Policy Assignment event.",
|
||||
@@ -2270,7 +2337,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Delete Policy Assignment event.",
|
||||
@@ -2292,7 +2360,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an Activity Log Alert for the Create or Update Network Security Group event.",
|
||||
@@ -2314,7 +2383,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Delete Network Security Group event.",
|
||||
@@ -2336,7 +2406,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Create or Update Security Solution event.",
|
||||
@@ -2358,7 +2429,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Delete Security Solution event.",
|
||||
@@ -2380,7 +2452,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Create or Update SQL Server Firewall Rule event.",
|
||||
@@ -2402,7 +2475,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the 'Delete SQL Server Firewall Rule.'",
|
||||
@@ -2424,7 +2498,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Create or Update Public IP Addresses rule.",
|
||||
@@ -2446,7 +2521,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Delete Public IP Address rule.",
|
||||
@@ -2466,7 +2542,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.3 Configuring Application Insights",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Resource Logs capture activity to the data access plane while the Activity log is a subscription-level log for the control plane. Resource-level diagnostic logs provide insight into operations that were performed within that resource itself; for example, reading or updating a secret from a Key Vault. Currently, 95 Azure resources support Azure Monitoring (See the more information section for a complete list), including Network Security Groups, Load Balancers, Key Vault, AD, Logic Apps, and CosmosDB. The content of these logs varies by resource type. A number of back-end services were not configured to log and store Resource Logs for certain activities or for a sufficient length. It is crucial that monitoring is correctly configured to log all relevant activities and retain those logs for a sufficient length of time. Given that the mean time to detection in an enterprise is 240 days, a minimum retention period of two years is recommended.",
|
||||
@@ -2486,7 +2562,7 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.3 Configuring Application Insights",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The use of Basic or Free SKUs in Azure whilst cost effective have significant limitations in terms of what can be monitored and what support can be realized from Microsoft. Typically, these SKU’s do not have a service SLA and Microsoft will usually refuse to provide support for them. Consequently Basic/Free SKUs should never be used for production workloads.",
|
||||
@@ -2508,7 +2584,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.3 Configuring Application Insights",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.3 Configuring Application Insights",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Application Insights within Azure act as an Application Performance Monitoring solution providing valuable data into how well an application performs and additional information when performing incident response. The types of log data collected include application metrics, telemetry data, and application trace logging data providing organizations with detailed information about application activity and application transactions. Both data sets help organizations adopt a proactive and retroactive means to handle security and performance related metrics within their modern applications.",
|
||||
|
||||
@@ -494,7 +494,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.1 Security Defaults Security Defaults",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.1 Security Defaults Security Defaults",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Security defaults in Microsoft Entra ID make it easier to be secure and help protect your organization. Security defaults contain preconfigured security settings for common attacks. Security defaults is available to everyone. The goal is to ensure that all organizations have a basic level of security enabled at no extra cost. You may turn on security defaults in the Azure portal.",
|
||||
@@ -516,7 +517,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.1 Security Defaults Security Defaults",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.1 Security Defaults Security Defaults",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable multi-factor authentication for all roles, groups, and users that have write access or permissions to Azure resources. These include custom created objects or built-in roles such as; - Service Co-Administrators - Subscription Owners - Contributors",
|
||||
@@ -538,7 +540,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.1 Security Defaults",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.1 Security Defaults Security Defaults",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable multi-factor authentication for all non-privileged users.",
|
||||
@@ -558,7 +561,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.1 Security Defaults",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.1 Security Defaults Security Defaults",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Do not allow users to remember multi-factor authentication on devices.",
|
||||
@@ -580,7 +584,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Microsoft Entra ID Conditional Access allows an organization to configure `Named locations` and configure whether those locations are trusted or untrusted. These settings provide organizations the means to specify Geographical locations for use in conditional access policies, or define actual IP addresses and IP ranges and whether or not those IP addresses and/or ranges are trusted by the organization.",
|
||||
@@ -600,7 +605,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "**CAUTION**: If these policies are created without first auditing and testing the result, misconfiguration can potentially lock out administrators or create undesired access issues. Conditional Access Policies can be used to block access from geographic locations that are deemed out-of-scope for your organization or application. The scope and variables for this policy should be carefully examined and defined.",
|
||||
@@ -620,7 +626,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "For designated users, they will be prompted to use their multi-factor authentication (MFA) process on login.",
|
||||
@@ -640,7 +647,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "For designated users, they will be prompted to use their multi-factor authentication (MFA) process on logins.",
|
||||
@@ -660,7 +668,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "For designated users, they will be prompted to use their multi-factor authentication (MFA) process on login.",
|
||||
@@ -682,7 +691,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "This recommendation ensures that users accessing the Windows Azure Service Management API (i.e. Azure Powershell, Azure CLI, Azure Resource Manager API, etc.) are required to use multifactor authentication (MFA) credentials when accessing resources through the Windows Azure Service Management API.",
|
||||
@@ -702,7 +712,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "1.2 Conditional Access",
|
||||
"Section": "1.Identity and Access Management",
|
||||
"SubSection": "1.2 Conditional Access",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "This recommendation ensures that users accessing Microsoft Admin Portals (i.e. Microsoft 365 Admin, Microsoft 365 Defender, Exchange Admin Center, Azure Portal, etc.) are required to use multifactor authentication (MFA) credentials when logging into an Admin Portal.",
|
||||
@@ -724,7 +735,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Turning on Microsoft Defender for Servers enables threat detection for Servers, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -746,7 +758,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Turning on Microsoft Defender for App Service enables threat detection for App Service, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -768,7 +781,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Turning on Microsoft Defender for Azure SQL Databases enables threat detection for Managed Instance Azure SQL databases, providing threat intelligence, anomaly detection, and behavior analytics in Microsoft Defender for Cloud.",
|
||||
@@ -790,7 +804,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Turning on Microsoft Defender for SQL servers on machines enables threat detection for SQL servers on machines, providing threat intelligence, anomaly detection, and behavior analytics in Microsoft Defender for Cloud.",
|
||||
@@ -812,7 +827,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Turning on Microsoft Defender for Open-source relational databases enables threat detection for Open-source relational databases, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -834,7 +850,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Microsoft Defender for Azure Cosmos DB scans all incoming network requests for threats to your Azure Cosmos DB resources.",
|
||||
@@ -856,7 +873,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Turning on Microsoft Defender for Storage enables threat detection for Storage, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -878,7 +896,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Turning on Microsoft Defender for Containers enables threat detection for Container Registries including Kubernetes, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud. The following services will be enabled for container instances: - Defender agent in Azure - Azure Policy for Kubernetes - Agentless discovery for Kubernetes - Agentless container vulnerability assessment",
|
||||
@@ -900,7 +919,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Turning on Microsoft Defender for Key Vault enables threat detection for Key Vault, providing threat intelligence, anomaly detection, and behavior analytics in the Microsoft Defender for Cloud.",
|
||||
@@ -922,7 +942,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "[**NOTE:** As of August 1, customers with an existing subscription to Defender for DNS can continue to use the service, but new subscribers will receive alerts about suspicious DNS activity as part of Defender for Servers P2.] Microsoft Defender for DNS scans all network traffic exiting from within a subscription.",
|
||||
@@ -944,7 +965,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Microsoft Defender for Resource Manager scans incoming administrative requests to change your infrastructure from both CLI and the Azure portal.",
|
||||
@@ -966,7 +988,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure that the latest OS patches for all virtual machines are applied.",
|
||||
@@ -988,7 +1011,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "The Microsoft Cloud Security Benchmark (or MCSB) is an Azure Policy Initiative containing many security policies to evaluate resource configuration against best practice recommendations. If a policy in the MCSB is set with effect type `Disabled`, it is not evaluated and may prevent administrators from being informed of valuable security recommendations.",
|
||||
@@ -1010,7 +1034,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable automatic provisioning of the monitoring agent to collect security data.",
|
||||
@@ -1032,7 +1057,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable automatic provisioning of vulnerability assessment for machines on both Azure and hybrid (Arc enabled) machines.",
|
||||
@@ -1052,7 +1078,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable automatic provisioning of the Microsoft Defender for Containers components.",
|
||||
@@ -1074,7 +1101,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable security alert emails to subscription owners.",
|
||||
@@ -1096,7 +1124,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Microsoft Defender for Cloud emails the subscription owners whenever a high-severity alert is triggered for their subscription. You should provide a security contact email address as an additional email address.",
|
||||
@@ -1118,7 +1147,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enables emailing security alerts to the subscription owner or other designated security contact.",
|
||||
@@ -1140,7 +1170,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "This integration setting enables Microsoft Defender for Cloud Apps (formerly 'Microsoft Cloud App Security' or 'MCAS' - see additional info) to communicate with Microsoft Defender for Cloud.",
|
||||
@@ -1162,7 +1193,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "This integration setting enables Microsoft Defender for Endpoint (formerly 'Advanced Threat Protection' or 'ATP' or 'WDATP' - see additional info) to communicate with Microsoft Defender for Cloud. **IMPORTANT:** When enabling integration between DfE & DfC it needs to be taken into account that this will have some side effects that may be undesirable. 1. For server 2019 & above if defender is installed (default for these server SKU's) this will trigger a deployment of the new unified agent and link to any of the extended configuration in the Defender portal. 1. If the new unified agent is required for server SKU's of Win 2016 or Linux and lower there is additional integration that needs to be switched on and agents need to be aligned.",
|
||||
@@ -1182,7 +1214,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.1 Microsoft Defender for Cloud",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.1 Microsoft Defender for Cloud",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "An organization's attack surface is the collection of assets with a public network identifier or URI that an external threat actor can see or access from outside your cloud. It is the set of points on the boundary of a system, a system element, system component, or an environment where an attacker can try to enter, cause an effect on, or extract data from, that system, system element, system component, or environment. The larger the attack surface, the harder it is to protect. This tool can be configured to scan your organization's online infrastructure such as specified domains, hosts, CIDR blocks, and SSL certificates, and store them in an Inventory. Inventory items can be added, reviewed, approved, and removed, and may contain enrichments (insights) and additional information collected from the tool's different scan engines and open-source intelligence sources. A Defender EASM workspace will generate an Inventory of publicly exposed assets by crawling and scanning the internet using _Seeds_ you provide when setting up the tool. Seeds can be FQDNs, IP CIDR blocks, and WHOIS records. Defender EASM will generate Insights within 24-48 hours after Seeds are provided, and these insights include vulnerability data (CVEs), ports and protocols, and weak or expired SSL certificates that could be used by an attacker for reconnaisance or exploitation. Results are classified High/Medium/Low and some of them include proposed mitigations.",
|
||||
@@ -1204,7 +1237,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "2.2 Microsoft Defender for IoT",
|
||||
"Section": "2. Microsoft Defender",
|
||||
"SubSection": "2.2 Microsoft Defender for IoT",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Microsoft Defender for IoT acts as a central security hub for IoT devices within your organization.",
|
||||
@@ -1586,7 +1620,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable auditing on SQL Servers.",
|
||||
@@ -1608,7 +1643,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure that no SQL Databases allow ingress from 0.0.0.0/0 (ANY IP).",
|
||||
@@ -1630,7 +1666,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Transparent Data Encryption (TDE) with Customer-managed key support provides increased transparency and control over the TDE Protector, increased security with an HSM-backed external service, and promotion of separation of duties. With TDE, data is encrypted at rest with a symmetric key (called the database encryption key) stored in the database or data warehouse distribution. To protect this data encryption key (DEK) in the past, only a certificate that the Azure SQL Service managed could be used. Now, with Customer-managed key support for TDE, the DEK can be protected with an asymmetric key that is stored in the Azure Key Vault. The Azure Key Vault is a highly available and scalable cloud-based key store which offers central key management, leverages FIPS 140-2 Level 2 validated hardware security modules (HSMs), and allows separation of management of keys and data for additional security. Based on business needs or criticality of data/databases hosted on a SQL server, it is recommended that the TDE protector is encrypted by a key that is managed by the data owner (Customer-managed key).",
|
||||
@@ -1652,7 +1689,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Use Microsoft Entra authentication for authentication with SQL Database to manage credentials in a single place.",
|
||||
@@ -1674,7 +1712,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable Transparent Data Encryption on every SQL server.",
|
||||
@@ -1696,7 +1735,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.1 SQL Server - Auditing",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.1 SQL Server - Auditing",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "SQL Server Audit Retention should be configured to be greater than 90 days.",
|
||||
@@ -1718,7 +1758,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable `SSL connection` on `PostgreSQL` Servers.",
|
||||
@@ -1740,7 +1781,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable `log_checkpoints` on `PostgreSQL Servers`.",
|
||||
@@ -1762,7 +1804,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable `log_connections` on `PostgreSQL Servers`.",
|
||||
@@ -1784,7 +1827,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable `log_disconnections` on `PostgreSQL Servers`.",
|
||||
@@ -1806,7 +1850,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable `connection_throttling` on `PostgreSQL Servers`.",
|
||||
@@ -1828,7 +1873,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure `log_retention_days` on `PostgreSQL Servers` is set to an appropriate value.",
|
||||
@@ -1850,7 +1896,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Disable access from Azure services to PostgreSQL Database Server.",
|
||||
@@ -1870,7 +1917,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.3 PostgreSQL Database Server. Storage Accounts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Azure Database for PostgreSQL servers should be created with 'infrastructure double encryption' enabled.",
|
||||
@@ -1892,7 +1940,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.4 MySQL Database",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.4 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable `SSL connection` on `MYSQL` Servers.",
|
||||
@@ -1914,7 +1963,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.4 MySQL Database",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.4 MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure `TLS version` on `MySQL flexible` servers is set to use TLS version 1.2 or higher.",
|
||||
@@ -1936,7 +1986,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.4 MySQL Database",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.4 MySQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable audit_log_enabled on MySQL Servers.",
|
||||
@@ -1958,7 +2009,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.4 MySQL Database",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.4 MySQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Set `audit_log_enabled` to include CONNECTION on MySQL Servers.",
|
||||
@@ -1980,7 +2032,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.5 Cosmos DB",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.5 Cosmos DB",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Limiting your Cosmos DB to only communicate on whitelisted networks lowers its attack footprint.",
|
||||
@@ -2002,7 +2055,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.5 Cosmos DB",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.5 Cosmos DB",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Private endpoints limit network traffic to approved sources.",
|
||||
@@ -2024,7 +2078,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "4.5 Cosmos DB",
|
||||
"Section": "4. Database Services",
|
||||
"SubSection": "4.5 Cosmos DB",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Cosmos DB can use tokens or Entra ID for client authentication which in turn will use Azure RBAC for authorization. Using Entra ID is significantly more secure because Entra ID handles the credentials and allows for MFA and centralized management, and the Azure RBAC better integrated with the rest of Azure.",
|
||||
@@ -2086,7 +2141,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable Diagnostic settings for exporting activity logs. Diagnostic settings are available for each individual resource within a subscription. Settings should be configured for all appropriate resources for your environment.",
|
||||
@@ -2108,7 +2164,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "**Prerequisite**: A Diagnostic Setting must exist. If a Diagnostic Setting does not exist, the navigation and options within this recommendation will not be available. Please review the recommendation at the beginning of this subsection titled: Ensure that a 'Diagnostic Setting' exists. The diagnostic setting should be configured to log the appropriate activities from the control/management plane.",
|
||||
@@ -2130,7 +2187,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Storage accounts with the activity log exports can be configured to use Customer Managed Keys (CMK).",
|
||||
@@ -2152,7 +2210,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enable AuditEvent logging for key vault instances to ensure interactions with key vaults are logged and available.",
|
||||
@@ -2174,7 +2233,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Ensure that network flow logs are captured and fed into a central log analytics workspace.",
|
||||
@@ -2196,7 +2256,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.1 Configuring Diagnostic Settings",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.1 Configuring Diagnostic Settings",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "Enable AppServiceHTTPLogs diagnostic log category for Azure App Service instances to ensure all http requests are captured and centrally logged.",
|
||||
@@ -2218,7 +2279,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Create Policy Assignment event.",
|
||||
@@ -2240,7 +2302,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Delete Policy Assignment event.",
|
||||
@@ -2262,7 +2325,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an Activity Log Alert for the Create or Update Network Security Group event.",
|
||||
@@ -2284,7 +2348,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Delete Network Security Group event.",
|
||||
@@ -2306,7 +2371,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Create or Update Security Solution event.",
|
||||
@@ -2328,7 +2394,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Delete Security Solution event.",
|
||||
@@ -2350,7 +2417,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Create or Update SQL Server Firewall Rule event.",
|
||||
@@ -2372,7 +2440,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Delete SQL Server Firewall Rule.",
|
||||
@@ -2394,7 +2463,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Create or Update Public IP Addresses rule.",
|
||||
@@ -2416,7 +2486,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.2 Monitoring using Activity Log Alerts",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Create an activity log alert for the Delete Public IP Address rule.",
|
||||
@@ -2438,7 +2509,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "5.3 Configuring Application Insights. Storage Accounts",
|
||||
"Section": "5. Logging and Monitoring",
|
||||
"SubSection": "5.3 Configuring Application Insights. Storage Accounts",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Application Insights within Azure act as an Application Performance Monitoring solution providing valuable data into how well an application performs and additional information when performing incident response. The types of log data collected include application metrics, telemetry data, and application trace logging data providing organizations with detailed information about application activity and application transactions. Both data sets help organizations adopt a proactive and retroactive means to handle security and performance related metrics within their modern applications.",
|
||||
@@ -3044,7 +3116,7 @@
|
||||
"Id": "9.4",
|
||||
"Description": "Ensure that Register with Entra ID is enabled on App Service",
|
||||
"Checks": [
|
||||
""
|
||||
"app_register_with_identity"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
@@ -3175,9 +3247,7 @@
|
||||
{
|
||||
"Id": "9.10",
|
||||
"Description": "Ensure Azure Key Vaults are Used to Store Secrets",
|
||||
"Checks": [
|
||||
""
|
||||
],
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "9. AppService",
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1292,7 +1292,8 @@
|
||||
"Checks": [],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.1. MySQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.1. MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Manual",
|
||||
"Description": "It is recommended to set a password for the administrative user (`root` by default) to prevent unauthorized access to the SQL database instances. This recommendation is applicable only for MySQL Instances. PostgreSQL does not offer any setting for No Password from the cloud console.",
|
||||
@@ -1313,7 +1314,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.1. MySQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.1. MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `skip_show_database` database flag for Cloud SQL Mysql instance to `on`",
|
||||
@@ -1334,7 +1336,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.1. MySQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.1. MySQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set the `local_infile` database flag for a Cloud SQL MySQL instance to `off`.",
|
||||
@@ -1355,7 +1358,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.2. PostgreSQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_error_verbosity` flag controls the verbosity/details of messages logged. Valid values are: - `TERSE` - `DEFAULT` - `VERBOSE` `TERSE` excludes the logging of `DETAIL`, `HINT`, `QUERY`, and `CONTEXT` error information. `VERBOSE` output includes the `SQLSTATE` error code, source code file name, function name, and line number that generated the error. Ensure an appropriate value is set to 'DEFAULT' or stricter.",
|
||||
@@ -1376,7 +1380,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.2. PostgreSQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_min_error_statement` flag defines the minimum message severity level that are considered as an error statement. Messages for error statements are logged with the SQL statement. Valid values include `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`. Each severity level includes the subsequent levels mentioned above. Ensure a value of `ERROR` or stricter is set.",
|
||||
@@ -1397,7 +1402,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.2. PostgreSQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Profile": "Level 2",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The value of `log_statement` flag determined the SQL statements that are logged. Valid values are: - `none` - `ddl` - `mod` - `all` The value `ddl` logs all data definition statements. The value `mod` logs all ddl statements, plus data-modifying statements. The statements are logged after a basic parsing is done and statement type is determined, thus this does not logs statements with errors. When using extended query protocol, logging occurs after an Execute message is received and values of the Bind parameters are included. A value of 'ddl' is recommended unless otherwise directed by your organization's logging policy.",
|
||||
@@ -1418,7 +1424,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.2. PostgreSQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Instance addresses can be public IP or private IP. Public IP means that the instance is accessible through the public internet. In contrast, instances using only private IP are not accessible through the public internet, but are accessible through a Virtual Private Cloud (VPC). Limiting network access to your database will limit potential attacks.",
|
||||
@@ -1439,7 +1446,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.2. PostgreSQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Ensure `cloudsql.enable_pgaudit` database flag for Cloud SQL PostgreSQL instance is set to `on` to allow for centralized logging.",
|
||||
@@ -1460,7 +1468,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.2. PostgreSQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling the `log_connections` setting causes each attempted connection to the server to be logged, along with successful completion of client authentication. This parameter cannot be changed after the session starts.",
|
||||
@@ -1481,7 +1490,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.2. PostgreSQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "Enabling the `log_disconnections` setting logs the end of each session, including the session duration.",
|
||||
@@ -1502,7 +1512,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.2. PostgreSQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_min_duration_statement` flag defines the minimum amount of execution time of a statement in milliseconds where the total duration of the statement is logged. Ensure that `log_min_duration_statement` is disabled, i.e., a value of `-1` is set.",
|
||||
@@ -1523,7 +1534,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.2. PostgreSQL Database",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.2. PostgreSQL Database",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "The `log_min_messages` flag defines the minimum message severity level that is considered as an error statement. Messages for error statements are logged with the SQL statement. Valid values include `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `INFO`, `NOTICE`, `WARNING`, `ERROR`, `LOG`, `FATAL`, and `PANIC`. Each severity level includes the subsequent levels mentioned above. ERROR is considered the best practice setting. Changes should only be made in accordance with the organization's logging policy.",
|
||||
@@ -1544,7 +1556,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.3. SQL Server",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `3625 (trace flag)` database flag for Cloud SQL SQL Server instance to `on`.",
|
||||
@@ -1565,7 +1578,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.3. SQL Server",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `external scripts enabled` database flag for Cloud SQL SQL Server instance to `off`",
|
||||
@@ -1586,7 +1600,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.3. SQL Server",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `remote access` database flag for Cloud SQL SQL Server instance to `off`.",
|
||||
@@ -1607,7 +1622,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.3. SQL Server",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to check the `user connections` for a Cloud SQL SQL Server instance to ensure that it is not artificially limiting connections.",
|
||||
@@ -1628,7 +1644,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.3. SQL Server",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended that, `user options` database flag for Cloud SQL SQL Server instance should not be configured.",
|
||||
@@ -1649,7 +1666,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.3. SQL Server",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `contained database authentication` database flag for Cloud SQL on the SQL Server instance to `off`.",
|
||||
@@ -1670,7 +1688,8 @@
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
"Section": "6.3. SQL Server",
|
||||
"Section": "6. Cloud SQL Database Services",
|
||||
"SubSection": "6.3. SQL Server",
|
||||
"Profile": "Level 1",
|
||||
"AssessmentStatus": "Automated",
|
||||
"Description": "It is recommended to set `cross db ownership chaining` database flag for Cloud SQL SQL Server instance to `off`.",
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@ from prowler.lib.logger import logger
|
||||
|
||||
timestamp = datetime.today()
|
||||
timestamp_utc = datetime.now(timezone.utc).replace(tzinfo=timezone.utc)
|
||||
prowler_version = "4.5.0"
|
||||
prowler_version = "4.6.3"
|
||||
html_logo_url = "https://github.com/prowler-cloud/prowler/"
|
||||
square_logo_img = "https://prowler.com/wp-content/uploads/logo-html.png"
|
||||
aws_logo = "https://user-images.githubusercontent.com/38561120/235953920-3e3fba08-0795-41dc-b480-9bea57db9f2e.png"
|
||||
|
||||
@@ -72,31 +72,6 @@ aws:
|
||||
# AWS Cloudwatch Configuration
|
||||
# aws.cloudwatch_log_group_retention_policy_specific_days_enabled --> by default is 365 days
|
||||
log_group_retention_days: 365
|
||||
# aws.cloudwatch_log_group_no_critical_pii_in_logs --> see all available entities in https://microsoft.github.io/presidio/supported_entities/
|
||||
critical_pii_entities : [
|
||||
"CREDIT_CARD", # Credit card numbers are highly sensitive financial information.
|
||||
"CRYPTO", # Crypto wallet numbers (e.g., Bitcoin addresses) can give access to cryptocurrency.
|
||||
"IBAN_CODE", # International Bank Account Numbers are critical financial information.
|
||||
"US_BANK_NUMBER", # US bank account numbers are sensitive and should be protected.
|
||||
"US_SSN", # US Social Security Numbers are critical PII used for identity verification.
|
||||
"US_PASSPORT", # US passport numbers can be used for identity theft.
|
||||
"US_ITIN", # US Individual Taxpayer Identification Numbers are sensitive personal identifiers.
|
||||
#"UK_NHS", # UK NHS numbers can be used to access medical records and other private information.
|
||||
#"ES_NIF", # Spanish NIF (Personal tax ID) is critical for identification and tax purposes.
|
||||
#"ES_NIE", # Spanish NIE (Foreigners ID card) is a critical identifier for foreign residents.
|
||||
#"IT_FISCAL_CODE", # Italian personal identification code is sensitive PII for tax and legal purposes.
|
||||
#"IT_PASSPORT", # Italian passport numbers are critical PII.
|
||||
#"IT_IDENTITY_CARD", # Italian identity card numbers are critical for personal identification.
|
||||
#"PL_PESEL", # Polish PESEL numbers are sensitive personal identifiers.
|
||||
#"SG_NRIC_FIN", # Singapore National Registration Identification Card is critical PII.
|
||||
#"AU_ABN", # Australian Business Numbers are critical for business identification.
|
||||
#"AU_TFN", # Australian Tax File Numbers are sensitive and used for taxation purposes.
|
||||
#"AU_MEDICARE", # Australian Medicare numbers are sensitive medical identifiers.
|
||||
#"IN_PAN", # Indian Permanent Account Numbers are critical for tax purposes and identity.
|
||||
#"IN_AADHAAR", # Indian Aadhaar numbers are highly sensitive and serve as a universal identity number.
|
||||
#"FI_PERSONAL_IDENTITY_CODE" # Finnish Personal Identity Code is sensitive PII for personal identification.
|
||||
]
|
||||
pii_language: "en" # Language for recognizing PII entities
|
||||
|
||||
# AWS AppStream Session Configuration
|
||||
# aws.appstream_fleet_session_idle_disconnect_timeout
|
||||
@@ -393,6 +368,11 @@ aws:
|
||||
# Maximum number of days a secret should be rotated
|
||||
max_days_secret_unrotated: 90
|
||||
|
||||
# AWS Kinesis Configuration
|
||||
# Minimum retention period in hours for Kinesis streams
|
||||
min_kinesis_stream_retention_hours: 168 # 7 days
|
||||
|
||||
|
||||
# Azure Configuration
|
||||
azure:
|
||||
# Azure Network Configuration
|
||||
|
||||
@@ -111,7 +111,7 @@ def load_checks_to_execute(
|
||||
):
|
||||
checks_to_execute.add(check_name)
|
||||
# Only execute threat detection checks if threat-detection category is set
|
||||
if categories and categories != [] and "threat-detection" not in categories:
|
||||
if not categories or "threat-detection" not in categories:
|
||||
for threat_detection_check in check_categories.get("threat-detection", []):
|
||||
checks_to_execute.discard(threat_detection_check)
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ class CIS_Requirement_Attribute(BaseModel):
|
||||
"""CIS Requirement Attribute"""
|
||||
|
||||
Section: str
|
||||
SubSection: Optional[str]
|
||||
Profile: CIS_Requirement_Attribute_Profile
|
||||
AssessmentStatus: CIS_Requirement_Attribute_AssessmentStatus
|
||||
Description: str
|
||||
|
||||
@@ -322,8 +322,9 @@ class CheckMetadata(BaseModel):
|
||||
checks = set()
|
||||
|
||||
if service:
|
||||
if service == "lambda":
|
||||
service = "awslambda"
|
||||
# This is a special case for the AWS provider since `lambda` is a reserved keyword in Python
|
||||
if service == "awslambda":
|
||||
service = "lambda"
|
||||
checks = {
|
||||
check_name
|
||||
for check_name, check_metadata in bulk_checks_metadata.items()
|
||||
|
||||
@@ -94,11 +94,12 @@ def get_cis_table(
|
||||
print(
|
||||
f"\nCompliance Status of {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Framework:"
|
||||
)
|
||||
total_findings_count = len(fail_count) + len(pass_count) + len(muted_count)
|
||||
overview_table = [
|
||||
[
|
||||
f"{Fore.RED}{round(len(fail_count) / len(findings) * 100, 2)}% ({len(fail_count)}) FAIL{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / len(findings) * 100, 2)}% ({len(pass_count)}) PASS{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / len(findings) * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
f"{Fore.RED}{round(len(fail_count) / total_findings_count * 100, 2)}% ({len(fail_count)}) FAIL{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / total_findings_count * 100, 2)}% ({len(pass_count)}) PASS{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / total_findings_count * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
]
|
||||
]
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
|
||||
@@ -48,6 +48,7 @@ class AWSCIS(ComplianceOutput):
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
@@ -78,6 +79,7 @@ class AWSCIS(ComplianceOutput):
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
|
||||
@@ -42,12 +42,13 @@ class AzureCIS(ComplianceOutput):
|
||||
compliance_row = AzureCISModel(
|
||||
Provider=finding.provider,
|
||||
Description=compliance.Description,
|
||||
Subscription=finding.account_name,
|
||||
SubscriptionId=finding.account_uid,
|
||||
Location=finding.region,
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
@@ -73,12 +74,13 @@ class AzureCIS(ComplianceOutput):
|
||||
compliance_row = AzureCISModel(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
Subscription="",
|
||||
SubscriptionId="",
|
||||
Location="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
|
||||
@@ -48,6 +48,7 @@ class GCPCIS(ComplianceOutput):
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
@@ -78,6 +79,7 @@ class GCPCIS(ComplianceOutput):
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
|
||||
@@ -50,6 +50,7 @@ class KubernetesCIS(ComplianceOutput):
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
@@ -81,6 +82,7 @@ class KubernetesCIS(ComplianceOutput):
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Section=attribute.Section,
|
||||
Requirements_Attributes_SubSection=attribute.SubSection,
|
||||
Requirements_Attributes_Profile=attribute.Profile,
|
||||
Requirements_Attributes_AssessmentStatus=attribute.AssessmentStatus,
|
||||
Requirements_Attributes_Description=attribute.Description,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
@@ -14,6 +16,7 @@ class AWSCISModel(BaseModel):
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_SubSection: Optional[str]
|
||||
Requirements_Attributes_Profile: str
|
||||
Requirements_Attributes_AssessmentStatus: str
|
||||
Requirements_Attributes_Description: str
|
||||
@@ -38,12 +41,13 @@ class AzureCISModel(BaseModel):
|
||||
|
||||
Provider: str
|
||||
Description: str
|
||||
Subscription: str
|
||||
SubscriptionId: str
|
||||
Location: str
|
||||
AssessmentDate: str
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_SubSection: Optional[str]
|
||||
Requirements_Attributes_Profile: str
|
||||
Requirements_Attributes_AssessmentStatus: str
|
||||
Requirements_Attributes_Description: str
|
||||
@@ -75,6 +79,7 @@ class GCPCISModel(BaseModel):
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_SubSection: Optional[str]
|
||||
Requirements_Attributes_Profile: str
|
||||
Requirements_Attributes_AssessmentStatus: str
|
||||
Requirements_Attributes_Description: str
|
||||
@@ -105,6 +110,7 @@ class KubernetesCISModel(BaseModel):
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_Section: str
|
||||
Requirements_Attributes_SubSection: Optional[str]
|
||||
Requirements_Attributes_Profile: str
|
||||
Requirements_Attributes_AssessmentStatus: str
|
||||
Requirements_Attributes_Description: str
|
||||
|
||||
@@ -30,7 +30,7 @@ def get_ens_table(
|
||||
check = bulk_checks_metadata[finding.check_metadata.CheckID]
|
||||
check_compliances = check.Compliance
|
||||
for compliance in check_compliances:
|
||||
if compliance.Framework == "ENS" and compliance.Provider == "AWS":
|
||||
if compliance.Framework == "ENS":
|
||||
for requirement in compliance.Requirements:
|
||||
for attribute in requirement.Attributes:
|
||||
marco_categoria = f"{attribute.Marco}/{attribute.Categoria}"
|
||||
@@ -95,11 +95,12 @@ def get_ens_table(
|
||||
print(
|
||||
f"\nEstado de Cumplimiento de {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL}:"
|
||||
)
|
||||
total_findings_count = len(fail_count) + len(pass_count) + len(muted_count)
|
||||
overview_table = [
|
||||
[
|
||||
f"{Fore.RED}{round(len(fail_count) / len(findings) * 100, 2)}% ({len(fail_count)}) NO CUMPLE{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / len(findings) * 100, 2)}% ({len(pass_count)}) CUMPLE{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / len(findings) * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
f"{Fore.RED}{round(len(fail_count) / total_findings_count * 100, 2)}% ({len(fail_count)}) NO CUMPLE{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / total_findings_count * 100, 2)}% ({len(pass_count)}) CUMPLE{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / total_findings_count * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
]
|
||||
]
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
from prowler.lib.check.compliance_models import Compliance
|
||||
from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput
|
||||
from prowler.lib.outputs.compliance.ens.models import AzureENSModel
|
||||
from prowler.lib.outputs.finding import Finding
|
||||
|
||||
|
||||
class AzureENS(ComplianceOutput):
|
||||
"""
|
||||
This class represents the Azure ENS compliance output.
|
||||
|
||||
Attributes:
|
||||
- _data (list): A list to store transformed data from findings.
|
||||
- _file_descriptor (TextIOWrapper): A file descriptor to write data to a file.
|
||||
|
||||
Methods:
|
||||
- transform: Transforms findings into Azure ENS compliance format.
|
||||
"""
|
||||
|
||||
def transform(
|
||||
self,
|
||||
findings: list[Finding],
|
||||
compliance: Compliance,
|
||||
compliance_name: str,
|
||||
) -> None:
|
||||
"""
|
||||
Transforms a list of findings into AWS ENS compliance format.
|
||||
|
||||
Parameters:
|
||||
- findings (list): A list of findings.
|
||||
- compliance (Compliance): A compliance model.
|
||||
- compliance_name (str): The name of the compliance model.
|
||||
|
||||
Returns:
|
||||
- None
|
||||
"""
|
||||
for finding in findings:
|
||||
# Get the compliance requirements for the finding
|
||||
finding_requirements = finding.compliance.get(compliance_name, [])
|
||||
for requirement in compliance.Requirements:
|
||||
if requirement.Id in finding_requirements:
|
||||
for attribute in requirement.Attributes:
|
||||
compliance_row = AzureENSModel(
|
||||
Provider=finding.provider,
|
||||
Description=compliance.Description,
|
||||
SubscriptionId=finding.account_name,
|
||||
Location=finding.region,
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_IdGrupoControl=attribute.IdGrupoControl,
|
||||
Requirements_Attributes_Marco=attribute.Marco,
|
||||
Requirements_Attributes_Categoria=attribute.Categoria,
|
||||
Requirements_Attributes_DescripcionControl=attribute.DescripcionControl,
|
||||
Requirements_Attributes_Nivel=attribute.Nivel,
|
||||
Requirements_Attributes_Tipo=attribute.Tipo,
|
||||
Requirements_Attributes_Dimensiones=",".join(
|
||||
attribute.Dimensiones
|
||||
),
|
||||
Requirements_Attributes_ModoEjecucion=attribute.ModoEjecucion,
|
||||
Requirements_Attributes_Dependencias=",".join(
|
||||
attribute.Dependencias
|
||||
),
|
||||
Status=finding.status,
|
||||
StatusExtended=finding.status_extended,
|
||||
ResourceId=finding.resource_uid,
|
||||
ResourceName=finding.resource_name,
|
||||
CheckId=finding.check_id,
|
||||
Muted=finding.muted,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
# Add manual requirements to the compliance output
|
||||
for requirement in compliance.Requirements:
|
||||
if not requirement.Checks:
|
||||
for attribute in requirement.Attributes:
|
||||
compliance_row = AzureENSModel(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
SubscriptionId="",
|
||||
Location="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_IdGrupoControl=attribute.IdGrupoControl,
|
||||
Requirements_Attributes_Marco=attribute.Marco,
|
||||
Requirements_Attributes_Categoria=attribute.Categoria,
|
||||
Requirements_Attributes_DescripcionControl=attribute.DescripcionControl,
|
||||
Requirements_Attributes_Nivel=attribute.Nivel,
|
||||
Requirements_Attributes_Tipo=attribute.Tipo,
|
||||
Requirements_Attributes_Dimensiones=",".join(
|
||||
attribute.Dimensiones
|
||||
),
|
||||
Requirements_Attributes_ModoEjecucion=attribute.ModoEjecucion,
|
||||
Requirements_Attributes_Dependencias=",".join(
|
||||
attribute.Dependencias
|
||||
),
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
@@ -0,0 +1,103 @@
|
||||
from prowler.lib.check.compliance_models import Compliance
|
||||
from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput
|
||||
from prowler.lib.outputs.compliance.ens.models import GCPENSModel
|
||||
from prowler.lib.outputs.finding import Finding
|
||||
|
||||
|
||||
class GCPENS(ComplianceOutput):
|
||||
"""
|
||||
This class represents the GCP ENS compliance output.
|
||||
|
||||
Attributes:
|
||||
- _data (list): A list to store transformed data from findings.
|
||||
- _file_descriptor (TextIOWrapper): A file descriptor to write data to a file.
|
||||
|
||||
Methods:
|
||||
- transform: Transforms findings into GCP ENS compliance format.
|
||||
"""
|
||||
|
||||
def transform(
|
||||
self,
|
||||
findings: list[Finding],
|
||||
compliance: Compliance,
|
||||
compliance_name: str,
|
||||
) -> None:
|
||||
"""
|
||||
Transforms a list of findings into AWS ENS compliance format.
|
||||
|
||||
Parameters:
|
||||
- findings (list): A list of findings.
|
||||
- compliance (Compliance): A compliance model.
|
||||
- compliance_name (str): The name of the compliance model.
|
||||
|
||||
Returns:
|
||||
- None
|
||||
"""
|
||||
for finding in findings:
|
||||
# Get the compliance requirements for the finding
|
||||
finding_requirements = finding.compliance.get(compliance_name, [])
|
||||
for requirement in compliance.Requirements:
|
||||
if requirement.Id in finding_requirements:
|
||||
for attribute in requirement.Attributes:
|
||||
compliance_row = GCPENSModel(
|
||||
Provider=finding.provider,
|
||||
Description=compliance.Description,
|
||||
ProjectId=finding.account_uid,
|
||||
Location=finding.region,
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_IdGrupoControl=attribute.IdGrupoControl,
|
||||
Requirements_Attributes_Marco=attribute.Marco,
|
||||
Requirements_Attributes_Categoria=attribute.Categoria,
|
||||
Requirements_Attributes_DescripcionControl=attribute.DescripcionControl,
|
||||
Requirements_Attributes_Nivel=attribute.Nivel,
|
||||
Requirements_Attributes_Tipo=attribute.Tipo,
|
||||
Requirements_Attributes_Dimensiones=",".join(
|
||||
attribute.Dimensiones
|
||||
),
|
||||
Requirements_Attributes_ModoEjecucion=attribute.ModoEjecucion,
|
||||
Requirements_Attributes_Dependencias=",".join(
|
||||
attribute.Dependencias
|
||||
),
|
||||
Status=finding.status,
|
||||
StatusExtended=finding.status_extended,
|
||||
ResourceId=finding.resource_uid,
|
||||
ResourceName=finding.resource_name,
|
||||
CheckId=finding.check_id,
|
||||
Muted=finding.muted,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
# Add manual requirements to the compliance output
|
||||
for requirement in compliance.Requirements:
|
||||
if not requirement.Checks:
|
||||
for attribute in requirement.Attributes:
|
||||
compliance_row = GCPENSModel(
|
||||
Provider=compliance.Provider.lower(),
|
||||
Description=compliance.Description,
|
||||
ProjectId="",
|
||||
Location="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_IdGrupoControl=attribute.IdGrupoControl,
|
||||
Requirements_Attributes_Marco=attribute.Marco,
|
||||
Requirements_Attributes_Categoria=attribute.Categoria,
|
||||
Requirements_Attributes_DescripcionControl=attribute.DescripcionControl,
|
||||
Requirements_Attributes_Nivel=attribute.Nivel,
|
||||
Requirements_Attributes_Tipo=attribute.Tipo,
|
||||
Requirements_Attributes_Dimensiones=",".join(
|
||||
attribute.Dimensiones
|
||||
),
|
||||
Requirements_Attributes_ModoEjecucion=attribute.ModoEjecucion,
|
||||
Requirements_Attributes_Dependencias=",".join(
|
||||
attribute.Dependencias
|
||||
),
|
||||
Status="MANUAL",
|
||||
StatusExtended="Manual check",
|
||||
ResourceId="manual_check",
|
||||
ResourceName="Manual check",
|
||||
CheckId="manual",
|
||||
Muted=False,
|
||||
)
|
||||
self._data.append(compliance_row)
|
||||
@@ -28,3 +28,61 @@ class AWSENSModel(BaseModel):
|
||||
CheckId: str
|
||||
Muted: bool
|
||||
ResourceName: str
|
||||
|
||||
|
||||
class AzureENSModel(BaseModel):
|
||||
"""
|
||||
AzureENSModel generates a finding's output in CSV ENS format for Azure.
|
||||
"""
|
||||
|
||||
Provider: str
|
||||
Description: str
|
||||
SubscriptionId: str
|
||||
Location: str
|
||||
AssessmentDate: str
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_IdGrupoControl: str
|
||||
Requirements_Attributes_Marco: str
|
||||
Requirements_Attributes_Categoria: str
|
||||
Requirements_Attributes_DescripcionControl: str
|
||||
Requirements_Attributes_Nivel: str
|
||||
Requirements_Attributes_Tipo: str
|
||||
Requirements_Attributes_Dimensiones: str
|
||||
Requirements_Attributes_ModoEjecucion: str
|
||||
Requirements_Attributes_Dependencias: str
|
||||
Status: str
|
||||
StatusExtended: str
|
||||
ResourceId: str
|
||||
CheckId: str
|
||||
Muted: bool
|
||||
ResourceName: str
|
||||
|
||||
|
||||
class GCPENSModel(BaseModel):
|
||||
"""
|
||||
GCPENSModel generates a finding's output in CSV ENS format for GCP.
|
||||
"""
|
||||
|
||||
Provider: str
|
||||
Description: str
|
||||
ProjectId: str
|
||||
Location: str
|
||||
AssessmentDate: str
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_IdGrupoControl: str
|
||||
Requirements_Attributes_Marco: str
|
||||
Requirements_Attributes_Categoria: str
|
||||
Requirements_Attributes_DescripcionControl: str
|
||||
Requirements_Attributes_Nivel: str
|
||||
Requirements_Attributes_Tipo: str
|
||||
Requirements_Attributes_Dimensiones: str
|
||||
Requirements_Attributes_ModoEjecucion: str
|
||||
Requirements_Attributes_Dependencias: str
|
||||
Status: str
|
||||
StatusExtended: str
|
||||
ResourceId: str
|
||||
CheckId: str
|
||||
Muted: bool
|
||||
ResourceName: str
|
||||
|
||||
@@ -39,11 +39,12 @@ def get_generic_compliance_table(
|
||||
print(
|
||||
f"\nCompliance Status of {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Framework:"
|
||||
)
|
||||
total_findings_count = len(fail_count) + len(pass_count) + len(muted_count)
|
||||
overview_table = [
|
||||
[
|
||||
f"{Fore.RED}{round(len(fail_count) / len(findings) * 100, 2)}% ({len(fail_count)}) FAIL{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / len(findings) * 100, 2)}% ({len(pass_count)}) PASS{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / len(findings) * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
f"{Fore.RED}{round(len(fail_count) / total_findings_count * 100, 2)}% ({len(fail_count)}) FAIL{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / total_findings_count * 100, 2)}% ({len(pass_count)}) PASS{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / total_findings_count * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
]
|
||||
]
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
|
||||
@@ -45,6 +45,8 @@ class AWSISO27001(ComplianceOutput):
|
||||
AccountId=finding.account_uid,
|
||||
Region=finding.region,
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Category=attribute.Category,
|
||||
Requirements_Attributes_Objetive_ID=attribute.Objetive_ID,
|
||||
Requirements_Attributes_Objetive_Name=attribute.Objetive_Name,
|
||||
@@ -67,6 +69,8 @@ class AWSISO27001(ComplianceOutput):
|
||||
AccountId="",
|
||||
Region="",
|
||||
AssessmentDate=str(finding.timestamp),
|
||||
Requirements_Id=requirement.Id,
|
||||
Requirements_Description=requirement.Description,
|
||||
Requirements_Attributes_Category=attribute.Category,
|
||||
Requirements_Attributes_Objetive_ID=attribute.Objetive_ID,
|
||||
Requirements_Attributes_Objetive_Name=attribute.Objetive_Name,
|
||||
|
||||
@@ -11,6 +11,8 @@ class AWSISO27001Model(BaseModel):
|
||||
AccountId: str
|
||||
Region: str
|
||||
AssessmentDate: str
|
||||
Requirements_Id: str
|
||||
Requirements_Description: str
|
||||
Requirements_Attributes_Category: str
|
||||
Requirements_Attributes_Objetive_ID: str
|
||||
Requirements_Attributes_Objetive_Name: str
|
||||
|
||||
@@ -61,11 +61,12 @@ def get_kisa_ismsp_table(
|
||||
print(
|
||||
f"\nCompliance Status of {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Framework:"
|
||||
)
|
||||
total_findings_count = len(fail_count) + len(pass_count) + len(muted_count)
|
||||
overview_table = [
|
||||
[
|
||||
f"{Fore.RED}{round(len(fail_count) / len(findings) * 100, 2)}% ({len(fail_count)}) FAIL{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / len(findings) * 100, 2)}% ({len(pass_count)}) PASS{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / len(findings) * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
f"{Fore.RED}{round(len(fail_count) / total_findings_count * 100, 2)}% ({len(fail_count)}) FAIL{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / total_findings_count * 100, 2)}% ({len(pass_count)}) PASS{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / total_findings_count * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
]
|
||||
]
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
|
||||
@@ -69,11 +69,12 @@ def get_mitre_attack_table(
|
||||
print(
|
||||
f"\nCompliance Status of {Fore.YELLOW}{compliance_framework.upper()}{Style.RESET_ALL} Framework:"
|
||||
)
|
||||
total_findings_count = len(fail_count) + len(pass_count) + len(muted_count)
|
||||
overview_table = [
|
||||
[
|
||||
f"{Fore.RED}{round(len(fail_count) / len(findings) * 100, 2)}% ({len(fail_count)}) FAIL{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / len(findings) * 100, 2)}% ({len(pass_count)}) PASS{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / len(findings) * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
f"{Fore.RED}{round(len(fail_count) / total_findings_count * 100, 2)}% ({len(fail_count)}) FAIL{Style.RESET_ALL}",
|
||||
f"{Fore.GREEN}{round(len(pass_count) / total_findings_count * 100, 2)}% ({len(pass_count)}) PASS{Style.RESET_ALL}",
|
||||
f"{orange_color}{round(len(muted_count) / total_findings_count * 100, 2)}% ({len(muted_count)}) MUTED{Style.RESET_ALL}",
|
||||
]
|
||||
]
|
||||
print(tabulate(overview_table, tablefmt="rounded_grid"))
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
from prowler.exceptions.exceptions import ProwlerException
|
||||
|
||||
|
||||
# Exceptions codes from 9000 to 9999 are reserved for Jira exceptions
|
||||
class JiraBaseException(ProwlerException):
|
||||
"""Base class for Jira exceptions."""
|
||||
|
||||
JIRA_ERROR_CODES = {
|
||||
(9000, "JiraNoProjectsError"): {
|
||||
"message": "No projects were found in Jira.",
|
||||
"remediation": "Please create a project in Jira.",
|
||||
},
|
||||
(9001, "JiraAuthenticationError"): {
|
||||
"message": "Failed to authenticate with Jira.",
|
||||
"remediation": "Please check the connection settings and permissions and try again. Needed scopes are: read:jira-user read:jira-work write:jira-work",
|
||||
},
|
||||
(9002, "JiraTestConnectionError"): {
|
||||
"message": "Failed to connect to Jira.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9003, "JiraCreateIssueError"): {
|
||||
"message": "Failed to create an issue in Jira.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9004, "JiraGetProjectsError"): {
|
||||
"message": "Failed to get projects from Jira.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9005, "JiraGetCloudIDError"): {
|
||||
"message": "Failed to get the cloud ID from Jira.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9006, "JiraGetCloudIDNoResourcesError"): {
|
||||
"message": "No resources were found in Jira.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9007, "JiraGetCloudIDResponseError"): {
|
||||
"message": "Failed to get the cloud ID from Jira.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9008, "JiraRefreshTokenResponseError"): {
|
||||
"message": "Failed to refresh the access token, response code did not match 200.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9009, "JiraRefreshTokenError"): {
|
||||
"message": "Failed to refresh the access token.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9010, "JiraGetAccessTokenError"): {
|
||||
"message": "Failed to get the access token.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9011, "JiraGetAuthResponseError"): {
|
||||
"message": "Failed to authenticate with Jira.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9012, "JiraGetProjectsResponseError"): {
|
||||
"message": "Failed to get projects from Jira, response code did not match 200.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9013, "JiraSendFindingsResponseError"): {
|
||||
"message": "Failed to send findings to Jira, response code did not match 201.",
|
||||
"remediation": "Please check the finding format and try again.",
|
||||
},
|
||||
(9014, "JiraGetAvailableIssueTypesError"): {
|
||||
"message": "Failed to get available issue types from Jira.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9015, "JiraGetAvailableIssueTypesResponseError"): {
|
||||
"message": "Failed to get available issue types from Jira, response code did not match 200.",
|
||||
"remediation": "Please check the connection settings and permissions and try again.",
|
||||
},
|
||||
(9016, "JiraInvalidIssueTypeError"): {
|
||||
"message": "The issue type is invalid.",
|
||||
"remediation": "Please check the issue type and try again.",
|
||||
},
|
||||
(9017, "JiraNoTokenError"): {
|
||||
"message": "No token was found.",
|
||||
"remediation": "Make sure the token is set when using the Jira integration.",
|
||||
},
|
||||
(9018, "JiraInvalidProjectKeyError"): {
|
||||
"message": "The project key is invalid.",
|
||||
"remediation": "Please check the project key and try again.",
|
||||
},
|
||||
}
|
||||
|
||||
def __init__(self, code, file=None, original_exception=None, message=None):
|
||||
module = "Jira"
|
||||
error_info = self.JIRA_ERROR_CODES.get((code, self.__class__.__name__))
|
||||
if message:
|
||||
error_info["message"] = message
|
||||
super().__init__(
|
||||
code=code,
|
||||
source=module,
|
||||
file=file,
|
||||
original_exception=original_exception,
|
||||
error_info=error_info,
|
||||
)
|
||||
|
||||
|
||||
class JiraNoProjectsError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9000, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraAuthenticationError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9001, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraTestConnectionError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9002, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraCreateIssueError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9003, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraGetProjectsError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9004, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraGetCloudIDError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9005, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraGetCloudIDNoResourcesError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9006, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraGetCloudIDResponseError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9007, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraRefreshTokenResponseError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9008, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraRefreshTokenError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9009, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraGetAccessTokenError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9010, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraGetAuthResponseError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9011, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraGetProjectsResponseError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9012, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraSendFindingsResponseError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9013, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraGetAvailableIssueTypesError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9014, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraGetAvailableIssueTypesResponseError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9015, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraInvalidIssueTypeError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9016, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraNoTokenError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9017, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class JiraInvalidProjectKeyError(JiraBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9018, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
from py_ocsf_models.events.base_event import SeverityID, StatusID
|
||||
@@ -68,7 +69,11 @@ class OCSF(Output):
|
||||
activity_name=finding_activity.name,
|
||||
finding_info=FindingInformation(
|
||||
created_time_dt=finding.timestamp,
|
||||
created_time=int(finding.timestamp.timestamp()),
|
||||
created_time=(
|
||||
int(finding.timestamp.timestamp())
|
||||
if isinstance(finding.timestamp, datetime)
|
||||
else finding.timestamp
|
||||
),
|
||||
desc=finding.metadata.Description,
|
||||
title=finding.metadata.CheckTitle,
|
||||
uid=finding.uid,
|
||||
@@ -77,7 +82,11 @@ class OCSF(Output):
|
||||
types=finding.metadata.CheckType,
|
||||
),
|
||||
time_dt=finding.timestamp,
|
||||
time=int(finding.timestamp.timestamp()),
|
||||
time=(
|
||||
int(finding.timestamp.timestamp())
|
||||
if isinstance(finding.timestamp, datetime)
|
||||
else finding.timestamp
|
||||
),
|
||||
remediation=Remediation(
|
||||
desc=finding.metadata.Remediation.Recommendation.Text,
|
||||
references=list(
|
||||
|
||||
@@ -185,7 +185,7 @@ class Slack:
|
||||
"accessory": {
|
||||
"type": "button",
|
||||
"text": {"type": "plain_text", "text": "Prowler :slack:"},
|
||||
"url": "https://join.slack.com/t/prowler-workspace/shared_invite/zt-1hix76xsl-2uq222JIXrC7Q8It~9ZNog",
|
||||
"url": "https://goto.prowler.com/slack",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@ from prowler.providers.aws.exceptions.exceptions import (
|
||||
AWSIAMRoleARNPartitionEmptyError,
|
||||
AWSIAMRoleARNRegionNotEmtpyError,
|
||||
AWSIAMRoleARNServiceNotIAMnorSTSError,
|
||||
AWSInvalidPartitionError,
|
||||
AWSInvalidProviderIdError,
|
||||
AWSNoCredentialsError,
|
||||
AWSProfileNotFoundError,
|
||||
@@ -62,12 +63,32 @@ from prowler.providers.aws.models import (
|
||||
AWSMFAInfo,
|
||||
AWSOrganizationsInfo,
|
||||
AWSSession,
|
||||
Partition,
|
||||
)
|
||||
from prowler.providers.common.models import Audit_Metadata, Connection
|
||||
from prowler.providers.common.provider import Provider
|
||||
|
||||
|
||||
class AwsProvider(Provider):
|
||||
"""
|
||||
AwsProvider class is the main class for the AWS provider.
|
||||
|
||||
This class is responsible for initializing the AWS provider, setting up the AWS session, validating the AWS
|
||||
credentials, assuming an IAM role, getting the AWS Organizations metadata, and setting the AWS identity.
|
||||
|
||||
Attributes:
|
||||
_type (str): The provider type.
|
||||
_identity (AWSIdentityInfo): The AWS provider identity information.
|
||||
_session (AWSSession): The AWS provider session.
|
||||
_organizations_metadata (AWSOrganizationsInfo): The AWS Organizations metadata.
|
||||
_audit_resources (list): The list of resources to audit.
|
||||
_audit_config (dict): The audit configuration.
|
||||
_scan_unused_services (bool): A boolean indicating whether to scan unused services.
|
||||
_enabled_regions (set): The set of enabled regions.
|
||||
_mutelist (AWSMutelist): The AWS provider mutelist.
|
||||
audit_metadata (Audit_Metadata): The audit metadata.
|
||||
"""
|
||||
|
||||
_type: str = "aws"
|
||||
_identity: AWSIdentityInfo
|
||||
_session: AWSSession
|
||||
@@ -106,10 +127,10 @@ class AwsProvider(Provider):
|
||||
"""
|
||||
Initializes the AWS provider.
|
||||
|
||||
Arguments:
|
||||
Args:
|
||||
- retries_max_attempts: The maximum number of retries for the AWS client.
|
||||
- role_arn: The ARN of the IAM role to assume.
|
||||
- session_duration: The duration of the session in seconds.
|
||||
- session_duration: The duration of the session in seconds, between 900 and 43200.
|
||||
- external_id: The external ID to use when assuming the IAM role.
|
||||
- role_session_name: The name of the session when assuming the IAM role.
|
||||
- mfa: A boolean indicating whether MFA is enabled.
|
||||
@@ -134,6 +155,37 @@ class AwsProvider(Provider):
|
||||
- ArgumentTypeError: If the input external ID is invalid.
|
||||
- ArgumentTypeError: If the input role session name is invalid.
|
||||
|
||||
Usage:
|
||||
- Boto3 is used so we follow their credential setup process:
|
||||
- Authentication: Make sure you have properly configured your AWS CLI with a valid Access Key and Region or declare the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.
|
||||
- aws configure
|
||||
or
|
||||
- export AWS_ACCESS_KEY_ID="ASXXXXXXX"
|
||||
export AWS_SECRET_ACCESS_KEY="XXXXXXXXX"
|
||||
export AWS_SESSION_TOKEN="XXXXXXXXX"
|
||||
- To create a new aws object you can use:
|
||||
- aws = AwsProvider()
|
||||
- aws = AwsProvider(aws_access_key_id="ASXXXXXXX", aws_secret_access_key="XXXXXXXXX", aws_session_token="XXXXXXXXX")
|
||||
- Profile: If you have multiple profiles in your AWS CLI configuration, you can specify the profile to use:
|
||||
- aws = AwsProvider(profile="profile_name")
|
||||
- MFA: If you have MFA enabled you can specify it:
|
||||
- aws = AwsProvider(mfa=True)
|
||||
* Note: If you have MFA enabled you will be prompted to enter the MFA ARN and the MFA TOTP code.
|
||||
* Note: Take into account that you can use static credentials or a profile, with the combination of MFA.
|
||||
|
||||
- Assume Role: *Requires authentication.* Prowler can be used against multiple accounts using IAM Assume Role features depending on each use case:
|
||||
- Set up a custom profile inside your AWS CLI configuration file:
|
||||
- [profile profile_name]
|
||||
role_arn = arn:aws:iam::123456789012:role/role_name
|
||||
- aws = AwsProvider(profile="profile_name")
|
||||
- Use role_arn directly:
|
||||
- aws = AwsProvider(role_arn="arn:aws:iam::123456789012:role/role_name")
|
||||
- Use role_arn with session duration(in seconds, by default 3600) and external ID:
|
||||
- aws = AwsProvider(role_arn="arn:aws:iam::123456789012:role/role_name", session_duration=3600, external_id="external_id")
|
||||
- Use custom role session name:
|
||||
- aws = AwsProvider(role_arn="arn:aws:iam::123456789012:role/role_name", role_session_name="custom_session_name")
|
||||
* Note: You can use the combination of MFA with Assume Role.
|
||||
- aws = AwsProvider(role_arn="arn:aws:iam::123456789012:role/role_name", mfa=True)
|
||||
"""
|
||||
|
||||
logger.info("Initializing AWS provider ...")
|
||||
@@ -367,7 +419,7 @@ class AwsProvider(Provider):
|
||||
"""
|
||||
get_organizations_info returns a AWSOrganizationsInfo object if the account to be audited is a delegated administrator for AWS Organizations or if the AWS Organizations Role ARN (--organizations-role) is passed.
|
||||
|
||||
Arguments:
|
||||
Args:
|
||||
- organizations_session: needs to be a Session object with permissions to do organizations:DescribeAccount and organizations:ListTagsForResource.
|
||||
- aws_account_id: is the AWS Account ID from which we want to get the AWS Organizations account metadata
|
||||
|
||||
@@ -424,6 +476,21 @@ class AwsProvider(Provider):
|
||||
regions: set,
|
||||
profile_region: str,
|
||||
) -> AWSIdentityInfo:
|
||||
"""
|
||||
set_identity sets the AWS provider identity information.
|
||||
|
||||
Args:
|
||||
- caller_identity: The AWS caller identity information.
|
||||
- profile: The AWS CLI profile name.
|
||||
- regions: A set of regions to audit.
|
||||
- profile_region: The AWS CLI profile region.
|
||||
|
||||
Returns:
|
||||
- AWSIdentityInfo: The AWS provider identity information.
|
||||
|
||||
Raises:
|
||||
- AWSInvalidProviderIdError: If the AWS provider ID is invalid.
|
||||
"""
|
||||
logger.info(f"Original AWS Caller Identity UserId: {caller_identity.user_id}")
|
||||
logger.info(f"Original AWS Caller Identity ARN: {caller_identity.arn}")
|
||||
|
||||
@@ -447,6 +514,22 @@ class AwsProvider(Provider):
|
||||
aws_secret_access_key: str = None,
|
||||
aws_session_token: Optional[str] = None,
|
||||
) -> Session:
|
||||
"""
|
||||
setup_session sets up an AWS session using the provided credentials.
|
||||
|
||||
Args:
|
||||
- mfa: A boolean indicating whether MFA is enabled.
|
||||
- profile: The name of the AWS CLI profile to use.
|
||||
- aws_access_key_id: The AWS access key ID.
|
||||
- aws_secret_access_key: The AWS secret access key.
|
||||
- aws_session_token: The AWS session token, optional.
|
||||
|
||||
Returns:
|
||||
- Session: The AWS session.
|
||||
|
||||
Raises:
|
||||
- AWSSetUpSessionError: If an error occurs during the setup process.
|
||||
"""
|
||||
try:
|
||||
logger.debug("Creating original session ...")
|
||||
|
||||
@@ -588,6 +671,21 @@ class AwsProvider(Provider):
|
||||
return refreshed_credentials
|
||||
|
||||
def print_credentials(self):
|
||||
"""
|
||||
Print the AWS credentials.
|
||||
|
||||
This method prints the AWS credentials used by the provider.
|
||||
|
||||
Example output:
|
||||
```
|
||||
Using the AWS credentials below:
|
||||
AWS-CLI Profile: default
|
||||
AWS Regions: all
|
||||
AWS Account: 123456789012
|
||||
User Id: AIDAJDPLRKLG7EXAMPLE
|
||||
Caller Identity ARN: arn:aws:iam::123456789012:user/prowler
|
||||
```
|
||||
"""
|
||||
# Beautify audited regions, set "all" if there is no filter region
|
||||
regions = (
|
||||
", ".join(self._identity.audited_regions)
|
||||
@@ -659,7 +757,7 @@ class AwsProvider(Provider):
|
||||
"""
|
||||
get_available_aws_service_regions returns the available regions for the given service and partition.
|
||||
|
||||
Arguments:
|
||||
Args:
|
||||
- service: The AWS service name.
|
||||
- partition: The AWS partition name. Default is "aws".
|
||||
- audited_regions: A set of regions to audit. Default is None.
|
||||
@@ -679,13 +777,26 @@ class AwsProvider(Provider):
|
||||
def get_checks_from_input_arn(self) -> set:
|
||||
"""
|
||||
get_checks_from_input_arn gets the list of checks from the input arns
|
||||
|
||||
Returns:
|
||||
- set: set of strings representing the checks from the input arns
|
||||
|
||||
Example:
|
||||
checks = get_checks_from_input_arn()
|
||||
"""
|
||||
checks_from_arn = set()
|
||||
is_subservice_in_checks = False
|
||||
# Handle if there are audit resources so only their services are executed
|
||||
if self._audit_resources:
|
||||
# TODO: this should be retrieved automatically
|
||||
services_without_subservices = ["guardduty", "kms", "s3", "elb", "efs"]
|
||||
services_without_subservices = [
|
||||
"guardduty",
|
||||
"kms",
|
||||
"s3",
|
||||
"elb",
|
||||
"efs",
|
||||
"sqs",
|
||||
]
|
||||
service_list = set()
|
||||
sub_service_list = set()
|
||||
for resource in self._audit_resources:
|
||||
@@ -745,7 +856,18 @@ class AwsProvider(Provider):
|
||||
|
||||
# TODO: This can be moved to another class since it doesn't need self
|
||||
def get_regions_from_audit_resources(self, audit_resources: list) -> set:
|
||||
"""get_regions_from_audit_resources gets the regions from the audit resources arns"""
|
||||
"""get_regions_from_audit_resources gets the regions from the audit resources arns
|
||||
|
||||
Args:
|
||||
- audit_resources: list of ARNs of the resources to audit
|
||||
|
||||
Returns:
|
||||
- set: set of strings representing the regions from the audit resources arns
|
||||
|
||||
Example:
|
||||
audit_resources = ["arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0"]
|
||||
regions = get_regions_from_audit_resources(audit_resources)
|
||||
"""
|
||||
audited_regions = set()
|
||||
for resource in audit_resources:
|
||||
region = resource.split(":")[3]
|
||||
@@ -805,7 +927,18 @@ class AwsProvider(Provider):
|
||||
raise error
|
||||
|
||||
def get_default_region(self, service: str) -> str:
|
||||
"""get_default_region returns the default region based on the profile and audited service regions"""
|
||||
"""get_default_region returns the default region based on the profile and audited service regions
|
||||
|
||||
Args:
|
||||
- service: The AWS service name
|
||||
|
||||
Returns:
|
||||
- str: The default region for the given service
|
||||
|
||||
Example:
|
||||
service = "ec2"
|
||||
default_region = get_default_region(service)
|
||||
"""
|
||||
try:
|
||||
service_regions = AwsProvider.get_available_aws_service_regions(
|
||||
service, self._identity.partition, self._identity.audited_regions
|
||||
@@ -826,7 +959,14 @@ class AwsProvider(Provider):
|
||||
raise error
|
||||
|
||||
def get_global_region(self) -> str:
|
||||
"""get_global_region returns the global region based on the audited partition"""
|
||||
"""get_global_region returns the global region based on the audited partition
|
||||
|
||||
Returns:
|
||||
- str: The global region for the audited partition
|
||||
|
||||
Example:
|
||||
global_region = get_global_region()a
|
||||
"""
|
||||
global_region = "us-east-1"
|
||||
if self._identity.partition == "aws-cn":
|
||||
global_region = "cn-north-1"
|
||||
@@ -838,7 +978,14 @@ class AwsProvider(Provider):
|
||||
|
||||
@staticmethod
|
||||
def input_role_mfa_token_and_code() -> AWSMFAInfo:
|
||||
"""input_role_mfa_token_and_code ask for the AWS MFA ARN and TOTP and returns it."""
|
||||
"""input_role_mfa_token_and_code ask for the AWS MFA ARN and TOTP and returns it.
|
||||
|
||||
Returns:
|
||||
- AWSMFAInfo: An object containing the MFA ARN and TOTP code
|
||||
|
||||
Example:
|
||||
mfa_info = input_role_mfa_token_and_code()
|
||||
"""
|
||||
mfa_ARN = input("Enter ARN of MFA: ")
|
||||
mfa_TOTP = input("Enter MFA code: ")
|
||||
return AWSMFAInfo(arn=mfa_ARN, totp=mfa_TOTP)
|
||||
@@ -846,6 +993,12 @@ class AwsProvider(Provider):
|
||||
def set_session_config(self, retries_max_attempts: int) -> Config:
|
||||
"""
|
||||
set_session_config returns a botocore Config object with the Prowler user agent and the default retrier configuration if nothing is passed as argument
|
||||
|
||||
Args:
|
||||
- retries_max_attempts: The maximum number of retries for the standard retrier config
|
||||
|
||||
Returns:
|
||||
- Config: The botocore Config object
|
||||
"""
|
||||
# Set the maximum retries for the standard retrier config
|
||||
default_session_config = Config(
|
||||
@@ -872,6 +1025,13 @@ class AwsProvider(Provider):
|
||||
) -> AWSCredentials:
|
||||
"""
|
||||
assume_role assumes the IAM roles passed with the given session and returns AWSCredentials
|
||||
|
||||
Args:
|
||||
- session: The AWS session object
|
||||
- assumed_role_info: The AWSAssumeRoleInfo object
|
||||
|
||||
Returns:
|
||||
- AWSCredentials: The AWS credentials for the assumed role
|
||||
"""
|
||||
try:
|
||||
role_session_name = (
|
||||
@@ -923,7 +1083,14 @@ class AwsProvider(Provider):
|
||||
)
|
||||
|
||||
def get_aws_enabled_regions(self, current_session: Session) -> set:
|
||||
"""get_aws_enabled_regions returns a set of enabled AWS regions"""
|
||||
"""get_aws_enabled_regions returns a set of enabled AWS regions
|
||||
|
||||
Args:
|
||||
- current_session: The AWS session object
|
||||
|
||||
Returns:
|
||||
- set: set of strings representing the enabled AWS regions
|
||||
"""
|
||||
try:
|
||||
# EC2 Client to check enabled regions
|
||||
service = "ec2"
|
||||
@@ -947,6 +1114,12 @@ class AwsProvider(Provider):
|
||||
# TODO: review this function
|
||||
# Maybe this should be done within the AwsProvider and not in __main__.py
|
||||
def get_checks_to_execute_by_audit_resources(self) -> set[str]:
|
||||
"""
|
||||
get_checks_to_execute_by_audit_resources gets the checks to execute based on the audit resources
|
||||
|
||||
Returns:
|
||||
- set: set of strings representing the checks to execute
|
||||
"""
|
||||
# Once the provider is set and we have the eventual checks from arn, it is time to exclude the others
|
||||
try:
|
||||
checks = set()
|
||||
@@ -1262,7 +1435,9 @@ class AwsProvider(Provider):
|
||||
logger.critical(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
raise error
|
||||
if raise_on_exception:
|
||||
raise error
|
||||
return Connection(error=error)
|
||||
|
||||
@staticmethod
|
||||
def create_sts_session(
|
||||
@@ -1271,7 +1446,7 @@ class AwsProvider(Provider):
|
||||
"""
|
||||
Create an STS session client.
|
||||
|
||||
Parameters:
|
||||
Args:
|
||||
- session (session.Session): The AWS session object.
|
||||
- aws_region (str): The AWS region to use for the session.
|
||||
|
||||
@@ -1295,6 +1470,59 @@ class AwsProvider(Provider):
|
||||
)
|
||||
raise error
|
||||
|
||||
@staticmethod
|
||||
def get_regions(partition: Partition = Partition.aws) -> set:
|
||||
"""
|
||||
Get the available AWS regions from the AWS services JSON file with the ability of filtering by partition.
|
||||
|
||||
Args:
|
||||
partition (str): The AWS partition to retrieve regions for. Defaults to "aws".
|
||||
|
||||
Returns:
|
||||
set: A set of region names.
|
||||
|
||||
Raises:
|
||||
AWSInvalidPartitionError: If the provided partition name is invalid.
|
||||
|
||||
Example:
|
||||
>>> AwsProvider.get_regions("aws")
|
||||
{"af-south-1"}
|
||||
"""
|
||||
|
||||
try:
|
||||
regions = set()
|
||||
data = read_aws_regions_file()
|
||||
|
||||
if partition is None:
|
||||
for service in data["services"].values():
|
||||
for partition in service["regions"]:
|
||||
regions.update(service["regions"][partition])
|
||||
else:
|
||||
partition = Partition(partition)
|
||||
for service in data["services"].values():
|
||||
regions.update(service["regions"][partition.value])
|
||||
|
||||
return regions
|
||||
except ValueError as value_error:
|
||||
logger.error(
|
||||
f"{value_error.__class__.__name__}[{value_error.__traceback__.tb_lineno}]: {value_error}"
|
||||
)
|
||||
raise AWSInvalidPartitionError(
|
||||
message=f"Invalid partition: {partition}",
|
||||
file=os.path.basename(__file__),
|
||||
)
|
||||
except KeyError as key_error:
|
||||
logger.error(
|
||||
f"{key_error.__class__.__name__}[{key_error.__traceback__.tb_lineno}]: {key_error}"
|
||||
)
|
||||
raise AWSInvalidPartitionError(
|
||||
message=f"Invalid partition: {partition}",
|
||||
file=os.path.basename(__file__),
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(f"{error.__class__.__name__}: {error}")
|
||||
raise error
|
||||
|
||||
|
||||
def read_aws_regions_file() -> dict:
|
||||
"""
|
||||
@@ -1311,29 +1539,21 @@ def read_aws_regions_file() -> dict:
|
||||
return data
|
||||
|
||||
|
||||
def get_aws_available_regions() -> set:
|
||||
"""
|
||||
Get the available AWS regions from the AWS services JSON file.
|
||||
|
||||
Returns:
|
||||
set: A set of available AWS regions.
|
||||
"""
|
||||
try:
|
||||
data = read_aws_regions_file()
|
||||
|
||||
regions = set()
|
||||
for service in data["services"].values():
|
||||
for partition in service["regions"]:
|
||||
for item in service["regions"][partition]:
|
||||
regions.add(item)
|
||||
return regions
|
||||
except Exception as error:
|
||||
logger.error(f"{error.__class__.__name__}: {error}")
|
||||
return set()
|
||||
|
||||
|
||||
# TODO: This can be moved to another class since it doesn't need self
|
||||
def get_aws_region_for_sts(session_region: str, regions: set[str]) -> str:
|
||||
"""
|
||||
Get the AWS region for the STS Assume Role operation.
|
||||
|
||||
Args:
|
||||
- session_region (str): The region configured in the AWS session.
|
||||
- regions (set[str]): The regions passed with the -f/--region/--filter-region option.
|
||||
|
||||
Returns:
|
||||
str: The AWS region for the STS Assume Role operation
|
||||
|
||||
Example:
|
||||
aws_region = get_aws_region_for_sts(session_region, regions)
|
||||
"""
|
||||
# If there is no region passed with -f/--region/--filter-region
|
||||
if regions is None or len(regions) == 0:
|
||||
# If you have a region configured in your AWS config or credentials file
|
||||
|
||||
@@ -1270,6 +1270,7 @@
|
||||
"ap-southeast-2",
|
||||
"ca-central-1",
|
||||
"eu-central-1",
|
||||
"eu-central-2",
|
||||
"eu-west-1",
|
||||
"eu-west-2",
|
||||
"eu-west-3",
|
||||
@@ -1280,6 +1281,7 @@
|
||||
],
|
||||
"aws-cn": [],
|
||||
"aws-us-gov": [
|
||||
"us-gov-east-1",
|
||||
"us-gov-west-1"
|
||||
]
|
||||
}
|
||||
@@ -1294,6 +1296,7 @@
|
||||
"ap-southeast-2",
|
||||
"ca-central-1",
|
||||
"eu-central-1",
|
||||
"eu-central-2",
|
||||
"eu-west-1",
|
||||
"eu-west-2",
|
||||
"eu-west-3",
|
||||
@@ -1304,6 +1307,7 @@
|
||||
],
|
||||
"aws-cn": [],
|
||||
"aws-us-gov": [
|
||||
"us-gov-east-1",
|
||||
"us-gov-west-1"
|
||||
]
|
||||
}
|
||||
@@ -1318,6 +1322,7 @@
|
||||
"ap-southeast-2",
|
||||
"ca-central-1",
|
||||
"eu-central-1",
|
||||
"eu-central-2",
|
||||
"eu-west-1",
|
||||
"eu-west-2",
|
||||
"eu-west-3",
|
||||
@@ -1328,6 +1333,7 @@
|
||||
],
|
||||
"aws-cn": [],
|
||||
"aws-us-gov": [
|
||||
"us-gov-east-1",
|
||||
"us-gov-west-1"
|
||||
]
|
||||
}
|
||||
@@ -2621,6 +2627,7 @@
|
||||
"connectcampaigns": {
|
||||
"regions": {
|
||||
"aws": [
|
||||
"af-south-1",
|
||||
"ap-southeast-2",
|
||||
"ca-central-1",
|
||||
"eu-central-1",
|
||||
@@ -3288,6 +3295,7 @@
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ap-southeast-4",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"ca-west-1",
|
||||
"eu-central-1",
|
||||
@@ -3972,6 +3980,7 @@
|
||||
"ap-northeast-2",
|
||||
"ap-northeast-3",
|
||||
"ap-south-1",
|
||||
"ap-south-2",
|
||||
"ap-southeast-1",
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
@@ -3984,6 +3993,7 @@
|
||||
"eu-west-1",
|
||||
"eu-west-2",
|
||||
"eu-west-3",
|
||||
"il-central-1",
|
||||
"me-central-1",
|
||||
"me-south-1",
|
||||
"sa-east-1",
|
||||
@@ -4390,6 +4400,7 @@
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ap-southeast-4",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"ca-west-1",
|
||||
"eu-central-1",
|
||||
@@ -4831,6 +4842,7 @@
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ap-southeast-4",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"ca-west-1",
|
||||
"eu-central-1",
|
||||
@@ -5541,6 +5553,7 @@
|
||||
"iotfleetwise": {
|
||||
"regions": {
|
||||
"aws": [
|
||||
"ap-south-1",
|
||||
"eu-central-1",
|
||||
"us-east-1"
|
||||
],
|
||||
@@ -5847,6 +5860,7 @@
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ap-southeast-4",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"ca-west-1",
|
||||
"eu-central-1",
|
||||
@@ -5963,6 +5977,7 @@
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ap-southeast-4",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"ca-west-1",
|
||||
"eu-central-1",
|
||||
@@ -6235,6 +6250,7 @@
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ap-southeast-4",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"ca-west-1",
|
||||
"eu-central-1",
|
||||
@@ -7152,6 +7168,7 @@
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ap-southeast-4",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"ca-west-1",
|
||||
"eu-central-1",
|
||||
@@ -7615,15 +7632,9 @@
|
||||
"opsworkscm": {
|
||||
"regions": {
|
||||
"aws": [
|
||||
"ap-northeast-1",
|
||||
"ap-southeast-1",
|
||||
"ap-southeast-2",
|
||||
"eu-central-1",
|
||||
"eu-west-1",
|
||||
"us-east-1",
|
||||
"us-east-2",
|
||||
"us-west-1",
|
||||
"us-west-2"
|
||||
"us-east-1"
|
||||
],
|
||||
"aws-cn": [],
|
||||
"aws-us-gov": []
|
||||
@@ -9201,6 +9212,7 @@
|
||||
"ap-southeast-3",
|
||||
"ca-central-1",
|
||||
"eu-central-1",
|
||||
"eu-central-2",
|
||||
"eu-north-1",
|
||||
"eu-south-1",
|
||||
"eu-south-2",
|
||||
@@ -9255,7 +9267,6 @@
|
||||
"eu-west-2",
|
||||
"eu-west-3",
|
||||
"il-central-1",
|
||||
"me-central-1",
|
||||
"me-south-1",
|
||||
"sa-east-1",
|
||||
"us-east-1",
|
||||
@@ -9263,10 +9274,7 @@
|
||||
"us-west-1",
|
||||
"us-west-2"
|
||||
],
|
||||
"aws-cn": [
|
||||
"cn-north-1",
|
||||
"cn-northwest-1"
|
||||
],
|
||||
"aws-cn": [],
|
||||
"aws-us-gov": [
|
||||
"us-gov-east-1",
|
||||
"us-gov-west-1"
|
||||
@@ -9848,6 +9856,7 @@
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ap-southeast-4",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"ca-west-1",
|
||||
"eu-central-1",
|
||||
@@ -10646,6 +10655,7 @@
|
||||
"regions": {
|
||||
"aws": [
|
||||
"ap-northeast-1",
|
||||
"ap-south-1",
|
||||
"ap-southeast-2",
|
||||
"eu-central-1",
|
||||
"eu-west-1",
|
||||
@@ -10680,7 +10690,10 @@
|
||||
"us-east-2",
|
||||
"us-west-2"
|
||||
],
|
||||
"aws-cn": [],
|
||||
"aws-cn": [
|
||||
"cn-north-1",
|
||||
"cn-northwest-1"
|
||||
],
|
||||
"aws-us-gov": []
|
||||
}
|
||||
},
|
||||
@@ -10688,6 +10701,7 @@
|
||||
"regions": {
|
||||
"aws": [
|
||||
"ap-northeast-1",
|
||||
"ap-south-1",
|
||||
"ap-southeast-2",
|
||||
"eu-central-1",
|
||||
"eu-west-1",
|
||||
@@ -10766,6 +10780,7 @@
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ap-southeast-4",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"ca-west-1",
|
||||
"eu-central-1",
|
||||
@@ -11082,15 +11097,19 @@
|
||||
"ap-northeast-2",
|
||||
"ap-northeast-3",
|
||||
"ap-south-1",
|
||||
"ap-south-2",
|
||||
"ap-southeast-1",
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-3",
|
||||
"ca-central-1",
|
||||
"eu-central-1",
|
||||
"eu-central-2",
|
||||
"eu-north-1",
|
||||
"eu-south-1",
|
||||
"eu-west-1",
|
||||
"eu-west-2",
|
||||
"eu-west-3",
|
||||
"me-central-1",
|
||||
"me-south-1",
|
||||
"sa-east-1",
|
||||
"us-east-1",
|
||||
@@ -11337,6 +11356,7 @@
|
||||
"ap-northeast-1",
|
||||
"ap-southeast-1",
|
||||
"ap-southeast-2",
|
||||
"ap-southeast-5",
|
||||
"ca-central-1",
|
||||
"eu-central-1",
|
||||
"eu-central-2",
|
||||
|
||||
@@ -74,6 +74,10 @@ class AWSBaseException(ProwlerException):
|
||||
"message": "The provided AWS Session Token is expired",
|
||||
"remediation": "Get a new AWS Session Token and configure it for the provider.",
|
||||
},
|
||||
(1917, "AWSInvalidPartitionError"): {
|
||||
"message": "The provided AWS partition is invalid",
|
||||
"remediation": "Check the provided AWS partition and ensure it is valid.",
|
||||
},
|
||||
}
|
||||
|
||||
def __init__(self, code, file=None, original_exception=None, message=None):
|
||||
@@ -220,3 +224,10 @@ class AWSSessionTokenExpiredError(AWSCredentialsError):
|
||||
super().__init__(
|
||||
1016, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class AWSInvalidPartitionError(AWSBaseException):
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
1917, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from argparse import ArgumentTypeError, Namespace
|
||||
from re import fullmatch, search
|
||||
|
||||
from prowler.providers.aws.aws_provider import get_aws_available_regions
|
||||
from prowler.providers.aws.aws_provider import AwsProvider
|
||||
from prowler.providers.aws.config import ROLE_SESSION_NAME
|
||||
from prowler.providers.aws.lib.arn.arn import arn_type
|
||||
|
||||
@@ -64,7 +64,7 @@ def init_parser(self):
|
||||
"-f",
|
||||
nargs="+",
|
||||
help="AWS region names to run Prowler against",
|
||||
choices=get_aws_available_regions(),
|
||||
choices=AwsProvider.get_regions(partition=None),
|
||||
)
|
||||
# AWS Organizations
|
||||
aws_orgs_subparser = aws_parser.add_argument_group("AWS Organizations")
|
||||
|
||||
@@ -101,3 +101,17 @@ class AWSService:
|
||||
except Exception:
|
||||
# Handle exceptions if necessary
|
||||
pass # Replace 'pass' with any additional exception handling logic. Currently handled within the called function
|
||||
|
||||
def get_unknown_arn(self, resource_type: str = None, region: str = None) -> str:
|
||||
"""
|
||||
Generate an unknown ARN for the service
|
||||
Args:
|
||||
region (str): The region to get the unknown ARN for.
|
||||
resource_type (str): The resource type to get the unknown ARN for
|
||||
Returns:
|
||||
str: The unknown ARN for the region.
|
||||
Examples:
|
||||
>>> service.get_unknown_arn(resource_type="bucket", region="us-east-1")
|
||||
arn:aws:s3:us-east-1:123456789012:bucket/unknown
|
||||
"""
|
||||
return f"arn:{self.audited_partition}:{self.service}:{f'{region}' if region else ''}:{self.audited_account}:{f'{resource_type}/' if resource_type else ''}unknown"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
from boto3.session import Session
|
||||
from botocore.config import Config
|
||||
@@ -82,6 +83,29 @@ class AWSMFAInfo:
|
||||
totp: str
|
||||
|
||||
|
||||
class Partition(str, Enum):
|
||||
"""
|
||||
Enum class representing different AWS partitions.
|
||||
|
||||
Attributes:
|
||||
aws (str): Represents the standard AWS commercial regions.
|
||||
aws_cn (str): Represents the AWS China regions.
|
||||
aws_us_gov (str): Represents the AWS GovCloud (US) Regions.
|
||||
aws_iso (str): Represents the AWS ISO (US) Regions.
|
||||
aws_iso_b (str): Represents the AWS ISOB (US) Regions.
|
||||
aws_iso_e (str): Represents the AWS ISOE (Europe) Regions.
|
||||
aws_iso_f (str): Represents the AWS ISOF Regions.
|
||||
"""
|
||||
|
||||
aws = "aws"
|
||||
aws_cn = "aws-cn"
|
||||
aws_us_gov = "aws-us-gov"
|
||||
aws_iso = "aws-iso"
|
||||
aws_iso_b = "aws-iso-b"
|
||||
aws_iso_e = "aws-iso-e"
|
||||
aws_iso_f = "aws-iso-f"
|
||||
|
||||
|
||||
class AWSOutputOptions(ProviderOutputOptions):
|
||||
security_hub_enabled: bool
|
||||
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ class accessanalyzer_enabled(Check):
|
||||
else:
|
||||
if analyzer.status == "NOT_AVAILABLE":
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"IAM Access Analyzer in account {analyzer.name} is not enabled."
|
||||
report.status_extended = f"IAM Access Analyzer in account {accessanalyzer_client.audited_account} is not enabled."
|
||||
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
|
||||
+2
-1
@@ -6,7 +6,8 @@ from prowler.providers.aws.services.accessanalyzer.accessanalyzer_client import
|
||||
|
||||
def fixer(region):
|
||||
"""
|
||||
Enable Access Analyzer in a region. Requires the access-analyzer:CreateAnalyzer permission:
|
||||
Enable Access Analyzer in a region. Requires the access-analyzer:CreateAnalyzer permission.
|
||||
Permissions:
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
|
||||
@@ -43,8 +43,10 @@ class AccessAnalyzer(AWSService):
|
||||
if analyzer_count == 0:
|
||||
self.analyzers.append(
|
||||
Analyzer(
|
||||
arn=self.audited_account_arn,
|
||||
name=self.audited_account,
|
||||
arn=self.get_unknown_arn(
|
||||
region=regional_client.region, resource_type="analyzer"
|
||||
),
|
||||
name="analyzer/unknown",
|
||||
status="NOT_AVAILABLE",
|
||||
tags=[],
|
||||
type="",
|
||||
|
||||
+3
-1
@@ -25,7 +25,9 @@
|
||||
"Url": "https://aws.amazon.com/blogs/security/how-to-get-ready-for-certificate-transparency/"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Categories": [
|
||||
"logging"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
|
||||
+2
-1
@@ -29,7 +29,8 @@
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"forensics-ready"
|
||||
"forensics-ready",
|
||||
"logging"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
|
||||
+3
-1
@@ -28,7 +28,9 @@
|
||||
"Url": "https://docs.aws.amazon.com/apigateway/latest/developerguide/security-monitoring.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Categories": [
|
||||
"logging"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from typing import Optional
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from pydantic import BaseModel
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
@@ -7,7 +8,6 @@ from prowler.lib.scan_filters.scan_filters import is_resource_filtered
|
||||
from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
|
||||
################## ApiGatewayV2
|
||||
class ApiGatewayV2(AWSService):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
@@ -71,6 +71,15 @@ class ApiGatewayV2(AWSService):
|
||||
tags=[stage.get("Tags")],
|
||||
)
|
||||
)
|
||||
except ClientError as error:
|
||||
if error.response["Error"]["Code"] == "NotFoundException":
|
||||
logger.warning(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}:{error.__traceback__.tb_lineno} -- {error}"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
from prowler.providers.aws.services.appsync.appsync_service import AppSync
|
||||
from prowler.providers.common.provider import Provider
|
||||
|
||||
appsync_client = AppSync(Provider.get_global_provider())
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "appsync_field_level_logging_enabled",
|
||||
"CheckTitle": "AWS AppSync should have field-level logging enabled",
|
||||
"CheckType": [
|
||||
"Software and Configuration Checks/AWS Security Best Practices"
|
||||
],
|
||||
"ServiceName": "appsync",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:aws:appsync:{region}:{account-id}:apis/{api-id}",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsAppSyncGraphQLApi",
|
||||
"Description": "This control checks whether an AWS AppSync API (only GraphQL APIs since boto3 doesnt have a method to return other APIs) field-level logging turned on. The control fails if the field resolver log level is set to None.",
|
||||
"Risk": "Without field-level logging enabled, it's difficult to monitor, troubleshoot, and optimize GraphQL API queries effectively.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/appsync-logging-enabled.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws appsync update-graphql-api --api-id <api-id> --log-config fieldLogLevel=<fieldLoggingLevel>",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/appsync-controls.html#appsync-2",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable field-level logging for your AWS AppSync API to monitor and troubleshoot GraphQL queries effectively.",
|
||||
"Url": "https://docs.aws.amazon.com/appsync/latest/devguide/monitoring.html#setup-and-configuration"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"logging"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.appsync.appsync_client import appsync_client
|
||||
|
||||
|
||||
class appsync_field_level_logging_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
# Check only GraphQL APIs because boto3 does not have a method to get other types of AppSync APIs (list_apis is not working)
|
||||
for api in appsync_client.graphql_apis.values():
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = api.region
|
||||
report.resource_id = api.id
|
||||
report.resource_arn = api.arn
|
||||
report.resource_tags = api.tags
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"AppSync API {api.name} has field log level enabled."
|
||||
)
|
||||
if api.field_log_level != "ALL" and api.field_log_level != "ERROR":
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"AppSync API {api.name} does not have field log level enabled."
|
||||
)
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "appsync_graphql_api_no_api_key_authentication",
|
||||
"CheckTitle": "AWS AppSync GraphQL APIs should not be authenticated with API keys",
|
||||
"CheckType": [
|
||||
"Software and Configuration Checks/AWS Security Best Practices"
|
||||
],
|
||||
"ServiceName": "appsync",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:aws:appsync:{region}:{account-id}:apis/{api-id}",
|
||||
"Severity": "high",
|
||||
"ResourceType": "AwsAppSyncGraphQLApi",
|
||||
"Description": "This control checks whether your application uses an API key to interact with an AWS AppSync GraphQL API. The control fails if an AWS AppSync GraphQL API is authenticated with an API key.",
|
||||
"Risk": "API keys in AppSync can expose applications to unauthorized access if compromised. Avoiding API keys helps reduce the risk of unintended access.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/appsync-authorization-check.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws appsync update-graphql-api --api-id <api-id> --authentication-type <authentication-type>",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/appsync-controls.html#appsync-5",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Use authentication methods other than API keys for AWS AppSync GraphQL APIs, such as AWS_IAM or Amazon Cognito.",
|
||||
"Url": "https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"trustboundaries"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.appsync.appsync_client import appsync_client
|
||||
|
||||
|
||||
class appsync_graphql_api_no_api_key_authentication(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for api in appsync_client.graphql_apis.values():
|
||||
if api.type == "GRAPHQL":
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = api.region
|
||||
report.resource_id = api.id
|
||||
report.resource_arn = api.arn
|
||||
report.resource_tags = api.tags
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"AppSync GraphQL API {api.name} is not using an API KEY for authentication."
|
||||
if api.authentication_type == "API_KEY":
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"AppSync GraphQL API {api.name} is using an API KEY for authentication."
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,61 @@
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.scan_filters.scan_filters import is_resource_filtered
|
||||
from prowler.providers.aws.lib.service.service import AWSService
|
||||
|
||||
|
||||
class AppSync(AWSService):
|
||||
def __init__(self, provider):
|
||||
# Call AWSService's __init__
|
||||
super().__init__(__class__.__name__, provider)
|
||||
self.graphql_apis = {}
|
||||
self.__threading_call__(self._list_graphql_apis)
|
||||
|
||||
def _list_graphql_apis(self, regional_client):
|
||||
logger.info("AppSync - Describing APIs...")
|
||||
try:
|
||||
list_graphql_apis_paginator = regional_client.get_paginator(
|
||||
"list_graphql_apis"
|
||||
)
|
||||
for page in list_graphql_apis_paginator.paginate():
|
||||
for api in page["graphqlApis"]:
|
||||
api_arn = api["arn"]
|
||||
if not self.audit_resources or (
|
||||
is_resource_filtered(
|
||||
api_arn,
|
||||
self.audit_resources,
|
||||
)
|
||||
):
|
||||
self.graphql_apis[api_arn] = GraphqlApi(
|
||||
id=api["apiId"],
|
||||
name=api["name"],
|
||||
arn=api_arn,
|
||||
region=regional_client.region,
|
||||
type=api.get("apiType", "GRAPHQL"),
|
||||
field_log_level=api.get("logConfig", {}).get(
|
||||
"fieldLogLevel", ""
|
||||
),
|
||||
authentication_type=api.get(
|
||||
"authenticationType", "API_KEY"
|
||||
),
|
||||
tags=[api.get("tags", {})],
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
|
||||
class GraphqlApi(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
arn: str
|
||||
region: str
|
||||
type: str
|
||||
field_log_level: str
|
||||
authentication_type: str
|
||||
tags: Optional[list] = []
|
||||
+13
-12
@@ -8,19 +8,20 @@ class autoscaling_group_launch_configuration_no_public_ip(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for group in autoscaling_client.groups:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = group.region
|
||||
report.resource_id = group.name
|
||||
report.resource_arn = group.arn
|
||||
report.resource_tags = group.tags
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Autoscaling group {group.name} does not have an associated launch configuration assigning a public IP address."
|
||||
|
||||
for lc in autoscaling_client.launch_configurations.values():
|
||||
if lc.name == group.launch_configuration_name and lc.public_ip:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Autoscaling group {group.name} has an associated launch configuration assigning a public IP address."
|
||||
if lc.name == group.launch_configuration_name:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = group.region
|
||||
report.resource_id = group.name
|
||||
report.resource_arn = group.arn
|
||||
report.resource_tags = group.tags
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Autoscaling group {group.name} does not have an associated launch configuration assigning a public IP address."
|
||||
|
||||
findings.append(report)
|
||||
if lc.public_ip:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Autoscaling group {group.name} has an associated launch configuration assigning a public IP address."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
+8
-11
@@ -8,20 +8,17 @@ class autoscaling_group_launch_configuration_requires_imdsv2(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for group in autoscaling_client.groups:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = group.region
|
||||
report.resource_id = group.name
|
||||
report.resource_arn = group.arn
|
||||
report.resource_tags = group.tags
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Autoscaling group {group.name} has IMDSv2 disabled or not required."
|
||||
)
|
||||
|
||||
for (
|
||||
launch_configuration
|
||||
) in autoscaling_client.launch_configurations.values():
|
||||
if launch_configuration.name == group.launch_configuration_name:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = group.region
|
||||
report.resource_id = group.name
|
||||
report.resource_arn = group.arn
|
||||
report.resource_tags = group.tags
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Autoscaling group {group.name} has IMDSv2 disabled or not required."
|
||||
if (
|
||||
launch_configuration.http_endpoint == "enabled"
|
||||
and launch_configuration.http_tokens == "required"
|
||||
@@ -32,6 +29,6 @@ class autoscaling_group_launch_configuration_requires_imdsv2(Check):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Autoscaling group {group.name} has metadata service disabled."
|
||||
|
||||
findings.append(report)
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
+3
-1
@@ -23,7 +23,9 @@
|
||||
"Url": "https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-add-availability-zone.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Categories": [
|
||||
"redundancy"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
|
||||
+2
-1
@@ -24,7 +24,8 @@
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"forensics-ready"
|
||||
"forensics-ready",
|
||||
"logging"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
|
||||
+11
-2
@@ -1,3 +1,4 @@
|
||||
import hashlib
|
||||
import json
|
||||
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
@@ -28,11 +29,19 @@ class awslambda_function_no_secrets_in_variables(Check):
|
||||
data=json.dumps(function.environment, indent=2),
|
||||
excluded_secrets=secrets_ignore_patterns,
|
||||
)
|
||||
original_env_vars = {}
|
||||
for name, value in function.environment.items():
|
||||
original_env_vars.update(
|
||||
{
|
||||
hashlib.sha1( # nosec B324 SHA1 is used here for non-security-critical unique identifiers
|
||||
value.encode("utf-8")
|
||||
).hexdigest(): name
|
||||
}
|
||||
)
|
||||
if detect_secrets_output:
|
||||
environment_variable_names = list(function.environment.keys())
|
||||
secrets_string = ", ".join(
|
||||
[
|
||||
f"{secret['type']} in variable {environment_variable_names[int(secret['line_number']) - 2]}"
|
||||
f"{secret['type']} in variable {original_env_vars[secret['hashed_secret']]}"
|
||||
for secret in detect_secrets_output
|
||||
]
|
||||
)
|
||||
|
||||
+2
-2
@@ -14,14 +14,14 @@ class awslambda_function_not_publicly_accessible(Check):
|
||||
report.resource_tags = function.tags
|
||||
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Lambda function {function.name} has a policy resource-based policy not public."
|
||||
report.status_extended = f"Lambda function {function.name} has a resource-based policy without public access."
|
||||
if is_policy_public(
|
||||
function.policy,
|
||||
awslambda_client.audited_account,
|
||||
is_cross_account_allowed=True,
|
||||
):
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Lambda function {function.name} has a policy resource-based policy with public access."
|
||||
report.status_extended = f"Lambda function {function.name} has a resource-based policy with public access."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
|
||||
+3
-3
@@ -8,14 +8,14 @@ class backup_recovery_point_encrypted(Check):
|
||||
for recovery_point in backup_client.recovery_points:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = recovery_point.backup_vault_region
|
||||
report.resource_id = recovery_point.backup_vault_name
|
||||
report.resource_id = recovery_point.id
|
||||
report.resource_arn = recovery_point.arn
|
||||
report.resource_tags = recovery_point.tags
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Backup Recovery Point {recovery_point.arn} for Backup Vault {recovery_point.backup_vault_name} is not encrypted at rest."
|
||||
report.status_extended = f"Backup Recovery Point {recovery_point.id} for Backup Vault {recovery_point.backup_vault_name} is not encrypted at rest."
|
||||
if recovery_point.encrypted:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Backup Recovery Point {recovery_point.arn} for Backup Vault {recovery_point.backup_vault_name} is encrypted at rest."
|
||||
report.status_extended = f"Backup Recovery Point {recovery_point.id} for Backup Vault {recovery_point.backup_vault_name} is encrypted at rest."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ class Backup(AWSService):
|
||||
self.backup_vault_arn_template = f"arn:{self.audited_partition}:backup:{self.region}:{self.audited_account}:backup-vault"
|
||||
self.backup_vaults = []
|
||||
self.__threading_call__(self._list_backup_vaults)
|
||||
self.__threading_call__(self._list_tags, self.backup_vaults)
|
||||
if self.backup_vaults is not None:
|
||||
self.__threading_call__(self._list_tags, self.backup_vaults)
|
||||
self.backup_plans = []
|
||||
self.__threading_call__(self._list_backup_plans)
|
||||
self.__threading_call__(self._list_tags, self.backup_plans)
|
||||
@@ -28,6 +29,7 @@ class Backup(AWSService):
|
||||
self.__threading_call__(self._list_backup_selections)
|
||||
self.recovery_points = []
|
||||
self.__threading_call__(self._list_recovery_points)
|
||||
self.__threading_call__(self._list_tags, self.recovery_points)
|
||||
|
||||
def _list_backup_vaults(self, regional_client):
|
||||
logger.info("Backup - Listing Backup Vaults...")
|
||||
@@ -171,10 +173,11 @@ class Backup(AWSService):
|
||||
|
||||
def _list_tags(self, resource):
|
||||
try:
|
||||
tags = self.regional_clients[resource.region].list_tags(
|
||||
ResourceArn=resource.arn
|
||||
)["Tags"]
|
||||
resource.tags = [tags] if tags else []
|
||||
if getattr(resource, "arn", None):
|
||||
tags = self.regional_clients[resource.region].list_tags(
|
||||
ResourceArn=resource.arn
|
||||
)["Tags"]
|
||||
resource.tags = [tags] if tags else []
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
@@ -183,21 +186,28 @@ class Backup(AWSService):
|
||||
def _list_recovery_points(self, regional_client):
|
||||
logger.info("Backup - Listing Recovery Points...")
|
||||
try:
|
||||
for backup_vault in self.backup_vaults:
|
||||
paginator = regional_client.get_paginator(
|
||||
"list_recovery_points_by_backup_vault"
|
||||
)
|
||||
for page in paginator.paginate(BackupVaultName=backup_vault.name):
|
||||
for recovery_point in page.get("RecoveryPoints", []):
|
||||
self.recovery_points.append(
|
||||
RecoveryPoint(
|
||||
arn=recovery_point.get("RecoveryPointArn"),
|
||||
backup_vault_name=backup_vault.name,
|
||||
encrypted=recovery_point.get("IsEncrypted", False),
|
||||
backup_vault_region=backup_vault.region,
|
||||
tags=[],
|
||||
)
|
||||
)
|
||||
if self.backup_vaults:
|
||||
for backup_vault in self.backup_vaults:
|
||||
paginator = regional_client.get_paginator(
|
||||
"list_recovery_points_by_backup_vault"
|
||||
)
|
||||
for page in paginator.paginate(BackupVaultName=backup_vault.name):
|
||||
for recovery_point in page.get("RecoveryPoints", []):
|
||||
arn = recovery_point.get("RecoveryPointArn")
|
||||
if arn:
|
||||
self.recovery_points.append(
|
||||
RecoveryPoint(
|
||||
arn=arn,
|
||||
id=arn.split(":")[-1],
|
||||
backup_vault_name=backup_vault.name,
|
||||
encrypted=recovery_point.get(
|
||||
"IsEncrypted", False
|
||||
),
|
||||
backup_vault_region=backup_vault.region,
|
||||
region=regional_client.region,
|
||||
tags=[],
|
||||
)
|
||||
)
|
||||
except ClientError as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
@@ -241,6 +251,8 @@ class BackupReportPlan(BaseModel):
|
||||
|
||||
class RecoveryPoint(BaseModel):
|
||||
arn: str
|
||||
id: str
|
||||
region: str
|
||||
backup_vault_name: str
|
||||
encrypted: bool
|
||||
backup_vault_region: str
|
||||
|
||||
+4
-2
@@ -8,8 +8,10 @@ class bedrock_model_invocation_logging_enabled(Check):
|
||||
for region, logging in bedrock_client.logging_configurations.items():
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = region
|
||||
report.resource_id = bedrock_client.audited_account
|
||||
report.resource_arn = bedrock_client.audited_account_arn
|
||||
report.resource_id = "model-invocation-logging"
|
||||
report.resource_arn = (
|
||||
bedrock_client._get_model_invocation_logging_arn_template(region)
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = "Bedrock Model Invocation Logging is disabled."
|
||||
if logging.enabled:
|
||||
|
||||
+4
-2
@@ -13,8 +13,10 @@ class bedrock_model_invocation_logs_encryption_enabled(Check):
|
||||
cloudwatch_encryption = True
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = region
|
||||
report.resource_id = bedrock_client.audited_account
|
||||
report.resource_arn = bedrock_client.audited_account_arn
|
||||
report.resource_id = "model-invocation-logging"
|
||||
report.resource_arn = (
|
||||
bedrock_client._get_model_invocation_logging_arn_template(region)
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = "Bedrock Model Invocation logs are encrypted."
|
||||
if logging.s3_bucket:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user