fix(aws): delegated administrator lookup and reporting (#12342)

Co-authored-by: Pedro Martín <pedromarting3@gmail.com>
This commit is contained in:
Prowler BotandPedro Martín authored and GitHub committed 2026-08-05 10:46:20 +02:00
1 parent 065ce48c0f
commit 5f94be2611
16 files changed
+837 -252

No files matched your search

@@ -1,34 +1,80 @@
from unittest import mock
from moto import mock_aws
from prowler.providers.aws.services.securityhub.securityhub_service import (
SecurityHubHub,
)
from tests.providers.aws.utils import AWS_REGION_EU_WEST_1
# Patching the fixer client imports securityhub_client, which instantiates
# SecurityHub against the global provider at module level. Stubbing the class
# first keeps that import from reaching AWS when this file runs on its own.
SERVICE_MODULE = "prowler.providers.aws.services.securityhub.securityhub_service"
FIXER_MODULE = "prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled_fixer"
class test_securityhub_enabled_fixer:
@mock_aws
def _mocked_securityhub_client(fixer_config: dict) -> tuple:
"""Build a Security Hub client mock with a single regional client."""
regional_client = mock.MagicMock()
securityhub_client = mock.MagicMock()
securityhub_client.fixer_config = fixer_config
securityhub_client.regional_clients = {AWS_REGION_EU_WEST_1: regional_client}
return securityhub_client, regional_client
class Test_securityhub_enabled_fixer:
def test_securityhub_enabled_fixer(self):
securityhub_client = mock.MagicMock
securityhub_client.securityhubs = [
SecurityHubHub(
arn="arn:aws:securityhub:us-east-1:0123456789012:hub/default",
id="default",
status="ACTIVE",
standards="cis-aws-foundations-benchmark/v/1.2.0",
integrations="",
region="eu-west-1",
)
]
with mock.patch(
"prowler.providers.aws.services.securityhub.securityhub_service.SecurityHub",
new=securityhub_client,
"""Security Hub is enabled with the default standards from the fixer config."""
securityhub_client, regional_client = _mocked_securityhub_client(
{"securityhub_enabled": {"EnableDefaultStandards": True}}
)
with (
mock.patch(f"{SERVICE_MODULE}.SecurityHub", new=mock.MagicMock()),
mock.patch(f"{FIXER_MODULE}.securityhub_client", new=securityhub_client),
):
# Test Check
# Test Fixer
from prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled_fixer import (
fixer,
)
assert fixer(AWS_REGION_EU_WEST_1)
regional_client.enable_security_hub.assert_called_once_with(
EnableDefaultStandards=True
)
def test_securityhub_enabled_fixer_default_standards_disabled(self):
"""EnableDefaultStandards must be taken from the fixer configuration."""
securityhub_client, regional_client = _mocked_securityhub_client(
{"securityhub_enabled": {"EnableDefaultStandards": False}}
)
with (
mock.patch(f"{SERVICE_MODULE}.SecurityHub", new=mock.MagicMock()),
mock.patch(f"{FIXER_MODULE}.securityhub_client", new=securityhub_client),
):
# Test Fixer
from prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled_fixer import (
fixer,
)
assert fixer(AWS_REGION_EU_WEST_1)
regional_client.enable_security_hub.assert_called_once_with(
EnableDefaultStandards=False
)
def test_securityhub_enabled_fixer_error(self):
"""A failing EnableSecurityHub call must return False instead of raising."""
securityhub_client, regional_client = _mocked_securityhub_client({})
regional_client.enable_security_hub.side_effect = Exception(
"AccessDeniedException"
)
with (
mock.patch(f"{SERVICE_MODULE}.SecurityHub", new=mock.MagicMock()),
mock.patch(f"{FIXER_MODULE}.securityhub_client", new=securityhub_client),
):
# Test Fixer
from prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled_fixer import (
fixer,
)
assert not fixer(AWS_REGION_EU_WEST_1)
@@ -3,36 +3,52 @@ from unittest import mock
from prowler.providers.aws.services.securityhub.securityhub_service import (
SecurityHubHub,
)
from tests.providers.aws.utils import AWS_REGION_EU_WEST_1
from tests.providers.aws.utils import AWS_ACCOUNT_NUMBER, AWS_REGION_EU_WEST_1
# Patching the check client imports securityhub_client, which instantiates
# SecurityHub against the global provider at module level. Stubbing the class
# first keeps that import from reaching AWS when this file runs on its own.
SERVICE_MODULE = "prowler.providers.aws.services.securityhub.securityhub_service"
CHECK_MODULE = (
"prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled"
)
HUB_ARN = f"arn:aws:securityhub:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:hub/default"
UNKNOWN_HUB_ARN = (
f"arn:aws:securityhub:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:hub/unknown"
)
def _mocked_securityhub_client(securityhubs: list, audit_config: dict = None):
"""Build a Security Hub client mock holding the given hubs."""
securityhub_client = mock.MagicMock()
securityhub_client.region = AWS_REGION_EU_WEST_1
securityhub_client.audited_partition = "aws"
securityhub_client.audited_account = AWS_ACCOUNT_NUMBER
securityhub_client.audit_config = audit_config if audit_config is not None else {}
securityhub_client.securityhubs = securityhubs
return securityhub_client
class Test_securityhub_enabled:
def test_securityhub_hub_inactive(self):
securityhub_client = mock.MagicMock
securityhub_client.region = AWS_REGION_EU_WEST_1
securityhub_client.get_unknown_arn = (
lambda x: f"arn:aws:securityhub:{x}:0123456789012:hub/unknown"
securityhub_client = _mocked_securityhub_client(
[
SecurityHubHub(
arn=UNKNOWN_HUB_ARN,
id="hub/unknown",
status="NOT_AVAILABLE",
standards="",
integrations="",
region=AWS_REGION_EU_WEST_1,
tags=[{"test_key": "test_value"}],
)
]
)
securityhub_client.securityhubs = [
SecurityHubHub(
arn=f"arn:aws:securityhub:{AWS_REGION_EU_WEST_1}:0123456789012:hub/unknown",
id="hub/unknown",
status="NOT_AVAILABLE",
standards="",
integrations="",
region=AWS_REGION_EU_WEST_1,
tags=[{"test_key": "test_value"}],
)
]
with (
mock.patch(
"prowler.providers.aws.services.securityhub.securityhub_service.SecurityHub",
new=securityhub_client,
),
mock.patch(
"prowler.providers.aws.services.securityhub.securityhub_service.SecurityHub.get_unknown_arn",
return_value="arn:aws:securityhub:eu-west-1:0123456789012:hub/unknown",
),
mock.patch(f"{SERVICE_MODULE}.SecurityHub", new=mock.MagicMock()),
mock.patch(f"{CHECK_MODULE}.securityhub_client", new=securityhub_client),
):
# Test Check
from prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled import (
@@ -42,32 +58,32 @@ class Test_securityhub_enabled:
check = securityhub_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].status_extended == "Security Hub is not enabled."
assert result[0].resource_id == "hub/unknown"
assert (
result[0].resource_arn
== "arn:aws:securityhub:eu-west-1:0123456789012:hub/unknown"
)
assert result[0].resource_arn == UNKNOWN_HUB_ARN
assert result[0].region == AWS_REGION_EU_WEST_1
assert result[0].resource_tags == [{"test_key": "test_value"}]
def test_securityhub_hub_active_with_standards(self):
securityhub_client = mock.MagicMock
securityhub_client.securityhubs = [
SecurityHubHub(
arn="arn:aws:securityhub:us-east-1:0123456789012:hub/default",
id="default",
status="ACTIVE",
standards="cis-aws-foundations-benchmark/v/1.2.0",
integrations="",
region=AWS_REGION_EU_WEST_1,
tags=[{"test_key": "test_value"}],
)
]
with mock.patch(
"prowler.providers.aws.services.securityhub.securityhub_service.SecurityHub",
new=securityhub_client,
securityhub_client = _mocked_securityhub_client(
[
SecurityHubHub(
arn=HUB_ARN,
id="default",
status="ACTIVE",
standards="cis-aws-foundations-benchmark/v/1.2.0",
integrations="",
region=AWS_REGION_EU_WEST_1,
tags=[{"test_key": "test_value"}],
)
]
)
with (
mock.patch(f"{SERVICE_MODULE}.SecurityHub", new=mock.MagicMock()),
mock.patch(f"{CHECK_MODULE}.securityhub_client", new=securityhub_client),
):
# Test Check
from prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled import (
@@ -77,35 +93,35 @@ class Test_securityhub_enabled:
check = securityhub_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "Security Hub is enabled with standards: cis-aws-foundations-benchmark/v/1.2.0."
)
assert result[0].resource_id == "default"
assert (
result[0].resource_arn
== "arn:aws:securityhub:us-east-1:0123456789012:hub/default"
)
assert result[0].resource_arn == HUB_ARN
assert result[0].region == AWS_REGION_EU_WEST_1
assert result[0].resource_tags == [{"test_key": "test_value"}]
def test_securityhub_hub_active_with_integrations(self):
securityhub_client = mock.MagicMock
securityhub_client.securityhubs = [
SecurityHubHub(
arn="arn:aws:securityhub:us-east-1:0123456789012:hub/default",
id="default",
status="ACTIVE",
standards="",
integrations="prowler",
region=AWS_REGION_EU_WEST_1,
tags=[{"test_key": "test_value"}],
)
]
with mock.patch(
"prowler.providers.aws.services.securityhub.securityhub_service.SecurityHub",
new=securityhub_client,
securityhub_client = _mocked_securityhub_client(
[
SecurityHubHub(
arn=HUB_ARN,
id="default",
status="ACTIVE",
standards="",
integrations="prowler",
region=AWS_REGION_EU_WEST_1,
tags=[{"test_key": "test_value"}],
)
]
)
with (
mock.patch(f"{SERVICE_MODULE}.SecurityHub", new=mock.MagicMock()),
mock.patch(f"{CHECK_MODULE}.securityhub_client", new=securityhub_client),
):
# Test Check
from prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled import (
@@ -115,38 +131,35 @@ class Test_securityhub_enabled:
check = securityhub_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "Security Hub is enabled without standards but with integrations: prowler."
)
assert result[0].resource_id == "default"
assert (
result[0].resource_arn
== "arn:aws:securityhub:us-east-1:0123456789012:hub/default"
)
assert result[0].resource_arn == HUB_ARN
assert result[0].region == AWS_REGION_EU_WEST_1
assert result[0].resource_tags == [{"test_key": "test_value"}]
def test_securityhub_hub_active_without_integrations_or_standards(self):
securityhub_client = mock.MagicMock
securityhub_client.region = AWS_REGION_EU_WEST_1
securityhub_client.audited_partition = "aws"
securityhub_client.audited_account = "0123456789012"
securityhub_client.securityhubs = [
SecurityHubHub(
arn="arn:aws:securityhub:us-east-1:0123456789012:hub/default",
id="default",
status="ACTIVE",
standards="",
integrations="",
region=AWS_REGION_EU_WEST_1,
tags=[{"test_key": "test_value"}],
)
]
with mock.patch(
"prowler.providers.aws.services.securityhub.securityhub_service.SecurityHub",
new=securityhub_client,
securityhub_client = _mocked_securityhub_client(
[
SecurityHubHub(
arn=HUB_ARN,
id="default",
status="ACTIVE",
standards="",
integrations="",
region=AWS_REGION_EU_WEST_1,
tags=[{"test_key": "test_value"}],
)
]
)
with (
mock.patch(f"{SERVICE_MODULE}.SecurityHub", new=mock.MagicMock()),
mock.patch(f"{CHECK_MODULE}.securityhub_client", new=securityhub_client),
):
# Test Check
from prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled import (
@@ -156,39 +169,37 @@ class Test_securityhub_enabled:
check = securityhub_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert not result[0].muted
assert (
result[0].status_extended
== "Security Hub is enabled but without any standard or integration."
)
assert result[0].resource_id == "default"
assert (
result[0].resource_arn
== "arn:aws:securityhub:us-east-1:0123456789012:hub/default"
)
assert result[0].resource_arn == HUB_ARN
assert result[0].region == AWS_REGION_EU_WEST_1
assert result[0].resource_tags == [{"test_key": "test_value"}]
def test_securityhub_hub_active_without_integrations_or_standards_muted(self):
securityhub_client = mock.MagicMock
securityhub_client.audit_config = {"mute_non_default_regions": True}
securityhub_client.region = AWS_REGION_EU_WEST_1
securityhub_client.audited_partition = "aws"
securityhub_client.audited_account = "0123456789012"
securityhub_client.securityhubs = [
SecurityHubHub(
arn="arn:aws:securityhub:us-east-1:0123456789012:hub/default",
id="default",
status="ACTIVE",
standards="",
integrations="",
region="eu-south-2",
tags=[],
)
]
with mock.patch(
"prowler.providers.aws.services.securityhub.securityhub_service.SecurityHub",
new=securityhub_client,
securityhub_client = _mocked_securityhub_client(
[
SecurityHubHub(
arn=HUB_ARN,
id="default",
status="ACTIVE",
standards="",
integrations="",
region="eu-south-2",
tags=[],
)
],
audit_config={"mute_non_default_regions": True},
)
with (
mock.patch(f"{SERVICE_MODULE}.SecurityHub", new=mock.MagicMock()),
mock.patch(f"{CHECK_MODULE}.securityhub_client", new=securityhub_client),
):
# Test Check
from prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled import (
@@ -198,6 +209,7 @@ class Test_securityhub_enabled:
check = securityhub_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].muted
assert (
@@ -205,9 +217,6 @@ class Test_securityhub_enabled:
== "Security Hub is enabled but without any standard or integration."
)
assert result[0].resource_id == "default"
assert (
result[0].resource_arn
== "arn:aws:securityhub:us-east-1:0123456789012:hub/default"
)
assert result[0].resource_arn == HUB_ARN
assert result[0].region == "eu-south-2"
assert result[0].resource_tags == []