Skip to content

How to set granular S3 permissions per prefix

By Aleem Rehmtulla, May Inc.

TL;DR

AWS IAM is the right tool for fine-grained per-prefix access — write a policy with two statements: s3:GetObject on the prefix wildcard, and s3:ListBucket on the bucket itself with a Condition on s3:prefix. The s3:prefix condition on listing is the part most people miss, which is why first-attempt policies let users read but not list. For human collaboration, S3 Viewer offers a simpler alternative: invite someone by email as a Viewer or Editor and limit them to specific folders in a bucket, without writing IAM at all.

Steps

Step-by-step.

  1. 01

    Decide the scope

    Bucket, prefix, or single key. The smaller the scope, the safer.
  2. 02

    IAM: write the read statement

    Allow s3:GetObject on every key inside the prefix. Resource uses a wildcard.
    "Resource": "arn:aws:s3:::my-bucket/reports/finance/*"
  3. 03

    IAM: add the listing condition (the part most people miss)

    Listing requires s3:ListBucket on the bucket itself (not the prefix), with a Condition on s3:prefix. This is why most first-attempt IAM policies let users read but not list.
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "ReadInsidePrefix",
          "Effect": "Allow",
          "Action": ["s3:GetObject"],
          "Resource": "arn:aws:s3:::my-bucket/reports/finance/*"
        },
        {
          "Sid": "ListInsidePrefix",
          "Effect": "Allow",
          "Action": ["s3:ListBucket"],
          "Resource": "arn:aws:s3:::my-bucket",
          "Condition": {
            "StringLike": { "s3:prefix": ["reports/finance/*"] }
          }
        }
      ]
    }
  4. 04

    IAM: attach to a user or role and test

    Attach the policy to the IAM user or role and verify with the IAM policy simulator before handing it over. Confirm both list and get work inside the prefix and deny outside.
  5. 05

    Team workflows: S3 Viewer roles and folder limits

    Authoring an IAM policy per teammate is heavy for human collaboration. For team access, add the server once with a least-privilege credential and give each member a role: Viewer (browse and download), Editor (also upload, rename, delete and create buckets where supported) or Admin (also manage members, rename the server and remove buckets from it). Owner is not assignable — it stays with whoever created the server, and only an Owner can delete it. A bucket can override a member's server role, and a Viewer or Editor can be limited to specific folders in a bucket: while inviting them, or later under Settings, Members, switch the bucket from Whole bucket to Specific folders and add reports/finance/. They can't open, list or copy anything outside it. Admins always get whole buckets. S3 Viewer enforces this on its server — the stored credential still reaches the whole bucket — so use IAM as above when the limit has to hold for programmatic access too.
  6. 06

    Verify

    Try to list and read outside the prefix. Both should deny. If they don't, the policy is too broad — most likely the Resource wildcard is wrong or the listing Condition is missing.

Under the hood

What's actually happening.

S3 has no folders — “prefix-scoped” access is enforced by IAM policy on the key pattern. The catch is that listing requires a separate s3:ListBucket permission on the bucket ARN scoped via Condition/s3:prefix, which trips up most people writing their first IAM policy. For team collaboration, S3 Viewer offers an alternative: add the server once with one least-privilege key, give invited members a role, and limit a Viewer or Editor to the folders they need. Roles and folder limits are checked on our server before any S3 call is signed, including both ends of a copy or move, so you don't have to write a new IAM policy every time you onboard someone. The limit lives in S3 Viewer rather than in your provider: the server's credential can still reach the whole bucket, and members never see it.

FAQ

Common questions.

How do I give someone access to one folder in an S3 bucket?

Write an IAM policy with two statements: s3:GetObject on arn:aws:s3:::bucket/prefix/* (the read), and s3:ListBucket on arn:aws:s3:::bucket with a Condition StringLike: { s3:prefix: ['prefix/*'] } (the listing). The listing condition is the part most people miss. For people rather than programs, S3 Viewer is simpler: connect the bucket once, invite them by email as a Viewer or Editor, and limit that access to the folder. They never hold a key, and everything else in the bucket stays out of reach.

Why does my IAM policy let users read S3 files but not list the folder?

You're missing s3:ListBucket with an s3:prefix Condition. In S3, GetObject and ListBucket are separate permissions on different resources — GetObject is on the key (bucket/prefix/*), ListBucket is on the bucket (bucket). Granting one doesn't grant the other.

What's the difference between s3:ListBucket and s3:GetObject?

s3:ListBucket is permission to list keys in a bucket — it acts on the bucket ARN. s3:GetObject is permission to read the bytes of a specific key — it acts on the key ARN. To browse a folder, a user needs both: ListBucket to see the keys, GetObject to read them.

Can I scope down to a single S3 key?

Yes — set Resource to the exact key ARN with no wildcard, e.g., arn:aws:s3:::my-bucket/reports/q4-finance.pdf. Pair it with a ListBucket condition on the parent prefix if the user also needs to see it in a listing.

Do I need a custom IAM policy for every teammate?

Not necessarily. In S3 Viewer, one least-privilege key connects the server and four roles (Owner, Admin, Editor, Viewer) handle who can do what, with a per-bucket override where you need it, and a Viewer or Editor can be limited to specific folders. Use IAM when the scoping has to hold for programmatic access with its own keys; use S3 Viewer when people need to browse and manage files.

Does this work with Cloudflare R2?

R2 has its own token system rather than IAM-style policies. You scope R2 API tokens to specific buckets when you create them in the Cloudflare dashboard. For access control on top of that, S3 Viewer's roles are usually simpler.

Use S3 Viewer for this

Skip the CLI. Try it in the browser.

S3 Viewer turns the steps above into a single click. Open source, self-hostable, free.