-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.yaml
131 lines (120 loc) · 4.89 KB
/
main.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
AWSTemplateFormatVersion: 2010-09-09
Description: This template defines a Custom Resource (to retrieve the ARN of a global WAF Web ACL), and a CloudFront distribution to which the ACL is attached.
Parameters:
pS3BucketName:
Description: Name for the S3 bucket that's the origin of the CloudFront distribution.
Type: String
Resources:
# IAM role for the WAF Web ACL Custom Resource backing Lambda
WafWebAclCustomResourceLambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: [lambda.amazonaws.com]
Action: ['sts:AssumeRole']
Policies:
- PolicyName: WafWebAclLambdaCustomResourcePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: ['logs:*']
Resource: 'arn:aws:logs:*:*:*'
- Effect: Allow
Action: ['wafv2:ListWebACLs']
Resource: 'arn:aws:wafv2:*'
# Permissions for CloudFormation to invoke the WAF Web ACL Custom Resource backing Lambda
CloudFormationLambdaFunctionPermission:
Type: AWS::Lambda::Permission
Properties:
Action: 'lambda:InvokeFunction'
FunctionName: !GetAtt WafWebAclCustomResourceLambdaFunction.Arn
Principal: 'cloudformation.amazonaws.com'
# WAF Web ACL Custom Resource backing Lambda function
WafWebAclCustomResourceLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: |
import boto3
import json
import cfnresponse
wafClient = boto3.client('wafv2', region_name='us-east-1')
def handler(event, context):
print(json.dumps(event))
responseData = {}
try:
# for Delete requests, immediately send a SUCCESS response
if (event['RequestType'] == 'Delete'):
cfnresponse.send(event, context, cfnresponse.SUCCESS,
responseData, 'WafWebAclCustomResource')
# retrieve all web ACLs
wafWebAclsResponse = wafClient.list_web_acls(Scope='CLOUDFRONT')
print(json.dumps(wafWebAclsResponse))
# filter for our intended one by name
wafWebAcl = next(
(acl for acl in wafWebAclsResponse['WebACLs'] if acl['Name'] == 'owasp-top10-waf-v2-acl'), None)
print(json.dumps(wafWebAcl))
if wafWebAcl is None:
# if not found, return failure
responseData['Error'] = 'Could not retrieve OWASP Top 10 WAF ACL(name should be `owasp-top10-waf-v2-acl`)'
cfnresponse.send(event, context, cfnresponse.FAILURE,
responseData, 'WafWebAclCustomResource')
else:
# return ACL ARN
responseData['WebAclArn'] = wafWebAcl['ARN']
cfnresponse.send(event, context, cfnresponse.SUCCESS,
responseData, 'WafWebAclCustomResource')
except BaseException as exception:
responseData['Error'] = json.dumps(exception)
cfnresponse.send(event, context, cfnresponse.FAILURE,
responseData, 'WafWebAclCustomResource')
Handler: index.handler
Runtime: python3.9
Timeout: 10
Role: !GetAtt WafWebAclCustomResourceLambdaExecutionRole.Arn
# WAF Web ACL Custom Resource
WafWebAclCustomResource:
Type: Custom::WafWebAcl
Properties:
ServiceToken: !GetAtt WafWebAclCustomResourceLambdaFunction.Arn
# S3 bucket to act as CloudFront origin
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref pS3BucketName
VersioningConfiguration:
Status: Enabled
# CloudFront OAI
WebCDNAccessID:
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: Access to S3 bucket only through CDN
# CloudFront distribution
WebCDN:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Comment: !Sub CDN for OWASP Top 10 WAF v2 example
Origins:
- S3OriginConfig:
OriginAccessIdentity: !Sub origin-access-identity/cloudfront/${WebCDNAccessID}
DomainName: !GetAtt S3Bucket.DomainName
Id: !Ref S3Bucket
Enabled: true
HttpVersion: http2
DefaultCacheBehavior:
AllowedMethods: ['HEAD', 'GET']
DefaultTTL: 86400 # One day
ForwardedValues:
QueryString: true
Cookies:
Forward: none
TargetOriginId: !Ref S3Bucket
ViewerProtocolPolicy: redirect-to-https
WebACLId: !GetAtt WafWebAclCustomResource.WebAclArn