Skip to main content

More Info:

Identifies roles whose permissions let them create, change or delete infrastructure - compute, networking, storage and the accounts own guardrails. Every workload and user that can assume the role gets that write access, so an application flaw becomes an infrastructure change. Keep write permissions on dedicated roles, scope them to the resources the workload owns, and leave everything else read-only.

Risk Level

High

Address

Security

Compliance Standards

  • Cloudanix Best Practice

Triage and Remediation

Remediation

Using Console

Below is a practical, step‑by‑step way to find and fix IAM roles that have permissions to modify infrastructure in AWS, using only the AWS Console.

1. Identify High‑Risk Roles

  1. Sign in to the AWS Management Console.
  2. Go to IAM:
    • Search for “IAM” in the services search bar and open IAM.
  3. In the left menu, click Access reportsPolicy usage (AWS Managed Policies) (if available in your region), or:
    • Click Policies and filter by:
      • AdministratorAccess
      • PowerUserAccess
      • Any custom policies that obviously grant high privileges (e.g., names containing admin, fullaccess, *).
  4. For each high‑privilege policy:
    1. Click the policy.
    2. Go to the Policy usage tab.
    3. Review which roles this policy is attached to.
Focus on roles that:
  • Use AdministratorAccess, PowerUserAccess, or very broad * permissions.
  • Have broad access to critical infra services: ec2:*, iam:*, cloudformation:*, eks:*, rds:*, lambda:*, elasticloadbalancing:*, etc.

2. Understand What Each Role Really Needs

For each high‑risk role you found:
  1. In IAM → Roles, click the role name.
  2. Check:
    • Trust relationships (who/what can assume the role).
    • Permissions tab → all attached policies.
  3. Determine the role’s real purpose:
    • Is it used by an application (e.g., EC2 instance profile, Lambda, ECS task)?
    • Is it used by a human via AWS SSO or sts:AssumeRole?
    • Is it used by a CI/CD system (e.g., GitHub Actions, Jenkins, CodePipeline)?
Ask (with your team if needed):
  • Which specific services and actions does this role actually need to perform?
  • What environments does it operate in (dev/test/prod)?
Document the minimal required permissions per role (services + actions + resource scopes).

3. Create a Least‑Privilege Custom Policy

You’ll now replace broad/infrastructure‑modifying permissions with a custom least‑privilege policy.
  1. In IAM → Policies, click Create policy.
  2. Choose Visual editor (easier through console).
  3. For each service the role truly needs:
    1. Click Service and select (for example):
      • Amazon EC2
      • AWS Lambda
      • Amazon S3
      • etc.
    2. Under Actions, select only the exact Read/Write operations required, and avoid:
      • * (All EC2 actions, All IAM actions, etc.).
      • Any action that allows broad infra modification if not required, such as:
        • ec2:TerminateInstances, ec2:RunInstances, ec2:CreateVpc, etc.
        • iam:* or powerful IAM actions like iam:CreateRole, iam:PutRolePolicy, iam:PassRole* (unless truly required).
        • cloudformation:* if not really needed.
    3. Under Resources, avoid All resources where possible:
      • Use ARNs to narrow to specific resources (e.g., a specific S3 bucket, specific Lambda functions, a particular VPC or EC2 instances via tags).
      • Use Conditions to further restrict (e.g., only allow certain tags, regions, or actions from particular principals/IPs).
  4. Click Next → add Tags if needed → Next: Review.
  5. Give the policy a clear, descriptive name, e.g.:
    • AppName-Role-LeastPrivilege-EC2Lambda-Policy
  6. Click Create policy.
Repeat as needed to create multiple smaller, purpose‑built policies instead of a single large “catch‑all” policy.

4. Apply the New Policy to the Role and Remove Over‑Privileged Ones

For each high‑risk role:
  1. In IAM → Roles, select the role.
  2. Go to the Permissions tab and click Add permissionsAttach policies.
  3. Search for and select the new custom policy(ies) you just created.
  4. Click NextAdd permissions.
