From 35cc10e30ce60de4f31ef428fdb0e1effd29f18d Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Tue, 16 Apr 2024 14:59:38 +0100 Subject: [PATCH 01/16] Fix cloudtrail mapping --- frameworks/CIS/map.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/CIS/map.json b/frameworks/CIS/map.json index 2ed0355..d2d766e 100644 --- a/frameworks/CIS/map.json +++ b/frameworks/CIS/map.json @@ -9,7 +9,7 @@ }, "mapping": { "CloudTrail.": { - "1": ["cloudtrail.HasOneMultiRegionTrail"], + "1": ["cloudtrail.NeedToEnableCloudTrail, cloudtrail.HasOneMultiRegionTrail"], "2": ["cloudtrail.RequiresKmsKey"], "4": ["cloudtrail.LogFileValidationEnabled"], "5": ["cloudtrail.CloudWatchLogsLogGroupArn"], From 85f55b49b0bb4f85d3786fb04934060c81d066d9 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Wed, 17 Apr 2024 13:31:48 +0100 Subject: [PATCH 02/16] Add checks --- .../opensearch/drivers/OpensearchCommon.py | 14 ++++++++++ services/opensearch/opensearch.reporter.json | 26 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/services/opensearch/drivers/OpensearchCommon.py b/services/opensearch/drivers/OpensearchCommon.py index 22eb0fb..40bc4a6 100644 --- a/services/opensearch/drivers/OpensearchCommon.py +++ b/services/opensearch/drivers/OpensearchCommon.py @@ -154,6 +154,20 @@ def _checkSearchSlowLogs(self): if 'SEARCH_SLOW_LOGS' in self.attribute['DomainStatus']['LogPublishingOptions']: self.results["SearchSlowLogs"] = [1, "Enabled"] + def _checkApplicationLogs(self): + self.results["ApplicationLogs"] = [-1, "Disabled"] + if 'DomainStatus' in self.attribute: + if 'LogPublishingOptions' in self.attribute['DomainStatus']: + if 'ES_APPLICATION_LOGS' in self.attribute['DomainStatus']['LogPublishingOptions']: + self.results["SearchSlowLogs"] = [1, "Enabled"] + + def _checkAuditLogs(self): + self.results["AuditLogs"] = [-1, "Disabled"] + if 'DomainStatus' in self.attribute: + if 'LogPublishingOptions' in self.attribute['DomainStatus']: + if 'SEARCH_SLOW_LOGS' in self.attribute['DomainStatus']['LogPublishingOptions']: + self.results["AUDIT_LOGS"] = [1, "Enabled"] + def _checkAutoTune(self): self.results["AutoTune"] = [-1, "Disabled"] if 'DomainStatus' in self.attribute: diff --git a/services/opensearch/opensearch.reporter.json b/services/opensearch/opensearch.reporter.json index edf1b30..c26b343 100644 --- a/services/opensearch/opensearch.reporter.json +++ b/services/opensearch/opensearch.reporter.json @@ -194,6 +194,32 @@ "[Enable log publishing]" ] }, + "ApplicationLogs": { + "category": "P", + "^description": "OpenSearch Service exposes OpenSearch error logs, search slow logs, indexing slow logs, and audit logs in Amazon CloudWatch Logs. Search slow logs, indexing slow logs, and error logs are useful for troubleshooting performance and stability issues. Audit logs, which are only available if you enable fine-grained access control to track user activity. For more information, see Logs in the OpenSearch documentation. Search slow logs and indexing slow logs are an important tool for understanding and troubleshooting the performance of your search and indexing operations. Enable search and index slow log delivery for all production domains. You must also configure logging thresholds—otherwise, CloudWatch won't capture the logs.", + "downtime": 0, + "slowness": 1, + "additionalCost": 1, + "criticality": "M", + "needFullTest": 0, + "shortDesc": " Enable error log delivery for all production domains.", + "ref": [ + "[Enable log publishing]" + ] + }, + "AuditLogs": { + "category": "P", + "^description": "OpenSearch Service exposes OpenSearch error logs, search slow logs, indexing slow logs, and audit logs in Amazon CloudWatch Logs. Search slow logs, indexing slow logs, and error logs are useful for troubleshooting performance and stability issues. Audit logs, which are only available if you enable fine-grained access control to track user activity. For more information, see Logs in the OpenSearch documentation. Search slow logs and indexing slow logs are an important tool for understanding and troubleshooting the performance of your search and indexing operations. Enable search and index slow log delivery for all production domains. You must also configure logging thresholds—otherwise, CloudWatch won't capture the logs.", + "downtime": 0, + "slowness": 1, + "additionalCost": 1, + "criticality": "M", + "needFullTest": 0, + "shortDesc": " Enable audit log delivery for all production domains.", + "ref": [ + "[Enable log publishing]" + ] + }, "AutoTune": { "category": "P", "^description": "Auto-Tune uses performance and usage metrics from your OpenSearch cluster to suggest changes to queue sizes, cache sizes, and Java virtual machine (JVM) settings on your nodes. These optional changes improve cluster speed and stability. You can revert to the default OpenSearch Service settings at any time. Auto-Tune is enabled by default on new domains unless you explicitly disable it.", From de3e19d60389b77bd393fbcca1a086619aff3bd5 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Wed, 17 Apr 2024 13:55:46 +0100 Subject: [PATCH 03/16] Add checks --- .../opensearch/drivers/OpensearchCommon.py | 19 ++++++++++++++++++- services/opensearch/opensearch.reporter.json | 13 +++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/services/opensearch/drivers/OpensearchCommon.py b/services/opensearch/drivers/OpensearchCommon.py index 40bc4a6..9453479 100644 --- a/services/opensearch/drivers/OpensearchCommon.py +++ b/services/opensearch/drivers/OpensearchCommon.py @@ -74,7 +74,24 @@ def _checkMasterNodes(self): self.results["DedicatedMasterNodes"] = [-1, "Wrong number of dedicated master nodes"] return self.results["DedicatedMasterNodes"] = [1, "Sufficient dedicated master nodes"] - + + def _checkDataNodes(self): + total_nodes = self.cluster_config['InstanceCount'] + master_enabled = self.cluster_config["DedicatedMasterEnabled"] + master_nodes = 0 + if master_enabled: + master_nodes = self.cluster_config['DedicatedMasterCount'] + warm_enabled = self.cluster_config["WarmEnabled"] + warm_nodes = 0 + if warm_enabled: + warm_nodes = self.cluster_config['WarmCount'] + data_nodes = total_nodes - master_nodes - warm_nodes + + if data_nodes < 3: + self.results["DataNodes"] = [-1, "Insufficient data nodes"] + return + self.results["DataNodes"] = [1, "Sufficient data nodes"] + def _checkAvailabilityZones(self): enabled = self.cluster_config["ZoneAwarenessEnabled"] self.results["AvailabilityZones"] = [-1, "Multi-AZ not enabled"] diff --git a/services/opensearch/opensearch.reporter.json b/services/opensearch/opensearch.reporter.json index c26b343..7e4d28d 100644 --- a/services/opensearch/opensearch.reporter.json +++ b/services/opensearch/opensearch.reporter.json @@ -38,6 +38,19 @@ "Dedicated master nodes in Amazon OpenSearch Service]" ] }, + "DataNodes": { + "category": "R", + "^description": "An OpenSearch domain requires at least three data nodes for high availability and fault-tolerance. Deploying an OpenSearch domain with at least three data nodes ensures cluster operations if a node fails.", + "downtime": 0, + "slowness": 1, + "additionalCost": 1, + "criticality": "H", + "needFullTest": 0, + "shortDesc": "We recommend that you add three data nodes to each production OpenSearch Service domain.", + "ref": [ + "Data nodes in Amazon OpenSearch Service]" + ] + }, "AvailabilityZones": { "category": "R", "^description": "To prevent data loss and minimize cluster downtime in the event of a service disruption, you can distribute nodes across two or three Availability Zones in the same AWS Region. Availability Zones are isolated locations within each Region. With a two-AZ configuration, losing one Availability Zone means that you lose half of all domain capacity. Moving to three Availability Zones further reduces the impact of losing a single Availability Zone. Deploy mission-critical domains across three Availability Zones and two replica shards per index. This configuration lets OpenSearch Service distribute replica shards to different AZs than their corresponding primary shards. There are no cross-AZ data transfer charges for cluster communications between Availability Zones.", From 1229b1a369f1d38675f6dff3b2ad0d41f7dafd10 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Wed, 17 Apr 2024 16:34:19 +0100 Subject: [PATCH 04/16] Add checks --- services/opensearch/drivers/OpensearchCommon.py | 7 +++++++ services/opensearch/opensearch.reporter.json | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/services/opensearch/drivers/OpensearchCommon.py b/services/opensearch/drivers/OpensearchCommon.py index 9453479..8a81a44 100644 --- a/services/opensearch/drivers/OpensearchCommon.py +++ b/services/opensearch/drivers/OpensearchCommon.py @@ -164,6 +164,13 @@ def _checkNodeToNodeEncryption(self): if 'Enabled' in self.attribute['DomainStatus']['NodeToNodeEncryptionOptions']: self.results["NodeToNodeEncryption"] = [1, "Enabled"] + def _checkTLSEnforced(self): + self.results["TLSEnforced"] = [-1, "Disabled"] + if 'DomainStatus' in self.attribute: + if 'DomainEndpointOptions' in self.attribute['DomainStatus']: + if 'EnforceHTTPS' in self.attribute['DomainStatus']['DomainEndpointOptions']: + self.results["TLSEnforced"] = [1, "Enabled"] + def _checkSearchSlowLogs(self): self.results["SearchSlowLogs"] = [-1, "Disabled"] if 'DomainStatus' in self.attribute: diff --git a/services/opensearch/opensearch.reporter.json b/services/opensearch/opensearch.reporter.json index 7e4d28d..1ee3877 100644 --- a/services/opensearch/opensearch.reporter.json +++ b/services/opensearch/opensearch.reporter.json @@ -194,6 +194,19 @@ "[Enable node-to-node encryption]" ] }, + "TLSEnforced": { + "category": "S", + "^description": "HTTPS (TLS) can be used to help prevent potential attackers from using person-in-the-middle or similar attacks to eavesdrop on or manipulate network traffic. Only encrypted connections over HTTPS (TLS) should be allowed. Encrypting data in transit can affect performance. You should test your application with this feature to understand the performance profile and the impact of TLS. TLS 1.2 provides several security enhancements over previous versions of TLS. ", + "downtime": -1, + "slowness": -1, + "additionalCost": 0, + "criticality": "I", + "needFullTest": 0, + "shortDesc": "If your domain stores sensitive data, make sure the domain endpoint is configured to use the latest TLS security policy.", + "ref": [ + "[Enable node-to-node encryption]" + ] + }, "SearchSlowLogs": { "category": "P", "^description": "OpenSearch Service exposes OpenSearch error logs, search slow logs, indexing slow logs, and audit logs in Amazon CloudWatch Logs. Search slow logs, indexing slow logs, and error logs are useful for troubleshooting performance and stability issues. Audit logs, which are only available if you enable fine-grained access control to track user activity. For more information, see Logs in the OpenSearch documentation. Search slow logs and indexing slow logs are an important tool for understanding and troubleshooting the performance of your search and indexing operations. Enable search and index slow log delivery for all production domains. You must also configure logging thresholds—otherwise, CloudWatch won't capture the logs.", From 619f954f6615cb619b650409f3f5826aafa4fe32 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Wed, 17 Apr 2024 16:50:46 +0100 Subject: [PATCH 05/16] Fix missing passwordPolicyWeak check --- services/iam/iam.reporter.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/services/iam/iam.reporter.json b/services/iam/iam.reporter.json index ed1fa16..9965c25 100644 --- a/services/iam/iam.reporter.json +++ b/services/iam/iam.reporter.json @@ -104,6 +104,19 @@ "[IAM Password Policy]" ] }, + "passwordPolicyWeak": { + "category": "S", + "^description": "Your current password policy is not strong. Improving the strength of your password policy would improve the security of your account. Consider implementing best practices when setting the password policy. If you already configure as per your organization ", + "shortDesc": "Set a stronger password policy", + "criticality": "M", + "downtime": 0, + "slowness": 0, + "additionalCost": 0, + "needFullTest": 0, + "ref": [ + "[AWS Docs]" + ] + }, "passwordPolicyReuse": { "category": "S", "^description": "Your current password policy is not strong. Improving the strength of your password policy would improve the security of your account. Consider implementing best practices when setting the password policy. If you already configure as per your organization ", From 49d6c1e051a0b430fc60099d42c5952fff1fe4c7 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Thu, 18 Apr 2024 11:57:14 +0100 Subject: [PATCH 06/16] Fix description --- services/kms/kms.reporter.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/kms/kms.reporter.json b/services/kms/kms.reporter.json index b338ea4..5532305 100644 --- a/services/kms/kms.reporter.json +++ b/services/kms/kms.reporter.json @@ -27,13 +27,13 @@ }, "KeyInPendingDeletion":{ "category": "O", - "^description": "[Informational], no action needed. {$COUNT} KMS key is under Pending Deletion Stage.", + "^description": "[Warning] {$COUNT} KMS key is under Pending Deletion Stage. KMS keys cannot be recovered once deleted. Data encrypted under a KMS key is also permanently unrecoverable if the KMS key is deleted. If meaningful data has been encrypted under a KMS key scheduled for deletion, consider decrypting the data or re-encrypting the data under a new KMS key unless you are intentionally performing a cryptographic erasure.", "downtime": 0, "slowness": 0, "additionalCost": 0, "needFullTest": 0, "criticality": "I", - "shortDesc": "[Info] No Action Needed", + "shortDesc": "[Warning] Ensure intentional deletion", "ref": [ "[KMS Key State Explanation]" ] From 1df6415ae366e149f6b46420c3bc19384ffb436b Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Thu, 18 Apr 2024 16:40:27 +0100 Subject: [PATCH 07/16] Add check --- services/s3/drivers/S3Bucket.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/services/s3/drivers/S3Bucket.py b/services/s3/drivers/S3Bucket.py index 6d2abf8..55c5a44 100644 --- a/services/s3/drivers/S3Bucket.py +++ b/services/s3/drivers/S3Bucket.py @@ -70,14 +70,23 @@ def _checkObjectLock(self): self.results['ObjectLock'] = [-1, 'Off'] def _checkBucketReplication(self): - self.results['BucketReplication'] = [1, 'On'] try: resp = self.s3Client.get_bucket_replication( Bucket=self.bucket ) + source_loc = self.s3Client.get_bucket_location( + Bucket=self.bucket + ) + target_loc = resp.get('ReplicationConfiguration').get('Rules')[0].get('Destination').get('Bucket') + if source_loc.get('LocationConstraint') != target_loc.split('.')[1]: + self.results['CrossRegionReplication'] = [1, 'On'] + else: + self.results['SameRegionReplication'] = [1, 'On'] except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'ReplicationConfigurationNotFoundError': - self.results['BucketReplication'] = [-1, 'Off'] + self.results['CrossRegionReplication'] = [-1, 'Off'] + self.results['SameRegionReplication'] = [-1, 'Off'] + def _checkLifecycle(self): self.results['BucketLifecycle'] = [1, 'On'] From 4fc3abb70ba06d1892518f8625e794a18dcd9b44 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Thu, 18 Apr 2024 16:44:05 +0100 Subject: [PATCH 08/16] Add checks --- services/s3/drivers/S3Bucket.py | 7 +++---- services/s3/s3.reporter.json | 13 +++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/services/s3/drivers/S3Bucket.py b/services/s3/drivers/S3Bucket.py index 55c5a44..3301df6 100644 --- a/services/s3/drivers/S3Bucket.py +++ b/services/s3/drivers/S3Bucket.py @@ -71,6 +71,8 @@ def _checkObjectLock(self): def _checkBucketReplication(self): try: + self.results['BucketReplication'] = [1, 'On'] + resp = self.s3Client.get_bucket_replication( Bucket=self.bucket ) @@ -80,12 +82,9 @@ def _checkBucketReplication(self): target_loc = resp.get('ReplicationConfiguration').get('Rules')[0].get('Destination').get('Bucket') if source_loc.get('LocationConstraint') != target_loc.split('.')[1]: self.results['CrossRegionReplication'] = [1, 'On'] - else: - self.results['SameRegionReplication'] = [1, 'On'] except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'ReplicationConfigurationNotFoundError': - self.results['CrossRegionReplication'] = [-1, 'Off'] - self.results['SameRegionReplication'] = [-1, 'Off'] + self.results['BucketReplication'] = [-1, 'Off'] def _checkLifecycle(self): diff --git a/services/s3/s3.reporter.json b/services/s3/s3.reporter.json index 23101f5..e3af6f1 100644 --- a/services/s3/s3.reporter.json +++ b/services/s3/s3.reporter.json @@ -79,6 +79,19 @@ "[AWS Docs]" ] }, + "CrossRegionReplication": { + "category": "RS", + "^description": "You have not enabled cross-region replication on {$COUNT} buckets. Replication enables automatic, asynchronous copying of objects across Amazon S3 buckets.", + "shortDesc": "Enable Bucket Replication", + "criticality": "I", + "downtime": 0, + "slowness": 0, + "additionalCost": 1, + "needFullTest": 0, + "ref": [ + "[AWS Docs]" + ] + }, "BucketLifecycle": { "category": "CO", "^description": "You have not configured lifecycle policies for objects in {$COUNT} buckets. Lifecycle configuration is a set of rules that define actions that Amazon S3 applies to a group of objects. This will save you cost by moving infrequently accessed objects to lower cost storage tiers and expiring objects that are no longer needed.", From 8ab99c4b8eff05a682eb821bd4d01c207760429d Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Fri, 19 Apr 2024 16:02:38 +0100 Subject: [PATCH 09/16] Add checks --- services/s3/drivers/S3Bucket.py | 11 +++++++++++ services/s3/s3.reporter.json | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/services/s3/drivers/S3Bucket.py b/services/s3/drivers/S3Bucket.py index 3301df6..c605ac4 100644 --- a/services/s3/drivers/S3Bucket.py +++ b/services/s3/drivers/S3Bucket.py @@ -109,6 +109,17 @@ def _checkLogging(self): except botocore.exceptions.ClientError as e: print("[{}] Unable to get Logging Informaton, skip".format(self.bucket)) + def _checkEventNotif(self): + self.results['EventNotification'] = [1, 'On'] + try: + resp = self.s3Client.get_bucket_notification_configuration( + Bucket=self.bucket + ) + self.results['EventNotification'] = [-1, 'On'] + except botocore.exceptions.ClientError as e: + if e.response['Error']['Code'] == 'NoSuchNotificationConfiguration': + self.results['EventNotification'] = [-1, 'Off'] + def _checkIntelligentTiering(self): try: self.results['ObjectsInIntelligentTier'] = [1,'On'] diff --git a/services/s3/s3.reporter.json b/services/s3/s3.reporter.json index e3af6f1..11fe55e 100644 --- a/services/s3/s3.reporter.json +++ b/services/s3/s3.reporter.json @@ -92,6 +92,19 @@ "[AWS Docs]" ] }, + "EventNotification": { + "category": "OS", + "^description": "When you enable S3 Event Notifications, you receive alerts when specific events occur that impact your S3 buckets. For example, you can be notified of object creation, object removal, and object restoration. These notifications can alert relevant teams to accidental or intentional modifications that may lead to unauthorized data access.", + "shortDesc": "Enable Event Notification", + "criticality": "I", + "downtime": 0, + "slowness": 0, + "additionalCost": 1, + "needFullTest": 0, + "ref": [ + "[AWS Docs]" + ] + }, "BucketLifecycle": { "category": "CO", "^description": "You have not configured lifecycle policies for objects in {$COUNT} buckets. Lifecycle configuration is a set of rules that define actions that Amazon S3 applies to a group of objects. This will save you cost by moving infrequently accessed objects to lower cost storage tiers and expiring objects that are no longer needed.", From 87f94e2d0929465ab04245372671a19037a36cf3 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Fri, 19 Apr 2024 16:12:30 +0100 Subject: [PATCH 10/16] Add checks --- services/s3/drivers/S3Bucket.py | 10 ++++++++++ services/s3/s3.reporter.json | 13 +++++++++++++ 2 files changed, 23 insertions(+) diff --git a/services/s3/drivers/S3Bucket.py b/services/s3/drivers/S3Bucket.py index c605ac4..5727c7f 100644 --- a/services/s3/drivers/S3Bucket.py +++ b/services/s3/drivers/S3Bucket.py @@ -119,6 +119,16 @@ def _checkEventNotif(self): except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'NoSuchNotificationConfiguration': self.results['EventNotification'] = [-1, 'Off'] + + def _checkACL(self): + try: + resp = self.s3Client.get_bucket_acl( + Bucket=self.bucket + ) + self.results['AccessControlList'] = [-1, 'Enabled'] + except botocore.exceptions.ClientError as e: + if e.response['Error']['Code'] == 'NoSuchAcl': + self.results['AccessControlList'] = [1, 'Disabled'] def _checkIntelligentTiering(self): try: diff --git a/services/s3/s3.reporter.json b/services/s3/s3.reporter.json index 11fe55e..23d3f43 100644 --- a/services/s3/s3.reporter.json +++ b/services/s3/s3.reporter.json @@ -12,6 +12,19 @@ "[Protecting data with encryption]" ] }, + "AccessControlList": { + "category": "S", + "^description": "You are using {$COUNT} S3 buckets with ACLs. ACLs are legacy access control mechanisms that predate IAM. Instead of ACLs, we recommend using S3 bucket policies or AWS Identity and Access Management (IAM) policies to manage access to your S3 buckets.", + "shortDesc": "Enable SSE", + "criticality": "L", + "downtime": 0, + "slowness": 0, + "additionalCost": 0, + "needFullTest": 0, + "ref": [ + "[Protecting data with IAM]" + ] + }, "PublicAccessBlock": { "category": "S", "^description": "You have disabled public access block on {$COUNT} S3 buckets.This leaves your data to be accessible by anyone. Unless absolutely necessary, enable public access block. Block Public Access at the S3 bucket level provides controls to ensure that objects never have public access. Public access is granted to buckets and objects through access control lists (ACLs), bucket policies, or both.", From 83896d5b89004eaf5c1342fb95dfac4275fd1213 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Fri, 19 Apr 2024 16:43:39 +0100 Subject: [PATCH 11/16] Add checks --- services/s3/drivers/S3Bucket.py | 2 ++ services/s3/s3.reporter.json | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/services/s3/drivers/S3Bucket.py b/services/s3/drivers/S3Bucket.py index 5727c7f..f2eba57 100644 --- a/services/s3/drivers/S3Bucket.py +++ b/services/s3/drivers/S3Bucket.py @@ -23,6 +23,8 @@ def _checkEncrypted(self): resp = self.s3Client.get_bucket_encryption( Bucket=self.bucket ) + if "kms" not in resp.get('ServerSideEncryptionConfiguration').get('Rules')[0].get('ApplyServerSideEncryptionByDefault').get('SSEAlgorithm'): + self.results['SSEWithKMS'] = [1, 'On'] except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'ServerSideEncryptionConfigurationNotFoundError': self.results['ServerSideEncrypted'] = [-1, 'Off'] diff --git a/services/s3/s3.reporter.json b/services/s3/s3.reporter.json index 23d3f43..a4a9c6a 100644 --- a/services/s3/s3.reporter.json +++ b/services/s3/s3.reporter.json @@ -3,7 +3,20 @@ "category": "S", "^description": "You have not enabled server side encryption (SSE) on {$COUNT} buckets which automatically encrypts objects uploaded to the bucket. If this bucket contains non-publically-available data, and you are not implementing client-side encryption, please enable SSE.", "shortDesc": "Enable SSE", - "criticality": "L", + "criticality": "M", + "downtime": 0, + "slowness": 0, + "additionalCost": 0, + "needFullTest": 0, + "ref": [ + "[Protecting data with encryption]" + ] + }, + "SSEWithKMS": { + "category": "S", + "^description": "You have not enabled server side encryption (SSE) with KMS on {$COUNT} buckets which automatically encrypts objects uploaded to the bucket. If this bucket contains non-publically-available data, and you are not implementing client-side encryption, please enable SSE with KMS.", + "shortDesc": "Enable SSE with KMS", + "criticality": "M", "downtime": 0, "slowness": 0, "additionalCost": 0, From df0b30d80d708ec4c5cf48abc950f9b8caf35273 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Fri, 19 Apr 2024 16:56:49 +0100 Subject: [PATCH 12/16] Add mapping --- frameworks/NIST/NIST.py | 9 + frameworks/NIST/NISTPageBuilder.py | 6 + frameworks/NIST/map.json | 375 +++++++++++++++++++++++++++++ 3 files changed, 390 insertions(+) create mode 100644 frameworks/NIST/NIST.py create mode 100644 frameworks/NIST/NISTPageBuilder.py create mode 100644 frameworks/NIST/map.json diff --git a/frameworks/NIST/NIST.py b/frameworks/NIST/NIST.py new file mode 100644 index 0000000..c47fbf2 --- /dev/null +++ b/frameworks/NIST/NIST.py @@ -0,0 +1,9 @@ +import json + +import constants as _C +from frameworks.Framework import Framework + +class NIST(Framework): + def __init__(self, data): + super().__init__(data) + pass \ No newline at end of file diff --git a/frameworks/NIST/NISTPageBuilder.py b/frameworks/NIST/NISTPageBuilder.py new file mode 100644 index 0000000..4102900 --- /dev/null +++ b/frameworks/NIST/NISTPageBuilder.py @@ -0,0 +1,6 @@ +from frameworks.FrameworkPageBuilder import FrameworkPageBuilder + +class NISTPageBuilder(FrameworkPageBuilder): + def init(self): + super().__init__() + self.template = 'default' \ No newline at end of file diff --git a/frameworks/NIST/map.json b/frameworks/NIST/map.json new file mode 100644 index 0000000..b9023b2 --- /dev/null +++ b/frameworks/NIST/map.json @@ -0,0 +1,375 @@ +{ + "metadata": { + "originator": "NIST", + "shortname": "NIST AWS", + "fullname": "National Institute of Standards and Technology (NIST) SP 800-53 Rev. 5", + "description": "The NIST Special Publication 800-53 Revision 5 provides a catalog of security and privacy controls for federal information systems and organizations to protect organizational operations and assets, individuals, other organizations, and the Nation from a diverse set of threats including hostile cyber attacks, natural disasters, structural failures, and human errors.", + "_": "https://docs.aws.amazon.com/securityhub/latest/userguide/nist-standard.html", + "emptyCheckDefaultMsg": "Please refer to the NIST control section for further details. Kindly provide evidence or artifacts demonstrating compliance with the respective NIST control." + }, + "mapping": { + "Account.": { + "1": [], + "2": [] + }, + "ACM.": { + "1": [] + }, + "APIGateway.": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [], + "8": [], + "9": [] + }, + "Appsync.": { + "5": [] + }, + "Autoscaling.": { + "1": [], + "2": [], + "3": [], + "5": [], + "6": [], + "9": [] + }, + "Backup.": { + "1": [] + }, + "CloudFront.": { + "1": [], + "3": [], + "4": [], + "5": [], + "6": [], + "7": [], + "8": [], + "9": [], + "10": [], + "12": [] + }, + "CloudTrail.": { + "1": ["cloudtrail.HasOneMultiRegionTrail"], + "2": ["cloudtrail.RequiresKmsKey"], + "4": ["cloudtrail.LogFileValidationEnabled"], + "5": ["cloudtrail.CloudWatchLogsLogGroupArn"] + }, + "CloudWatch.": { + "15": [], + "16": [], + "17": [] + }, + "CodeBuild.": { + "1": [], + "2": [], + "3": [], + "4": [] + }, + "Config.": { + "1": [] + }, + "DMS.": { + "1": [], + "6": [], + "7": [], + "8": [], + "9": [] + }, + "DocumentDB.": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [] + }, + "DynamoDB.": { + "1": [], + "2": [], + "3": [], + "4": [], + "6": [] + }, + "EC2.": { + "1": ["ec2.EBSSnapshotIsPublic"], + "2": ["ec2.SGDefaultDisallowTraffic"], + "3": ["ec2.EBSInUse", "ec2.EBSEncrypted"], + "4": ["ec2.EC2Active"], + "5": [""], + "6": [], + "7": ["ec2.EBSEncrypted"], + "8": ["ec2.ASGIMDSv2"], + "9": ["ec2.EC2InstancePublicIP"], + "10": [], + "12": ["ec2.EC2EIPNotInUse"], + "13": ["ec2.SGSensitivePortOpenToAll", "ec2.SGAllPortOpenToAll"], + "15": ["ec2.EC2SubnetAutoPublicIP"], + "16": [], + "17": [], + "18": [], + "19": [], + "20": [], + "21": [], + "23": [], + "24": [], + "25": [], + "28": [], + "51": [] + + }, + "ECR.": { + "1": [], + "2": [], + "3": [] + }, + "ECS.": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [], + "8": [], + "9": [], + "10": [], + "12": [] + }, + "EFS.": { + "1": [], + "2": [], + "3": [], + "4": [] + }, + "EKS.": { + "1": ["eks.eksEndpointPublicAccess"], + "2": ["eks.eksClusterVersionEol"], + "8": ["eks.eksClusterLogging"] + }, + "ElastiCache.": { + "1": [], + "2": [], + "3": [], + "4": ["elasticache.EncInTransitAndRest"], + "5": ["elasticache.EncInTransitAndRest"], + "6": [], + "7": [] + }, + "ElasticBeanstalk.": { + "1": [], + "2": [] + }, + "ELB.": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [], + "6": [], + "7": ["ec2.ELBConnectionDraining"], + "8": [], + "9": ["ec2.ELBCrossZone"], + "10": [], + "12": [], + "13": [], + "14": [], + "16": ["ec2.ELBEnableWAF"] + }, + "EMR.": { + "1": [], + "2": [] + }, + "ES.": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [], + "6": [], + "7": [], + "8": [] + }, + "EventBridge.": { + "3": [], + "4": [] + }, + "FSx.": { + "1": [] + }, + "GuardDuty.": { + "1": [] + }, + "IAM.": { + "1": ["iam.FullAdminAccess"], + "2": ["iam.userNotUsingGroup","iam.InlinePolicy"], + "3": ["iam.hasAccessKeyNoRotate90days"], + "4": ["iam.rootHasAccessKey"], + "5": ["iam.mfaActive"], + "6": [], + "7": ["iam.passwordPolicyWeak"], + "8": ["iam.consoleLastAccess90", "iam.consoleLastAccess365"], + "9": ["iam.rootMfaActive"], + "19": ["iam.mfaActive"], + "21": ["iam.ManagedPolicyFullAccessOneServ"], + }, + "Kinesis.": { + "1": [] + }, + "KMS.": { + "1": [], + "2": [], + "3": ["kms.KeyInPendingDeletion"], + "4": ["kms.KeyRotationEnabled"] + }, + "Lambda.": { + "1": ["lambda.lambdaPublicAccess"], + "2": ["lambda.lambdaRuntimeUpdate"], + "3": [], + "5": [] + }, + "Macie.": { + "1": ["s3.MacieToEnable"], + "2": [] + }, + "MSK.": { + "1": [], + "2": [], + }, + "MQ.": { + "5": [], + "6": [] + }, + "Neptune.": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [], + "6": [], + "7": [], + "8": [], + "9": [] + }, + "NetworkFirewall.": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [], + "6": [], + "9": [] + }, + "Opensearch.": { + "1": ["opensearch.EncyptionAtRest"], + "2": ["opensearch.DomainWithinVPC"], + "3": ["opensearch.NodeToNodeEncryption"], + "4": ["opensearch.ApplicationLogs"], + "5": ["opensearch.AuditLogs"], + "6": ["opensearch.DataNodes"], + "7": ["opensearch.FineGrainedAccessControl"], + "8": ["opensearch.TLSEnforced"], + "10": ["opensearch.ServiceSoftwareVersion"] + }, + "PCA.": { + "1": [] + }, + "RDS.": { + "1": ["rds.SnapshotRDSIsPublic"], + "2": ["rds.PubliclyAccessible"], + "3": ["rds.StorageEncrypted"], + "4": [], + "5": ["rds.MultiAZ"], + "6": ["rds.EnhancedMonitor"], + "7": ["rds.DeleteProtection"], + "8": ["rds.DeleteProtection"], + "9": [], + "10": [], + "11": ["rds.Backup"], + "12": [], + "13": ["rds.AutoMinorVersionUpgrade"], + "14": [], + "15": ["rds.MultiAZ"], + "16": [], + "17": [], + "18": [], + "19": [], + "20": [], + "21": [], + "22": [], + "23": [], + "24": ["rds.DefaultMasterAdmin"], + "25": ["rdsDefaultMasterAdmin"], + "26": [], + "27": ["rds.StorageEncrypted"], + "34": [], + "35": ["rds.AutoMinorVersionUpgrade"] + }, + "Redshift.": { + "1": [], + "2": [], + "3": [], + "4": [], + "6": [], + "7": [], + "8": [], + "9": [], + "10": [] + }, + "Route53.": { + "2": [] + }, + "S3.": { + "1": ["s3.S3AccountPublicAccessBlock"], + "2": ["s3.PublicAccessBlock"], + "3": ["s3.PublicAccessBlock"], + "5": ["s3.TlsEnforced"], + "7": ["s3.CrossRegionReplication"], + "8": ["s3.PublicAccessBlock"], + "9": ["s3.BucketLogging"], + "10": ["s3.BucketVersioning", "s3.BucketLifecycle"], + "11": ["s3.EventNotification"], + "12": ["s3.AccessControlList"], + "13": ["s3.BucketLifecycle"], + "14": ["s3.BucketVersioning"], + "15": ["s3.ObjectLock"], + "17": ["ServerSideEncrypted", "s3.SSEWithKMS"], + "19": [], + "20": ["s3.MFADelete"], + }, + "Sagemaker.": { + "1": [], + "2": [], + "3": [] + }, + "SecretsManager.": { + "1": [], + "2": [], + "3": [], + "4": [] + }, + "SNS.": { + "1": [] + }, + "SQS.": { + "1": [] + }, + "SSM.": { + "1": [], + "2": [], + "3": [], + "4": [] + }, + "WAF.": { + "1": [], + "2": [], + "3": [], + "4": [], + "5": [], + "6": [], + "7": [], + "8": [], + "10": [], + "11": [], + "12": [] + } + } +} \ No newline at end of file From 010b18bdabdde5486cac5884dd7142499cc27153 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Fri, 19 Apr 2024 17:41:11 +0100 Subject: [PATCH 13/16] Fix stray commas --- frameworks/NIST/map.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frameworks/NIST/map.json b/frameworks/NIST/map.json index b9023b2..8e98dca 100644 --- a/frameworks/NIST/map.json +++ b/frameworks/NIST/map.json @@ -209,7 +209,7 @@ "8": ["iam.consoleLastAccess90", "iam.consoleLastAccess365"], "9": ["iam.rootMfaActive"], "19": ["iam.mfaActive"], - "21": ["iam.ManagedPolicyFullAccessOneServ"], + "21": ["iam.ManagedPolicyFullAccessOneServ"] }, "Kinesis.": { "1": [] @@ -232,7 +232,7 @@ }, "MSK.": { "1": [], - "2": [], + "2": [] }, "MQ.": { "5": [], @@ -333,7 +333,7 @@ "15": ["s3.ObjectLock"], "17": ["ServerSideEncrypted", "s3.SSEWithKMS"], "19": [], - "20": ["s3.MFADelete"], + "20": ["s3.MFADelete"] }, "Sagemaker.": { "1": [], From 1b1a0262853289bad55e948e564a1ea15bfd67f8 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Tue, 23 Apr 2024 14:09:24 +0100 Subject: [PATCH 14/16] Fix syntax --- frameworks/CIS/map.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/CIS/map.json b/frameworks/CIS/map.json index cfe52e8..43eaf1e 100644 --- a/frameworks/CIS/map.json +++ b/frameworks/CIS/map.json @@ -9,7 +9,7 @@ }, "mapping": { "CloudTrail.": { - "1": ["cloudtrail.NeedToEnableCloudTrail, cloudtrail.HasOneMultiRegionTrail"], + "1": ["cloudtrail.NeedToEnableCloudTrail", "cloudtrail.HasOneMultiRegionTrail"], "2": ["cloudtrail.RequiresKmsKey"], "4": ["cloudtrail.LogFileValidationEnabled"], "5": ["cloudtrail.CloudWatchLogsLogGroupArn"], From 6cdbfe71be2b45c7806035a9c1cf6e6ad2901753 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Fri, 26 Apr 2024 15:34:21 +0100 Subject: [PATCH 15/16] Add NIST --- .gitignore | 1 + frameworks/FrameworkPageBuilder.py | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 79669d2..bf00902 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Custom test.py +test.md crossAccounts.json output.zip __fork/*.json diff --git a/frameworks/FrameworkPageBuilder.py b/frameworks/FrameworkPageBuilder.py index 2f0b5d5..d34da39 100644 --- a/frameworks/FrameworkPageBuilder.py +++ b/frameworks/FrameworkPageBuilder.py @@ -6,6 +6,7 @@ from frameworks.WAFS.WAFS import WAFS from frameworks.MSR.MSR import MSR from frameworks.CIS.CIS import CIS +from frameworks.CIS.CIS import NIST class FrameworkPageBuilder(PageBuilder): COMPLIANCE_STATUS = ["Not available", "Compliant", "Need Attention"] From 9a09e80208efe3a6230448f62a9f7b9621c74867 Mon Sep 17 00:00:00 2001 From: Subramaniam Date: Fri, 26 Apr 2024 15:41:13 +0100 Subject: [PATCH 16/16] Add WIP caveat --- frameworks/NIST/map.json | 2 +- frameworks/NIST/readme.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 frameworks/NIST/readme.md diff --git a/frameworks/NIST/map.json b/frameworks/NIST/map.json index 8e98dca..fd9c3b6 100644 --- a/frameworks/NIST/map.json +++ b/frameworks/NIST/map.json @@ -3,7 +3,7 @@ "originator": "NIST", "shortname": "NIST AWS", "fullname": "National Institute of Standards and Technology (NIST) SP 800-53 Rev. 5", - "description": "The NIST Special Publication 800-53 Revision 5 provides a catalog of security and privacy controls for federal information systems and organizations to protect organizational operations and assets, individuals, other organizations, and the Nation from a diverse set of threats including hostile cyber attacks, natural disasters, structural failures, and human errors.", + "description": "[Work In Progress] The NIST Special Publication 800-53 Revision 5 provides a catalog of security and privacy controls for federal information systems and organizations to protect organizational operations and assets, individuals, other organizations, and the Nation from a diverse set of threats including hostile cyber attacks, natural disasters, structural failures, and human errors.", "_": "https://docs.aws.amazon.com/securityhub/latest/userguide/nist-standard.html", "emptyCheckDefaultMsg": "Please refer to the NIST control section for further details. Kindly provide evidence or artifacts demonstrating compliance with the respective NIST control." }, diff --git a/frameworks/NIST/readme.md b/frameworks/NIST/readme.md new file mode 100644 index 0000000..43f6201 --- /dev/null +++ b/frameworks/NIST/readme.md @@ -0,0 +1 @@ +### This framework is a work in progress should be used as a reference only. There are currently many outstanding checks that are yet to be implemented. Please see [CONTRIBUTING](./CONTRIBUTING.md) if you would like to contribute to building this framework. \ No newline at end of file