EBS Volume Encryption (FedRAMP) :: Kloudfuse Docs

EBS Volume Encryption (FedRAMP)

Table of Contents

FedRAMP High and Moderate baselines require encryption at rest for all persistent data. This page covers configuring AWS EBS volume encryption for Kloudfuse FED deployments using a customer-managed KMS key (CMK), which satisfies the FedRAMP SC-28 (Protection of Information at Rest) control family.

This page applies to the kfuse-fed chart only. Standard (kfuse) deployments follow the same EBS encryption steps, but FedRAMP compliance also requires the managed services (RDS, ElastiCache, MSK) and S3 buckets to be encrypted — those are covered in their respective setup pages.

FedRAMP Encryption Requirements

FedRAMP mandates the following for data at rest:

NIST SP 800-53 Control Requirement How EBS CMK satisfies it
SC-28 Protect information at rest AES-256 encryption on all EBS volumes
SC-12 Cryptographic key establishment and management Customer-managed KMS key with defined lifecycle
SC-13 Cryptographic protection FIPS 140-2 validated AWS KMS HSMs
AU-2, AU-9 Audit events and protection of audit information KMS key usage logged in CloudTrail

Prerequisites

Set the required environment variables before running the commands on this page:

export NAMESPACE=<your-namespace>
export AWS_REGION=<aws-region>
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export CLUSTER_NAME=<your-eks-cluster-name>

Create a Customer-Managed KMS Key

Create a dedicated CMK for EBS encryption with automatic annual rotation enabled:

KMS_KEY_ID=$(aws kms create-key \
  --description "Kloudfuse EBS encryption key - FedRAMP" \
  --key-usage ENCRYPT_DECRYPT \
  --origin AWS_KMS \
  --region "$AWS_REGION" \
  --query 'KeyMetadata.KeyId' --output text)

echo "KMS Key ID: $KMS_KEY_ID"

# Create a human-readable alias
aws kms create-alias \
  --alias-name "alias/kfuse-ebs-fedramp" \
  --target-key-id "$KMS_KEY_ID" \
  --region "$AWS_REGION"

# Enable automatic annual key rotation (required for FedRAMP)
aws kms enable-key-rotation \
  --key-id "$KMS_KEY_ID" \
  --region "$AWS_REGION"

Verify rotation is enabled:

aws kms get-key-rotation-status \
  --key-id "$KMS_KEY_ID" \
  --region "$AWS_REGION" \
  --query 'KeyRotationEnabled'

Configure the KMS Key Policy

The EBS CSI driver’s service account role and the EKS node IAM role must be granted kms:GenerateDataKeyWithoutPlaintext, kms:Decrypt, and kms:CreateGrant permissions. Replace the placeholders with your actual role ARNs:

aws kms put-key-policy \
  --key-id "$KMS_KEY_ID" \
  --policy-name default \
  --region "$AWS_REGION" \
  --policy '{
    "Version": "2012-10-17",
    "Statement": [\
      {\
        "Sid": "Enable IAM User Permissions",\
        "Effect": "Allow",\
        "Principal": {\
          "AWS": "arn:aws:iam::'"$AWS_ACCOUNT_ID"':root"\
        },\
        "Action": "kms:*",\
        "Resource": "*"\
      },\
      {\
        "Sid": "Allow EBS CSI driver to use the key",\
        "Effect": "Allow",\
        "Principal": {\
          "AWS": [\
            "arn:aws:iam::'"$AWS_ACCOUNT_ID"':role/<ebs-csi-irsa-role>",\
            "arn:aws:iam::'"$AWS_ACCOUNT_ID"':role/<eks-node-role>"\
          ]\
        },\
        "Action": [\
          "kms:GenerateDataKeyWithoutPlaintext",\
          "kms:Decrypt",\
          "kms:CreateGrant",\
          "kms:DescribeKey"\
        ],\
        "Resource": "*"\
      }\
    ]
  }'

Create an Encrypted StorageClass

Define a StorageClass that references the CMK. All PVCs using this StorageClass will be encrypted with the customer-managed key.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: kfuse-encrypted-gp3
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  encrypted: "true"
  kmsKeyId: <kms-key-arn>
  iops: "6000"
  throughput: "300"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Retain

Apply the StorageClass to your cluster:

kubectl apply -f storageclass-encrypted-gp3.yaml

Configure Helm Values

Reference the encrypted StorageClass across all stateful Kloudfuse components in your custom-values.yaml:

pinot:
  server:
    persistence:
      storageClass: kfuse-encrypted-gp3
      size: 500Gi
  controller:
    persistence:
      storageClass: kfuse-encrypted-gp3
      size: 100Gi
  zookeeper:
    persistence:
      storageClass: kfuse-encrypted-gp3
      size: 20Gi

kafka:
  persistence:
    storageClass: kfuse-encrypted-gp3
    size: 200Gi
  zookeeper:
    persistence:
      storageClass: kfuse-encrypted-gp3
      size: 20Gi

kfuse-configdb:
  primary:
    persistence:
      storageClass: kfuse-encrypted-gp3
      size: 50Gi

Enable Account-Level EBS Encryption Default (Optional)

To ensure no unencrypted EBS volume can be provisioned in the AWS account — a defense-in-depth measure aligned with FedRAMP — enable the account-level EBS encryption default:

aws ec2 enable-ebs-encryption-by-default \
  --region "$AWS_REGION"

# Set the account default KMS key to your CMK
aws ec2 modify-ebs-default-kms-key-id \
  --kms-key-id "$KMS_KEY_ID" \
  --region "$AWS_REGION"

Validate Encryption

After deploying Kloudfuse, confirm that all PVC-backed EBS volumes are encrypted with the CMK:

# List PVs and their corresponding EBS volume IDs
kubectl get pv -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.csi.volumeHandle}{"\n"}{end}'
# Check encryption status for a specific volume
aws ec2 describe-volumes \
  --volume-id <vol-id> \
  --region "$AWS_REGION" \
  --query 'Volumes[0].{Encrypted:Encrypted,KmsKeyId:KmsKeyId}'

Audit: CloudTrail KMS Logging

FedRAMP AU-2 requires logging of cryptographic key usage. Verify that CloudTrail is recording KMS events:

aws cloudtrail get-event-selectors \
  --trail-name <your-trail-name> \
  --region "$AWS_REGION"

To query recent KMS usage for the CMK:

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=ResourceName,AttributeValue="$KMS_KEY_ID" \
  --region "$AWS_REGION" \
  --max-results 20

References