Context & Approach


An effective approach to finding the least privileges for AWS IAM policies is to use AWS CloudTrail. This page provides a detailed how-to; useful for continuous delivery IAM users.


  • Use a programmatic access only user, with full permissions. This is to filter out events that trigger from AWS console interaction.
  • Deploy your CloudFormation infrastructure using this user from your development machine.

    ⚠ It takes around 10 minutes for these logs to be shown in the AWS CloudTrail. So take a coffee in the meantime.

  • Visit AWS CloudTrail console, and limit results to the time period since you started the deployment. This ensures you’re not getting unrelated logs.
  • Filter by username instead of AWS KEY for immediate results. The AWS Key responds with inconsistent results. The probable cause is the eventual consistency. Waiting some time, it starts showing results with AWS Key as well.
  • Download all the events as CSV; open said file, and order records by column Event name
  • Start adding permission using these event names
    • As per AWS recommended best practise, limit scope to relevant environments.
      • E.g. arn:aws:cloudformation:us-east-1:000000000000:stack/name-production-stories/*
    • Categorise permission based on their logical names. This helps with creating a more logical picture in your mind.
    • Use inline policies, and if limit reached, start extracting them to normal policies. Saves some time.
    • When you need a specific resource, go back to CloudTrail, find the event name. Expanding said log, the event source should have the data in requestParameters.
  • As you add the permission, delete the event records from the CSV. This greatly speeds up finding events that haven’t been added yet, as there can be dozens of duplicate events.
  • Remember to also destroy the stack, to find the relevant access policies.

Finally, while still using your development machine, do a final deployment with a user having the new privileges you added on the previous steps. This catches any missing events not logged in CloudTrail, such as TagResource. And it’s the fastest way to trigger & complete the deployment.