Compare commits

...

9 Commits
v5.14 ... 4.6.1

Author SHA1 Message Date
Prowler Bot
e771218bba fix(k8s): handle Kubernetes kubeconfig content correctly (#5967)
Co-authored-by: Sergio Garcia <hello@mistercloudsec.com>
2024-11-29 10:19:00 -04:00
Prowler Bot
c627a3e9aa fix(azure): containerregistry_not_publicly_accesible is not accurate (#5966)
Co-authored-by: StylusFrost <43682773+StylusFrost@users.noreply.github.com>
2024-11-29 09:53:06 -04:00
Prowler Bot
1c58644118 fix(rds): add default key value to RDS event (#5965)
Co-authored-by: Rubén De la Torre Vico <rubendltv22@gmail.com>
2024-11-29 09:52:55 -04:00
Prowler Bot
398fa37a23 fix(gcp): use session credentials to check if API is active (#5936)
Co-authored-by: Sergio Garcia <hello@mistercloudsec.com>
2024-11-27 16:58:40 -04:00
Prowler Bot
412d948585 fix(aws): exclude threat detection checks if category not present (#5934)
Co-authored-by: Sergio Garcia <hello@mistercloudsec.com>
2024-11-27 12:56:00 -04:00
Prowler Bot
6bc0432ed5 fix(list_by_service): execute lambda if requested (#5931)
Co-authored-by: Pepe Fagoaga <pepe@prowler.com>
2024-11-27 11:22:49 -04:00
Pepe Fagoaga
b2ebc8410a chore(version): update Prowler v4 version (#5901) 2024-11-26 08:11:16 -04:00
Prowler Bot
94b6fbda91 chore(gcp): update docstring of ADC credentials (#5879)
Co-authored-by: Sergio Garcia <hello@mistercloudsec.com>
2024-11-25 13:54:40 -04:00
Prowler Bot
3ce785a7b4 chore(aws): update fixers docstring (#5878)
Co-authored-by: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com>
2024-11-25 13:01:45 -04:00
42 changed files with 323 additions and 101 deletions

View File

@@ -12,7 +12,7 @@ from prowler.lib.logger import logger
timestamp = datetime.today()
timestamp_utc = datetime.now(timezone.utc).replace(tzinfo=timezone.utc)
prowler_version = "4.6.0"
prowler_version = "4.6.1"
html_logo_url = "https://github.com/prowler-cloud/prowler/"
square_logo_img = "https://prowler.com/wp-content/uploads/logo-html.png"
aws_logo = "https://user-images.githubusercontent.com/38561120/235953920-3e3fba08-0795-41dc-b480-9bea57db9f2e.png"

View File

@@ -111,7 +111,7 @@ def load_checks_to_execute(
):
checks_to_execute.add(check_name)
# Only execute threat detection checks if threat-detection category is set
if categories and categories != [] and "threat-detection" not in categories:
if not categories or "threat-detection" not in categories:
for threat_detection_check in check_categories.get("threat-detection", []):
checks_to_execute.discard(threat_detection_check)

View File

@@ -322,8 +322,9 @@ class CheckMetadata(BaseModel):
checks = set()
if service:
if service == "lambda":
service = "awslambda"
# This is a special case for the AWS provider since `lambda` is a reserved keyword in Python
if service == "awslambda":
service = "lambda"
checks = {
check_name
for check_name, check_metadata in bulk_checks_metadata.items()

View File

@@ -6,7 +6,8 @@ from prowler.providers.aws.services.accessanalyzer.accessanalyzer_client import
def fixer(region):
"""
Enable Access Analyzer in a region. Requires the access-analyzer:CreateAnalyzer permission:
Enable Access Analyzer in a region. Requires the access-analyzer:CreateAnalyzer permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [

View File

@@ -7,7 +7,8 @@ from prowler.providers.aws.services.cloudtrail.cloudtrail_client import (
def fixer(region):
"""
NOTE: Define the S3 bucket name in the fixer_config.yaml file.
Enable CloudTrail in a region. Requires the cloudtrail:CreateTrail permission:
Enable CloudTrail in a region. Requires the cloudtrail:CreateTrail permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [

View File

@@ -8,9 +8,8 @@ def fixer(resource_id: str, region: str) -> bool:
"""
Modify the attributes of a DocumentDB cluster snapshot to remove public access.
Specifically, this fixer removes the 'all' value from the 'restore' attribute to
prevent the snapshot from being publicly accessible.
Requires the rds:ModifyDBClusterSnapshotAttribute permissions.
prevent the snapshot from being publicly accessible. Requires the rds:ModifyDBClusterSnapshotAttribute permissions.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -21,7 +20,6 @@ def fixer(resource_id: str, region: str) -> bool:
}
]
}
Args:
resource_id (str): The DB cluster snapshot identifier.
region (str): AWS region where the snapshot exists.

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.ec2.ec2_client import ec2_client
def fixer(region):
"""
Enable EBS encryption by default in a region. NOTE: Custom KMS keys for EBS Default Encryption may be overwritten.
Requires the ec2:EnableEbsEncryptionByDefault permission:
Requires the ec2:EnableEbsEncryptionByDefault permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [

View File

@@ -6,8 +6,8 @@ def fixer(resource_id: str, region: str) -> bool:
"""
Modify the attributes of an EBS snapshot to remove public access.
Specifically, this fixer removes the 'all' value from the 'createVolumePermission' attribute to
prevent the snapshot from being publicly accessible.
Requires the ec2:ModifySnapshotAttribute permission.
prevent the snapshot from being publicly accessible. Requires the ec2:ModifySnapshotAttribute permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.ec2.ec2_client import ec2_client
def fixer(region):
"""
Enable EBS snapshot block public access in a region.
Requires the ec2:EnableSnapshotBlockPublicAccess permission:
Requires the ec2:EnableSnapshotBlockPublicAccess permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.ec2.ec2_client import ec2_client
def fixer(region):
"""
Enable IMDSv2 for EC2 instances in the specified region.
Requires the ec2:ModifyInstanceMetadataDefaults permission:
Requires the ec2:ModifyInstanceMetadataDefaults permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [

View File

@@ -4,7 +4,8 @@ from prowler.providers.aws.services.guardduty.guardduty_client import guardduty_
def fixer(region):
"""
Enable GuardDuty in a region. Requires the guardduty:CreateDetector permission:
Enable GuardDuty in a region. Requires the guardduty:CreateDetector permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.iam.iam_client import iam_client
def fixer(resource_id: str) -> bool:
"""
Enable IAM password policy to expire passwords within 90 days or less or the configurable value in prowler/config/fixer_config.yaml.
Requires the iam:UpdateAccountPasswordPolicy permission:
Requires the iam:UpdateAccountPasswordPolicy permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -16,6 +17,8 @@ def fixer(resource_id: str) -> bool:
}
]
}
Args:
resource_id (str): AWS account ID
Returns:
bool: True if IAM password policy is updated, False otherwise
"""

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.iam.iam_client import iam_client
def fixer(resource_id: str) -> bool:
"""
Enable IAM password policy to require lowercase characters or the configurable value in prowler/config/fixer_config.yaml.
Requires the iam:UpdateAccountPasswordPolicy permission:
Requires the iam:UpdateAccountPasswordPolicy permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -16,6 +17,8 @@ def fixer(resource_id: str) -> bool:
}
]
}
Args:
resource_id (str): AWS account ID
Returns:
bool: True if IAM password policy is updated, False otherwise
"""

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.iam.iam_client import iam_client
def fixer(resource_id: str) -> bool:
"""
Enable IAM password policy to require a minimum password length of 14 characters or the configurable value in prowler/config/fixer_config.yaml.
Requires the iam:UpdateAccountPasswordPolicy permission:
Requires the iam:UpdateAccountPasswordPolicy permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -16,6 +17,8 @@ def fixer(resource_id: str) -> bool:
}
]
}
Args:
resource_id (str): AWS account ID
Returns:
bool: True if IAM password policy is updated, False otherwise
"""

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.iam.iam_client import iam_client
def fixer(resource_id: str) -> bool:
"""
Enable IAM password policy to require numbers or the configurable value in prowler/config/fixer_config.yaml.
Requires the iam:UpdateAccountPasswordPolicy permission:
Requires the iam:UpdateAccountPasswordPolicy permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -16,6 +17,8 @@ def fixer(resource_id: str) -> bool:
}
]
}
Args:
resource_id (str): AWS account ID
Returns:
bool: True if IAM password policy is updated, False otherwise
"""

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.iam.iam_client import iam_client
def fixer(resource_id: str) -> bool:
"""
Enable IAM password policy to prevent reusing the 24 previous passwords or the configurable value in prowler/config/fixer_config.yaml.
Requires the iam:UpdateAccountPasswordPolicy permission:
Requires the iam:UpdateAccountPasswordPolicy permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -16,6 +17,8 @@ def fixer(resource_id: str) -> bool:
}
]
}
Args:
resource_id (str): AWS account ID
Returns:
bool: True if IAM password policy is updated, False otherwise
"""

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.iam.iam_client import iam_client
def fixer(resource_id: str) -> bool:
"""
Enable IAM password policy to require symbols or the configurable value in prowler/config/fixer_config.yaml.
Requires the iam:UpdateAccountPasswordPolicy permission:
Requires the iam:UpdateAccountPasswordPolicy permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -16,6 +17,8 @@ def fixer(resource_id: str) -> bool:
}
]
}
Args:
resource_id (str): AWS account ID
Returns:
bool: True if IAM password policy is updated, False otherwise
"""

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.iam.iam_client import iam_client
def fixer(resource_id: str) -> bool:
"""
Enable IAM password policy to require uppercase characters or the configurable value in prowler/config/fixer_config.yaml.
Requires the iam:UpdateAccountPasswordPolicy permission:
Requires the iam:UpdateAccountPasswordPolicy permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -16,6 +17,8 @@ def fixer(resource_id: str) -> bool:
}
]
}
Args:
resource_id (str): AWS account ID
Returns:
bool: True if IAM password policy is updated, False otherwise
"""

View File

@@ -7,7 +7,6 @@ def fixer(resource_id: str, region: str) -> bool:
Cancel the scheduled deletion of a KMS key.
Specifically, this fixer calls the 'cancel_key_deletion' method to restore the KMS key's availability if it is marked for deletion.
Requires the kms:CancelKeyDeletion permission.
Permissions:
{
"Version": "2012-10-17",
@@ -19,11 +18,9 @@ def fixer(resource_id: str, region: str) -> bool:
}
]
}
Args:
resource_id (str): The ID of the KMS key to cancel the deletion for.
region (str): AWS region where the KMS key exists.
Returns:
bool: True if the operation is successful (deletion cancellation is completed), False otherwise.
"""

View File

@@ -4,7 +4,8 @@ from prowler.providers.aws.services.kms.kms_client import kms_client
def fixer(resource_id: str, region: str) -> bool:
"""
Enable CMK rotation. Requires the kms:EnableKeyRotation permission:
Enable CMK rotation. Requires the kms:EnableKeyRotation permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [

View File

@@ -6,9 +6,8 @@ def fixer(resource_id: str, region: str) -> bool:
"""
Modify the attributes of a Neptune DB cluster snapshot to remove public access.
Specifically, this fixer removes the 'all' value from the 'restore' attribute to
prevent the snapshot from being publicly accessible.
Requires the rds:ModifyDBClusterSnapshotAttribute permissions.
prevent the snapshot from being publicly accessible. Requires the rds:ModifyDBClusterSnapshotAttribute permissions.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -19,11 +18,9 @@ def fixer(resource_id: str, region: str) -> bool:
}
]
}
Args:
resource_id (str): The DB cluster snapshot identifier.
region (str): AWS region where the snapshot exists.
Returns:
bool: True if the operation is successful (public access is removed), False otherwise.
"""

View File

@@ -6,9 +6,8 @@ def fixer(resource_id: str, region: str) -> bool:
"""
Modify the attributes of an RDS instance to disable public accessibility.
Specifically, this fixer sets the 'PubliclyAccessible' attribute to False
to prevent the RDS instance from being publicly accessible.
Requires the rds:ModifyDBInstance permission:
to prevent the RDS instance from being publicly accessible. Requires the rds:ModifyDBInstance permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -19,11 +18,9 @@ def fixer(resource_id: str, region: str) -> bool:
}
]
}
Args:
resource_id (str): The DB instance identifier.
region (str): AWS region where the DB instance exists.
Returns:
bool: True if the operation is successful (public access is disabled), False otherwise.
"""

View File

@@ -446,7 +446,7 @@ class RDS(AWSService):
arn=arn,
sns_topic_arn=event["SnsTopicArn"],
status=event["Status"],
source_type=event["SourceType"],
source_type=event.get("SourceType", ""),
source_id=event.get("SourceIdsList", []),
event_list=event.get("EventCategoriesList", []),
enabled=event["Enabled"],

View File

@@ -5,10 +5,9 @@ from prowler.providers.aws.services.rds.rds_client import rds_client
def fixer(resource_id: str, region: str) -> bool:
"""
Modify the attributes of an RDS DB snapshot or DB cluster snapshot to remove public access.
Specifically, this fixer removes the 'all' value from the 'restore' attribute to
prevent the snapshot from being publicly accessible for both DB snapshots and DB cluster snapshots.
Requires the rds:ModifyDBSnapshotAttribute or rds:ModifyDBClusterSnapshotAttribute permissions.
Specifically, this fixer removes the 'all' value from the 'restore' attribute to prevent the snapshot from being publicly accessible
for both DB snapshots and DB cluster snapshots. Requires the rds:ModifyDBSnapshotAttribute or rds:ModifyDBClusterSnapshotAttribute permissions.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -24,11 +23,9 @@ def fixer(resource_id: str, region: str) -> bool:
}
]
}
Args:
resource_id (str): The DB snapshot or DB cluster snapshot identifier.
region (str): AWS region where the snapshot exists.
Returns:
bool: True if the operation is successful (public access is removed), False otherwise.
"""

View File

@@ -5,7 +5,8 @@ from prowler.providers.aws.services.s3.s3control_client import s3control_client
def fixer(resource_id: str) -> bool:
"""
Enable S3 Block Public Access for the account. NOTE: By blocking all S3 public access you may break public S3 buckets.
Requires the s3:PutAccountPublicAccessBlock permission:
Requires the s3:PutAccountPublicAccessBlock permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
@@ -16,6 +17,8 @@ def fixer(resource_id: str) -> bool:
}
]
}
Args:
resource_id (str): The AWS account ID.
Returns:
bool: True if S3 Block Public Access is enabled, False otherwise
"""

View File

@@ -6,7 +6,8 @@ from prowler.providers.aws.services.securityhub.securityhub_client import (
def fixer(region):
"""
Enable Security Hub in a region. Requires the securityhub:EnableSecurityHub permission:
Enable Security Hub in a region. Requires the securityhub:EnableSecurityHub permission.
Permissions:
{
"Version": "2012-10-17",
"Statement": [

View File

@@ -18,12 +18,7 @@ class containerregistry_not_publicly_accessible(Check):
report.status = "FAIL"
report.status_extended = f"Container Registry {container_registry_info.name} from subscription {subscription} allows unrestricted network access."
if (
getattr(
container_registry_info.network_rule_set, "default_action", ""
).lower()
== "deny"
):
if not container_registry_info.public_network_access:
report.status = "PASS"
report.status_extended = f"Container Registry {container_registry_info.name} from subscription {subscription} does not allow unrestricted network access."

View File

@@ -37,8 +37,13 @@ class ContainerRegistry(AzureService):
resource_group=resource_group,
sku=getattr(registry.sku, "name", ""),
login_server=getattr(registry, "login_server", ""),
public_network_access=getattr(
registry, "public_network_access", ""
public_network_access=(
False
if getattr(
registry, "public_network_access" "Enabled"
)
== "Disabled"
else True
),
admin_user_enabled=getattr(
registry, "admin_user_enabled", False
@@ -93,7 +98,7 @@ class ContainerRegistryInfo:
resource_group: str
sku: str
login_server: str
public_network_access: str
public_network_access: bool
admin_user_enabled: bool
network_rule_set: NetworkRuleSet
monitor_diagnostic_settings: list[DiagnosticSetting]

View File

@@ -417,17 +417,17 @@ class GcpProvider(Provider):
GCPTestConnectionError if an error occurs during the test connection
Usage:
- Using static credentials:
- Using ADC credentials from `/Users/<user>/.config/gcloud/application_default_credentials.json`:
>>> GcpProvider.test_connection(
... client_id="client_id",
... client_secret="client_secret",
... refresh_token="refresh_token"
... )
- Using a credentials file:
- Using a Service Account credentials file path:
>>> GcpProvider.test_connection(
... credentials_file="credentials_file"
... )
- Using a service account to impersonate, authentication is required to impersonate a service account:
- Using ADC credentials with a Service Account to impersonate:
>>> GcpProvider.test_connection(
... client_id="client_id",
... client_secret="client_secret",
@@ -436,7 +436,7 @@ class GcpProvider(Provider):
... )
"""
try:
# Set the GCP credentials using the provided client_id, client_secret and refresh_token
# Set the GCP credentials using the provided client_id, client_secret and refresh_token from ADC
gcp_credentials = None
if any([client_id, client_secret, refresh_token]):
gcp_credentials = GcpProvider.validate_static_arguments(
@@ -738,7 +738,7 @@ class GcpProvider(Provider):
client_id: str = None, client_secret: str = None, refresh_token: str = None
) -> dict:
"""
Validate the static arguments client_id, client_secret and refresh_token
Validate the static arguments client_id, client_secret and refresh_token of ADC credentials
Args:
client_id: str
@@ -749,7 +749,7 @@ class GcpProvider(Provider):
dict
Raises:
GCPStaticCredentialsError if any of the static arguments is missing
GCPStaticCredentialsError if any of the static arguments is missing from the ADC credentials
Usage:
>>> GcpProvider.validate_static_arguments(client_id, client_secret, refresh_token)

View File

@@ -55,7 +55,9 @@ class GCPService:
project_ids = []
for project_id in audited_project_ids:
try:
client = discovery.build("serviceusage", "v1")
client = discovery.build(
"serviceusage", "v1", credentials=self.credentials
)
request = client.services().get(
name=f"projects/{project_id}/services/{self.service}.googleapis.com"
)

View File

@@ -1,4 +1,5 @@
import os
from typing import Union
from colorama import Fore, Style
from kubernetes.client.exceptions import ApiException
@@ -74,14 +75,14 @@ class KubernetesProvider(Provider):
fixer_config: dict = {},
mutelist_path: str = None,
mutelist_content: dict = {},
kubeconfig_content: dict = None,
kubeconfig_content: Union[dict, str] = None,
):
"""
Initializes the KubernetesProvider instance.
Args:
kubeconfig_file (str): Path to the kubeconfig file.
kubeconfig_content (dict): Content of the kubeconfig file.
kubeconfig_content (str or dict): Content of the kubeconfig file.
context (str): Context name.
namespace (list): List of namespaces.
config_content (dict): Audit configuration.
@@ -224,7 +225,7 @@ class KubernetesProvider(Provider):
@staticmethod
def setup_session(
kubeconfig_file: str = None,
kubeconfig_content: dict = None,
kubeconfig_content: Union[dict, str] = None,
context: str = None,
) -> KubernetesSession:
"""
@@ -232,7 +233,7 @@ class KubernetesProvider(Provider):
Args:
kubeconfig_file (str): Path to the kubeconfig file.
kubeconfig_content (dict): Content of the kubeconfig file.
kubeconfig_content (str or dict): Content of the kubeconfig file.
context (str): Context name.
Returns:
@@ -243,14 +244,20 @@ class KubernetesProvider(Provider):
KubernetesInvalidProviderIdError: If the provider ID is invalid.
KubernetesSetUpSessionError: If an error occurs while setting up the session.
"""
logger.info(f"Using kubeconfig file: {kubeconfig_file}")
try:
if kubeconfig_content:
config.load_kube_config_from_dict(
safe_load(kubeconfig_content), context=context
)
logger.info("Using kubeconfig content...")
config_data = safe_load(kubeconfig_content)
config.load_kube_config_from_dict(config_data, context=context)
if context:
contexts = config_data.get("contexts", [])
for context_item in contexts:
if context_item["name"] == context:
context = context_item
else:
context = config_data.get("contexts", [])[0]
else:
logger.info(f"Using kubeconfig file: {kubeconfig_file}...")
kubeconfig_file = (
kubeconfig_file if kubeconfig_file else "~/.kube/config"
)
@@ -273,17 +280,19 @@ class KubernetesProvider(Provider):
return KubernetesSession(
api_client=client.ApiClient(), context=context
)
if context:
contexts = config.list_kube_config_contexts(
config_file=kubeconfig_file
)[0]
for context_item in contexts:
if context_item["name"] == context:
context = context_item
else:
context = config.list_kube_config_contexts(config_file=kubeconfig_file)[
1
]
if context:
contexts = config.list_kube_config_contexts(
config_file=kubeconfig_file
)[0]
for context_item in contexts:
if context_item["name"] == context:
context = context_item
else:
# If no context is provided, use the active context in the kubeconfig file
# The first element is the list of contexts, the second is the active context
context = config.list_kube_config_contexts(
config_file=kubeconfig_file
)[1]
return KubernetesSession(api_client=client.ApiClient(), context=context)
except parser.ParserError as parser_error:
@@ -318,7 +327,7 @@ class KubernetesProvider(Provider):
@staticmethod
def test_connection(
kubeconfig_file: str = "~/.kube/config",
kubeconfig_content: dict = None,
kubeconfig_content: Union[dict, str] = None,
namespace: str = None,
provider_id: str = None,
raise_on_exception: bool = True,
@@ -328,7 +337,7 @@ class KubernetesProvider(Provider):
Args:
kubeconfig_file (str): Path to the kubeconfig file.
kubeconfig_content (dict): Content of the kubeconfig file.
kubeconfig_content (str or dict): Content of the kubeconfig file.
namespace (str): Namespace name.
provider_id (str): Provider ID to use, in this case, the Kubernetes context.
raise_on_exception (bool): Whether to raise an exception on error.
@@ -352,7 +361,7 @@ class KubernetesProvider(Provider):
... )
- Using the kubeconfig content:
>>> connection = KubernetesProvider.test_connection(
... kubeconfig_content={"kubecofig": "content"},
... kubeconfig_content="kubeconfig content",
... namespace="default",
... provider_id="my-context",
... raise_on_exception=True,

View File

@@ -23,7 +23,7 @@ packages = [
{include = "dashboard"}
]
readme = "README.md"
version = "4.6.0"
version = "4.6.1"
[tool.poetry.dependencies]
alive-progress = "3.2.0"

View File

@@ -14,11 +14,13 @@ S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME_CUSTOM_ALIAS = (
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_SEVERITY = "medium"
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME_SERVICE = "s3"
CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME = "cloudtrail_threat_detection_enumeration"
class TestCheckLoader:
provider = "aws"
def get_custom_check_metadata(self):
def get_custom_check_s3_metadata(self):
return CheckMetadata(
Provider="aws",
CheckID=S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME,
@@ -52,9 +54,37 @@ class TestCheckLoader:
Compliance=[],
)
def get_threat_detection_check_metadata(self):
return CheckMetadata(
Provider="aws",
CheckID=CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME,
CheckTitle="Ensure there are no potential enumeration threats in CloudTrail",
CheckType=[],
ServiceName="cloudtrail",
SubServiceName="",
ResourceIdTemplate="arn:partition:service:region:account-id:resource-id",
Severity="critical",
ResourceType="AwsCloudTrailTrail",
Description="This check ensures that there are no potential enumeration threats in CloudTrail.",
Risk="Potential enumeration threats in CloudTrail can lead to unauthorized access to resources.",
RelatedUrl="",
Remediation=Remediation(
Code=Code(CLI="", NativeIaC="", Other="", Terraform=""),
Recommendation=Recommendation(
Text="To remediate this issue, ensure that there are no potential enumeration threats in CloudTrail.",
Url="https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-concepts.html#cloudtrail-concepts-logging-data-events",
),
),
Categories=["threat-detection"],
DependsOn=[],
RelatedTo=[],
Notes="",
Compliance=[],
)
def test_load_checks_to_execute(self):
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
assert {S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME} == load_checks_to_execute(
@@ -64,7 +94,7 @@ class TestCheckLoader:
def test_load_checks_to_execute_with_check_list(self):
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
check_list = [S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME]
@@ -76,7 +106,7 @@ class TestCheckLoader:
def test_load_checks_to_execute_with_severities(self):
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
severities = [S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_SEVERITY]
@@ -88,7 +118,7 @@ class TestCheckLoader:
def test_load_checks_to_execute_with_severities_and_services(self):
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
service_list = [S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME_SERVICE]
severities = [S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_SEVERITY]
@@ -104,7 +134,7 @@ class TestCheckLoader:
self,
):
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
service_list = ["ec2"]
severities = [S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_SEVERITY]
@@ -120,7 +150,7 @@ class TestCheckLoader:
self,
):
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
checks_file = "path/to/test_file"
with patch(
@@ -137,7 +167,7 @@ class TestCheckLoader:
self,
):
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
service_list = [S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME_SERVICE]
@@ -178,7 +208,7 @@ class TestCheckLoader:
self,
):
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
categories = {"internet-exposed"}
@@ -190,7 +220,7 @@ class TestCheckLoader:
def test_load_checks_to_execute_no_bulk_checks_metadata(self):
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
with patch(
"prowler.lib.check.checks_loader.CheckMetadata.get_bulk",
@@ -221,7 +251,7 @@ class TestCheckLoader:
compliance_frameworks = ["soc2_aws"]
bulk_checks_metatada = {
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_metadata()
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata()
}
with patch(
"prowler.lib.check.checks_loader.CheckMetadata.get_bulk",
@@ -248,3 +278,27 @@ class TestCheckLoader:
assert {"check1_name", "check2_name"} == update_checks_to_execute_with_aliases(
checks_to_execute, check_aliases
)
def test_threat_detection_category(self):
bulk_checks_metatada = {
CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME: self.get_threat_detection_check_metadata()
}
categories = {"threat-detection"}
assert {CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME} == load_checks_to_execute(
bulk_checks_metadata=bulk_checks_metatada,
categories=categories,
provider=self.provider,
)
def test_discard_threat_detection_checks(self):
bulk_checks_metatada = {
CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME: self.get_threat_detection_check_metadata()
}
categories = {}
assert set() == load_checks_to_execute(
bulk_checks_metadata=bulk_checks_metatada,
categories=categories,
provider=self.provider,
)

View File

@@ -32,6 +32,35 @@ mock_metadata = CheckMetadata(
Compliance=[],
)
mock_metadata_lambda = CheckMetadata(
Provider="aws",
CheckID="awslambda_function_url_public",
CheckTitle="Check 1",
CheckType=["type1"],
ServiceName="lambda",
SubServiceName="subservice1",
ResourceIdTemplate="template1",
Severity="high",
ResourceType="resource1",
Description="Description 1",
Risk="risk1",
RelatedUrl="url1",
Remediation={
"Code": {
"CLI": "cli1",
"NativeIaC": "native1",
"Other": "other1",
"Terraform": "terraform1",
},
"Recommendation": {"Text": "text1", "Url": "url1"},
},
Categories=["categoryone"],
DependsOn=["dependency1"],
RelatedTo=["related1"],
Notes="notes1",
Compliance=[],
)
class TestCheckMetada:
@@ -188,6 +217,46 @@ class TestCheckMetada:
# Assertions
assert result == {"accessanalyzer_enabled"}
@mock.patch("prowler.lib.check.models.load_check_metadata")
@mock.patch("prowler.lib.check.models.recover_checks_from_provider")
def test_list_by_service_lambda(self, mock_recover_checks, mock_load_metadata):
# Mock the return value of recover_checks_from_provider
mock_recover_checks.return_value = [
("awslambda_function_url_public", "/path/to/awslambda_function_url_public")
]
# Mock the return value of load_check_metadata
mock_load_metadata.return_value = mock_metadata_lambda
bulk_metadata = CheckMetadata.get_bulk(provider="aws")
result = CheckMetadata.list(
bulk_checks_metadata=bulk_metadata, service="lambda"
)
# Assertions
assert result == {"awslambda_function_url_public"}
@mock.patch("prowler.lib.check.models.load_check_metadata")
@mock.patch("prowler.lib.check.models.recover_checks_from_provider")
def test_list_by_service_awslambda(self, mock_recover_checks, mock_load_metadata):
# Mock the return value of recover_checks_from_provider
mock_recover_checks.return_value = [
("awslambda_function_url_public", "/path/to/awslambda_function_url_public")
]
# Mock the return value of load_check_metadata
mock_load_metadata.return_value = mock_metadata_lambda
bulk_metadata = CheckMetadata.get_bulk(provider="aws")
result = CheckMetadata.list(
bulk_checks_metadata=bulk_metadata, service="awslambda"
)
# Assertions
assert result == {"awslambda_function_url_public"}
@mock.patch("prowler.lib.check.models.load_check_metadata")
@mock.patch("prowler.lib.check.models.recover_checks_from_provider")
def test_list_by_service_invalid(self, mock_recover_checks, mock_load_metadata):

View File

@@ -21,6 +21,9 @@ class Test_documentdb_cluster_backup_enabled:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_backup_enabled.documentdb_cluster_backup_enabled import (
documentdb_cluster_backup_enabled,
@@ -52,6 +55,9 @@ class Test_documentdb_cluster_backup_enabled:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_backup_enabled.documentdb_cluster_backup_enabled import (
documentdb_cluster_backup_enabled,
@@ -92,6 +98,9 @@ class Test_documentdb_cluster_backup_enabled:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_backup_enabled.documentdb_cluster_backup_enabled import (
documentdb_cluster_backup_enabled,
@@ -130,6 +139,9 @@ class Test_documentdb_cluster_backup_enabled:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_backup_enabled.documentdb_cluster_backup_enabled import (
documentdb_cluster_backup_enabled,
@@ -168,6 +180,9 @@ class Test_documentdb_cluster_backup_enabled:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_backup_enabled.documentdb_cluster_backup_enabled import (
documentdb_cluster_backup_enabled,
@@ -207,6 +222,9 @@ class Test_documentdb_cluster_backup_enabled:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_backup_enabled.documentdb_cluster_backup_enabled import (
documentdb_cluster_backup_enabled,

View File

@@ -20,6 +20,9 @@ class Test_documentdb_cluster_cloudwatch_log_export:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_cloudwatch_log_export.documentdb_cluster_cloudwatch_log_export import (
documentdb_cluster_cloudwatch_log_export,
@@ -51,6 +54,9 @@ class Test_documentdb_cluster_cloudwatch_log_export:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_cloudwatch_log_export.documentdb_cluster_cloudwatch_log_export import (
documentdb_cluster_cloudwatch_log_export,
@@ -90,6 +96,9 @@ class Test_documentdb_cluster_cloudwatch_log_export:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_cloudwatch_log_export.documentdb_cluster_cloudwatch_log_export import (
documentdb_cluster_cloudwatch_log_export,
@@ -127,6 +136,9 @@ class Test_documentdb_cluster_cloudwatch_log_export:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_cloudwatch_log_export.documentdb_cluster_cloudwatch_log_export import (
documentdb_cluster_cloudwatch_log_export,
@@ -164,6 +176,9 @@ class Test_documentdb_cluster_cloudwatch_log_export:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_cloudwatch_log_export.documentdb_cluster_cloudwatch_log_export import (
documentdb_cluster_cloudwatch_log_export,

View File

@@ -20,6 +20,9 @@ class Test_documentdb_cluster_deletion_protection:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_deletion_protection.documentdb_cluster_deletion_protection import (
documentdb_cluster_deletion_protection,
@@ -51,6 +54,9 @@ class Test_documentdb_cluster_deletion_protection:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_deletion_protection.documentdb_cluster_deletion_protection import (
documentdb_cluster_deletion_protection,
@@ -90,6 +96,9 @@ class Test_documentdb_cluster_deletion_protection:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_deletion_protection.documentdb_cluster_deletion_protection import (
documentdb_cluster_deletion_protection,

View File

@@ -20,6 +20,9 @@ class Test_documentdb_cluster_multi_az_enabled:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_multi_az_enabled.documentdb_cluster_multi_az_enabled import (
documentdb_cluster_multi_az_enabled,
@@ -51,6 +54,9 @@ class Test_documentdb_cluster_multi_az_enabled:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_multi_az_enabled.documentdb_cluster_multi_az_enabled import (
documentdb_cluster_multi_az_enabled,
@@ -89,6 +95,9 @@ class Test_documentdb_cluster_multi_az_enabled:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_multi_az_enabled.documentdb_cluster_multi_az_enabled import (
documentdb_cluster_multi_az_enabled,

View File

@@ -22,6 +22,9 @@ class Test_documentdb_cluster_public_snapshot:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_public_snapshot.documentdb_cluster_public_snapshot import (
documentdb_cluster_public_snapshot,
@@ -63,6 +66,9 @@ class Test_documentdb_cluster_public_snapshot:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_public_snapshot.documentdb_cluster_public_snapshot import (
documentdb_cluster_public_snapshot,
@@ -116,6 +122,9 @@ class Test_documentdb_cluster_public_snapshot:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_public_snapshot.documentdb_cluster_public_snapshot import (
documentdb_cluster_public_snapshot,

View File

@@ -20,6 +20,9 @@ class Test_documentdb_cluster_storage_encrypted:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_storage_encrypted.documentdb_cluster_storage_encrypted import (
documentdb_cluster_storage_encrypted,
@@ -51,6 +54,9 @@ class Test_documentdb_cluster_storage_encrypted:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_storage_encrypted.documentdb_cluster_storage_encrypted import (
documentdb_cluster_storage_encrypted,
@@ -89,6 +95,9 @@ class Test_documentdb_cluster_storage_encrypted:
with mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_service.DocumentDB",
new=documentdb_client,
), mock.patch(
"prowler.providers.aws.services.documentdb.documentdb_client.documentdb_client",
new=documentdb_client,
):
from prowler.providers.aws.services.documentdb.documentdb_cluster_storage_encrypted.documentdb_cluster_storage_encrypted import (
documentdb_cluster_storage_encrypted,

View File

@@ -57,7 +57,7 @@ class Test_containerregistry_not_publicly_accessible:
resource_group="mock_resource_group",
sku="Basic",
login_server="mock_login_server.azurecr.io",
public_network_access="Enabled",
public_network_access=True,
admin_user_enabled=True,
network_rule_set=NetworkRuleSet(default_action="Allow"),
private_endpoint_connections=[],
@@ -131,7 +131,7 @@ class Test_containerregistry_not_publicly_accessible:
resource_group="mock_resource_group",
sku="Basic",
login_server="mock_login_server.azurecr.io",
public_network_access="Enabled",
public_network_access=False,
admin_user_enabled=False,
network_rule_set=NetworkRuleSet(default_action="Deny"),
private_endpoint_connections=[],

View File

@@ -32,7 +32,7 @@ class TestContainerRegistryService:
resource_group="mock_resource_group",
sku="Basic",
login_server="mock_login_server.azurecr.io",
public_network_access="Enabled",
public_network_access=False,
admin_user_enabled=True,
network_rule_set=None,
private_endpoint_connections=[],
@@ -71,7 +71,7 @@ class TestContainerRegistryService:
assert registry_info.resource_group == "mock_resource_group"
assert registry_info.sku == "Basic"
assert registry_info.login_server == "mock_login_server.azurecr.io"
assert registry_info.public_network_access == "Enabled"
assert not registry_info.public_network_access
assert registry_info.admin_user_enabled is True
assert isinstance(registry_info.monitor_diagnostic_settings, list)