Then:
  1. Still on the role’s Permissions tab, identify over‑privileged policies such as:
    • AdministratorAccess
    • PowerUserAccess
    • Any policy with * on critical infra services.
  2. For each such policy:
    • Click the X or “Detach” button next to the policy.
    • Confirm the detachment.
Change only one or a few roles at a time, and in lower environments first (dev/stage), to avoid breaking production.
For roles that still must modify infrastructure (e.g., CI/CD roles, automation roles), scope them down:
  1. Limit IAM Changes:
    • Avoid iam:*. Instead grant minimal:
      • iam:PassRole only for specific roles (narrow by ARN).
      • If needed, iam:CreateRole, iam:AttachRolePolicy, etc., but only for specific roles and with conditions.
  2. Limit EC2 / VPC / RDS / CFN:
    • Prefer granular actions: e.g., ec2:DescribeInstances, ec2:RebootInstances instead of ec2:*.
    • Restrict by resource ARN or tags when supported.
  3. Use Conditions in policies:
    • Restrict to specific regions: aws:RequestedRegion.
    • Restrict to specific VPC / tags when available.
    • Restrict to service principals or specific users where relevant.

6. (Optional) Use IAM Permissions Boundaries for Shared/Delegated Roles

If you delegate creation of roles to different teams but want to ensure they cannot grant themselves infra‑wide powers:
  1. Create a permissions boundary policy (IAM → Policies → Create policy) that:
    • Allows typical application actions.
    • Explicitly denies dangerous top‑level actions such as:
      • iam:* (or specifically iam:CreateRole, iam:PutRolePolicy, etc.).
      • ec2:* except for approved actions.
      • cloudformation:* if not required.
  2. Save the policy (e.g., OrgAppRoles-PermissionsBoundary).
  3. When a new role is created:
    • In IAM → Roles → Create role, on the Permissions boundary step select this policy.
  4. For existing roles (where needed):
    • Go to the role → Permissions tab → Permissions boundaryEdit and attach the boundary.
This ensures even if a team attaches an overly broad policy, the boundary caps actual effective permissions.

7. Validate with IAM Access Analyzer and Access Advisor

  1. In IAM → Access Analyzer:
    • Create an analyzer if not present.
    • Review Findings for unusual or broad access (e.g., roles with external access or public access).
  2. In IAM → Roles, select a role and go to:
    • Access Advisor tab (or Last accessed info):
      • Inspect which services the role actually uses.
      • If some services are never used, remove those permissions from the role’s policies.

  1. AWS Config Rules:
    • Go to AWS Config in the console.
    • Set up rules such as:
      • IAM_POLICY_NO_STATEMENTS_WITH_ADMIN_ACCESS
      • IAM_USER_NO_POLICIES_CHECK
      • And other IAM‑related rules that flag over‑privileged policies.
  2. Security Hub (if used):
    • Enable Foundational Security Best Practices standard.
    • Review and remediate IAM‑related findings regularly.

9. Operate a Safe Change Process

For production roles that can modify infrastructure, add process protections:
  1. Test role changes in dev/stage accounts first.
  2. Keep versioned IAM policies (JSON exported to Git or similar).
  3. Implement change approvals for any role that:
    • Can modify networks (VPC, Security Groups, Route Tables).
    • Can create/modify IAM roles or policies.
    • Can deploy infra via CloudFormation/Terraform/other IaC tools.

If you share an example of a specific role’s current policy (JSON or console screenshots), I can walk you through an exact “before → after” policy and the precise console clicks for that case.
Below is a concise, AWS-CLI–focused walkthrough to find and remediate IAM roles whose permissions can modify infrastructure (e.g., EC2, RDS, Lambda, CloudFormation, IAM, etc.).

1. Preparation

Configure AWS CLI with appropriate credentials and region:
Ensure you’re using an admin or security/audit account to inspect and update IAM.

2. Identify IAM Roles and Attached Policies

2.1 List all roles

2.2 For each role, list its inline and attached policies

Example for one role:

3. Detect “Infrastructure-Modifying” Permissions

You’re looking for actions that can create/update/delete infrastructure, or grant such rights to others.

