awslabs / amplify-video

An open source Category Plugin for the AWS Amplify-CLI that makes it easy to deploy live and file based streaming video services and integrate them into your Amplify applications.
https://www.npmjs.com/package/amplify-category-video
Apache License 2.0
267 stars 56 forks source link

Getting 403 Forbidden when trying to upload video to the input s3 bucket as an authenticated user #316

Open pedramp20 opened 2 years ago

pedramp20 commented 2 years ago

Describe the bug I followed the instruction to setup VOD and configured it to allow authenticated users to be able to upload to the input s3 bucket. When I check the AuthRole it has the policy allowing PutObject to the input bucket. however, I get forbidden 403 error when trying to upload a video file to the bucket. I am using the code provided here. Has anybody else faced the same issue? Is it a limitation of amplify to support multiple buckets?

nathanagez commented 2 years ago

Hi @pedramp20, does your user is part of Cognito's Admin group ?

pedramp20 commented 2 years ago

@nathanagez No it is not. As I explain, I chose the option where any authenticated user can upload videos.

? Choose what project you want to update? xxxxVod
? Select a system-provided encoding template, specify an already-created template name:  Default HLS Adaptive Bitrate
? Do you want to get notifications on the video processing job? Yes
? Do you want a custom function executed for notifications? Yes
? Is this a production enviroment? Yes
? We detected you have signed urls configured. Would you like to: Leave as configured
? Do you want Amplify to create a new GraphQL API to manage your videos? (Beta) Yes
Using xxxapi to manage API
? Define your permission schema (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed)
 ( ) Admins can only upload videos
>(*) Any authenticated user can upload videos

Based on my understanding and as the name suggests any authenticated user should be able to upload video? Am I correct @nathanagez ?

kylekirkby commented 2 years ago

@pedramp20 Have you got any other auth roles that the users are assuming? If you've enabled Cognito user groups with the amplify cli, you may be assuming a group auth role instead...

You can always create signed urls with a lambda function for uploading with your own business logic granting users a signed URL.

nathanagez commented 2 years ago

@pedramp20 If I'm not wrong amplify-video only supports admin upload FTM, is it right @wizage ? If it's the case we should mention it inside the documentation.

pedramp20 commented 2 years ago

@kylekrkby Yes, there are other groups. I am investigating to make sure what role(s) are assumed while calling the s3 api. I know that I can generate the signed url with a lambda function and don't think it is causing this failure?

@nathanagez If this is the case, the option is very misleading. Is there any way to specify the group(s) that are given the PutObject permission? I couldn't find any policy or cloudformation script giving access to a specific group!? I looked at the s3 permissions there is no explicit deny or ACL. The AuthRole also allows PutObject. Can you please refer to the code where these settings are defined?

nathanagez commented 2 years ago

@kylekrkby Yes, there are other groups. I am investigating to make sure what role(s) are assumed while calling the s3 api. I know that I can generate the signed url with a lambda function and don't think it is causing this failure?

@nathanagez If this is the case, the option is very misleading. Is there any way to specify the group(s) that are given the PutObject permission? I couldn't find any policy or cloudformation script giving access to a specific group!? I looked at the s3 permissions there is no explicit deny or ACL. The AuthRole also allows PutObject. Can you please refer to the code where these settings are defined?

Yes I agree with you, when your user is part of Admin group it will create a policy that you can find here: https://github.com/awslabs/amplify-video/blob/9da19ba66a0bbc9523d9942104817efd42541ade/provider-utils/awscloudformation/service-walkthroughs/vod-roles.js#L13

pedramp20 commented 2 years ago

Thank you all for your help. As you pointed out @kylekirkby, when there are other groups with lower precedence, the user assumes that role and since the policy with PutObject permission is not added to those roles, user gets 403 when calls the s3 api. I think this is very important to be included in the documentation. The option provided in the CLI only adds the policy to the AuthRole and if other groups and hence other roles exist, it is pretty much useless and very misleading. The approach of hard coding a role in the code is not very helpful either, while this option could be given to the user to tick the groups s/he wants to grant the permission to.

