mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-01-25 02:08:11 +00:00
Compare commits
15 Commits
feat/githu
...
3.11.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3aaf2b2c27 | ||
|
|
e7d098ed1e | ||
|
|
21fba27355 | ||
|
|
74e37307f7 | ||
|
|
d9d7c009a5 | ||
|
|
2220cf9733 | ||
|
|
3325b72b86 | ||
|
|
9182d56246 | ||
|
|
299ece19a8 | ||
|
|
0a0732d7c0 | ||
|
|
28011d97a9 | ||
|
|
e71b0d1b6a | ||
|
|
ec01b62a82 | ||
|
|
12b45c6896 | ||
|
|
51c60dd4ee |
@@ -178,11 +178,7 @@ Prowler will follow the same credentials search as [Google authentication librar
|
|||||||
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
||||||
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
||||||
|
|
||||||
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the following roles to the member associated with the credentials:
|
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the `Viewer` role to the member associated with the credentials.
|
||||||
|
|
||||||
- Viewer
|
|
||||||
- Security Reviewer
|
|
||||||
- Stackdriver Account Viewer
|
|
||||||
|
|
||||||
> By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
|
> By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
|
||||||
|
|
||||||
|
|||||||
@@ -97,10 +97,6 @@ Prowler will follow the same credentials search as [Google authentication librar
|
|||||||
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
||||||
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
||||||
|
|
||||||
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the following roles to the member associated with the credentials:
|
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the `Viewer` role to the member associated with the credentials.
|
||||||
|
|
||||||
- Viewer
|
|
||||||
- Security Reviewer
|
|
||||||
- Stackdriver Account Viewer
|
|
||||||
|
|
||||||
> By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
|
> By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
|
||||||
|
|||||||
@@ -22,8 +22,4 @@ Prowler will follow the same credentials search as [Google authentication librar
|
|||||||
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
||||||
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
||||||
|
|
||||||
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the following roles to the member associated with the credentials:
|
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the `Viewer` role to the member associated with the credentials.
|
||||||
|
|
||||||
- Viewer
|
|
||||||
- Security Reviewer
|
|
||||||
- Stackdriver Account Viewer
|
|
||||||
|
|||||||
14
poetry.lock
generated
14
poetry.lock
generated
@@ -902,13 +902,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0dev)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "google-api-python-client"
|
name = "google-api-python-client"
|
||||||
version = "2.105.0"
|
version = "2.106.0"
|
||||||
description = "Google API Client Library for Python"
|
description = "Google API Client Library for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "google-api-python-client-2.105.0.tar.gz", hash = "sha256:0a8b32cfc2d9b3c1868ae6faef7ee1ab9c89a6cec30be709ea9c97f9a3e5902d"},
|
{file = "google-api-python-client-2.106.0.tar.gz", hash = "sha256:f6a3862be2f6e5e0536d7bd47b5af3f24ac0b9147c76c830cafb3329d71d5724"},
|
||||||
{file = "google_api_python_client-2.105.0-py2.py3-none-any.whl", hash = "sha256:571ce7c41e53415e385aab5a955725f71780550683ffcb71596f5809677d40b7"},
|
{file = "google_api_python_client-2.106.0-py2.py3-none-any.whl", hash = "sha256:c47c0dae5dd20aa43e4ea184566fe59d0c8fd0b86dd223b29040d8ea4f7ed6ea"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -1365,13 +1365,13 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mkdocs-material"
|
name = "mkdocs-material"
|
||||||
version = "9.4.7"
|
version = "9.4.8"
|
||||||
description = "Documentation that simply works"
|
description = "Documentation that simply works"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "mkdocs_material-9.4.7-py3-none-any.whl", hash = "sha256:4d698d52bb6a6a3c452ab854481c4cdb68453a0420956a6aee2de55fe15fe610"},
|
{file = "mkdocs_material-9.4.8-py3-none-any.whl", hash = "sha256:8b20f6851bddeef37dced903893cd176cf13a21a482e97705a103c45f06ce9b9"},
|
||||||
{file = "mkdocs_material-9.4.7.tar.gz", hash = "sha256:e704e001c9ef17291e1d3462c202425217601653e18f68f85d28eff4690e662b"},
|
{file = "mkdocs_material-9.4.8.tar.gz", hash = "sha256:f0c101453e8bc12b040e8b64ca39a405d950d8402609b1378cc2b98976e74b5f"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -2889,4 +2889,4 @@ docs = ["mkdocs", "mkdocs-material"]
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "6ed432b0310655c247da3b4f542b9410842fb46de838408b99b6e61fb367cf38"
|
content-hash = "d765b7a8c5d49f3a20316d575093430785a29ed5968d315b727455dea803331c"
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ from prowler.providers.common.audit_info import (
|
|||||||
set_provider_audit_info,
|
set_provider_audit_info,
|
||||||
set_provider_execution_parameters,
|
set_provider_execution_parameters,
|
||||||
)
|
)
|
||||||
|
from prowler.providers.common.clean import clean_provider_local_output_directories
|
||||||
from prowler.providers.common.outputs import set_provider_output_options
|
from prowler.providers.common.outputs import set_provider_output_options
|
||||||
from prowler.providers.common.quick_inventory import run_provider_quick_inventory
|
from prowler.providers.common.quick_inventory import run_provider_quick_inventory
|
||||||
|
|
||||||
@@ -301,6 +302,9 @@ def prowler():
|
|||||||
if checks_folder:
|
if checks_folder:
|
||||||
remove_custom_checks_module(checks_folder, provider)
|
remove_custom_checks_module(checks_folder, provider)
|
||||||
|
|
||||||
|
# clean local directories
|
||||||
|
clean_provider_local_output_directories(args)
|
||||||
|
|
||||||
# If there are failed findings exit code 3, except if -z is input
|
# If there are failed findings exit code 3, except if -z is input
|
||||||
if not args.ignore_exit_code_3 and stats["total_fail"] > 0:
|
if not args.ignore_exit_code_3 and stats["total_fail"] > 0:
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from prowler.lib.logger import logger
|
|||||||
|
|
||||||
timestamp = datetime.today()
|
timestamp = datetime.today()
|
||||||
timestamp_utc = datetime.now(timezone.utc).replace(tzinfo=timezone.utc)
|
timestamp_utc = datetime.now(timezone.utc).replace(tzinfo=timezone.utc)
|
||||||
prowler_version = "3.11.0"
|
prowler_version = "3.11.1"
|
||||||
html_logo_url = "https://github.com/prowler-cloud/prowler/"
|
html_logo_url = "https://github.com/prowler-cloud/prowler/"
|
||||||
html_logo_img = "https://user-images.githubusercontent.com/3985464/113734260-7ba06900-96fb-11eb-82bc-d4f68a1e2710.png"
|
html_logo_img = "https://user-images.githubusercontent.com/3985464/113734260-7ba06900-96fb-11eb-82bc-d4f68a1e2710.png"
|
||||||
square_logo_img = "https://user-images.githubusercontent.com/38561120/235905862-9ece5bd7-9aa3-4e48-807a-3a9035eb8bfb.png"
|
square_logo_img = "https://user-images.githubusercontent.com/38561120/235905862-9ece5bd7-9aa3-4e48-807a-3a9035eb8bfb.png"
|
||||||
|
|||||||
@@ -674,10 +674,13 @@
|
|||||||
"regions": {
|
"regions": {
|
||||||
"aws": [
|
"aws": [
|
||||||
"ap-northeast-1",
|
"ap-northeast-1",
|
||||||
|
"ap-south-1",
|
||||||
"ap-southeast-1",
|
"ap-southeast-1",
|
||||||
"ap-southeast-2",
|
"ap-southeast-2",
|
||||||
"eu-central-1",
|
"eu-central-1",
|
||||||
"eu-west-1",
|
"eu-west-1",
|
||||||
|
"eu-west-2",
|
||||||
|
"eu-west-3",
|
||||||
"us-east-1",
|
"us-east-1",
|
||||||
"us-east-2",
|
"us-east-2",
|
||||||
"us-west-2"
|
"us-west-2"
|
||||||
@@ -1013,6 +1016,17 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"aws-appfabric": {
|
||||||
|
"regions": {
|
||||||
|
"aws": [
|
||||||
|
"ap-northeast-1",
|
||||||
|
"eu-west-1",
|
||||||
|
"us-east-1"
|
||||||
|
],
|
||||||
|
"aws-cn": [],
|
||||||
|
"aws-us-gov": []
|
||||||
|
}
|
||||||
|
},
|
||||||
"awshealthdashboard": {
|
"awshealthdashboard": {
|
||||||
"regions": {
|
"regions": {
|
||||||
"aws": [
|
"aws": [
|
||||||
@@ -2068,7 +2082,9 @@
|
|||||||
"ap-east-1",
|
"ap-east-1",
|
||||||
"ap-northeast-1",
|
"ap-northeast-1",
|
||||||
"ap-northeast-2",
|
"ap-northeast-2",
|
||||||
|
"ap-northeast-3",
|
||||||
"ap-south-1",
|
"ap-south-1",
|
||||||
|
"ap-south-2",
|
||||||
"ap-southeast-1",
|
"ap-southeast-1",
|
||||||
"ap-southeast-2",
|
"ap-southeast-2",
|
||||||
"ca-central-1",
|
"ca-central-1",
|
||||||
@@ -2079,6 +2095,7 @@
|
|||||||
"eu-west-1",
|
"eu-west-1",
|
||||||
"eu-west-2",
|
"eu-west-2",
|
||||||
"eu-west-3",
|
"eu-west-3",
|
||||||
|
"me-central-1",
|
||||||
"me-south-1",
|
"me-south-1",
|
||||||
"sa-east-1",
|
"sa-east-1",
|
||||||
"us-east-1",
|
"us-east-1",
|
||||||
@@ -2467,6 +2484,7 @@
|
|||||||
"ap-southeast-1",
|
"ap-southeast-1",
|
||||||
"ap-southeast-2",
|
"ap-southeast-2",
|
||||||
"ap-southeast-3",
|
"ap-southeast-3",
|
||||||
|
"ap-southeast-4",
|
||||||
"ca-central-1",
|
"ca-central-1",
|
||||||
"eu-central-1",
|
"eu-central-1",
|
||||||
"eu-central-2",
|
"eu-central-2",
|
||||||
@@ -4336,16 +4354,6 @@
|
|||||||
"aws-us-gov": []
|
"aws-us-gov": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gamesparks": {
|
|
||||||
"regions": {
|
|
||||||
"aws": [
|
|
||||||
"ap-northeast-1",
|
|
||||||
"us-east-1"
|
|
||||||
],
|
|
||||||
"aws-cn": [],
|
|
||||||
"aws-us-gov": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"glacier": {
|
"glacier": {
|
||||||
"regions": {
|
"regions": {
|
||||||
"aws": [
|
"aws": [
|
||||||
@@ -6062,6 +6070,15 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"managedblockchain-query": {
|
||||||
|
"regions": {
|
||||||
|
"aws": [
|
||||||
|
"us-east-1"
|
||||||
|
],
|
||||||
|
"aws-cn": [],
|
||||||
|
"aws-us-gov": []
|
||||||
|
}
|
||||||
|
},
|
||||||
"managedservices": {
|
"managedservices": {
|
||||||
"regions": {
|
"regions": {
|
||||||
"aws": [
|
"aws": [
|
||||||
@@ -6388,11 +6405,18 @@
|
|||||||
"aws": [
|
"aws": [
|
||||||
"af-south-1",
|
"af-south-1",
|
||||||
"ap-northeast-1",
|
"ap-northeast-1",
|
||||||
|
"ap-northeast-2",
|
||||||
|
"ap-northeast-3",
|
||||||
"ap-south-1",
|
"ap-south-1",
|
||||||
"ap-southeast-1",
|
"ap-southeast-1",
|
||||||
"ap-southeast-2",
|
"ap-southeast-2",
|
||||||
|
"ap-southeast-4",
|
||||||
|
"ca-central-1",
|
||||||
"eu-central-1",
|
"eu-central-1",
|
||||||
|
"eu-north-1",
|
||||||
"eu-west-1",
|
"eu-west-1",
|
||||||
|
"eu-west-3",
|
||||||
|
"sa-east-1",
|
||||||
"us-east-1",
|
"us-east-1",
|
||||||
"us-east-2",
|
"us-east-2",
|
||||||
"us-west-2"
|
"us-west-2"
|
||||||
@@ -7152,6 +7176,41 @@
|
|||||||
"aws-us-gov": []
|
"aws-us-gov": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pca-connector-ad": {
|
||||||
|
"regions": {
|
||||||
|
"aws": [
|
||||||
|
"af-south-1",
|
||||||
|
"ap-east-1",
|
||||||
|
"ap-northeast-1",
|
||||||
|
"ap-northeast-2",
|
||||||
|
"ap-northeast-3",
|
||||||
|
"ap-south-1",
|
||||||
|
"ap-south-2",
|
||||||
|
"ap-southeast-1",
|
||||||
|
"ap-southeast-2",
|
||||||
|
"ap-southeast-3",
|
||||||
|
"ap-southeast-4",
|
||||||
|
"ca-central-1",
|
||||||
|
"eu-central-1",
|
||||||
|
"eu-central-2",
|
||||||
|
"eu-north-1",
|
||||||
|
"eu-south-1",
|
||||||
|
"eu-south-2",
|
||||||
|
"eu-west-1",
|
||||||
|
"eu-west-2",
|
||||||
|
"eu-west-3",
|
||||||
|
"me-central-1",
|
||||||
|
"me-south-1",
|
||||||
|
"sa-east-1",
|
||||||
|
"us-east-1",
|
||||||
|
"us-east-2",
|
||||||
|
"us-west-1",
|
||||||
|
"us-west-2"
|
||||||
|
],
|
||||||
|
"aws-cn": [],
|
||||||
|
"aws-us-gov": []
|
||||||
|
}
|
||||||
|
},
|
||||||
"personalize": {
|
"personalize": {
|
||||||
"regions": {
|
"regions": {
|
||||||
"aws": [
|
"aws": [
|
||||||
@@ -9928,6 +9987,7 @@
|
|||||||
"ap-northeast-2",
|
"ap-northeast-2",
|
||||||
"ap-northeast-3",
|
"ap-northeast-3",
|
||||||
"ap-south-1",
|
"ap-south-1",
|
||||||
|
"ap-south-2",
|
||||||
"ap-southeast-1",
|
"ap-southeast-1",
|
||||||
"ap-southeast-2",
|
"ap-southeast-2",
|
||||||
"ap-southeast-4",
|
"ap-southeast-4",
|
||||||
|
|||||||
@@ -135,7 +135,12 @@ def allowlist_findings(
|
|||||||
|
|
||||||
|
|
||||||
def is_allowlisted(
|
def is_allowlisted(
|
||||||
allowlist: dict, audited_account: str, check: str, region: str, resource: str, tags
|
allowlist: dict,
|
||||||
|
audited_account: str,
|
||||||
|
check: str,
|
||||||
|
finding_region: str,
|
||||||
|
finding_resource: str,
|
||||||
|
finding_tags,
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
allowlisted_checks = {}
|
allowlisted_checks = {}
|
||||||
@@ -150,15 +155,15 @@ def is_allowlisted(
|
|||||||
if "*" in allowlist["Accounts"]:
|
if "*" in allowlist["Accounts"]:
|
||||||
checks_multi_account = allowlist["Accounts"]["*"]["Checks"]
|
checks_multi_account = allowlist["Accounts"]["*"]["Checks"]
|
||||||
allowlisted_checks.update(checks_multi_account)
|
allowlisted_checks.update(checks_multi_account)
|
||||||
|
|
||||||
# Test if it is allowlisted
|
# Test if it is allowlisted
|
||||||
if is_allowlisted_in_check(
|
if is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
audited_account,
|
audited_account,
|
||||||
audited_account,
|
|
||||||
check,
|
check,
|
||||||
region,
|
finding_region,
|
||||||
resource,
|
finding_resource,
|
||||||
tags,
|
finding_tags,
|
||||||
):
|
):
|
||||||
is_finding_allowlisted = True
|
is_finding_allowlisted = True
|
||||||
|
|
||||||
@@ -171,23 +176,29 @@ def is_allowlisted(
|
|||||||
|
|
||||||
|
|
||||||
def is_allowlisted_in_check(
|
def is_allowlisted_in_check(
|
||||||
allowlisted_checks, audited_account, account, check, region, resource, tags
|
allowlisted_checks,
|
||||||
|
audited_account,
|
||||||
|
check,
|
||||||
|
finding_region,
|
||||||
|
finding_resource,
|
||||||
|
finding_tags,
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
# Default value is not allowlisted
|
# Default value is not allowlisted
|
||||||
is_check_allowlisted = False
|
is_check_allowlisted = False
|
||||||
|
|
||||||
for allowlisted_check, allowlisted_check_info in allowlisted_checks.items():
|
for allowlisted_check, allowlisted_check_info in allowlisted_checks.items():
|
||||||
# map lambda to awslambda
|
# map lambda to awslambda
|
||||||
allowlisted_check = re.sub("^lambda", "awslambda", allowlisted_check)
|
allowlisted_check = re.sub("^lambda", "awslambda", allowlisted_check)
|
||||||
# extract the exceptions
|
|
||||||
|
# Check if the finding is excepted
|
||||||
exceptions = allowlisted_check_info.get("Exceptions")
|
exceptions = allowlisted_check_info.get("Exceptions")
|
||||||
# Check if there are exceptions
|
|
||||||
if is_excepted(
|
if is_excepted(
|
||||||
exceptions,
|
exceptions,
|
||||||
audited_account,
|
audited_account,
|
||||||
region,
|
finding_region,
|
||||||
resource,
|
finding_resource,
|
||||||
tags,
|
finding_tags,
|
||||||
):
|
):
|
||||||
# Break loop and return default value since is excepted
|
# Break loop and return default value since is excepted
|
||||||
break
|
break
|
||||||
@@ -201,13 +212,27 @@ def is_allowlisted_in_check(
|
|||||||
or check == allowlisted_check
|
or check == allowlisted_check
|
||||||
or re.search(allowlisted_check, check)
|
or re.search(allowlisted_check, check)
|
||||||
):
|
):
|
||||||
if is_allowlisted_in_region(
|
allowlisted_in_check = True
|
||||||
allowlisted_regions,
|
allowlisted_in_region = is_allowlisted_in_region(
|
||||||
allowlisted_resources,
|
allowlisted_regions, finding_region
|
||||||
allowlisted_tags,
|
)
|
||||||
region,
|
allowlisted_in_resource = is_allowlisted_in_resource(
|
||||||
resource,
|
allowlisted_resources, finding_resource
|
||||||
tags,
|
)
|
||||||
|
allowlisted_in_tags = is_allowlisted_in_tags(
|
||||||
|
allowlisted_tags, finding_tags
|
||||||
|
)
|
||||||
|
|
||||||
|
# For a finding to be allowlisted requires the following set to True:
|
||||||
|
# - allowlisted_in_check -> True
|
||||||
|
# - allowlisted_in_region -> True
|
||||||
|
# - allowlisted_in_tags -> True or allowlisted_in_resource -> True
|
||||||
|
# - excepted -> False
|
||||||
|
|
||||||
|
if (
|
||||||
|
allowlisted_in_check
|
||||||
|
and allowlisted_in_region
|
||||||
|
and (allowlisted_in_tags or allowlisted_in_resource)
|
||||||
):
|
):
|
||||||
is_check_allowlisted = True
|
is_check_allowlisted = True
|
||||||
|
|
||||||
@@ -220,25 +245,11 @@ def is_allowlisted_in_check(
|
|||||||
|
|
||||||
|
|
||||||
def is_allowlisted_in_region(
|
def is_allowlisted_in_region(
|
||||||
allowlist_regions, allowlist_resources, allowlisted_tags, region, resource, tags
|
allowlisted_regions,
|
||||||
|
finding_region,
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
# By default is not allowlisted
|
return __is_item_matched__(allowlisted_regions, finding_region)
|
||||||
is_region_allowlisted = False
|
|
||||||
# If there is a *, it affects to all regions
|
|
||||||
if "*" in allowlist_regions or region in allowlist_regions:
|
|
||||||
for elem in allowlist_resources:
|
|
||||||
if is_allowlisted_in_tags(
|
|
||||||
allowlisted_tags,
|
|
||||||
elem,
|
|
||||||
resource,
|
|
||||||
tags,
|
|
||||||
):
|
|
||||||
is_region_allowlisted = True
|
|
||||||
# if we find the element there is no point in continuing with the loop
|
|
||||||
break
|
|
||||||
|
|
||||||
return is_region_allowlisted
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.critical(
|
logger.critical(
|
||||||
f"{error.__class__.__name__} -- {error}[{error.__traceback__.tb_lineno}]"
|
f"{error.__class__.__name__} -- {error}[{error.__traceback__.tb_lineno}]"
|
||||||
@@ -246,25 +257,9 @@ def is_allowlisted_in_region(
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def is_allowlisted_in_tags(allowlisted_tags, elem, resource, tags):
|
def is_allowlisted_in_tags(allowlisted_tags, finding_tags):
|
||||||
try:
|
try:
|
||||||
# By default is not allowlisted
|
return __is_item_matched__(allowlisted_tags, finding_tags)
|
||||||
is_tag_allowlisted = False
|
|
||||||
# Check if it is an *
|
|
||||||
if elem == "*":
|
|
||||||
elem = ".*"
|
|
||||||
# Check if there are allowlisted tags
|
|
||||||
if allowlisted_tags:
|
|
||||||
for allowlisted_tag in allowlisted_tags:
|
|
||||||
if re.search(allowlisted_tag, tags):
|
|
||||||
is_tag_allowlisted = True
|
|
||||||
break
|
|
||||||
|
|
||||||
else:
|
|
||||||
if re.search(elem, resource):
|
|
||||||
is_tag_allowlisted = True
|
|
||||||
|
|
||||||
return is_tag_allowlisted
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.critical(
|
logger.critical(
|
||||||
f"{error.__class__.__name__} -- {error}[{error.__traceback__.tb_lineno}]"
|
f"{error.__class__.__name__} -- {error}[{error.__traceback__.tb_lineno}]"
|
||||||
@@ -272,7 +267,25 @@ def is_allowlisted_in_tags(allowlisted_tags, elem, resource, tags):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def is_excepted(exceptions, audited_account, region, resource, tags):
|
def is_allowlisted_in_resource(allowlisted_resources, finding_resource):
|
||||||
|
try:
|
||||||
|
return __is_item_matched__(allowlisted_resources, finding_resource)
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
logger.critical(
|
||||||
|
f"{error.__class__.__name__} -- {error}[{error.__traceback__.tb_lineno}]"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def is_excepted(
|
||||||
|
exceptions,
|
||||||
|
audited_account,
|
||||||
|
finding_region,
|
||||||
|
finding_resource,
|
||||||
|
finding_tags,
|
||||||
|
):
|
||||||
|
"""is_excepted returns True if the account, region, resource and tags are excepted"""
|
||||||
try:
|
try:
|
||||||
excepted = False
|
excepted = False
|
||||||
is_account_excepted = False
|
is_account_excepted = False
|
||||||
@@ -281,39 +294,50 @@ def is_excepted(exceptions, audited_account, region, resource, tags):
|
|||||||
is_tag_excepted = False
|
is_tag_excepted = False
|
||||||
if exceptions:
|
if exceptions:
|
||||||
excepted_accounts = exceptions.get("Accounts", [])
|
excepted_accounts = exceptions.get("Accounts", [])
|
||||||
|
is_account_excepted = __is_item_matched__(
|
||||||
|
excepted_accounts, audited_account
|
||||||
|
)
|
||||||
|
|
||||||
excepted_regions = exceptions.get("Regions", [])
|
excepted_regions = exceptions.get("Regions", [])
|
||||||
|
is_region_excepted = __is_item_matched__(excepted_regions, finding_region)
|
||||||
|
|
||||||
excepted_resources = exceptions.get("Resources", [])
|
excepted_resources = exceptions.get("Resources", [])
|
||||||
|
is_resource_excepted = __is_item_matched__(
|
||||||
|
excepted_resources, finding_resource
|
||||||
|
)
|
||||||
|
|
||||||
excepted_tags = exceptions.get("Tags", [])
|
excepted_tags = exceptions.get("Tags", [])
|
||||||
if exceptions:
|
is_tag_excepted = __is_item_matched__(excepted_tags, finding_tags)
|
||||||
if audited_account in excepted_accounts:
|
|
||||||
is_account_excepted = True
|
if (
|
||||||
if region in excepted_regions:
|
is_account_excepted
|
||||||
is_region_excepted = True
|
and is_region_excepted
|
||||||
for excepted_resource in excepted_resources:
|
and is_resource_excepted
|
||||||
if re.search(excepted_resource, resource):
|
and is_tag_excepted
|
||||||
is_resource_excepted = True
|
):
|
||||||
for tag in excepted_tags:
|
excepted = True
|
||||||
if tag in tags:
|
|
||||||
is_tag_excepted = True
|
|
||||||
if (
|
|
||||||
(
|
|
||||||
(excepted_accounts and is_account_excepted)
|
|
||||||
or not excepted_accounts
|
|
||||||
)
|
|
||||||
and (
|
|
||||||
(excepted_regions and is_region_excepted)
|
|
||||||
or not excepted_regions
|
|
||||||
)
|
|
||||||
and (
|
|
||||||
(excepted_resources and is_resource_excepted)
|
|
||||||
or not excepted_resources
|
|
||||||
)
|
|
||||||
and ((excepted_tags and is_tag_excepted) or not excepted_tags)
|
|
||||||
):
|
|
||||||
excepted = True
|
|
||||||
return excepted
|
return excepted
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.critical(
|
logger.critical(
|
||||||
f"{error.__class__.__name__} -- {error}[{error.__traceback__.tb_lineno}]"
|
f"{error.__class__.__name__} -- {error}[{error.__traceback__.tb_lineno}]"
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def __is_item_matched__(matched_items, finding_items):
|
||||||
|
"""__is_item_matched__ return True if any of the matched_items are present in the finding_items, otherwise returns False."""
|
||||||
|
try:
|
||||||
|
is_item_matched = False
|
||||||
|
if matched_items and (finding_items or finding_items == ""):
|
||||||
|
for item in matched_items:
|
||||||
|
if item == "*":
|
||||||
|
item = ".*"
|
||||||
|
if re.search(item, finding_items):
|
||||||
|
is_item_matched = True
|
||||||
|
break
|
||||||
|
return is_item_matched
|
||||||
|
except Exception as error:
|
||||||
|
logger.critical(
|
||||||
|
f"{error.__class__.__name__} -- {error}[{error.__traceback__.tb_lineno}]"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|||||||
@@ -56,12 +56,15 @@ def is_account_only_allowed_in_condition(
|
|||||||
):
|
):
|
||||||
# if there is an arn/account without the source account -> we do not consider it safe
|
# if there is an arn/account without the source account -> we do not consider it safe
|
||||||
# here by default we assume is true and look for false entries
|
# here by default we assume is true and look for false entries
|
||||||
is_condition_valid = True
|
is_condition_key_restrictive = True
|
||||||
for item in condition_statement[condition_operator][value]:
|
for item in condition_statement[condition_operator][value]:
|
||||||
if source_account not in item:
|
if source_account not in item:
|
||||||
is_condition_valid = False
|
is_condition_key_restrictive = False
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if is_condition_key_restrictive:
|
||||||
|
is_condition_valid = True
|
||||||
|
|
||||||
# value is a string
|
# value is a string
|
||||||
elif isinstance(
|
elif isinstance(
|
||||||
condition_statement[condition_operator][value],
|
condition_statement[condition_operator][value],
|
||||||
|
|||||||
@@ -139,7 +139,10 @@ class IAM(AWSService):
|
|||||||
logger.warning(
|
logger.warning(
|
||||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
@@ -208,14 +211,24 @@ class IAM(AWSService):
|
|||||||
reuse_prevention=reuse_prevention,
|
reuse_prevention=reuse_prevention,
|
||||||
hard_expiry=hard_expiry,
|
hard_expiry=hard_expiry,
|
||||||
)
|
)
|
||||||
except Exception as error:
|
|
||||||
if "NoSuchEntity" in str(error):
|
except ClientError as error:
|
||||||
|
if error.response["Error"]["Code"] == "NoSuchEntity":
|
||||||
# Password policy does not exist
|
# Password policy does not exist
|
||||||
stored_password_policy = None
|
stored_password_policy = None
|
||||||
|
logger.warning(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
return stored_password_policy
|
return stored_password_policy
|
||||||
|
|
||||||
@@ -268,17 +281,22 @@ class IAM(AWSService):
|
|||||||
logger.info("IAM - List Attached Group Policies...")
|
logger.info("IAM - List Attached Group Policies...")
|
||||||
try:
|
try:
|
||||||
for group in self.groups:
|
for group in self.groups:
|
||||||
list_attached_group_policies_paginator = self.client.get_paginator(
|
try:
|
||||||
"list_attached_group_policies"
|
list_attached_group_policies_paginator = self.client.get_paginator(
|
||||||
)
|
"list_attached_group_policies"
|
||||||
attached_group_policies = []
|
)
|
||||||
for page in list_attached_group_policies_paginator.paginate(
|
attached_group_policies = []
|
||||||
GroupName=group.name
|
for page in list_attached_group_policies_paginator.paginate(
|
||||||
):
|
GroupName=group.name
|
||||||
for attached_group_policy in page["AttachedPolicies"]:
|
):
|
||||||
attached_group_policies.append(attached_group_policy)
|
for attached_group_policy in page["AttachedPolicies"]:
|
||||||
|
attached_group_policies.append(attached_group_policy)
|
||||||
|
|
||||||
group.attached_policies = attached_group_policies
|
group.attached_policies = attached_group_policies
|
||||||
|
except Exception as error:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
@@ -337,18 +355,33 @@ class IAM(AWSService):
|
|||||||
logger.info("IAM - List Attached User Policies...")
|
logger.info("IAM - List Attached User Policies...")
|
||||||
try:
|
try:
|
||||||
for user in self.users:
|
for user in self.users:
|
||||||
attached_user_policies = []
|
try:
|
||||||
get_user_attached_policies_paginator = self.client.get_paginator(
|
attached_user_policies = []
|
||||||
"list_attached_user_policies"
|
get_user_attached_policies_paginator = self.client.get_paginator(
|
||||||
)
|
"list_attached_user_policies"
|
||||||
for page in get_user_attached_policies_paginator.paginate(
|
)
|
||||||
UserName=user.name
|
for page in get_user_attached_policies_paginator.paginate(
|
||||||
):
|
UserName=user.name
|
||||||
for policy in page["AttachedPolicies"]:
|
):
|
||||||
attached_user_policies.append(policy)
|
for policy in page["AttachedPolicies"]:
|
||||||
|
attached_user_policies.append(policy)
|
||||||
|
|
||||||
user.attached_policies = attached_user_policies
|
user.attached_policies = attached_user_policies
|
||||||
|
|
||||||
|
except ClientError as error:
|
||||||
|
if error.response["Error"]["Code"] == "NoSuchEntity":
|
||||||
|
logger.warning(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
@@ -371,10 +404,19 @@ class IAM(AWSService):
|
|||||||
|
|
||||||
role.attached_policies = attached_role_policies
|
role.attached_policies = attached_role_policies
|
||||||
except ClientError as error:
|
except ClientError as error:
|
||||||
if error.response["Error"]["Code"] == "NoSuchEntityException":
|
if error.response["Error"]["Code"] == "NoSuchEntity":
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -639,8 +681,16 @@ class IAM(AWSService):
|
|||||||
response = self.client.list_role_tags(RoleName=role.name)["Tags"]
|
response = self.client.list_role_tags(RoleName=role.name)["Tags"]
|
||||||
role.tags = response
|
role.tags = response
|
||||||
except ClientError as error:
|
except ClientError as error:
|
||||||
if error.response["Error"]["Code"] == "NoSuchEntityException":
|
if error.response["Error"]["Code"] == "NoSuchEntity":
|
||||||
role.tags = []
|
role.tags = []
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
except Exception as error:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -653,8 +703,12 @@ class IAM(AWSService):
|
|||||||
response = self.client.list_user_tags(UserName=user.name)["Tags"]
|
response = self.client.list_user_tags(UserName=user.name)["Tags"]
|
||||||
user.tags = response
|
user.tags = response
|
||||||
except ClientError as error:
|
except ClientError as error:
|
||||||
if error.response["Error"]["Code"] == "NoSuchEntityException":
|
if error.response["Error"]["Code"] == "NoSuchEntity":
|
||||||
user.tags = []
|
user.tags = []
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -664,13 +718,22 @@ class IAM(AWSService):
|
|||||||
try:
|
try:
|
||||||
for policy in self.policies:
|
for policy in self.policies:
|
||||||
try:
|
try:
|
||||||
response = self.client.list_policy_tags(PolicyArn=policy.arn)[
|
if policy.type != "Inline":
|
||||||
"Tags"
|
response = self.client.list_policy_tags(PolicyArn=policy.arn)[
|
||||||
]
|
"Tags"
|
||||||
policy.tags = response
|
]
|
||||||
|
policy.tags = response
|
||||||
except ClientError as error:
|
except ClientError as error:
|
||||||
if error.response["Error"]["Code"] == "NoSuchEntityException":
|
if error.response["Error"]["Code"] == "NoSuchEntity":
|
||||||
policy.tags = []
|
policy.tags = []
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
except Exception as error:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -697,9 +760,19 @@ class IAM(AWSService):
|
|||||||
]
|
]
|
||||||
|
|
||||||
except ClientError as error:
|
except ClientError as error:
|
||||||
|
if error.response["Error"]["Code"] == "NoSuchEntity":
|
||||||
|
logger.warning(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
@@ -717,6 +790,15 @@ class IAM(AWSService):
|
|||||||
"AccessKeyMetadata"
|
"AccessKeyMetadata"
|
||||||
]
|
]
|
||||||
except ClientError as error:
|
except ClientError as error:
|
||||||
|
if error.response["Error"]["Code"] == "NoSuchEntity":
|
||||||
|
logger.warning(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{self.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,9 +13,14 @@ class rds_instance_deprecated_engine_version(Check):
|
|||||||
report.resource_arn = db_instance.arn
|
report.resource_arn = db_instance.arn
|
||||||
report.resource_tags = db_instance.tags
|
report.resource_tags = db_instance.tags
|
||||||
report.status_extended = f"RDS instance {db_instance.id} is using a deprecated engine {db_instance.engine} with version {db_instance.engine_version}."
|
report.status_extended = f"RDS instance {db_instance.id} is using a deprecated engine {db_instance.engine} with version {db_instance.engine_version}."
|
||||||
|
|
||||||
if (
|
if (
|
||||||
db_instance.engine_version
|
hasattr(
|
||||||
|
rds_client.db_engines.get(db_instance.region, {}).get(
|
||||||
|
db_instance.engine, {}
|
||||||
|
),
|
||||||
|
"engine_versions",
|
||||||
|
)
|
||||||
|
and db_instance.engine_version
|
||||||
in rds_client.db_engines[db_instance.region][
|
in rds_client.db_engines[db_instance.region][
|
||||||
db_instance.engine
|
db_instance.engine
|
||||||
].engine_versions
|
].engine_versions
|
||||||
|
|||||||
@@ -16,23 +16,30 @@ class SQS(AWSService):
|
|||||||
super().__init__(__class__.__name__, audit_info)
|
super().__init__(__class__.__name__, audit_info)
|
||||||
self.queues = []
|
self.queues = []
|
||||||
self.__threading_call__(self.__list_queues__)
|
self.__threading_call__(self.__list_queues__)
|
||||||
self.__get_queue_attributes__(self.regional_clients)
|
self.__get_queue_attributes__()
|
||||||
self.__list_queue_tags__()
|
self.__list_queue_tags__()
|
||||||
|
|
||||||
def __list_queues__(self, regional_client):
|
def __list_queues__(self, regional_client):
|
||||||
logger.info("SQS - describing queues...")
|
logger.info("SQS - describing queues...")
|
||||||
try:
|
try:
|
||||||
list_queues_paginator = regional_client.get_paginator("list_queues")
|
list_queues_paginator = regional_client.get_paginator("list_queues")
|
||||||
for page in list_queues_paginator.paginate():
|
# The SQS API uses nonstandard pagination
|
||||||
|
# you must specify a PageSize if there are more than 1000 queues
|
||||||
|
for page in list_queues_paginator.paginate(
|
||||||
|
PaginationConfig={"PageSize": 1000}
|
||||||
|
):
|
||||||
if "QueueUrls" in page:
|
if "QueueUrls" in page:
|
||||||
for queue in page["QueueUrls"]:
|
for queue in page["QueueUrls"]:
|
||||||
arn = f"arn:{self.audited_partition}:sqs:{regional_client.region}:{self.audited_account}:{queue}"
|
# the queue name is the last path segment of the url
|
||||||
|
queue_name = queue.split("/")[-1]
|
||||||
|
arn = f"arn:{self.audited_partition}:sqs:{regional_client.region}:{self.audited_account}:{queue_name}"
|
||||||
if not self.audit_resources or (
|
if not self.audit_resources or (
|
||||||
is_resource_filtered(arn, self.audit_resources)
|
is_resource_filtered(arn, self.audit_resources)
|
||||||
):
|
):
|
||||||
self.queues.append(
|
self.queues.append(
|
||||||
Queue(
|
Queue(
|
||||||
arn=arn,
|
arn=arn,
|
||||||
|
name=queue_name,
|
||||||
id=queue,
|
id=queue,
|
||||||
region=regional_client.region,
|
region=regional_client.region,
|
||||||
)
|
)
|
||||||
@@ -42,28 +49,46 @@ class SQS(AWSService):
|
|||||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
)
|
)
|
||||||
|
|
||||||
def __get_queue_attributes__(self, regional_clients):
|
def __get_queue_attributes__(self):
|
||||||
try:
|
try:
|
||||||
logger.info("SQS - describing queue attributes...")
|
logger.info("SQS - describing queue attributes...")
|
||||||
for queue in self.queues:
|
for queue in self.queues:
|
||||||
regional_client = regional_clients[queue.region]
|
try:
|
||||||
queue_attributes = regional_client.get_queue_attributes(
|
regional_client = self.regional_clients[queue.region]
|
||||||
QueueUrl=queue.id, AttributeNames=["All"]
|
queue_attributes = regional_client.get_queue_attributes(
|
||||||
)
|
QueueUrl=queue.id, AttributeNames=["All"]
|
||||||
if "Attributes" in queue_attributes:
|
)
|
||||||
if "Policy" in queue_attributes["Attributes"]:
|
if "Attributes" in queue_attributes:
|
||||||
queue.policy = loads(queue_attributes["Attributes"]["Policy"])
|
if "Policy" in queue_attributes["Attributes"]:
|
||||||
if "KmsMasterKeyId" in queue_attributes["Attributes"]:
|
queue.policy = loads(
|
||||||
queue.kms_key_id = queue_attributes["Attributes"][
|
queue_attributes["Attributes"]["Policy"]
|
||||||
"KmsMasterKeyId"
|
)
|
||||||
]
|
if "KmsMasterKeyId" in queue_attributes["Attributes"]:
|
||||||
if "SqsManagedSseEnabled" in queue_attributes["Attributes"]:
|
queue.kms_key_id = queue_attributes["Attributes"][
|
||||||
if (
|
"KmsMasterKeyId"
|
||||||
queue_attributes["Attributes"]["SqsManagedSseEnabled"]
|
]
|
||||||
== "true"
|
if "SqsManagedSseEnabled" in queue_attributes["Attributes"]:
|
||||||
):
|
if (
|
||||||
queue.kms_key_id = "SqsManagedSseEnabled"
|
queue_attributes["Attributes"]["SqsManagedSseEnabled"]
|
||||||
|
== "true"
|
||||||
|
):
|
||||||
|
queue.kms_key_id = "SqsManagedSseEnabled"
|
||||||
|
except ClientError as error:
|
||||||
|
if (
|
||||||
|
error.response["Error"]["Code"]
|
||||||
|
== "AWS.SimpleQueueService.NonExistentQueue"
|
||||||
|
):
|
||||||
|
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"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
@@ -87,6 +112,14 @@ class SQS(AWSService):
|
|||||||
logger.warning(
|
logger.warning(
|
||||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
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"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -96,6 +129,7 @@ class SQS(AWSService):
|
|||||||
|
|
||||||
class Queue(BaseModel):
|
class Queue(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
|
name: str
|
||||||
arn: str
|
arn: str
|
||||||
region: str
|
region: str
|
||||||
policy: dict = None
|
policy: dict = None
|
||||||
|
|||||||
32
prowler/providers/common/clean.py
Normal file
32
prowler/providers/common/clean.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import importlib
|
||||||
|
import sys
|
||||||
|
from shutil import rmtree
|
||||||
|
|
||||||
|
from prowler.config.config import default_output_directory
|
||||||
|
from prowler.lib.logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
def clean_provider_local_output_directories(args):
|
||||||
|
"""
|
||||||
|
clean_provider_local_output_directories cleans deletes local custom dirs when output is sent to remote provider storage
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# import provider cleaning function
|
||||||
|
provider_clean_function = f"clean_{args.provider}_local_output_directories"
|
||||||
|
getattr(importlib.import_module(__name__), provider_clean_function)(args)
|
||||||
|
except AttributeError as attribute_exception:
|
||||||
|
logger.info(
|
||||||
|
f"Cleaning local output directories not initialized for provider {args.provider}: {attribute_exception}"
|
||||||
|
)
|
||||||
|
except Exception as error:
|
||||||
|
logger.critical(
|
||||||
|
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def clean_aws_local_output_directories(args):
|
||||||
|
"""clean_aws_provider_local_output_directories deletes local custom dirs when output is sent to remote provider storage for aws provider"""
|
||||||
|
if args.output_bucket or args.output_bucket_no_assume:
|
||||||
|
if args.output_directory != default_output_directory:
|
||||||
|
rmtree(args.output_directory)
|
||||||
@@ -22,7 +22,7 @@ packages = [
|
|||||||
{include = "prowler"}
|
{include = "prowler"}
|
||||||
]
|
]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
version = "3.11.0"
|
version = "3.11.1"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
alive-progress = "3.1.4"
|
alive-progress = "3.1.4"
|
||||||
@@ -38,10 +38,10 @@ boto3 = "1.26.165"
|
|||||||
botocore = "1.29.165"
|
botocore = "1.29.165"
|
||||||
colorama = "0.4.6"
|
colorama = "0.4.6"
|
||||||
detect-secrets = "1.4.0"
|
detect-secrets = "1.4.0"
|
||||||
google-api-python-client = "2.105.0"
|
google-api-python-client = "2.106.0"
|
||||||
google-auth-httplib2 = "^0.1.0"
|
google-auth-httplib2 = "^0.1.0"
|
||||||
mkdocs = {version = "1.5.3", optional = true}
|
mkdocs = {version = "1.5.3", optional = true}
|
||||||
mkdocs-material = {version = "9.4.7", optional = true}
|
mkdocs-material = {version = "9.4.8", optional = true}
|
||||||
msgraph-core = "0.2.2"
|
msgraph-core = "0.2.2"
|
||||||
pydantic = "1.10.13"
|
pydantic = "1.10.13"
|
||||||
python = "^3.9"
|
python = "^3.9"
|
||||||
|
|||||||
@@ -8,15 +8,18 @@ from prowler.providers.aws.lib.allowlist.allowlist import (
|
|||||||
is_allowlisted,
|
is_allowlisted,
|
||||||
is_allowlisted_in_check,
|
is_allowlisted_in_check,
|
||||||
is_allowlisted_in_region,
|
is_allowlisted_in_region,
|
||||||
|
is_allowlisted_in_resource,
|
||||||
is_allowlisted_in_tags,
|
is_allowlisted_in_tags,
|
||||||
is_excepted,
|
is_excepted,
|
||||||
parse_allowlist_file,
|
parse_allowlist_file,
|
||||||
)
|
)
|
||||||
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info
|
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info
|
||||||
from prowler.providers.common.models import Audit_Metadata
|
from prowler.providers.common.models import Audit_Metadata
|
||||||
|
from tests.providers.aws.audit_info_utils import (
|
||||||
AWS_ACCOUNT_NUMBER = "123456789012"
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_REGION = "us-east-1"
|
AWS_REGION_EU_WEST_1,
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Test_Allowlist:
|
class Test_Allowlist:
|
||||||
@@ -56,7 +59,7 @@ class Test_Allowlist:
|
|||||||
def test_s3_allowlist(self):
|
def test_s3_allowlist(self):
|
||||||
audit_info = self.set_mocked_audit_info()
|
audit_info = self.set_mocked_audit_info()
|
||||||
# Create bucket and upload allowlist yaml
|
# Create bucket and upload allowlist yaml
|
||||||
s3_resource = resource("s3", region_name=AWS_REGION)
|
s3_resource = resource("s3", region_name=AWS_REGION_US_EAST_1)
|
||||||
s3_resource.create_bucket(Bucket="test-allowlist")
|
s3_resource.create_bucket(Bucket="test-allowlist")
|
||||||
s3_resource.Object("test-allowlist", "allowlist.yaml").put(
|
s3_resource.Object("test-allowlist", "allowlist.yaml").put(
|
||||||
Body=open(
|
Body=open(
|
||||||
@@ -75,7 +78,7 @@ class Test_Allowlist:
|
|||||||
def test_dynamo_allowlist(self):
|
def test_dynamo_allowlist(self):
|
||||||
audit_info = self.set_mocked_audit_info()
|
audit_info = self.set_mocked_audit_info()
|
||||||
# Create table and put item
|
# Create table and put item
|
||||||
dynamodb_resource = resource("dynamodb", region_name=AWS_REGION)
|
dynamodb_resource = resource("dynamodb", region_name=AWS_REGION_US_EAST_1)
|
||||||
table_name = "test-allowlist"
|
table_name = "test-allowlist"
|
||||||
params = {
|
params = {
|
||||||
"TableName": table_name,
|
"TableName": table_name,
|
||||||
@@ -97,7 +100,7 @@ class Test_Allowlist:
|
|||||||
Item={
|
Item={
|
||||||
"Accounts": "*",
|
"Accounts": "*",
|
||||||
"Checks": "iam_user_hardware_mfa_enabled",
|
"Checks": "iam_user_hardware_mfa_enabled",
|
||||||
"Regions": ["eu-west-1", AWS_REGION],
|
"Regions": [AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1],
|
||||||
"Resources": ["keyword"],
|
"Resources": ["keyword"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -107,7 +110,7 @@ class Test_Allowlist:
|
|||||||
in parse_allowlist_file(
|
in parse_allowlist_file(
|
||||||
audit_info,
|
audit_info,
|
||||||
"arn:aws:dynamodb:"
|
"arn:aws:dynamodb:"
|
||||||
+ AWS_REGION
|
+ AWS_REGION_US_EAST_1
|
||||||
+ ":"
|
+ ":"
|
||||||
+ str(AWS_ACCOUNT_NUMBER)
|
+ str(AWS_ACCOUNT_NUMBER)
|
||||||
+ ":table/"
|
+ ":table/"
|
||||||
@@ -119,7 +122,7 @@ class Test_Allowlist:
|
|||||||
def test_dynamo_allowlist_with_tags(self):
|
def test_dynamo_allowlist_with_tags(self):
|
||||||
audit_info = self.set_mocked_audit_info()
|
audit_info = self.set_mocked_audit_info()
|
||||||
# Create table and put item
|
# Create table and put item
|
||||||
dynamodb_resource = resource("dynamodb", region_name=AWS_REGION)
|
dynamodb_resource = resource("dynamodb", region_name=AWS_REGION_US_EAST_1)
|
||||||
table_name = "test-allowlist"
|
table_name = "test-allowlist"
|
||||||
params = {
|
params = {
|
||||||
"TableName": table_name,
|
"TableName": table_name,
|
||||||
@@ -152,7 +155,7 @@ class Test_Allowlist:
|
|||||||
in parse_allowlist_file(
|
in parse_allowlist_file(
|
||||||
audit_info,
|
audit_info,
|
||||||
"arn:aws:dynamodb:"
|
"arn:aws:dynamodb:"
|
||||||
+ AWS_REGION
|
+ AWS_REGION_US_EAST_1
|
||||||
+ ":"
|
+ ":"
|
||||||
+ str(AWS_ACCOUNT_NUMBER)
|
+ str(AWS_ACCOUNT_NUMBER)
|
||||||
+ ":table/"
|
+ ":table/"
|
||||||
@@ -169,7 +172,7 @@ class Test_Allowlist:
|
|||||||
"*": {
|
"*": {
|
||||||
"Checks": {
|
"Checks": {
|
||||||
"check_test": {
|
"check_test": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": ["prowler", "^test", "prowler-pro"],
|
"Resources": ["prowler", "^test", "prowler-pro"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,7 +186,7 @@ class Test_Allowlist:
|
|||||||
finding_1.check_metadata = MagicMock
|
finding_1.check_metadata = MagicMock
|
||||||
finding_1.check_metadata.CheckID = "check_test"
|
finding_1.check_metadata.CheckID = "check_test"
|
||||||
finding_1.status = "FAIL"
|
finding_1.status = "FAIL"
|
||||||
finding_1.region = AWS_REGION
|
finding_1.region = AWS_REGION_US_EAST_1
|
||||||
finding_1.resource_id = "prowler"
|
finding_1.resource_id = "prowler"
|
||||||
finding_1.resource_tags = []
|
finding_1.resource_tags = []
|
||||||
|
|
||||||
@@ -195,6 +198,66 @@ class Test_Allowlist:
|
|||||||
assert len(allowlisted_findings) == 1
|
assert len(allowlisted_findings) == 1
|
||||||
assert allowlisted_findings[0].status == "WARNING"
|
assert allowlisted_findings[0].status == "WARNING"
|
||||||
|
|
||||||
|
def test_is_allowlisted_with_everything_excepted(self):
|
||||||
|
allowlist = {
|
||||||
|
"Accounts": {
|
||||||
|
"*": {
|
||||||
|
"Checks": {
|
||||||
|
"athena_*": {
|
||||||
|
"Regions": "*",
|
||||||
|
"Resources": "*",
|
||||||
|
"Tags": "*",
|
||||||
|
"Exceptions": {
|
||||||
|
"Accounts": ["*"],
|
||||||
|
"Regions": ["*"],
|
||||||
|
"Resources": ["*"],
|
||||||
|
"Tags": ["*"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert not is_allowlisted(
|
||||||
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"athena_1",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler",
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_is_allowlisted_with_default_allowlist(self):
|
||||||
|
allowlist = {
|
||||||
|
"Accounts": {
|
||||||
|
"*": {
|
||||||
|
"Checks": {
|
||||||
|
"*": {
|
||||||
|
"Tags": ["*"],
|
||||||
|
"Regions": ["*"],
|
||||||
|
"Resources": ["*"],
|
||||||
|
"Exceptions": {
|
||||||
|
"Tags": [],
|
||||||
|
"Regions": [],
|
||||||
|
"Accounts": [],
|
||||||
|
"Resources": [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert is_allowlisted(
|
||||||
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"athena_1",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler",
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
||||||
def test_is_allowlisted(self):
|
def test_is_allowlisted(self):
|
||||||
# Allowlist example
|
# Allowlist example
|
||||||
allowlist = {
|
allowlist = {
|
||||||
@@ -202,7 +265,7 @@ class Test_Allowlist:
|
|||||||
"*": {
|
"*": {
|
||||||
"Checks": {
|
"Checks": {
|
||||||
"check_test": {
|
"check_test": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": ["prowler", "^test", "prowler-pro"],
|
"Resources": ["prowler", "^test", "prowler-pro"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,22 +274,37 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist,
|
||||||
)
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
assert is_allowlisted(
|
AWS_REGION_US_EAST_1,
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", ""
|
"prowler",
|
||||||
)
|
"",
|
||||||
|
|
||||||
assert is_allowlisted(
|
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", ""
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist,
|
allowlist,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
"check_test",
|
"check_test",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler-test",
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert is_allowlisted(
|
||||||
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"test-prowler",
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert is_allowlisted(
|
||||||
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler-pro-test",
|
"prowler-pro-test",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -244,7 +322,7 @@ class Test_Allowlist:
|
|||||||
"*": {
|
"*": {
|
||||||
"Checks": {
|
"Checks": {
|
||||||
"check_test": {
|
"check_test": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": [".*"],
|
"Resources": [".*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,15 +331,30 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler-test",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"test-prowler",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
@@ -277,7 +370,7 @@ class Test_Allowlist:
|
|||||||
"*": {
|
"*": {
|
||||||
"Checks": {
|
"Checks": {
|
||||||
"check_test": {
|
"check_test": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": ["*"],
|
"Resources": ["*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,15 +379,30 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler-test",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"test-prowler",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
@@ -310,7 +418,7 @@ class Test_Allowlist:
|
|||||||
"*": {
|
"*": {
|
||||||
"Checks": {
|
"Checks": {
|
||||||
"check_test_2": {
|
"check_test_2": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": ["*"],
|
"Resources": ["*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,7 +426,7 @@ class Test_Allowlist:
|
|||||||
AWS_ACCOUNT_NUMBER: {
|
AWS_ACCOUNT_NUMBER: {
|
||||||
"Checks": {
|
"Checks": {
|
||||||
"check_test": {
|
"check_test": {
|
||||||
"Regions": [AWS_REGION],
|
"Regions": [AWS_REGION_US_EAST_1],
|
||||||
"Resources": ["*"],
|
"Resources": ["*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,19 +435,39 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test_2", AWS_REGION, "prowler", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test_2",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler-test", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler-test",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "test-prowler", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"test-prowler",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
@@ -354,7 +482,7 @@ class Test_Allowlist:
|
|||||||
AWS_ACCOUNT_NUMBER: {
|
AWS_ACCOUNT_NUMBER: {
|
||||||
"Checks": {
|
"Checks": {
|
||||||
"check_test": {
|
"check_test": {
|
||||||
"Regions": [AWS_REGION],
|
"Regions": [AWS_REGION_US_EAST_1],
|
||||||
"Resources": ["prowler"],
|
"Resources": ["prowler"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,7 +491,12 @@ class Test_Allowlist:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert is_allowlisted(
|
assert is_allowlisted(
|
||||||
allowlist, AWS_ACCOUNT_NUMBER, "check_test", AWS_REGION, "prowler", ""
|
allowlist,
|
||||||
|
AWS_ACCOUNT_NUMBER,
|
||||||
|
"check_test",
|
||||||
|
AWS_REGION_US_EAST_1,
|
||||||
|
"prowler",
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
@@ -373,47 +506,27 @@ class Test_Allowlist:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_is_allowlisted_in_region(self):
|
def test_is_allowlisted_in_region(self):
|
||||||
# Allowlist example
|
allowlisted_regions = [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1]
|
||||||
allowlisted_regions = [AWS_REGION, "eu-west-1"]
|
finding_region = AWS_REGION_US_EAST_1
|
||||||
allowlisted_resources = ["*"]
|
|
||||||
|
|
||||||
assert is_allowlisted_in_region(
|
assert is_allowlisted_in_region(allowlisted_regions, finding_region)
|
||||||
allowlisted_regions, allowlisted_resources, None, AWS_REGION, "prowler", ""
|
|
||||||
)
|
|
||||||
|
|
||||||
assert is_allowlisted_in_region(
|
def test_is_allowlisted_in_region_wildcard(self):
|
||||||
allowlisted_regions,
|
allowlisted_regions = ["*"]
|
||||||
allowlisted_resources,
|
finding_region = AWS_REGION_US_EAST_1
|
||||||
None,
|
|
||||||
AWS_REGION,
|
|
||||||
"prowler-test",
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
|
|
||||||
assert is_allowlisted_in_region(
|
assert is_allowlisted_in_region(allowlisted_regions, finding_region)
|
||||||
allowlisted_regions,
|
|
||||||
allowlisted_resources,
|
|
||||||
None,
|
|
||||||
AWS_REGION,
|
|
||||||
"test-prowler",
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
|
|
||||||
assert not (
|
def test_is_not_allowlisted_in_region(self):
|
||||||
is_allowlisted_in_region(
|
allowlisted_regions = [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1]
|
||||||
allowlisted_regions,
|
finding_region = "eu-west-2"
|
||||||
allowlisted_resources,
|
|
||||||
None,
|
assert not is_allowlisted_in_region(allowlisted_regions, finding_region)
|
||||||
"us-east-2",
|
|
||||||
"test",
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_is_allowlisted_in_check(self):
|
def test_is_allowlisted_in_check(self):
|
||||||
allowlisted_checks = {
|
allowlisted_checks = {
|
||||||
"check_test": {
|
"check_test": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": ["*"],
|
"Resources": ["*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -421,9 +534,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"check_test",
|
"check_test",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -431,9 +543,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"check_test",
|
"check_test",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler-test",
|
"prowler-test",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -441,9 +552,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"check_test",
|
"check_test",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"test-prowler",
|
"test-prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -452,7 +562,6 @@ class Test_Allowlist:
|
|||||||
is_allowlisted_in_check(
|
is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"check_test",
|
"check_test",
|
||||||
"us-east-2",
|
"us-east-2",
|
||||||
"test",
|
"test",
|
||||||
@@ -464,7 +573,7 @@ class Test_Allowlist:
|
|||||||
# Allowlist example
|
# Allowlist example
|
||||||
allowlisted_checks = {
|
allowlisted_checks = {
|
||||||
"s3_*": {
|
"s3_*": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": ["*"],
|
"Resources": ["*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -472,9 +581,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"s3_bucket_public_access",
|
"s3_bucket_public_access",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -482,9 +590,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"s3_bucket_no_mfa_delete",
|
"s3_bucket_no_mfa_delete",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler-test",
|
"prowler-test",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -492,9 +599,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"s3_bucket_policy_public_write_access",
|
"s3_bucket_policy_public_write_access",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"test-prowler",
|
"test-prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -503,9 +609,8 @@ class Test_Allowlist:
|
|||||||
is_allowlisted_in_check(
|
is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"iam_user_hardware_mfa_enabled",
|
"iam_user_hardware_mfa_enabled",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"test",
|
"test",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -514,7 +619,7 @@ class Test_Allowlist:
|
|||||||
def test_is_allowlisted_lambda_generic_check(self):
|
def test_is_allowlisted_lambda_generic_check(self):
|
||||||
allowlisted_checks = {
|
allowlisted_checks = {
|
||||||
"lambda_*": {
|
"lambda_*": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": ["*"],
|
"Resources": ["*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -522,9 +627,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"awslambda_function_invoke_api_operations_cloudtrail_logging_enabled",
|
"awslambda_function_invoke_api_operations_cloudtrail_logging_enabled",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -532,9 +636,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"awslambda_function_no_secrets_in_code",
|
"awslambda_function_no_secrets_in_code",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -542,9 +645,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"awslambda_function_no_secrets_in_variables",
|
"awslambda_function_no_secrets_in_variables",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -552,9 +654,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"awslambda_function_not_publicly_accessible",
|
"awslambda_function_not_publicly_accessible",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -562,9 +663,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"awslambda_function_url_cors_policy",
|
"awslambda_function_url_cors_policy",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -572,9 +672,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"awslambda_function_url_public",
|
"awslambda_function_url_public",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -582,9 +681,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"awslambda_function_using_supported_runtimes",
|
"awslambda_function_using_supported_runtimes",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -592,7 +690,7 @@ class Test_Allowlist:
|
|||||||
def test_is_allowlisted_lambda_concrete_check(self):
|
def test_is_allowlisted_lambda_concrete_check(self):
|
||||||
allowlisted_checks = {
|
allowlisted_checks = {
|
||||||
"lambda_function_no_secrets_in_variables": {
|
"lambda_function_no_secrets_in_variables": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": ["*"],
|
"Resources": ["*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -600,9 +698,8 @@ class Test_Allowlist:
|
|||||||
assert is_allowlisted_in_check(
|
assert is_allowlisted_in_check(
|
||||||
allowlisted_checks,
|
allowlisted_checks,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
AWS_ACCOUNT_NUMBER,
|
|
||||||
"awslambda_function_no_secrets_in_variables",
|
"awslambda_function_no_secrets_in_variables",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
@@ -614,7 +711,7 @@ class Test_Allowlist:
|
|||||||
"*": {
|
"*": {
|
||||||
"Checks": {
|
"Checks": {
|
||||||
"check_test": {
|
"check_test": {
|
||||||
"Regions": [AWS_REGION, "eu-west-1"],
|
"Regions": [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1],
|
||||||
"Resources": ["*"],
|
"Resources": ["*"],
|
||||||
"Tags": ["environment=dev", "project=.*"],
|
"Tags": ["environment=dev", "project=.*"],
|
||||||
}
|
}
|
||||||
@@ -627,7 +724,7 @@ class Test_Allowlist:
|
|||||||
allowlist,
|
allowlist,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
"check_test",
|
"check_test",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler",
|
"prowler",
|
||||||
"environment=dev",
|
"environment=dev",
|
||||||
)
|
)
|
||||||
@@ -636,7 +733,7 @@ class Test_Allowlist:
|
|||||||
allowlist,
|
allowlist,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
"check_test",
|
"check_test",
|
||||||
AWS_REGION,
|
AWS_REGION_US_EAST_1,
|
||||||
"prowler-test",
|
"prowler-test",
|
||||||
"environment=dev | project=prowler",
|
"environment=dev | project=prowler",
|
||||||
)
|
)
|
||||||
@@ -654,56 +751,45 @@ class Test_Allowlist:
|
|||||||
|
|
||||||
def test_is_allowlisted_in_tags(self):
|
def test_is_allowlisted_in_tags(self):
|
||||||
allowlist_tags = ["environment=dev", "project=prowler"]
|
allowlist_tags = ["environment=dev", "project=prowler"]
|
||||||
allowlist_resource = "*"
|
|
||||||
|
assert is_allowlisted_in_tags(allowlist_tags, "environment=dev")
|
||||||
|
|
||||||
assert is_allowlisted_in_tags(
|
assert is_allowlisted_in_tags(
|
||||||
allowlist_tags,
|
allowlist_tags,
|
||||||
"*",
|
|
||||||
"prowler",
|
|
||||||
"environment=dev",
|
|
||||||
)
|
|
||||||
|
|
||||||
assert is_allowlisted_in_tags(
|
|
||||||
allowlist_tags,
|
|
||||||
allowlist_resource,
|
|
||||||
"prowler-test",
|
|
||||||
"environment=dev | project=prowler",
|
"environment=dev | project=prowler",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not (
|
assert not (
|
||||||
is_allowlisted_in_tags(
|
is_allowlisted_in_tags(
|
||||||
allowlist_tags,
|
allowlist_tags,
|
||||||
allowlist_resource,
|
|
||||||
"test",
|
|
||||||
"environment=pro",
|
"environment=pro",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_is_allowlisted_in_tags_regex(self):
|
def test_is_allowlisted_in_tags_regex(self):
|
||||||
allowlist_tags = ["environment=(dev|test)", ".*=prowler"]
|
allowlist_tags = ["environment=(dev|test)", ".*=prowler"]
|
||||||
allowlist_resource = "*"
|
|
||||||
|
|
||||||
assert is_allowlisted_in_tags(
|
assert is_allowlisted_in_tags(
|
||||||
allowlist_tags,
|
allowlist_tags,
|
||||||
allowlist_resource,
|
|
||||||
"prowler-test",
|
|
||||||
"environment=test | proj=prowler",
|
"environment=test | proj=prowler",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert is_allowlisted_in_tags(
|
assert is_allowlisted_in_tags(
|
||||||
allowlist_tags,
|
allowlist_tags,
|
||||||
allowlist_resource,
|
|
||||||
"prowler-test",
|
|
||||||
"env=prod | project=prowler",
|
"env=prod | project=prowler",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not is_allowlisted_in_tags(
|
assert not is_allowlisted_in_tags(
|
||||||
allowlist_tags,
|
allowlist_tags,
|
||||||
allowlist_resource,
|
|
||||||
"prowler-test",
|
|
||||||
"environment=prod | project=myproj",
|
"environment=prod | project=myproj",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_is_allowlisted_in_tags_with_no_tags_in_finding(self):
|
||||||
|
allowlist_tags = ["environment=(dev|test)", ".*=prowler"]
|
||||||
|
finding_tags = ""
|
||||||
|
|
||||||
|
assert not is_allowlisted_in_tags(allowlist_tags, finding_tags)
|
||||||
|
|
||||||
def test_is_excepted(self):
|
def test_is_excepted(self):
|
||||||
# Allowlist example
|
# Allowlist example
|
||||||
exceptions = {
|
exceptions = {
|
||||||
@@ -737,6 +823,28 @@ class Test_Allowlist:
|
|||||||
"environment=test",
|
"environment=test",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_is_excepted_all_wildcard(self):
|
||||||
|
exceptions = {
|
||||||
|
"Accounts": ["*"],
|
||||||
|
"Regions": ["*"],
|
||||||
|
"Resources": ["*"],
|
||||||
|
"Tags": ["*"],
|
||||||
|
}
|
||||||
|
assert is_excepted(
|
||||||
|
exceptions, AWS_ACCOUNT_NUMBER, "eu-south-2", "test", "environment=test"
|
||||||
|
)
|
||||||
|
assert not is_excepted(
|
||||||
|
exceptions, AWS_ACCOUNT_NUMBER, "eu-south-2", "test", None
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_is_not_excepted(self):
|
||||||
|
exceptions = {
|
||||||
|
"Accounts": [AWS_ACCOUNT_NUMBER],
|
||||||
|
"Regions": ["eu-central-1", "eu-south-3"],
|
||||||
|
"Resources": ["test"],
|
||||||
|
"Tags": ["environment=test", "project=.*"],
|
||||||
|
}
|
||||||
|
|
||||||
assert not is_excepted(
|
assert not is_excepted(
|
||||||
exceptions,
|
exceptions,
|
||||||
AWS_ACCOUNT_NUMBER,
|
AWS_ACCOUNT_NUMBER,
|
||||||
@@ -760,3 +868,11 @@ class Test_Allowlist:
|
|||||||
"test",
|
"test",
|
||||||
"environment=pro",
|
"environment=pro",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_is_allowlisted_in_resource(self):
|
||||||
|
allowlist_resources = ["prowler", "^test", "prowler-pro"]
|
||||||
|
|
||||||
|
assert is_allowlisted_in_resource(allowlist_resources, "prowler")
|
||||||
|
assert is_allowlisted_in_resource(allowlist_resources, "prowler-test")
|
||||||
|
assert is_allowlisted_in_resource(allowlist_resources, "test-prowler")
|
||||||
|
assert not is_allowlisted_in_resource(allowlist_resources, "random")
|
||||||
|
|||||||
@@ -1282,3 +1282,75 @@ class Test_policy_condition_parser:
|
|||||||
assert not is_account_only_allowed_in_condition(
|
assert not is_account_only_allowed_in_condition(
|
||||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_condition_parser_two_lists_unrestrictive(self):
|
||||||
|
condition_statement = {
|
||||||
|
"StringLike": {
|
||||||
|
"AWS:ResourceAccount": [
|
||||||
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||||
|
NON_TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ArnLike": {
|
||||||
|
"AWS:SourceArn": [
|
||||||
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
||||||
|
f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert not is_account_only_allowed_in_condition(
|
||||||
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_condition_parser_two_lists_both_restrictive(self):
|
||||||
|
condition_statement = {
|
||||||
|
"StringLike": {
|
||||||
|
"AWS:ResourceAccount": [
|
||||||
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ArnLike": {
|
||||||
|
"AWS:SourceArn": [
|
||||||
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert is_account_only_allowed_in_condition(
|
||||||
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_condition_parser_two_lists_first_restrictive(self):
|
||||||
|
condition_statement = {
|
||||||
|
"StringLike": {
|
||||||
|
"AWS:ResourceAccount": [
|
||||||
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ArnLike": {
|
||||||
|
"AWS:SourceArn": [
|
||||||
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
||||||
|
f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert is_account_only_allowed_in_condition(
|
||||||
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_condition_parser_two_lists_second_restrictive(self):
|
||||||
|
condition_statement = {
|
||||||
|
"StringLike": {
|
||||||
|
"AWS:ResourceAccount": [
|
||||||
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||||
|
NON_TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ArnLike": {
|
||||||
|
"AWS:SourceArn": [
|
||||||
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert is_account_only_allowed_in_condition(
|
||||||
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||||
|
)
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ from prowler.providers.aws.services.sqs.sqs_service import Queue
|
|||||||
AWS_REGION = "eu-west-1"
|
AWS_REGION = "eu-west-1"
|
||||||
AWS_ACCOUNT_NUMBER = "123456789012"
|
AWS_ACCOUNT_NUMBER = "123456789012"
|
||||||
|
|
||||||
queue_id = str(uuid4())
|
test_queue_name = str(uuid4())
|
||||||
topic_arn = f"arn:aws:sqs:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:{queue_id}"
|
test_queue_url = (
|
||||||
|
f"https://sqs.{AWS_REGION}.amazonaws.com/{AWS_ACCOUNT_NUMBER}/{test_queue_name}"
|
||||||
|
)
|
||||||
|
test_queue_arn = f"arn:aws:sqs:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:{test_queue_name}"
|
||||||
|
|
||||||
test_restricted_policy = {
|
test_restricted_policy = {
|
||||||
"Version": "2012-10-17",
|
"Version": "2012-10-17",
|
||||||
@@ -19,7 +22,7 @@ test_restricted_policy = {
|
|||||||
"Effect": "Allow",
|
"Effect": "Allow",
|
||||||
"Principal": {"AWS": {AWS_ACCOUNT_NUMBER}},
|
"Principal": {"AWS": {AWS_ACCOUNT_NUMBER}},
|
||||||
"Action": "sqs:ReceiveMessage",
|
"Action": "sqs:ReceiveMessage",
|
||||||
"Resource": topic_arn,
|
"Resource": test_queue_arn,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -33,7 +36,7 @@ test_public_policy = {
|
|||||||
"Effect": "Allow",
|
"Effect": "Allow",
|
||||||
"Principal": "*",
|
"Principal": "*",
|
||||||
"Action": "sqs:ReceiveMessage",
|
"Action": "sqs:ReceiveMessage",
|
||||||
"Resource": topic_arn,
|
"Resource": test_queue_arn,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -47,7 +50,7 @@ test_public_policy_with_condition_same_account_not_valid = {
|
|||||||
"Effect": "Allow",
|
"Effect": "Allow",
|
||||||
"Principal": "*",
|
"Principal": "*",
|
||||||
"Action": "sqs:ReceiveMessage",
|
"Action": "sqs:ReceiveMessage",
|
||||||
"Resource": topic_arn,
|
"Resource": test_queue_arn,
|
||||||
"Condition": {
|
"Condition": {
|
||||||
"DateGreaterThan": {"aws:CurrentTime": "2009-01-31T12:00Z"},
|
"DateGreaterThan": {"aws:CurrentTime": "2009-01-31T12:00Z"},
|
||||||
"DateLessThan": {"aws:CurrentTime": "2009-01-31T15:00Z"},
|
"DateLessThan": {"aws:CurrentTime": "2009-01-31T15:00Z"},
|
||||||
@@ -65,7 +68,7 @@ test_public_policy_with_condition_same_account = {
|
|||||||
"Effect": "Allow",
|
"Effect": "Allow",
|
||||||
"Principal": "*",
|
"Principal": "*",
|
||||||
"Action": "sqs:ReceiveMessage",
|
"Action": "sqs:ReceiveMessage",
|
||||||
"Resource": topic_arn,
|
"Resource": test_queue_arn,
|
||||||
"Condition": {
|
"Condition": {
|
||||||
"StringEquals": {"aws:SourceAccount": f"{AWS_ACCOUNT_NUMBER}"}
|
"StringEquals": {"aws:SourceAccount": f"{AWS_ACCOUNT_NUMBER}"}
|
||||||
},
|
},
|
||||||
@@ -82,7 +85,7 @@ test_public_policy_with_condition_diff_account = {
|
|||||||
"Effect": "Allow",
|
"Effect": "Allow",
|
||||||
"Principal": "*",
|
"Principal": "*",
|
||||||
"Action": "sqs:ReceiveMessage",
|
"Action": "sqs:ReceiveMessage",
|
||||||
"Resource": topic_arn,
|
"Resource": test_queue_arn,
|
||||||
"Condition": {"StringEquals": {"aws:SourceAccount": "111122223333"}},
|
"Condition": {"StringEquals": {"aws:SourceAccount": "111122223333"}},
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -110,10 +113,11 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
sqs_client.queues = []
|
sqs_client.queues = []
|
||||||
sqs_client.queues.append(
|
sqs_client.queues.append(
|
||||||
Queue(
|
Queue(
|
||||||
id=queue_id,
|
id=test_queue_url,
|
||||||
|
name=test_queue_name,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
policy=test_restricted_policy,
|
policy=test_restricted_policy,
|
||||||
arn="arn_test",
|
arn=test_queue_arn,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -129,8 +133,8 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
assert len(result) == 1
|
assert len(result) == 1
|
||||||
assert result[0].status == "PASS"
|
assert result[0].status == "PASS"
|
||||||
assert search("is not public", result[0].status_extended)
|
assert search("is not public", result[0].status_extended)
|
||||||
assert result[0].resource_id == queue_id
|
assert result[0].resource_id == test_queue_url
|
||||||
assert result[0].resource_arn == "arn_test"
|
assert result[0].resource_arn == test_queue_arn
|
||||||
assert result[0].resource_tags == []
|
assert result[0].resource_tags == []
|
||||||
assert result[0].region == AWS_REGION
|
assert result[0].region == AWS_REGION
|
||||||
|
|
||||||
@@ -139,10 +143,11 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
sqs_client.queues = []
|
sqs_client.queues = []
|
||||||
sqs_client.queues.append(
|
sqs_client.queues.append(
|
||||||
Queue(
|
Queue(
|
||||||
id=queue_id,
|
id=test_queue_url,
|
||||||
|
name=test_queue_name,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
policy=test_public_policy,
|
policy=test_public_policy,
|
||||||
arn="arn_test",
|
arn=test_queue_arn,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -161,8 +166,8 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
"is public because its policy allows public access",
|
"is public because its policy allows public access",
|
||||||
result[0].status_extended,
|
result[0].status_extended,
|
||||||
)
|
)
|
||||||
assert result[0].resource_id == queue_id
|
assert result[0].resource_id == test_queue_url
|
||||||
assert result[0].resource_arn == "arn_test"
|
assert result[0].resource_arn == test_queue_arn
|
||||||
assert result[0].resource_tags == []
|
assert result[0].resource_tags == []
|
||||||
assert result[0].region == AWS_REGION
|
assert result[0].region == AWS_REGION
|
||||||
|
|
||||||
@@ -172,10 +177,11 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
sqs_client.audited_account = AWS_ACCOUNT_NUMBER
|
sqs_client.audited_account = AWS_ACCOUNT_NUMBER
|
||||||
sqs_client.queues.append(
|
sqs_client.queues.append(
|
||||||
Queue(
|
Queue(
|
||||||
id=queue_id,
|
id=test_queue_url,
|
||||||
|
name=test_queue_name,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
policy=test_public_policy_with_condition_same_account_not_valid,
|
policy=test_public_policy_with_condition_same_account_not_valid,
|
||||||
arn="arn_test",
|
arn=test_queue_arn,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -194,8 +200,8 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
"is public because its policy allows public access",
|
"is public because its policy allows public access",
|
||||||
result[0].status_extended,
|
result[0].status_extended,
|
||||||
)
|
)
|
||||||
assert result[0].resource_id == queue_id
|
assert result[0].resource_id == test_queue_url
|
||||||
assert result[0].resource_arn == "arn_test"
|
assert result[0].resource_arn == test_queue_arn
|
||||||
assert result[0].resource_tags == []
|
assert result[0].resource_tags == []
|
||||||
assert result[0].region == AWS_REGION
|
assert result[0].region == AWS_REGION
|
||||||
|
|
||||||
@@ -205,10 +211,11 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
sqs_client.audited_account = AWS_ACCOUNT_NUMBER
|
sqs_client.audited_account = AWS_ACCOUNT_NUMBER
|
||||||
sqs_client.queues.append(
|
sqs_client.queues.append(
|
||||||
Queue(
|
Queue(
|
||||||
id=queue_id,
|
id=test_queue_url,
|
||||||
|
name=test_queue_name,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
policy=test_public_policy_with_condition_same_account,
|
policy=test_public_policy_with_condition_same_account,
|
||||||
arn="arn_test",
|
arn=test_queue_arn,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -225,10 +232,10 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
assert result[0].status == "PASS"
|
assert result[0].status == "PASS"
|
||||||
assert (
|
assert (
|
||||||
result[0].status_extended
|
result[0].status_extended
|
||||||
== f"SQS queue {queue_id} is not public because its policy only allows access from the same account."
|
== f"SQS queue {test_queue_url} is not public because its policy only allows access from the same account."
|
||||||
)
|
)
|
||||||
assert result[0].resource_id == queue_id
|
assert result[0].resource_id == test_queue_url
|
||||||
assert result[0].resource_arn == "arn_test"
|
assert result[0].resource_arn == test_queue_arn
|
||||||
assert result[0].resource_tags == []
|
assert result[0].resource_tags == []
|
||||||
assert result[0].region == AWS_REGION
|
assert result[0].region == AWS_REGION
|
||||||
|
|
||||||
@@ -238,10 +245,11 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
sqs_client.audited_account = AWS_ACCOUNT_NUMBER
|
sqs_client.audited_account = AWS_ACCOUNT_NUMBER
|
||||||
sqs_client.queues.append(
|
sqs_client.queues.append(
|
||||||
Queue(
|
Queue(
|
||||||
id=queue_id,
|
id=test_queue_url,
|
||||||
|
name=test_queue_name,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
policy=test_public_policy_with_condition_diff_account,
|
policy=test_public_policy_with_condition_diff_account,
|
||||||
arn="arn_test",
|
arn=test_queue_arn,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -258,9 +266,9 @@ class Test_sqs_queues_not_publicly_accessible:
|
|||||||
assert result[0].status == "FAIL"
|
assert result[0].status == "FAIL"
|
||||||
assert (
|
assert (
|
||||||
result[0].status_extended
|
result[0].status_extended
|
||||||
== f"SQS queue {queue_id} is public because its policy allows public access, and the condition does not limit access to resources within the same account."
|
== f"SQS queue {test_queue_url} is public because its policy allows public access, and the condition does not limit access to resources within the same account."
|
||||||
)
|
)
|
||||||
assert result[0].resource_id == queue_id
|
assert result[0].resource_id == test_queue_url
|
||||||
assert result[0].resource_arn == "arn_test"
|
assert result[0].resource_arn == test_queue_arn
|
||||||
assert result[0].resource_tags == []
|
assert result[0].resource_tags == []
|
||||||
assert result[0].region == AWS_REGION
|
assert result[0].region == AWS_REGION
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ AWS_REGION = "eu-west-1"
|
|||||||
AWS_ACCOUNT_NUMBER = "123456789012"
|
AWS_ACCOUNT_NUMBER = "123456789012"
|
||||||
|
|
||||||
test_kms_key_id = str(uuid4())
|
test_kms_key_id = str(uuid4())
|
||||||
queue_id = str(uuid4())
|
test_queue_name = str(uuid4())
|
||||||
topic_arn = f"arn:aws:sqs:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:{queue_id}"
|
test_queue_url = (
|
||||||
|
f"https://sqs.{AWS_REGION}.amazonaws.com/{AWS_ACCOUNT_NUMBER}/{test_queue_name}"
|
||||||
|
)
|
||||||
|
test_queue_arn = f"arn:aws:sqs:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:{test_queue_name}"
|
||||||
|
|
||||||
|
|
||||||
class Test_sqs_queues_server_side_encryption_enabled:
|
class Test_sqs_queues_server_side_encryption_enabled:
|
||||||
@@ -33,10 +36,11 @@ class Test_sqs_queues_server_side_encryption_enabled:
|
|||||||
sqs_client.queues = []
|
sqs_client.queues = []
|
||||||
sqs_client.queues.append(
|
sqs_client.queues.append(
|
||||||
Queue(
|
Queue(
|
||||||
id=queue_id,
|
id=test_queue_url,
|
||||||
|
name=test_queue_name,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
kms_key_id=test_kms_key_id,
|
kms_key_id=test_kms_key_id,
|
||||||
arn="arn_test",
|
arn=test_queue_arn,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -52,17 +56,18 @@ class Test_sqs_queues_server_side_encryption_enabled:
|
|||||||
assert len(result) == 1
|
assert len(result) == 1
|
||||||
assert result[0].status == "PASS"
|
assert result[0].status == "PASS"
|
||||||
assert search("is using Server Side Encryption", result[0].status_extended)
|
assert search("is using Server Side Encryption", result[0].status_extended)
|
||||||
assert result[0].resource_id == queue_id
|
assert result[0].resource_id == test_queue_url
|
||||||
assert result[0].resource_arn == "arn_test"
|
assert result[0].resource_arn == test_queue_arn
|
||||||
|
|
||||||
def test_queues_no_encryption(self):
|
def test_queues_no_encryption(self):
|
||||||
sqs_client = mock.MagicMock
|
sqs_client = mock.MagicMock
|
||||||
sqs_client.queues = []
|
sqs_client.queues = []
|
||||||
sqs_client.queues.append(
|
sqs_client.queues.append(
|
||||||
Queue(
|
Queue(
|
||||||
id=queue_id,
|
id=test_queue_url,
|
||||||
|
name=test_queue_name,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
arn="arn_test",
|
arn=test_queue_arn,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -80,5 +85,5 @@ class Test_sqs_queues_server_side_encryption_enabled:
|
|||||||
assert search(
|
assert search(
|
||||||
"is not using Server Side Encryption", result[0].status_extended
|
"is not using Server Side Encryption", result[0].status_extended
|
||||||
)
|
)
|
||||||
assert result[0].resource_id == queue_id
|
assert result[0].resource_id == test_queue_url
|
||||||
assert result[0].resource_arn == "arn_test"
|
assert result[0].resource_arn == test_queue_arn
|
||||||
|
|||||||
@@ -110,9 +110,25 @@ class Test_SQS_Service:
|
|||||||
sqs = SQS(audit_info)
|
sqs = SQS(audit_info)
|
||||||
assert len(sqs.queues) == 1
|
assert len(sqs.queues) == 1
|
||||||
assert sqs.queues[0].id == queue["QueueUrl"]
|
assert sqs.queues[0].id == queue["QueueUrl"]
|
||||||
|
assert sqs.queues[0].name == test_queue
|
||||||
|
assert sqs.queues[0].name == sqs.queues[0].arn.split(":")[-1]
|
||||||
|
assert sqs.queues[0].name == sqs.queues[0].id.split("/")[-1]
|
||||||
|
assert sqs.queues[0].arn == test_queue_arn
|
||||||
assert sqs.queues[0].region == AWS_REGION
|
assert sqs.queues[0].region == AWS_REGION
|
||||||
assert sqs.queues[0].tags == [{"test": "test"}]
|
assert sqs.queues[0].tags == [{"test": "test"}]
|
||||||
|
|
||||||
|
# moto does not properly mock this and is hardcoded to return 1000 queues
|
||||||
|
# so this test currently always fails
|
||||||
|
# @mock_sqs
|
||||||
|
# # Test SQS list queues for over 1000 queues
|
||||||
|
# def test__list_queues__pagination_over_a_thousand(self):
|
||||||
|
# sqs_client = client("sqs", region_name=AWS_REGION)
|
||||||
|
# for i in range(0,1050):
|
||||||
|
# sqs_client.create_queue(QueueName=f"{test_queue}-{i}", tags={"test": "test"})
|
||||||
|
# audit_info = self.set_mocked_audit_info()
|
||||||
|
# sqs = SQS(audit_info)
|
||||||
|
# assert len(sqs.queues) > 1000
|
||||||
|
|
||||||
@mock_sqs
|
@mock_sqs
|
||||||
# Test SQS list queues
|
# Test SQS list queues
|
||||||
def test__get_queue_attributes__(self):
|
def test__get_queue_attributes__(self):
|
||||||
|
|||||||
87
tests/providers/common/clean_test.py
Normal file
87
tests/providers/common/clean_test.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import importlib
|
||||||
|
import logging
|
||||||
|
import tempfile
|
||||||
|
from argparse import Namespace
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
from mock import patch
|
||||||
|
|
||||||
|
from prowler.providers.common.clean import clean_provider_local_output_directories
|
||||||
|
|
||||||
|
|
||||||
|
class Test_Common_Clean:
|
||||||
|
def set_provider_input_args(self, provider):
|
||||||
|
set_args_function = f"set_{provider}_input_args"
|
||||||
|
args = getattr(
|
||||||
|
getattr(importlib.import_module(__name__), __class__.__name__),
|
||||||
|
set_args_function,
|
||||||
|
)(self)
|
||||||
|
return args
|
||||||
|
|
||||||
|
def set_aws_input_args(self):
|
||||||
|
args = Namespace()
|
||||||
|
args.provider = "aws"
|
||||||
|
args.output_bucket = "test-bucket"
|
||||||
|
args.output_bucket_no_assume = None
|
||||||
|
return args
|
||||||
|
|
||||||
|
def set_azure_input_args(self):
|
||||||
|
args = Namespace()
|
||||||
|
args.provider = "azure"
|
||||||
|
return args
|
||||||
|
|
||||||
|
def test_clean_provider_local_output_directories_non_initialized(self, caplog):
|
||||||
|
provider = "azure"
|
||||||
|
input_args = self.set_provider_input_args(provider)
|
||||||
|
caplog.set_level(logging.INFO)
|
||||||
|
clean_provider_local_output_directories(input_args)
|
||||||
|
assert (
|
||||||
|
f"Cleaning local output directories not initialized for provider {provider}:"
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_clean_aws_local_output_directories_non_default_dir_output_bucket(self):
|
||||||
|
provider = "aws"
|
||||||
|
input_args = self.set_provider_input_args(provider)
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
input_args.output_directory = temp_dir
|
||||||
|
clean_provider_local_output_directories(input_args)
|
||||||
|
assert not path.exists(input_args.output_directory)
|
||||||
|
|
||||||
|
def test_clean_aws_local_output_directories_non_default_dir_output_bucket_no_assume(
|
||||||
|
self,
|
||||||
|
):
|
||||||
|
provider = "aws"
|
||||||
|
input_args = self.set_provider_input_args(provider)
|
||||||
|
input_args.output_bucket = None
|
||||||
|
input_args.output_bucket_no_assume = "test"
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
input_args.output_directory = temp_dir
|
||||||
|
clean_provider_local_output_directories(input_args)
|
||||||
|
assert not path.exists(input_args.output_directory)
|
||||||
|
|
||||||
|
def test_clean_aws_local_output_directories_default_dir_output_bucket(self):
|
||||||
|
provider = "aws"
|
||||||
|
input_args = self.set_provider_input_args(provider)
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
with patch(
|
||||||
|
"prowler.providers.common.clean.default_output_directory", new=temp_dir
|
||||||
|
):
|
||||||
|
input_args.output_directory = temp_dir
|
||||||
|
clean_provider_local_output_directories(input_args)
|
||||||
|
assert path.exists(input_args.output_directory)
|
||||||
|
|
||||||
|
def test_clean_aws_local_output_directories_default_dir_output_bucket_no_assume(
|
||||||
|
self,
|
||||||
|
):
|
||||||
|
provider = "aws"
|
||||||
|
input_args = self.set_provider_input_args(provider)
|
||||||
|
input_args.output_bucket_no_assume = "test"
|
||||||
|
input_args.ouput_bucket = None
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
with patch(
|
||||||
|
"prowler.providers.common.clean.default_output_directory", new=temp_dir
|
||||||
|
):
|
||||||
|
input_args.output_directory = temp_dir
|
||||||
|
clean_provider_local_output_directories(input_args)
|
||||||
|
assert path.exists(input_args.output_directory)
|
||||||
Reference in New Issue
Block a user