Skip to content

Commit d4eff6d

Browse files
committed
feat: Support creating a SNS topic
1 parent 69a493b commit d4eff6d

5 files changed

Lines changed: 103 additions & 3 deletions

File tree

layer/python/cloudtrail_watcher/services/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@
1616
'dynamodb',
1717
'elasticloadbalancing',
1818
'cloudfront',
19-
'sqs'
19+
'sqs',
20+
'sns'
2021
]
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import boto3
2+
3+
from .common import *
4+
5+
sns = boto3.client('sns')
6+
7+
def process_event(event: dict, set_tag: bool = False) -> dict:
8+
""" Process CloudTrail event for sns """
9+
10+
result = dict()
11+
12+
if event['eventName'] == 'CreateTopic':
13+
result['resource_id'] = _process_create_topic(event, set_tag)
14+
else:
15+
message = f"Cannot process event: {event['eventName']}, eventID: {event['eventID']}"
16+
result['error'] = message
17+
18+
return result
19+
20+
21+
def _process_create_topic(event: dict, set_tag: bool = False) -> list:
22+
""" Process CreateTopic event """
23+
24+
topic_arn = event['responseElements']['topicArn']
25+
topic_name = event['requestParameters']['name']
26+
27+
if set_tag:
28+
if not check_contain_mandatory_tag_list(event['requestParameters']['tags']):
29+
sns.tag_resource(
30+
ResourceArn=topic_arn,
31+
Tags=[{'Key': 'User', 'Value': get_user_identity(event)}]
32+
)
33+
34+
return [topic_name]

template.sar.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ Resources:
6969
"cloudfront:TagResource",
7070
"ecr:ListTagsForResource",
7171
"ecr:TagResource",
72-
"sqs:TagQueue"
72+
"sqs:TagQueue",
73+
"sns:TagResource"
7374
]
7475
Resource: "*"
7576

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"eventVersion": "1.11",
3+
"userIdentity": {
4+
"type": "IAMUser",
5+
"principalId": "YOUR_PRINCIPAL_ID",
6+
"arn": "arn:aws:iam::000000000000:user/test_user",
7+
"accountId": "000000000000",
8+
"accessKeyId": "YOUR_ACCESS_KEY_ID",
9+
"userName": "test_user",
10+
"sessionContext": {
11+
"attributes": {
12+
"creationDate": "2025-09-05T02:33:23Z",
13+
"mfaAuthenticated": "true"
14+
}
15+
}
16+
},
17+
"eventTime": "2025-09-05T13:15:27Z",
18+
"eventSource": "sns.amazonaws.com",
19+
"eventName": "CreateTopic",
20+
"awsRegion": "ap-northeast-2",
21+
"sourceIPAddress": "127.0.0.1",
22+
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
23+
"requestParameters": {
24+
"name": "sns-test.fifo",
25+
"attributes": {
26+
"Policy": "{\"Version\":\"2008-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:Publish\",\"SNS:RemovePermission\",\"SNS:SetTopicAttributes\",\"SNS:DeleteTopic\",\"SNS:ListSubscriptionsByTopic\",\"SNS:GetTopicAttributes\",\"SNS:AddPermission\",\"SNS:Subscribe\"],\"Resource\":\"arn:aws:sns:ap-northeast-2:000000000000:sns-test.fifo\",\"Condition\":{\"StringEquals\":{\"AWS:SourceAccount\":\"000000000000\"}}}]}",
27+
"TracingConfig": "PassThrough",
28+
"FifoTopic": "true",
29+
"FifoThroughputScope": "MessageGroup"
30+
},
31+
"tags": []
32+
},
33+
"responseElements": {
34+
"topicArn": "arn:aws:sns:ap-northeast-2:000000000000:sns-test.fifo"
35+
},
36+
"requestID": "e9345ab2-abc8-5d6e-a882-3b864f67588a",
37+
"eventID": "ae241752-2a62-4166-9991-c1854aee9d36",
38+
"readOnly": false,
39+
"eventType": "AwsApiCall",
40+
"managementEvent": true,
41+
"recipientAccountId": "000000000000",
42+
"eventCategory": "Management",
43+
"tlsDetails": {
44+
"tlsVersion": "TLSv1.3",
45+
"cipherSuite": "TLS_AES_128_GCM_SHA256",
46+
"clientProvidedHostHeader": "sns.ap-northeast-2.amazonaws.com"
47+
},
48+
"sessionCredentialFromConsole": "true"
49+
}

test/services/test_services.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,19 @@ def test_create_queue(self):
428428
self.assertEqual(result['region'], 'ap-northeast-2')
429429
self.assertEqual(result['event_name'], 'CreateQueue')
430430
self.assertEqual(result['source_ip_address'], '127.0.0.1')
431-
self.assertEqual(result['event_source'], 'sqs')
431+
self.assertEqual(result['event_source'], 'sqs')
432+
433+
434+
class SNSTest(unittest.TestCase):
435+
def test_create_topic(self):
436+
with open('./samples/sns_CreateTopic.json') as f:
437+
data = json.loads(f.read())
438+
439+
result = build_result(data)
440+
441+
self.assertEqual(result['resource_id'], ['sns-test.fifo'])
442+
self.assertEqual(result['identity'], 'user/test_user')
443+
self.assertEqual(result['region'], 'ap-northeast-2')
444+
self.assertEqual(result['event_name'], 'CreateTopic')
445+
self.assertEqual(result['source_ip_address'], '127.0.0.1')
446+
self.assertEqual(result['event_source'], 'sns')

0 commit comments

Comments
 (0)