I have created a Lambda Python function through AWS Cloud 9 but have hit an issue when trying to write to an S3 bucket from the Lambda Function. When I test in Cloud 9 the Python codes runs fine and writes to the S3 bucket perfectly. When I push this to the Lambda function and it runs I think get the error. This makes me think there is a permission different between the roles used to run the application in Could 9, and that when the Lambda function runs.
The below error is given and I am looking for some advise on what I could be missing, below the error I have described the setup:
[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)
The code I have is as follows:
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 ...
The .yml file with the necessary permissions is as follows:
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'
The role the Lambda function executes with is as follows: IAM Role
Any advice as to where this could be going wrong. I understand that I need to provide the correct access but I am unsure as to where else I need to specify the correct access (I really do not want to make my S3 public just so my Lambda function can access it). In Lambda it shows that S3 has been added as a resource the functions role has access to but yet receiving the above error.