Назад | Перейти на главную страницу

Разрешения AWS: доступ Lambda запрещен для S3

Я создал функцию Lambda Python с помощью AWS Cloud 9, но столкнулся с проблемой при попытке записи в корзину S3 из функции Lambda. Когда я тестирую в Cloud 9, коды Python работают нормально и отлично записываются в корзину S3. Когда я нажимаю это на функцию Lambda, и она запускается, я думаю, что получаю ошибку. Это заставляет меня думать, что между ролями, используемыми для запуска приложения в Could 9, и тем, когда выполняется функция Lambda, есть разные разрешения.

Приведена приведенная ниже ошибка, и я ищу совет, что мне может не хватать, под ошибкой, которую я описал настройку:

[ERROR] ClientError: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
Traceback (most recent call last):
  File "/var/task/index.py", line 22, in handler
    s3.Bucket(bucket_name).put_object(Key=s3_path, Body=encoded_string)
  File "/var/runtime/boto3/resources/factory.py", line 520, in do_action
    response = action(self, *args, **kwargs)
  File "/var/runtime/boto3/resources/action.py", line 83, in __call__
    response = getattr(parent.meta.client, operation_name)(**params)
  File "/var/runtime/botocore/client.py", line 320, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/var/runtime/botocore/client.py", line 623, in _make_api_call
    raise error_class(parsed_response, operation_name)

У меня есть следующий код:

    import json
    import datetime
    from botocore.vendored import requests
    import boto3


    def handler(event, context):
        print("Start:")
        response = requests.get('https://##########')

        data = response.json()

        for i in data:
            print (i)
            encoded_string = json.dumps(i).encode("utf-8")
            bucket_name = "data"
            file_name = str(i['id']) + ".txt"
            lambda_path = "/tmp/" + file_name
            s3_path = "testBucket/" + file_name
            s3 = boto3.resource("s3")
            s3.Bucket(bucket_name).put_object(Key=s3_path, Body=encoded_string)
...rest of code ...

Файл .yml с необходимыми разрешениями выглядит следующим образом:

AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::Serverless-2016-10-31
- AWS::CodeStar

Parameters:
  ProjectId:
    Type: String
    Description: CodeStar projectId used to associate new resources to team members
  CodeDeployRole:
    Type: String
    Description: IAM role to allow AWS CodeDeploy to manage deployment of AWS Lambda functions
  Stage:
    Type: String
    Description: The name for a project pipeline stage, such as Staging or Prod, for which resources are provisioned and deployed.
    Default: ''

Globals:
  Function:
    AutoPublishAlias: live
    DeploymentPreference:
      Enabled: true
      Type: Canary10Percent5Minutes
      Role: !Ref CodeDeployRole

Resources:
  HelloWorld:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: python3.7
      Timeout: 10
      Role:
        Fn::GetAtt:
        - LambdaExecutionRole
        - Arn
      Events:
        GetEvent:
          Type: Api
          Properties:
            Path: /
            Method: get
        PostEvent:
          Type: Api
          Properties:
            Path: /
            Method: post
  LambdaExecutionRole:
    Description: Creating service role in IAM for AWS Lambda
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub 'CodeStar-${ProjectId}-Execution${Stage}'
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: [lambda.amazonaws.com]
          Action: sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        -  arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      PermissionsBoundary: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/CodeStar_${ProjectId}_PermissionsBoundary'

Роль, которую выполняет лямбда-функция, следующая: Роль IAM

Любой совет относительно того, где это может пойти не так. Я понимаю, что мне нужно предоставить правильный доступ, но я не уверен, где еще мне нужно указать правильный доступ (я действительно не хочу, чтобы мой S3 был общедоступным, чтобы моя функция Lambda могла получить к нему доступ). В Lambda это показывает, что S3 был добавлен в качестве ресурса, к которому у роли функции есть доступ, но все же получил указанную выше ошибку.

Я считаю, что решение должно быть таким же простым, как изменение вашего LambdaExecutionRole к этому:

LambdaExecutionRole:
  Description: Creating service role in IAM for AWS Lambda
  Type: AWS::IAM::Role
  Properties:
    RoleName: !Sub 'CodeStar-${ProjectId}-Execution${Stage}'
    AssumeRolePolicyDocument:
      Statement:
      - Effect: Allow
        Principal:
          Service: [lambda.amazonaws.com]
        Action: sts:AssumeRole
    Path: /
    ManagedPolicyArns:
    - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
    - arn:aws:iam::aws:policy/AmazonS3FullAccess         # <== Add
    # PermissionsBoundary: !Sub ...                      # <== Comment out

Если это сработает, вы можете поэкспериментировать с ограничением разрешений S3 для определенного сегмента, но для начала попробуйте добавить AmazonS3FullAccess политика и комментарий Разрешения.

Надеюсь, это поможет :)