feat(wafv2): change web_acls from list to dict (#5308)

Co-authored-by: Sergio <sergio@prowler.com>
This commit is contained in:
Hugo Pereira Brito
2024-10-07 16:23:58 +02:00
committed by GitHub
parent a6b10a8611
commit 09d099891a
8 changed files with 91 additions and 83 deletions
@@ -16,7 +16,7 @@ class cognito_user_pool_waf_acl_attached(Check):
report.status_extended = (
f"Cognito User Pool {pool.name} is not associated with a WAF Web ACL."
)
for acl in wafv2_client.web_acls:
for acl in wafv2_client.web_acls.values():
if pool.arn in acl.user_pools:
report.status = "PASS"
report.status_extended = f"Cognito User Pool {pool.name} is associated with the WAF Web ACL {acl.name}."
@@ -18,7 +18,7 @@ class elbv2_waf_acl_attached(Check):
report.status_extended = (
f"ELBv2 ALB {lb.name} is not protected by WAF Web ACL."
)
for acl in wafv2_client.web_acls:
for acl in wafv2_client.web_acls.values():
if lb_arn in acl.albs:
report.status = "PASS"
report.status_extended = f"ELBv2 ALB {lb.name} is protected by WAFv2 Web ACL {acl.name}."
@@ -12,11 +12,13 @@ class WAFv2(AWSService):
def __init__(self, provider):
# Call AWSService's __init__
super().__init__(__class__.__name__, provider)
self.web_acls = []
self.web_acls = {}
self.__threading_call__(self._list_web_acls)
self.__threading_call__(self._list_resources_for_web_acl)
self.__threading_call__(self._get_logging_configuration)
self.__threading_call__(self._list_tags, self.web_acls)
self.__threading_call__(
self._list_resources_for_web_acl, self.web_acls.values()
)
self.__threading_call__(self._get_logging_configuration, self.web_acls.values())
self.__threading_call__(self._list_tags, self.web_acls.values())
def _list_web_acls(self, regional_client):
logger.info("WAFv2 - Listing Regional Web ACLs...")
@@ -25,66 +27,69 @@ class WAFv2(AWSService):
if not self.audit_resources or (
is_resource_filtered(wafv2["ARN"], self.audit_resources)
):
self.web_acls.append(
WebAclv2(
arn=wafv2["ARN"],
name=wafv2["Name"],
id=wafv2["Id"],
albs=[],
user_pools=[],
region=regional_client.region,
)
arn = wafv2["ARN"]
self.web_acls[arn] = WebAclv2(
arn=arn,
name=wafv2["Name"],
id=wafv2["Id"],
albs=[],
user_pools=[],
region=regional_client.region,
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def _get_logging_configuration(self, regional_client):
def _get_logging_configuration(self, acl):
logger.info("WAFv2 - Get Logging Configuration...")
for acl in self.web_acls:
if acl.region == regional_client.region:
try:
logging_enabled = regional_client.get_logging_configuration(
ResourceArn=acl.arn
)
acl.logging_enabled = bool(
logging_enabled["LoggingConfiguration"]["LogDestinationConfigs"]
)
try:
logging_enabled = self.regional_clients[
acl.region
].get_logging_configuration(ResourceArn=acl.arn)
acl.logging_enabled = bool(
logging_enabled["LoggingConfiguration"]["LogDestinationConfigs"]
)
except ClientError as error:
if error.response["Error"]["Code"] == "WAFNonexistentItemException":
logger.warning(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
else:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
except ClientError as error:
if error.response["Error"]["Code"] == "WAFNonexistentItemException":
logger.warning(
f"{acl.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
else:
logger.error(
f"{acl.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
except Exception as error:
logger.error(
f"{acl.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def _list_resources_for_web_acl(self, regional_client):
def _list_resources_for_web_acl(self, acl):
logger.info("WAFv2 - Describing resources...")
for acl in self.web_acls:
if acl.region == regional_client.region:
try:
for resource in regional_client.list_resources_for_web_acl(
WebACLArn=acl.arn, ResourceType="APPLICATION_LOAD_BALANCER"
)["ResourceArns"]:
acl.albs.append(resource)
try:
for resource in self.regional_clients[
acl.region
].list_resources_for_web_acl(
WebACLArn=acl.arn, ResourceType="APPLICATION_LOAD_BALANCER"
)[
"ResourceArns"
]:
acl.albs.append(resource)
for resource in regional_client.list_resources_for_web_acl(
WebACLArn=acl.arn, ResourceType="COGNITO_USER_POOL"
)["ResourceArns"]:
acl.user_pools.append(resource)
for resource in self.regional_clients[
acl.region
].list_resources_for_web_acl(
WebACLArn=acl.arn, ResourceType="COGNITO_USER_POOL"
)[
"ResourceArns"
]:
acl.user_pools.append(resource)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
except Exception as error:
logger.error(
f"{acl.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def _list_tags(self, resource: any):
logger.info("WAFv2 - Listing tags...")
@@ -5,7 +5,7 @@ from prowler.providers.aws.services.wafv2.wafv2_client import wafv2_client
class wafv2_webacl_logging_enabled(Check):
def execute(self):
findings = []
for web_acl in wafv2_client.web_acls:
for web_acl in wafv2_client.web_acls.values():
report = Check_Report_AWS(self.metadata())
report.region = web_acl.region
report.resource_id = web_acl.id
@@ -12,7 +12,7 @@ class Test_cognito_user_pool_waf_acl_attached:
cognito_client.user_pools = {}
cognito_client.audited_account = AWS_ACCOUNT_NUMBER
wafv2_client = mock.MagicMock
wafv2_client.web_acls = []
wafv2_client.web_acls = {}
with mock.patch(
"prowler.providers.aws.services.cognito.cognito_service.CognitoIDP",
new=cognito_client,
@@ -53,7 +53,7 @@ class Test_cognito_user_pool_waf_acl_attached:
}
cognito_client.audited_account = AWS_ACCOUNT_NUMBER
wafv2_client = mock.MagicMock
wafv2_client.web_acls = []
wafv2_client.web_acls = {}
with mock.patch(
"prowler.providers.aws.services.cognito.cognito_service.CognitoIDP",
@@ -105,8 +105,8 @@ class Test_cognito_user_pool_waf_acl_attached:
web_acl_arn = "arn:aws:wafv2:us-east-1:123456789012:regional/webacl/abcd1234"
web_acl_name = "abcd1234"
web_acl_id = "abcd1234"
wafv2_client.web_acls = [
WebAclv2(
wafv2_client.web_acls = {
web_acl_arn: WebAclv2(
arn=web_acl_arn,
name=web_acl_name,
id=web_acl_id,
@@ -114,7 +114,7 @@ class Test_cognito_user_pool_waf_acl_attached:
user_pools=[user_pool_arn],
region="us-east-1",
)
]
}
with mock.patch(
"prowler.providers.aws.services.cognito.cognito_service.CognitoIDP",
@@ -226,7 +226,7 @@ class Test_elbv2_waf_acl_attached:
elbv2_waf_acl_attached,
)
service_client.web_acls[0].albs.append(lb["LoadBalancerArn"])
service_client.web_acls[waf["ARN"]].albs.append(lb["LoadBalancerArn"])
check = elbv2_waf_acl_attached()
result = check.execute()
@@ -45,14 +45,15 @@ class Test_WAFv2_Service:
"MetricName": "idk",
},
)["Summary"]
waf_arn = waf["ARN"]
# WAFv2 client for this test class
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
wafv2 = WAFv2(aws_provider)
assert len(wafv2.web_acls) == 1
assert wafv2.web_acls[0].name == waf["Name"]
assert wafv2.web_acls[0].region == AWS_REGION_EU_WEST_1
assert wafv2.web_acls[0].arn == waf["ARN"]
assert wafv2.web_acls[0].id == waf["Id"]
assert wafv2.web_acls[waf_arn].name == waf["Name"]
assert wafv2.web_acls[waf_arn].region == AWS_REGION_EU_WEST_1
assert wafv2.web_acls[waf_arn].arn == waf["ARN"]
assert wafv2.web_acls[waf_arn].id == waf["Id"]
# Test WAFv2 Describe Web ACLs Resources
@mock_aws
@@ -70,6 +71,7 @@ class Test_WAFv2_Service:
"MetricName": "idk",
},
)["Summary"]
waf_arn = waf["ARN"]
security_group = ec2.create_security_group(
GroupName="a-security-group", Description="First One"
)
@@ -97,10 +99,10 @@ class Test_WAFv2_Service:
# WAFv2 client for this test class
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
wafv2 = WAFv2(aws_provider)
wafv2.web_acls[0].albs.append(lb["LoadBalancerArn"])
wafv2.web_acls[waf_arn].albs.append(lb["LoadBalancerArn"])
assert len(wafv2.web_acls) == 1
assert len(wafv2.web_acls[0].albs) == 1
assert lb["LoadBalancerArn"] in wafv2.web_acls[0].albs
assert len(wafv2.web_acls[waf_arn].albs) == 1
assert lb["LoadBalancerArn"] in wafv2.web_acls[waf_arn].albs
# Test WAFv2 describe Web user pools
@mock_aws
@@ -117,15 +119,16 @@ class Test_WAFv2_Service:
"MetricName": "idk",
},
)["Summary"]
waf_arn = waf["ARN"]
user_pool = cognito.create_user_pool(PoolName="my-user-pool")["UserPool"]
wafv2.associate_web_acl(WebACLArn=waf["ARN"], ResourceArn=user_pool["Arn"])
# WAFv2 client for this test class
aws = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
wafv2 = WAFv2(aws)
wafv2.web_acls[0].user_pools.append(user_pool["Arn"])
wafv2.web_acls[waf_arn].user_pools.append(user_pool["Arn"])
assert len(wafv2.web_acls) == 1
assert len(wafv2.web_acls[0].user_pools) == 1
assert user_pool["Arn"] in wafv2.web_acls[0].user_pools
assert len(wafv2.web_acls[waf_arn].user_pools) == 1
assert user_pool["Arn"] in wafv2.web_acls[waf_arn].user_pools
@mock_aws
def test_list_tags(self):
@@ -143,10 +146,11 @@ class Test_WAFv2_Service:
wafv2.tag_resource(
ResourceARN=waf["ARN"], Tags=[{"Key": "Name", "Value": "my-web-acl"}]
)
waf_arn = waf["ARN"]
# WAFv2 client for this test class
aws = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
wafv2 = WAFv2(aws)
assert len(wafv2.web_acls) == 1
assert len(wafv2.web_acls[0].tags) == 1
assert wafv2.web_acls[0].tags[0]["Key"] == "Name"
assert wafv2.web_acls[0].tags[0]["Value"] == "my-web-acl"
assert len(wafv2.web_acls[waf_arn].tags) == 1
assert wafv2.web_acls[waf_arn].tags[0]["Key"] == "Name"
assert wafv2.web_acls[waf_arn].tags[0]["Value"] == "my-web-acl"
@@ -12,7 +12,7 @@ waf_arn = f"arn:aws:wafv2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:regional/w
class Test_wafv2_webacl_logging_enabled:
def test_no_web_acls(self):
wafv2_client = mock.MagicMock
wafv2_client.web_acls = []
wafv2_client.web_acls = {}
with mock.patch(
"prowler.providers.aws.services.wafv2.wafv2_service.WAFv2",
new=wafv2_client,
@@ -30,10 +30,9 @@ class Test_wafv2_webacl_logging_enabled:
def test_wafv2_wb_acl_with_logging(self):
wafv2_client = mock.MagicMock
wafv2_client.web_acls = []
wafv2_client.enabled = True
wafv2_client.web_acls.append(
WebAclv2(
wafv2_client.web_acls = {
waf_arn: WebAclv2(
arn=waf_arn,
name=waf_name,
id=waf_id,
@@ -43,7 +42,7 @@ class Test_wafv2_webacl_logging_enabled:
logging_enabled=True,
tags=[{"Key": "Name", "Value": waf_name}],
)
)
}
with mock.patch(
"prowler.providers.aws.services.wafv2.wafv2_service.WAFv2",
new=wafv2_client,
@@ -70,10 +69,10 @@ class Test_wafv2_webacl_logging_enabled:
def test_wafv2_wb_acl_without_logging(self):
wafv2_client = mock.MagicMock
wafv2_client.web_acls = []
wafv2_client.web_acls = {}
wafv2_client.enabled = True
wafv2_client.web_acls.append(
WebAclv2(
wafv2_client.web_acls = {
waf_arn: WebAclv2(
arn=waf_arn,
name=waf_name,
id=waf_id,
@@ -83,7 +82,7 @@ class Test_wafv2_webacl_logging_enabled:
logging_enabled=False,
tags=[{"Key": "Name", "Value": waf_name}],
)
)
}
with mock.patch(
"prowler.providers.aws.services.wafv2.wafv2_service.WAFv2",
new=wafv2_client,