> ## 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.

# Notebook Data Should Be Encrypted

### More Info:

Ensure that the data stored on Machine Learning (ML) storage volumes attached to your AWS SageMaker notebook instances is encrypted in order to meet regulatory requirements and protect your SageMaker data at rest. SageMaker is a fully-managed AWS service that enables developers and data engineers to quickly and easily build, train and deploy machine learning models at any scale. An AWS SageMaker notebook instance is a fully managed ML instance that is running the Jupyter Notebook open-source web application.

### Risk Level

High

### Address

Cost optimization, Operational Maturity, Security

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS AWS
* CIS Critical Security Controls v8
* CMMC 2.0
* CSA Cloud Controls Matrix v4
* Cloudanix Best Practice
* DPDPA
* Digital Operational Resilience Act (EU)
* GDPR
* HIPAA
* ISO/IEC 27017
* ISO/IEC 27018
* ISO/IEC 27701
* KSA PDPL
* MAS Technology Risk Management (Singapore)
* MITRE ATT\&CK (Cloud)
* NIS2 Directive
* NIST
* NIST SP 800-171
* NYDFS 23 NYCRR 500
* SWIFT Customer Security Controls Framework
* Sarbanes-Oxley IT General Controls
* Securities and Exchange Board of India (SEBI) - Cloud Security Adoption Framework
* UK NCSC Cyber Assessment Framework

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        For DynamoDB, “notebook data” translates to DynamoDB table data needing encryption at rest.

        DynamoDB already encrypts all table data at rest by default with an AWS-owned KMS key. If your requirement is stricter (e.g., must use a customer-managed KMS key), follow these steps in the AWS Console:

        ***

        ### 1. Confirm Encryption Status of the Table

        1. Sign in to the **AWS Management Console**.
        2. Go to **DynamoDB**.
        3. In the left menu, click **Tables**.
        4. Click the specific table.
        5. Choose the **Additional settings** or **Overview** tab (depending on UI version).
        6. Look for **Encryption at rest**:
           * It should show something like:
             * **Encryption type**: AWS owned key\
               or
             * **KMS key**: alias/aws/dynamodb\
               or
             * **KMS key**: `alias/your-cmk-alias`

        If encryption is already enabled (it always is), you only need remediation if your policy requires a **customer-managed KMS key (CMK)**.

        ***

        ### 2. (If Required) Create a Customer-Managed KMS Key

        1. In the console, open **Key Management Service (KMS)**.
        2. Click **Customer managed keys** → **Create key**.
        3. Key type: **Symmetric**.
        4. Key usage: **Encrypt and decrypt**.
        5. Set **Alias** (e.g., `alias/dynamodb-notebook-data`).
        6. Configure **Key administrators** and **Key users**:
           * Ensure the IAM roles/services that use DynamoDB have permission to use this key.
        7. Finish key creation.

        ***

        ### 3. Update DynamoDB Table to Use the Customer-Managed KMS Key

        > Note: DynamoDB encryption with AWS-owned/AWS-managed key is default; using a **customer-managed key** is an optional enhancement. UI labels may differ slightly between regions/UI versions but the flow is similar.

        1. Go back to **DynamoDB → Tables**.
        2. Select the table.
        3. Go to **Additional settings** or **Table details**.
        4. Find the **Encryption at rest** section.
        5. Click **Edit** (or **Manage encryption**).
        6. Change encryption from **AWS owned key** or default key to **Customer managed key**.
        7. From the dropdown, choose your new KMS key alias (e.g., `alias/dynamodb-notebook-data`).
        8. Save/Apply the change.

        DynamoDB will handle re-encryption transparently; no application changes are needed.

        ***

        ### 4. Validate Compliance

        1. Re-open the table **Details/Additional settings**.
        2. Confirm:
           * **Encryption at rest** is **Enabled**.
           * **KMS key** now references your customer-managed CMK alias.
        3. Optionally, in **KMS → Customer managed keys**, open the key and check **Key usage** / **CloudTrail** to see DynamoDB using the key.

        ***

        If your policy only says “must be encrypted,” DynamoDB’s default (AWS-owned key) already satisfies that; the remediation is primarily confirming and documenting that encryption at rest is enabled and enforced for all DynamoDB tables storing notebook data.
      </Accordion>

      <Accordion title="Using CLI">
        Below are the minimal, step‑by‑step AWS CLI steps to ensure DynamoDB “Notebook Data” is encrypted at rest.

        ***

        ### 1. Identify the DynamoDB table(s)

        If you already know the table name, skip to step 2.

        ```bash theme={null}
        aws dynamodb list-tables
        ```

        Assume your table is called `notebook-data-table` (replace with your actual name).

        ***

        ### 2. Check current encryption status

        ```bash theme={null}
        aws dynamodb describe-table \
          --table-name notebook-data-table \
          --query "Table.SSEDescription"
        ```

        Look at:

        * `Status` (ENABLED, ENABLING, DISABLED)
        * `SSEType` (KMS)
        * `KMSMasterKeyArn` (if using a CMK)

        If `Status` is `DISABLED` or not present, encryption is not enabled.

        ***

        ### 3. (Optional) Choose or create a KMS key

        If you want to use an AWS-managed key for DynamoDB (simplest), skip to step 4.

        To create a customer-managed KMS key:

        ```bash theme={null}
        aws kms create-key \
          --description "CMK for DynamoDB Notebook Data Encryption" \
          --query "KeyMetadata.KeyId" \
          --output text
        ```

        Note the returned `KeyId` or ARN.\
        Ensure the key policy allows DynamoDB and relevant IAM principals to use it.

        ***

        ### 4. Enable encryption on the table

        #### Option A – Use AWS-owned key (default encryption)

        ```bash theme={null}
        aws dynamodb update-table \
          --table-name notebook-data-table \
          --sse-specification Enabled=true
        ```

        #### Option B – Use AWS-managed KMS key for DynamoDB

        ```bash theme={null}
        aws dynamodb update-table \
          --table-name notebook-data-table \
          --sse-specification Enabled=true,SSEType=KMS
        ```

        #### Option C – Use your own customer-managed KMS key

        Replace `<kms-key-arn-or-id>` with your key:

        ```bash theme={null}
        aws dynamodb update-table \
          --table-name notebook-data-table \
          --sse-specification Enabled=true,SSEType=KMS,KMSMasterKeyId=<kms-key-arn-or-id>
        ```

        ***

        ### 5. Confirm encryption is enabled

        Run again:

        ```bash theme={null}
        aws dynamodb describe-table \
          --table-name notebook-data-table \
          --query "Table.SSEDescription"
        ```

        You should see:

        * `Status`: `ENABLED`
        * `SSEType`: `KMS`
        * `KMSMasterKeyArn`: set (if using KMS)

        Once done, the DynamoDB table storing notebook data is encrypted at rest.
      </Accordion>

      <Accordion title="Using Python">
        To encrypt DynamoDB “notebook data” at rest, you need to ensure the DynamoDB table has Server-Side Encryption (SSE) enabled, preferably with a customer-managed KMS key. Below are step-by-step instructions using Python (boto3).

        ***

        ## 1. Prerequisites

        * `boto3` installed:
          ```bash theme={null}
          pip install boto3
          ```
        * AWS credentials configured (via `aws configure`, environment variables, or an IAM role).
        * IAM permissions for:
          * `dynamodb:DescribeTable`
          * `dynamodb:UpdateTable`
          * `kms:CreateKey` (if you’ll create a new CMK)
          * `kms:DescribeKey`
          * `kms:EnableKeyRotation`
          * `kms:PutKeyPolicy` (as needed)

        ***

        ## 2. (Optional) Create a customer-managed KMS key for DynamoDB

        If you want to use your own CMK instead of the AWS-owned key:

        ```python theme={null}
        import boto3

        kms = boto3.client('kms', region_name='us-east-1')  # choose your region

        response = kms.create_key(
            Description='CMK for encrypting DynamoDB notebook data',
            KeyUsage='ENCRYPT_DECRYPT',
            Origin='AWS_KMS'
        )

        cmk_arn = response['KeyMetadata']['Arn']
        print("Created KMS CMK:", cmk_arn)

        # (Optional but recommended) enable key rotation
        kms.enable_key_rotation(KeyId=cmk_arn)
        ```

        Keep `cmk_arn` – you’ll use it in the DynamoDB SSE config.

        ***

        ## 3. Check current encryption status of the DynamoDB table

        ```python theme={null}
        import boto3

        dynamodb = boto3.client('dynamodb', region_name='us-east-1')  # choose your region
        table_name = 'your-notebook-data-table'

        desc = dynamodb.describe_table(TableName=table_name)
        print(desc['Table'].get('SSEDescription', 'No SSEDescription found'))
        ```

        Look at:

        * `SSEDescription['Status']` (e.g., `ENABLED`, `ENABLING`, `DISABLED`)
        * `SSEDescription['SSEType']` (e.g., `KMS`)
        * `SSEDescription['KMSMasterKeyArn']` (if using CMK)

        ***

        ## 4. Enable or update server-side encryption on the table

        ### Option A – Use AWS owned key (simpler)

        ```python theme={null}
        dynamodb.update_table(
            TableName=table_name,
            SSESpecification={
                'Enabled': True,
                'SSEType': 'KMS'  # with no KMSMasterKeyId, DynamoDB uses the AWS owned key
            }
        )
        ```

        ### Option B – Use customer-managed CMK (more control)

        Use the `cmk_arn` from step 2:

        ```python theme={null}
        cmk_arn = 'arn:aws:kms:us-east-1:123456789012:key/your-key-id-or-arn'

        dynamodb.update_table(
            TableName=table_name,
            SSESpecification={
                'Enabled': True,
                'SSEType': 'KMS',
                'KMSMasterKeyId': cmk_arn
            }
        )
        ```

        ***

        ## 5. Wait for encryption to finish and verify

        ```python theme={null}
        import time

        while True:
            desc = dynamodb.describe_table(TableName=table_name)
            sse = desc['Table'].get('SSEDescription', {})
            status = sse.get('Status')
            print("SSE Status:", status)

            if status in ['ENABLED', 'UPDATING']:
                break
            time.sleep(5)

        print("Final SSEDescription:", sse)
        ```

        Ensure:

        * `Status` is `ENABLED`
        * `SSEType` is `KMS`
        * `KMSMasterKeyArn` is set (if using CMK)

        ***

        ## 6. Enforce encryption via IaC / policy (optional but recommended)

        To prevent future unencrypted tables:

        * Use IaC (CloudFormation/Terraform) with `SSESpecification` always set.
        * Add AWS Config rule `dynamodb-table-encryption-enabled` and remediate non-compliant tables with an automation script similar to the above.

        This ensures that all “notebook data” stored in DynamoDB is encrypted at rest.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "aws_kms_key" "SAGEMAKER_ENCRYPTION_KEY" {
          description         = "KMS key for SageMaker notebook volume encryption"
          enable_key_rotation = true

          # Optional: scope down key policy as required for your org
        }

        resource "aws_sagemaker_notebook_instance" "SAGEMAKER_NOTEBOOK" {
          # Substitute:
          # - NOTEBOOK_NAME with the desired SageMaker notebook instance name
          # - INSTANCE_TYPE with the SageMaker instance type (e.g., "ml.t3.medium")
          # - IAM_ROLE_ARN with the ARN of the SageMaker execution role that has KMS permissions
          name          = "NOTEBOOK_NAME"
          instance_type = "INSTANCE_TYPE"
          role_arn      = "IAM_ROLE_ARN"

          # This is the critical setting: enables encryption of the notebook's EBS volume
          kms_key_id = aws_kms_key.SAGEMAKER_ENCRYPTION_KEY.arn

          # Optionally mirror any existing networking configuration:
          # subnet_id         = "SUBNET_ID"
          # security_group_ids = ["SECURITY_GROUP_ID_1", "SECURITY_GROUP_ID_2"]
        }
        ```

        Changing `kms_key_id` on an existing `aws_sagemaker_notebook_instance` forces resource replacement: Terraform will destroy the current unencrypted notebook instance and create a new, encrypted one. This is destructive and irreversible, and any data on the original notebook’s volume must be backed up and restored manually to the new instance.

        To verify, `terraform plan` should show the current unencrypted `aws_sagemaker_notebook_instance` scheduled for `-/+` replacement, with the new resource including `kms_key_id = aws_kms_key.SAGEMAKER_ENCRYPTION_KEY.arn`.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://docs.aws.amazon.com/sagemaker/latest/dg/encryption-at-rest.html](https://docs.aws.amazon.com/sagemaker/latest/dg/encryption-at-rest.html)
