feat(neptune): Additional Neptune checks (#4243)

This commit is contained in:
sansns-aws
2024-06-24 11:38:41 -04:00
committed by GitHub
parent 836b4ba2cc
commit 9253cd42dd
22 changed files with 1253 additions and 2 deletions
@@ -0,0 +1,30 @@
{
"Provider": "aws",
"CheckID": "neptune_cluster_backup_retention",
"CheckTitle": "Check for Neptune Clusters Backup Retention Period.",
"CheckType": [],
"ServiceName": "neptune",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-instance",
"Severity": "medium",
"ResourceType": "AwsRdsDbCluster",
"Description": "Check if Neptune Clusters have backup enabled.",
"Risk": "Ensure that your Amazon Neptune graph database clusters have set a minimum backup retention period of 7 days or greater in order to achieve your organization compliance requirements. The retention period represents the number of days to retain automated snapshots.",
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-5",
"Remediation": {
"Code": {
"CLI": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/sufficient-backup-retention-period.html#",
"NativeIaC": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/sufficient-backup-retention-period.html#",
"Other": "",
"Terraform": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/sufficient-backup-retention-period.html#"
},
"Recommendation": {
"Text": "Enable automated backup for production data. Define a retention period and periodically test backup restoration. A Disaster Recovery process should be in place to govern Data Protection approach.",
"Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-5"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,31 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.neptune.neptune_client import neptune_client
class neptune_cluster_backup_enabled(Check):
def execute(self):
findings = []
for cluster in neptune_client.clusters.values():
report = Check_Report_AWS(self.metadata())
report.region = cluster.region
report.resource_id = cluster.name
report.resource_arn = cluster.arn
report.resource_tags = cluster.tags
report.status = "FAIL"
report.status_extended = (
f"Neptune Cluster {cluster.name} does not have backup enabled."
)
if cluster.backup_retention_period > neptune_client.audit_config.get(
"minimum_backup_retention_period", 7
):
report.status = "PASS"
report.status_extended = f"Neptune Cluster {cluster.name} has backup enabled with retention period {cluster.backup_retention_period} days."
else:
if cluster.backup_retention_period > 0:
report.status = "FAIL"
report.check_metadata.Severity = "low"
report.status_extended = f"Neptune Cluster {cluster.name} has backup enabled with retention period {cluster.backup_retention_period} days. Recommended to increase the backup retention period to a minimum of 7 days."
findings.append(report)
return findings
@@ -0,0 +1,30 @@
{
"Provider": "aws",
"CheckID": "neptune_cluster_deletion_protection_enabled",
"CheckTitle": "Check if Neptune Clusters storage has deletion protection enabled.",
"CheckType": [],
"ServiceName": "neptune",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-cluster",
"Severity": "medium",
"ResourceType": "AwsRdsDbCluster",
"Description": "Check if Neptune Clusters storage has deletion protection enabled.",
"Risk": "Enabling cluster deletion protection offers an additional layer of protection against accidental database deletion or deletion by an unauthorized user. A Neptune DB cluster can't be deleted while deletion protection is enabled. You must first disable deletion protection before a delete request can succeed.",
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-4",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Enable deletion protection for production Neptune Clusters.",
"Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-4"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,24 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.neptune.neptune_client import neptune_client
class neptune_cluster_deletion_protection(Check):
def execute(self):
findings = []
for cluster in neptune_client.clusters.values():
report = Check_Report_AWS(self.metadata())
report.region = cluster.region
report.resource_id = cluster.name
report.resource_arn = cluster.arn
report.resource_tags = cluster.tags
report.status = "FAIL"
report.status_extended = f"Neptune Cluster {cluster.name} does not have deletion protection enabled."
if cluster.deletion_protection:
report.status = "PASS"
report.status_extended = (
f"Neptune Cluster {cluster.name} has deletion protection enabled."
)
findings.append(report)
return findings
@@ -0,0 +1,30 @@
{
"Provider": "aws",
"CheckID": "neptune_cluster_iam_authentication_enabled",
"CheckTitle": "Check if Neptune Clusters have IAM authentication enabled.",
"CheckType": [],
"ServiceName": "rds",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-cluster",
"Severity": "medium",
"ResourceType": "AwsRdsDbCluster",
"Description": "Check if Neptune Clusters have IAM authentication enabled.",
"Risk": "Ensure that IAM Database Authentication feature is enabled for your Amazon Neptune database clusters in order to make use of AWS Identity and Access Management (IAM) service to manage database access.",
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-7",
"Remediation": {
"Code": {
"CLI": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/iam-db-authentication.html#",
"NativeIaC": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/iam-db-authentication.html#",
"Other": "",
"Terraform": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/iam-db-authentication.html#"
},
"Recommendation": {
"Text": "Enable IAM authentication for Neptune Clusters.",
"Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-7"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,24 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.neptune.neptune_client import neptune_client
class neptune_cluster_iam_authentication_enabled(Check):
def execute(self):
findings = []
for cluster in neptune_client.clusters.values():
report = Check_Report_AWS(self.metadata())
report.region = cluster.region
report.resource_id = cluster.name
report.resource_arn = cluster.arn
report.resource_tags = cluster.tags
report.status = "FAIL"
report.status_extended = f"Neptune Cluster {cluster.name} does not have IAM authentication enabled."
if cluster.iam_auth:
report.status = "PASS"
report.status_extended = (
f"Neptune Cluster {cluster.name} has IAM authentication enabled."
)
findings.append(report)
return findings
@@ -0,0 +1,30 @@
{
"Provider": "aws",
"CheckID": "neptune_cluster_multi_az_enabled",
"CheckTitle": "Check if Neptune Clusters have multi-AZ enabled.",
"CheckType": [],
"ServiceName": "neptune",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-cluster",
"Severity": "medium",
"ResourceType": "AwsRdsDbCluster",
"Description": "Check if Neptune Clusters have multi-AZ enabled.",
"Risk": "Ensure that your Amazon Neptune graph database clusters are using Multi-AZ deployment configurations to enhance High Availability (HA) through automatic failover to read replicas in the event of a failure such as an Availability Zone (AZ) outage, an internal hardware or network outage, a software failure or in case of planned system maintenance.",
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-9",
"Remediation": {
"Code": {
"CLI": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/multi-az.html#",
"NativeIaC": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/multi-az.html#",
"Other": "",
"Terraform": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/multi-az.html#"
},
"Recommendation": {
"Text": "Enable multi-AZ deployment for production Neptune Clusters.",
"Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-9"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,26 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.neptune.neptune_client import neptune_client
class neptune_cluster_multi_az(Check):
def execute(self):
findings = []
for cluster in neptune_client.clusters.values():
report = Check_Report_AWS(self.metadata())
report.region = cluster.region
report.resource_id = cluster.name
report.resource_arn = cluster.arn
report.resource_tags = cluster.tags
report.status = "FAIL"
report.status_extended = (
f"Neptune Cluster {cluster.name} does not have Multi-AZ enabled."
)
if cluster.multi_az:
report.status = "PASS"
report.status_extended = (
f"Neptune Cluster {cluster.name} has Multi-AZ enabled."
)
findings.append(report)
return findings
@@ -0,0 +1,30 @@
{
"Provider": "aws",
"CheckID": "neptune_cluster_encrypted",
"CheckTitle": "Check if Neptune Clusters storage is encrypted at rest.",
"CheckType": [],
"ServiceName": "neptune",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:rds:region:account-id:db-cluster",
"Severity": "high",
"ResourceType": "AwsRdsDbClusters",
"Description": "Check if Neptune Clusters storage is encrypted at rest.",
"Risk": "Ensure that the data available on your Amazon Neptune database instances is encrypted in order to meet regulatory requirements and prevent unauthorized users from accessing sensitive information. Encryption provides an additional layer of protection by securing your Neptune databases from unauthorized access to the underlying storage. Neptune is a fast, scalable, highly secure and fully-managed graph database service that makes it easy to build and run applications that work with deeply connected datasets.",
"RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-1",
"Remediation": {
"Code": {
"CLI": "https://docs.prowler.com/checks/aws/general-policies/general_18/",
"NativeIaC": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Neptune/encryption-enabled.html",
"Other": "",
"Terraform": "https://docs.prowler.com/checks/aws/general-policies/general_18/"
},
"Recommendation": {
"Text": "Enable Encryption. Use a CMK where possible. It will provide additional management and privacy benefits.",
"Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/neptune-controls.html#neptune-1"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,26 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.neptune.neptune_client import neptune_client
class neptune_cluster_storage_encrypted(Check):
def execute(self):
findings = []
for cluster in neptune_client.clusters.values():
report = Check_Report_AWS(self.metadata())
report.region = cluster.region
report.resource_id = cluster.name
report.resource_arn = cluster.arn
report.resource_tags = cluster.tags
report.status = "FAIL"
report.status_extended = (
f"Neptune Cluster {cluster.name} is not encrypted at rest."
)
if cluster.encrypted:
report.status = "PASS"
report.status_extended = (
f"Neptune Cluster {cluster.name} is encrypted at rest."
)
findings.append(report)
return findings
@@ -39,6 +39,12 @@ class Neptune(AWSService):
arn=cluster_arn,
name=cluster["DBClusterIdentifier"],
id=cluster["DbClusterResourceId"],
backup_retention_period=cluster.get("BackupRetentionPeriod", 0),
encrypted=cluster.get("StorageEncrypted", False),
kms_key=cluster.get("KmsKeyId", ""),
multi_az=cluster["MultiAZ"],
iam_auth=cluster.get("IAMDatabaseAuthenticationEnabled", False),
deletion_protection=cluster.get("DeletionProtection", False),
db_subnet_group_id=cluster["DBSubnetGroup"],
region=regional_client.region,
)
@@ -96,6 +102,12 @@ class Cluster(BaseModel):
arn: str
name: str
id: str
backup_retention_period: int
encrypted: bool
kms_key: str
multi_az: bool
iam_auth: bool
deletion_protection: bool
region: str
db_subnet_group_id: str
subnets: Optional[list]
@@ -0,0 +1,282 @@
from unittest import mock
import botocore
from boto3 import client
from moto import mock_aws
from tests.providers.aws.utils import (
AWS_ACCOUNT_NUMBER,
AWS_REGION_US_EAST_1,
set_mocked_aws_provider,
)
minimum_backup_retention_period = 2
make_api_call = botocore.client.BaseClient._make_api_call
def mock_make_api_call(self, operation_name, kwarg):
if operation_name == "DescribeDBEngineVersions":
return {
"DBEngineVersions": [
{
"Engine": "mysql",
"EngineVersion": "8.0.32",
"DBEngineDescription": "description",
"DBEngineVersionDescription": "description",
},
]
}
return make_api_call(self, operation_name, kwarg)
@mock.patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
class Test_neptune_cluster_backup_enabled:
@mock_aws
def test_neptune_no_instances(self):
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled import (
neptune_cluster_backup_enabled,
)
check = neptune_cluster_backup_enabled()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_neptune_cluster_without_backup(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=False,
BackupRetentionPeriod=0,
StorageEncrypted=True,
Tags=[],
)
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled import (
neptune_cluster_backup_enabled,
)
check = neptune_cluster_backup_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 does not have backup enabled."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_neptune_cluster_with_backup_less_than_recommended(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=True,
BackupRetentionPeriod=4,
StorageEncrypted=True,
Tags=[],
)
db_cluster = f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:cluster:db-cluster-1"
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled.neptune_client",
new=Neptune(aws_provider),
) as service_client:
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled import (
neptune_cluster_backup_enabled,
)
service_client.clusters[db_cluster].iam_auth = True
check = neptune_cluster_backup_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 has backup enabled with retention period 4 days. Recommended to increase the backup retention period to a minimum of 7 days."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_neptune_cluster_with_backup(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=True,
BackupRetentionPeriod=9,
StorageEncrypted=True,
Tags=[],
)
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled import (
neptune_cluster_backup_enabled,
)
check = neptune_cluster_backup_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 has backup enabled with retention period 9 days."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_neptune_cluster_with_backup_modified_retention(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=True,
BackupRetentionPeriod=2,
StorageEncrypted=True,
Tags=[],
)
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled.neptune_client",
new=Neptune(aws_provider),
) as service_client:
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_backup_enabled.neptune_cluster_backup_enabled import (
neptune_cluster_backup_enabled,
)
service_client.audit_config = {"minimum_backup_retention_period": 1}
check = neptune_cluster_backup_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 has backup enabled with retention period 2 days."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@@ -0,0 +1,168 @@
from unittest import mock
import botocore
from boto3 import client
from moto import mock_aws
from tests.providers.aws.utils import (
AWS_ACCOUNT_NUMBER,
AWS_REGION_US_EAST_1,
set_mocked_aws_provider,
)
make_api_call = botocore.client.BaseClient._make_api_call
def mock_make_api_call(self, operation_name, kwarg):
if operation_name == "DescribeDBEngineVersions":
return {
"DBEngineVersions": [
{
"Engine": "mysql",
"EngineVersion": "8.0.32",
"DBEngineDescription": "description",
"DBEngineVersionDescription": "description",
},
]
}
return make_api_call(self, operation_name, kwarg)
@mock.patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
class Test_neptune_cluster_deletion_protection:
@mock_aws
def test_neptune_no_instances(self):
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_deletion_protection.neptune_cluster_deletion_protection.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_deletion_protection.neptune_cluster_deletion_protection import (
neptune_cluster_deletion_protection,
)
check = neptune_cluster_deletion_protection()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_neptune_cluster_without_deletion_protection(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=False,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=False,
BackupRetentionPeriod=0,
StorageEncrypted=False,
Tags=[],
)
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_deletion_protection.neptune_cluster_deletion_protection.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_deletion_protection.neptune_cluster_deletion_protection import (
neptune_cluster_deletion_protection,
)
check = neptune_cluster_deletion_protection()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 does not have deletion protection enabled."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_neptune_cluster_with_deletion_protection(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=True,
BackupRetentionPeriod=0,
StorageEncrypted=True,
Tags=[],
)
db_cluster = f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:cluster:db-cluster-1"
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_deletion_protection.neptune_cluster_deletion_protection.neptune_client",
new=Neptune(aws_provider),
) as service_client:
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_deletion_protection.neptune_cluster_deletion_protection import (
neptune_cluster_deletion_protection,
)
service_client.clusters[db_cluster].deletion_protection = True
check = neptune_cluster_deletion_protection()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 has deletion protection enabled."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@@ -0,0 +1,168 @@
from unittest import mock
import botocore
from boto3 import client
from moto import mock_aws
from tests.providers.aws.utils import (
AWS_ACCOUNT_NUMBER,
AWS_REGION_US_EAST_1,
set_mocked_aws_provider,
)
make_api_call = botocore.client.BaseClient._make_api_call
def mock_make_api_call(self, operation_name, kwarg):
if operation_name == "DescribeDBEngineVersions":
return {
"DBEngineVersions": [
{
"Engine": "mysql",
"EngineVersion": "8.0.32",
"DBEngineDescription": "description",
"DBEngineVersionDescription": "description",
},
]
}
return make_api_call(self, operation_name, kwarg)
@mock.patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
class Test_neptune_cluster_iam_authentication_enabled:
@mock_aws
def test_neptune_no_instances(self):
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_iam_authentication_enabled.neptune_cluster_iam_authentication_enabled.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_iam_authentication_enabled.neptune_cluster_iam_authentication_enabled import (
neptune_cluster_iam_authentication_enabled,
)
check = neptune_cluster_iam_authentication_enabled()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_neptune_cluster_without_iam_auth(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=False,
BackupRetentionPeriod=0,
StorageEncrypted=True,
Tags=[],
)
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_iam_authentication_enabled.neptune_cluster_iam_authentication_enabled.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_iam_authentication_enabled.neptune_cluster_iam_authentication_enabled import (
neptune_cluster_iam_authentication_enabled,
)
check = neptune_cluster_iam_authentication_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 does not have IAM authentication enabled."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_neptune_cluster_with_iam_auth(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=True,
BackupRetentionPeriod=0,
StorageEncrypted=True,
Tags=[],
)
db_cluster = f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:cluster:db-cluster-1"
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_iam_authentication_enabled.neptune_cluster_iam_authentication_enabled.neptune_client",
new=Neptune(aws_provider),
) as service_client:
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_iam_authentication_enabled.neptune_cluster_iam_authentication_enabled import (
neptune_cluster_iam_authentication_enabled,
)
service_client.clusters[db_cluster].iam_auth = True
check = neptune_cluster_iam_authentication_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 has IAM authentication enabled."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@@ -0,0 +1,168 @@
from unittest import mock
import botocore
from boto3 import client
from moto import mock_aws
from tests.providers.aws.utils import (
AWS_ACCOUNT_NUMBER,
AWS_REGION_US_EAST_1,
set_mocked_aws_provider,
)
make_api_call = botocore.client.BaseClient._make_api_call
def mock_make_api_call(self, operation_name, kwarg):
if operation_name == "DescribeDBEngineVersions":
return {
"DBEngineVersions": [
{
"Engine": "mysql",
"EngineVersion": "8.0.32",
"DBEngineDescription": "description",
"DBEngineVersionDescription": "description",
},
]
}
return make_api_call(self, operation_name, kwarg)
@mock.patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
class Test_neptune_cluster_multi_az:
@mock_aws
def test_neptune_no_instances(self):
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_multi_az.neptune_cluster_multi_az.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_multi_az.neptune_cluster_multi_az import (
neptune_cluster_multi_az,
)
check = neptune_cluster_multi_az()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_neptune_cluster_without_multi_az(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=False,
BackupRetentionPeriod=0,
StorageEncrypted=True,
Tags=[],
)
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_multi_az.neptune_cluster_multi_az.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_multi_az.neptune_cluster_multi_az import (
neptune_cluster_multi_az,
)
check = neptune_cluster_multi_az()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 does not have Multi-AZ enabled."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_neptune_cluster_with_multi_az(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=True,
BackupRetentionPeriod=0,
StorageEncrypted=True,
Tags=[],
)
db_cluster = f"arn:aws:rds:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:cluster:db-cluster-1"
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_multi_az.neptune_cluster_multi_az.neptune_client",
new=Neptune(aws_provider),
) as service_client:
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_multi_az.neptune_cluster_multi_az import (
neptune_cluster_multi_az,
)
service_client.clusters[db_cluster].multi_az = True
check = neptune_cluster_multi_az()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 has Multi-AZ enabled."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@@ -0,0 +1,166 @@
from unittest import mock
import botocore
from boto3 import client
from moto import mock_aws
from tests.providers.aws.utils import (
AWS_ACCOUNT_NUMBER,
AWS_REGION_US_EAST_1,
set_mocked_aws_provider,
)
make_api_call = botocore.client.BaseClient._make_api_call
def mock_make_api_call(self, operation_name, kwarg):
if operation_name == "DescribeDBEngineVersions":
return {
"DBEngineVersions": [
{
"Engine": "mysql",
"EngineVersion": "8.0.32",
"DBEngineDescription": "description",
"DBEngineVersionDescription": "description",
},
]
}
return make_api_call(self, operation_name, kwarg)
@mock.patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
class Test_neptune_cluster_storage_encrypted:
@mock_aws
def test_neptune_no_instances(self):
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_storage_encrypted.neptune_cluster_storage_encrypted.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_storage_encrypted.neptune_cluster_storage_encrypted import (
neptune_cluster_storage_encrypted,
)
check = neptune_cluster_storage_encrypted()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_neptune_cluster_without_storage_encrypted(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=False,
BackupRetentionPeriod=0,
StorageEncrypted=False,
Tags=[],
)
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_storage_encrypted.neptune_cluster_storage_encrypted.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_storage_encrypted.neptune_cluster_storage_encrypted import (
neptune_cluster_storage_encrypted,
)
check = neptune_cluster_storage_encrypted()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 is not encrypted at rest."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@mock_aws
def test_neptune_cluster_with_storage_encrypted(self):
conn = client("neptune", region_name=AWS_REGION_US_EAST_1)
conn.create_db_parameter_group(
DBParameterGroupName="test",
DBParameterGroupFamily="default.neptune",
Description="test parameter group",
)
conn.create_db_cluster(
DBClusterIdentifier="db-cluster-1",
Engine="neptune",
DatabaseName="test-1",
DeletionProtection=True,
DBClusterParameterGroupName="test",
MasterUsername="test",
MasterUserPassword="password",
EnableIAMDatabaseAuthentication=True,
BackupRetentionPeriod=0,
StorageEncrypted=True,
Tags=[],
)
from prowler.providers.aws.services.neptune.neptune_service import Neptune
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.neptune.neptune_cluster_storage_encrypted.neptune_cluster_storage_encrypted.neptune_client",
new=Neptune(aws_provider),
):
# Test Check
from prowler.providers.aws.services.neptune.neptune_cluster_storage_encrypted.neptune_cluster_storage_encrypted import (
neptune_cluster_storage_encrypted,
)
check = neptune_cluster_storage_encrypted()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "Neptune Cluster db-cluster-1 is encrypted at rest."
)
assert result[0].resource_id == "db-cluster-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}:cluster:db-cluster-1"
)
assert result[0].resource_tags == []
@@ -127,8 +127,8 @@ class Test_Neptune_Service:
DBClusterIdentifier=NEPTUNE_CLUSTER_NAME,
Port=123,
Tags=NEPTUNE_CLUSTER_TAGS,
StorageEncrypted=False,
DeletionProtection=True | False,
EnableIAMDatabaseAuthentication=False,
DeletionProtection=False,
)["DBCluster"]
cluster_arn = cluster["DBClusterArn"]
@@ -143,6 +143,12 @@ class Test_Neptune_Service:
arn=cluster_arn,
name=NEPTUNE_CLUSTER_NAME,
id=cluster_id,
backup_retention_period=1,
encrypted=True,
kms_key="default_kms_key_id",
multi_az=False,
iam_auth=False,
deletion_protection=False,
region=AWS_REGION_US_EAST_1,
db_subnet_group_id=SUBNET_GROUP_NAME,
subnets=[SUBNET_1, SUBNET_2],