无服务器框架:尝试为lambda定义角色会产生未定义的资源错误

时间:2018-01-07 07:04:56

标签: aws-lambda amazon-rds amazon-cloudformation amazon-vpc serverless

我正在写一个lambda来更新RDS实例。显然,RDS实例必须位于VPC中,并且lambda必须位于VPC中,以便它可以访问RDS。好吧那么。所以我将lambda配置为VPC,然后它没有权限在EC2上打开网络接口,所以我必须给lambda一个具有这些权限的角色。

这是我的serverless.yml:

service: users-to-rds

plugins:
  - serverless-plugin-typescript

provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  timeout: 30
  region: ap-southeast-2
  iamRoleStatements:
    - Effect: Allow
      Action:
        - "S3:*"
      Resource: arn:aws:s3:::*
    - Effect: Allow
      Action:
        - "rds:*"
      Resource: "*"
  vpc:
    securityGroupIds:
      - sg-stuff
    subnetIds:
      - subnet-stuff
      - subnet-stuff
      - subnet-stuff

functions:
  writeToDB:
    handler: write-users-to-rds.writeToDB
    events:
      - sns: userlists
    role:
      Fn::GetAtt: [ "doStuffFromInsideVPC", "Arn" ]

Resources:
  SNSInvokeLambdaPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: "lambda:InvokeFunction"
      Principal: "sns.amazonaws.com"
      SourceArn:
        Ref: UserListNotification
      FunctionName:
        Fn::GetAtt: [ "UserListToRDS", "Arn" ]
  doStuffFromInsideVPC:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: '2017'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: doStuffFromInsideVPCPolicy
          PolicyDocument:
            Version: '2017'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource:
                  - 'Fn::Join':
                    - ':'
                    - - 'arn:aws:logs'
                      - Ref: 'AWS::Region'
                      - Ref: 'AWS::AccountId'
                      - 'log-group:/aws/lambda/*:*:*'
              - Effect: Allow
                Action:
                  - ec2:CreateNetworkInterface
                  - ec2:DescribeNetworkInterfaces
                  - ec2:DetachNetworkInterface
                  - ec2:DeleteNetworkInterface
                Resource: "*"

当我进行无服务器部署时,它会将zip上传到AWS,然后我被告知:

  

CloudFormation模板无效:模板错误:Fn :: GetAtt实例引用未定义资源doStuffFromInsideVPC

当然完全是胡说八道。就在那里。显然曾经有一个错误,CloudFormation没有及时创建角色资源,所以无服务器更新后添加了DependsOn,导致它等到角色存在。看看.serverless / cloudformation-template-update-stack.json它似乎有一个需要它的DependsOn。

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "The AWS CloudFormation template for this Serverless application",
  "Resources": {
    "ServerlessDeploymentBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "AccelerateConfiguration": {
          "AccelerationStatus": "Suspended"
        }
      }
    },
    "WriteToDBLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": "/aws/lambda/users-to-rds-dev-writeToDB"
      }
    },
    "WriteToDBLambdaFunction": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {
            "Ref": "ServerlessDeploymentBucket"
          },
          "S3Key": "serverless/users-to-rds/dev/1515307801502-2018-01-07T06:50:01.502Z/users-to-rds.zip"
        },
        "FunctionName": "users-to-rds-dev-writeToDB",
        "Handler": "write-users-to-rds.writeToDB",
        "MemorySize": 1024,
        "Role": {
          "Fn::GetAtt": [
            "doStuffFromInsideVPC",
            "Arn"
          ]
        },
        "Runtime": "nodejs6.10",
        "Timeout": 30,
        "VpcConfig": {
          "SecurityGroupIds": [
            "sg-stuff"
          ],
          "SubnetIds": [
            "subnet-stuff",
            "subnet-stuff",
            "subnet-stuff"
          ]
        }
      },
      "DependsOn": [
        "WriteToDBLogGroup",
        "doStuffFromInsideVPC"
      ]
    },
    "WriteToDBLambdaVersionAOwtYsOPCw4hVAkxPXSzE66bZXvdbu2xQUzGAe58E": {
      "Type": "AWS::Lambda::Version",
      "DeletionPolicy": "Retain",
      "Properties": {
        "FunctionName": {
          "Ref": "WriteToDBLambdaFunction"
        },
        "CodeSha256": "7gOzejhkEn37BviNCIVy1lw32IwPs9/oyeaPBQjlqVA="
      }
    },
    "SNSTopicUserlists": {
      "Type": "AWS::SNS::Topic",
      "Properties": {
        "TopicName": "userlists",
        "DisplayName": "",
        "Subscription": [
          {
            "Endpoint": {
              "Fn::GetAtt": [
                "WriteToDBLambdaFunction",
                "Arn"
              ]
            },
            "Protocol": "lambda"
          }
        ]
      }
    },
    "WriteToDBLambdaPermissionUserlistsSNS": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "FunctionName": {
          "Fn::GetAtt": [
            "WriteToDBLambdaFunction",
            "Arn"
          ]
        },
        "Action": "lambda:InvokeFunction",
        "Principal": "sns.amazonaws.com",
        "SourceArn": {
          "Fn::Join": [
            "",
            [
              "arn:aws:sns:",
              {
                "Ref": "AWS::Region"
              },
              ":",
              {
                "Ref": "AWS::AccountId"
              },
              ":",
              "userlists"
            ]
          ]
        }
      }
    }
  },
  "Outputs": {
    "ServerlessDeploymentBucketName": {
      "Value": {
        "Ref": "ServerlessDeploymentBucket"
      }
    },
    "WriteToDBLambdaFunctionQualifiedArn": {
      "Description": "Current Lambda function version",
      "Value": {
        "Ref": "WriteToDBLambdaVersionAOwtYsOPCw4hVAkxPXSzE66bZXvdbu2xQUzGAe58E"
      }
    }
  }
}

任何想法,任何人?谢谢。

1 个答案:

答案 0 :(得分:3)

根据serverless.yaml reference,资源应按以下方式定义:

resources:
  Resources:
    YourResource:
    ...

在你的情况下试试这个:

resources:
  Resources:
    SNSInvokeLambdaPermission:
      Type: "AWS::Lambda::Permission"
      ...