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

# KMS Keys Should Not Be Exposed

### More Info:

Any publicly accessible AWS Key Management Service master keys should be identified and their access policy should be updated in order to stop any unsigned requests made to these resources.

### Risk Level

High

### Address

Security

### Compliance Standards

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

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Sure, here are the step by step instructions to remediate this misconfiguration in AWS using the AWS console:

        1. Log in to the AWS Management Console.
        2. Go to the AWS KMS console.
        3. Click on the "Aliases" tab.
        4. Select the KMS key that is exposed.
        5. Click on the "Key Policy" button.
        6. Review the Key Policy to ensure that it is not exposing the KMS key.
        7. If the Key Policy is exposing the KMS key, click on the "Edit" button.
        8. Update the Key Policy to remove any permissions that expose the KMS key.
        9. Click on the "Review and Save" button.
        10. Review the changes made to the Key Policy.
        11. Click on the "Save Changes" button to save the updated Key Policy.

        Once you have completed these steps, the KMS key will no longer be exposed and the misconfiguration will be remediated.

        #
      </Accordion>

      <Accordion title="Using CLI">
        To remediate the issue of KMS Keys being exposed in AWS, you can follow the below steps using AWS CLI:

        1. List all the KMS keys in your AWS account by running the following command:

        ```
        aws kms list-keys
        ```

        2. Identify the KMS key(s) that are exposed and note down their Key IDs.

        3. Remove the Key Policy from the KMS key(s) by running the following command:

        ```
        aws kms put-key-policy --key-id <key-id> --policy-name default --policy "{}"
        ```

        Replace `<key-id>` with the Key ID of the KMS key that you want to remediate.

        4. Verify that the Key Policy has been removed by running the following command:

        ```
        aws kms get-key-policy --key-id <key-id> --policy-name default
        ```

        Replace `<key-id>` with the Key ID of the KMS key that you remediated. This command should return an empty policy.

        5. Repeat steps 3 and 4 for all the exposed KMS keys in your AWS account.

        By following the above steps, you can remediate the issue of KMS Keys being exposed in AWS.
      </Accordion>

      <Accordion title="Using Python">
        To remediate the issue of KMS Keys being exposed in AWS using Python, you can follow the below steps:

        Step 1: Identify the KMS keys that are exposed.

        You can use the AWS CLI command `aws kms list-keys` to list all the KMS keys in your AWS account. Then, you can use the `aws kms describe-key` command to get the details of each key and check if any of them are exposed.

        Step 2: Revoke the key policy that is exposing the KMS key.

        You can use the `aws kms put-key-policy` command to revoke the key policy that is exposing the KMS key. Here's an example of how you can do it:

        ```python theme={null}
        import boto3

        # Create a KMS client
        kms = boto3.client('kms')

        # Specify the key ID and the policy name
        key_id = 'your_key_id'
        policy_name = 'your_policy_name'

        # Get the current key policy
        key_policy = kms.get_key_policy(KeyId=key_id, PolicyName=policy_name)

        # Revoke the key policy
        key_policy['Policy'] = '{"Statement": []}'
        kms.put_key_policy(KeyId=key_id, PolicyName=policy_name, Policy=json.dumps(key_policy['Policy']))
        ```

        Step 3: Monitor the KMS keys to ensure they are not exposed again.

        You can set up CloudWatch alarms to monitor the KMS keys and get notified if any of them are exposed again. You can also use AWS Config to monitor the KMS keys and get notified if any of the key policies are changed.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # KMS key with a restricted key policy (no public "*"/"AWS": "*" principal)
        resource "aws_kms_key" "SECURE_KMS_KEY" {
          description         = "KMS key without public access"
          deletion_window_in_days = 30
          enable_key_rotation = true

          # Attach a non‑public key policy. This replaces any existing policy on this key.
          policy = data.aws_iam_policy_document.SECURE_KMS_KEY_POLICY.json

          tags = {
            Name = "REPLACE_WITH_KEY_NAME"
          }
        }

        # Build the key policy in Terraform instead of allowing public access
        data "aws_iam_policy_document" "SECURE_KMS_KEY_POLICY" {
          # Allow the owning account (root) full control to avoid lockout
          statement {
            sid    = "EnableRootAccountAdmin"
            effect = "Allow"

            principals {
              type        = "AWS"
              identifiers = ["arn:aws:iam::ACCOUNT_ID:root"] # REPLACE ACCOUNT_ID
            }

            actions = [
              "kms:*",
            ]

            resources = ["*"]
          }

          # Example: allow an admin role to manage this key (customize as needed)
          statement {
            sid    = "AllowKmsAdminRole"
            effect = "Allow"

            principals {
              type        = "AWS"
              identifiers = ["arn:aws:iam::ACCOUNT_ID:role/KMS_ADMIN_ROLE_NAME"] # REPLACE ROLE
            }

            actions = [
              "kms:Describe*",
              "kms:Create*",
              "kms:Update*",
              "kms:Enable*",
              "kms:Disable*",
              "kms:ScheduleKeyDeletion",
              "kms:CancelKeyDeletion",
              "kms:Put*",
              "kms:TagResource",
              "kms:UntagResource",
              "kms:List*",
              "kms:Revoke*",
              "kms:EnableKeyRotation",
              "kms:DisableKeyRotation",
              "kms:Get*",
            ]

            resources = ["*"]
          }

          # Example: allow a specific principal to use the key for cryptographic operations
          statement {
            sid    = "AllowApplicationUseOfKey"
            effect = "Allow"

            principals {
              type        = "AWS"
              identifiers = ["arn:aws:iam::ACCOUNT_ID:role/APPLICATION_ROLE_NAME"] # REPLACE ROLE
            }

            actions = [
              "kms:Encrypt",
              "kms:Decrypt",
              "kms:ReEncrypt*",
              "kms:GenerateDataKey*",
              "kms:DescribeKey",
            ]

            resources = ["*"]
          }

          # IMPORTANT: Do NOT add any statement here with Principal "*" or {"AWS": "*"}.
        }

        # If you are attaching a policy to an EXISTING key that is already managed by Terraform:
        #   - Keep the existing aws_kms_key resource and only change its `policy` argument
        #   - Do NOT change the key_id or create a new aws_kms_key for the same physical key
        #
        # This change does NOT force replacement of the KMS key, but it is high‑risk:
        # a wrong policy can permanently lock you out of the key and its encrypted data.

        ```

        After updating and running `terraform plan`, you should see an in‑place update on the existing `aws_kms_key` resource with a change to the `policy` JSON only, and no `-/+` replacement of the key.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://docs.aws.amazon.com/kms/latest/developerguide/determining-access.html](https://docs.aws.amazon.com/kms/latest/developerguide/determining-access.html)
