> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Ddb customer kms keys remediation

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Below are step‑by‑step console instructions to ensure DynamoDB tables use a customer‑managed KMS key (CMK) instead of the default AWS owned key.

        ***

        ## 1. Create (or Identify) a KMS CMK

        1. Sign in to the **AWS Management Console**.
        2. Go to **AWS Key Management Service (KMS)**:
           * In the search bar, type **KMS** and open **Key Management Service**.
        3. In the left pane, choose **Customer managed keys**.
        4. Click **Create key**.
        5. Configure the key:
           * **Key type**: Symmetric.
           * **Key usage**: Encrypt and decrypt.
           * Click **Next**.
        6. Set **Alias** (e.g., `alias/dynamodb-table-kms-key`), optional description.
        7. Configure **Key administrators** and **Key users**:
           * Make sure the IAM roles/users that manage/operate DynamoDB have permission to use this key.
        8. Finish the wizard:
           * Review and click **Finish** (or **Create key**).

        You now have a CMK that can be used by DynamoDB.

        ***

        ## 2. Update an Existing DynamoDB Table to Use the CMK

        1. Go to the **DynamoDB** console.
        2. In the left pane, click **Tables**.
        3. Click on the table you want to remediate.
        4. In the table’s page, choose the **Additional settings** / **Encryption** tab (exact label may vary slightly).
        5. Under **Encryption at rest**:
           * If it shows **AWS owned CMK**, click **Edit**.
        6. Select **Customer managed key**.
        7. In the dropdown, choose your CMK (e.g., `alias/dynamodb-table-kms-key`).
        8. Click **Save changes** / **Update**.

        The table’s encryption at rest will now use your CMK. Repeat for each non‑compliant table.

        ***

        ## 3. Ensure New Tables Use CMKs by Default

        There’s no single global default per service via console, so enforce this via process or templates:

        * When creating any new table in the **DynamoDB console**:
          1. Click **Create table**.
          2. In the **Table settings** / **Additional settings** section, find **Encryption at rest**.
          3. Choose **Customer managed key**.
          4. Select the CMK you created.
          5. Complete table creation.

        * Optionally, enforce via:
          * Standard CloudFormation/Terraform templates that specify `SSESpecification` with a KMS key.
          * IAM policies that restrict use of AWS owned keys for DynamoDB (advanced/optional).

        ***

        These steps will remediate the finding by ensuring DynamoDB tables use a KMS CMK for encryption at rest.
      </Accordion>

      <Accordion title="Using CLI">
        Below are the CLI steps to ensure a DynamoDB table uses a customer-managed KMS key (CMK) for encryption.

        ### 1. Identify the table and region

        Decide which table(s) to fix and the AWS Region (e.g., `us-east-1`).

        ```bash theme={null}
        TABLE_NAME="my-dynamodb-table"
        REGION="us-east-1"
        ```

        ***

        ### 2. Create (or choose) a KMS CMK

        #### 2.1 Create a new CMK (if you don’t already have one)

        ```bash theme={null}
        aws kms create-key \
          --description "CMK for DynamoDB encryption" \
          --key-usage ENCRYPT_DECRYPT \
          --origin AWS_KMS \
          --region $REGION
        ```

        Note the `KeyId` in the output.

        Optionally, give it an alias:

        ```bash theme={null}
        CMK_KEY_ID="<KeyId-from-previous-command>"

        aws kms create-alias \
          --alias-name "alias/dynamodb-cmk" \
          --target-key-id "$CMK_KEY_ID" \
          --region $REGION
        ```

        You can also reuse an existing CMK or alias, e.g. `alias/dynamodb-cmk`.

        ***

        ### 3. Update the DynamoDB table to use the CMK

        Use `update-table` and specify server-side encryption with KMS and your CMK (either KeyId or alias):

        ```bash theme={null}
        aws dynamodb update-table \
          --table-name "$TABLE_NAME" \
          --region "$REGION" \
          --sse-specification Enabled=true,SSEType=KMS,KMSMasterKeyId="alias/dynamodb-cmk"
        ```

        ***

        ### 4. Verify encryption settings

        ```bash theme={null}
        aws dynamodb describe-table \
          --table-name "$TABLE_NAME" \
          --region "$REGION" \
          --query "Table.SSEDescription"
        ```

        You should see something like:

        * `Status`: `ENABLED`
        * `SSEType`: `KMS`
        * `KMSMasterKeyArn`: your CMK ARN

        Repeat steps 3–4 for each non-compliant table.
      </Accordion>

      <Accordion title="Using Python">
        Below is a practical, step‑by‑step approach using Python (boto3) to ensure DynamoDB tables are encrypted with a customer-managed KMS key (CMK).

        ***

        ## 1. Prerequisites

        * Python 3.x
        * `boto3` installed:
          ```bash theme={null}
          pip install boto3
          ```
        * IAM permissions for:
          * `dynamodb:DescribeTable`, `dynamodb:UpdateTable`
          * `kms:DescribeKey`
        * A **KMS CMK ARN** you want to use (or create one in KMS console and copy its ARN).

        ***

        ## 2. Understand What You Need to Change

        You want each DynamoDB table to have:

        * `SSEEnabled = True`
        * `SSEType = "KMS"`
        * `KMSMasterKeyId = "<your-cmk-arn>"`

        This is done with `UpdateTable` and the `SSESpecification` parameter.

        ***

        ## 3. Python: Update a Single Table to Use CMK

        ```python theme={null}
        import boto3
        from botocore.exceptions import ClientError

        region = "us-east-1"  # change as needed
        table_name = "your-table-name"  # change as needed
        cmk_arn = "arn:aws:kms:us-east-1:123456789012:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

        dynamodb = boto3.client("dynamodb", region_name=region)

        def enable_kms_cmk_encryption(table_name, cmk_arn):
            try:
                # Describe current SSE settings
                resp = dynamodb.describe_table(TableName=table_name)
                sse_desc = resp["Table"].get("SSEDescription", {})

                already_ok = (
                    sse_desc.get("Status") in ("ENABLED", "UPDATING") and
                    sse_desc.get("SSEType") == "KMS" and
                    sse_desc.get("KMSMasterKeyArn") == cmk_arn
                )
                if already_ok:
                    print(f"Table {table_name} already uses CMK: {cmk_arn}")
                    return

                print(f"Updating table {table_name} to use CMK: {cmk_arn}")

                # Update SSE specification
                dynamodb.update_table(
                    TableName=table_name,
                    SSESpecification={
                        "Enabled": True,
                        "SSEType": "KMS",
                        "KMSMasterKeyId": cmk_arn,
                    },
                )

                print(f"Update initiated for {table_name}. Encryption change is asynchronous.")

            except ClientError as e:
                print(f"Error updating {table_name}: {e}")

        if __name__ == "__main__":
            enable_kms_cmk_encryption(table_name, cmk_arn)
        ```

        ***

        ## 4. Python: Bulk Remediation for All Tables in a Region

        ```python theme={null}
        import boto3
        from botocore.exceptions import ClientError

        region = "us-east-1"  # change as needed
        cmk_arn = "arn:aws:kms:us-east-1:123456789012:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

        dynamodb = boto3.client("dynamodb", region_name=region)

        def list_all_tables():
            tables = []
            paginator = dynamodb.get_paginator("list_tables")
            for page in paginator.paginate():
                tables.extend(page.get("TableNames", []))
            return tables

        def remediate_tables_with_cmk(cmk_arn):
            for table_name in list_all_tables():
                try:
                    resp = dynamodb.describe_table(TableName=table_name)
                    sse_desc = resp["Table"].get("SSEDescription", {})
                    status = sse_desc.get("Status")
                    sse_type = sse_desc.get("SSEType")
                    current_key = sse_desc.get("KMSMasterKeyArn")

                    # Skip if already using this CMK
                    if status in ("ENABLED", "UPDATING") and sse_type == "KMS" and current_key == cmk_arn:
                        print(f"[SKIP] {table_name} already uses CMK: {cmk_arn}")
                        continue

                    print(f"[UPDATE] {table_name} -> CMK: {cmk_arn}")
                    dynamodb.update_table(
                        TableName=table_name,
                        SSESpecification={
                            "Enabled": True,
                            "SSEType": "KMS",
                            "KMSMasterKeyId": cmk_arn,
                        },
                    )
                except ClientError as e:
                    print(f"[ERROR] {table_name}: {e}")

        if __name__ == "__main__":
            remediate_tables_with_cmk(cmk_arn)
        ```

        ***

        ## 5. KMS Key Policy Considerations

        Ensure the CMK key policy allows DynamoDB to use it. A minimal example statement (add to CMK key policy):

        ```json theme={null}
        {
          "Sid": "AllowDynamoDBUseOfTheKey",
          "Effect": "Allow",
          "Principal": {
            "Service": "dynamodb.amazonaws.com"
          },
          "Action": [
            "kms:Encrypt",
            "kms:Decrypt",
            "kms:ReEncrypt*",
            "kms:GenerateDataKey*",
            "kms:DescribeKey"
          ],
          "Resource": "*"
        }
        ```

        Also ensure your IAM principal (user/role running the script) has `kms:DescribeKey` and, if needed, `kms:ListAliases`.

        ***

        If you share any specific error you hit while running this, I can adjust the code or permissions for your case.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "aws_kms_key" "dynamodb_cmk" {
          description             = "CMK for DynamoDB table encryption"
          deletion_window_in_days = 30

          # Optional: restrict usage via key policy, tags, etc.
          # See AWS KMS docs for hardening guidance.
        }

        resource "aws_dynamodb_table" "this" {
          name         = "YOUR_TABLE_NAME"          # replace with your table name
          billing_mode = "PAY_PER_REQUEST"

          hash_key = "PARTITION_KEY_NAME"           # replace with your partition key
          attribute {
            name = "PARTITION_KEY_NAME"             # replace with your partition key
            type = "S"                              # adjust type as needed
          }

          server_side_encryption {
            enabled     = true
            kms_key_arn = aws_kms_key.dynamodb_cmk.arn
          }

          # ...any other existing arguments (tags, range key, GSIs, LSIs, etc.)
        }
        ```

        Changing `server_side_encryption` to use a CMK is an in-place update for existing DynamoDB tables and does not force replacement.

        To verify, `terraform plan` should show an in-place update (`~`) on the `aws_dynamodb_table` resource adding/updating the `server_side_encryption` block with `enabled = true` and `kms_key_arn = arn:aws:kms:...`.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
