Como resolvo dependências circulares com modelos do AWS Serverless Application Model (SAM) no CloudFormation?

3 minuto de leitura
0

Se eu implantar um modelo do AWS Serverless Application Model (SAM) no AWS CloudFormation, recebo um erro semelhante ao seguinte: “Dependência circular entre recursos: [Function, Bucket, FunctionRole, FunctionUploadPermission].”

Breve descrição

Você receberá um erro no CloudFormation se usar o seguinte exemplo de modelo AWS SAM:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Circular Dependency
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "{AWS::StackName}-${AWS::Region}-${AWS::AccountId}"
  Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://mybucket/function.zip
      Runtime: nodejs12.x
      Handler: index.handler
      Policies:
        - Version: 2012-10-17
          Statement:
            - Effect: Allow
              Action: s3:GetObject*
              Resource: !Sub "arn:aws:s3:::${Bucket}*"
      Events:
        Upload:
          Properties:
            Bucket:
              Ref: Bucket
            Events: s3:ObjectCreated:*
          Type: S3

O modelo produz um erro porque cria a seguinte dependência circular:

  1. O recurso Bucket depende de FunctionUploadPermission.
  2. A FunctionUploadPermission depende da Função.
  3. A Função depende da FunctionRole.
  4. FunctionRole depende do recurso Bucket, que cria um loop.

Observação: na mensagem de erro, o recurso FunctionUploadPermission é do tipo AWS::Lambda::Permission. Esse recurso é gerado automaticamente pelo AWS SAM quando a propriedade Eventos para AWS::Serverless::Function for especificada. O recurso FunctionRole é do tipo AWS::IAM::Role. Esse recurso é gerado automaticamente pelo AWS SAM quando a propriedade Perfil para AWS::Serverless::Function não for especificada.

Para resolver a dependência circular, você deve interromper o loop substituindo a referência dinâmica para o recurso do bucket.

Resolução

Substitua o modelo do CloudFormation que tem uma dependência circular pelo seguinte modelo:

Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Circular Dependency
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "${AWS::StackName}-${AWS::Region}-${AWS::AccountId}"
  Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://mybucket/function.zip
      Runtime: nodejs12.x
      Handler: index.handler
      Policies:
        - Version: 2012-10-17
          Statement:
            - Effect: Allow
              Action: s3:GetObject*
              Resource: !Sub "arn:aws:s3:::${AWS::StackName}-${AWS::Region}-${AWS::AccountId}*"
      Events:
        Upload:
          Properties:
            Bucket:
              Ref: Bucket
            Events: s3:ObjectCreated:*
          Type: S3

No modelo, o nome do bucket na seção Recursos da declaração de política usa os mesmos pseudoparâmetros usados na propriedade BucketName do recurso de bucket. Agora, você pode passar o nome do bucket sem referenciar esse bucket diretamente. Consequentemente, o erro é resolvido porque o loop de dependência circular é quebrado. Ou seja, o loop de dependência circular resultante do FunctionRole dependendo do recurso Bucket.

**Observação:**Substitua s3://mybucket/function.zip pela localização do seu arquivo.


Informações relacionadas

Fn::Sub (função intrínsica)

Ref (função intrínseca)

AWS::Serverless::Function

AWS::S3::Bucket

AWS OFICIAL
AWS OFICIALAtualizada há 3 anos