Using Shieldly with Terraform

Shieldly doesn't have a native Terraform provider — instead, extract the IAM policy JSON your plan is about to create or change and run it through the same @shieldly/cli used everywhere else. This works with any Terraform version and any backend.

IAM resources this covers

Terraform stores each of these resources' policy document as a JSON string in plan/state output — exactly the input analyze-iam expects:

Resource typeAttributeWhat it is
aws_iam_policypolicyStandalone managed policy
aws_iam_role_policypolicyInline policy on a role
aws_iam_user_policypolicyInline policy on a user
aws_iam_group_policypolicyInline policy on a group

Extract the policy JSON from a plan

terraform plan -out=tfplan
terraform show -json tfplan > plan.json

# Pull every IAM policy document about to be created/changed into its own file
jq -r '
  .resource_changes[]
  | select(.type == "aws_iam_policy" or .type == "aws_iam_role_policy"
        or .type == "aws_iam_user_policy" or .type == "aws_iam_group_policy")
  | .change.after.policy
' plan.json | nl -ba | while read -r n policy; do
  echo "$policy" > "policy-$n.json"
done

Requires jq (preinstalled on GitHub Actions and GitLab CI runners).

Scan every extracted policy

for f in policy-*.json; do
  npx @shieldly/cli analyze-iam "$f" || exit 1
done

analyze-iam exits non-zero on its own when a scan finds a Critical or High severity issue — the loop above fails the pipeline on the first one, before terraform apply runs.

Full CI example (GitHub Actions)

- name: Terraform plan
  run: |
    terraform init
    terraform plan -out=tfplan
    terraform show -json tfplan > plan.json

- name: Extract + scan IAM policies
  env:
    SHIELDLY_API_KEY: ${{ secrets.SHIELDLY_API_KEY }}
  run: |
    jq -r '
      .resource_changes[]
      | select(.type == "aws_iam_policy" or .type == "aws_iam_role_policy"
            or .type == "aws_iam_user_policy" or .type == "aws_iam_group_policy")
      | .change.after.policy
    ' plan.json | nl -ba | while read -r n policy; do
      echo "$policy" > "policy-$n.json"
      npx @shieldly/cli analyze-iam "policy-$n.json" || exit 1
    done

Same recipe works in GitLab CI or Jenkins — see Using Shieldly with GitLab CI and Using Shieldly with Jenkins for the pipeline syntax.

Privacy

Shieldly does not log your policy input. Cache keys are one-way SHA-256 hashes.