MSK clusters should be encrypted in transit among broker nodes
Kafka broker nodes replicate partition data across the cluster continuously. Without TLS, that replication traffic travels in plaintext over the VPC network, exposing message payloads, consumer group metadata, and authentication tokens to anyone with network-level access. VPC traffic mirroring, compromised ENIs, or misconfigured routing can all expose unencrypted streams.
TLS between brokers adds minimal latency on modern instance types and removes an eavesdropping risk that network-layer controls alone cannot close.
Retrofit consideration
Changing the in_cluster encryption setting on an existing MSK cluster requires creating a new cluster. AWS does not support modifying encryption-in-transit settings after cluster creation. Plan for data migration and client reconnection.
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "msk_kafka_cluster" {
source = "nistcsf.compliance.tf/terraform-aws-modules/msk-kafka-cluster/aws"
version = ">=3.0.0"
broker_node_client_subnets = ["subnet-12345678", "subnet-12345678", "subnet-12345678"]
broker_node_instance_type = "kafka.t3.small"
broker_node_security_groups = ["sg-12345678"]
client_authentication = {
sasl = {
iam = true
}
}
kafka_version = "3.6.0"
name = "abc123"
number_of_broker_nodes = 3
}
If you use terraform-aws-modules/msk-kafka-cluster/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "msk_kafka_cluster" {
source = "terraform-aws-modules/msk-kafka-cluster/aws"
version = ">=3.0.0"
broker_node_client_subnets = ["subnet-12345678", "subnet-12345678", "subnet-12345678"]
broker_node_instance_type = "kafka.t3.small"
broker_node_security_groups = ["sg-12345678"]
client_authentication = {
sasl = {
iam = true
}
}
kafka_version = "3.6.0"
name = "abc123"
number_of_broker_nodes = 3
encryption_in_transit_in_cluster = true
}
Use AWS provider resources directly. See docs for the resources involved: aws_msk_cluster.
resource "aws_msk_cluster" "this" {
broker_node_group_info {
client_subnets = [element(["subnet-abc123", "subnet-def456"], 0), element(["subnet-abc123", "subnet-def456"], 1)]
instance_type = "kafka.t3.small"
security_groups = ["sg-abc12345"]
}
client_authentication {
sasl {
iam = true
}
}
cluster_name = "pofix-abc123"
kafka_version = "3.5.1"
number_of_broker_nodes = 2
encryption_info {
encryption_in_transit {
in_cluster = true
}
}
}
What this control checks
In Terraform, aws_msk_cluster must include an encryption_info block containing encryption_in_transit with in_cluster = true. While in_cluster defaults to true in the AWS provider, explicit configuration avoids ambiguity and prevents drift if provider defaults ever change. in_cluster = false fails this control, as it permits plaintext communication between brokers. The client_broker argument in the same block controls client-to-broker encryption and is evaluated separately; setting it to "TLS" is complementary but not what this control checks.
Common pitfalls
Encryption settings are immutable after creation
Change
in_clusteron an existing cluster and Terraform will destroy and recreate it, causing full downtime and data loss unless you've planned a blue-green migration. AWS doesn't expose a modify path forencryption_in_transitafter cluster creation.Default value masks missing configuration
Explicitly set
in_cluster = truein every cluster definition. The argument defaults totrue, so omittingencryption_infoentirely still passes this control, but relying on provider defaults is fragile. A future provider version change could silently introduce drift in clusters that never had the setting pinned.client_broker setting is independent
Setting
client_brokerto"TLS_PLAINTEXT"or"PLAINTEXT"has no effect onin_cluster. A cluster can pass this control while still accepting plaintext client connections. Both arguments represent separate encryption decisions and should be reviewed independently.Custom configurations may conflict with TLS
If you use a custom MSK configuration (
aws_msk_configuration) with listener-related properties, validate compatibility with your cluster encryption mode. In-cluster encryption is governed by the clusterencryption_in_transitsetting, not by custom configuration properties, so don't treat them as an override.
Audit evidence
An auditor expects AWS Config rule evaluation results showing MSK clusters with in-cluster TLS enabled, or output from aws kafka describe-cluster where EncryptionInfo.EncryptionInTransit.InCluster is true for each cluster. Console screenshots of the MSK cluster's "Encryption" settings panel with "Within the cluster" set to TLS are also valid.
For continuous coverage, AWS Config conformance pack results or scanner output from Prowler or Steampipe that explicitly evaluate this property across all regions provide the strongest evidence of ongoing compliance.
Framework-specific interpretation
NIST Cybersecurity Framework v2.0: PR.DS-2 covers protection of data in transit. Inter-broker TLS is the mechanism that satisfies it at the MSK layer: Kafka replication runs continuously inside the cluster, and without it there are no authenticated channels at the broker level regardless of what client-facing encryption is configured.
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
msk_cluster_encryption_in_transit_with_tls_enabledAWS Config Managed Rule:
MSK_IN_CLUSTER_NODE_REQUIRE_TLSCheckov Check:
CKV_AWS_81Powerpipe Control:
aws_compliance.control.msk_cluster_encryption_in_transit_with_tls_enabledProwler Check:
kafka_cluster_in_transit_encryption_enabledAWS Security Hub Control:
MSK.1KICS Query:
6db52fa6-d4da-4608-908a-89f0c59e743eTrivy Check:
AWS-0073
Last reviewed: 2026-03-09