Skip to content

Advanced Patterns

Andy Rea edited this page Oct 18, 2025 · 1 revision

Advanced Patterns

Advanced patterns and best practices for complex IAM policy testing scenarios.

Comprehensive Testing Pattern

From test/scenarios/18-comprehensive-all-features.yml:

# Combine ALL features
vars_file: "../vars/cross-account-vars.yml"
policy_json: "../policies/user-alice-identity.json"
resource_policy_template: "../policies/s3-bucket-policy-templated.json.tpl"
caller_arn: "{{.alice_arn}}"
resource_owner: "{{.target_account_root}}"
scp_paths:
  - "../scp/deny-s3-delete.json"

tests:
  - name: "Cross-account read with all policies"
    action: "s3:GetObject"
    resource: "arn:aws:s3:::{{.shared_bucket}}/{{.data_prefix}}/file.txt"
    expect: "allowed"

Hierarchical Scenarios

Organize scenarios by environment:

scenarios/
├── base/
│   ├── common.yml           # Shared config
│   └── s3-base.yml         # S3-specific base
├── dev/
│   ├── developer.yml       # extends: ../base/common.yml
│   └── readonly.yml        # extends: ../base/common.yml
└── prod/
    ├── developer.yml       # extends: ../dev/developer.yml + prod SCPs
    └── admin.yml           # Full access

Matrix Testing Pattern

Test multiple users/roles against same resources:

# base-test.yml
vars_file: "vars/common.yml"
policy_json: "policies/s3-read-only.json"

tests:
  - name: "GetObject test"
    action: "s3:GetObject"
    resource: "arn:aws:s3:::{{.bucket}}/*"
    expect: "allowed"

# test-alice.yml
extends: "base-test.yml"
caller_arn: "arn:aws:iam::123456789012:user/alice"

# test-bob.yml
extends: "base-test.yml"
caller_arn: "arn:aws:iam::123456789012:user/bob"

Negative Testing

Always test what should be denied:

tests:
  # Positive tests
  - name: "Read allowed"
    action: "s3:GetObject"
    expect: "allowed"

  # Negative tests (ensure restricted)
  - name: "Write denied"
    action: "s3:PutObject"
    expect: "implicitDeny"

  - name: "Delete denied"
    action: "s3:DeleteObject"
    expect: "implicitDeny"

  - name: "Admin actions denied"
    action: "s3:DeleteBucket"
    expect: "implicitDeny"

Environment-Specific Variables

vars/
├── common.yml          # Shared values
├── dev.yml            # Dev overrides
├── staging.yml        # Staging overrides
└── prod.yml           # Prod overrides
# common.yml
region: "us-east-1"
department: "Engineering"

# prod.yml (extends common)
environment: "production"
bucket_prefix: "prod"
strict_mode: true

Best Practices

1. Test Boundaries

tests:
  - name: "Exact match allowed"
    resource: "arn:aws:s3:::allowed-bucket/*"
    expect: "allowed"

  - name: "Similar but denied"
    resource: "arn:aws:s3:::allowed-bucket-backup/*"
    expect: "implicitDeny"

2. Test Wildcards

# Policy allows: s3:Get*
tests:
  - action: "s3:GetObject"
    expect: "allowed"
  - action: "s3:GetObjectVersion"
    expect: "allowed"
  - action: "s3:GetBucketLocation"
    expect: "allowed"
  - action: "s3:PutObject"  # Not Get*
    expect: "implicitDeny"

3. Test Condition Edge Cases

tests:
  - name: "Exact IP match"
    context:
      - ContextKeyName: "aws:SourceIp"
        ContextKeyValues: ["10.0.1.100"]
    expect: "allowed"

  - name: "IP off by one"
    context:
      - ContextKeyName: "aws:SourceIp"
        ContextKeyValues: ["10.0.1.101"]
    expect: "implicitDeny"

CI/CD Integration

Run tests in pipeline:

# .github/workflows/policy-tests.yml
name: IAM Policy Tests
on: [pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Download politest
        run: |
          wget https://github.com/reaandrew/politest/releases/latest/download/politest-linux-amd64
          chmod +x politest-linux-amd64

      - name: Configure AWS
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}

      - name: Run all tests
        run: |
          for scenario in scenarios/*.yml; do
            ./politest-linux-amd64 --scenario $scenario
          done

See More


Comprehensive example: test/scenarios/18-comprehensive-all-features.yml

Clone this wiki locally