Restricting S3 resources based on a user's group

Viewed 184

I have a web app where users (logged in via Cognito with an ID Token JWT) can upload/download files from an S3. Users should only access S3 resources related to their organization. For that, I'm thinking of separating S3 path by organization:

"arn:aws:s3:::my_bucket/org1"
"arn:aws:s3:::my_bucket/org2"
"arn:aws:s3:::my_bucket/org3"

Question

How do you secure the S3 paths ("folders") so that users can only access resources for their org? I did some research, see options below - but is there an easier way? This seems like a fairly common use case. Thanks!

Options I've considered

EDIT: I initially thought of using JWT claims (#1 below). But it's dawning on me that AWS prefers the use of "Identity Pools" for this kind of thing. This makes sense because you can connect different IdP's (ex Auth0) to an Identiy Pool, and set policies using Identities (Identity Role -> Identity Policy). So I'm going to try that and report back if that works.

  1. S3 Policy using JWT claims. Haven't found docs on using JWTs, so not sure if this is possible. Use the JWT claim as the path selector in the s3 policy. Each user has a custom claim called "organization".
User 1 has JWT with claim "organization: organization1"
User 2 has JWT with claim "organization: organization2"
etc.

Sample bucket policy [1] (not sure if syntax is correct)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": ["s3:ListBucket"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::mybucket"],
      "Condition": {"StringLike": {"s3:prefix": ["${cognito-identity.amazonaws.com:organization}/*"]}} // here
    },
    {
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::mybucket/${cognito-identity.amazonaws.com:organization}/*"] // here
    }
  ]
}
  1. IAM policies with the Identity Pool's "Role Based Access Control" feature [0].
  • Assign each cognito user a Group value in the User Pool. This is their organization (ex. "organization1").
  • Map the Group to an IAM Role called "OrgRole" w/ an IAM policy that only allows s3 access to a path with their organization.

Something like this...

User  | Cognito Group | IAM Role | IAM Policy S3 resource Mapping
user1 | organization1 | OrgRole  | my-bucket/organization1/*
user2 | organization2 | OrgRole  | my-bucket/organization1/*
user3 | organization2 | OrgRole  | my-bucket/organization2/*
user4 | organization3 | OrgRole  | my-bucket/organization3/*

Sample IAM policy for this role

      "Resource": ["arn:aws:s3:::my_bucket/${current-users-cognito-group}/*"]

Cons: Complicated setup and per [0], only supports 25 groups per user pool which doesn't scale. Which makes me think my setup is incorrect.

[0] https://aws.amazon.com/blogs/aws/new-amazon-cognito-groups-and-fine-grained-role-based-access-control-2/

[1] https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html

[2] https://aws.amazon.com/blogs/security/writing-iam-policies-grant-access-to-user-specific-folders-in-an-amazon-s3-bucket/

0 Answers
Related