aws-cloudformation / cfn-lint

CloudFormation Linter
MIT No Attribution
2.4k stars 576 forks source link

v1: E1018, E1022 - {'Fn::GetAtt': ['GetReadRoles', 'Roles']} is not of type 'array' #3326

Closed egut closed 2 weeks ago

egut commented 2 weeks ago

CloudFormation Lint Version

v1.3.0

What operating system are you using?

Ubuntu

Describe the bug

cfn-lint assumes that custom lambda can't return a array and therefore gets confused. This works fine in 0.87.7.

Expected behavior

cfn-lint can't(?) assume anything about output from custom lambda. It would be good though.

Reproduction template

---
AWSTemplateFormatVersion: 2010-09-09
Description: 'Bug for E1018, E1022'
Parameters:
  BucketName:
    Description: 'Name of the bucket.'
    Type: 'String'
    AllowedPattern: '^[a-z0-9-]+$'
Resources:
  Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Ref 'BucketName'

  GetReadRoles:
    Type: 'Custom::ListIAMRoles'
    Properties:
      # expected E1020 as its a custom lambda in original template
      ServiceToken: !Ref 'ListIAMRoles'
      Resource: !Ref 'BucketName'
      # This will return a list from the python code:
      #
      # role_list = list(set(role_list))
      # cfnresponse.send(event, context, cfnresponse.SUCCESS, {"Roles": role_list})

  BucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      Bucket: !Ref 'Bucket'
      PolicyDocument:
        Version: '2012-10-17'
        Statement:

          # Deny all unless specific Role
          - Sid: 'DenyAllOtherRead'
            Effect: 'Deny'
            Principal: '*'
            Action:
              - 's3:GetObject'
              - 's3:ListBucket'
            Resource:
              - !GetAtt 'Bucket.Arn'
              - !Sub '${Bucket.Arn}/*'
            Condition:
              StringNotLike:
                'aws:PrincipalArn': !Split
                  - ','
                  - !Join
                    - ','
                    - !GetAtt 'GetReadRoles.Roles'
                  # E1018 {'Fn::GetAtt': ['GetReadRoles', 'Roles']} is not of type 'array'
                  #
                  # In original code there are more items in the list to join
                  # that's why this looks a bit strange here, but it reproduce
                  # the same error.
Outputs:
  ReadRoles:
    Description: 'All roles that have ReadAccess to the bucket.'
    Value: !Join
      - ','
      - !GetAtt 'GetReadRoles.Roles'
    # E1022 {'Fn::GetAtt': ['GetReadRoles', 'Roles']} is not of type 'array'
kddejong commented 2 weeks ago

Resolved and will be fixed in the next release.