Skip to content

Commit

Permalink
fix(sns): contentBasedDeduplication is always false for imported topic (
Browse files Browse the repository at this point in the history
#29542)

Closes #29532.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
msambol committed Apr 6, 2024
1 parent 21dba21 commit 4a9e683
Show file tree
Hide file tree
Showing 7 changed files with 296 additions and 10 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,59 @@
"SignatureVersion": "2",
"TopicName": "fooTopicSignatureVersion"
}
},
"MyTopic288CE2107": {
"Type": "AWS::SNS::Topic",
"Properties": {
"DisplayName": "fooDisplayName2",
"KmsMasterKeyId": {
"Fn::GetAtt": [
"CustomKey1E6D0D07",
"Arn"
]
},
"TopicName": "fooTopic2"
}
},
"PublishRoleF42F66B6": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"PublishRoleDefaultPolicy9257B12D": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "sns:Publish",
"Effect": "Allow",
"Resource": {
"Ref": "MyTopic288CE2107"
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "PublishRoleDefaultPolicy9257B12D",
"Roles": [
{
"Ref": "PublishRoleF42F66B6"
}
]
}
}
},
"Parameters": {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,25 @@ class SNSInteg extends Stack {
successFeedbackSampleRate: 50,
});

// Topic with signatureVersion
new Topic(this, 'MyTopicSignatureVersion', {
topicName: 'fooTopicSignatureVersion',
displayName: 'fooDisplayNameSignatureVersion',
signatureVersion: '2',
});

// Can import topic
const topic2 = new Topic(this, 'MyTopic2', {
topicName: 'fooTopic2',
displayName: 'fooDisplayName2',
masterKey: key,
});
const importedTopic = Topic.fromTopicArn(this, 'ImportedTopic', topic2.topicArn);

const publishRole = new Role(this, 'PublishRole', {
assumedBy: new ServicePrincipal('s3.amazonaws.com'),
});
importedTopic.grantPublish(publishRole);
}
}

Expand Down
46 changes: 41 additions & 5 deletions packages/aws-cdk-lib/aws-sns/lib/topic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,24 @@ export enum LoggingProtocol {
APPLICATION = 'application',
}

/**
* Represents an SNS topic defined outside of this stack.
*/
export interface TopicAttributes {
/**
* The ARN of the SNS topic.
*/
readonly topicArn: string;

/**
* Whether content-based deduplication is enabled.
* Only applicable for FIFO topics.
*
* @default false
*/
readonly contentBasedDeduplication?: boolean;
}

/**
* A new SNS topic
*/
Expand All @@ -166,16 +184,34 @@ export class Topic extends TopicBase {
* @param topicArn topic ARN (i.e. arn:aws:sns:us-east-2:444455556666:MyTopic)
*/
public static fromTopicArn(scope: Construct, id: string, topicArn: string): ITopic {
return Topic.fromTopicAttributes(scope, id, { topicArn });
};

/**
* Import an existing SNS topic provided a topic attributes
*
* @param scope The parent creating construct
* @param id The construct's name
* @param attrs the attributes of the topic to import
*/
public static fromTopicAttributes(scope: Construct, id: string, attrs: TopicAttributes): ITopic {
const topicName = Stack.of(scope).splitArn(attrs.topicArn, ArnFormat.NO_RESOURCE_NAME).resource;
const fifo = topicName.endsWith('.fifo');

if (attrs.contentBasedDeduplication && !fifo) {
throw new Error('Cannot import topic; contentBasedDeduplication is only available for FIFO SNS topics.');
}

class Import extends TopicBase {
public readonly topicArn = topicArn;
public readonly topicName = Stack.of(scope).splitArn(topicArn, ArnFormat.NO_RESOURCE_NAME).resource;
public readonly fifo = this.topicName.endsWith('.fifo');
public readonly contentBasedDeduplication = false;
public readonly topicArn = attrs.topicArn;
public readonly topicName = topicName;
public readonly fifo = fifo;
public readonly contentBasedDeduplication = attrs.contentBasedDeduplication || false;
protected autoCreatePolicy: boolean = false;
}

return new Import(scope, id, {
environmentFromArn: topicArn,
environmentFromArn: attrs.topicArn,
});
}

Expand Down
42 changes: 42 additions & 0 deletions packages/aws-cdk-lib/aws-sns/test/sns.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,48 @@ describe('Topic', () => {
expect(imported.fifo).toEqual(true);
});

test('fromTopicAttributes contentBasedDeduplication false', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
const imported = sns.Topic.fromTopicAttributes(stack, 'Imported', {
topicArn: 'arn:aws:sns:*:123456789012:mytopic',
});

// THEN
expect(imported.topicName).toEqual('mytopic');
expect(imported.topicArn).toEqual('arn:aws:sns:*:123456789012:mytopic');
expect(imported.contentBasedDeduplication).toEqual(false);
});

test('fromTopicAttributes contentBasedDeduplication true', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
const imported = sns.Topic.fromTopicAttributes(stack, 'Imported', {
topicArn: 'arn:aws:sns:*:123456789012:mytopic.fifo',
contentBasedDeduplication: true,
});

// THEN
expect(imported.topicName).toEqual('mytopic.fifo');
expect(imported.topicArn).toEqual('arn:aws:sns:*:123456789012:mytopic.fifo');
expect(imported.contentBasedDeduplication).toEqual(true);
});

test('fromTopicAttributes throws with contentBasedDeduplication on non-fifo topic', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
expect(() => sns.Topic.fromTopicAttributes(stack, 'Imported', {
topicArn: 'arn:aws:sns:*:123456789012:mytopic',
contentBasedDeduplication: true,
})).toThrow(/Cannot import topic; contentBasedDeduplication is only available for FIFO SNS topics./);
});

test('sets account for imported topic env', () => {
// GIVEN
const stack = new cdk.Stack();
Expand Down

0 comments on commit 4a9e683

Please sign in to comment.