Почему AWS Lambda CFN S3-response возвращает 403 при событии Delete? - PullRequest
0 голосов
/ 12 февраля 2019

Я использую без сервера для развертывания приложения, где я использую Настраиваемый ресурс для переноса базы данных RDS.

Все работает во время развертывания, но когдаЯ удаляю из стека тайм-ауты пользовательских ресурсов через час с сообщением «Не удалось стабилизировать пользовательский ресурс в ожидаемое время».Запрос к предварительно подписанному URL-адресу AWS S3 возвращает 403 с кодом ошибки AccessDenied.

Мое первое успешно отправленное тело ответа на предварительно подписанный URL-адрес (при создании):

{
    "Status": "SUCCESS",
    "RequestId": "bd487606-8017-49f2-99af-b29b2bbad40b",
    "LogicalResourceId": "SheltersDBMigrationTrigger",
    "StackId": "arn:aws:cloudformation:us-east-1:848139458219:stack/update-shelters-dev/c08a80e0-2e4e-11e9-87a6-124d1eab42ba",
    "PhysicalResourceId": "DB_MIGRATION"
}

Мое второе отправленное, ошибочное тело ответа на предварительно подписанный URL-адрес (после удаления):

{
    "Status": "SUCCESS",
    "RequestId": "2d166d36-7c0c-4848-9eb5-aedaf5e9172c",
    "LogicalResourceId": "SheltersDBMigrationTrigger",
    "StackId": "arn:aws:cloudformation:us-east-1:848139458219:stack/update-shelters-dev/c08a80e0-2e4e-11e9-87a6-124d1eab42ba",
    "PhysicalResourceId": "DB_MIGRATION"
}

lambda.go:

func handler(ctx context.Context, event cfn.Event) (rid string, data map[string]interface{}, err error) {
  rid = "DB_MIGRATION"

  if event.RequestType != cfn.RequestCreate {
    return
  }

  db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(%s)/", os.Getenv("DB_MASTER_USER"), os.Getenv("DB_MASTER_PASSWORD"), os.Getenv("DB_ADDRESS")))
  if err != nil {
    panic(err)
  }
  defer db.Close()

  defer func() {
    if r := recover(); r != nil {
      err = fmt.Errorf("handler: Failed to migrate DB: %v", r)
    }
  }()

  MigrateDb(db)

  return
}

func main() {
  lambda.Start(cfn.LambdaWrap(handler))
}

конфигурация без сервера для Lambda CFN :

functions:
  dbMigration:
    handler: lambda-bin/migrate-db
    environment:
      DB_MASTER_USER: ${env:DB_MASTER_USER}
      DB_MASTER_PASSWORD: ${env:DB_MASTER_PASSWORD}
      DB_ADDRESS:
        "Fn::GetAtt": [ SheltersDB, Endpoint.Address ]
    vpc:
      securityGroupIds:
        - Ref: SheltersVPCSecurityGroup
      subnetIds:
        - Ref: SheltersSubnet1
        - Ref: SheltersSubnet2

...

Resources:
    SheltersDBMigrationTrigger:
      Type: Custom::DBMigration
      DependsOn:
        - SheltersDB
      Properties:
        ServiceToken: !GetAtt
          - DbMigrationLambdaFunction
          - Arn
    SheltersSubnet1:
      Type: AWS::EC2::Subnet
      Properties:
        AvailabilityZone: !Select [ 0, {Fn::GetAZs: ""} ]
        CidrBlock: 10.0.1.0/24
        VpcId: !Ref SheltersVPC
    SheltersSubnet2:
      Type: AWS::EC2::Subnet
      Properties:
        AvailabilityZone: !Select [ 1, {Fn::GetAZs: ""} ]
        CidrBlock: 10.0.2.0/24
        VpcId: !Ref SheltersVPC
    SheltersVPCSecurityGroup:
      Type: AWS::EC2::SecurityGroup
      Properties:
        GroupDescription: "Security group for DB connections"
        VpcId: !Ref SheltersVPC
    SheltersVPCSecurityGroupIngress:
      Type: AWS::EC2::SecurityGroupIngress
      Properties:
        GroupId: !Ref SheltersVPCSecurityGroup
        IpProtocol: tcp
        FromPort: "3306"
        ToPort: "3306"
        SourceSecurityGroupId: !Ref SheltersVPCSecurityGroup
    SheltersVPC:
      Type: AWS::EC2::VPC
      Properties:
        CidrBlock: 10.0.0.0/16
    SheltersRouteTable:
      Type: AWS::EC2::RouteTable
      Properties:
        VpcId: !Ref SheltersVPC
    SheltersSubnet1Association:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        SubnetId: !Ref SheltersSubnet1
        RouteTableId: !Ref SheltersRouteTable
    SheltersSubnet2Association:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        SubnetId: !Ref SheltersSubnet2
        RouteTableId: !Ref SheltersRouteTable
    SheltersVPCS3Endpoint:
      Type: AWS::EC2::VPCEndpoint
      Properties:
        VpcId: !Ref SheltersVPC
        PolicyDocument: "{\"Version\":\"2008-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"*\",\"Resource\":\"*\"}]}"
        RouteTableIds:
          - !Ref SheltersRouteTable
        ServiceName: !Join ['', ['com.amazonaws.', !Ref 'AWS::Region', '.s3']]

Вот суть моих полных исходных файлов и журнала.

Обновление с обнаруженной проблемой

Кажется, что мой VPCEndpoint для S3, SheltersVPCS3Endpoint, удаляется до dBMigration, и поэтому я получаю 403.

С чистой Cloudformation, я думаюэто можно было бы легко решить, поставив DependsOn на dbMigration, но при отсутствии сервера это кажется невозможным.

Ответы [ 2 ]

0 голосов
/ 20 апреля 2019

После долгого исследования вместе с поддержкой AWS мы обнаружили, что SheltersVPCS3Endpoint было удалено до удаления dbMigration, и поэтому Lambda fn не мог связаться с корзиной S3, которая вызвала тайм-аут.

Поскольку невозможно добавить DependsOn к функциям в Serverless, мне пришлось перейти с Serverless на Cloudformation.Когда я добавил следующее, это кажется решенным.

  DbMigrationLambdaFunction:
     DependsOn:
       - SheltersVPCS3Endpoint
0 голосов
/ 20 февраля 2019

Вам нужно дать вашей лямбда-функции правильное разрешение.если вы добавите

provider:
  name: aws
  iamRoleStatements:
    $ref: ./iamRoleStatements.json

в свою бессерверную конфигурацию

и затем создадите свой iamRoleStatements.json, чтобы дать разрешение вашей функции для сегментов S3, расположенных в том же каталоге, что и ваша бессерверная конфигурация

[
  {
    "Effect": "Allow",
    "Action": [
      "s3:*"
    ],
    "Resource": "*"
  }
]

это дает всем вашим ресурсам право делать все, что они хотят, в вашу корзину s3

Если вы хотите узнать больше о работе с функциями IAM i без сервера, взгляните на https://serverless.com/blog/abcs-of-iam-permissions/

...