Skip to content

Failed to setup multi-VPC private connectivity by following the blog/doc

1

Hi All,

I'd like to setup multi-VPC private connectivity so that MSK in AWS account A can be securely accessed from AWS account B with IAM role in the EC2 instance.

I followed the blog https://aws.amazon.com/blogs/big-data/connect-kafka-client-applications-securely-to-your-amazon-msk-cluster-from-different-vpcs-and-aws-accounts/ to turn on multi-VPC on the MSK cluster, created a VPC connection in account B, but I just failed to list topics from account B.

For this demo/test, I am just using the default vpc in the account B, with the default security group, which allows all inbound/outbound connections. The subnet mappings are also correct. I have questions for step 8 in the blog "The next step is to update the outbound rules for the VPC endpoint security group to allow communication to the port range 14001:14100." If the "VPC endpoint security group" refers to the security group I choose when creating the VPC connection/endpoint, it's the default security group.

I also followed the doc at https://docs.aws.amazon.com/msk/latest/developerguide/mvpc-cross-account-user-action.html

In my case, I created a IAM policy in account B, then create a IAM role for EC2 instance and bind the IAM role to the EC2 instance. I am not sure what is the correct IAM policy, how to set the MSK ARN in that policy, should I set the ARN for MSK in account A, or the ARN for VPC connection in account B. I tried both and didn't work. My current IAM policy in account B is

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kafka-cluster:Connect",
                "kafka-cluster:AlterCluster",
                "kafka-cluster:DescribeCluster",
                "kafka-cluster:WriteDataIdempotently"
            ],
            "Resource": [
                "arn:aws:kafka:us-west-2:12ditAWSID:cluster/demo-cluster-1/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kafka-cluster:*Topic*",
                "kafka-cluster:WriteData",
                "kafka-cluster:ReadData"
            ],
            "Resource": [
                "arn:aws:kafka:us-west-2:12ditAWSID:topic/demo-cluster-1/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kafka-cluster:AlterGroup",
                "kafka-cluster:DescribeGroup"
            ],
            "Resource": "arn:aws:kafka:us-west-2:12ditAWSID:group/demo-cluster-1/*"
        }
    ]
}

I tested it with Redpanad Console. With a config.yaml

kafka:
  brokers:
    - b-1.iam.democluster1.someid.c6.kafka.us-west-2.amazonaws.com:14001
  sasl:
    enabled: true
    mechanism: AWS_MSK_IAM
    awsMskIam:
      region: us-west-2
  tls:
    enabled: true
analytics:
  enabled: false
server:
  listenAddress: 0.0.0.0
  listenPort: 8080

./redpanda-console --config.filepath rpconsole.yml {"level":"info","ts":"2025-01-13T02:56:03.465Z","msg":"started Redpanda Console","version":"2.8.2","built_at":"1736522726"} {"level":"info","ts":"2025-01-13T02:56:03.467Z","msg":"connecting to Kafka seed brokers, trying to fetch cluster metadata"} {"level":"error","ts":"2025-01-13T02:56:03.882Z","logger":"kafka_client","msg":"unable to initialize sasl","broker":"seed_0","err":"[e1ac7b3c-969c-4161-8691-a18fa83f2937]: Access denied: SASL_AUTHENTICATION_FAILED: SASL Authentication failed."} {"level":"warn","ts":"2025-01-13T02:56:03.882Z","msg":"Failed to test Kafka connection, going to retry in 1s","remaining_retries":5}

I even turned on the CloudWatch Logs for the MSK cluster to see any error. It seems that the accountB EC2 instance can reach out to the demo cluster in account A, but fail to pass SASL-based IAM

The log I got in CloudWatchLogs is [2025-01-13 02:03:42,151] INFO TCP CONNECTION INFO: { "clientIpAddress":"INTERNAL_IP", "tcpConnectionId":"INTERNAL_IP-INTERNAL_IP-1726", "clientVpcEndpointId":"vpce-..", "clientVpcId":"vpc-.." } (org.apache.kafka.common.security.authenticator.SaslServerAuthenticator)

[2025-01-13 02:03:42,245] INFO [SocketServer listenerType=ZK_BROKER, nodeId=1] Failed authentication with /INTERNAL_IP (channelId=INTERNAL_IP-INTERNAL_IP-1726) ([5edfda02-c8a1-4645-8a35-0c626b462006]: Access denied) (org.apache.kafka.common.network.Selector)

