[英]CDK: Add origin/behavior to existing CloudFront distribution
We have a CF distribution that is used for caching responses from MediaPackage.我们有一个 CF 分布,用于缓存来自 MediaPackage 的响应。 We have multiple MediaPackage endpoints and for each endpoint there is a corresponding origin/behavior on the same CF distribution.我们有多个 MediaPackage 端点,对于每个端点,在同一个 CF 分布上都有一个对应的起源/行为。
Using CDK how can we add a new origin/behavior on the existing CF distribution?.使用 CDK 我们如何在现有的 CF 发行版上添加新的起源/行为?。 I tried below but ran into an error:我在下面尝试但遇到了错误:
// load existing distribution
const distribution = Distribution.fromDistributionAttributes(scope, `${props.stackName}-Distribution`, {
distributionId: 'E33333B',
domainName: 'test.example.com'
}) as Distribution;
// Convert to CfnDistribution
const distributionLive = distribution.node.defaultChild as CfnDistribution;
const distributionConfig =
distributionLive.distributionConfig as CfnDistribution.DistributionConfigProperty;
// Fetch origin/behaviors list
const cacheBehaviors = distributionConfig.cacheBehaviors as CfnDistribution.CacheBehaviorProperty[];
const origins = distributionConfig.origins as CfnDistribution.OriginProperty[];
// Add new origin/behavior
origins.push({..})
cacheBehaviors.push({..})
Error:错误:
/dist/lib/resources/cloudfront.js:95
const distConfig = distributionLive.distributionConfig;
^
TypeError: Cannot read property 'distributionConfig' of undefined
It is easy to do through, here is one example很容易完成,这里有一个例子
https://kuchbhilearning.blogspot.com/2022/10/add-cloudfront-behavior-and-origin.html https://kuchbhilearning.blogspot.com/2022/10/add-cloudfront-behavior-and-origin.html
We need to use addBehavior
method exposed by Cloudfront distribution.我们需要使用addBehavior
分发公开的 addBehavior 方法。 Pass the pattern and origin to this behaviour.将模式和来源传递给此行为。
You can create a lambda function which will update the CF distribution to add new behavior.您可以创建一个 lambda function 来更新 CF 分发以添加新行为。 Then create a custom AWS resource to call this lambda function on create/update as below -然后创建自定义 AWS 资源以在创建/更新时调用此 lambda function,如下所示 -
#lambda function code to be saved in lambda_codes/update_cf/update_distribution.py
import boto3
import os
client = boto3.client('cloudfront')
def lambda_handler(event,context):
responseData={}
try:
if (event['RequestType'] == 'Create') or (event['RequestType'] == 'Update'):
config_res = client.get_distribution_config(Id=event['ResourceProperties']["Id"])
config_req = dict(config_res["DistributionConfig"])
ETag = config_res["ETag"]
LambdaFunctionARN = event['ResourceProperties']["LambdaFunctionARN"]
LambdaFunctionAssociations = {
'Quantity': 1,
'Items': [{
'LambdaFunctionARN': LambdaFunctionARN,
'EventType': 'viewer-request',
'IncludeBody': False
}]
}
CacheBehaviors= {}
CacheBehaviors_Item=dict(config_req['DefaultCacheBehavior'])
CacheBehaviors_Item['PathPattern'] ='/index.html'
CacheBehaviors['Items'] = [CacheBehaviors_Item]
CacheBehaviors['Items'][0]['LambdaFunctionAssociations'] = LambdaFunctionAssociations
CacheBehaviors['Quantity'] = 1
config_req['CacheBehaviors']=CacheBehaviors
print(config_req)
response = client.update_distribution(Id=event['ResourceProperties']["Id"],
IfMatch=ETag,
DistributionConfig=config_req)
print("Response",response)
responseData['Status'] = 'SUCCESS'
print ('SUCCESS')
return { "status" : responseData['Status'] }
else:
print("SUCCESS - operation not Create or Update, ResponseData=" + str(responseData))
return { "status" : 'SUCCESS' }
except Exception as e:
responseData['Error'] = str(e)
print("FAILED ERROR: " + responseData['Error'])
Below is the python CDK stack to create above updating CF lambda and custom resource calling it.下面是在更新 CF lambda 和调用它的自定义资源之上创建的 python CDK 堆栈。
from constructs import Construct
import json
import os
import base64
from aws_cdk import (
Duration,
Stack,
aws_iam as iam,
aws_lambda as lambda_,
)
class InfraCodeStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
#Policy Statement for CF access
cf_update_lambda_role_policy_statement = iam.PolicyDocument(
statements= [
iam.PolicyStatement(
effect = iam.Effect.ALLOW,
actions= [
"cloudfront:GetDistributionConfig",
"cloudfront:UpdateDistribution"
],
resources= ["*"],
)
]
)
#Cf_Update lambda role
cf_lambda_iamrole = iam.Role(
self, "Cf_Update_Lambda_Role",
role_name= "Cf_Update_Lambda_Role",
assumed_by= iam.CompositePrincipal(iam.ServicePrincipal("lambda.amazonaws.com")),
description= 'Role to allow lambda to update cloudfront config',
inline_policies= {'CF_Update_lambda_Cloudfront_Policy':cf_update_lambda_role_policy_statement },
managed_policies= [
iam.ManagedPolicy.from_aws_managed_policy_name('service-role/AWSLambdaBasicExecutionRole')
]
)
#Cf_Update lambda function
cf_update_lambda = lambda_.Function(self, "cf-update-lambda-dev",
code=lambda_.Code.from_asset("lambda_codes/update_cf"),
function_name="cf-update-lambda-dev",
handler='update_distribution.lambda_handler',
role=cf_lambda_iamrole,
tracing=lambda_.Tracing.ACTIVE,
runtime=lambda_.Runtime.PYTHON_3_9
)
cf_update_lambda.node.add_dependency(get_version)
#Updating cloudfront via custom sdk call
input_event_to_cf_update_lambda = {
"RequestType" : "Update",
"ResourceProperties" : {
"Id" : cloudfront_object.distribution_id, ## your cloudfront object created in the stack's id
"LambdaFunctionARN" : function_arn, ## lambda@edge arn to be attached to behavior
"AWSRegion": "us-east-1"
}
}
def lambda_context(custom=None,env=None,client=None):
client_context = dict(
custom=custom,
env=env,
client=client)
json_context = json.dumps(client_context).encode('utf-8')
return base64.b64encode(json_context).decode('utf-8')
context = {
"custom": {},
"env": {},
"client": {}
}
cf_update_lambda_custom = cr.AwsCustomResource(self, "cf_update_lambda_custom",
on_update=cr.AwsSdkCall(
service="Lambda",
action="invoke",
parameters={ "FunctionName": cf_update_lambda.function_name,
"InvocationType" : "RequestResponse",
"LogType" : "Tail",
"ClientContext" : lambda_context(**context),
"Payload" : json.dumps(input_event_to_cf_update_lambda),
},
physical_resource_id=cr.PhysicalResourceId.of("lambda_update_cf_custom_resource")
),
policy=cr.AwsCustomResourcePolicy.from_statements(
[ iam.PolicyStatement(
effect = iam.Effect.ALLOW,
actions= [
"lambda:InvokeAsync",
"lambda:InvokeFunction"
],
resources= ['*'],
)]
),
)
cf_update_lambda_custom.node.add_dependency(cf_update_lambda)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.