diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/metadata.json b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/metadata.json new file mode 100644 index 00000000000..8182205d01c --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/metadata.json @@ -0,0 +1,11 @@ +{ + "id": "0f04217d-488f-4e7a-bec8-f16159686cd6", + "queryName": "DynamoDB Table Point In Time Recovery Disabled", + "severity": "MEDIUM", + "category": "Best Practices", + "descriptionText": "It's considered a best practice to have point in time recovery enabled for DynamoDB Table", + "descriptionUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html", + "platform": "CloudFormation", + "descriptionID": "a0a51171", + "cloudProvider": "aws" +} diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/query.rego b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/query.rego new file mode 100644 index 00000000000..5ac17c30751 --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/query.rego @@ -0,0 +1,62 @@ +package Cx + +import data.generic.common as common_lib +import data.generic.cloudformation as cf_lib + +CxPolicy[result] { + document := input.document[i] + resource := document.Resources[key] + resource.Type == "AWS::DynamoDB::Table" + properties := resource.Properties + + properties.PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled == false + + result := { + "documentId": input.document[i].id, + "resourceType": resource.Type, + "resourceName": cf_lib.get_resource_name(resource, key), + "searchKey": sprintf("Resources.%s.Properties.PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled", [key]), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("Resources[%s].Properties.PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled should be set to 'true'", [key]), + "keyActualValue": sprintf("Resources[%s].Properties.PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled is set to 'false'", [key]), + } +} + +CxPolicy[result] { + document := input.document[i] + resource := document.Resources[key] + resource.Type == "AWS::DynamoDB::Table" + properties := resource.Properties + + not common_lib.valid_key(properties, "PointInTimeRecoverySpecification") + + result := { + "documentId": input.document[i].id, + "resourceType": resource.Type, + "resourceName": cf_lib.get_resource_name(resource, key), + "searchKey": sprintf("Resources.%s.Properties", [key]), + "issueType": "MissingAttribute", + "keyExpectedValue": sprintf("Resources[%s].Properties.PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled should be defined and set to 'true'", [key]), + "keyActualValue": sprintf("Resources[%s].Properties.PointInTimeRecoverySpecification is not defined", [key]), + } +} + +CxPolicy[result] { + document := input.document[i] + resource := document.Resources[key] + resource.Type == "AWS::DynamoDB::Table" + properties := resource.Properties + specification := properties.PointInTimeRecoverySpecification + + not common_lib.valid_key(specification, "PointInTimeRecoveryEnabled") + + result := { + "documentId": input.document[i].id, + "resourceType": resource.Type, + "resourceName": cf_lib.get_resource_name(resource, key), + "searchKey": sprintf("Resources.%s.Properties.PointInTimeRecoverySpecification", [key]), + "issueType": "MissingAttribute", + "keyExpectedValue": sprintf("Resources[%s].Properties.PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled should be defined and set to 'true'", [key]), + "keyActualValue": sprintf("Resources[%s].Properties.PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled is not defined", [key]), + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative1.yaml b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative1.yaml new file mode 100644 index 00000000000..2d5c40288b2 --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative1.yaml @@ -0,0 +1,6 @@ +Resources: + MyDynamoDBTable: + Type: AWS::DynamoDB::Table + Properties: + PointInTimeRecoverySpecification: + PointInTimeRecoveryEnabled: true diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative2.json b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative2.json new file mode 100644 index 00000000000..4c1df5b5ef7 --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative2.json @@ -0,0 +1,15 @@ +{ + "Resources": { + "DynamoDBOnDemandTable1": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "BillingMode": "PAY_PER_REQUEST", + "PointInTimeRecoverySpecification" : { + "PointInTimeRecoveryEnabled" : true + } + } + }, + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Sample CloudFormation template for DynamoDB with customer managed CMK" + } +} diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive1.yaml b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive1.yaml new file mode 100644 index 00000000000..8f52a77e5e8 --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive1.yaml @@ -0,0 +1,6 @@ +Resources: + MyDynamoDBTable: + Type: AWS::DynamoDB::Table + Properties: + PointInTimeRecoverySpecification: + PointInTimeRecoveryEnabled: false diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive2.yaml b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive2.yaml new file mode 100644 index 00000000000..ba26abc5cac --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive2.yaml @@ -0,0 +1,5 @@ +Resources: + MyDynamoDBTable: + Type: AWS::DynamoDB::Table + Properties: + TableName: my-table diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive3.json b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive3.json new file mode 100644 index 00000000000..07d9427442a --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive3.json @@ -0,0 +1,15 @@ +{ + "Resources": { + "DynamoDBOnDemandTable1": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "BillingMode": "PAY_PER_REQUEST", + "PointInTimeRecoverySpecification" : { + "PointInTimeRecoveryEnabled" : false + } + } + }, + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Sample CloudFormation template for DynamoDB with customer managed CMK" + } +} diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive4.json b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive4.json new file mode 100644 index 00000000000..7eac82d4f31 --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive4.json @@ -0,0 +1,12 @@ +{ + "Resources": { + "DynamoDBOnDemandTable1": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "BillingMode": "PAY_PER_REQUEST" + } + }, + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Sample CloudFormation template for DynamoDB with customer managed CMK" + } +} diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive5.yaml b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive5.yaml new file mode 100644 index 00000000000..eb222d7f5ce --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive5.yaml @@ -0,0 +1,5 @@ +Resources: + MyDynamoDBTable: + Type: AWS::DynamoDB::Table + Properties: + PointInTimeRecoverySpecification: {} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive6.json b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive6.json new file mode 100644 index 00000000000..a83a1d3b63e --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive6.json @@ -0,0 +1,13 @@ +{ + "Resources": { + "DynamoDBOnDemandTable1": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "BillingMode": "PAY_PER_REQUEST", + "PointInTimeRecoverySpecification" : {} + } + }, + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Sample CloudFormation template for DynamoDB with customer managed CMK" + } +} diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive_expected_result.json new file mode 100644 index 00000000000..a0a74b5bdfa --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive_expected_result.json @@ -0,0 +1,38 @@ +[ + { + "queryName": "DynamoDB Table Point In Time Recovery Disabled", + "severity": "MEDIUM", + "line": 6, + "filename": "positive1.yaml" + }, + { + "queryName": "DynamoDB Table Point In Time Recovery Disabled", + "severity": "MEDIUM", + "line": 4, + "filename": "positive2.yaml" + }, + { + "queryName": "DynamoDB Table Point In Time Recovery Disabled", + "severity": "MEDIUM", + "line": 8, + "filename": "positive3.json" + }, + { + "queryName": "DynamoDB Table Point In Time Recovery Disabled", + "severity": "MEDIUM", + "line": 5, + "filename": "positive4.json" + }, + { + "queryName": "DynamoDB Table Point In Time Recovery Disabled", + "severity": "MEDIUM", + "line": 5, + "filename": "positive5.yaml" + }, + { + "queryName": "DynamoDB Table Point In Time Recovery Disabled", + "severity": "MEDIUM", + "line": 7, + "filename": "positive6.json" + } +]