Thanks for looking into this.

2 Answers
0

Greeting

Hi Jove,
Thanks for sharing your detailed setup and challenges. I understand how frustrating it can be to troubleshoot complex multi-VPC connectivity issues, especially when working across AWS accounts with IAM and private networking. Let’s dive deeper and resolve this together. 😊


Clarifying the Issue

From your description, you’re setting up multi-VPC private connectivity for an Amazon MSK cluster in Account A, accessed securely from an EC2 instance in Account B using IAM-based authentication. While you’ve followed the AWS blog and documentation, you’re unable to list topics in the MSK cluster, facing a SASL_AUTHENTICATION_FAILED error.

Key pain points:

  • IAM Policy Confusion: Uncertainty around which ARN to use for IAM permissions in Account B.
  • Security Group Rules: Questions about configuring the VPC endpoint security group correctly.
  • Debugging SASL Authentication: Logs indicate the client can connect but fails authentication.

This updated guide adds more details on IAM roles, network debugging, and potential edge cases to help you succeed.


Why This Matters

Successfully configuring multi-VPC private connectivity ensures your Kafka applications remain secure, scalable, and compliant with AWS best practices. This setup is critical for organizations managing cross-account workloads while maintaining secure isolation between environments.


Key Terms

  • Amazon MSK: Managed Kafka service enabling scalable, secure stream processing.
  • SASL Authentication: Mechanism supporting IAM-based authentication for secure communication.
  • VPC Endpoint: Private connection to AWS services without public internet exposure.
  • IAM Role: Cross-account access mechanism allowing secure permission delegation.
  • Security Group: A virtual firewall controlling inbound and outbound traffic for AWS resources.
  • DNS Resolution: Translation of domain names to IP addresses for VPC endpoints and other services.

The Solution (Our Recipe)

Steps at a Glance:

  1. Configure IAM roles and policies for cross-account access.
  2. Verify security group rules for the MSK cluster and VPC endpoint.
  3. Check VPC peering, route tables, and DNS resolution.
  4. Debug SASL authentication and validate client configuration.
  5. Test Connectivity.

Step-by-Step Guide:

  1. Set Up IAM Role in Account B
    • Ensure the IAM policy in Account B grants access to the MSK cluster in Account A. Use the MSK ARN from Account A for the Resource.
    • Example IAM policy:
      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "kafka-cluster:Connect",
                      "kafka-cluster:DescribeCluster"
                  ],
                  "Resource": "arn:aws:kafka:us-west-2:ACCOUNT_A_ID:cluster/demo-cluster-1/*"
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "kafka-cluster:ReadData",
                      "kafka-cluster:WriteData"
                  ],
                  "Resource": "arn:aws:kafka:us-west-2:ACCOUNT_A_ID:topic/demo-cluster-1/*"
              }
          ]
      }
    • Attach this policy to the IAM role assigned to the EC2 instance in Account B.

  1. Configure Security Groups
    • For the MSK cluster in Account A:
      • Allow inbound traffic on ports 14001-14100 from the security group of the VPC endpoint in Account B.
    • For the VPC endpoint in Account B:
      • Allow outbound traffic to the MSK security group in Account A.
    • Example commands:
      # Inbound rule for MSK security group
      aws ec2 authorize-security-group-ingress \
          --group-id sg-MSK_GROUP_ID \
          --protocol tcp \
          --port 14001-14100 \
          --source-group sg-ENDPOINT_GROUP_ID
      
      # Outbound rule for VPC endpoint security group
      aws ec2 authorize-security-group-egress \
          --group-id sg-ENDPOINT_GROUP_ID \
          --protocol tcp \
          --port 14001-14100 \
          --destination-group sg-MSK_GROUP_ID

  1. Verify VPC Peering and Route Tables

    • Ensure VPC peering is correctly configured between Account A and Account B.
    • Update route tables in both VPCs to enable traffic between subnets.
    • Verify DNS resolution for the VPC endpoint is enabled:
      aws ec2 modify-vpc-endpoint \
          --vpc-endpoint-id vpce-12345 \
          --private-dns-enabled
  2. Debug SASL Authentication

    • Ensure the Redpanda Console uses the correct IAM role via the instance profile.
    • Validate config.yaml:
      kafka:
        brokers:
          - b-1.iam.democluster1.someid.c6.kafka.us-west-2.amazonaws.com:14001
        sasl:
          enabled: true
          mechanism: AWS_MSK_IAM
          awsMskIam:
            region: us-west-2
        tls:
          enabled: true
    • Enable detailed logging in CloudWatch for further debugging:
      • Look for Access Denied or misconfiguration in the IAM role.

  1. Test Connectivity
    • Use tools like telnet or curl to verify connectivity to the broker:
      telnet b-1.iam.democluster1.someid.c6.kafka.us-west-2.amazonaws.com 14001
    • Confirm successful authentication by listing topics:
      kafka-topics.sh --list --bootstrap-server b-1.iam.democluster1.someid.c6.kafka.us-west-2.amazonaws.com:14001

