AWS 用户无权通过显式拒绝访问此资源

Posted

技术标签:

【中文标题】AWS 用户无权通过显式拒绝访问此资源【英文标题】:AWS User is not authorized to access this resource with an explicit deny 【发布时间】:2020-01-04 14:26:05 【问题描述】:

我正在 AWS 上部署一个无服务器应用程序,但在尝试从前端访问我的无服务器应用程序时遇到了一些问题。我的印象是,问题出在后端,更具体地说是 serverless.yml 配置文件(参见下面的第一行代码),或者是我的 auth0Authorizer.ts 文件(参见下面的第二行代码)。当我登录到我的前端应用程序时,我收到一条 403 错误消息,上面写着 User is not authorized to access this resource with an explicit deny。我真的怀疑这是否与 AWS 上的任何配置有关。

    org: name
app: serverless-todo-app-app
service:
  name: serverless-todo-app
package:
  individually: true

plugins:
  - serverless-webpack
  - serverless-iam-roles-per-function
  - serverless-reqvalidator-plugin
  - serverless-aws-documentation

provider:
  name: aws
  runtime: nodejs8.10
  stage: $opt:stage, 'dev'
  region: $opt:region, 'us-west-1'

  tracing: true

  environment:
    TODOS_TABLE: Todos-v4-$self:provider.stage
    USER_ID_INDEX: UserIdIndex
    SIGNED_URL_EXPIRATION: 300 
    IMAGES_S3_BUCKET: 'severless-todo-app-bucket-v1-$self:provider.stage'
    DYNAMODB_TABLE: TableName 
    TableName: $self:provider.environment.TODOS_TABLE
    AUTH_0_SECRET: ***********************************
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Scan
        - dynamodb:PutItem
        - dynamodb:GetItem
        - codedeploy:*
        - xray:PutTelemetryRecords
        - xray:PutTraceSegments
      Resource:
        - '*'
    - Effect: Allow
      Action:
        - s3:GetObject
        - xray:PutTelemetryRecords
        - xray:PutTraceSegments     
      Resource: arn:aws:s3:::$self:provider.environment.IMAGES_S3_BUCKET/*

custom:
  documentation:
    api:
      info:
        version: v1.0.0
        title: Udagram API
        description: Serverless application
    models:
      - name: TodoRequest
        contentType: application/json
        schema: $file(models/create-todo-request.json)


functions:

  Auth:
    handler: src/lambda/auth/auth0Authorizer.handler

  # TODO: Configure this function
  GetTodos:
    iamRoleStatements:
      - Effect: Allow
        Action:
          - dynamodb:Query
          - dynamodb:GetItem
        Resource: arn:aws:dynamodb:$self:provider.region:*:table/$self:provider.environment.TODOS_TABLE

    handler: src/lambda/http/getTodos.handler
    events:
      - http:
          authorizer: Auth
          method: get
          path: todos
          cors: true


  # TODO: Configure this function
  CreateTodo:
    handler: src/lambda/http/createTodo.handler
    iamRoleStatements:
      - Effect: Allow
        Action:
          - dynamodb:PutItem
          - xray:PutTelemetryRecords
          - xray:PutTraceSegments
        Resource: arn:aws:dynamodb:$self:provider.region:*:table/$self:provider.environment.TODOS_TABLE
    events:
      - http:
          authorizer: Auth
          method: post
          path: todos
          cors: true
          reqValidatorName: RequestBodyValidator
          documentation:
            summary: Create a new todo
            description: Create a new todo
            requestModels:
              'application/json': TodoRequest
  # TODO: Configure this function
  UpdateTodo:
    handler: src/lambda/http/updateTodo.handler
    iamRoleStatements:
      - Effect: Allow
        Action:
          - dynamodb:UpdateItem
          - xray:PutTelemetryRecords
          - xray:PutTraceSegments
        Resource: arn:aws:dynamodb:$self:provider.region:*:table/$self:provider.environment.TODOS_TABLE

    events:
      - http:
          authorizer: Auth
          method: patch
          path: todos/todoId
          cors: true
  # TODO: Configure this function
  DeleteTodo:
    handler: src/lambda/http/deleteTodo.handler
    iamRoleStatements:
      - Effect: Allow
        Action:
          - dynamodb:DeleteItem
        Resource: arn:aws:dynamodb:$self:provider.region:*:table/$self:provider.environment.TODOS_TABLE

    events:
      - http:
          authorizer: Auth
          method: delete
          path: todos/todoId
          cors: true

  # TODO: Configure this function
  GenerateUploadUrl:
    handler: src/lambda/http/generateUploadUrl.handler
    iamRoleStatements:
      - Effect: Allow
        Action:
          - s3:PutObject
          - s3:GetObject
          - xray:PutTelemetryRecords
          - xray:PutTraceSegments
        Resource: arn:aws:s3:::$self:provider.environment.IMAGES_S3_BUCKET/*
      - Effect: Allow
        Action:
          - dynamodb:PutItem
          - dynamodb:GetItem
          - dynamodb:UpdateItem
        Resource: arn:aws:dynamodb:$self:provider.region:*:table/$self:provider.environment.TODOS_TABLE

    events:
      - http:
          authorizer: Auth
          method: post
          path: todos/todoId/attachment
          cors: true

resources:
  Resources:
    # TODO: Add any necessary AWS resources
    AttachmentsBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: $self:provider.environment.IMAGES_S3_BUCKET
        CorsConfiguration:
          CorsRules:
            -
              AllowedOrigins:
                - '*'
              AllowedHeaders:
                - '*'
              AllowedMethods:
                - GET
                - PUT
                - POST
                - DELETE
                - HEAD
              MaxAge: 0

    BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        PolicyDocument:
          Id: MyPolicy
          Version: "2012-10-17"
          Statement:
            - Sid: PublicReadForGetBucketObjects
              Effect: Allow
              Principal: '*'
              Action: 's3:GetObject'
              Resource: 'arn:aws:s3:::$self:provider.environment.IMAGES_S3_BUCKET/*'
        Bucket: !Ref AttachmentsBucket


    GatewayResponseDefault4XX:
      Type: AWS::ApiGateway::GatewayResponse
      Properties:
        ResponseParameters:
          gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
          gatewayresponse.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
          gatewayresponse.header.Access-Control-Allow-Methods: "'GET,OPTIONS,POST'"
        ResponseType: DEFAULT_4XX
        RestApiId:
          Ref: ApiGatewayRestApi

    RequestBodyValidator:
      Type: AWS::ApiGateway::RequestValidator
      Properties:
        Name: 'request-body-validator'
        RestApiId:
          Ref: ApiGatewayRestApi
        ValidateRequestBody: true
        ValidateRequestParameters: false

    TodosDynamoDBTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: todoId
            AttributeType: S
          - AttributeName: userId
            AttributeType: S
        KeySchema:
          - AttributeName: userId
            KeyType: HASH
          - AttributeName: todoId
            KeyType: RANGE
        BillingMode: PAY_PER_REQUEST
        TableName: $self:provider.environment.TODOS_TABLE
        GlobalSecondaryIndexes:
          - IndexName: $self:provider.environment.USER_ID_INDEX
            KeySchema:
            - AttributeName: userId
              KeyType: HASH

            Projection:
              ProjectionType: ALL
import  CustomAuthorizerEvent, CustomAuthorizerResult, CustomAuthorizerHandler  from 'aws-lambda'
import 'source-map-support/register'
import  verify  from 'jsonwebtoken'
import  JwtToken  from '../../auth/JwtToken'

const auth0Secret = process.env.AUTH_0_SECRET
export const handler: CustomAuthorizerHandler = async (event: CustomAuthorizerEvent): Promise<CustomAuthorizerResult> => 
  try 
    const decodedToken = verifyToken(event.authorizationToken)
    console.log('User was authorized')

    return 
      principalId: decodedToken.sub,
      policyDocument: 
        Version: '2012-10-17',
        Statement: [
          
            Action: 'execute-api:Invoke',
            Effect: 'Allow',
            Resource: '*'
          
        ]
      
    
   catch (e) 
    console.log('User was not authorized', e.message)

    return 
      principalId: 'user',
      policyDocument: 
        Version: '2012-10-17',
        Statement: [
          
            Action: 'execute-api:Invoke',
            Effect: 'Deny',
            Resource: '*'
          
        ]
      
    
  


function verifyToken(authHeader: string): JwtToken 
  if (!authHeader)
    throw new Error('No authentication header')

  if (!authHeader.toLowerCase().startsWith('bearer '))
    throw new Error('Invalid authentication header')

  const split = authHeader.split(' ')
  const token = split[1]

  return verify(token, auth0Secret) as JwtToken

【问题讨论】:

您正在代码的错误块中传递会话策略。如果您的代码产生错误,则将应用您在 execute-api:Invoke 上的带有 Deny 的会话策略。检查所引发错误的日志。 【参考方案1】:

当 AWS 明确表示拒绝表示 IAM 策略链中的某个位置时,该操作存在拒绝。在这种情况下,唯一的策略是您的授权方 Lambda 提供的会话策略。正如 @hephalump 在 cmets 中提到的那样,根据您的代码,它会在出现错误时发生,因此请检查日志以查看需要做什么。

【讨论】:

以上是关于AWS 用户无权通过显式拒绝访问此资源的主要内容,如果未能解决你的问题,请参考以下文章

403 - 禁止访问: 访问被拒绝。您无权使用所提供的凭据查看此目录或页面。 怎么解决 ?

在 AWS Lambda 中担任角色,在 SSM 调用时拒绝访问

在 IIS7 中托管 ASP.NET 会导致访问被拒绝?

如何在 Mac OSX EACCES 上修复:权限被拒绝...您无权访问此文件

AWS 组织中的 Cloudtrail 显式拒绝失败

访问被拒绝您无权访问 Selenium Python 中的站点 [重复]