forked from newrelic/aws-unified-firehose
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfirehose-cloudwatch-trigger-stack.yaml
143 lines (129 loc) · 5.45 KB
/
firehose-cloudwatch-trigger-stack.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
LogGroupConfig:
Description: "JSON array of objects representing your LogGroup and Filters (if applicable). For example: [{\"LogGroupName\":\"logGroup1\",\"FilterPattern\":\"filter1\"}]"
Type: String
LogGroupArns:
Description: "Comma-separated list of CloudWatch Log Group ARNs to create subscription to Data Firehose"
Type: CommaDelimitedList
InvalidLogGroups:
Description: "Comma-separated list of CloudWatch Log Groups provided in use input which are invalid and should be skipped."
Type: CommaDelimitedList
LoggingFirehoseStreamArn:
Type: String
Description: "Data Firehose arn to create cloudwatch log group subscription"
Conditions:
HasValidLogGroups: !Not [!Equals [!Select [0, !Ref LogGroupArns], ""]]
Resources:
NewRelicLogsCloudWatchFirehoseLogGroupTriggers:
Type: 'Custom::CloudWatchNotifications'
Condition: HasValidLogGroups
Properties:
ServiceToken: !GetAtt NewRelicLogsCloudWatchFirehoseEventLambda.Arn
LoggingFirehoseStreamArn: !Ref LoggingFirehoseStreamArn
LogGroupConfig: !Ref LogGroupConfig
InvalidLogGroups: !Ref InvalidLogGroups
NewRelicLogsCloudWatchFirehoseLambdaIAMRole:
Type: "AWS::IAM::Role"
Condition: HasValidLogGroups
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: "LambdaExecutionPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- logs:PutSubscriptionFilter
Resource: !Ref LogGroupArns
- Effect: Allow
Action:
- 'logs:CreateLogGroup'
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
Resource: 'arn:aws:logs:*:*:*'
- Effect: Allow
Action:
- 'iam:PassRole'
Resource: !GetAtt NewRelicLogsCloudWatchFirehoseIAMRole.Arn
NewRelicLogsCloudWatchFirehoseIAMRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- logs.amazonaws.com
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: "FirehoseWritePolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- firehose:PutRecord
- firehose:PutRecordBatch
Resource: !Ref LoggingFirehoseStreamArn
NewRelicLogsCloudWatchFirehoseEventLambda:
Type: 'AWS::Lambda::Function'
Condition: HasValidLogGroups
Properties:
Environment:
Variables:
CloudWatchFirehoseRoleArn: !GetAtt NewRelicLogsCloudWatchFirehoseIAMRole.Arn
Code:
ZipFile: |
import json
import boto3
import cfnresponse
import logging
import os
logger = logging.getLogger()
logger.setLevel(logging.INFO)
log_client = boto3.client('logs')
def lambda_handler(event, context):
response = {}
try:
if event['RequestType'] == 'Create' or event['RequestType'] == 'Update':
event_data = event['ResourceProperties']
firehose_arn = event_data.get('LoggingFirehoseStreamArn', '')
log_group_config_str = event_data.get('LogGroupConfig', [])
invalid_log_groups = set(event_data.get('InvalidLogGroups', []))
logger.info(f'Invalid Log Groups: {invalid_log_groups}')
# Parsing LogGroupConfig JSON array
log_group_config = json.loads(log_group_config_str)
for log_group in log_group_config:
log_group_name = log_group['LogGroupName']
if log_group_name in invalid_log_groups:
logger.info(f'Log group {log_group_name} is invalid. Skipping...')
continue
filter_pattern = log_group['FilterPattern'] if 'FilterPattern' in log_group else ''
cloudwatch_firehose_role_arn = os.environ['CloudWatchFirehoseRoleArn']
response = log_client.put_subscription_filter(
logGroupName=log_group_name,
roleArn=cloudwatch_firehose_role_arn,
filterName='LoggingFirehoseSubscription',
filterPattern=filter_pattern,
destinationArn=firehose_arn
)
cfnresponse.send(event, context, cfnresponse.SUCCESS, response)
except Exception as e:
logger.error(f'Error: {str(e)}')
cfnresponse.send(event, context, cfnresponse.FAILED, {}, reason=f'{str(e)}')
Handler: index.lambda_handler
Role: !GetAtt NewRelicLogsCloudWatchFirehoseLambdaIAMRole.Arn
Runtime: python3.12
Timeout: 120