rules:
- id: no-iam-priv-esc-roles
  patterns:
  - pattern-either:
    - patterns:
      - pattern-inside: |
          resource $TYPE "..." {
            ...
            policy = jsonencode({
              ...
              Statement = [
                ...
              ]
              ...
            })
            ...
          }
      - pattern-not-inside: |
          resource $TYPE "..." {
            ...
            policy = jsonencode({
              ...
              Statement = [
                ...,
                {... Effect = "Deny" ...},
                ...
              ]
              ...
            })
            ...
          }
      - pattern: |
          Action = $ACTION
      - metavariable-pattern:
          metavariable: $TYPE
          pattern-either:
          - pattern: |
              "aws_iam_role_policy"
          - pattern: |
              "aws_iam_policy"
          - pattern: |
              "aws_iam_user_policy"
          - pattern: |
              "aws_iam_group_policy"
    - patterns:
      - pattern-inside: |
          data aws_iam_policy_document "..." {
            ...
            statement {
              ...
            }
            ...
          }
      - pattern-not-inside: |
          data aws_iam_policy_document "..." {
            ...
            statement {
              ...
              effect = "Deny"
              ...
            }
            ...
          }
      - pattern: |
          actions = $ACTION
  - metavariable-pattern:
      metavariable: $ACTION
      pattern-either:
            # TODO: this is a hack because generic currently doesn't work with [..., $ACTION, ...]
            # we will replace this once full support for terraform gets released.
      - patterns:
        - pattern: |
            [..., "sts:AssumeRole", ...]
        - pattern: |
            [..., "iam:UpdateAssumeRolePolicy", ...]
      - patterns:
        - pattern: |
            [..., "iam:PassRole", ...]
        - pattern: |
            [..., "lambda:CreateFunction", ...]
        - pattern: |
            [..., "lambda:InvokeFunction", ...]
      - patterns:
        - pattern: |
            [..., "iam:PassRole", ...]
        - pattern: |
            [..., "lambda:CreateFunction", ...]
        - pattern: |
            [..., "lambda:CreateEventSourceMapping", ...]
      - pattern: |
          "lambda:UpdateFunctionCode"
      - patterns:
        - pattern: |
            [..., "iam:PassRole", ...]
        - pattern: |
            [..., "glue:CreateDevEndpoint", ...]
      - patterns:
        - pattern: |
            [..., "iam:PassRole", ...]
        - pattern: |
            [..., "cloudformation:CreateStack", ...]
      - patterns:
        - pattern: |
            [..., "iam:PassRole", ...]
        - pattern: |
            [..., "datapipeline:CreatePipeline", ...]
        - pattern: |
            [..., "datapipeline:PutPipelineDefinition", ...]
  message: >-
    Ensure that groups of actions that include iam:PassRole and could result in privilege escalation
    are not all allowed for the same user. These actions could result in an attacker gaining full admin
    access of an AWS account. Try not to use these actions in conjuction.
  metadata:
    references:
    - https://cloudsplaining.readthedocs.io/en/latest/glossary/privilege-escalation/
    - https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/
    category: security
    cwe:
    - 'CWE-269: Improper Privilege Management'
    technology:
    - terraform
    - aws
    owasp:
    - A04:2021 - Insecure Design
    subcategory:
    - audit
    likelihood: LOW
    impact: LOW
    confidence: LOW
  languages: [hcl]
  severity: WARNING
