feat(new check): add accessanalyzer_enabled check (#1864)

Co-authored-by: sergargar <sergargar@users.noreply.github.com>
This commit is contained in:
Sergio Garcia
2023-02-08 17:39:25 +01:00
committed by GitHub
parent 7d2ce7e6ab
commit 5b9db9795d
8 changed files with 224 additions and 12 deletions

View File

@@ -258,7 +258,7 @@
"Id": "1.20",
"Description": "Ensure that IAM Access analyzer is enabled for all regions",
"Checks": [
"accessanalyzer_enabled_without_findings"
"accessanalyzer_enabled"
],
"Attributes": [
{

View File

@@ -258,7 +258,7 @@
"Id": "1.20",
"Description": "Ensure that IAM Access analyzer is enabled for all regions",
"Checks": [
"accessanalyzer_enabled_without_findings"
"accessanalyzer_enabled"
],
"Attributes": [
{

View File

@@ -0,0 +1,36 @@
{
"Provider": "aws",
"CheckID": "accessanalyzer_enabled",
"CheckTitle": "Check if IAM Access Analyzer is enabled",
"CheckType": [
"IAM"
],
"ServiceName": "accessanalyzer",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:access-analyzer:region:account-id:analyzer/resource-id",
"Severity": "low",
"ResourceType": "Other",
"Description": "Check if IAM Access Analyzer is enabled",
"Risk": "AWS IAM Access Analyzer helps you identify the resources in your organization and accounts, such as Amazon S3 buckets or IAM roles, that are shared with an external entity. This lets you identify unintended access to your resources and data, which is a security risk. IAM Access Analyzer uses a form of mathematical analysis called automated reasoning, which applies logic and mathematical inference to determine all possible access paths allowed by a resource policy.",
"RelatedUrl": "https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html",
"Remediation": {
"Code": {
"CLI": "aws accessanalyzer create-analyzer --analyzer-name <NAME> --type <ACCOUNT|ORGANIZATION>",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Enable IAM Access Analyzer for all accounts, create analyzer and take action over it is recommendations (IAM Access Analyzer is available at no additional cost).",
"Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}

View File

@@ -0,0 +1,36 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.accessanalyzer.accessanalyzer_client import (
accessanalyzer_client,
)
class accessanalyzer_enabled(Check):
def execute(self):
findings = []
for analyzer in accessanalyzer_client.analyzers:
report = Check_Report_AWS(self.metadata())
report.region = analyzer.region
if analyzer.status == "ACTIVE":
report.status = "PASS"
report.status_extended = (
f"IAM Access Analyzer {analyzer.name} is enabled"
)
report.resource_id = analyzer.name
report.resource_arn = analyzer.arn
elif analyzer.status == "NOT_AVAILABLE":
report.status = "FAIL"
report.status_extended = (
f"IAM Access Analyzer in account {analyzer.name} is not enabled"
)
report.resource_id = analyzer.name
else:
report.status = "FAIL"
report.status_extended = (
f"IAM Access Analyzer {analyzer.name} is not active"
)
report.resource_id = analyzer.name
report.resource_arn = analyzer.arn
findings.append(report)
return findings

View File

@@ -31,7 +31,7 @@ class accessanalyzer_enabled_without_findings(Check):
elif analyzer.status == "NOT_AVAILABLE":
report.status = "FAIL"
report.status_extended = (
f"IAM Access Analyzer {analyzer.name} is not enabled"
f"IAM Access Analyzer in account {analyzer.name} is not enabled"
)
report.resource_id = analyzer.name
else:

View File

@@ -0,0 +1,140 @@
from unittest import mock
from prowler.providers.aws.services.accessanalyzer.accessanalyzer_service import (
Analyzer,
)
class Test_accessanalyzer_enabled:
def test_no_analyzers(self):
accessanalyzer_client = mock.MagicMock
accessanalyzer_client.analyzers = []
with mock.patch(
"prowler.providers.aws.services.accessanalyzer.accessanalyzer_service.AccessAnalyzer",
new=accessanalyzer_client,
):
# Test Check
from prowler.providers.aws.services.accessanalyzer.accessanalyzer_enabled.accessanalyzer_enabled import (
accessanalyzer_enabled,
)
check = accessanalyzer_enabled()
result = check.execute()
assert len(result) == 0
def test_one_analyzer_not_available(self):
# Include analyzers to check
accessanalyzer_client = mock.MagicMock
accessanalyzer_client.analyzers = [
Analyzer(
arn="",
name="012345678910",
status="NOT_AVAILABLE",
tags="",
type="",
region="eu-west-1",
)
]
with mock.patch(
"prowler.providers.aws.services.accessanalyzer.accessanalyzer_service.AccessAnalyzer",
accessanalyzer_client,
):
from prowler.providers.aws.services.accessanalyzer.accessanalyzer_enabled.accessanalyzer_enabled import (
accessanalyzer_enabled,
)
check = accessanalyzer_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "IAM Access Analyzer in account 012345678910 is not enabled"
)
assert result[0].resource_id == "012345678910"
def test_two_analyzers(self):
accessanalyzer_client = mock.MagicMock
accessanalyzer_client.analyzers = [
Analyzer(
arn="",
name="012345678910",
status="NOT_AVAILABLE",
tags="",
type="",
region="eu-west-1",
),
Analyzer(
arn="",
name="Test Analyzer",
status="ACTIVE",
tags="",
type="",
region="eu-west-2",
),
]
# Patch AccessAnalyzer Client
with mock.patch(
"prowler.providers.aws.services.accessanalyzer.accessanalyzer_service.AccessAnalyzer",
new=accessanalyzer_client,
):
# Test Check
from prowler.providers.aws.services.accessanalyzer.accessanalyzer_enabled.accessanalyzer_enabled import (
accessanalyzer_enabled,
)
check = accessanalyzer_enabled()
result = check.execute()
assert len(result) == 2
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "IAM Access Analyzer in account 012345678910 is not enabled"
)
assert result[0].resource_id == "012345678910"
assert result[0].region == "eu-west-1"
assert result[1].status == "PASS"
assert (
result[1].status_extended
== "IAM Access Analyzer Test Analyzer is enabled"
)
assert result[1].resource_id == "Test Analyzer"
assert result[1].region == "eu-west-2"
def test_one_active_analyzer(self):
accessanalyzer_client = mock.MagicMock
accessanalyzer_client.analyzers = [
Analyzer(
arn="",
name="Test Analyzer",
status="ACTIVE",
tags="",
type="",
region="eu-west-2",
)
]
with mock.patch(
"prowler.providers.aws.services.accessanalyzer.accessanalyzer_service.AccessAnalyzer",
new=accessanalyzer_client,
):
# Test Check
from prowler.providers.aws.services.accessanalyzer.accessanalyzer_enabled.accessanalyzer_enabled import (
accessanalyzer_enabled,
)
check = accessanalyzer_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "IAM Access Analyzer Test Analyzer is enabled"
)
assert result[0].resource_id == "Test Analyzer"
assert result[0].region == "eu-west-2"

View File

@@ -30,7 +30,7 @@ class Test_accessanalyzer_enabled_without_findings:
accessanalyzer_client.analyzers = [
Analyzer(
arn="",
name="Test Analyzer",
name="012345678910",
status="NOT_AVAILABLE",
tags="",
type="",
@@ -52,16 +52,16 @@ class Test_accessanalyzer_enabled_without_findings:
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "IAM Access Analyzer Test Analyzer is not enabled"
== "IAM Access Analyzer in account 012345678910 is not enabled"
)
assert result[0].resource_id == "Test Analyzer"
assert result[0].resource_id == "012345678910"
def test_two_analyzers(self):
accessanalyzer_client = mock.MagicMock
accessanalyzer_client.analyzers = [
Analyzer(
arn="",
name="Test Analyzer",
name="012345678910",
status="NOT_AVAILABLE",
tags="",
type="",
@@ -104,9 +104,9 @@ class Test_accessanalyzer_enabled_without_findings:
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "IAM Access Analyzer Test Analyzer is not enabled"
== "IAM Access Analyzer in account 012345678910 is not enabled"
)
assert result[0].resource_id == "Test Analyzer"
assert result[0].resource_id == "012345678910"
assert result[0].region == "eu-west-1"
assert result[1].status == "FAIL"
assert (
@@ -155,7 +155,7 @@ class Test_accessanalyzer_enabled_without_findings:
accessanalyzer_client.analyzers = [
Analyzer(
arn="",
name="Test Analyzer",
name="012345678910",
status="NOT_AVAILABLE",
tags="",
type="",
@@ -179,7 +179,7 @@ class Test_accessanalyzer_enabled_without_findings:
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "IAM Access Analyzer Test Analyzer is not enabled"
== "IAM Access Analyzer in account 012345678910 is not enabled"
)
assert result[0].resource_id == "Test Analyzer"
assert result[0].resource_id == "012345678910"
assert result[0].region == "eu-west-1"