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

# Ensure Kubernetes Secrets Are Encrypted Using Customer Master Keys Managed AWS KMS

### More Info:

Where etcd encryption is used, appropriate providers should be configured.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CIS EKS
* CMMC 2.0
* CSA Cloud Controls Matrix v4
* DPDPA
* Digital Operational Resilience Act (EU)
* 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
* 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="Manual Steps" defaultOpen="true">
        1. **Identify the cluster and region**
           * On any machine with AWS CLI access, list clusters and pick the target name and region:
             ```bash theme={null}
             aws eks list-clusters --region us-east-1
             aws eks describe-cluster --name <CLUSTER_NAME> --region <REGION>
             ```

        2. **Check if KMS encryption is enabled and which key is used**
           * On any machine with AWS CLI access, run:
             ```bash theme={null}
             aws eks describe-cluster \
               --name <CLUSTER_NAME> \
               --region <REGION> \
               --query 'cluster.encryptionConfig' \
               --output json
             ```
           * Review the output: ensure `resources` includes `"secrets"` and that `provider.keyArn` points to the intended customer-managed KMS key (not just an AWS-managed default, if your policy requires CMKs).

        3. **Review the KMS key configuration and key policy**
           * On any machine with AWS CLI access, get key details:
             ```bash theme={null}
             aws kms describe-key --key-id <KEY_ARN> --region <REGION>
             aws kms get-key-policy \
               --key-id <KEY_ARN> \
               --policy-name default \
               --region <REGION> \
               --output json
             ```
           * Confirm the key is customer-managed, enabled, in the correct account, and the key policy allows the EKS cluster’s IAM role (or node roles, per your design) to use it for encryption/decryption.

        4. **Decide remediation approach (replacement, recreation, or accept risk)**
           * If `encryptionConfig` is empty, does not include `"secrets"`, or uses an incorrect key:
             * Document that etcd secrets are not protected by the desired CMK.
             * Decide whether to:
               * Recreate the cluster with **Secrets Encryption** enabled and the correct CMK, then migrate workloads; or
               * Create a new, compliant cluster and gradually cut over; or
               * Accept/temporarily waive the risk with a documented exception.

        5. **Implement remediation via cloud/IaC (for new or replacement clusters)**
           * For a new or replacement cluster using AWS CLI, specify encryption with your CMK:
             ```bash theme={null}
             aws eks create-cluster \
               --name <NEW_CLUSTER_NAME> \
               --region <REGION> \
               --role-arn <EKS_SERVICE_ROLE_ARN> \
               --resources-vpc-config subnetIds=<SUBNET_IDS>,securityGroupIds=<SG_IDS> \
               --encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"<KMS_KEY_ARN>"}}]'
             ```
           * If using CloudFormation/Terraform, configure the `encryptionConfig`/`encryption_config` block with `resources = ["secrets"]` and `provider.keyArn = <KMS_KEY_ARN>` and deploy the new cluster.

        6. **Verify the final state**
           * After creating or migrating to the compliant cluster, re-run:
             ```bash theme={null}
             aws eks describe-cluster \
               --name <CLUSTER_NAME> \
               --region <REGION> \
               --query 'cluster.encryptionConfig' \
               --output json
             ```
           * Confirm that `resources` includes `"secrets"` and `provider.keyArn` matches the intended customer-managed KMS CMK.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot configure EKS secrets encryption or modify the kube-apiserver encryption-provider settings; this must be done via the EKS control plane configuration at cluster creation time using the AWS console/CLI/IaC. Refer to the Manual Steps section for how to review current settings and plan remediation (which will typically require recreating the cluster with Secrets Encryption enabled).
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Report EKS secrets encryption status for one or more clusters.
        #
        # REQUIREMENTS (run on: any machine with AWS CLI and kubectl access):
        #   - aws CLI v2 configured with permissions to describe EKS clusters
        #   - jq installed
        #
        # USAGE:
        #   ./check-eks-secrets-encryption.sh REGION CLUSTER1 [CLUSTER2 ...]
        #
        # NOTES:
        #   - This does NOT change anything; it only reports current state.
        #   - For a given cluster, **problems** are:
        #       * "encryptionConfig: []"   → no EKS‑managed secrets encryption
        #       * "resources: []" or missing "secrets" in resources
        #       * "keyArn: null"           → no CMK configured
        #       * KMS key not enabled / cannot be described

        set -euo pipefail

        if [ "$#" -lt 2 ]; then
          echo "Usage: $0 REGION CLUSTER1 [CLUSTER2 ...]" >&2
          exit 1
        fi

        REGION="$1"
        shift

        if ! command -v aws >/dev/null 2>&1; then
          echo "ERROR: aws CLI not found in PATH" >&2
          exit 2
        fi

        if ! command -v jq >/dev/null 2>&1; then
          echo "ERROR: jq not found in PATH" >&2
          exit 2
        fi

        echo "Region: ${REGION}"
        echo

        for CLUSTER in "$@"; do
          echo "==== Cluster: ${CLUSTER} ===="

          # 1. Describe the cluster's encryption config from the EKS control plane
          if ! DESC_JSON=$(aws eks describe-cluster \
              --name "${CLUSTER}" \
              --region "${REGION}" 2>/dev/null); then
            echo "  ERROR: unable to describe cluster via AWS API (check name/permissions)." 
            echo
            continue
          fi

          # Extract encryption config
          ENC_JSON=$(echo "${DESC_JSON}" | jq -c '.cluster.encryptionConfig // []')

          # Human‑readable summary
          echo "  EKS encryptionConfig (control plane view):"
          echo "${ENC_JSON}" | jq '.'

          # Simple evaluations
          ENC_COUNT=$(echo "${ENC_JSON}" | jq 'length')
          if [ "${ENC_COUNT}" -eq 0 ]; then
            echo "  ISSUE: No EKS secrets encryption configured (encryptionConfig is empty)."
          else
            # For each provider entry, check secrets + keyArn
            echo "${ENC_JSON}" | jq -c '.[]' | nl -ba | while read -r IDX LINE; do
              RESOURCES=$(echo "${LINE}" | jq -r '.resources // [] | join(",")')
              KEY_ARN=$(echo "${LINE}" | jq -r '.provider.keyArn // empty')

              echo "  Provider #${IDX}:"
              echo "    resources: ${RESOURCES:-<none>}"
              echo "    keyArn:   ${KEY_ARN:-<none>}"

              if [ -z "${RESOURCES}" ]; then
                echo "    ISSUE: resources list empty; 'secrets' not covered."
              elif ! echo "${RESOURCES}" | tr ',' '\n' | grep -qx 'secrets'; then
                echo "    ISSUE: 'secrets' not present in resources; secrets not encrypted by this provider."
              fi

              if [ -z "${KEY_ARN}" ]; then
                echo "    ISSUE: keyArn is missing; CMK not configured correctly."
              else
                # 2. Describe the CMK status from KMS
                if KEY_DESC=$(aws kms describe-key \
                      --key-id "${KEY_ARN}" \
                      --region "${REGION}" 2>/dev/null); then
                  KEY_STATE=$(echo "${KEY_DESC}" | jq -r '.KeyMetadata.KeyState')
                  KEY_MANAGER=$(echo "${KEY_DESC}" | jq -r '.KeyMetadata.KeyManager')
                  echo "    KMS key state:    ${KEY_STATE}"
                  echo "    KMS key manager:  ${KEY_MANAGER}"
                  if [ "${KEY_STATE}" != "Enabled" ]; then
                    echo "    ISSUE: KMS key is not Enabled (current state: ${KEY_STATE})."
                  fi
                  if [ "${KEY_MANAGER}" != "CUSTOMER" ]; then
                    echo "    ISSUE: KMS key is not a customer managed CMK (KeyManager=${KEY_MANAGER})."
                  fi
                else
                  echo "    ISSUE: unable to describe KMS key (check IAM or key exists)."
                fi
              fi
            done
          fi

          echo
        done
        ```

        ### How to interpret the output

        Run (from any machine with AWS CLI access):

        ```bash theme={null}
        ./check-eks-secrets-encryption.sh us-east-1 my-prod-cluster my-dev-cluster
        ```

        Indicators of a problem for a given cluster:

        * `encryptionConfig: []` or printed as `[]`
        * Any provider with:
          * `resources: <none>` or `resources` not including `secrets`
          * `keyArn: <none>`
          * KMS key state not `Enabled`
          * KMS `KeyManager` not `CUSTOMER` (i.e., not a customer-managed CMK)

        This script only reports; remediation requires recreating or reconfiguring the cluster with Secrets Encryption enabled using a customer-managed KMS CMK.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
