/
InboundDNSProduct.yml
144 lines (141 loc) · 5.19 KB
/
InboundDNSProduct.yml
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
144
AWSTemplateFormatVersion: 2010-09-09
Description: This template configures Route53 private hosted zones and Authorization to hub VPC in an AVM-vended account for Hybrid DNS capabilities
Parameters:
HubHostedZoneID:
Type: String
Description: The hosted zone ID of the Networking Hub Private Hosted Zone
LocalVPCID:
Type: AWS::EC2::VPC::Id
Description: VPC ID of the local VPC in the Application Account that needs to be associated to the Hub Private Hosted Zone
SNSAuthorizationTopicArn:
Type: String
Description: Arn of the SNS Hub Authorization Topic (Shared Services)
Resources:
AuthorizationCustomResource:
Type: Custom::Authorization
Properties:
ServiceToken: !GetAtt AuthorizationLambda.Arn
HostedZoneId: !Ref HubHostedZoneID
VPCId: !Ref LocalVPCID
VPCRegion: !Ref "AWS::Region"
SNSAuthorizationTopic: !Ref SNSAuthorizationTopicArn
AuthorizationLambdaRole:
Type: 'AWS::IAM::Role'
Metadata:
cfn_nag:
rules_to_suppress:
- id: W11
reason: "Resource * acceptable for this policy."
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: 'lambda.amazonaws.com'
Action:
- 'sts:AssumeRole'
Path: '/'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
Policies:
- PolicyName: Route53PrivateZoneAssociation
PolicyDocument:
Statement:
- Effect: Allow
Action:
- 'route53:AssociateVPCWithHostedZone'
Resource:
- !Sub 'arn:${AWS::Partition}:route53:::hostedzone/*'
- !Sub 'arn:${AWS::Partition}:ec2:*:${AWS::AccountId}:vpc/*'
- PolicyName: DescribeVPCAndAssumeRole
PolicyDocument:
Statement:
- Effect: Allow
Action:
- 'ec2:DescribeVpcs'
Resource: '*'
- PolicyName: SNSPublish
PolicyDocument:
Statement:
- Effect: Allow
Action:
- sns:Publish
Resource: !Ref SNSAuthorizationTopicArn
AuthorizationLambda: # needs no monitoring because it is used as a custom resource
Type: 'AWS::Lambda::Function'
Properties:
Code:
ZipFile:
!Sub |
# Import statements
import boto3, sys
import os
import cfnresponse
import json
import time
from botocore.exceptions import ClientError
# Start Lambda function
def create_association(event,context):
props = event['ResourceProperties']
route53 = boto3.client('route53')
sns = boto3.client('sns')
try:
#Paylod for SNS message
subject=f"{props['HostedZoneId']} Authorization Request"
payload={
"hostedZoneId": f"{props['HostedZoneId']}",
"VPCId": f"{props['VPCId']}",
"VPCRegion": f"{props['VPCRegion']}"
}
sns.publish(
TopicArn=f"{props['SNSAuthorizationTopic']}",
Subject=subject,
Message=json.dumps(payload)
)
# Try associating vpc with hosted zone every 5 seconds or until lambda timeout
while True:
time.sleep(5)
try:
response = route53.associate_vpc_with_hosted_zone(
HostedZoneId=f"{props['HostedZoneId']}",
VPC={
"VPCRegion": f"{props['VPCRegion']}",
"VPCId": f"{props['VPCId']}"
}
)
break
except ClientError as ix:
print (ix)
continue
print("Respond: SUCCESS")
cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
return
except ClientError as ex:
print('Updating Association has failed. See the following error.')
print(ex.response['Error']['Message'])
print("Respond: FAILED")
cfnresponse.send(event, context, cfnresponse.FAILED, ex.response)
def lambda_handler(event, context):
print(f"Custom::Authorization: {event['RequestType']}")
if event['RequestType'] in ["Create","Update"]:
print(f"{event['RequestType']}: Authorization Custom Resource")
create_association(event,context)
# Handle a CloudFormation resource delete event
if event['RequestType'] == "Delete":
print("Delete: Authorization Custom Resource")
# Nothing to delete
cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
return
Environment:
Variables:
BP_VPC: !Ref LocalVPCID
Handler: 'index.lambda_handler'
MemorySize: 128
Role: !GetAtt 'AuthorizationLambdaRole.Arn'
Runtime: 'python3.6'
Timeout: 60
AuthorizationLambdaLogGroup:
Type: 'AWS::Logs::LogGroup'
Properties:
LogGroupName: !Sub '/aws/lambda/${AuthorizationLambda}'