From bd62f56df416decc80f7f1e1a788e0d103b8fce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Tue, 28 Oct 2025 12:08:01 +0100 Subject: [PATCH] chore(aws): enhance metadata for `dynamodb` service (#8871) Co-authored-by: Daniel Barranquero --- prowler/CHANGELOG.md | 5 ++- ...r_cluster_encryption_enabled.metadata.json | 29 ++++++++++------ ...n_transit_encryption_enabled.metadata.json | 27 +++++++++------ ...accelerator_cluster_multi_az.metadata.json | 34 ++++++++++++------- ...db_table_autoscaling_enabled.metadata.json | 32 ++++++++++------- ...b_table_cross_account_access.metadata.json | 27 +++++++++------ ..._deletion_protection_enabled.metadata.json | 34 ++++++++++++------- ...ble_protected_by_backup_plan.metadata.json | 30 +++++++++------- ...s_kms_cmk_encryption_enabled.metadata.json | 30 +++++++++------- ...dynamodb_tables_pitr_enabled.metadata.json | 31 ++++++++++------- 10 files changed, 172 insertions(+), 107 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 966c872dc5..7489582dcf 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -6,9 +6,12 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Added - GitHub provider check `organization_default_repository_permission_strict` [(#8785)](https://github.com/prowler-cloud/prowler/pull/8785) +- `codepipeline_project_repo_private` check for AWS provider [(#5915)](https://github.com/prowler-cloud/prowler/pull/5915) + +### Changed - Update AWS Direct Connect service metadata to new format [(#8855)](https://github.com/prowler-cloud/prowler/pull/8855) - Update AWS DRS service metadata to new format [(#8870)](https://github.com/prowler-cloud/prowler/pull/8870) -- `codepipeline_project_repo_private` check for AWS provider [(#5915)](https://github.com/prowler-cloud/prowler/pull/5915) +- Update AWS DynamoDB service metadata to new format [(#8871)](https://github.com/prowler-cloud/prowler/pull/8871) --- diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_encryption_enabled/dynamodb_accelerator_cluster_encryption_enabled.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_encryption_enabled/dynamodb_accelerator_cluster_encryption_enabled.metadata.json index fd755c6489..630765920b 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_encryption_enabled/dynamodb_accelerator_cluster_encryption_enabled.metadata.json +++ b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_encryption_enabled/dynamodb_accelerator_cluster_encryption_enabled.metadata.json @@ -1,28 +1,35 @@ { "Provider": "aws", "CheckID": "dynamodb_accelerator_cluster_encryption_enabled", - "CheckTitle": "Check if DynamoDB DAX Clusters are encrypted at rest.", + "CheckTitle": "DynamoDB DAX cluster has encryption at rest enabled", "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" ], "ServiceName": "dynamodb", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:dax:region:account-id:cache/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Check if DynamoDB DAX Clusters are encrypted at rest.", - "Risk": "Encryption at rest provides an additional layer of data protection by securing your data from unauthorized access to the underlying storage.", - "RelatedUrl": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAXEncryptionAtRest.html", + "Description": "**Amazon DynamoDB Accelerator (DAX) clusters** are evaluated for **server-side `encryption at rest`**. The finding indicates whether the cluster's on-disk cache, configuration, and logs are encrypted using service-managed keys.", + "Risk": "Without **encryption at rest**, DAX on-disk cache and logs can be extracted from underlying storage by those with low-level access, compromising **confidentiality** and enabling offline data mining.\n\nThreats:\n- Compromised host or admin\n- Lost/retired media\n- Unauthorized backups or snapshots", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAXEncryptionAtRest.html", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/DAX/encryption-enabled.html", + "https://docs.aws.amazon.com/prescriptive-guidance/latest/encryption-best-practices/dynamodb.html" + ], "Remediation": { "Code": { - "CLI": "aws dax create-cluster --cluster-name --node-type --replication-factor --iam-role-arn --sse-specification Enabled=true", - "NativeIaC": "https://docs.prowler.com/checks/aws/general-policies/bc_aws_general_23#cloudformation", - "Other": "", - "Terraform": "https://docs.prowler.com/checks/aws/general-policies/bc_aws_general_23#terraform" + "CLI": "aws dax create-cluster --cluster-name --node-type --replication-factor 1 --iam-role-arn --sse-specification Enabled=true", + "NativeIaC": "```yaml\nResources:\n DaxCluster:\n Type: AWS::DAX::Cluster\n Properties:\n ClusterName: \n NodeType: \n ReplicationFactor: 1\n IAMRoleARN: \n SSESpecification: # Critical: enables encryption at rest\n SSEEnabled: true # Encrypts DAX cluster data at rest\n```", + "Other": "1. In the AWS console, open **DynamoDB** > under **DAX**, choose **Clusters** > **Create cluster**\n2. Enter a name and choose a node type\n3. In **Encryption**, select **Enable encryption**\n4. Choose the IAM role and required networking, then click **Launch cluster**\n5. If replacing an existing unencrypted cluster: point your application to the new cluster endpoint, then delete the old cluster", + "Terraform": "```hcl\nresource \"aws_dax_cluster\" \"example\" {\n cluster_name = \"\"\n node_type = \"\"\n replication_factor = 1\n iam_role_arn = \"\"\n\n # Critical: enables encryption at rest\n server_side_encryption {\n enabled = true # Encrypts DAX cluster data at rest\n }\n}\n```" }, "Recommendation": { - "Text": "Re-create the cluster to enable encryption at rest if it was not enabled at creation.", - "Url": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAXEncryptionAtRest.html" + "Text": "Provision DAX clusters with **`encryption at rest`** enabled. Apply **least privilege** for DAX administration and data access, and monitor with logging.\n\nAdopt **defense in depth**: enable encryption in transit, restrict network exposure, and avoid caching highly sensitive data. Re-create unencrypted clusters to enforce this setting.", + "Url": "https://hub.prowler.com/check/dynamodb_accelerator_cluster_encryption_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.metadata.json index 50741ae1c2..328815df1d 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.metadata.json +++ b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_in_transit_encryption_enabled/dynamodb_accelerator_cluster_in_transit_encryption_enabled.metadata.json @@ -1,28 +1,33 @@ { "Provider": "aws", "CheckID": "dynamodb_accelerator_cluster_in_transit_encryption_enabled", - "CheckTitle": "Check if DynamoDB Accelerator (DAX) clusters are encrypted in transit.", + "CheckTitle": "DynamoDB Accelerator (DAX) cluster has encryption in transit enabled", "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices", + "Effects/Data Exposure" ], "ServiceName": "dynamodb", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:dynamodb:region:account-id:table/table-name", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "This control checks whether an Amazon DynamoDB Accelerator (DAX) cluster is encrypted in transit, with the endpoint encryption type set to TLS. The control fails if the DAX cluster isn't encrypted in transit.", - "Risk": "Without encryption in transit, DAX clusters are vulnerable to person-in-the-middle attacks or eavesdropping on network traffic, which could lead to unauthorized access or manipulation of sensitive data.", - "RelatedUrl": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAXEncryptionInTransit.html", + "Description": "**DAX clusters** have endpoint encryption set to `TLS`, enforcing **encryption in transit** for client connections to the cluster", + "Risk": "Missing **TLS** enables interception and manipulation of DAX traffic, impacting:\n- Confidentiality: exposure of queries, data, or credentials\n- Integrity: tampered requests/responses and cache poisoning\n- Availability: session hijacking or replay causing service disruption", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/dynamodb-controls.html#dynamodb-7", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAXEncryptionInTransit.html" + ], "Remediation": { "Code": { "CLI": "aws dax create-cluster --cluster-name --node-type --replication-factor --cluster-endpoint-encryption-type TLS", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/dynamodb-controls.html#dynamodb-7", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: Create DAX cluster with TLS (encryption in transit)\nResources:\n :\n Type: AWS::DAX::Cluster\n Properties:\n ClusterName: \n IAMRoleARN: \n NodeType: \n ReplicationFactor: 1\n ClusterEndpointEncryptionType: TLS # Critical: Enables TLS for in-transit encryption\n```", + "Other": "1. In the AWS Console, go to DynamoDB > DAX\n2. Click Create cluster\n3. Set Cluster name, Node type, Replication factor, and IAM role\n4. Enable Encryption in transit (TLS)\n5. Create the cluster and wait until ACTIVE\n6. Update your application to use the new DAX cluster endpoint\n7. Delete the old non-TLS DAX cluster", + "Terraform": "```hcl\n# DAX cluster with encryption in transit enabled\nresource \"aws_dax_cluster\" \"\" {\n cluster_name = \"\"\n node_type = \"\"\n replication_factor = 1\n iam_role_arn = \"\"\n cluster_endpoint_encryption_type = \"TLS\" # Critical: Enables TLS for in-transit encryption\n}\n```" }, "Recommendation": { - "Text": "Ensure that DynamoDB Accelerator (DAX) clusters are encrypted in transit by enabling TLS during cluster creation.", - "Url": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAXEncryptionInTransit.html" + "Text": "Enforce **TLS** for all DAX endpoints and clients (`encryption in transit`). If an existing cluster lacks it, create a new TLS-enabled cluster and migrate.\n\nApply **defense in depth**: restrict network paths, keep access private, and use **least privilege** IAM to reduce blast radius.", + "Url": "https://hub.prowler.com/check/dynamodb_accelerator_cluster_in_transit_encryption_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_multi_az/dynamodb_accelerator_cluster_multi_az.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_multi_az/dynamodb_accelerator_cluster_multi_az.metadata.json index a39e2ae9bf..25497712f3 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_multi_az/dynamodb_accelerator_cluster_multi_az.metadata.json +++ b/prowler/providers/aws/services/dynamodb/dynamodb_accelerator_cluster_multi_az/dynamodb_accelerator_cluster_multi_az.metadata.json @@ -1,30 +1,38 @@ { "Provider": "aws", "CheckID": "dynamodb_accelerator_cluster_multi_az", - "CheckTitle": "Check if DynamoDB Accelerator (DAX) clusters have nodes in multiple availability zones.", - "CheckType": [], + "CheckTitle": "DynamoDB Accelerator (DAX) cluster has nodes in multiple Availability Zones", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Effects/Denial of Service" + ], "ServiceName": "dynamodb", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:dax:region:account-id:cache/table-name", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "This control checks whether an Amazon DynamoDB Accelerator (DAX) cluster has nodes in multiple availability zones.", - "Risk": "Without DAX nodes in multiple availability zones (AZ) the nodes are at risk of interruption if an AZ disruption occurs.", - "RelatedUrl": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAX.concepts.cluster.html#DAX.concepts.regions-and-azs", + "Description": "**Amazon DynamoDB Accelerator (DAX)** cluster node placement across **Availability Zones** is evaluated. Clusters with nodes in more than one AZ within the Region are recognized as multi-AZ; clusters whose nodes reside in a single AZ are recognized as single-AZ.", + "Risk": "Without **multi-AZ DAX nodes**, an AZ outage or primary node failure can render the cache **unavailable**, harming **availability** and causing **latency spikes** and **throttling** as load shifts to DynamoDB. Loss of caching can drive higher costs and trigger **timeout cascades** in read-heavy workloads.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.icompaas.com/support/solutions/articles/62000233618-ensure-dynamodb-accelerator-dax-clusters-have-nodes-in-multiple-availability-zones", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAX.concepts.cluster.html#DAX.concepts.regions-and-azs", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAX.create-cluster.console.html" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "CLI": "aws dax increase-replication-factor --cluster-name --new-replication-factor 2 --availability-zones ", + "NativeIaC": "```yaml\nResources:\n DAXCluster:\n Type: AWS::DAX::Cluster\n Properties:\n ClusterName: \n IAMRoleARN: \n NodeType: \n ReplicationFactor: 2 # CRITICAL: at least 2 nodes so nodes can be placed in multiple AZs\n SubnetGroupName: \n AvailabilityZones: # CRITICAL: specify multiple AZs to ensure multi-AZ placement\n - \n - \n```", + "Other": "1. In AWS Console, go to DynamoDB > DAX > Subnet groups and ensure the subnet group used by the cluster includes subnets from at least two Availability Zones; save if you add one.\n2. Go to DynamoDB > DAX > Clusters, select , and choose Modify.\n3. Set Cluster size to 2 or more.\n4. In Availability Zones (or node placement), select at least two different AZs.\n5. Save changes and wait until status is Available, then confirm nodes show multiple AZs in Cluster details.", + "Terraform": "```hcl\nresource \"aws_dax_cluster\" \"example\" {\n cluster_name = \"\"\n node_type = \"\"\n replication_factor = 2 # CRITICAL: at least 2 nodes to allow multi-AZ\n iam_role_arn = \"\"\n subnet_group_name = \"\"\n availability_zones = [\"\", \"\"] # CRITICAL: ensures nodes are in multiple AZs\n}\n```" }, "Recommendation": { - "Text": "Create a DAX cluster with nodes in multiple availability zones.", - "Url": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAX.concepts.cluster.html#DAX.concepts.regions-and-azs" + "Text": "Deploy **DAX clusters** with at least `3` nodes spread across distinct **Availability Zones** to ensure fault tolerance. Use subnet groups spanning multiple AZs, access via the cluster endpoint, and validate **failover** regularly. Monitor capacity to avoid single-AZ or single-node dependencies.", + "Url": "https://hub.prowler.com/check/dynamodb_accelerator_cluster_multi_az" } }, "Categories": [ - "redundancy" + "resilience" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_table_autoscaling_enabled/dynamodb_table_autoscaling_enabled.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_table_autoscaling_enabled/dynamodb_table_autoscaling_enabled.metadata.json index bb77b56de1..17b9e81f99 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_table_autoscaling_enabled/dynamodb_table_autoscaling_enabled.metadata.json +++ b/prowler/providers/aws/services/dynamodb/dynamodb_table_autoscaling_enabled/dynamodb_table_autoscaling_enabled.metadata.json @@ -1,31 +1,39 @@ { "Provider": "aws", "CheckID": "dynamodb_table_autoscaling_enabled", - "CheckTitle": "Check if DynamoDB tables automatically scale capacity with demand.", + "CheckTitle": "DynamoDB table uses on-demand capacity or has auto scaling enabled for read and write capacity units", "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices", + "Effects/Denial of Service", + "Effects/Resource Consumption" ], "ServiceName": "dynamodb", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:dynamodb:region:account-id:table/table-name", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsDynamoDbTable", - "Description": "This check ensures that DynamoDB tables can scale their read and write capacity as needed, either using on-demand capacity mode or provisioned mode with auto scaling configured.", - "Risk": "If DynamoDB tables do not automatically scale capacity with demand, they may experience throttling exceptions, leading to reduced availability and performance of applications.", - "RelatedUrl": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AutoScaling.Console.html#AutoScaling.Console.ExistingTable", + "Description": "**DynamoDB tables** use **automatic capacity scaling** via `on-demand` mode or `PROVISIONED` mode with **auto scaling** enabled for both `read` and `write` capacity units.\n\nProvisioned tables are evaluated for scaling on both dimensions.", + "Risk": "**Insufficient capacity scaling** causes throttling that degrades **availability** and increases latency.\n\nSustained throttling can trigger retry storms, timeouts, and backlogs, risking missed writes or out-of-order processing that impacts **data integrity** and drives **operational costs**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/dynamodb-controls.html#dynamodb-1", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AutoScaling.Console.html#AutoScaling.Console.ExistingTable" + ], "Remediation": { "Code": { "CLI": "aws dynamodb update-table --table-name --billing-mode PAY_PER_REQUEST", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/dynamodb-controls.html#dynamodb-1", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: Set table to on-demand capacity\nResources:\n :\n Type: AWS::DynamoDB::Table\n Properties:\n AttributeDefinitions:\n - AttributeName: id\n AttributeType: S\n KeySchema:\n - AttributeName: id\n KeyType: HASH\n BillingMode: PAY_PER_REQUEST # Critical: enables on-demand capacity to pass the control\n```", + "Other": "1. Open the AWS console and go to DynamoDB\n2. Click Tables and select your table\n3. Open the Additional settings tab and click Edit in Read/write capacity\n4. Set Capacity mode to On-demand (PAY_PER_REQUEST)\n5. Click Save", + "Terraform": "```hcl\n# DynamoDB table with on-demand capacity\nresource \"aws_dynamodb_table\" \"\" {\n name = \"\"\n hash_key = \"id\"\n\n attribute {\n name = \"id\"\n type = \"S\"\n }\n\n billing_mode = \"PAY_PER_REQUEST\" # Critical: enables on-demand capacity to pass the control\n}\n```" }, "Recommendation": { - "Text": "Enable DynamoDB automatic scaling on existing tables by configuring on-demand capacity mode or provisioned mode with auto scaling.", - "Url": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AutoScaling.Console.html#AutoScaling.Console.ExistingTable" + "Text": "Adopt **elastic capacity**: prefer `on-demand` for unpredictable traffic, or use `PROVISIONED` with **auto scaling** on both reads and writes.\n\nDefine safe utilization targets and bounds, monitor consumption, and plan for bursts to maintain **availability** and **resilience** over manual fixed throughput.", + "Url": "https://hub.prowler.com/check/dynamodb_table_autoscaling_enabled" } }, - "Categories": [], + "Categories": [ + "resilience" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.metadata.json index 1ab8b56140..2c18fa16aa 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.metadata.json +++ b/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.metadata.json @@ -1,32 +1,39 @@ { "Provider": "aws", "CheckID": "dynamodb_table_cross_account_access", - "CheckTitle": "DynamoDB tables should not be accessible from other AWS accounts", + "CheckTitle": "DynamoDB table resource-based policy does not allow cross-account access", "CheckType": [ - "Infrastructure Security" + "Software and Configuration Checks/AWS Security Best Practices", + "TTPs/Initial Access/Unauthorized Access", + "Effects/Data Exposure" ], "ServiceName": "dynamodb", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:dynamodb:region:account-id:table/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsDynamoDbTable", - "Description": "This check determines if the DynamoDB table is accessible from other AWS accounts.", - "Risk": "If the DynamoDB table is accessible from other AWS accounts, it may lead to unauthorized access to the data stored in the table.", - "RelatedUrl": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/access-control-resource-based.html", + "Description": "**DynamoDB tables** are evaluated for **resource-based policies** that permit cross-account or public principals.\n\nTables without a resource policy, or with policies restricted to the same account, are identified as isolated configurations.", + "Risk": "Allowing other accounts to access a table affects:\n- **Confidentiality**: unauthorized reads/data exfiltration\n- **Integrity**: writes or deletes by external principals\n- **Availability**: capacity exhaustion and throttling\n- **Cost**: owner pays for external requests\n\nIf public principals are allowed, exposure can be unrestricted.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.icompaas.com/support/solutions/articles/62000233614-ensure-dynamodb-tables-should-not-be-accessible-from-other-aws-accounts", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/access-control-resource-based.html", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-bpa-rbp.html" + ], "Remediation": { "Code": { "CLI": "aws dynamodb delete-resource-policy --resource-arn ", "NativeIaC": "", - "Other": "", + "Other": "1. Open the AWS Console and go to DynamoDB > Tables\n2. Select and open the Permissions tab\n3. In Resource-based policy, click Delete policy and confirm\n4. Save changes to remove any cross-account access", "Terraform": "" }, "Recommendation": { - "Text": "Ensure that the DynamoDB table is not accessible from other AWS accounts.", - "Url": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-bpa-rbp.html" + "Text": "Apply **least privilege**:\n- Avoid cross-account data access; *if required*, allow only named principals\n- Constrain with `aws:PrincipalOrgID`, `aws:SourceVpc`, `aws:PrincipalArn`; add `Deny` guardrails\n- Enable **Block Public Access** and monitor with **IAM Access Analyzer**", + "Url": "https://hub.prowler.com/check/dynamodb_table_cross_account_access" } }, "Categories": [ - "trustboundaries" + "trust-boundaries" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_table_deletion_protection_enabled/dynamodb_table_deletion_protection_enabled.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_table_deletion_protection_enabled/dynamodb_table_deletion_protection_enabled.metadata.json index 5516e61c76..28c5ab7c89 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_table_deletion_protection_enabled/dynamodb_table_deletion_protection_enabled.metadata.json +++ b/prowler/providers/aws/services/dynamodb/dynamodb_table_deletion_protection_enabled/dynamodb_table_deletion_protection_enabled.metadata.json @@ -1,31 +1,39 @@ { "Provider": "aws", "CheckID": "dynamodb_table_deletion_protection_enabled", - "CheckTitle": "Check if DynamoDB tables have deletion protection enabled.", + "CheckTitle": "DynamoDB table has deletion protection enabled", "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Effects/Data Destruction" ], "ServiceName": "dynamodb", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:dynamodb:region:account-id:table/table-name", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsDynamoDbTable", - "Description": "This control checks whether an Amazon DynamoDB table has deletion protection enabled to prevent accidental deletion during regular table management operations.", - "Risk": "If deletion protection is not enabled, a DynamoDB table could be accidentally deleted, leading to data loss and potential disruption of business operations.", - "RelatedUrl": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.Basics.html#WorkingWithTables.Basics.DeletionProtection", + "Description": "**DynamoDB tables** have **deletion protection** enabled via the `deletion protection` setting, meaning delete operations require this setting to be disabled first", + "Risk": "Without **deletion protection**, tables can be removed by authorized actions or misconfigured automation, causing irrecoverable data loss and service outage. This impacts **integrity** and **availability**, and increases the blast radius of compromised credentials or mistaken runbooks.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/dynamodb-controls.html#dynamodb-6", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.Basics.html#WorkingWithTables.Basics.DeletionProtection" + ], "Remediation": { "Code": { - "CLI": "aws dynamodb update-table --table-name --deletion-protection-enabled", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/dynamodb-controls.html#dynamodb-6", - "Terraform": "" + "CLI": "aws dynamodb update-table --table-name --deletion-protection-enabled", + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::DynamoDB::Table\n Properties:\n DeletionProtectionEnabled: true # CRITICAL: Enables deletion protection to prevent table deletion\n```", + "Other": "1. Open the AWS Management Console and go to DynamoDB\n2. Select the table\n3. Choose Additional settings\n4. Enable Deletion protection\n5. Save changes", + "Terraform": "```hcl\nresource \"aws_dynamodb_table\" \"\" {\n name = \"\"\n hash_key = \"id\"\n\n attribute {\n name = \"id\"\n type = \"S\"\n }\n\n deletion_protection_enabled = true # CRITICAL: Prevents accidental table deletion\n}\n```" }, "Recommendation": { - "Text": "Enable deletion protection for your DynamoDB tables to prevent accidental deletion.", - "Url": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.Basics.html#WorkingWithTables.Basics.DeletionProtection" + "Text": "Enable **deletion protection** on critical tables.\n- Enforce **least privilege** to restrict who can modify this setting\n- Require change control to disable it before planned deletes\n- Combine with **PITR** and backups for defense in depth\n- Use automation to make this the default for new tables", + "Url": "https://hub.prowler.com/check/dynamodb_table_deletion_protection_enabled" } }, - "Categories": [], + "Categories": [ + "resilience" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_table_protected_by_backup_plan/dynamodb_table_protected_by_backup_plan.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_table_protected_by_backup_plan/dynamodb_table_protected_by_backup_plan.metadata.json index 663c7f7e84..af18daf064 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_table_protected_by_backup_plan/dynamodb_table_protected_by_backup_plan.metadata.json +++ b/prowler/providers/aws/services/dynamodb/dynamodb_table_protected_by_backup_plan/dynamodb_table_protected_by_backup_plan.metadata.json @@ -1,32 +1,38 @@ { "Provider": "aws", "CheckID": "dynamodb_table_protected_by_backup_plan", - "CheckTitle": "Check if DynamoDB tables are included in a backup plan.", + "CheckTitle": "DynamoDB table is protected by a backup plan", "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" ], "ServiceName": "dynamodb", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:dynamodb:region:account-id:table/table-name", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsDynamoDbTable", - "Description": "This control checks whether an Amazon DynamoDB table is covered by a backup plan. The control fails if the DynamoDB table isn't included in a backup plan.", - "Risk": "If a DynamoDB table is not covered by a backup plan, data loss may occur due to accidental deletion, corruption, or unexpected failure, compromising the resilience of your application.", - "RelatedUrl": "https://docs.aws.amazon.com/aws-backup/latest/devguide/assigning-resources.html", + "Description": "**DynamoDB tables** are evaluated for inclusion in an **AWS Backup backup plan** through resource assignments, including explicit tables, resource-type wildcards, or all-resources coverage.\n\nThe result indicates whether a table is governed by scheduled backups and retention defined by the plan.", + "Risk": "Without a backup plan, table data lacks governed copies, harming **availability** and **integrity**. Accidental deletes, corrupt writes, or malicious actions can become unrecoverable, and RPO/RTO worsen. You also forfeit cross-Region/account copies and immutability features, increasing downtime and data loss.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/aws-backup/latest/devguide/assigning-resources.html", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/CreateBackupAWS.html", + "https://aws.amazon.com/blogs/database/set-up-scheduled-backups-for-amazon-dynamodb-using-aws-backup/" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/dynamodb-controls.html#dynamodb-4", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: Add DynamoDB tables to an AWS Backup plan\nResources:\n BackupPlan:\n Type: AWS::Backup::BackupPlan\n Properties:\n BackupPlan:\n BackupPlanName: \n BackupPlanRule:\n - RuleName: r\n TargetBackupVault: Default\n\n BackupSelection:\n Type: AWS::Backup::BackupSelection\n Properties:\n BackupPlanId: !Ref BackupPlan\n BackupSelection:\n SelectionName: \n IamRoleArn: \n Resources:\n - arn:aws:dynamodb:*:*:table/* # CRITICAL: adds all DynamoDB tables to the backup plan, making them protected\n```", + "Other": "1. In the AWS Backup console, go to Settings > Configure resources and enable DynamoDB, then Confirm\n2. Go to Backup plans > Create backup plan > Build a new plan\n3. Enter a plan name, set Rule name to any value, set Backup vault to Default, and Create plan\n4. On the plan page, choose Assign resources\n5. Enter a Resource assignment name, set IAM role to Default role, select your DynamoDB table, and choose Assign resources", + "Terraform": "```hcl\n# Terraform: Add DynamoDB tables to an AWS Backup plan\nresource \"aws_backup_plan\" \"\" {\n name = \"\"\n rule {\n rule_name = \"r\"\n target_vault_name = \"Default\"\n }\n}\n\ndata \"aws_iam_role\" \"\" {\n name = \"AWSServiceRoleForBackup\"\n}\n\nresource \"aws_backup_selection\" \"\" {\n name = \"\"\n plan_id = aws_backup_plan..id\n iam_role_arn = data.aws_iam_role..arn\n resources = [\n \"arn:aws:dynamodb:*:*:table/*\" # CRITICAL: adds all DynamoDB tables to the backup plan, making them protected\n ]\n}\n```" }, "Recommendation": { - "Text": "Ensure that all active DynamoDB tables are included in a backup plan to safeguard against data loss.", - "Url": "https://docs.aws.amazon.com/aws-backup/latest/devguide/assigning-resources.html" + "Text": "Place all critical tables under an **AWS Backup backup plan** following **defense in depth** and **least privilege**:\n- Use tag-based assignments for coverage at scale\n- Define schedules, retention, and cross-Region/account copies\n- Enable **Vault Lock** for immutability\n- Regularly test restores and restrict backup deletion", + "Url": "https://hub.prowler.com/check/dynamodb_table_protected_by_backup_plan" } }, "Categories": [ - "redundancy" + "resilience" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_tables_kms_cmk_encryption_enabled/dynamodb_tables_kms_cmk_encryption_enabled.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_tables_kms_cmk_encryption_enabled/dynamodb_tables_kms_cmk_encryption_enabled.metadata.json index 935834773c..c419aa472d 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_tables_kms_cmk_encryption_enabled/dynamodb_tables_kms_cmk_encryption_enabled.metadata.json +++ b/prowler/providers/aws/services/dynamodb/dynamodb_tables_kms_cmk_encryption_enabled/dynamodb_tables_kms_cmk_encryption_enabled.metadata.json @@ -1,28 +1,34 @@ { "Provider": "aws", "CheckID": "dynamodb_tables_kms_cmk_encryption_enabled", - "CheckTitle": "Check if DynamoDB table has encryption at rest enabled using CMK KMS.", + "CheckTitle": "DynamoDB table is encrypted at rest with AWS KMS", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices" ], "ServiceName": "dynamodb", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:dynamodb:region:account-id:table/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsDynamoDbTable", - "Description": "Check if DynamoDB table has encryption at rest enabled using CMK KMS.", - "Risk": "All user data stored in Amazon DynamoDB is fully encrypted at rest. This functionality helps reduce the operational burden and complexity involved in protecting sensitive data.", - "RelatedUrl": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html", + "Description": "**DynamoDB tables** use **AWS KMS keys** (`KMS`) for encryption at rest instead of the default service-owned key", + "Risk": "Relying on the default service-owned key reduces control over **confidentiality**: no custom key policies, limited auditability, and no independent rotation or disablement. This weakens least-privilege enforcement and incident response, and can impede meeting mandates that require customer-controlled keys.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.prowler.com/checks/aws/general-policies/ensure-that-dynamodb-tables-are-encrypted#terraform", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "https://docs.prowler.com/checks/aws/general-policies/ensure-that-dynamodb-tables-are-encrypted#terraform" + "CLI": "aws dynamodb update-table --table-name --sse-specification Enabled=true,SSEType=KMS", + "NativeIaC": "```yaml\n# CloudFormation: Enable KMS encryption on a DynamoDB table\nResources:\n :\n Type: AWS::DynamoDB::Table\n Properties:\n AttributeDefinitions:\n - AttributeName: id\n AttributeType: S\n KeySchema:\n - AttributeName: id\n KeyType: HASH\n BillingMode: PAY_PER_REQUEST\n SSESpecification:\n SSEEnabled: true # Critical: enables KMS-based encryption\n SSEType: KMS # Critical: switches from DEFAULT to AWS KMS\n```", + "Other": "1. Open the AWS Management Console and go to DynamoDB\n2. Select your table\n3. In Table details, find Encryption at rest and click Edit\n4. Select AWS KMS: choose AWS managed key (alias/aws/dynamodb) or a customer managed key\n5. Click Save", + "Terraform": "```hcl\nresource \"aws_dynamodb_table\" \"\" {\n name = \"\"\n billing_mode = \"PAY_PER_REQUEST\"\n hash_key = \"id\"\n\n attribute {\n name = \"id\"\n type = \"S\"\n }\n\n server_side_encryption {\n enabled = true # Critical: enables AWS KMS encryption (uses AWS managed key if no key ARN provided)\n }\n}\n```" }, "Recommendation": { - "Text": "Specify an encryption key when you create a new table or switch the encryption keys on an existing table by using the AWS Management Console.", - "Url": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html" + "Text": "Encrypt tables with **KMS keys** in your account-prefer **customer-managed keys** for sensitive data.\n\n- Enforce least-privilege key policies and scope grants\n- Enable rotation and monitor key usage\n- Separate duties for key admins vs data users\n- Restrict which principals can use the key for DynamoDB", + "Url": "https://hub.prowler.com/check/dynamodb_tables_kms_cmk_encryption_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_tables_pitr_enabled/dynamodb_tables_pitr_enabled.metadata.json b/prowler/providers/aws/services/dynamodb/dynamodb_tables_pitr_enabled/dynamodb_tables_pitr_enabled.metadata.json index 9fc7112c6e..4ba8d96275 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_tables_pitr_enabled/dynamodb_tables_pitr_enabled.metadata.json +++ b/prowler/providers/aws/services/dynamodb/dynamodb_tables_pitr_enabled/dynamodb_tables_pitr_enabled.metadata.json @@ -1,31 +1,38 @@ { "Provider": "aws", "CheckID": "dynamodb_tables_pitr_enabled", - "CheckTitle": "Check if DynamoDB tables point-in-time recovery (PITR) is enabled.", + "CheckTitle": "DynamoDB table has point-in-time recovery (PITR) enabled", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Effects/Data Destruction" ], "ServiceName": "dynamodb", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:dynamodb:region:account-id:table/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsDynamoDbTable", - "Description": "Check if DynamoDB tables point-in-time recovery (PITR) is enabled.", - "Risk": "If the DynamoDB Table does not have point-in-time recovery enabled, it is vulnerable to accidental write or delete operations.", - "RelatedUrl": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html", + "Description": "**DynamoDB tables** have **Point-in-Time Recovery** (`PITR`) enabled", + "Risk": "Without **PITR**, unintended or malicious writes/deletes cannot be precisely rolled back, leading to permanent data loss and corrupted state. Failures from buggy deployments, compromised credentials, or faulty batch jobs reduce data **integrity** and **availability**, and prolong incident recovery and forensic analysis.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html", + "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery.Tutorial.html" + ], "Remediation": { "Code": { "CLI": "aws dynamodb update-continuous-backups --table-name --point-in-time-recovery-specification PointInTimeRecoveryEnabled=true", - "NativeIaC": "https://docs.prowler.com/checks/aws/general-policies/general_6#cloudformation--serverless", - "Other": "", - "Terraform": "https://docs.prowler.com/checks/aws/general-policies/general_6#terraform" + "NativeIaC": "```yaml\n# CloudFormation: enable PITR on a DynamoDB table\nResources:\n :\n Type: AWS::DynamoDB::Table\n Properties:\n PointInTimeRecoverySpecification:\n PointInTimeRecoveryEnabled: true # Critical: enables Point-in-Time Recovery (PITR)\n```", + "Other": "1. Open the AWS Management Console and go to DynamoDB\n2. Select your table and open the Backups tab\n3. Click Edit in the Point-in-time recovery section and choose Turn on point-in-time recovery\n4. Click Save", + "Terraform": "```hcl\n# Enable PITR on a DynamoDB table\nresource \"aws_dynamodb_table\" \"\" {\n name = \"\"\n billing_mode = \"PAY_PER_REQUEST\"\n hash_key = \"id\"\n\n attribute {\n name = \"id\"\n type = \"S\"\n }\n\n point_in_time_recovery {\n enabled = true # Critical: enables PITR\n }\n}\n```" }, "Recommendation": { - "Text": "Enable point-in-time recovery, this is not enabled by default.", - "Url": "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html" + "Text": "Enable **PITR** on critical tables and set a recovery window aligned to your RPO (1-35 days). Enforce **least privilege** on who can modify backup settings. Regularly test restores and monitor backup status. Embed PITR in IaC and change control for consistency, and apply **defense in depth** with on-demand backups for key milestones.", + "Url": "https://hub.prowler.com/check/dynamodb_tables_pitr_enabled" } }, - "Categories": [], + "Categories": [ + "resilience" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Data Protection"