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

# Secrets Should Be Encrypted At Rest

### More Info:

Advisory: EncryptionConfiguration with a KMS provider should be enabled for Secret resources so etcd does not store secrets in plaintext.

### Risk Level

High

### Address

Security

### Compliance Standards

* Cloudanix Best Practice

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Identify how the cluster is managed and where to configure encryption**
           * Determine provider and provisioning method (console only, or via Terraform/CloudFormation/ARM/Bicep/Deployment Manager, etc.).
           * On any machine with cloud CLI access, list cluster details, for example:
             * EKS:
               ```bash theme={null}
               aws eks describe-cluster --name YOUR_CLUSTER_NAME --region YOUR_REGION \
                 --query "cluster.encryptionConfig" --output json
               ```
             * GKE:
               ```bash theme={null}
               gcloud container clusters describe YOUR_CLUSTER_NAME \
                 --region YOUR_REGION --format="json(databaseEncryption)"
               ```
             * AKS:
               ```bash theme={null}
               az aks show -g YOUR_RESOURCE_GROUP -n YOUR_CLUSTER_NAME \
                 --query "securityProfile.azureKeyVaultKms|securityProfile.encryptionAtHost" -o json
               ```

        2. **Review current at-rest encryption status for Secrets**
           * In the provider console, open the cluster and locate the encryption / security / data protection section.
           * Confirm whether “envelope encryption”, “KMS provider”, “customer-managed keys”, or similar is **enabled for Kubernetes Secrets / etcd**.
           * If using IaC, inspect the config:
             * EKS (Terraform example): check `encryption_config` block on `aws_eks_cluster`.
             * GKE: check `database_encryption` / `kms_key_name` on the cluster resource.
             * AKS: check `azure_key_vault_kms` or equivalent encryption profile.

        3. **Decide on an appropriate KMS key and scope**
           * With your security team, choose or create a KMS key dedicated to Kubernetes Secrets, with restricted IAM/RBAC (only control plane and key admins can use it).
           * On any machine with cloud CLI access, gather candidate keys:
             * AWS KMS:
               ```bash theme={null}
               aws kms list-keys
               ```
             * GCP KMS:
               ```bash theme={null}
               gcloud kms keys list --location=YOUR_LOCATION --keyring=YOUR_KEYRING
               ```
             * Azure Key Vault:
               ```bash theme={null}
               az keyvault key list --vault-name YOUR_VAULT_NAME -o table
               ```

        4. **Enable or update envelope/KMS encryption for Secrets in the cluster configuration**
           * If using the cloud console:
             * Edit the cluster, locate the encryption/KMS settings, and enable encryption for **Kubernetes Secrets** using the selected KMS key.
             * Save/apply the change; be aware that some providers require cluster recreation or may briefly impact control-plane operations.
           * If using IaC:
             * Add or update the appropriate encryption/KMS blocks to include Secrets and reference the chosen KMS key.
             * Apply the changes with your IaC tool (e.g., `terraform apply`, `az deployment group create`, `gcloud deployment-manager deployments update`), following your change-management process.

        5. **Verify encryption is enabled and active for Secrets**
           * After the change completes, re-run the provider CLI describe commands from step 1 and confirm that:
             * A KMS/encryption configuration is present, and
             * It explicitly covers Kubernetes Secrets / etcd data.
           * For example, on EKS you should see non-empty `encryptionConfig` with `resources` including `"secrets"` and a KMS key ARN.

        6. **Validate behavior with a test Secret and document the decision**
           * On any machine with kubectl access:
             ```bash theme={null}
             kubectl create secret generic encryption-test-secret \
               --from-literal=secret-key=test-value-12345
             ```
           * Use cloud-provider guidance (if available) or support tools to confirm new etcd entries for Secrets are encrypted (direct etcd inspection usually isn’t possible on managed control planes; rely on provider guarantees once encryption is reported as enabled).
           * Record in your security documentation: the cluster, date of change, KMS key ID/ARN/URI used, and who is authorized to manage that key.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot configure at-rest encryption for Secrets because this setting is only available in the managed control-plane / cloud provider configuration (for example, via the provider console, CLI, or IaC). Refer to the Manual Steps section for how to enable KMS/envelope encryption for Secrets in your specific environment.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Check: Secrets are encrypted at rest (CBP C6.2) - MANUAL
        #
        # This script does NOT prove that KMS/envelope encryption is enabled,
        # because that setting lives in the managed control plane / cloud
        # provider config and is not exposed via the Kubernetes API.
        #
        # Instead, it:
        #   1. Lists all namespaces and counts Secrets (to scope review effort).
        #   2. Fetches one sample Secret per namespace and shows encoded size.
        #   3. Prints guidance on what must be reviewed manually in the cloud console / IaC.
        #
        # Run from: any machine with kubectl access and cluster-wide read on Secrets.

        set -euo pipefail

        echo "==[ Context ]===================================================="
        kubectl config current-context || true
        echo

        echo "==[ Namespaces and Secret counts ]==============================="
        kubectl get ns -o custom-columns='NAMESPACE:.metadata.name' --no-headers | while read -r ns; do
          count=$(kubectl get secrets -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
          printf "%-30s %6s\n" "$ns" "$count"
        done
        echo

        echo "==[ Sample Secret sizes by namespace ]==========================="
        echo "# For each namespace (that has Secrets), one arbitrary Secret is inspected."
        echo "# This does NOT show whether etcd encryption is enabled; it just helps identify"
        echo "# where sensitive data is stored for focused review."
        echo

        kubectl get ns -o custom-columns='NAMESPACE:.metadata.name' --no-headers | while read -r ns; do
          secret_name=$(kubectl get secrets -n "$ns" --no-headers 2>/dev/null | awk 'NR==1{print $1}')
          if [ -z "${secret_name:-}" ]; then
            continue
          fi

          echo "Namespace: $ns"
          echo "  Sample Secret: $secret_name"
          # Dump Secret yaml to show type and keys (but not decoded values)
          kubectl get secret "$secret_name" -n "$ns" -o yaml | sed 's/^/    /'
          echo

          # Show the approximate size of the raw Secret object and each data entry
          echo "  Encoded data entry sizes (bytes):"
          kubectl get secret "$secret_name" -n "$ns" -o json \
            | jq -r '
              .data // {} | to_entries[]
              | "    \(.key): \(.value | @base64d | length)"
            '
          echo "------------------------------------------------------------"
        done

        echo
        echo "==[ Manual review required ]======================================"
        cat <<'EOF'
        This benchmark control is MANUAL: there is no kubectl/API field that
        shows whether KMS/envelope encryption for Secrets is enabled.

        Use this script's output to:
          - Identify namespaces and Secrets that contain sensitive data.
          - Prioritize which environments/clusters must have KMS/envelope encryption enabled.

        Then, for EACH CLUSTER, verify in the cloud provider:

        *Amazon EKS*
          - Console: EKS > Clusters > <cluster> > Configuration > Encryption
            - EXPECTED: "Secrets encryption" (or similar) enabled with a KMS key.
          - CLI (example, read-only):
              aws eks describe-cluster --name <cluster-name> \
                --region <region> \
                --query 'cluster.encryptionConfig' --output yaml
            - EXPECTED: encryptionConfig contains:
                - resources including "secrets"
                - provider.keyArn set to a KMS key ARN

        *Google GKE*
          - Console: Kubernetes Engine > Clusters > <cluster> > Details > Security
            - EXPECTED: "Application-layer Secrets Encryption" enabled for secrets.
          - CLI (example, read-only):
              gcloud container clusters describe <cluster-name> \
                --region <region> \
                --format='yaml(databaseEncryption,workloadIdentityConfig)'
            - EXPECTED: databaseEncryption.state: "ENCRYPTED"
              and keyName set to a KMS key.

        *Azure AKS*
          - Console: Kubernetes services > <cluster> > Encryption
            - EXPECTED: "Secret encryption with customer-managed keys" enabled.
          - CLI (example, read-only):
              az aks show -g <resource-group> -n <cluster-name> \
                --query 'securityProfile.azureKeyVaultKms' -o yaml
            - EXPECTED: "enabled": true and a configured Key Vault/Key ID.

        *Other managed / on-prem*
          - Review the control plane configuration (API server / etcd config or
            cluster definition in IaC) for:
              - EncryptionConfiguration with a KMS provider that lists "secrets"
                in the resources array, OR
              - The provider's documented "Secrets envelope/KMS encryption" option.

        What indicates a PROBLEM (non-compliant state):
          - No documentation or IaC showing KMS/envelope encryption enabled.
          - Cloud console / CLI shows:
              - No encryptionConfig, or
              - encryptionConfig without "secrets" as a resource, or
              - Provider-specific flag for Secrets encryption is disabled/not set.
        In these cases, Secrets are likely stored in plaintext in etcd and this
        control should be marked as failing until KMS/envelope encryption is
        explicitly enabled.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