As a solution, I am trying to pass the userpoolId to the template to add the policy to those roles and based on your documentation and this discussion, all the files with the same name in the build folder are overwritten with the items in the custom folder but it is not what I am experiencing. @nathanagez can you please confirm if this is the case?

Basically I have added the parameter to the paramters.json, props.jason, the main vod template and s3input template but on push they are not copied to the build folder and as a result I get an error stating "Parameters: [UserPoolId] do not exist in the template

parameters.json

{
    "authRoleName": {
        "Ref": "AuthRoleName"
    },
    "UserPoolId": {
        "Fn::GetAtt": [ "authxxxx", "Outputs.UserPoolId" ]
    },
    "GraphQLAPIId": {
        "Fn::GetAtt": [ "apixxxx", "Outputs.GraphQLAPIIdOutput" ]
    },
    "GraphQLEndpoint": {
        "Fn::GetAtt": [ "apixxxx", "Outputs.GraphQLAPIEndpointOutput" ]
    }
}

props.json

{
    "shared": {
        "resourceName": "xxxxVod"
    },
    "template": {
        "type": [ "HLS" ],
        "name": "Amplify_Video_HLS.json"
    },
    "sns": {
        "createTopic": true,
        "snsFunction": true
    },
    "contentDeliveryNetwork": {
        "signedKey": true,
        "functionNameSchema": "xxxxVod-${env}-tokenGen",
        "enableDistribution": true
    },
    "parameters": {
        "authRoleName": {
            "Ref": "AuthRoleName"
        },
        "UserPoolId": {
            "Fn::GetAtt": [ "authxxxx", "Outputs.UserPoolId" ]
        },
        "GraphQLAPIId": {
            "Fn::GetAtt": [ "apixxxx", "Outputs.GraphQLAPIIdOutput" ]
        },
        "GraphQLEndpoint": {
            "Fn::GetAtt": [ "apixxxx", "Outputs.GraphQLAPIEndpointOutput" ]
        }
    },
    "permissions": {
        "permissionSchema": [ "any" ]
    },
    "cms": {
        "overrideSchema": false,
        "editAPI": false
    }
}

\custom\xxxx-vod-workflow-template.yaml

...
Resources:

  rS3InputBucket:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub "https://s3.amazonaws.com/${pS3}/${pSourceFolder}/S3InputBucket.template"
      Parameters:
        authRoleName: !Ref authRoleName

        UserPoolId: !Ref UserPoolId

        pPolicyName: !Sub "${AWS::StackName}-s3UploadPermissions"

        pBucketName: !Ref pS3InputName

...

\custom\vod-helpers\S3InputBucket.template

Parameters:
  pBucketName:
    Type: String
    Description: ProjectName
    AllowedPattern: "[a-zA-Z][a-zA-Z0-9-_]*"
    Default: DefaultName
  pPolicyName:
    Type: String
    Description: Policy name for allowing uploads from all auth users
    Default: S3UploadPolicy\
  authRoleName:
    Type: String
    Description: Name of authRole
    Default: NONE
  UserPoolId:
    Type: String
    Default: NONE

....

  UploadPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: !Ref pPolicyName
      Roles:
        - !Ref authRoleName
        - !Join
          - ''
          - - !Ref UserPoolId
            - '-YourGroupRole'
pedramp20 commented 2 years ago

It seems like allowing other groups to upload is already implemented and merged? @wizage https://github.com/awslabs/amplify-video/issues/136

pedramp20 commented 2 years ago

@wizage please review this pull request. I got rid of the hacky way of adding the hardcoded admin group and modifying Cognito pool groups. I added an extra question, where users can choose the group(s) they want to grant permissions to. https://github.com/awslabs/amplify-video/pull/318