Repository: prowler-cloud/prowler
Pull request: chore(aws): improve logic for determining if resources are publicly accessible
### Context

Improve logic for determining if resources are publicly accessible.

### Description

The following resources need to be reviewed:

- [x] Amazon S3 bucket
- [x] AWS CloudTrail trail
- [x] Amazon VPC subnet → verify if subnet has any public NACL associated
- [x] Amazon Redshift cluster → verify if cluster is publicly exposed due to a public SG in a public VPC.
- [x] Amazon RDS DB instance → verify if instance is publicly exposed due to a public SG in a public subnet.
- [x] Amazon RDS DB snapshot
- [x] Amazon Elastic Load Balancer -> verify if the ELB is publicly exposed due to a public SG.
- [x] Amazon Elasticsearch Domain: 
- [x] Amazon Machine Images (AMI)
- [x] Amazon EBS snapshots
- [x] Amazon EKS clusters -> checks `eks_control_plane_endpoint_access_restricted` and `eks_endpoints_not_publicly_accessible` unified in `eks_cluster_not_publicly_accessible`
- [x] Amazon SQS queue
- [x] AWS Lambda function

### Checklist

- Are there new checks included in this PR? Yes / No
    - If so, do we need to update permissions for the provider? Please review this carefully.
- [x] Review if the code is being covered by tests.
- [x] Review if code is being documented following this specification https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings
- [x] Review if backport is needed.

### License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.


Problem statement:
False Positive in s3_bucket_policy_public_write_access and s3_bucket_public_access
### Steps to Reproduce

1. prowler aws -c s3_bucket_policy_public_write_access or  prowler aws -c s3_bucket_public_access
2. aws
3. single account
4. 

### Expected behavior

Scanning for S3 public access with a policy that does not allow _public_ access returns a PASS status.

### Actual Result with Screenshots or Logs

prowler aws -c s3_bucket_cross_account_access --resource-arn arn:aws:s3:::sample-bucket

Overview Results:
╭───────────────────┬─────────────────┬────────────────╮
│ 100.0% (1) Failed │ 0.0% (0) Passed │ 0.0% (0) Muted │
╰───────────────────┴─────────────────┴────────────────╯

Account 123456789012 Scan Results (severity columns are for fails only):
╭────────────┬───────────┬──────────┬────────────┬────────┬──────────┬───────┬─────────╮
│ Provider   │ Service   │ Status   │   Critical │   High │   Medium │   Low │   Muted │
├────────────┼───────────┼──────────┼────────────┼────────┼──────────┼───────┼─────────┤
│ aws        │ s3        │ FAIL (1) │          1 │      0 │        0 │     0 │       0 │
╰────────────┴───────────┴──────────┴────────────┴────────┴──────────┴───────┴─────────╯

### How did you install Prowler?

From pip package (pip install prowler)

### Environment Resource

ECS/WSL

### OS used

Amazon Linux/Ubuntu

### Prowler version

4.4.0

### Pip version

pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.10)

### Context

This occurs when the bucket-level `Block all public access` is _not_ set, and the policy allows access only to an AWS service principal, ex:
```
 "Principal": {
                "Service": "personalize.amazonaws.com"
```
In this case, it also does not take into account conditions to restrict account where the service principal could be used from, ex:
```
            "Condition": {
                "StringLike": {
                    "aws:SourceOrgID": "o-a1b2c3d4"
                }
```
This will trigger either (or both of) `s3_bucket_policy_public_write_access ` and/or  `s3_bucket_public_access` if the actions in the policy would trigger the check. However, with the principal above, the access to the bucket is **not** public as the check says (even without the condition, though without it, it could be susceptible to confused-deputy and access from other AWS accounts).

Hints from issue discussion:

Commit message: fix: tests

Patch to review:
diff --git a/prowler/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible.py b/prowler/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible.py
index 778c44be93..6f0fde12c3 100644
--- a/prowler/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible.py
+++ b/prowler/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible.py
@@ -17,7 +17,6 @@ def execute(self):
             report.status_extended = f"Lambda function {function.name} has a policy resource-based policy not public."
             if is_policy_public(
                 function.policy,
-                awslambda_client.audited_account,
                 is_cross_account_allowed=True,
             ):
                 report.status = "FAIL"
diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py b/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py
index 3f47461cd9..10e84c1c06 100644
--- a/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py
+++ b/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py
@@ -20,7 +20,6 @@ def execute(self):
                 report.status_extended = f"DynamoDB table {table.name} has a resource-based policy but is not cross account."
                 if is_policy_public(
                     table.policy,
-                    source_account=dynamodb_client.audited_account,
                 ):
                     report.status = "FAIL"
                     report.status_extended = f"DynamoDB table {table.name} has a resource-based policy allowing cross account access."
diff --git a/prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.py b/prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.py
index 3d51a60929..82f32555e6 100644
--- a/prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.py
+++ b/prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.py
@@ -1,4 +1,6 @@
 from prowler.lib.check.models import Check, Check_Report_AWS
+from prowler.providers.aws.services.ec2.ec2_client import ec2_client
+from prowler.providers.aws.services.ec2.lib.security_groups import check_security_group
 from prowler.providers.aws.services.elbv2.elbv2_client import elbv2_client
 
 
@@ -18,6 +20,18 @@ def execute(self):
                 report.status_extended = (
                     f"ELBv2 ALB {lb.name} is internet facing in {lb.dns}."
                 )
+            elif lb.security_groups:
+                for sg_id in lb.security_groups:
+                    sg_arn = f"arn:{elbv2_client.audited_partition}:ec2:{lb.region}:{elbv2_client.audited_account}:security-group/{sg_id}"
+                    if sg_arn in ec2_client.security_groups:
+                        for ingress_rule in ec2_client.security_groups[
+                            sg_arn
+                        ].ingress_rules:
+                            if check_security_group(
+                                ingress_rule, "tcp", any_address=True
+                            ):
+                                report.status = "FAIL"
+                                report.status_extended = f"ELBv2 ALB {lb.name} is internet facing due to public security group {sg_id}."
 
             findings.append(report)
 
diff --git a/prowler/providers/aws/services/elbv2/elbv2_service.py b/prowler/providers/aws/services/elbv2/elbv2_service.py
index d0693b38d9..4a1293e395 100644
--- a/prowler/providers/aws/services/elbv2/elbv2_service.py
+++ b/prowler/providers/aws/services/elbv2/elbv2_service.py
@@ -47,6 +47,7 @@ def _describe_load_balancers(self, regional_client):
                             type=elbv2["Type"],
                             dns=elbv2.get("DNSName", None),
                             scheme=elbv2.get("Scheme", None),
