Skip to content

Commit 51f33c4

Browse files
authored
Create elastio-alerts-to-s3.yaml (#132)
1 parent ee7cbf9 commit 51f33c4

1 file changed

Lines changed: 175 additions & 0 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Description: 'CloudFormation template for Elastio Webhook Integration with S3'
3+
4+
Parameters:
5+
AuthToken:
6+
Type: String
7+
NoEcho: true
8+
Description: Authentication token for webhook validation
9+
10+
S3BucketName:
11+
Type: String
12+
Description: Name of the S3 bucket to store webhook events
13+
14+
Resources:
15+
WebhookEventsBucket:
16+
Type: AWS::S3::Bucket
17+
Properties:
18+
BucketName: !Ref S3BucketName
19+
BucketEncryption:
20+
ServerSideEncryptionConfiguration:
21+
- ServerSideEncryptionByDefault:
22+
SSEAlgorithm: AES256
23+
24+
WebhookSecret:
25+
Type: AWS::SecretsManager::Secret
26+
Properties:
27+
Name: !Sub '${AWS::StackName}-webhook-secret'
28+
SecretString: !Sub '{"AUTHTOKEN":"${AuthToken}"}'
29+
30+
WebhookFunction:
31+
Type: AWS::Lambda::Function
32+
Properties:
33+
FunctionName: !Sub '${AWS::StackName}-webhook-handler'
34+
Handler: index.lambda_handler
35+
Role: !GetAtt WebhookLambdaRole.Arn
36+
Code:
37+
ZipFile: |
38+
import json
39+
import os
40+
import uuid
41+
from datetime import datetime
42+
import boto3
43+
from botocore.exceptions import ClientError
44+
45+
def get_secret(secret_name, region_name):
46+
session = boto3.session.Session()
47+
client = session.client(service_name='secretsmanager', region_name=region_name)
48+
try:
49+
get_secret_value_response = client.get_secret_value(SecretId=secret_name)
50+
except ClientError as e:
51+
raise e
52+
return json.loads(get_secret_value_response['SecretString'])
53+
54+
def validate_api_key(auth_token, api_key):
55+
return auth_token == api_key
56+
57+
def lambda_handler(event, context):
58+
try:
59+
secret_name = os.environ["SECRETNAME"]
60+
region_name = os.environ["AWSREGION"]
61+
s3_bucket = os.environ["S3BUCKET"]
62+
except KeyError as exc:
63+
print(f"Required environment variable {exc} missing")
64+
return {
65+
"statusCode": 400,
66+
"body": json.dumps(f"Required environment variable {exc} missing")
67+
}
68+
69+
try:
70+
secret = get_secret(secret_name, region_name)
71+
auth_token = secret["AUTHTOKEN"]
72+
api_key = event.get("headers", {}).get("x-api-key")
73+
if not validate_api_key(auth_token, api_key):
74+
print("Unauthorized: Invalid API key")
75+
return {
76+
"statusCode": 401,
77+
"body": json.dumps("Unauthorized")
78+
}
79+
except Exception as e:
80+
print(f"Error in API key validation: {str(e)}")
81+
return {
82+
"statusCode": 500,
83+
"body": json.dumps("Internal server error during authentication")
84+
}
85+
86+
try:
87+
if event.get("isBase64Encoded", False):
88+
import base64
89+
body = json.loads(base64.b64decode(event["body"]))
90+
else:
91+
body = json.loads(event["body"])
92+
93+
timestamp = datetime.utcnow().strftime("%Y%m%d-%H%M%S")
94+
unique_id = str(uuid.uuid4())
95+
filename = f"{timestamp}-{unique_id}.json"
96+
97+
s3 = boto3.client('s3')
98+
s3.put_object(
99+
Bucket=s3_bucket,
100+
Key=filename,
101+
Body=json.dumps(body, ensure_ascii=False).encode('utf8'),
102+
ContentType='application/json'
103+
)
104+
105+
print(f"Successfully stored event in S3: s3://{s3_bucket}/{filename}")
106+
return {
107+
"statusCode": 200,
108+
"body": json.dumps("Event successfully processed and stored")
109+
}
110+
except Exception as e:
111+
print(f"Error processing event: {str(e)}")
112+
return {
113+
"statusCode": 500,
114+
"body": json.dumps(f"Error processing event: {str(e)}")
115+
}
116+
Runtime: python3.13
117+
Timeout: 10
118+
Environment:
119+
Variables:
120+
AWSREGION: !Ref AWS::Region
121+
S3BUCKET: !Ref S3BucketName
122+
SECRETNAME: !Ref WebhookSecret
123+
124+
WebhookFunctionUrl:
125+
Type: AWS::Lambda::Url
126+
Properties:
127+
AuthType: NONE
128+
TargetFunctionArn: !GetAtt WebhookFunction.Arn
129+
130+
WebhookFunctionUrlPermission:
131+
Type: AWS::Lambda::Permission
132+
Properties:
133+
FunctionName: !Ref WebhookFunction
134+
Action: lambda:InvokeFunctionUrl
135+
Principal: '*'
136+
FunctionUrlAuthType: NONE
137+
138+
WebhookLambdaRole:
139+
Type: AWS::IAM::Role
140+
Properties:
141+
AssumeRolePolicyDocument:
142+
Version: '2012-10-17'
143+
Statement:
144+
- Effect: Allow
145+
Principal:
146+
Service: lambda.amazonaws.com
147+
Action: sts:AssumeRole
148+
ManagedPolicyArns:
149+
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
150+
Policies:
151+
- PolicyName: WebhookLambdaPolicy
152+
PolicyDocument:
153+
Version: '2012-10-17'
154+
Statement:
155+
- Effect: Allow
156+
Action:
157+
- s3:PutObject
158+
Resource: !Sub '${WebhookEventsBucket.Arn}/*'
159+
- Effect: Allow
160+
Action:
161+
- secretsmanager:GetSecretValue
162+
Resource: !Ref WebhookSecret
163+
164+
Outputs:
165+
FunctionUrl:
166+
Description: URL endpoint for webhook
167+
Value: !GetAtt WebhookFunctionUrl.FunctionUrl
168+
169+
SecretName:
170+
Description: Name of the secret containing the auth token
171+
Value: !Ref WebhookSecret
172+
173+
S3BucketName:
174+
Description: Name of the S3 bucket for webhook events
175+
Value: !Ref S3BucketName

0 commit comments

Comments
 (0)