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

# Kubernetes Boot Disk Should Be Encrypted With Customer Managed Keys

### More Info:

Ensure that boot disk on k8 node pools are encrypted with CMK

### Risk Level

High

### Address

Security

### Compliance Standards

* ISO 27001
* Securities and Exchange Board of India (SEBI) - Cloud Security Adoption Framework

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        To remediate the misconfiguration, follow these steps:

        1. Open the Google Cloud Platform (GCP) Console and navigate to the Kubernetes Engine page.

        2. Select the cluster that you want to remediate.

        3. Click on the "Nodes" tab and select the node pool that you want to remediate.

        4. Click on the "Edit" button to edit the node pool.

        5. Scroll down to the "Security" section and click on the "Show" button next to "Boot disk encryption".

        6. Select "Customer-managed encryption keys" from the drop-down menu.

        7. Click on the "Select a key" button and choose the key that you want to use for encryption.

        8. Click on the "Save" button to save the changes.

        9. Repeat steps 4-8 for each node pool in the cluster.

        10. Verify that the boot disk encryption has been configured correctly by checking the "Encryption" column in the nodes list. It should show "Customer-managed" for each node.

        By following these steps, you have successfully remediated the misconfiguration by encrypting the Kubernetes boot disk with customer-managed keys in GCP using the GCP console.

        #
      </Accordion>

      <Accordion title="Using CLI">
        To remediate the misconfiguration "Kubernetes Boot Disk Should Be Encrypted With Customer Managed Keys" for GCP using GCP CLI, follow the below steps:

        1. Open the Cloud Shell or any terminal and ensure that you have the gcloud CLI installed and authenticated with your GCP account.

        2. Run the following command to get the name of the boot disk of your Kubernetes cluster:

           ```
           gcloud container clusters describe [CLUSTER_NAME] --zone [ZONE] | grep "bootDiskName"
           ```

           Replace `[CLUSTER_NAME]` with the name of your Kubernetes cluster and `[ZONE]` with the zone in which your cluster is running.

        3. Run the following command to encrypt the boot disk with a customer-managed key:

           ```
           gcloud compute disks add-iam-policy-binding [DISK_NAME] --zone [ZONE] --member user:[USER_EMAIL] --role roles/compute.encrypterDecrypter
           ```

           Replace `[DISK_NAME]` with the name of the boot disk obtained from step 2, `[ZONE]` with the zone in which your cluster is running and `[USER_EMAIL]` with the email address of the user who will manage the key.

        4. Run the following command to update the disk encryption key:

           ```
           gcloud compute disks update [DISK_NAME] --zone [ZONE] --customer-managed-key --customer-key-name [KEY_NAME] --source-key [KEY_RESOURCE_ID]
           ```

           Replace `[DISK_NAME]` with the name of the boot disk obtained from step 2, `[ZONE]` with the zone in which your cluster is running, `[KEY_NAME]` with the name of the customer-managed key and `[KEY_RESOURCE_ID]` with the ID of the key resource.

        By following the above steps, you can remediate the misconfiguration "Kubernetes Boot Disk Should Be Encrypted With Customer Managed Keys" for GCP using GCP CLI.
      </Accordion>

      <Accordion title="Using Python">
        To remediate the misconfiguration "Kubernetes Boot Disk Should Be Encrypted With Customer Managed Keys" in GCP using Python, you can follow the below steps:

        1. First, you need to create a customer-managed encryption key in Cloud KMS using the following command:

        ```python theme={null}
        from google.cloud import kms_v1
        from google.oauth2 import service_account

        credentials = service_account.Credentials.from_service_account_file('path/to/your/credentials.json')
        kms_client = kms_v1.KeyManagementServiceClient(credentials=credentials)

        parent = kms_client.key_ring_path('project-id', 'location', 'key-ring')
        key_id = 'my-key'
        purpose = kms_v1.CryptoKey.CryptoKeyPurpose.ENCRYPT_DECRYPT

        response = kms_client.create_crypto_key(parent, key_id, {'purpose': purpose})
        print(f'Created key: {response.name}')
        ```

        Note: Replace the `path/to/your/credentials.json` with the actual path to your GCP service account credentials file, `project-id` with your GCP project ID, `location` with the location of your key ring, and `my-key` with the name of your encryption key.

        2. Next, you need to update your Kubernetes cluster to use the customer-managed encryption key for boot disk encryption. You can use the following command to update the cluster:

        ```python theme={null}
        from google.cloud import container_v1
        from google.oauth2 import service_account

        credentials = service_account.Credentials.from_service_account_file('path/to/your/credentials.json')
        container_client = container_v1.ClusterManagerClient(credentials=credentials)

        cluster_id = 'my-cluster'
        project_id = 'project-id'
        zone = 'us-central1-a'
        key_id = 'projects/project-id/locations/location/keyRings/key-ring/cryptoKeys/my-key'

        cluster = container_client.get_cluster(project_id, zone, cluster_id)
        cluster.spec.master_authorized_networks_config.encryption_config = {
            'state': 'ENCRYPTED',
            'key_name': key_id
        }

        update_request = container_client.update_cluster(project_id, zone, cluster_id, cluster)
        print(f'Updated cluster: {update_request.name}')
        ```

        Note: Replace the `path/to/your/credentials.json` with the actual path to your GCP service account credentials file, `project-id` with your GCP project ID, `location` with the location of your key ring, `my-key` with the name of your encryption key, and `my-cluster` with the name of your Kubernetes cluster.

        3. Finally, you can verify that the boot disk encryption is using the customer-managed encryption key by checking the cluster details:

        ```python theme={null}
        cluster = container_client.get_cluster(project_id, zone, cluster_id)
        print(f'Boot disk encryption key: {cluster.spec.master_authorized_networks_config.encryption_config.key_name}')
        ```

        This will print the name of the encryption key used for boot disk encryption.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "google_container_cluster" "PRIMARY_CLUSTER" {
          name     = "PRIMARY_CLUSTER_NAME"     # replace with your cluster name
          location = "GCP_REGION_OR_ZONE"       # e.g. "us-central1" or "us-central1-a"

          # For regional clusters, use `locations` as needed
          # locations = ["us-central1-a", "us-central1-b", "us-central1-f"]

          remove_default_node_pool = true
          initial_node_count       = 1

          # Option 1: manage the (default) node pool via `node_config`
          node_config {
            machine_type = "e2-medium"

            # Use your full KMS key resource ID:
            # projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY_NAME
            boot_disk_kms_key = "KMS_KEY_RESOURCE_ID"

            # The node service account must have Cloud KMS CryptoKey Encrypter/Decrypter on this key
            service_account = "NODE_SERVICE_ACCOUNT_EMAIL"
          }

          # Option 2: use separately managed node pools instead (preferred for most setups):
          # node_pool_defaults {
          #   node_config {
          #     boot_disk_kms_key = "KMS_KEY_RESOURCE_ID"
          #     service_account   = "NODE_SERVICE_ACCOUNT_EMAIL"
          #   }
          # }
        }

        # Example separately managed node pool using the same CMK:
        resource "google_container_node_pool" "PRIMARY_NODE_POOL" {
          name     = "PRIMARY_NODE_POOL_NAME"   # replace with node pool name
          cluster  = google_container_cluster.PRIMARY_CLUSTER.id
          location = google_container_cluster.PRIMARY_CLUSTER.location

          node_count = 3

          node_config {
            machine_type = "e2-medium"

            # Ensure boot disk uses the customer-managed key
            boot_disk_kms_key = "KMS_KEY_RESOURCE_ID"

            service_account = "NODE_SERVICE_ACCOUNT_EMAIL"
          }
        }
        ```

        Replacing `boot_disk_kms_key` on existing nodes forces recreation of the node pool (and draining/cordoning of nodes), so plan for a rolling replacement and potential disruption to workloads that cannot be rescheduled.

        `terraform plan` should show either:

        * an in-place update adding `boot_disk_kms_key` if Google API allows it for your case but still with node pool recreation under the hood, or
        * explicit `-/+` (destroy and create) for the affected `google_container_node_pool` (or cluster-managed default node pool) with the new `boot_disk_kms_key` value.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://cloud.google.com/blog/products/containers-kubernetes/exploring-container-security-use-your-own-keys-to-protect-your-data-on-gke](https://cloud.google.com/blog/products/containers-kubernetes/exploring-container-security-use-your-own-keys-to-protect-your-data-on-gke)