+                            security_groups=elbv2.get("SecurityGroups", []),
                             availability_zones={
                                 az["ZoneName"]: az["SubnetId"]
                                 for az in elbv2.get("AvailabilityZones", [])
@@ -204,6 +205,7 @@ class LoadBalancerv2(BaseModel):
     drop_invalid_header_fields: Optional[str]
     listeners: Dict[str, Listenerv2] = {}
     scheme: Optional[str]
+    security_groups: list[str] = []
     # Key: ZoneName, Value: SubnetId
     availability_zones: Dict[str, str] = {}
     tags: Optional[list] = []
diff --git a/prowler/providers/aws/services/iam/lib/policy.py b/prowler/providers/aws/services/iam/lib/policy.py
index 95af304b3f..f7537a93c1 100644
--- a/prowler/providers/aws/services/iam/lib/policy.py
+++ b/prowler/providers/aws/services/iam/lib/policy.py
@@ -1,3 +1,4 @@
+import inspect
 from ipaddress import ip_address, ip_network
 
 from prowler.lib.logger import logger
@@ -125,12 +126,16 @@ def is_condition_restricting_from_private_ip(condition_statement: dict) -> bool:
 
                 for ip in condition_statement[CONDITION_OPERATOR][CONDITION_KEY]:
                     # Select if IP address or IP network searching in the string for '/'
-                    if "/" in ip:
-                        if not ip_network(ip, strict=False).is_private:
-                            break
+                    if ip == "*":
+                        is_from_private_ip = False
+                        break
                     else:
-                        if not ip_address(ip).is_private:
-                            break
+                        if "/" in ip:
+                            if not ip_network(ip, strict=False).is_private:
+                                break
+                        else:
+                            if not ip_address(ip).is_private:
+                                break
                 else:
                     is_from_private_ip = True
 
@@ -147,7 +152,6 @@ def is_condition_restricting_from_private_ip(condition_statement: dict) -> bool:
 # TODO: Add logic for deny statements
 def is_policy_public(
     policy: dict,
-    source_account: str = "",
     is_cross_account_allowed=False,
     not_allowed_actions: list = [],
 ) -> bool:
@@ -156,13 +160,20 @@ def is_policy_public(
     If the policy gives access to an AWS service principal is considered public if the policy is not pair with conditions since it can be invoked by AWS services in other accounts.
     Args:
         policy (dict): The AWS policy to check
-        source_account (str): The account to check if the access is restricted to it, default: ""
         is_cross_account_allowed (bool): If the policy can allow cross-account access, default: False
         not_allowed_actions (list): List of actions that are not allowed, default: []. If not_allowed_actions is empty, the function will not consider the actions in the policy.
     Returns:
         bool: True if the policy allows public access, False otherwise
     """
     is_public = False
+    source_account = ""
+    trusted_account_ids = []
+    # Get service client from the check to get the trusted account IDs and source account
+    for var_name, value in inspect.stack()[1].frame.f_globals.items():
+        if "_client" in var_name:
+            trusted_account_ids = value.audit_config.get("trusted_account_ids", [])
+            source_account = value.audited_account
+            break
     for statement in policy.get("Statement", []):
         # Only check allow statements
         if statement["Effect"] == "Allow":
@@ -225,6 +236,7 @@ def is_policy_public(
                         statement.get("Condition", {}),
                         source_account,
                         is_cross_account_allowed,
+                        trusted_account_ids,
                     )
                     and not is_condition_block_restrictive_organization(
                         statement.get("Condition", {})
@@ -242,6 +254,7 @@ def is_condition_block_restrictive(
     condition_statement: dict,
     source_account: str = "",
     is_cross_account_allowed=False,
+    trusted_account_ids: list = [],
 ):
     """
     is_condition_block_restrictive parses the IAM Condition policy block and, by default, returns True if the source_account passed as argument is within, False if not.
@@ -258,6 +271,8 @@ def is_condition_block_restrictive(
 
         source_account: str with a 12-digit AWS Account number, e.g.: 111122223333, default: ""
 
+        trusted_account_ids: list with a list of trusted AWS Account numbers, e.g.: ["111122223333"], default: []
+
         is_cross_account_allowed: bool to allow cross-account access, e.g.: True, default: False
 
     """
@@ -310,12 +325,20 @@ def is_condition_block_restrictive(
                         # if cross account is not allowed check for each condition block looking for accounts
                         # different than default
                         if not is_cross_account_allowed:
-                            # 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 or trusted accounts -> we do not consider it safe
                             # here by default we assume is true and look for false entries
                             for item in condition_statement[condition_operator][value]:
-                                if source_account not in item:
-                                    is_condition_key_restrictive = False
-                                    break
+                                if (
+                                    "aws:sourcevpc" != value
+                                    and "aws:sourcevpce" != value
+                                ):
+                                    if source_account not in item:
+                                        if not any(
+                                            trusted_account_id in item
+                                            for trusted_account_id in trusted_account_ids
+                                        ):
+                                            is_condition_key_restrictive = False
+                                            break
 
                         if is_condition_key_restrictive:
                             is_condition_valid = True
@@ -325,14 +348,21 @@ def is_condition_block_restrictive(
                         condition_statement[condition_operator][value],
                         str,
                     ):
-                        if is_cross_account_allowed:
+                        if "aws:sourcevpc" == value or "aws:sourcevpce" == value:
                             is_condition_valid = True
                         else:
-                            if (
-                                source_account
-                                in condition_statement[condition_operator][value]
-                            ):
+                            if is_cross_account_allowed:
                                 is_condition_valid = True
+                            else:
+                                if (
+                                    source_account
+                                    in condition_statement[condition_operator][value]
+                                ) or any(
+                                    trusted_account_id
+                                    in condition_statement[condition_operator][value]
+                                    for trusted_account_id in trusted_account_ids
+                                ):
+                                    is_condition_valid = True
 
     return is_condition_valid
 
diff --git a/prowler/providers/aws/services/opensearch/opensearch_service.py b/prowler/providers/aws/services/opensearch/opensearch_service.py
index ddb8cfdf8e..c319956247 100644
--- a/prowler/providers/aws/services/opensearch/opensearch_service.py
+++ b/prowler/providers/aws/services/opensearch/opensearch_service.py
@@ -88,7 +88,6 @@ def _describe_domain(self, regional_clients):
                     DomainName=domain.name
                 )
                 domain.arn = describe_domain["DomainStatus"]["ARN"]
-                domain.vpc_endpoints = None
                 if "Endpoints" in describe_domain["DomainStatus"]:
                     if "vpc" in describe_domain["DomainStatus"]["Endpoints"]:
                         domain.vpc_endpoints = [
@@ -98,11 +97,13 @@ def _describe_domain(self, regional_clients):
                             ].values()
                         ]
 
-                domain.vpc_id = None
                 if "VPCOptions" in describe_domain["DomainStatus"]:
-                    domain.vpc_id = describe_domain["DomainStatus"]["VPCOptions"][
+                    domain.vpc_id = describe_domain["DomainStatus"]["VPCOptions"].get(
                         "VPCId"
-                    ]
+                    )
+                    domain.subnet_ids = describe_domain["DomainStatus"][
+                        "VPCOptions"
+                    ].get("SubnetIds", [])
                 domain.cognito_options = describe_domain["DomainStatus"][
                     "CognitoOptions"
                 ]["Enabled"]
@@ -157,8 +158,9 @@ class OpenSearchDomain(BaseModel):
     region: str
     arn: str = None
     logging: list[PublishingLoggingOption] = []
-    vpc_endpoints: list[str] = None
+    vpc_endpoints: list[str] = []
     vpc_id: str = None
+    subnet_ids: list[str] = []
     access_policy: dict = None
     cognito_options: bool = None
     encryption_at_rest: bool = None
diff --git a/prowler/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible.metadata.json b/prowler/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible.metadata.json
index 2a71338586..de58049f28 100644
--- a/prowler/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible.metadata.json
+++ b/prowler/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible.metadata.json
@@ -1,28 +1,27 @@
 {
   "Provider": "aws",
   "CheckID": "opensearch_service_domains_not_publicly_accessible",
-  "CheckTitle": "Check if Amazon Opensearch/Elasticsearch domains are set as Public or if it has open policy access",
+  "CheckTitle": "Check if Amazon Opensearch/Elasticsearch domains are publicly accessible",
   "CheckType": [
-    "Protect",
-    "Secure Access Management"
+    "Effects/Data Exposure"
   ],
   "ServiceName": "opensearch",
   "SubServiceName": "",
   "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
   "Severity": "critical",
   "ResourceType": "AwsOpenSearchServiceDomain",
-  "Description": "Check if Amazon Opensearch/Elasticsearch domains are set as Public or if it has open policy access",
+  "Description": "Check if Amazon Opensearch/Elasticsearch domains are publicly accessible via their access policies.",
   "Risk": "Publicly accessible services could expose sensitive data to bad actors.",
   "RelatedUrl": "",
   "Remediation": {
     "Code": {
-      "CLI": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Elasticsearch/elasticsearch-domain-exposed.html",
+      "CLI": "",
       "NativeIaC": "",
-      "Other": "https://docs.prowler.com/checks/aws/public-policies/public_3#fix---runtime",
+      "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Elasticsearch/elasticsearch-domain-exposed.html",
       "Terraform": ""
     },
     "Recommendation": {
-      "Text": "Use  VPC endpoints for internal services.",
+      "Text": "Modify the access policy attached to your Amazon OpenSearch domain and replace the 'Principal' element value (i.e. '*') with the ARN of the trusted AWS account. You can also add a Condition clause to the policy statement to limit the domain access to a specific (trusted) IP address/IP range only.",
       "Url": "https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html"
     }
   },
diff --git a/prowler/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible.py b/prowler/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible.py
index 8165bf6e4f..b25d3e78df 100644
--- a/prowler/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible.py
+++ b/prowler/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible.py
@@ -1,7 +1,9 @@
 from prowler.lib.check.models import Check, Check_Report_AWS
+from prowler.providers.aws.services.iam.lib.policy import is_policy_public
 from prowler.providers.aws.services.opensearch.opensearch_client import (
     opensearch_client,
 )
+from prowler.providers.aws.services.vpc.vpc_client import vpc_client
 
 
 class opensearch_service_domains_not_publicly_accessible(Check):
@@ -15,43 +17,25 @@ def execute(self):
             report.resource_tags = domain.tags
             report.status = "PASS"
             report.status_extended = (
-                f"Opensearch domain {domain.name} does not allow anonymous access."
+                f"Opensearch domain {domain.name} is not publicly accessible."
             )
 
             if domain.vpc_id:
+                public_subnets = []
                 report.status_extended = f"Opensearch domain {domain.name} is in a VPC, then it is not publicly accessible."
-            elif domain.access_policy:
-                for statement in domain.access_policy["Statement"]:
-                    # look for open policies
+                for subnet in domain.subnet_ids:
                     if (
-                        statement["Effect"] == "Allow"
-                        and (
-                            "AWS" in statement["Principal"]
-                            and "*" in statement["Principal"]["AWS"]
-                        )
-                        or (statement["Principal"] == "*")
+                        subnet in vpc_client.vpc_subnets
+                        and vpc_client.vpc_subnets[subnet].public
                     ):
-                        if "Condition" not in statement:
-                            report.status = "FAIL"
-                            report.status_extended = f"Opensearch domain {domain.name} policy allows access (Principal: '*')."
-                            break
-                        else:
-                            if (
-                                "IpAddress" in statement["Condition"]
-                                and "aws:SourceIp"
-                                in statement["Condition"]["IpAddress"]
-                            ):
-                                for ip in statement["Condition"]["IpAddress"][
-                                    "aws:SourceIp"
-                                ]:
-                                    if ip == "*":
-                                        report.status = "FAIL"
-                                        report.status_extended = f"Opensearch domain {domain.name} policy allows access (Principal: '*') and network *."
-                                        break
-                                    elif ip == "0.0.0.0/0":
-                                        report.status = "FAIL"
-                                        report.status_extended = f"Opensearch domain {domain.name} policy allows access (Principal: '*') and network 0.0.0.0/0."
-                                        break
+                        public_subnets.append(subnet)
+
+                if len(public_subnets) > 0:
+                    report.status = "FAIL"
+                    report.status_extended = f"Opensearch domain {domain.name} is publicly accessible due to public subnets: {', '.join(public_subnets)}."
+            elif domain.access_policy and is_policy_public(domain.access_policy):
+                report.status = "FAIL"
+                report.status_extended = f"Opensearch domain {domain.name} is publicly accessible via access policy."
 
             findings.append(report)
 
diff --git a/prowler/providers/aws/services/rds/rds_instance_no_public_access/rds_instance_no_public_access.py b/prowler/providers/aws/services/rds/rds_instance_no_public_access/rds_instance_no_public_access.py
index 0604afd65a..5364653c97 100644
--- a/prowler/providers/aws/services/rds/rds_instance_no_public_access/rds_instance_no_public_access.py
+++ b/prowler/providers/aws/services/rds/rds_instance_no_public_access/rds_instance_no_public_access.py
@@ -2,6 +2,7 @@
 from prowler.providers.aws.services.ec2.ec2_client import ec2_client
 from prowler.providers.aws.services.ec2.lib.security_groups import check_security_group
 from prowler.providers.aws.services.rds.rds_client import rds_client
+from prowler.providers.aws.services.vpc.vpc_client import vpc_client
 
 
 class rds_instance_no_public_access(Check):
@@ -37,6 +38,17 @@ def execute(self):
                                         report.status = "FAIL"
                                         report.status_extended = f"RDS Instance {db_instance.id} is set as publicly accessible and security group {security_group.name} ({security_group.id}) has {db_instance.engine} port {db_instance_port} open to the Internet at endpoint {db_instance.endpoint.get('Address')}."
                                         break
+            # If the DB Instance is in a public subnet, it is publicly accessible
+            if report.status == "PASS" and db_instance.subnet_ids:
+                for subnet_id in db_instance.subnet_ids:
+                    if (
+                        subnet_id in vpc_client.vpc_subnets
+                        and vpc_client.vpc_subnets[subnet_id].public
+                    ):
+                        report.status = "FAIL"
+                        report.status_extended = f"RDS Instance {db_instance.id} is in a public subnet {subnet_id}."
+                        break
+
             findings.append(report)
 
         return findings
diff --git a/prowler/providers/aws/services/rds/rds_service.py b/prowler/providers/aws/services/rds/rds_service.py
index c3c385a566..b61471b8fb 100644
--- a/prowler/providers/aws/services/rds/rds_service.py
+++ b/prowler/providers/aws/services/rds/rds_service.py
@@ -102,6 +102,13 @@ def _describe_db_instances(self, regional_client):
                                 ),
                                 port=instance.get("Endpoint", {}).get("Port"),
                                 vpc_id=instance.get("DBSubnetGroup", {}).get("VpcId"),
+                                subnet_ids=[
+                                    subnet_id["SubnetIdentifier"]
+                                    for subnet_id in instance.get(
+                                        "DBSubnetGroup", {}
+                                    ).get("Subnets", [])
+                                    if subnet_id["SubnetStatus"] == "Active"
+                                ],
                             )
         except Exception as error:
             logger.error(
@@ -512,6 +519,7 @@ class DBInstance(BaseModel):
     copy_tags_to_snapshot: Optional[bool]
     port: Optional[int]
     vpc_id: Optional[str]
+    subnet_ids: list[str] = []
 
 
 class DBCluster(BaseModel):
diff --git a/prowler/providers/aws/services/redshift/redshift_cluster_public_access/redshift_cluster_public_access.py b/prowler/providers/aws/services/redshift/redshift_cluster_public_access/redshift_cluster_public_access.py
index 58f031f9f8..1a42615be7 100644
--- a/prowler/providers/aws/services/redshift/redshift_cluster_public_access/redshift_cluster_public_access.py
+++ b/prowler/providers/aws/services/redshift/redshift_cluster_public_access/redshift_cluster_public_access.py
@@ -1,5 +1,8 @@
 from prowler.lib.check.models import Check, Check_Report_AWS
+from prowler.providers.aws.services.ec2.ec2_client import ec2_client
+from prowler.providers.aws.services.ec2.lib.security_groups import check_security_group
 from prowler.providers.aws.services.redshift.redshift_client import redshift_client
+from prowler.providers.aws.services.vpc.vpc_client import vpc_client
 
 
 class redshift_cluster_public_access(Check):
@@ -18,6 +21,25 @@ def execute(self):
             if cluster.endpoint_address and cluster.public_access:
                 report.status = "FAIL"
                 report.status_extended = f"Redshift Cluster {cluster.id} is publicly accessible at endpoint {cluster.endpoint_address}."
+            elif (
+                cluster.vpc_id
+                and cluster.vpc_id in vpc_client.vpcs
+                and vpc_client.vpcs[cluster.vpc_id].public
+            ):
+                report.status = "FAIL"
+                report.status_extended = f"Redshift Cluster {cluster.id} is in a public VPC {cluster.vpc_id}."
+            elif cluster.vpc_security_groups:
+                for sg_id in cluster.vpc_security_groups:
+                    sg_arn = f"arn:{redshift_client.audited_partition}:ec2:{cluster.region}:{redshift_client.audited_account}:security-group/{sg_id}"
+                    if sg_arn in ec2_client.security_groups:
+                        for ingress_rule in ec2_client.security_groups[
+                            sg_arn
+                        ].ingress_rules:
+                            if check_security_group(
+                                ingress_rule, "tcp", any_address=True
+                            ):
+                                report.status = "FAIL"
+                                report.status_extended = f"Redshift Cluster {cluster.id} is in VPC {cluster.vpc_id} with a public security group {sg_id}."
 
             findings.append(report)
 
diff --git a/prowler/providers/aws/services/redshift/redshift_service.py b/prowler/providers/aws/services/redshift/redshift_service.py
index 27e09361b3..8075e1c4c7 100644
--- a/prowler/providers/aws/services/redshift/redshift_service.py
+++ b/prowler/providers/aws/services/redshift/redshift_service.py
@@ -7,7 +7,6 @@
 from prowler.providers.aws.lib.service.service import AWSService
 
 
-################################ Redshift
 class Redshift(AWSService):
     def __init__(self, provider):
         # Call AWSService's __init__
@@ -18,7 +17,7 @@ def __init__(self, provider):
         self._describe_cluster_snapshots(self.regional_clients)
 
     def _describe_clusters(self, regional_client):
-        logger.info("Redshift - describing clusters...")
+        logger.info("Redshift - Describing Clusters...")
         try:
             list_clusters_paginator = regional_client.get_paginator("describe_clusters")
             for page in list_clusters_paginator.paginate():
@@ -30,6 +29,12 @@ def _describe_clusters(self, regional_client):
                         cluster_to_append = Cluster(
                             arn=arn,
                             id=cluster["ClusterIdentifier"],
+                            vpc_id=cluster.get("VpcId"),
+                            vpc_security_groups=[
+                                sg["VpcSecurityGroupId"]
+                                for sg in cluster.get("VpcSecurityGroups")
+                                if sg["Status"] == "active"
+                            ],
                             region=regional_client.region,
                             tags=cluster.get("Tags"),
                         )
@@ -54,7 +59,7 @@ def _describe_clusters(self, regional_client):
             )
 
     def _describe_logging_status(self, regional_clients):
-        logger.info("Redshift - describing logging status...")
+        logger.info("Redshift - Describing Logging Status...")
         try:
             for cluster in self.clusters:
                 regional_client = regional_clients[cluster.region]
@@ -75,7 +80,7 @@ def _describe_logging_status(self, regional_clients):
             )
 
     def _describe_cluster_snapshots(self, regional_clients):
-        logger.info("Redshift - describing logging status...")
+        logger.info("Redshift - Describing Cluster Snapshots...")
         try:
             for cluster in self.clusters:
                 regional_client = regional_clients[cluster.region]
@@ -95,10 +100,12 @@ class Cluster(BaseModel):
     id: str
     arn: str
     region: str
-    public_access: bool = None
+    vpc_id: str = None
+    vpc_security_groups: list = []
+    public_access: bool = False
     endpoint_address: str = None
-    allow_version_upgrade: bool = None
-    logging_enabled: bool = None
+    allow_version_upgrade: bool = False
+    logging_enabled: bool = False
     bucket: str = None
     cluster_snapshots: bool = None
     tags: Optional[list] = []
diff --git a/prowler/providers/aws/services/s3/s3_bucket_cross_account_access/s3_bucket_cross_account_access.py b/prowler/providers/aws/services/s3/s3_bucket_cross_account_access/s3_bucket_cross_account_access.py
index ea1c812436..85bb6962ae 100644
--- a/prowler/providers/aws/services/s3/s3_bucket_cross_account_access/s3_bucket_cross_account_access.py
+++ b/prowler/providers/aws/services/s3/s3_bucket_cross_account_access/s3_bucket_cross_account_access.py
@@ -20,9 +20,7 @@ def execute(self):
                 report.status_extended = (
                     f"S3 Bucket {bucket.name} does not have a bucket policy."
                 )
-            elif is_policy_public(
-                bucket.policy, source_account=s3_client.audited_account
-            ):
+            elif is_policy_public(bucket.policy):
                 report.status = "FAIL"
                 report.status_extended = f"S3 Bucket {bucket.name} has a bucket policy allowing cross account access."
 
diff --git a/prowler/providers/aws/services/vpc/vpc_service.py b/prowler/providers/aws/services/vpc/vpc_service.py
index 194b7f85a4..773303759b 100644
--- a/prowler/providers/aws/services/vpc/vpc_service.py
+++ b/prowler/providers/aws/services/vpc/vpc_service.py
@@ -369,6 +369,34 @@ def _describe_vpc_subnets(self, regional_client):
                                         public = True
                                     if "NatGatewayId" in route:
                                         nat_gateway = True
+                            if not public:
+                                # Check if the subnet has any public NACL associated
+                                nacls = (
+                                    regional_client_for_subnet.describe_network_acls(
+                                        Filters=[
+                                            {
+                                                "Name": "association.subnet-id",
+                                                "Values": [subnet["SubnetId"]],
+                                            }
+                                        ]
+                                    )
+                                )
+                                has_ingress = False
+                                has_egress = False
+                                for nacl in nacls.get("NetworkAcls", []):
+                                    for acl_entry in nacl.get("Entries", []):
+                                        if acl_entry.get("RuleAction") == "allow" and (
+                                            acl_entry.get("CidrBlock") == "0.0.0.0/0"
+                                            or acl_entry.get("Ipv6CidrBlock") == "::/0"
+                                        ):
+                                            if acl_entry.get("Egress"):
+                                                has_egress = True
+                                            else:
+                                                has_ingress = True
+                                        if has_egress and has_ingress:
+                                            public = True
+                                            break
+
                             subnet_name = ""
                             for tag in subnet.get("Tags", []):
                                 if tag["Key"] == "Name":
@@ -393,6 +421,8 @@ def _describe_vpc_subnets(self, regional_client):
                             for vpc in self.vpcs.values():
                                 if vpc.id == subnet["VpcId"]:
                                     vpc.subnets.append(object)
+                                    if object.public:
+                                        vpc.public = True
                         except Exception as error:
                             logger.error(
                                 f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
@@ -454,6 +484,7 @@ class VPCs(BaseModel):
     name: str
     default: bool
     in_use: bool = False
+    public: bool = False
     cidr_block: str
     flow_log: bool = False
     region: str
diff --git a/tests/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible_test.py b/tests/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible_test.py
index 4278b991d8..d7f8d75a40 100644
--- a/tests/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible_test.py
+++ b/tests/providers/aws/services/awslambda/awslambda_function_not_publicly_accessible/awslambda_function_not_publicly_accessible_test.py
@@ -267,6 +267,7 @@ def test_function_not_public(self):
     def test_function_public_with_canonical(self):
         lambda_client = mock.MagicMock
         lambda_client.audited_account = AWS_ACCOUNT_NUMBER
+        lambda_client.audit_config = {}
         function_name = "test-lambda"
         function_runtime = "nodejs4.3"
         function_arn = f"arn:aws:lambda:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:function/{function_name}"
@@ -498,6 +499,7 @@ def test_function_public_with_alb(self):
     def test_function_could_be_invoked_by_specific_aws_account(self):
         lambda_client = mock.MagicMock
         lambda_client.audited_account = AWS_ACCOUNT_NUMBER
+        lambda_client.audit_config = {}
         function_name = "test-lambda"
         function_runtime = "nodejs4.3"
         function_arn = f"arn:aws:lambda:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:function/{function_name}"
@@ -557,6 +559,7 @@ def test_function_could_be_invoked_by_specific_aws_account(self):
     def test_function_could_be_invoked_by_specific_other_aws_account(self):
         lambda_client = mock.MagicMock
         lambda_client.audited_account = AWS_ACCOUNT_NUMBER
+        lambda_client.audit_config = {}
         function_name = "test-lambda"
         function_runtime = "nodejs4.3"
         function_arn = f"arn:aws:lambda:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:function/{function_name}"
@@ -616,6 +619,7 @@ def test_function_could_be_invoked_by_specific_other_aws_account(self):
     def test_function_public_policy_with_several_statements(self):
         lambda_client = mock.MagicMock
         lambda_client.audited_account = AWS_ACCOUNT_NUMBER
+        lambda_client.audit_config = {}
         function_name = "test-lambda"
         function_runtime = "nodejs4.3"
         function_arn = f"arn:aws:lambda:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:function/{function_name}"
diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket_test.py
index e09dd1806f..abc39d9765 100644
--- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket_test.py
+++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket_test.py
@@ -14,6 +14,10 @@
 
 
 class Test_cloudfront_s3_origin_non_existent_bucket:
+    @mock.patch(
+        "prowler.providers.aws.services.s3.s3_service.S3._head_bucket",
+        new=mock.MagicMock(return_value=False),
+    )
     def test_no_distributions(self):
         # Distributions
         cloudfront_client = mock.MagicMock
diff --git a/tests/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access_test.py b/tests/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access_test.py
index 80b1242223..4071394a6d 100644
--- a/tests/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access_test.py
+++ b/tests/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access_test.py
@@ -124,6 +124,7 @@ def test_tables_no_policy(self):
         from prowler.providers.aws.services.dynamodb.dynamodb_service import Table
 
         dynamodb_client.audited_account = AWS_ACCOUNT_NUMBER
+        dynamodb_client.audit_config = {}
         arn = test_table_arn
         dynamodb_client.tables = {
             arn: Table(
@@ -161,6 +162,7 @@ def test_tables_not_public(self):
         from prowler.providers.aws.services.dynamodb.dynamodb_service import Table
 
         dynamodb_client.audited_account = AWS_ACCOUNT_NUMBER
+        dynamodb_client.audit_config = {}
         arn = test_table_arn
         dynamodb_client.tables = {
             arn: Table(
@@ -198,6 +200,7 @@ def test_tables_public(self):
         from prowler.providers.aws.services.dynamodb.dynamodb_service import Table
 
         dynamodb_client.audited_account = AWS_ACCOUNT_NUMBER
+        dynamodb_client.audit_config = {}
         arn = test_table_arn
         dynamodb_client.tables = {
             arn: Table(
@@ -237,6 +240,7 @@ def test_tables_public_with_condition_not_valid(self):
         from prowler.providers.aws.services.dynamodb.dynamodb_service import Table
 
         dynamodb_client.audited_account = AWS_ACCOUNT_NUMBER
+        dynamodb_client.audit_config = {}
         arn = test_table_arn
         dynamodb_client.tables = {
             arn: Table(
@@ -276,6 +280,7 @@ def test_tables_public_with_condition_valid(self):
         from prowler.providers.aws.services.dynamodb.dynamodb_service import Table
 
         dynamodb_client.audited_account = AWS_ACCOUNT_NUMBER
+        dynamodb_client.audit_config = {}
         arn = test_table_arn
         dynamodb_client.tables = {
             arn: Table(
@@ -314,6 +319,7 @@ def test_tables_public_with_condition_valid_with_other_account(self):
         from prowler.providers.aws.services.dynamodb.dynamodb_service import Table
 
         dynamodb_client.audited_account = AWS_ACCOUNT_NUMBER
+        dynamodb_client.audit_config = {}
         arn = test_table_arn
         dynamodb_client.tables = {
             arn: Table(
@@ -352,6 +358,7 @@ def test_tables_public_with_condition_with_invalid_block(self):
         from prowler.providers.aws.services.dynamodb.dynamodb_service import Table
 
         dynamodb_client.audited_account = AWS_ACCOUNT_NUMBER
+        dynamodb_client.audit_config = {}
         arn = test_table_arn
         dynamodb_client.tables = {
             arn: Table(
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_cassandra_exposed_to_internet/ec2_instance_port_cassandra_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_cassandra_exposed_to_internet/ec2_instance_port_cassandra_exposed_to_internet_test.py
index d9ee15e932..0ffb3aabb3 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_cassandra_exposed_to_internet/ec2_instance_port_cassandra_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_cassandra_exposed_to_internet/ec2_instance_port_cassandra_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_cifs_exposed_to_internet/ec2_instance_port_cifs_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_cifs_exposed_to_internet/ec2_instance_port_cifs_exposed_to_internet_test.py
index 0e6a838227..1c01d74ea7 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_cifs_exposed_to_internet/ec2_instance_port_cifs_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_cifs_exposed_to_internet/ec2_instance_port_cifs_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_elasticsearch_kibana_exposed_to_internet/ec2_instance_port_elasticsearch_kibana_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_elasticsearch_kibana_exposed_to_internet/ec2_instance_port_elasticsearch_kibana_exposed_to_internet_test.py
index 5ba9aa593e..911856a184 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_elasticsearch_kibana_exposed_to_internet/ec2_instance_port_elasticsearch_kibana_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_elasticsearch_kibana_exposed_to_internet/ec2_instance_port_elasticsearch_kibana_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_ftp_exposed_to_internet/ec2_instance_port_ftp_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_ftp_exposed_to_internet/ec2_instance_port_ftp_exposed_to_internet_test.py
index 63cf5f2417..f285bc1bee 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_ftp_exposed_to_internet/ec2_instance_port_ftp_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_ftp_exposed_to_internet/ec2_instance_port_ftp_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_kafka_exposed_to_internet/ec2_instance_port_kafka_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_kafka_exposed_to_internet/ec2_instance_port_kafka_exposed_to_internet_test.py
index 40ea7dea81..de0468d7d7 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_kafka_exposed_to_internet/ec2_instance_port_kafka_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_kafka_exposed_to_internet/ec2_instance_port_kafka_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_kerberos_exposed_to_internet/ec2_instance_port_kerberos_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_kerberos_exposed_to_internet/ec2_instance_port_kerberos_exposed_to_internet_test.py
index 65ff232f65..77601cfd02 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_kerberos_exposed_to_internet/ec2_instance_port_kerberos_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_kerberos_exposed_to_internet/ec2_instance_port_kerberos_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_ldap_exposed_to_internet/ec2_instance_port_ldap_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_ldap_exposed_to_internet/ec2_instance_port_ldap_exposed_to_internet_test.py
index 53c7cd05dd..26c26979a5 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_ldap_exposed_to_internet/ec2_instance_port_ldap_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_ldap_exposed_to_internet/ec2_instance_port_ldap_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_memcached_exposed_to_internet/ec2_instance_port_memcached_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_memcached_exposed_to_internet/ec2_instance_port_memcached_exposed_to_internet_test.py
index 59c7d54d49..ae7c8d1dff 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_memcached_exposed_to_internet/ec2_instance_port_memcached_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_memcached_exposed_to_internet/ec2_instance_port_memcached_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_mongodb_exposed_to_internet/ec2_instance_port_mongodb_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_mongodb_exposed_to_internet/ec2_instance_port_mongodb_exposed_to_internet_test.py
index 8a825c1548..128c89bd39 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_mongodb_exposed_to_internet/ec2_instance_port_mongodb_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_mongodb_exposed_to_internet/ec2_instance_port_mongodb_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_mysql_exposed_to_internet/ec2_instance_port_mysql_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_mysql_exposed_to_internet/ec2_instance_port_mysql_exposed_to_internet_test.py
index 61c400df22..93f7462253 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_mysql_exposed_to_internet/ec2_instance_port_mysql_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_mysql_exposed_to_internet/ec2_instance_port_mysql_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_oracle_exposed_to_internet/ec2_instance_port_oracle_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_oracle_exposed_to_internet/ec2_instance_port_oracle_exposed_to_internet_test.py
index b4397077a5..9771c7fff4 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_oracle_exposed_to_internet/ec2_instance_port_oracle_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_oracle_exposed_to_internet/ec2_instance_port_oracle_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_postgresql_exposed_to_internet/ec2_instance_port_postgresql_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_postgresql_exposed_to_internet/ec2_instance_port_postgresql_exposed_to_internet_test.py
index 20c4b7eb18..471e311c55 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_postgresql_exposed_to_internet/ec2_instance_port_postgresql_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_postgresql_exposed_to_internet/ec2_instance_port_postgresql_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_rdp_exposed_to_internet/ec2_instance_port_rdp_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_rdp_exposed_to_internet/ec2_instance_port_rdp_exposed_to_internet_test.py
index fcf9521e2e..55ab1616b1 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_rdp_exposed_to_internet/ec2_instance_port_rdp_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_rdp_exposed_to_internet/ec2_instance_port_rdp_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_redis_exposed_to_internet/ec2_instance_port_redis_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_redis_exposed_to_internet/ec2_instance_port_redis_exposed_to_internet_test.py
index b08a9d7fde..7092d48383 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_redis_exposed_to_internet/ec2_instance_port_redis_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_redis_exposed_to_internet/ec2_instance_port_redis_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_sqlserver_exposed_to_internet/ec2_instance_port_sqlserver_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_sqlserver_exposed_to_internet/ec2_instance_port_sqlserver_exposed_to_internet_test.py
index 8ae6373b24..b725293e71 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_sqlserver_exposed_to_internet/ec2_instance_port_sqlserver_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_sqlserver_exposed_to_internet/ec2_instance_port_sqlserver_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_ssh_exposed_to_internet/ec2_instance_port_ssh_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_ssh_exposed_to_internet/ec2_instance_port_ssh_exposed_to_internet_test.py
index 7536a3eec3..5986f96935 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_ssh_exposed_to_internet/ec2_instance_port_ssh_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_ssh_exposed_to_internet/ec2_instance_port_ssh_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ec2/ec2_instance_port_telnet_exposed_to_internet/ec2_instance_port_telnet_exposed_to_internet_test.py b/tests/providers/aws/services/ec2/ec2_instance_port_telnet_exposed_to_internet/ec2_instance_port_telnet_exposed_to_internet_test.py
index b2b8fdeb81..9d8828476d 100644
--- a/tests/providers/aws/services/ec2/ec2_instance_port_telnet_exposed_to_internet/ec2_instance_port_telnet_exposed_to_internet_test.py
+++ b/tests/providers/aws/services/ec2/ec2_instance_port_telnet_exposed_to_internet/ec2_instance_port_telnet_exposed_to_internet_test.py
@@ -220,6 +220,23 @@ def test_ec2_instance_exposed_port_in_public_subnet(self):
         subnet_id = ec2_client.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/16")[
             "Subnet"
         ]["SubnetId"]
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         instance = ec2_resource.create_instances(
             ImageId="ami-12345678",
             MinCount=1,
diff --git a/tests/providers/aws/services/ecr/ecr_repositories_not_publicly_accessible/ecr_repositories_not_publicly_accessible_test.py b/tests/providers/aws/services/ecr/ecr_repositories_not_publicly_accessible/ecr_repositories_not_publicly_accessible_test.py
index e6fad5645b..9a34c3a004 100644
--- a/tests/providers/aws/services/ecr/ecr_repositories_not_publicly_accessible/ecr_repositories_not_publicly_accessible_test.py
+++ b/tests/providers/aws/services/ecr/ecr_repositories_not_publicly_accessible/ecr_repositories_not_publicly_accessible_test.py
@@ -87,6 +87,8 @@ def test_registry_no_repositories(self):
     def test_repository_not_public(self):
         ecr_client = mock.MagicMock
         ecr_client.registries = {}
+        ecr_client.audit_config = {}
+        ecr_client.audited_account = AWS_ACCOUNT_NUMBER
         ecr_client.registries[AWS_REGION_EU_WEST_1] = Registry(
             id=AWS_ACCOUNT_NUMBER,
             region=AWS_REGION_EU_WEST_1,
@@ -130,6 +132,8 @@ def test_repository_not_public(self):
     def test_repository_public(self):
         ecr_client = mock.MagicMock
         ecr_client.registries = {}
+        ecr_client.audit_config = {}
+        ecr_client.audited_account = AWS_ACCOUNT_NUMBER
         ecr_client.registries[AWS_REGION_EU_WEST_1] = Registry(
             id=AWS_ACCOUNT_NUMBER,
             region=AWS_REGION_EU_WEST_1,
diff --git a/tests/providers/aws/services/efs/efs_not_publicly_accessible/efs_not_publicly_accessible_test.py b/tests/providers/aws/services/efs/efs_not_publicly_accessible/efs_not_publicly_accessible_test.py
index 2ea9111cde..a6fc23dccc 100644
--- a/tests/providers/aws/services/efs/efs_not_publicly_accessible/efs_not_publicly_accessible_test.py
+++ b/tests/providers/aws/services/efs/efs_not_publicly_accessible/efs_not_publicly_accessible_test.py
@@ -77,6 +77,8 @@
 class Test_efs_not_publicly_accessible:
     def test_efs_valid_policy(self):
         efs_client = mock.MagicMock
+        efs_client.audited_account = AWS_ACCOUNT_NUMBER
+        efs_client.audit_config = {}
         efs_arn = f"arn:aws:elasticfilesystem:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:file-system/{file_system_id}"
         efs_client.filesystems = [
             FileSystem(
@@ -111,6 +113,8 @@ def test_efs_valid_policy(self):
 
     def test_efs_valid_policy_with_mount_target_condition(self):
         efs_client = mock.MagicMock
+        efs_client.audited_account = AWS_ACCOUNT_NUMBER
+        efs_client.audit_config = {}
         efs_arn = f"arn:aws:elasticfilesystem:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:file-system/{file_system_id}"
         efs_client.filesystems = [
             FileSystem(
@@ -145,6 +149,8 @@ def test_efs_valid_policy_with_mount_target_condition(self):
 
     def test_efs_valid_policy_with_source_arn_condition(self):
         efs_client = mock.MagicMock
+        efs_client.audited_account = AWS_ACCOUNT_NUMBER
+        efs_client.audit_config = {}
         efs_arn = f"arn:aws:elasticfilesystem:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:file-system/{file_system_id}"
         efs_client.filesystems = [
             FileSystem(
@@ -179,6 +185,8 @@ def test_efs_valid_policy_with_source_arn_condition(self):
 
     def test_efs_invalid_policy(self):
         efs_client = mock.MagicMock
+        efs_client.audited_account = AWS_ACCOUNT_NUMBER
+        efs_client.audit_config = {}
         efs_arn = f"arn:aws:elasticfilesystem:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:file-system/{file_system_id}"
 
         efs_client.filesystems = [
@@ -214,6 +222,8 @@ def test_efs_invalid_policy(self):
 
     def test_efs_no_policy(self):
         efs_client = mock.MagicMock
+        efs_client.audited_account = AWS_ACCOUNT_NUMBER
+        efs_client.audit_config = {}
         efs_arn = f"arn:aws:elasticfilesystem:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:file-system/{file_system_id}"
         efs_client.filesystems = [
             FileSystem(
diff --git a/tests/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing_test.py b/tests/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing_test.py
index 5593a5ee37..2d26f74320 100644
--- a/tests/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing_test.py
+++ b/tests/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing_test.py
@@ -1,4 +1,3 @@
-from re import search
 from unittest import mock
 
 from boto3 import client, resource
@@ -89,9 +88,8 @@ def test_elbv2_private(self):
 
             assert len(result) == 1
             assert result[0].status == "PASS"
-            assert search(
-                "is not internet facing",
-                result[0].status_extended,
+            assert result[0].status_extended == (
+                "ELBv2 ALB my-lb is not internet facing."
             )
             assert result[0].resource_id == "my-lb"
             assert result[0].resource_arn == lb["LoadBalancerArn"]
@@ -145,9 +143,81 @@ def test_elbv2_internet_facing(self):
 
             assert len(result) == 1
             assert result[0].status == "FAIL"
-            assert search(
-                "is internet facing",
-                result[0].status_extended,
+            assert result[0].status_extended == (
+                f"ELBv2 ALB my-lb is internet facing in {lb['DNSName']}."
+            )
+            assert result[0].resource_id == "my-lb"
+            assert result[0].resource_arn == lb["LoadBalancerArn"]
+
+    @mock_aws
+    def test_elbv2_public_sg(self):
+        conn = client("elbv2", region_name=AWS_REGION_EU_WEST_1)
+        ec2 = resource("ec2", region_name=AWS_REGION_EU_WEST_1)
+        ec2_client = client("ec2", region_name=AWS_REGION_EU_WEST_1)
+
+        vpc = ec2.create_vpc(CidrBlock="172.28.7.0/24", InstanceTenancy="default")
+        subnet1 = ec2.create_subnet(
+            VpcId=vpc.id,
+            CidrBlock="172.28.7.192/26",
+            AvailabilityZone=AWS_REGION_EU_WEST_1_AZA,
+        )
+        subnet2 = ec2.create_subnet(
+            VpcId=vpc.id,
+            CidrBlock="172.28.7.0/26",
+            AvailabilityZone=AWS_REGION_EU_WEST_1_AZB,
+        )
+        default_sg = ec2_client.describe_security_groups(GroupNames=["default"])[
+            "SecurityGroups"
+        ][0]
+
+        default_sg_id = default_sg["GroupId"]
+
+        # Authorize ingress rule
+        ec2_client.authorize_security_group_ingress(
+            GroupId=default_sg_id,
+            IpPermissions=[
+                {
+                    "IpProtocol": "-1",
+                    "IpRanges": [{"CidrIp": "0.0.0.0/0"}],
+                }
+            ],
+        )
+        lb = conn.create_load_balancer(
+            Name="my-lb",
+            Subnets=[subnet1.id, subnet2.id],
+            SecurityGroups=[default_sg_id],
+            Scheme="internal",
+        )["LoadBalancers"][0]
+
+        from prowler.providers.aws.services.ec2.ec2_service import EC2
+        from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2
+
+        aws_provider = set_mocked_aws_provider(
+            [AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
+        )
+
+        with mock.patch(
+            "prowler.providers.common.provider.Provider.get_global_provider",
+            return_value=aws_provider,
+        ), mock.patch(
+            "prowler.providers.aws.services.elbv2.elbv2_internet_facing.elbv2_internet_facing.elbv2_client",
+            new=ELBv2(aws_provider),
+        ), mock.patch(
+            "prowler.providers.aws.services.elbv2.elbv2_internet_facing.elbv2_internet_facing.ec2_client",
+            new=EC2(aws_provider),
+        ):
+
+            from prowler.providers.aws.services.elbv2.elbv2_internet_facing.elbv2_internet_facing import (
+                elbv2_internet_facing,
+            )
+
+            check = elbv2_internet_facing()
+            result = check.execute()
+
+            assert len(result) == 1
+            assert result[0].status == "FAIL"
+            assert result[0].status_extended == (
+                f"ELBv2 ALB my-lb is internet facing due to public security group {default_sg_id}."
             )
             assert result[0].resource_id == "my-lb"
             assert result[0].resource_arn == lb["LoadBalancerArn"]
diff --git a/tests/providers/aws/services/elbv2/elbv2_service_test.py b/tests/providers/aws/services/elbv2/elbv2_service_test.py
index 81ab1d31eb..5cebd06734 100644
--- a/tests/providers/aws/services/elbv2/elbv2_service_test.py
+++ b/tests/providers/aws/services/elbv2/elbv2_service_test.py
@@ -101,6 +101,10 @@ def test_describe_load_balancers(self):
             ]
             == subnet2.id
         )
+        assert (
+            elbv2.loadbalancersv2[lb["LoadBalancerArn"]].security_groups[0]
+            == security_group.id
+        )
 
     # Test ELBv2 Describe Listeners
     @mock_aws
diff --git a/tests/providers/aws/services/iam/lib/policy_test.py b/tests/providers/aws/services/iam/lib/policy_test.py
index 5b62dc61e3..c72645337a 100644
--- a/tests/providers/aws/services/iam/lib/policy_test.py
+++ b/tests/providers/aws/services/iam/lib/policy_test.py
@@ -28,6 +28,14 @@ def test_condition_parser_string_equals_aws_SourceAccount_list(self):
             condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
         )
 
+    def test_condition_parser_string_equals_aws_SourceAccount_list_using_config(self):
+        condition_statement = {
+            "StringEquals": {"aws:SourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
+        }
+        assert is_condition_block_restrictive(
+            condition_statement, trusted_account_ids=[TRUSTED_AWS_ACCOUNT_NUMBER]
+        )
+
     def test_condition_parser_string_equals_aws_SourceAccount_list_not_valid(self):
         condition_statement = {
             "StringEquals": {
@@ -49,6 +57,14 @@ def test_condition_parser_string_equals_aws_SourceAccount_str(self):
             condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
         )
 
+    def test_condition_parser_string_equals_aws_SourceAccount_str_using_config(self):
+        condition_statement = {
+            "StringEquals": {"aws:SourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
+        }
+        assert is_condition_block_restrictive(
+            condition_statement, trusted_account_ids=[TRUSTED_AWS_ACCOUNT_NUMBER]
+        )
+
     def test_condition_parser_string_equals_aws_SourceAccount_str_not_valid(self):
         condition_statement = {
             "StringEquals": {"aws:SourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
@@ -1718,7 +1734,7 @@ def test_is_condition_restricting_from_private_ip_from_invalid_ip(self):
         }
         assert not is_condition_restricting_from_private_ip(condition_from_invalid_ip)
 
-    def test__is_policy_public__(self):
+    def test_is_policy_public_(self):
         policy = {
             "Statement": [
                 {
@@ -1733,7 +1749,7 @@ def test__is_policy_public__(self):
             policy, not_allowed_actions=["elasticfilesystem:ClientMount"]
         )
 
-    def test__is_policy_public__with_principal_dict(self):
+    def test_is_policy_public_with_principal_dict(self):
         policy = {
             "Statement": [
                 {
@@ -1748,7 +1764,7 @@ def test__is_policy_public__with_principal_dict(self):
             policy, not_allowed_actions=["elasticfilesystem:ClientMount"]
         )
 
-    def test__is_policy_public__with_secure_conditions_and_allowed_conditions(
+    def test_is_policy_public_with_secure_conditions_and_allowed_conditions(
         self,
     ):
         policy = {
@@ -1767,7 +1783,7 @@ def test__is_policy_public__with_secure_conditions_and_allowed_conditions(
         }
         assert not is_policy_public(policy)
 
-    def test__is_policy_public__with_secure_conditions_and_allowed_conditions_nested(
+    def test_is_policy_public_with_secure_conditions_and_allowed_conditions_nested(
         self,
     ):
         policy = {
@@ -1789,7 +1805,7 @@ def test__is_policy_public__with_secure_conditions_and_allowed_conditions_nested
         }
         assert not is_policy_public(policy)
 
-    def test__is_policy_public__with_secure_conditions_and_allowed_conditions_nested_dict(
+    def test_is_policy_public_with_secure_conditions_and_allowed_conditions_nested_dict(
         self,
     ):
         policy = {
@@ -1813,7 +1829,7 @@ def test__is_policy_public__with_secure_conditions_and_allowed_conditions_nested
         }
         assert not is_policy_public(policy)
 
-    def test__is_policy_public__with_secure_conditions_and_allowed_conditions_nested_dict_key(
+    def test_is_policy_public_with_secure_conditions_and_allowed_conditions_nested_dict_key(
         self,
     ):
         policy = {
@@ -1837,7 +1853,7 @@ def test__is_policy_public__with_secure_conditions_and_allowed_conditions_nested
         }
         assert not is_policy_public(policy)
 
-    def test__is_policy_public_with_action_wildcard(
+    def test_is_policy_public_with_action_wildcard(
         self,
     ):
         policy = {
@@ -1852,7 +1868,7 @@ def test__is_policy_public_with_action_wildcard(
         }
         assert is_policy_public(policy)
 
-    def test__is_policy_public_allowing_all_actions(
+    def test_is_policy_public_allowing_all_actions(
         self,
     ):
         policy = {
@@ -1867,6 +1883,19 @@ def test__is_policy_public_allowing_all_actions(
         }
         assert is_policy_public(policy)
 
+    def test_is_policy_public_allowing_other_account(self):
+        policy = {
+            "Statement": [
+                {
+                    "Effect": "Allow",
+                    "Principal": {"AWS": "arn:aws:iam::123456789012:root"},
+                    "Action": "*",
+                    "Resource": "*",
+                }
+            ]
+        }
+        assert not is_policy_public(policy)
+
     def test_check_admin_access(self):
         policy = {
             "Version": "2012-10-17",
diff --git a/tests/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible_test.py b/tests/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible_test.py
index dc6c5514f7..c1b1db96c1 100644
--- a/tests/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible_test.py
+++ b/tests/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible_test.py
@@ -133,7 +133,7 @@ def test_policy_data_restricted(self):
             assert result[0].status == "PASS"
             assert (
                 result[0].status_extended
-                == f"Opensearch domain {domain_name} does not allow anonymous access."
+                == f"Opensearch domain {domain_name} is not publicly accessible."
             )
             assert result[0].resource_id == domain_name
             assert result[0].resource_arn == domain_arn
@@ -174,7 +174,7 @@ def test_policy_data_not_restricted_with_principal_AWS(self):
             assert result[0].status == "FAIL"
             assert (
                 result[0].status_extended
-                == f"Opensearch domain {domain_name} policy allows access (Principal: '*')."
+                == f"Opensearch domain {domain_name} is publicly accessible via access policy."
             )
             assert result[0].resource_id == domain_name
             assert result[0].resource_arn == domain_arn
@@ -215,7 +215,7 @@ def test_policy_data_not_restricted_with_principal_no_AWS(self):
             assert result[0].status == "FAIL"
             assert (
                 result[0].status_extended
-                == f"Opensearch domain {domain_name} policy allows access (Principal: '*')."
+                == f"Opensearch domain {domain_name} is publicly accessible via access policy."
             )
             assert result[0].resource_id == domain_name
             assert result[0].resource_arn == domain_arn
@@ -256,7 +256,7 @@ def test_policy_data_not_restricted_ip_full(self):
             assert result[0].status == "FAIL"
             assert (
                 result[0].status_extended
-                == f"Opensearch domain {domain_name} policy allows access (Principal: '*') and network *."
+                == f"Opensearch domain {domain_name} is publicly accessible via access policy."
             )
             assert result[0].resource_id == domain_name
             assert result[0].resource_arn == domain_arn
@@ -297,7 +297,7 @@ def test_policy_data_not_restricted_whole_internet(self):
             assert result[0].status == "FAIL"
             assert (
                 result[0].status_extended
-                == f"Opensearch domain {domain_name} policy allows access (Principal: '*') and network 0.0.0.0/0."
+                == f"Opensearch domain {domain_name} is publicly accessible via access policy."
             )
             assert result[0].resource_id == domain_name
             assert result[0].resource_arn == domain_arn
@@ -348,3 +348,57 @@ def test_domain_inside_vpc(self):
             )
             assert result[0].region == AWS_REGION_US_WEST_2
             assert result[0].resource_tags == []
+
+    def test_domain_inside_vpc_with_public_subnet(self):
+        opensearch_client = mock.MagicMock
+        opensearch_client.opensearch_domains = []
+        vpc_client = mock.MagicMock
+        vpc_client.vpc_subnets = {
+            "subnet-123456": mock.MagicMock(public=True),
+            "subnet-654321": mock.MagicMock(public=False),
+        }
+
+        aws_provider = set_mocked_aws_provider([AWS_REGION_US_WEST_2])
+
+        with mock.patch(
+            "prowler.providers.common.provider.Provider.get_global_provider",
+            return_value=aws_provider,
+        ), mock.patch(
+            "prowler.providers.aws.services.opensearch.opensearch_service_domains_not_publicly_accessible.opensearch_service_domains_not_publicly_accessible.opensearch_client",
+            new=opensearch_client,
+        ), mock.patch(
+            "prowler.providers.aws.services.opensearch.opensearch_service_domains_not_publicly_accessible.opensearch_service_domains_not_publicly_accessible.vpc_client",
+            new=vpc_client,
+        ):
+            from prowler.providers.aws.services.opensearch.opensearch_service import (
+                OpenSearchDomain,
+            )
+            from prowler.providers.aws.services.opensearch.opensearch_service_domains_not_publicly_accessible.opensearch_service_domains_not_publicly_accessible import (
+                opensearch_service_domains_not_publicly_accessible,
+            )
+
+            opensearch_client.opensearch_domains.append(
+                OpenSearchDomain(
+                    name=domain_name,
+                    region=AWS_REGION_US_WEST_2,
+                    arn=f"arn:aws:es:{AWS_REGION_US_WEST_2}:{AWS_ACCOUNT_NUMBER}:domain/{domain_name}",
+                    vpc_id="vpc-123456",
+                    subnet_ids=["subnet-123456", "subnet-654321"],
+                )
+            )
+
+            check = opensearch_service_domains_not_publicly_accessible()
+            result = check.execute()
+            assert len(result) == 1
+            assert result[0].status == "FAIL"
+            assert (
+                result[0].status_extended
+                == f"Opensearch domain {domain_name} is publicly accessible due to public subnets: subnet-123456."
+            )
+            assert result[0].resource_id == domain_name
+            assert (
+                result[0].resource_arn
+                == f"arn:aws:es:{AWS_REGION_US_WEST_2}:{AWS_ACCOUNT_NUMBER}:domain/{domain_name}"
+            )
+            assert result[0].region == AWS_REGION_US_WEST_2
+            assert result[0].resource_tags == []
diff --git a/tests/providers/aws/services/opensearch/opensearch_service_test.py b/tests/providers/aws/services/opensearch/opensearch_service_test.py
index 1df689eb18..dfce95b103 100644
--- a/tests/providers/aws/services/opensearch/opensearch_service_test.py
+++ b/tests/providers/aws/services/opensearch/opensearch_service_test.py
@@ -135,7 +135,7 @@ def test_list_domain_names(self):
         assert opensearch.opensearch_domains[0].name == test_domain_name
         assert opensearch.opensearch_domains[0].region == AWS_REGION_EU_WEST_1
 
-    # Test OpenSearchService describ domain config
+    # Test OpenSearchService describe domain config
     def test_describe_domain_config(self):
         aws_provider = set_mocked_aws_provider([])
         opensearch = OpenSearchService(aws_provider)
@@ -150,7 +150,7 @@ def test_describe_domain_config(self):
         assert opensearch.opensearch_domains[0].logging[2].name == "AUDIT_LOGS"
         assert opensearch.opensearch_domains[0].logging[2].enabled
 
-    # Test OpenSearchService describ domain
+    # Test OpenSearchService describe domain
     def test_describe_domain(self):
         aws_provider = set_mocked_aws_provider([])
         opensearch = OpenSearchService(aws_provider)
diff --git a/tests/providers/aws/services/rds/rds_instance_no_public_access/rds_instance_no_public_access_test.py b/tests/providers/aws/services/rds/rds_instance_no_public_access/rds_instance_no_public_access_test.py
index fe82c0a876..15905d2d97 100644
--- a/tests/providers/aws/services/rds/rds_instance_no_public_access/rds_instance_no_public_access_test.py
+++ b/tests/providers/aws/services/rds/rds_instance_no_public_access/rds_instance_no_public_access_test.py
@@ -274,3 +274,102 @@ def test_rds_instance_public_with_filtered_sg(self):
                     == f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:db:db-master-1"
                 )
                 assert result[0].resource_tags == []
+
+    @mock_aws
+    def test_rds_instance_public_with_public_subnet(self):
+        ec2_client = client("ec2", region_name=AWS_REGION_US_EAST_1)
+        vpc_id = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
+        subnet_id = ec2_client.create_subnet(
+            VpcId=vpc_id,
+            CidrBlock="10.0.0.0/16",
+            AvailabilityZone=f"{AWS_REGION_US_EAST_1}a",
+        )["Subnet"]["SubnetId"]
+        # add default route of subnet to an internet gateway to make it public
+        igw_id = ec2_client.create_internet_gateway()["InternetGateway"][
+            "InternetGatewayId"
+        ]
+        # attach internet gateway to subnet
+        ec2_client.attach_internet_gateway(InternetGatewayId=igw_id, VpcId=vpc_id)
+        # create route table
+        route_table_id = ec2_client.create_route_table(VpcId=vpc_id)["RouteTable"][
+            "RouteTableId"
+        ]
+        # associate route table with subnet
+        ec2_client.associate_route_table(
+            RouteTableId=route_table_id, SubnetId=subnet_id
+        )
+        # add route to route table
+        ec2_client.create_route(
+            RouteTableId=route_table_id,
+            DestinationCidrBlock="0.0.0.0/0",
+            GatewayId=igw_id,
+        )
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_id],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
+        conn = client("rds", region_name=AWS_REGION_US_EAST_1)
+        conn.create_db_subnet_group(
+            DBSubnetGroupName="subnet-group",
+            DBSubnetGroupDescription="subnet-group",
+            SubnetIds=[subnet_id],
+        )
+        conn.create_db_instance(
+            DBInstanceIdentifier="db-master-1",
+            AllocatedStorage=10,
+            Engine="postgres",
+            DBName="staging-postgres",
+            DBInstanceClass="db.m1.small",
+            PubliclyAccessible=False,
+            DBSubnetGroupName="subnet-group",
+        )
+        from prowler.providers.aws.services.ec2.ec2_service import EC2
+        from prowler.providers.aws.services.rds.rds_service import RDS
+
+        aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
+
+        with mock.patch(
+            "prowler.providers.common.provider.Provider.get_global_provider",
+            return_value=aws_provider,
+        ):
+            with mock.patch(
+                "prowler.providers.aws.services.rds.rds_instance_no_public_access.rds_instance_no_public_access.rds_client",
+                new=RDS(aws_provider),
+            ), mock.patch(
+                "prowler.providers.aws.services.rds.rds_instance_no_public_access.rds_instance_no_public_access.ec2_client",
+                new=EC2(aws_provider),
+            ):
+                # Test Check
+                from prowler.providers.aws.services.rds.rds_instance_no_public_access.rds_instance_no_public_access import (
+                    rds_instance_no_public_access,
+                )
+
+                check = rds_instance_no_public_access()
+                result = check.execute()
+
+                assert len(result) == 1
+                assert result[0].status == "FAIL"
+                assert (
+                    result[0].status_extended
+                    == f"RDS Instance db-master-1 is in a public subnet {subnet_id}."
+                )
+                assert result[0].resource_id == "db-master-1"
+                assert result[0].region == AWS_REGION_US_EAST_1
+                assert (
+                    result[0].resource_arn
+                    == f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:db:db-master-1"
+                )
+                assert result[0].resource_tags == []
diff --git a/tests/providers/aws/services/rds/rds_service_test.py b/tests/providers/aws/services/rds/rds_service_test.py
index 11043a61e6..fcfb5713c6 100644
--- a/tests/providers/aws/services/rds/rds_service_test.py
+++ b/tests/providers/aws/services/rds/rds_service_test.py
@@ -121,6 +121,7 @@ def test_describe_db_instances(self):
             {"Key": "test", "Value": "test"},
         ]
         assert "test" in db_instance.parameter_groups
+        assert db_instance.subnet_ids == []
         assert db_instance.copy_tags_to_snapshot
         assert db_instance.port == 5432
 
diff --git a/tests/providers/aws/services/redshift/redshift_cluster_public_access/redshift_cluster_public_access_test.py b/tests/providers/aws/services/redshift/redshift_cluster_public_access/redshift_cluster_public_access_test.py
index e7250f9a13..c482134069 100644
--- a/tests/providers/aws/services/redshift/redshift_cluster_public_access/redshift_cluster_public_access_test.py
+++ b/tests/providers/aws/services/redshift/redshift_cluster_public_access/redshift_cluster_public_access_test.py
@@ -2,7 +2,11 @@
 from uuid import uuid4
 
 from prowler.providers.aws.services.redshift.redshift_service import Cluster
-from tests.providers.aws.utils import AWS_ACCOUNT_NUMBER, AWS_REGION_EU_WEST_1
+from tests.providers.aws.utils import (
+    AWS_ACCOUNT_NUMBER,
+    AWS_REGION_EU_WEST_1,
+    set_mocked_aws_provider,
+)
 
 CLUSTER_ID = str(uuid4())
 CLUSTER_ARN = (
@@ -14,17 +18,31 @@ class Test_redshift_cluster_public_access:
     def test_no_clusters(self):
         redshift_client = mock.MagicMock
         redshift_client.clusters = []
+        vpc_client = mock.MagicMock
+        ec2_client = mock.MagicMock
+        aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
+
         with mock.patch(
-            "prowler.providers.aws.services.redshift.redshift_service.Redshift",
-            redshift_client,
+            "prowler.providers.common.provider.Provider.get_global_provider",
+            return_value=aws_provider,
         ):
-            from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
-                redshift_cluster_public_access,
-            )
+            with mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.redshift_client",
+                new=redshift_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.vpc_client",
+                new=vpc_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.ec2_client",
+                new=ec2_client,
+            ):
+                from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
+                    redshift_cluster_public_access,
+                )
 
-            check = redshift_cluster_public_access()
-            result = check.execute()
-            assert len(result) == 0
+                check = redshift_cluster_public_access()
+                result = check.execute()
+                assert len(result) == 0
 
     def test_cluster_is_public(self):
         redshift_client = mock.MagicMock
@@ -38,23 +56,37 @@ def test_cluster_is_public(self):
                 endpoint_address="192.192.192.192",
             )
         )
+        vpc_client = mock.MagicMock
+        ec2_client = mock.MagicMock
+        aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
+
         with mock.patch(
-            "prowler.providers.aws.services.redshift.redshift_service.Redshift",
-            redshift_client,
+            "prowler.providers.common.provider.Provider.get_global_provider",
+            return_value=aws_provider,
         ):
-            from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
-                redshift_cluster_public_access,
-            )
+            with mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.redshift_client",
+                new=redshift_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.vpc_client",
+                new=vpc_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.ec2_client",
+                new=ec2_client,
+            ):
+                from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
+                    redshift_cluster_public_access,
+                )
 
-            check = redshift_cluster_public_access()
-            result = check.execute()
-            assert result[0].status == "FAIL"
-            assert (
-                result[0].status_extended
-                == f"Redshift Cluster {CLUSTER_ID} is publicly accessible at endpoint 192.192.192.192."
-            )
-            assert result[0].resource_id == CLUSTER_ID
-            assert result[0].resource_arn == CLUSTER_ARN
+                check = redshift_cluster_public_access()
+                result = check.execute()
+                assert result[0].status == "FAIL"
+                assert (
+                    result[0].status_extended
+                    == f"Redshift Cluster {CLUSTER_ID} is publicly accessible at endpoint 192.192.192.192."
+                )
+                assert result[0].resource_id == CLUSTER_ID
+                assert result[0].resource_arn == CLUSTER_ARN
 
     def test_cluster_is_not_public1(self):
         redshift_client = mock.MagicMock
@@ -68,23 +100,37 @@ def test_cluster_is_not_public1(self):
                 endpoint_address="192.192.192.192",
             )
         )
+        vpc_client = mock.MagicMock
+        ec2_client = mock.MagicMock
+        aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
+
         with mock.patch(
-            "prowler.providers.aws.services.redshift.redshift_service.Redshift",
-            redshift_client,
+            "prowler.providers.common.provider.Provider.get_global_provider",
+            return_value=aws_provider,
         ):
-            from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
-                redshift_cluster_public_access,
-            )
+            with mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.redshift_client",
+                new=redshift_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.vpc_client",
+                new=vpc_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.ec2_client",
+                new=ec2_client,
+            ):
+                from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
+                    redshift_cluster_public_access,
+                )
 
-            check = redshift_cluster_public_access()
-            result = check.execute()
-            assert result[0].status == "PASS"
-            assert (
-                result[0].status_extended
-                == f"Redshift Cluster {CLUSTER_ID} is not publicly accessible."
-            )
-            assert result[0].resource_id == CLUSTER_ID
-            assert result[0].resource_arn == CLUSTER_ARN
+                check = redshift_cluster_public_access()
+                result = check.execute()
+                assert result[0].status == "PASS"
+                assert (
+                    result[0].status_extended
+                    == f"Redshift Cluster {CLUSTER_ID} is not publicly accessible."
+                )
+                assert result[0].resource_id == CLUSTER_ID
+                assert result[0].resource_arn == CLUSTER_ARN
 
     def test_cluster_is_not_public2(self):
         redshift_client = mock.MagicMock
@@ -97,20 +143,141 @@ def test_cluster_is_not_public2(self):
                 public_access=True,
             )
         )
+        vpc_client = mock.MagicMock
+        ec2_client = mock.MagicMock
+        aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
+
         with mock.patch(
-            "prowler.providers.aws.services.redshift.redshift_service.Redshift",
-            redshift_client,
+            "prowler.providers.common.provider.Provider.get_global_provider",
+            return_value=aws_provider,
         ):
-            from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
-                redshift_cluster_public_access,
+            with mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.redshift_client",
+                new=redshift_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.vpc_client",
+                new=vpc_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.ec2_client",
+                new=ec2_client,
+            ):
+                from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
+                    redshift_cluster_public_access,
+                )
+
+                check = redshift_cluster_public_access()
+                result = check.execute()
+                assert result[0].status == "PASS"
+                assert (
+                    result[0].status_extended
+                    == f"Redshift Cluster {CLUSTER_ID} is not publicly accessible."
+                )
+                assert result[0].resource_id == CLUSTER_ID
+                assert result[0].resource_arn == CLUSTER_ARN
+
+    def test_cluster_is_in_public_vpc(self):
+        redshift_client = mock.MagicMock
+        redshift_client.clusters = []
+        redshift_client.clusters.append(
+            Cluster(
+                id=CLUSTER_ID,
+                arn=CLUSTER_ARN,
+                region=AWS_REGION_EU_WEST_1,
+                public_access=False,
+                vpc_id="vpc-123456",
             )
+        )
+        vpc_client = mock.MagicMock
+        vpc_client.vpcs = {"vpc-123456": mock.MagicMock(public=True)}
+        ec2_client = mock.MagicMock
+        aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
+
+        with mock.patch(
+            "prowler.providers.common.provider.Provider.get_global_provider",
+            return_value=aws_provider,
+        ):
+            with mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.redshift_client",
+                new=redshift_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.vpc_client",
+                new=vpc_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.ec2_client",
+                new=ec2_client,
+            ):
+                from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
+                    redshift_cluster_public_access,
+                )
 
-            check = redshift_cluster_public_access()
-            result = check.execute()
-            assert result[0].status == "PASS"
-            assert (
-                result[0].status_extended
-                == f"Redshift Cluster {CLUSTER_ID} is not publicly accessible."
+                check = redshift_cluster_public_access()
+                result = check.execute()
+                assert result[0].status == "FAIL"
+                assert (
+                    result[0].status_extended
+                    == f"Redshift Cluster {CLUSTER_ID} is in a public VPC vpc-123456."
+                )
+                assert result[0].resource_id == CLUSTER_ID
+                assert result[0].resource_arn == CLUSTER_ARN
+
+    def test_cluster_with_public_vpc_sgs(self):
+        redshift_client = mock.MagicMock
+        redshift_client.audited_partition = "aws"
+        redshift_client.audited_account = AWS_ACCOUNT_NUMBER
+        redshift_client.clusters = []
+        redshift_client.clusters.append(
+            Cluster(
+                id=CLUSTER_ID,
+                arn=CLUSTER_ARN,
+                region=AWS_REGION_EU_WEST_1,
+                vpc_id="vpc-123456",
+                public_access=False,
+                vpc_security_groups=["sg-123456"],
             )
-            assert result[0].resource_id == CLUSTER_ID
-            assert result[0].resource_arn == CLUSTER_ARN
+        )
+        vpc_client = mock.MagicMock
+        vpc_client.vpcs = {"vpc-123456": mock.MagicMock(public=False)}
+        ec2_client = mock.MagicMock
+        ec2_client.security_groups = {
+            f"arn:aws:ec2:eu-west-1:{AWS_ACCOUNT_NUMBER}:security-group/sg-123456": mock.MagicMock(
+                id="sg-123456",
+                ingress_rules=[
+                    {
+                        "IpProtocol": "-1",
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0",
+                            },
+                        ],
+                    }
+                ],
+            )
+        }
+        aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
+        with mock.patch(
+            "prowler.providers.common.provider.Provider.get_global_provider",
+            return_value=aws_provider,
+        ):
+            with mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.redshift_client",
+                new=redshift_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.vpc_client",
+                new=vpc_client,
+            ), mock.patch(
+                "prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access.ec2_client",
+                new=ec2_client,
+            ):
+                from prowler.providers.aws.services.redshift.redshift_cluster_public_access.redshift_cluster_public_access import (
+                    redshift_cluster_public_access,
+                )
+
+                check = redshift_cluster_public_access()
+                result = check.execute()
+                assert result[0].status == "FAIL"
+                assert (
+                    result[0].status_extended
+                    == f"Redshift Cluster {CLUSTER_ID} is in VPC vpc-123456 with a public security group sg-123456."
+                )
+                assert result[0].resource_id == CLUSTER_ID
+                assert result[0].resource_arn == CLUSTER_ARN
diff --git a/tests/providers/aws/services/redshift/redshift_service_test.py b/tests/providers/aws/services/redshift/redshift_service_test.py
index 133a0a35e7..96b7bd87ea 100644
--- a/tests/providers/aws/services/redshift/redshift_service_test.py
+++ b/tests/providers/aws/services/redshift/redshift_service_test.py
@@ -101,6 +101,12 @@ def test_describe_clusters(self):
         assert redshift.clusters[0].id == cluster_id
         assert redshift.clusters[0].region == AWS_REGION_EU_WEST_1
         assert redshift.clusters[0].public_access
+        assert redshift.clusters[0].vpc_id == response["Cluster"].get("VpcId")
+        assert redshift.clusters[0].vpc_security_groups == [
+            sg["VpcSecurityGroupId"]
+            for sg in response["Cluster"]["VpcSecurityGroups"]
+            if sg["Status"] == "active"
+        ]
         assert (
             redshift.clusters[0].endpoint_address
             == response["Cluster"]["Endpoint"]["Address"]
diff --git a/tests/providers/aws/services/vpc/vpc_service_test.py b/tests/providers/aws/services/vpc/vpc_service_test.py
index d8fe736ed0..5a5c9b597d 100644
--- a/tests/providers/aws/services/vpc/vpc_service_test.py
+++ b/tests/providers/aws/services/vpc/vpc_service_test.py
@@ -415,6 +415,53 @@ def test_describe_vpc_subnets(self):
                 assert vpc.subnets[0].region == AWS_REGION_US_EAST_1
                 assert vpc.subnets[0].tags is None
 
+    @mock_aws
+    def test_vpc_subnet_with_open_nacl(self):
+        # Generate VPC Client
+        ec2_client = client("ec2", region_name=AWS_REGION_US_EAST_1)
+        # Create VPC
+        vpc_id = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
+        subnet_id = ec2_client.create_subnet(
+            VpcId=vpc_id,
+            CidrBlock="10.0.0.0/16",
+            AvailabilityZone=f"{AWS_REGION_US_EAST_1}a",
+        )["Subnet"]["SubnetId"]
+        nacl_id = ec2_client.create_network_acl(VpcId=vpc_id)["NetworkAcl"][
+            "NetworkAclId"
+        ]
+        ec2_client.create_network_acl_entry(
+            NetworkAclId=nacl_id,
+            RuleNumber=100,
+            Protocol="-1",
+            RuleAction="allow",
+            Egress=False,
+            CidrBlock="0.0.0.0/0",
+        )
+        ec2_client.create_network_acl_entry(
+            NetworkAclId=nacl_id,
+            RuleNumber=200,
+            Protocol="-1",
+            RuleAction="allow",
+            Egress=True,
+            CidrBlock="0.0.0.0/0",
+        )
+        aws_provider = set_mocked_aws_provider(
+            [AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1]
+        )
+        from prowler.providers.aws.services.vpc.vpc_service import VPC
+
+        vpc = VPC(aws_provider)
+        assert (
+            len(vpc.vpcs) == 3
+        )  # Number of AWS regions + created VPC, one default VPC per region
+        for vpc in vpc.vpcs.values():
+            if vpc.cidr_block == "10.0.0.0/16":
+                assert vpc.subnets[0].id == subnet_id
+                assert vpc.subnets[0].vpc_id == vpc_id
+                assert vpc.subnets[0].availability_zone == f"{AWS_REGION_US_EAST_1}a"
+                assert vpc.subnets[0].public
+                assert vpc.subnets[0].region == AWS_REGION_US_EAST_1
+
     # Test VPC Describe VPN Connections
     @mock.patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
     def test_describe_vpn_connections(self):
diff --git a/tests/providers/aws/services/vpc/vpc_subnet_separate_private_public/vpc_subnet_separate_private_public_test.py b/tests/providers/aws/services/vpc/vpc_subnet_separate_private_public/vpc_subnet_separate_private_public_test.py
index 2bad60f227..4c924831bf 100644
--- a/tests/providers/aws/services/vpc/vpc_subnet_separate_private_public/vpc_subnet_separate_private_public_test.py
+++ b/tests/providers/aws/services/vpc/vpc_subnet_separate_private_public/vpc_subnet_separate_private_public_test.py
@@ -39,6 +39,23 @@ def test_vpc_subnet_only_private(self):
             RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
             SubnetId=subnet_private["Subnet"]["SubnetId"],
         )
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_private["Subnet"]["SubnetId"]],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
 
         from prowler.providers.aws.services.vpc.vpc_service import VPC
 
@@ -193,6 +210,23 @@ def test_vpc_subnet_private_and_public(self):
             RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
             SubnetId=subnet_private["Subnet"]["SubnetId"],
         )
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_private["Subnet"]["SubnetId"]],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=False,
+                RuleNumber=100,
+            )
         # VPC Public
         subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.128.0/17")
         # Create IGW and attach to VPC
diff --git a/tests/providers/aws/services/workspaces/workspaces_vpc_2private_1public_subnets_nat/workspaces_vpc_2private_1public_subnets_nat_test.py b/tests/providers/aws/services/workspaces/workspaces_vpc_2private_1public_subnets_nat/workspaces_vpc_2private_1public_subnets_nat_test.py
index 590a32e289..f63d05edd4 100644
--- a/tests/providers/aws/services/workspaces/workspaces_vpc_2private_1public_subnets_nat/workspaces_vpc_2private_1public_subnets_nat_test.py
+++ b/tests/providers/aws/services/workspaces/workspaces_vpc_2private_1public_subnets_nat/workspaces_vpc_2private_1public_subnets_nat_test.py
@@ -365,6 +365,23 @@ def test_workspaces_vpc_two_private_subnet_one_public_and_nat(self):
             RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
             SubnetId=subnet_private["Subnet"]["SubnetId"],
         )
+        nacls = (
+            ec2_client.describe_network_acls(
+                Filters=[
+                    {
+                        "Name": "association.subnet-id",
+                        "Values": [subnet_private["Subnet"]["SubnetId"]],
+                    }
+                ]
+            )
+        )["NetworkAcls"]
+        # Remove public ingress rule from private subnet in default NACLs
+        for nacl in nacls:
+            ec2_client.delete_network_acl_entry(
+                NetworkAclId=nacl["NetworkAclId"],
+                Egress=True,
+                RuleNumber=100,
+            )
         # VPC Private 2
         subnet_private_2 = ec2_client.create_subnet(
             VpcId=vpc.id,


Code review comments:
diff_hunk: @@ -1,28 +1,27 @@
 {
   "Provider": "aws",
   "CheckID": "opensearch_service_domains_not_publicly_accessible",
-  "CheckTitle": "Check if Amazon Opensearch/Elasticsearch domains are set as Public or if it has open policy access",
+  "CheckTitle": "Check if Amazon Opensearch/Elasticsearch domains are publicly accessible",
   "CheckType": [
-    "Protect",
-    "Secure Access Management"
+    "Effects/Data Exposure"
   ],
   "ServiceName": "opensearch",
   "SubServiceName": "",
   "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
   "Severity": "critical",
   "ResourceType": "AwsOpenSearchServiceDomain",
-  "Description": "Check if Amazon Opensearch/Elasticsearch domains are set as Public or if it has open policy access",
+  "Description": "Check if Amazon Opensearch/Elasticsearch domains are publicly accessible via their access policies.",
   "Risk": "Publicly accessible services could expose sensitive data to bad actors.",
   "RelatedUrl": "",
   "Remediation": {
     "Code": {
-      "CLI": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Elasticsearch/elasticsearch-domain-exposed.html",
+      "CLI": "",
       "NativeIaC": "",
-      "Other": "https://docs.prowler.com/checks/aws/public-policies/public_3#fix---runtime",
+      "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Elasticsearch/elasticsearch-domain-exposed.html",
path: prowler/providers/aws/services/opensearch/opensearch_service_domains_not_publicly_accessible/opensearch_service_domains_not_publicly_accessible.metadata.json
text: @user1:
This link returns a 404. Why are you removing the one from our knowledge base?

@author:
Link was changed!

diff_hunk: @@ -20,7 +20,6 @@ def execute(self):
                 report.status_extended = f"DynamoDB table {table.name} has a resource-based policy but is not cross account."
                 if is_policy_public(
                     table.policy,
-                    source_account=dynamodb_client.audited_account,
path: prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py
text: @user1:
Why are you removing this?

@author:
Because now I always get the audited account inside the function.

diff_hunk: @@ -156,13 +160,20 @@ def is_policy_public(
     If the policy gives access to an AWS service principal is considered public if the policy is not pair with conditions since it can be invoked by AWS services in other accounts.
     Args:
         policy (dict): The AWS policy to check
-        source_account (str): The account to check if the access is restricted to it, default: ""
         is_cross_account_allowed (bool): If the policy can allow cross-account access, default: False
         not_allowed_actions (list): List of actions that are not allowed, default: []. If not_allowed_actions is empty, the function will not consider the actions in the policy.
     Returns:
         bool: True if the policy allows public access, False otherwise
     """
     is_public = False
+    source_account = ""
+    trusted_account_ids = []
+    # Get service client from the check to get the trusted account IDs and source account
+    for var_name, value in inspect.stack()[1].frame.f_globals.items():
+        if "_client" in var_name:
+            trusted_account_ids = value.audit_config.get("trusted_account_ids", [])
+            source_account = value.audited_account
+            break
path: prowler/providers/aws/services/iam/lib/policy.py
text: @user1:
Why are you doing this? I think is much more readable and testable to pass these values to the function instead of adding inspect to the function.

@author:
It is because the source account it is needed in all the cases when we are checking if a resource policy is public.

@user1:
I get that but for me it is not clear the need of inspecting the stack to get the items, it is not straightforward and is something costly in terms of computation. I'd prefer to pass the `account_id` because is more readable and easier to understand.

diff_hunk: @@ -18,6 +20,18 @@ def execute(self):
                 report.status_extended = (
                     f"ELBv2 ALB {lb.name} is internet facing in {lb.dns}."
                 )
+            elif lb.security_groups:
path: prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.py
text: @user1:
Which scenario are you covering here? As far as I know the only two valid values for the LB `scheme` are `'internet-facing'|'internal'` and an `internal` LB means that can only be accessed from the VPC so even having security groups allowing access from the internet the LB won't be reachable.

@author:
You are right! This has to be with an `AND` logic.