Closing Thoughts

If the problem persists, consider the following documentation for more insights:

These resources should clarify additional configurations or edge cases. Let me know how it goes or if you'd like further assistance. 😊


Farewell

Best of luck, Jove! I hope these steps help you achieve seamless cross-account MSK connectivity. Feel free to reach out if you hit any snags. 🚀


Cheers,

Aaron 😊

answered 2 years ago

  • Hi Aaron, I don't mind an AI helping me, however this lengthly answer is not very helpful.

    I tried the telnet host 14001 and got

    Connected to b-1.iam.democluster1....kafka.us-west-2.amazonaws.com.
    Escape character is '^]'.
    ^CConnection closed by foreign host.
    

    Is this expected or something wrong?

    For the detailed steps

    • step 1, no problem, I even put more permission in the EC2 IAM role
    • step 2, both MSK and the client in accountB are put in default VPC. Outbound is no problem. For the inbound, there are in different aws account, how to set the security group of account B in account A?
    • private dns enable: MSK managed the VPC endpoint/privateLink, right? Do I need extra configuration?

    Since I got the error from the MSK broker in CloudWatch Logs, I think it proved the network connection is setup. There should be no inbound or outbound connectivity issue but somehow the connection from Kafka is not accepted.

    Again thanks for looking into my inquiry.

  • That telnet session shows the connection is working

0

HI Jove!

It seems you're dealing with a Kafka connectivity issue between an Amazon Managed Streaming for Apache Kafka (MSK) cluster and a client in a different AWS account (Account B). Let me address your concerns step-by-step.


Is the Telnet Response Normal?

The behavior you observed when running telnet is expected. Connecting to the MSK broker via Telnet validates that the network path to the broker is functioning. However, it doesn't confirm that the Kafka protocol is working or that authentication is successful. The connection closing after the ^C interruption is standard Telnet behavior.


Security Group Configuration Across Accounts

When MSK and the client reside in different accounts but within the same default VPCs, you must ensure the security groups are correctly configured.

In Account A (where MSK resides):

  1. MSK Security Group: Allow inbound traffic from the security group of the client in Account B. For example:
    • In the MSK security group, add an inbound rule with:
      • Protocol: TCP
      • Port Range: 9092 (or your Kafka listener port)
      • Source: The security group ID of the EC2 instance in Account B.

In Account B (where the client resides):

  1. Client Security Group: Allow outbound traffic to the MSK broker in Account A.
    • Outbound rule:
      • Protocol: TCP
      • Port Range: 9092
      • Destination: The MSK security group ID in Account A.

Private DNS Enablement

When MSK is set to use VPC endpoints (PrivateLink), private DNS resolution ensures the broker’s hostname resolves to the corresponding VPC endpoint. Typically, MSK manages this configuration automatically. You can verify this by:

  1. Checking the Enable Private DNS option for your VPC endpoint in the console.
  2. Confirming that DNS queries for the broker's hostname resolve to a private IP within the MSK VPC.

If private DNS isn't configured correctly, you might need to set custom DNS resolution using Route 53 or edit your local /etc/hosts file for testing.


Connection Not Accepted

If your network configuration and permissions are correct, but the Kafka connection is still not accepted, consider these points:

  1. Authentication: MSK supports SASL (e.g., SASL/SCRAM) or IAM authentication. Ensure your client is using the appropriate credentials or IAM roles for access.
  2. Broker Listener Configuration: Double-check the broker endpoints in the MSK console. Ensure your client uses the internal (private) endpoint if it's connecting from within the same VPC.
  3. CloudWatch Logs: Examine the error messages in the MSK broker logs for details. Common issues might include authentication failures or protocol mismatches.

Let me know if you'd like further clarification or help debugging! 😊


Cheers,

Aaron 😊

answered 2 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.