Configuring S3 Buckets with Permissions and Access Roles in AWS Cognito AuthRole

2023-02-15

Configuring S3 Buckets with Permissions and Access Roles in AWS Cognito AuthRole

This is a series of articles about setting up a complex Serverless backend infrastructure with AWS SAM and CloudFormation.

Here is the index of all the articles in case you want to jump to any of them:

1. Setup of AppSync and API Gateway with Multiple AWS Cognito User Pools

2. Configuring S3 Buckets with Permissions and Access Roles in AWS Cognito AuthRole

3. Intro to DynamoDB Resolvers for AppSync Implementation

4. Intro to Lambda Resolvers for AppSync Implementation

5. Configuring an AWS VPC to Include Lambda Resolvers with a Fixed IP

6. Intro to Pipeline Resolvers for AppSync Implementation

7. Handling Lambda Resolver Timeouts with SNS Messages

Introduction

AWS S3 is a versatile storage solution. When combined with AWS Cognito's AuthRole, it offers granular access control, ensuring users can only access relevant data. In this guide, we'll explore how to grant users read access to an entire S3 bucket but restrict write access to folders matching their user IDs.

The Code

Setting Up the S3 Bucket

  1. Create an S3 Bucket.
  2. Organize Data: Structure your data such that each user's data resides in a folder named after their user ID.
Resources:
  MyS3Bucket:
    Type: "AWS::S3::Bucket"

Configuring Cognito AuthRole and UnAuthRole for S3 Access

  1. Define the UnAuthRole
  2. Create a New Identity Pool: This associates the Cognito User Pool with the identity pool. This allows for federated identities and the distinction between authenticated and unauthenticated roles.
  3. Attach both Roles: identity pool using the IdentityPoolRoleAttachment resource.
Resources:
  # Unauthenticated Role with write access to the user folder
  CognitoAuthRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "cognito-identity.amazonaws.com"
            Action: "sts:AssumeRoleWithWebIdentity"
      Policies:
        - PolicyName: "S3AccessPolicy"
          PolicyDocument:
            Statement:
              - Effect: "Allow"
                Action: "s3:GetObject"
                Resource: !Sub "arn:aws:s3:::${MyS3Bucket}/*"
              - Effect: "Allow"
                Action: "s3:PutObject"
                Resource: !Sub "arn:aws:s3:::${MyS3Bucket}/${cognito-identity.amazonaws.com:sub}/*"
  # Unauthenticated Role with read access to the S3 bucket
  CognitoUnAuthRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Federated: "cognito-identity.amazonaws.com"
            Action:
              - "sts:AssumeRoleWithWebIdentity"
            Condition:
              StringEquals:
                "cognito-identity.amazonaws.com:aud": !Ref CognitoIdentityPool
      Policies:
        - PolicyName: "S3ReadAccessPolicy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: "s3:GetObject"
                Resource: !Sub "arn:aws:s3:::${MyS3Bucket}/*"

  # Cognito Identity Pool
  CognitoIdentityPool:
    Type: "AWS::Cognito::IdentityPool"
    Properties:
      IdentityPoolName: "MyIdentityPool"
      AllowUnauthenticatedIdentities: true
      CognitoIdentityProviders:
        - ClientId: !Ref UserPoolGeneralClient
          ProviderName: !GetAtt [UserPoolGeneral, ProviderName]

  # Attach roles to the Cognito Identity Pool
  SetIdentityPoolRoles:
    Type: "AWS::Cognito::IdentityPoolRoleAttachment"
    Properties:
      IdentityPoolId: !Ref CognitoIdentityPool
      Roles:
        authenticated: !GetAtt [CognitoAuthRole, Arn]
        unauthenticated: !GetAtt [CognitoUnAuthRole, Arn]

  # Assuming you have a user pool client for the general user pool
  UserPoolGeneralClient:
    Type: "AWS::Cognito::UserPoolClient"
    Properties:
      ClientName: "GeneralUserClient"
      UserPoolId: !Ref UserPoolGeneral
      GenerateSecret: false

Conclusion

By leveraging AWS Cognito and S3's powerful access control mechanisms, businesses can ensure that users have the right data access level. This setup not only enhances security but also provides a personalized user experience.

Please note that the code examples have been simplified to help understand the approach and the resources. Some adjustments might be needed.

---------

Next UP: Part 3. Intro to DynamoDB Resolvers for AppSync Implementation