3.1 Common infrastructure-modifying actions

Examples (not exhaustive):
  • ec2:*, ec2:RunInstances, ec2:Create*, ec2:Modify*, ec2:TerminateInstances
  • rds:*, lambda:*, elasticloadbalancing:*, eks:*, cloudformation:*
  • iam:Create*, iam:PutRolePolicy, iam:Attach*, iam:PassRole
  • autoscaling:*, elasticbeanstalk:*, apigateway:*, ecs:*, s3:CreateBucket, s3:PutBucketPolicy, etc.

3.2 Inspect policies attached to a role

a) Inline role policies

Review PolicyDocument.Statement[].Action for broad or dangerous actions (especially * or infra APIs above).

b) Attached managed policies

For each ARN:
Again, examine Statement[].Action for infra-modifying permissions.You can script this to grep for suspicious services:

4. Decide the Intended Scope (Least Privilege Design)

For each role:
  1. What is it supposed to do? (Application role, CI/CD role, break-glass admin, etc.)
  2. Map required actions:
    • e.g., EC2 instance profile that only needs to read from S3: s3:GetObject, s3:ListBucket.
    • CI/CD may need cloudformation:* in specific stacks only.
Anything beyond that is “extra” and should be removed or tightly constrained.

5. Remediate Inline Policies (Using AWS CLI)

5.1 Export existing inline policy

5.2 Edit to least privilege

Manually edit old_policy.json:
  • Remove wildcards like "Action": "*".
  • Replace broad services like "ec2:*" with specific actions (e.g., "ec2:DescribeInstances").
  • Add resource constraints where possible (e.g., specific ARNs instead of "Resource": "*")
  • Add conditions where appropriate (e.g., IP, tags, MFA).
Save as new_policy.json.

5.3 Apply updated inline policy


6. Remediate Managed Policies Attached to Roles

6.1 If AWS-managed (e.g., AdministratorAccess)

You cannot change AWS-managed policies; instead:
  1. Detach from the role:
  2. Create a new customer-managed least-privilege policy: Prepare least_priv_policy.json with restricted actions/resources.
  3. Attach the new policy:

6.2 If customer-managed

  1. Create a new version with reduced permissions. Edit current document into new_policy.json (least privilege).
  2. Optionally, delete old policy versions later to stay under the 5-version limit.
    Then:

7. Lock Down IAM-Sensitive Actions

Special attention to:
  • iam:PassRole – restrict to specific role ARNs and services:
  • iam:AttachRolePolicy, iam:PutRolePolicy, iam:CreatePolicy, iam:CreateRole, etc.
    Restrict to admin-only roles, or to specific ARNs.
Ensure only tightly controlled admin roles can modify IAM and broad infrastructure.

8. Validate Effective Permissions

8.1 Simulate policy for a role

Check which actions are “allowed.” Confirm only intended actions are permitted.

8.2 Optional: Enumerate all actions (coarse check)

Use a broad set (e.g., ec2:*, cloudformation:*) in simulation to see if any infra-modifying actions slip through.

9. Continuous Control

  • Use IAM Access Analyzer to find overly broad permissions:
  • Configure a CI check or script to:
    • List roles.
    • Parse attached policies.
    • Flag roles with Action: "*", resource: "*", or infra-modifying APIs.

If you share a sample policy document or a specific role name/policy, I can provide an exact CLI sequence and a concrete “before/after” JSON policy tailored to your use case.
Below is a focused, step‑by‑step approach to remediating IAM roles that can modify infrastructure in AWS, using Python (boto3). I’ll assume you want to:
  1. Identify “risky” IAM roles (those with permissions to change infrastructure such as EC2, IAM, CloudFormation, etc.).
  2. Review and reduce their permissions.
  3. Enforce a least‑privilege pattern.

1. Preparation

Install and configure AWS + Python tooling
Make sure the credentials you use have permission to call iam:ListRoles, iam:ListAttachedRolePolicies, iam:ListRolePolicies, iam:GetPolicy, iam:GetPolicyVersion, iam:GetRolePolicy.

