AWS Cloud 9を通じてLambda Python関数を作成しましたが、Lambda関数からS3バケットに書き込もうとしたときに問題が発生しました。Cloud9でテストすると、Pythonコードは正常に実行され、S3バケットに完全に書き込みます。これをLambda関数にプッシュして実行すると、エラーが発生すると思います。これにより、アプリケーションの実行に使用されるロール間に異なる権限があると思います可能性があります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'
Lambda関数が実行する役割は次のとおりです。 IAM Role
これがどこで間違っているのかについてのアドバイス。正しいアクセスを提供する必要があることを理解していますが、他にどこに正しいアクセスを指定する必要があるかわかりません(実際にLambda関数がアクセスできるように、S3をパブリックにしたくありません)。 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ポリシーを追加してコメントアウトしてみてくださいPermissionsBoundary。
それが役に立てば幸い:)