简体   繁体   English

CDK:将源/行为添加到现有 CloudFront 分配

[英]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.

相关问题 具有 EC2 来源的 CloudFront 分布(无 ALB) - CloudFront distribution with EC2 origin (no ALB) 如何在CDK中为CloudFront function添加环境变量? - How to add environment variable to CloudFront function in CDK? CloudFront 源路径和缓存行为交互 - CloudFront Origin Path and Cache Behavior interaction 具有 S3 源的 CloudFront 分配响应 XML ListBucketResult - CloudFront Distribution with S3 Origin Responds with XML ListBucketResult Cloudformation 模板 - 具有云端分发的 S3 存储桶网站 - 分发无法访问源 - Cloudformation template - S3 bucket website with cloudfront distribution - distribution can't access origin Cloudfront 自定义来源分发返回 502“错误无法满足请求。” 对于某些网址 - Cloudfront custom-origin distribution returns 502 "ERROR The request could not be satisfied." for some URLs Cloudfront 在没有公共访问的情况下为 S3 存储桶源提供通过 AWS CDK Python 创建的访问被拒绝的响应 - Cloudfront give Access denied response created through AWS CDK Python for S3 bucket origin without public Access 如何确保云端行为使用正确的来源而没有尾部斜杠 - How to make sure cloudfront behavior uses the correct origin without trailing slash AWS PowerShell 更新 CloudFront 分布 - AWS PowerShell update CloudFront distribution 将 Cloudfront 与 HTTP API 来源一起使用 - Using Cloudfront with an HTTP API Origin
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM