Ensure Kafka Cluster Encryption in Transit is Enabled
Overview
This check verifies that Amazon MSK (Managed Streaming for Apache Kafka) clusters have encryption in transit enabled. MSK clusters need two types of in-transit encryption:
- Client-broker encryption - Protects data between your applications and Kafka brokers
- Inter-broker encryption - Protects data replication between brokers within the cluster
Both must be enabled to fully protect your data in transit.
Note: MSK Serverless clusters have encryption in transit enabled by default and cannot be disabled.
Risk
Without encryption in transit, data transmitted over the network is vulnerable to:
- Eavesdropping - Attackers can intercept and read sensitive data, credentials, and metadata
- Man-in-the-middle attacks - Malicious actors can intercept and modify messages
- Lateral movement - Unencrypted inter-broker traffic exposes replication data, enabling attackers to poison topics or access data within your VPC
Remediation Steps
Prerequisites
- AWS account access with permissions to modify MSK clusters
- For existing clusters: Inter-broker encryption cannot be changed after cluster creation. If it is disabled, you must create a new cluster.
AWS Console Method
To check current encryption settings:
- Open the Amazon MSK console
- Select Clusters from the left navigation
- Click on your cluster name
- Look under Security settings for encryption information
To update client-broker encryption (existing cluster):
- Open the Amazon MSK console
- Select Clusters and click on your cluster name
- Click Edit under Security settings
- Under Encryption in transit, set Client-broker encryption to TLS
- Click Save changes
Important: Inter-broker encryption is immutable after cluster creation. If it shows as disabled, you must create a new cluster with encryption enabled.
To create a new cluster with full encryption:
- Open the Amazon MSK console
- Click Create cluster
- Choose Custom create for full configuration options
- Configure your cluster name, Kafka version, and broker settings
- Under Security settings:
- Set Client-broker encryption to TLS
- Ensure Inter-broker encryption is set to TLS (enabled by default)
- Complete the remaining configuration and click Create cluster
AWS CLI (optional)
List your MSK clusters:
aws kafka list-clusters --region us-east-1
Check encryption settings for a specific cluster:
aws kafka describe-cluster \
--cluster-arn arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/abc123 \
--region us-east-1 \
--query 'ClusterInfo.EncryptionInfo.EncryptionInTransit'
Update client-broker encryption on an existing cluster:
aws kafka update-security \
--cluster-arn arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/abc123 \
--current-version K1234567890 \
--encryption-info '{"EncryptionInTransit":{"ClientBroker":"TLS"}}' \
--region us-east-1
Replace:
arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/abc123with your cluster ARNK1234567890with your cluster's current version (found in describe-cluster output)
Note: The --current-version is required to prevent concurrent modifications. Get it from the describe-cluster output.
Create a new cluster with encryption enabled:
aws kafka create-cluster \
--cluster-name my-secure-msk-cluster \
--kafka-version 3.5.1 \
--number-of-broker-nodes 3 \
--broker-node-group-info '{
"InstanceType": "kafka.m5.large",
"ClientSubnets": ["subnet-111111", "subnet-222222", "subnet-333333"],
"SecurityGroups": ["sg-12345678"]
}' \
--encryption-info '{
"EncryptionInTransit": {
"ClientBroker": "TLS",
"InCluster": true
}
}' \
--region us-east-1
CloudFormation (optional)
AWSTemplateFormatVersion: '2010-09-09'
Description: Amazon MSK Cluster with encryption in transit enabled
Parameters:
ClusterName:
Type: String
Description: Name of the MSK cluster
Default: my-msk-cluster
KafkaVersion:
Type: String
Description: Apache Kafka version
Default: '3.5.1'
InstanceType:
Type: String
Description: Instance type for broker nodes
Default: kafka.m5.large
AllowedValues:
- kafka.m5.large
- kafka.m5.xlarge
- kafka.m5.2xlarge
- kafka.m5.4xlarge
NumberOfBrokerNodes:
Type: Number
Description: Number of broker nodes (must be multiple of AZs)
Default: 3
MinValue: 1
VolumeSize:
Type: Number
Description: EBS volume size in GiB
Default: 100
MinValue: 1
MaxValue: 16384
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Description: Subnet IDs for the MSK cluster (one per AZ)
SecurityGroupIds:
Type: List<AWS::EC2::SecurityGroup::Id>
Description: Security group IDs for the MSK cluster
Resources:
MSKCluster:
Type: AWS::MSK::Cluster
Properties:
ClusterName: !Ref ClusterName
KafkaVersion: !Ref KafkaVersion
NumberOfBrokerNodes: !Ref NumberOfBrokerNodes
BrokerNodeGroupInfo:
InstanceType: !Ref InstanceType
ClientSubnets: !Ref SubnetIds
SecurityGroups: !Ref SecurityGroupIds
StorageInfo:
EBSStorageInfo:
VolumeSize: !Ref VolumeSize
EncryptionInfo:
EncryptionInTransit:
ClientBroker: TLS
InCluster: true
Outputs:
ClusterArn:
Description: ARN of the MSK cluster
Value: !Ref MSKCluster
Key configuration:
ClientBroker: TLS- Enforces TLS encryption for all client connectionsInCluster: true- Enables encryption between brokers
Terraform (optional)
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
variable "cluster_name" {
description = "Name of the MSK cluster"
type = string
default = "my-msk-cluster"
}
variable "kafka_version" {
description = "Apache Kafka version"
type = string
default = "3.5.1"
}
variable "instance_type" {
description = "Instance type for broker nodes"
type = string
default = "kafka.m5.large"
}
variable "number_of_broker_nodes" {
description = "Number of broker nodes"
type = number
default = 3
}
variable "ebs_volume_size" {
description = "EBS volume size in GiB"
type = number
default = 100
}
variable "subnet_ids" {
description = "List of subnet IDs for the MSK cluster"
type = list(string)
}
variable "security_group_ids" {
description = "List of security group IDs"
type = list(string)
}
resource "aws_msk_cluster" "main" {
cluster_name = var.cluster_name
kafka_version = var.kafka_version
number_of_broker_nodes = var.number_of_broker_nodes
broker_node_group_info {
instance_type = var.instance_type
client_subnets = var.subnet_ids
security_groups = var.security_group_ids
storage_info {
ebs_storage_info {
volume_size = var.ebs_volume_size
}
}
}
encryption_info {
encryption_in_transit {
client_broker = "TLS"
in_cluster = true
}
}
tags = {
Name = var.cluster_name
}
}
output "cluster_arn" {
description = "ARN of the MSK cluster"
value = aws_msk_cluster.main.arn
}
output "bootstrap_brokers_tls" {
description = "TLS bootstrap brokers"
value = aws_msk_cluster.main.bootstrap_brokers_tls
}
Key configuration:
client_broker = "TLS"- Enforces TLS encryption for all client connectionsin_cluster = true- Enables encryption between brokers
Verification
After making changes, verify encryption is properly configured:
- In the AWS Console, navigate to your MSK cluster
- Check Security settings and confirm:
- Client-broker encryption shows TLS
- Inter-broker encryption shows TLS (or enabled)
CLI Verification
aws kafka describe-cluster \
--cluster-arn <your-cluster-arn> \
--region us-east-1 \
--query 'ClusterInfo.EncryptionInfo.EncryptionInTransit'
Expected output for a properly configured cluster:
{
"ClientBroker": "TLS",
"InCluster": true
}
Additional Resources
- Amazon MSK Encryption Documentation
- Amazon MSK Security Best Practices
- AWS::MSK::Cluster CloudFormation Reference
- Terraform aws_msk_cluster Resource
Notes
- Inter-broker encryption is immutable: Once a cluster is created, you cannot change the inter-broker encryption setting. If it is disabled, you must create a new cluster with encryption enabled.
- Client impact: Changing client-broker encryption to TLS-only will disconnect any clients using plaintext connections. Ensure all clients are configured to use TLS before making this change.
- Performance: TLS encryption adds minimal overhead to modern systems but may require slightly more CPU resources.
- MSK Serverless: If you use MSK Serverless, encryption in transit is always enabled and cannot be disabled.
- Compliance: This control helps meet requirements for AWS Foundational Security Best Practices, PCI DSS, SOC 2, ISO 27001, and other frameworks.