2. Define What “Can Modify Infrastructure” Means

Typical infra‑modifying services (example, adjust as needed):
  • ec2:*
  • iam:*
  • cloudformation:*
  • lambda:*
  • rds:*
  • elasticloadbalancing:*
  • autoscaling:*
  • eks:*
  • route53:*
  • organizations:*
  • s3:* (if modifying buckets that hold infra state, e.g., Terraform state)
  • ssm:* (if used to push changes)
  • logs:* and cloudtrail:* (if you want to protect logging infra)
High‑risk patterns:
  • *:*
  • service:* (e.g., ec2:*)
  • Specific mutating actions: RunInstances, Create*, Update*, Delete*, Put*, Attach*, Detach*, Modify*, Set*, etc.
Create a Python list/regex of these actions or service prefixes.

3. Python Script: Discover Risky IAM Roles

This script:
  • Lists all roles
  • Retrieves attached managed policies
  • Retrieves inline policies
  • Parses policy documents
  • Flags roles that can modify infrastructure
Run it:
Export results to a file if needed.

4. Analyze and Design Least‑Privilege Policies

For each flagged role:
  1. Identify who/what uses the role (Lambda, EC2 instance profile, CI/CD, human, etc.).
  2. Get CloudTrail logs or service usage reports to know exactly which actions/resources are actually used.
    • Use AWS Console: CloudTrail → Event history (filter by role ARN).
    • Or Athena queries over CloudTrail logs to list actions used.
  3. Build a minimal policy:
    • Restrict to specific actions actually required (e.g., ec2:DescribeInstances, not ec2:*).
    • Restrict Resource to needed ARNs or patterns instead of "*" where possible.
    • Add conditions (e.g., limit by tag, region, or source IP if appropriate).

5. Remediate Policies via Python

5.1 Example: Replace AdministratorAccess with Custom Managed Policy

  1. Create a new least‑privilege managed policy.
  2. Attach it to the role.
  3. Detach the broad policy.

5.2 Example: Tighten Inline Policy

If a role has an inline policy that’s too broad, replace it with a stricter one.
You’d construct new_doc (least‑privilege) based on CloudTrail usage.
  1. Service Control Policies (SCPs) (in AWS Organizations):
    • Deny dangerous infra‑modifying actions account‑wide except from designated roles.
  2. IAM permission boundaries:
    • Ensure new roles cannot be given wider permissions than an approved “boundary” policy.
  3. Automated checks:
    • Integrate the detection script into CI/CD.
    • Fail builds or send alerts if a role is created/updated with infra‑modifying permissions outside a whitelist.

7. Practical Workflow Summary

  1. Run discovery script → list risky roles.
  2. Prioritize by sensitivity (production, admin, CI/CD).
  3. For each role:
    • Review actual usage via CloudTrail.
    • Design a minimal policy (actions + resources + conditions).
    • Update the role via Python: create managed policy / update inline policy → detach/remove broad policies.
  4. Re‑run the discovery script to confirm the role no longer has broad infra‑modifying permissions.
  5. Add guardrails (SCPs, permission boundaries) to prevent regressions.
If you share an example role ARN/policy, I can help you write the exact Python code and least‑privilege replacement for that specific case.
Substitute:
  • var.AWS_REGION and var.AWS_ACCOUNT_ID with your variables or literals.
  • INSTANCE_ID_1, INSTANCE_ID_2 with the specific instance IDs the workload may manage.
  • SECURITY_GROUP_ID with the specific security group ID.
  • APP_OWNED_BUCKET_NAME with the S3 bucket the workload owns.
  • APP_INFRA_ROLE_NAME with the IAM role that should have this scoped infra-write access.
This change updates the IAM policy in place (no resource replacement of the role itself), but it may remove permissions workloads currently rely on; test in a non-production environment first.To verify, terraform plan should show:
  • ~ (update in-place) for the existing aws_iam_policy (or a new + if you are introducing this policy for the first time).
  • No changes that recreate the IAM role, only attachment changes if you are switching from a previous broad policy to this scoped one.