首页 > 解决方案 > 使用 Terraform 和无服务器框架创建 Lambda@edge 函数

问题描述

我正在尝试使用 Terraform(iam 角色)和无服务器框架创建 Lambda@edge 函数,管道已完成,但 CloudFront 无法使用此错误消息连接到 Lambda

The Lambda function associated with the CloudFront distribution is invalid or doesn't have the required permissions. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.

我对 Lambda@edge 设置(和 Terraform)不太熟悉,从 AWS 控制台,我可以看到 Lambdaarn保存到 CloudFront 的行为部分,但在 Lambda 中看不到任何触发器。

这是 Terraform 设置

resource "aws_iam_policy" "sls-user-policy" {
  name = "${var.service_name}-sls-user-policy-${terraform.workspace}"

  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:Describe*",
                "cloudformation:List*",
                "cloudformation:Get*",
                "cloudformation:CreateStack",
                "cloudformation:UpdateStack",
                "cloudformation:DeleteStack"
            ],
            "Resource": "arn:aws:cloudformation:${var.region}:${var.aws_account_number}:stack/${var.service_name}*/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:ValidateTemplate",
                "cloudfront:ListDistributionsByLambdaFunction",
                "iam:PassRole"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "iam:PassRole",
                "iam:CreateRole",
                "iam:CreateServiceLinkedRole",
                "iam:DeleteRole",
                "iam:DetachRolePolicy",
                "iam:PutRolePolicy",
                "iam:AttachRolePolicy",
                "iam:DeleteRolePolicy"
            ],
            "Resource": [
                "arn:aws:iam::${var.aws_account_number}:role/${var.service_name}-${terraform.workspace}-*",
                "arn:aws:iam::${var.aws_account_number}:role/${var.service_name}*-lambdaRole",
                "arn:aws:iam::${var.aws_account_number}:role/aws-service-role/ops.apigateway.amazonaws.com/AWSServiceRoleForAPIGateway",
                "arn:aws:iam::${var.aws_account_number}:role/aws-service-role/replicator.lambda.amazonaws.com/AWSServiceRoleForLambdaReplicator",
                "arn:aws:iam::${var.aws_account_number}:role/aws-service-role/logger.cloudfront.amazonaws.com/AWSServiceRoleForCloudFrontLogger"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "events:Put*",
                "events:Remove*",
                "events:Delete*",
                "events:Describe*"
            ],
            "Resource": "arn:aws:events::${var.aws_account_number}:rule/${var.service_name}*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups"
            ],
            "Resource": "arn:aws:logs:${var.region}:${var.aws_account_number}:log-group::log-stream:*"
        },
        {
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:DeleteLogGroup",
                "logs:DeleteLogStream",
                "logs:DescribeLogStreams",
                "logs:FilterLogEvents",
                "logs:PutLogsEvent"
            ],
            "Resource": [
                "arn:aws:logs:${var.region}:${var.aws_account_number}:log-group:/aws/*/${var.service_name}*:log-stream:*",
                "arn:aws:logs:${var.region}:${var.aws_account_number}:/aws/cloudfront/*"
            ],
            "Effect": "Allow"
        },
        {
            "Effect": "Allow",
            "Action": [
                "lambda:GetFunction",
                "lambda:CreateFunction",
                "lambda:DeleteFunction",
                "lambda:UpdateFunctionConfiguration",
                "lambda:UpdateFunctionCode",
                "lambda:ListVersionsByFunction",
                "lambda:PublishVersion",
                "lambda:CreateAlias",
                "lambda:DeleteAlias",
                "lambda:UpdateAlias",
                "lambda:GetFunctionConfiguration",
                "lambda:AddPermission",
                "lambda:RemovePermission",
                "lambda:InvokeFunction",
                "lambda:ListTags",
                "lambda:TagResource",
                "lambda:UntagResource",
                "lambda:EnableReplication*",
                "lambda:DisableReplication"
            ],
            "Resource": [
                "arn:aws:lambda:*:${var.aws_account_number}:function:${var.service_name}*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "apigateway:GET",
                "apigateway:POST",
                "apigateway:PUT",
                "apigateway:PATCH",
                "apigateway:DELETE",
                "apigateway:UpdateRestApiPolicy"
            ],
            "Resource": [
                "arn:aws:apigateway:${var.region}::/restapis",
                "arn:aws:apigateway:${var.region}::/restapis/*",
                "arn:aws:apigateway:${var.region}::/apikeys",
                "arn:aws:apigateway:${var.region}::/apikeys/*",
                "arn:aws:apigateway:${var.region}::/usageplans",
                "arn:aws:apigateway:${var.region}::/usageplans/*",
                "arn:aws:apigateway:${var.region}::/tags",
                "arn:aws:apigateway:${var.region}::/tags/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudfront:CreateDistribution",
                "cloudfront:GetDistribution",
                "cloudfront:ListDistributions",
                "cloudfront:TagResource",
                "cloudfront:UntagResource",
                "cloudfront:UpdateDistribution"
            ],
            "Resource": "arn:aws:cloudfront::${var.aws_account_number}:distribution/*"
        },
        {
            "Effect": "Allow",
            "Action": [
              "states:ListStateMachines",
              "states:ListActivities",
              "states:CreateStateMachine",
              "states:UpdateStateMachine",
              "states:DeleteStateMachine",
              "states:CreateActivity",
              "states:TagResource",
              "states:StartExecution"
            ],
            "Resource": [
              "arn:aws:states:*:${var.aws_account_number}:stateMachine:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "sns:Subscribe",
                "sns:Unsubscribe"
            ],
            "Resource": "arn:aws:sns:${var.region}:${var.aws_account_number}:${var.service_name}-*-${terraform.workspace}"
        }
    ]
}
EOF
}

无服务器.yml

service: service-integration

frameworkVersion: '>=1.1.0 <2.0.0'

plugins:
  - serverless-webpack
  - serverless-offline
  - serverless-iam-roles-per-function

custom:
  defaultStage: dev
  stage: ${opt:stage, self:custom.defaultStage}
  defaultBuild: 0
  webpack:
    webpackConfig: ./webpack/${self:custom.stage}.config.js
    forceExclude:
      - aws-sdk
  serverless-iam-roles-per-function:
    defaultInherit: true
  apigwBinary:
    types:
      - 'application/octet-stream'

provider:
  name: aws
  stage: ${self:custom.stage}
  runtime: nodejs10.x
  region: us-east-1

functions:
  edgeFunction:
    handler: src/services/edge-function/edge-function.run
    memorySize: 2048
    timeout: 30
    events:
      - cloudFront:
          eventType: origin-request
          pathPattern: /api/edge-function/*/*
          isDefaultOrigin: true
          origin: https://custom-origin.com
          behavior:
            ViewerProtocolPolicy: https-only
            AllowedMethods:
              - 'GET'
              - 'HEAD'
              - 'OPTIONS'
              - 'PUT'
              - 'PATCH'
              - 'POST'
              - 'DELETE'

resources:
  Resources:
    CloudFrontDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          PriceClass: PriceClass_200

    # got the below section from this link
    # https://www.pveller.com/lambda-edge-serverless/
    IamRoleLambdaExecution:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
                  - edgelambda.amazonaws.com

package:
  individually: true

标签: aws-lambdaterraformamazon-cloudfrontserverless-frameworkaws-lambda-edge

解决方案


推荐阅读