Least-privilege IAM, written for you
Run your code once. pogi writes the policy from the calls it saw. Then strict mode blocks anything that policy does not allow.

The problem
A tight policy needs every action your code calls, and most teams don't know that list. So they start with a wide policy and mean to narrow it later, or they find the missing permission when production fails.
How it works
01
Record what your code calls
In soft mode every call is allowed, and pogi writes down the action and the resource of each call made with an IAM user's key or by an assumed role. The console flags what strict mode would deny.
localhost:7644/_pogi/
localhost:7644/_pogi/IAM policy
user/dev · 3 calls recorded
The IAM page in soft mode: three called actions for the user dev, each flagged would deny. 02
Get the policy
pogi turns the list into a policy with exactly those actions, narrowed to the resources your code touched. Attach it from the console, or take it as JSON or Terraform.
/_pogi/iam/policy{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:ListAllMyBuckets", "Resource": "*" }, { "Effect": "Allow", "Action": "sns:ListTopics", "Resource": "*" }, { "Effect": "Allow", "Action": "sns:CreateTopic", "Resource": "arn:aws:sns:us-east-1:000000000000:alerts" } ] }03
Prove it in strict mode
With the policy attached, a call it does not allow fails with AccessDenied and AWS's own message. If your tests still pass, the policy is enough. The same modes work on Google Cloud and Azure.
localhost:7644/_pogi/
localhost:7644/_pogi/IAM policy
Strict · user/dev
The IAM page in strict mode: three recorded actions allowed, and two new calls, sqs:ListQueues and sns:Publish, flagged would deny.
Try it
This is real output from a running pogi.
Record, then read the policy
# soft mode: every call is allowed, and pogi writes down what the user dev calls
curl -X POST -d mode=soft http://localhost:7644/_pogi/iam/mode
aws s3 ls
aws sns create-topic --name alerts
aws sns list-topics
# the policy pogi wrote from those calls
curl "http://localhost:7644/_pogi/iam/policy?principal=arn:aws:iam::000000000000:user/dev"
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "sns:ListTopics",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "sns:CreateTopic",
"Resource": "arn:aws:sns:us-east-1:000000000000:alerts"
}
]
}Attach it, then enforce
# strict mode, with the policy attached to the user curl -X POST -d mode=strict http://localhost:7644/_pogi/iam/mode curl -X POST --data-urlencode "principal=arn:aws:iam::000000000000:user/dev" \ http://localhost:7644/_pogi/iam/attach # the user dev again: recorded calls pass, a new call fails aws s3 ls 2026-10-27 15:43:17 demo aws sqs list-queues aws: [ERROR]: An error occurred (AccessDeniedException) when calling the ListQueues operation: User: arn:aws:iam::000000000000:user/dev is not authorized to perform: sqs:ListQueues on resource: * because no identity-based policy allows the sqs:ListQueues action
What to know
- Calls made as root, or with the default test credentials, are always allowed and never recorded. pogi checks calls from an IAM user's key or an assumed role.
- pogi enforces identity policies, permissions boundaries, service control policies, S3 bucket policies and the Deny statements of API Gateway resource policies. It does not check other resource-based policies yet, such as SQS, SNS and KMS key policies.
- A policy that allows a call only under a condition can still read as "would deny", because the check has no condition keys.
- A pass in pogi is strong evidence, not proof. The real cloud can still deny a call.
Learn it step by step
The guides are in the docs.