-
-
Notifications
You must be signed in to change notification settings - Fork 0
AWS MSK IAM
AWS MSK exposes IAM auth via SASL/OAUTHBEARER — the bearer token is an AWS Signature V4 signature, not a JWT. @eventferry/kafka-iam wraps the official aws-msk-iam-sasl-signer-js library and gives you a one-liner sasl block for the publisher.
Separate package on purpose — the core @eventferry/kafka surface stays AWS-free, and users who don't run MSK never pull aws-sdk into their tree.
npm i @eventferry/kafka-iam aws-msk-iam-sasl-signer-jsaws-msk-iam-sasl-signer-js is the AWS-official SigV4 signer; declared as an optional peer.
import { KafkaPublisher } from "@eventferry/kafka";
import { createMskIamSasl } from "@eventferry/kafka-iam";
const publisher = new KafkaPublisher({
brokers: ["b-1.cluster.us-east-1.amazonaws.com:9098"],
ssl: true,
sasl: createMskIamSasl({ region: "us-east-1" }),
});
await publisher.connect();createMskIamSasl({ region }) returns a SaslOauthbearerConfig — drops directly into KafkaPublisher's sasl option.
The signer reads AWS credentials from the standard SDK chain: environment vars, EC2 instance metadata, ECS task role, EKS service account, ~/.aws/credentials. No explicit credential plumbing.
createMskIamSasl({
region: "us-east-1",
awsProfile: "prod", // ~/.aws/credentials profile
});Use when the deploy environment has multiple profiles or you're running locally against a non-default one.
createMskIamSasl({
region: "us-east-1",
awsRoleArn: "arn:aws:iam::123456789012:role/eventferry-publisher",
awsRoleSessionName: "eventferry-prod", // default "MSKSASLDefaultSession"
});The signer calls AssumeRole itself before signing. Useful for cross-account MSK clusters where your service runs under a different account than the broker.
awsProfile and awsRoleArn are mutually exclusive — pick one.
createMskIamSasl({
region: "us-east-1",
awsStsRegion: "us-east-1-fips", // STS region override
});Use when your STS endpoint differs from the signing region (FIPS / VPC endpoint setups).
MSK IAM tokens have a 15-minute lifetime. The helper caches the most recent token process-locally and refreshes shortly before expiry:
- Default
refreshAheadMs: 60_000— the cache returns a fresh token when remaining lifetime drops below 60 seconds. - Concurrent invocations during a refresh share a single in-flight signer call — no thundering herd at the SigV4 signer.
- Transient signer failures (network blip during refresh) clear the in-flight slot so the next call retries cleanly. Otherwise a brief outage would poison the cache and break every subsequent publish.
Tighten or loosen the refresh window:
createMskIamSasl({
region: "us-east-1",
refreshAheadMs: 120_000, // refresh 2 min before expiry
});For workloads where you can't tolerate a single refresh blip, drop refreshAheadMs lower — the cost is more signer calls (~1 per refresh window vs ~1 every 14 minutes).
The SASL principal defaults to "eventferry". Override when your alerting / audit expects a specific name:
createMskIamSasl({
region: "us-east-1",
principal: "orders-service",
});This is the field that lands on the broker's principal audit log, not the IAM role name. The IAM identity is still determined by the SigV4 signature.
For tests or non-standard signers:
createMskIamSasl({
region: "us-east-1",
signer: {
async generateAuthToken({ region }) {
return {
token: await mySignerFor(region),
expiryTime: Date.now() + 15 * 60 * 1000,
};
},
},
});When signer is set, the helper does NOT dynamically import aws-msk-iam-sasl-signer-js. Useful for unit tests that don't have AWS credentials available.
The IAM identity running the publisher needs:
If you use publisher.admin() / ensureTopics, add kafka-cluster:CreateTopic and kafka-cluster:DescribeCluster. If you use transactions, add kafka-cluster:WriteDataIdempotently.
For a complete policy by feature, see AWS MSK IAM docs.
| Symptom | Likely cause |
|---|---|
createMskIamSasl requires the "aws-msk-iam-sasl-signer-js" package |
Optional peer not installed — npm i aws-msk-iam-sasl-signer-js. |
Could not load credentials from any providers |
AWS credential chain didn't find anything. Set AWS_REGION / AWS_PROFILE, or attach an IAM role to the host. |
Producer connects but immediate SASL_AUTHENTICATION_FAILED
|
Token signed for wrong region, IAM identity missing Connect action, or cluster-level IAM auth not enabled. |
| Works locally, fails in EKS | Service account → IAM role mapping (IRSA) missing. Annotate the SA with eks.amazonaws.com/role-arn. |
- General OAUTHBEARER + other SASL mechanisms → Authentication and TLS
- Producer config → Kafka Publisher
- Multi-instance EOS on MSK → Transactions and EOS
Repository · Issues · npm: @eventferry/all · MIT
Get going
Adapters
Type & schema
Security
Operational
- Transactions and EOS
- Admin Operations
- Observability
- Consuming Events
- Dead-Letter Queue
- Reliability and Error Handling
Operations
Reference
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["kafka-cluster:Connect"], "Resource": "arn:aws:kafka:us-east-1:123456789012:cluster/your-cluster/<uuid>" }, { "Effect": "Allow", "Action": ["kafka-cluster:WriteData", "kafka-cluster:DescribeTopic"], "Resource": "arn:aws:kafka:us-east-1:123456789012:topic/your-cluster/<uuid>/*" }, { "Effect": "Allow", "Action": ["kafka-cluster:AlterCluster"], "Resource": "arn:aws:kafka:us-east-1:123456789012:cluster/your-cluster/<uuid>" } ] }