cfn-lint icon indicating copy to clipboard operation
cfn-lint copied to clipboard

cfn-lint doesn't validate second level key name of a FindInMap that is resolved by a nested FindInMap

Open Slooz opened this issue 3 years ago • 2 comments

cfn-lint version: 0.52.0

cfn-lint doesn't catch the following error:

Mappings:
  Mapping:
    Key:
      BucketNameKeyName: "" # should be BucketName
      BucketName: Bucket
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !FindInMap
        - Mapping
        - Key
        - !FindInMap
          - Mapping
          - Key
          - BucketNameKeyName

But the validate-template API does:

Template error: Unable to get mapping for Mapping::Key::

I was surprised that the template passed cfn-lint but failed validate-template. Is this something that cfn-lint could validate?

We use this syntax so that we can do something like the following, which is to have a mapping with an extra dimension based on deployment names within an account:

Parameters:
  DeploymentName:
    Type: String
Mappings:
  AccountMap:
    "000000000001":
      PrimaryDeploymentBucketName: Account1PrimaryBucket
      SecondaryDeploymentBucketName: Account1SecondaryBucket
      TertiaryDeploymentBucketName: Account1TertiaryBucket
    "000000000002":
      PrimaryDeploymentBucketName: Account2PrimaryBucket
      SecondaryDeploymentBucketName: Account2SecondaryBucket
      TertiaryDeploymentBucketName: Account2TertiaryBucket
  DeploymentMap:
    Primary:
      BucketNameAccountMapKey: PrimaryDeploymentBucketName
    Secondary:
      BucketNameAccountMapKey: SecondaryDeploymentBucketName
    Tertiary:
      BucketNameAccountMapKey: TertiaryDeploymentBucketName
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !FindInMap
        - AccountMap
        - !Ref AWS::AccountId
        - !FindInMap
          - DeploymentMap
          - !Ref DeploymentName
          - BucketNameAccountMapKey

Slooz avatar Jul 12 '21 21:07 Slooz

Just to make sure I have this correct. In this scenario we aren't finding the AWS::AccountId in the AccountMap mapping. The one issue we have currently is that cfn-lint is completely offline validation of the template. We don't associate to an account to resolve intrinsic function values. This is done for many reasons... the stack could be used for a StackSet or be put into a code repository and deployed in pipelines to different accounts the user doesn't have configured locally.

I've thought about this a few times and if there is a scalable way to do this testing. If for instance you provide a list of AccountIDs this template could be deployed to so we can validate that the mappings exist for each one. For AWS::Region we could resolve the regions parameters to cfn-lint.

kddejong avatar Aug 03 '21 15:08 kddejong

I don't think the issue here is that cfn-lint can't find AWS::AccountId in the AccountMap. The second code example that uses AWS::AccountId is just an example of how we use this functionality.

The first code example shows the issue. The nested !FindInMap resolves to "":

!FindInMap
  - Mapping
  - Key
  - BucketNameKeyName

The parent !FindInMap uses the resolved value:

!FindInMap
  - Mapping
  - Key
  - ""

"" isn't a valid key name within the mapping, so this is an error.

However, I do agree with you, it'd be useful if a list of account IDs could be provided similarly to how a list of regions can be provided.

Slooz avatar Aug 03 '21 17:08 Slooz