EBS Volume Encryption (FedRAMP)

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:

  • FIPS 140-2 validated encryption — AES-256 using AWS KMS with a customer-managed key satisfies this requirement for EBS.

  • Customer-managed keys (CMK) — the encryption key must be under agency control; AWS-managed keys (aws/ebs) do not satisfy FedRAMP High key management requirements.

  • Key rotation — CMKs must have automatic annual rotation enabled.

  • Audit trail — all KMS API calls must be logged to AWS CloudTrail.

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

  • AWS CLI configured with permissions to create KMS keys and IAM policies

  • EKS cluster with the EBS CSI driver installed (see EBS CSI driver prerequisites)

  • CloudTrail enabled in the AWS account for KMS audit logging

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'

The output must be true.

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": "*"
      }
    ]
  }'

Replace <ebs-csi-irsa-role> with the IAM role used by the ebs-csi-controller-sa service account in your cluster, and <eks-node-role> with your EKS managed node group IAM role. Both can be found in the EKS console under Compute → Node Groups.

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
yaml

Replace <kms-key-arn> with the full ARN of the CMK created above. Retrieve it with:

aws kms describe-key \
  --key-id "$KMS_KEY_ID" \
  --region "$AWS_REGION" \
  --query 'KeyMetadata.Arn' --output text

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
yaml

For the full FED install, combine this with the managed services values from Cloud Services and your ingress/TLS configuration.

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"

Enabling account-level default encryption applies to all new EBS volumes in the region, regardless of StorageClass settings. Verify that existing workloads in the account are compatible before enabling this setting.

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}'

The output should show "Encrypted": true and the KMS key ARN matching alias/kfuse-ebs-fedramp.

Check the StorageClass applied to each PVC:

kubectl get pvc -n "$NAMESPACE" \
  -o custom-columns='NAME:.metadata.name,STORAGECLASS:.spec.storageClassName,STATUS:.status.phase'

All PVCs should reference kfuse-encrypted-gp3.

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"

KMS GenerateDataKey, Decrypt, and CreateGrant events are automatically included in CloudTrail management events. No additional configuration is required beyond ensuring a trail is active.

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