Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trying to search an If statement for a value #500

Closed
Aaron-Garrett opened this issue Apr 16, 2024 · 2 comments
Closed

Trying to search an If statement for a value #500

Aaron-Garrett opened this issue Apr 16, 2024 · 2 comments
Labels

Comments

@Aaron-Garrett
Copy link

Aaron-Garrett commented Apr 16, 2024

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

Trying to search the If statement of CloudFormation template to see if its contents match a regex expression.

Any examples
Please supply:

  1. Example rules and template that you have tried
let aws_iam_entities_no_managed_policy = Resources.*[
  Type in [ /AWS::IAM::User/,
            /AWS::IAM::Role/,
            /AWS::IAM::Group/ ]
  Metadata.guard.SuppressedRules not exists or
  Metadata.guard.SuppressedRules.* != "IAM_ONLY_ALLOW_ManagedPolicies"
]

let INVALID_VALUES = [/(?i)policy\/AWS/, /(?i)\/VMImportExportRoleForAWSConnector/]

rule IAM_ONLY_ALLOW_ManagedPolicies when %aws_iam_entities_no_managed_policy !empty {
  when %aws_iam_entities_no_managed_policy.Properties.ManagedPolicyArns[*] !empty {
    let sub_queries = %aws_iam_entities_no_managed_policy.Properties.ManagedPolicyArns.*[ keys == "Fn::Sub" ]
    let if_queries = %aws_iam_entities_no_managed_policy.Properties.ManagedPolicyArns.*[ keys == "Fn::If" ]

    when %sub_queries EXISTS {
        %sub_queries not in %INVALID_VALUES
          <<
            Violation: AWS Managed Policies are not approved for use.
            Fix: Use EDB-Manged Policies instead
          >>
          %if_queries not in %INVALID_VALUES
          <<
            Violation: AWS Managed Policies are not approved for use.
            Fix: Use EDB-Manged Policies instead
          >>
    }
  }
}
let aws_iam_entities_no_managed_policy = Resources.*[
  Type in [ /AWS::IAM::User/,
            /AWS::IAM::Role/,
            /AWS::IAM::Group/ ]
  Metadata.guard.SuppressedRules not exists or
  Metadata.guard.SuppressedRules.* != "IAM_ONLY_ALLOW_ManagedPolicies"
]

let INVALID_VALUES = [/(?i)\/AWS/, /(?i)\/VMImportExportRoleForAWSConnector/]

rule IAM_ONLY_ALLOW_ManagedPolicies when %aws_iam_entities_no_managed_policy !empty {
  when %aws_iam_entities_no_managed_policy.Properties.ManagedPolicyArns[*] !empty {
    let sub_queries = %aws_iam_entities_no_managed_policy.Properties.ManagedPolicyArns.*[ keys == "Fn::Sub" ]
    let if_queries = %aws_iam_entities_no_managed_policy.Properties.ManagedPolicyArns.*[ keys == "Fn::If" ].*[ keys == "Fn::Sub" ]

    when %sub_queries EXISTS {
        %sub_queries not in %INVALID_VALUES
          <<
            Violation: AWS Managed Policies are not approved for use.
            Fix: Use EDB-Manged Policies instead
          >>
          %if_queries not in %INVALID_VALUES
          <<
            Violation: AWS Managed Policies are not approved for use.
            Fix: Use EDB-Manged Policies instead
          >>
    }
  }
}
  1. 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/pr-automation/lib/cfn-guard/rules/ 2>&1`
  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

Everything passed for the first one

The second one gave me errors saying things did not equal Fn::Sub, this was resolved when I removed the .*[ keys == "Fn::Sub" ] from the if statement query.

Operating System:
Ubuntu

OS Version
Latest

Additional Information
Here is an example block of code:

rAwsEdbFPDBUDeveloperRole:
    Type: AWS::IAM::Role
    # Condition: CreateDevORQaRole
    Properties:
      RoleName: !Sub aws_${pBusinessUsecase}_${pEnv}
      PermissionsBoundary: !Sub 'arn:aws:iam::${AWS::AccountId}:policy/Boundary'
      MaxSessionDuration: 36000
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
      ManagedPolicyArns:
      **- !Sub "arn:aws:iam::${AWS::AccountId}:policy/aws-kms-s3-rw"**
      - !Sub "arn:aws:iam::${AWS::AccountId}:policy/kms-secrets-rw"
      - !If [
            CreateDevRole,
            **!Sub "arn:aws:iam::${AWS::AccountId}:policy/aws-allowed-policies",**
            !Ref "AWS::NoValue",
          ]
      - !If [CreateDevRole, !Ref rFPDs3WritePolicy, !Ref "AWS::NoValue"] 
      - !Ref rFPDs3ReadPolicy
      - !Ref rSecretsPolicy
      - !If [CreateDevRole, !Ref rFPDRedshiftPolicy, !Ref "AWS::NoValue"]

I am wanting it to look at this chunk of code and flag anything !Sub that has aws after the "/" and anything !If that has aws after the "/", such as the bolded lines above. The !Sub search works well, but the !If statement keeps passing incorrectly even though I am searching only for \/aws.

@joshfried-aws
Copy link
Contributor

Hey @Aaron-Garrett I think i was able to come up with a rule to help you with this specific use case. I think one issue with the logic in your original rule was to do with the way if intrinsic functions is mapped to their json equivalent..

In this case your first if function maps to this in json format

{
    "Fn::If": [
        "CreateDevRole",
        {
            "Fn::Sub": "arn:aws:iam::${AWS::AccountId}:policy/aws-allowed-policies"
        },
        {
            "Ref": "AWS::NoValue"
        }
    ]
}

It's important to note here when evaluating this mapped if function that youre comparing a value (in this case a list where some elements are strings, some elements are maps/structs) to an array of regex. This will always pass in this case due to the contents of the list.

Heres the rule, i have added some comments to help clear things up

let aws_iam_entities_no_managed_policy = Resources.*[
  Type in [ /AWS::IAM::User/,
            /AWS::IAM::Role/,
            /AWS::IAM::Group/ ]
  Metadata.guard.SuppressedRules not exists or
  Metadata.guard.SuppressedRules.* != "IAM_ONLY_ALLOW_ManagedPolicies"
]

let INVALID_VALUES = [/(?i)\/AWS/, /(?i)\/VMImportExportRoleForAWSConnector/]

rule IAM_ONLY_ALLOW_ManagedPolicies when %aws_iam_entities_no_managed_policy !empty {
  let managed_policy_arns = %aws_iam_entities_no_managed_policy.Properties.ManagedPolicyArns

  when %managed_policy_arns !empty {
    check(%managed_policy_arns)
  }
}


rule check(curr) {
    # if is string, we can do direct comparison to the list of strings/regex
    when %curr is_string {
        %curr NOT IN %INVALID_VALUES
    }


    # if is_list or is_struct iterate and check each individual value
    when %curr is_list OR %curr is_struct{
        %curr.* {
            check(this)
        }
    }
}

I hope this was helpful to you, please let me know if you have anymore questions.

@joshfried-aws
Copy link
Contributor

Hey @Aaron-Garrett just checking in to see if the information I provided was enough to help you resolve your issue here.

Please let us know if you need anymore help on this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants