Skip to content

[BUG] #567

Description

@Aaron-Garrett

Describe the bug
A clear and concise description of what the bug is.

The rule I wrote checking for S3 permissions on wildcard Resource is running and failing on IAM roles without any S3 permissions.

To Reproduce
Please supply:

Example rules and template that results in the error
Template:

rImmutaRdsLambdaRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: immunment
      PermissionsBoundary: !Sub "arn:aws:iam::${AWS::AccountId}:policy/L-Boundary"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "rds.amazonaws.com"
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: "RdsInvokeLambdaPolicy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: "lambda:InvokeFunction"
                Resource: !GetAtt rIImmuta.Arn

CloudFormation Guard Rule:

I KNOW THIS SEEMS TOTALLY UNRELATED TO THE CODE ABOVE BUT THIS IS THE CHECK THAT KEEPS FAILING

# R5.0  Automatically inspect the code for * in S3 folder (prefix) access and present a warning statement to the developer if found

let aws_iam_policies_no_full_access_for_s3 = Resources.*[
  Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
  Metadata.guard.SuppressedRules not exists or
  Metadata.guard.SuppressedRules.* != "IAM_POLICY_NO_FULL_ACCESS_FOR_S3"
]

let aws_iam_roles_no_full_access_for_s3 = Resources.*[
  Type in [/AWS::IAM::Role/]
  Metadata.guard.SuppressedRules not exists or
  Metadata.guard.SuppressedRules.* != "IAM_ROLE_NO_FULL_ACCESS_FOR_S3"
]

# Checks there is no wildcard in the bucket name in an IAM Role

rule IAM_ROLE_FULL_BUCKET_NAME_USED when %aws_iam_roles_no_full_access_for_s3 !empty {
  let violationsString = Resources.*[
    Type in [/AWS::IAM::Role/]
    some Properties.Policies[*].PolicyDocument.Statement[*] {
      some Resource[*] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
    }
  ]
  let violationsSub = Resources.*[
    Type in [/AWS::IAM::Role/]
    some Properties.Policies[*].PolicyDocument.Statement[*] {
    some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
    }
  ]
  %violationsString empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
  %violationsSub empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
}

# Checks the full folder path is used with no wildcards before the second "/" in an IAM Role

rule IAM_ROLE_FULL_FOLDER_PATH_USED when %aws_iam_roles_no_full_access_for_s3 !empty {
  let violationsString = Resources.*[
    Type in [/AWS::IAM::Role/]
    some Properties.Policies[*].PolicyDocument.Statement[*] {
      some Resource[*] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
    }
  ]
  let violationsSub = Resources.*[
    Type in [/AWS::IAM::Role/]
    some Properties.Policies[*].PolicyDocument.Statement[*] {
    some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
    }
  ]
  %violationsString empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
  %violationsSub empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
}

# Checks there is no wildcard in the bucket name in an IAM Policy

rule IAM_POLICY_FULL_BUCKET_NAME_USED when %aws_iam_policies_no_full_access_for_s3 !empty {
  let violationsString = Resources.*[
    Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
    some Properties.PolicyDocument.Statement[*] {
      some Resource[*] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
    }
  ]
  let violationsSub = Resources.*[
    Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
    some Properties.PolicyDocument.Statement[*] {
    some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
    }
  ]
  %violationsString empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
  %violationsSub empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
}

# Checks the full folder path is used with no wildcards before the second "/" in an IAM Policy

rule IAM_POLICY_FULL_FOLDER_PATH_USED when %aws_iam_policies_no_full_access_for_s3 !empty {
  let violationsString = Resources.*[
    Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
    some Properties.PolicyDocument.Statement[*] {
      some Resource[*] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
    }
  ]
  let violationsSub = Resources.*[
    Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
    some Properties.PolicyDocument.Statement[*] {
    some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
    }
  ]
  %violationsString empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
  %violationsSub empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
}

let s3_no_full_permission = Resources.*[ Type == 'AWS::S3::BucketPolicy'
  Metadata.guard.SuppressedRules not exists or
  Metadata.guard.SuppressedRules.* != "S3_NO_FULL_PERMISSION"
]

# Checks there is no wildcard in the bucket name in an IAM Policy

rule BUCKET_POLICY_FULL_BUCKET_NAME_USED when %s3_no_full_permission !empty {
  let violationsString = Resources.*[
    Type == 'AWS::S3::BucketPolicy'
    some Properties.PolicyDocument.Statement[*] {
      some Resource[*] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
    }
  ]
  let violationsSub = Resources.*[
    Type == 'AWS::S3::BucketPolicy'
    some Properties.PolicyDocument.Statement[*] {
    some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
    }
  ]
  %violationsString empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
  %violationsSub empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
}


# Checks the full folder path is used with no wildcards before the second "/" in an IAM Policy

rule BUCKET_POLICY_FULL_FOLDER_PATH_USED when %s3_no_full_permission !empty {
  let violationsString = Resources.*[
    Type == 'AWS::S3::BucketPolicy'
    some Properties.PolicyDocument.Statement[*] {
      some Resource[*] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
    }
  ]
  let violationsSub = Resources.*[
    Type == 'AWS::S3::BucketPolicy'
    some Properties.PolicyDocument.Statement[*] {
      some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
    }
  ]
  %violationsString empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
  %violationsSub empty
  <<
    Violation: * in S3 folder (prefix) access.
    Fix: Avoid wildcard matching * in S3 folder (prefix) access
  >>
}

The commands you used to invoke the tool
        OUTPUT=RUST_BACKTRACE=1 ./cfn-guard-v3-ubuntu-latest/cfn-guard validate --show-summary pass,fail --data "$TEMPLATE_FILE" --rules .github/folderlib/cfn-guard/rules/ 2>&1 

The output of a -v log level if it's not related to cfn-guard-lambda, or the relevant CloudWatch log messages if it is related to the cfn-guard-lambda
s3_no_full_access.guard/IAM_ROLE_NO_FULL_ACCESS_FOR_S3      FAIL
---
Evaluating data template.yml against rules s3_no_full_access.guard
Number of non-compliant resources 1
Resource = rImmutaRdsLambdaRole {
  Type      = AWS::IAM::Role
  Rule = IAM_ROLE_NO_FULL_ACCESS_FOR_S3 {
    ALL {
      Check =  %violationsSub EMPTY   {
        ComparisonError {
          Message          {
            Violation: * in S3 folder (prefix) access.
            Fix: Avoid wildcard matching * in S3 folder (prefix) access
          }
          Error            = Check was not compliant as property [/Resources/rImmutaRdsLambdaRole[L:1549,C:4]] was not empty.
          PropertyPath    = /Resources/rImmutaRdsLambdaRole[L:1549,C:4]
          Operator        = EMPTY
          Code:
             1547.      Principal: secretsmanager.amazonaws.com
             1548.
             1549.  rImmutaRdsLambdaRole:
             1550.    Type: "AWS::IAM::Role"
             1551.    Properties:
             1552.      RoleName: !Sub immuta-rds-invoke-lambda-role-

        }
      }
    }
  }
}

Expected behavior
A clear and concise description of what you expected to happen.

The test should skip

Operating System:
[eg, MacOS, Windows, Ubuntu, etc]

Linux

OS Version
[eg Catalina, 10, 18.04, etc]

Ubuntu latest

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions