Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(msk-alpha): support any combination of client auth mechanisms #30307

Closed
wants to merge 55 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
92ffc5f
feat: support multiple client auth mechanisms
May 22, 2024
bb72fc6
chore: simplify clientAuthentication assignment
May 22, 2024
8e3e453
chore: integrationtest
May 23, 2024
00ca60f
fix(stepfunctions-tasks): runtime language used to evaluate expressio…
colifran May 22, 2024
c6c5ff1
feat(ec2): support placementGroup for ec2.Instance (#30293)
pahud May 22, 2024
44ab15d
fix(rds): readers not always be created after the writer (#30277)
pahud May 22, 2024
76361db
chore: add new team member `samson-keung` (#30312)
samson-keung May 22, 2024
81838d1
feat: update L1 CloudFormation resource definitions (#30182)
aws-cdk-automation May 22, 2024
ff9b98f
feat(codebuild): add deleteReports property to the ReportGroup Constr…
mazyu36 May 23, 2024
8323a70
chore(release): 2.143.0
May 23, 2024
ef589bf
chore(release): remove reverted PR from changelog
shikha372 May 23, 2024
479ad1c
revert: "fix(ses-actions): permissions too wide for S3 action" (#30375)
shikha372 May 29, 2024
0047b82
chore(release): 2.143.1
shikha372 May 30, 2024
e94ae5e
chore(rds): add default engine version for aurora mysql version "3.0…
yasomaru May 24, 2024
0c4fe06
docs(rds): improve docs about serverless v1 (#30316)
mazyu36 May 24, 2024
c00ace0
feat(ivs-alpha): support advanced channel type (#30086)
mazyu36 May 24, 2024
fda4546
feat(stepfunctions-tasks): support for the step functions mediaconver…
PavanRangudu May 24, 2024
cd1324c
feat(ec2): support `instanceInitiatedShutdownBehavior` for EC2 instan…
badmintoncryer May 27, 2024
aaacbc9
chore(deps): bump tj-actions/changed-files from 44.4.0 to 44.5.1 (#30…
dependabot[bot] May 27, 2024
7093524
feat: update L1 CloudFormation resource definitions (#30354)
aws-cdk-automation May 27, 2024
20bdc74
feat(stepfunctions-tasks): add workerType and numberOfWorkers to Glue…
mazyu36 May 27, 2024
affe6cf
chore(bedrock): support missing model versions in Amazon Bedrock mode…
yasomaru May 27, 2024
163c56d
fix(fsx): no validation error when `hour` property set to 24 in the `…
mazyu36 May 27, 2024
7b30b3f
feat(neptune): add copyTagsToSnapshot property to the DatabaseCluster…
mazyu36 May 27, 2024
e0d51cb
feat(ecs-patterns): allow custom container name for Scheduled ecs and…
moelasmar May 28, 2024
5f219e8
refactor(diff): make dedicated file and class for incorporating chang…
bergjaak May 28, 2024
43381bc
fix(s3): publicReadAccess causes deployment failure due to access den…
GavinZZ May 28, 2024
017ad4a
feat(appconfig): add grantReadConfig method to Environment Construct …
mazyu36 May 29, 2024
12e9611
chore(ecs): incorrect formatting of throw statement in the fromServic…
mazyu36 May 29, 2024
06a6705
chore(ec2): eventbridge pipes `pipes-data` vpc endpoint (#30246)
Liversticks May 29, 2024
d4b3756
feat(dynamodb): add resource polices for table (#30251)
LeeroyHannigan May 29, 2024
eb7c108
fix(lambda): use enum values for applicationLogLevel and systemLogLev…
dali546 May 29, 2024
255768c
feat(apprunner): add kmsKey property for the AppRunner Service class …
mazyu36 May 30, 2024
a440d02
fix(ecs): removed omitEmptyArray for placementConstraints (#27555) (#…
stm29 May 30, 2024
0ecc8b3
fix(stepfunctions): cannot use intrinsic functions in Fail state (#30…
sakurai-ryo May 30, 2024
6f32daa
chore: only use 50% of workers for jest (#30393)
TheRealAmazonKendra May 30, 2024
d920078
docs(apigatewayv2-integrations): add `StepFunctions Integration` to t…
badmintoncryer May 30, 2024
686f8b6
feat(lambda): allow running a build file (#30196)
bergjaak May 30, 2024
56d9f8c
docs(s3-deployment): update development section of readme (#30253)
neo01124 May 31, 2024
1c45651
fix(eks): add tag update support for eks cluster (#30123)
mrlikl May 31, 2024
4c351e7
chore(release): 2.144.0
May 31, 2024
a72016d
chore: remove revert from changelog
TheRealAmazonKendra May 31, 2024
1589f08
chore: update Contributors File (#30411)
aws-cdk-automation Jun 1, 2024
3e09e60
fix(apigateway): allow overriding authorizer on methods (#30415)
moelasmar Jun 1, 2024
419a974
chore(deps): bump tj-actions/changed-files from 44.5.1 to 44.5.2 (#30…
dependabot[bot] Jun 3, 2024
9d3f018
chore: fix typo in `queue.ts` comment (#30416)
rafrafek Jun 3, 2024
0afafaa
chore: fix typo in application-listener-rule (#30427)
mazyu36 Jun 3, 2024
36aa6a1
chore(config): add new resource types since March 2023 (#30378)
mazyu36 Jun 3, 2024
52d4f00
feat(logs): add distribution property to the Subscription class (#30423)
mazyu36 Jun 3, 2024
51d04da
feat(chatbot): configure `userRoleRequired` for the `SlackChannelConf…
badmintoncryer Jun 3, 2024
4f11c06
feat(codepipeline): `GitPushFilter` with branches and file paths for …
go-to-k Jun 3, 2024
d2df6cf
fix: route53 CrossAccountZoneDelegationRecord fails at deployment tim…
samson-keung Jun 4, 2024
127add3
chore: update nodejs to 20 in devcontainer and gitpod (#30424)
JohannesKonings Jun 4, 2024
a11831a
feat(codebuild): `Fleet` L2 (#29754)
nmussy Jun 4, 2024
b76ec12
chore(dynamodb): remove single quotes from throw statement in the par…
mazyu36 Jun 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions packages/@aws-cdk/aws-msk-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,25 @@ const cluster = new msk.Cluster(this, 'cluster', {
});
```

### SASL/SCRAM + SASL/IAM

Enable client authentication with [IAM](https://docs.aws.amazon.com/msk/latest/developerguide/iam-access-control.html) and [SASL/SCRAM](https://docs.aws.amazon.com/msk/latest/developerguide/msk-password.html):

```ts
declare const vpc: ec2.Vpc;
const cluster = new msk.Cluster(this, 'cluster', {
clusterName: 'myCluster',
kafkaVersion: msk.KafkaVersion.V2_8_1,
vpc,
encryptionInTransit: {
clientBroker: msk.ClientBrokerEncryption.TLS,
},
clientAuthentication: msk.ClientAuthentication.sasl({
iam: true,
scram: true,
}),
});
```

### SASL/IAM + TLS

Expand Down
51 changes: 12 additions & 39 deletions packages/@aws-cdk/aws-msk-alpha/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,13 +496,6 @@ export class Cluster extends ClusterBase {
);
}

if (
props.clientAuthentication?.saslProps?.iam &&
props.clientAuthentication?.saslProps?.scram
) {
throw Error('Only one client authentication method can be enabled.');
}

if (
props.encryptionInTransit?.clientBroker ===
ClientBrokerEncryption.PLAINTEXT &&
Expand Down Expand Up @@ -685,38 +678,18 @@ export class Cluster extends ClusterBase {
);
}

let clientAuthentication;
if (props.clientAuthentication?.saslProps?.iam) {
clientAuthentication = {
sasl: { iam: { enabled: props.clientAuthentication.saslProps.iam } },
};
if (props.clientAuthentication?.tlsProps) {
clientAuthentication = {
sasl: { iam: { enabled: props.clientAuthentication.saslProps.iam } },
tls: {
certificateAuthorityArnList: props.clientAuthentication?.tlsProps?.certificateAuthorities?.map(
(ca) => ca.certificateAuthorityArn,
),
},
};
}
} else if (props.clientAuthentication?.saslProps?.scram) {
clientAuthentication = {
sasl: {
scram: {
enabled: props.clientAuthentication.saslProps.scram,
},
},
let clientAuthentication: any = {};

if (props.clientAuthentication?.saslProps) {
clientAuthentication.sasl = {
...(props.clientAuthentication?.saslProps?.iam ? { iam: { enabled: props.clientAuthentication.saslProps.iam } } : {}),
...(props.clientAuthentication?.saslProps?.scram ? { scram: { enabled: props.clientAuthentication.saslProps.scram } } : {}),
};
} else if (
props.clientAuthentication?.tlsProps?.certificateAuthorities !== undefined
) {
clientAuthentication = {
tls: {
certificateAuthorityArnList: props.clientAuthentication?.tlsProps?.certificateAuthorities.map(
(ca) => ca.certificateAuthorityArn,
),
},
}

if (props.clientAuthentication?.tlsProps) {
clientAuthentication.tls = {
certificateAuthorityArnList: props.clientAuthentication.tlsProps?.certificateAuthorities?.map((ca) => ca.certificateAuthorityArn),
};
}

Expand Down Expand Up @@ -831,7 +804,7 @@ export class Cluster extends ClusterBase {
*/
private _bootstrapBrokers(responseField: string): string {
if (!this._clusterBootstrapBrokers) {
this._clusterBootstrapBrokers = new cr.AwsCustomResource(this, `BootstrapBrokers${responseField}`, {
this._clusterBootstrapBrokers = new cr.AwsCustomResource(this, 'BootstrapBrokers', {
onUpdate: {
service: 'Kafka',
action: 'getBootstrapBrokers',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ exports[`MSK Cluster Snapshot test with all values set 1`] = `
}
`;

exports[`MSK Cluster created with authentication enabled with sasl/iam auth and tls Snapshot test with all values set (iam/sasl) 1`] = `
exports[`MSK Cluster created with authentication enabled with sasl/iam auth, sasl/scram auth and tls auth Snapshot test with all values set (iam/sasl) 1`] = `
{
"Resources": {
"Vpc8378EB38": {
Expand Down Expand Up @@ -915,6 +915,9 @@ exports[`MSK Cluster created with authentication enabled with sasl/iam auth and
"Iam": {
"Enabled": true,
},
"Scram": {
"Enabled": true,
},
},
"Tls": {
"CertificateAuthorityArnList": [
Expand Down Expand Up @@ -965,6 +968,89 @@ exports[`MSK Cluster created with authentication enabled with sasl/iam auth and
"Type": "AWS::MSK::Cluster",
"UpdateReplacePolicy": "Retain",
},
"kafkaSASLKey69FC3AFA": {
"DeletionPolicy": "Retain",
"Properties": {
"Description": "Used for encrypting MSK secrets for SASL/SCRAM authentication.",
"KeyPolicy": {
"Statement": [
{
"Action": "kms:*",
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition",
},
":iam::",
{
"Ref": "AWS::AccountId",
},
":root",
],
],
},
},
"Resource": "*",
},
{
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:CreateGrant",
"kms:DescribeKey",
],
"Condition": {
"StringEquals": {
"kms:CallerAccount": {
"Ref": "AWS::AccountId",
},
"kms:ViaService": {
"Fn::Join": [
"",
[
"secretsmanager.",
{
"Ref": "AWS::Region",
},
".amazonaws.com",
],
],
},
},
},
"Effect": "Allow",
"Principal": {
"AWS": "*",
},
"Resource": "*",
"Sid": "Allow access through AWS Secrets Manager for all principals in the account that are authorized to use AWS Secrets Manager",
},
],
"Version": "2012-10-17",
},
},
"Type": "AWS::KMS::Key",
"UpdateReplacePolicy": "Retain",
},
"kafkaSASLKeyAlias7A73E101": {
"Properties": {
"AliasName": "alias/msk/test-cluster/sasl/scram",
"TargetKeyId": {
"Fn::GetAtt": [
"kafkaSASLKey69FC3AFA",
"Arn",
],
},
},
"Type": "AWS::KMS::Alias",
},
"sg1fromsg32181E6F4C07E": {
"Properties": {
"Description": "from sg3:2181",
Expand Down
84 changes: 66 additions & 18 deletions packages/@aws-cdk/aws-msk-alpha/test/cluster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,71 @@ describe('MSK Cluster', () => {
});
});

describe('with sasl/iam auth and tls', () => {
describe('with sasl/iam and sasl/scram', () => {
test('iam and scram enabled is true', () => {
new msk.Cluster(stack, 'Cluster', {
clusterName: 'cluster',
kafkaVersion: msk.KafkaVersion.V3_6_0,
vpc,
encryptionInTransit: {
clientBroker: msk.ClientBrokerEncryption.TLS,
},
clientAuthentication: msk.ClientAuthentication.sasl({
iam: true,
scram: true,
}),
});

Template.fromStack(stack).hasResourceProperties('AWS::MSK::Cluster', {
ClientAuthentication: {
Sasl: {
Iam: { Enabled: true },
Scram: { Enabled: true },
},
},
});
});

test('fails if tls encryption is set to plaintext', () => {
expect(() => new msk.Cluster(stack, 'Cluster', {
clusterName: 'cluster',
kafkaVersion: msk.KafkaVersion.V2_6_1,
vpc,
encryptionInTransit: {
clientBroker: msk.ClientBrokerEncryption.PLAINTEXT,
},
clientAuthentication: msk.ClientAuthentication.sasl({
iam: true,
scram: true,
}),
}),
).toThrow(
'To enable client authentication, you must enabled TLS-encrypted traffic between clients and brokers.',
);
});

test('fails if tls encryption is set to tls and plaintext', () => {
expect(
() =>
new msk.Cluster(stack, 'Cluster', {
clusterName: 'cluster',
kafkaVersion: msk.KafkaVersion.V2_6_1,
vpc,
encryptionInTransit: {
clientBroker: msk.ClientBrokerEncryption.TLS_PLAINTEXT,
},
clientAuthentication: msk.ClientAuthentication.sasl({
iam: true,
scram: true,
}),
}),
).toThrow(
'To enable SASL/SCRAM or IAM authentication, you must only allow TLS-encrypted traffic between clients and brokers.',
);
});
});

describe('with sasl/iam auth, sasl/scram auth and tls auth', () => {
test('Snapshot test with all values set (iam/sasl)', () => {
const cluster = new msk.Cluster(stack, 'kafka', {
clusterName: 'test-cluster',
Expand All @@ -249,6 +313,7 @@ describe('MSK Cluster', () => {
},
clientAuthentication: msk.ClientAuthentication.saslTls({
iam: true,
scram: true,
certificateAuthorities: [
acmpca.CertificateAuthority.fromCertificateAuthorityArn(
stack,
Expand Down Expand Up @@ -373,23 +438,6 @@ describe('MSK Cluster', () => {
});
});

test('fails if more than one authentication method is enabled', () => {
expect(
() =>
new msk.Cluster(stack, 'Cluster', {
clusterName: 'cluster',
kafkaVersion: msk.KafkaVersion.V2_6_1,
vpc,
encryptionInTransit: {
clientBroker: msk.ClientBrokerEncryption.TLS,
},
clientAuthentication: msk.ClientAuthentication.sasl({
iam: true,
scram: true,
}),
}),
).toThrow('Only one client authentication method can be enabled.');
});
});

describe('created with an instance type set', () => {
Expand Down
Loading