AWS Lambda - Access Denied Error - GetObject - amazon-web-services

I am a newbie to AWS Lambda. I am trying out the Tutorial from https://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html. When the user uploads a jpg to a S3 bucket called greetingsproject, the lambda function is triggered.
Error: 9a62ff86-3e24-491d-852e-ded2e2cf5d94
INFO: error while getting object = AccessDenied: Access Denied
I am getting the Access denied error in the following code snippet:
try {
console.log("srcBucket=" + srcBucket);
console.log("srcKey=" + srcKey);
const params = {
Bucket: srcBucket,
Key: srcKey
};
var origimage = await s3.getObject(params).promise();
} catch (error) {
console.log("error while getting object = " + error);
return;
}
My Policy for the Role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:PutLogEvents",
"logs:CreateLogGroup",
"logs:CreateLogStream"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::greetingsproject"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::greetingsproject",
"arn:aws:s3:::greetingsproject/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::greetingsproject",
"arn:aws:s3:::greetingsproject/*"
]
}
]
}
Not sure what other permissions I need to add to the policy.

The comment by Marcin about Lambda execution role put me on the right track.
I had followed the below steps previously:
Created a policy called greetingsProjectPolicy (with the above mentioned permissions)
Attached this policy to greetingsProjectRole.
Assigned the greetingsProjectRole to my lambda function.
I assumed that was it and the policy should be available to my lambda function.
However when I assigned the greetingsProjectRole to the function, internally AWS created a Execution role called greetingsProject-role-zhcbt61o.
When I clicked on this role, I was surprised to see that only role it had was the AWSLambdaBasicExecutionRole and the greetingsProjectPolicy was missing.
I had to add the greetingsProjectPolicy as a inline policy to greetingsProject-role-zhcbt61o. Now I no longer get the access denied error.
Not sure, if this is how AWS works or I am missing something.

Related

AWS cli not behaving as expected , w.r.t UI

I have one S3 bucket with no resource policy. I create policy explicitly that restrict IAM user access to this bucket by creating below policy and attaching it to IAM user.
If I login using that user in console , I see that list of bucket and can do action that are defined in policy. but when I try doing aws s3 ls is give me below error
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
Policy
{
"Statement": [
{
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Effect": "Allow",
"Resource": "*",
"Sid": "AllowAppsS3ListAccess"
},
{
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::bucket-name",
"arn:aws:s3:::bucket-name/*"
],
"Sid": "AllowAppsS3Access"
}
],
"Version": "2012-10-17"
}

Step function unable to trigger ECS task on fargate cluster, permission issue

I am creating and running a task on my ECS fargate cluster.
Task definition (with role) and fargate cluster is already created.
When I use run task step in step function, I am getting following error,
{
"Error": "ECS.AccessDeniedException",
"Cause": "User: arn:aws:sts::xxxxxxxxxx:assumed-role/StepFunctions-my-state-machine-role-xxxxxxxxxx/xxxxxxxxxx is not authorized to perform: iam:PassRole on resource: arn:aws:iam::xxxxxxxxxx:role/my-app-dev-exec because no identity-based policy allows the iam:PassRole action (Service: AmazonECS; Status Code: 400; Error Code: AccessDeniedException; Request ID: xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx; Proxy: null)"
}
The role attached to the step function has the following policies (as per the documentation provided by AWS https://docs.aws.amazon.com/step-functions/latest/dg/ecs-iam.html)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:RunTask"
],
"Resource": [
"arn:aws:ecs:eu-west-1:xxxxxxxxxx:task-definition/*:*"
]
},
{
"Effect": "Allow",
"Action": [
"ecs:StopTask",
"ecs:DescribeTasks"
],
"Resource": [
"arn:aws:ecs:eu-west-1:xxxxxxxxxx:task/*"
]
},
{
"Effect": "Allow",
"Action": [
"events:PutTargets",
"events:PutRule",
"events:DescribeRule"
],
"Resource": [
"arn:aws:events:eu-west-1:xxxxxxxxxx:rule/StepFunctionsGetEventsForECSTaskRule"
]
},
{
"Effect": "Allow",
"Action": [
"states:DescribeStateMachine",
"states:StartExecution",
"states:ListExecutions",
"states:UpdateStateMachine"
],
"Resource": [
"arn:aws:states:eu-west-1:xxxxxxxxxx:stateMachine:my-state-machine"
]
}
]
}
with following trusted entities
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "states.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Can someone help with what additional permission I need to give to resolve the above permission issue? From the error, I am not able to figure out what additional permission is required.
If I attach AmazonECS_FullAccess (aws managed) policy to the role, job works perfectly.
Because your task will use an IAM Role, you need to specify the additional permission 'PassRole'.
The best practice is to restrict which roles can be passed. So is recommended to add a condition limiting to only allow to pass roles to ECS tasks.
Try adding this statement to your policy:
{
"Action": "iam:PassRole",
"Effect": "Allow",
"Resource": [
"*"
],
"Condition": {
"StringLike": {
"iam:PassedToService": "ecs-tasks.amazonaws.com"
}
}
}

AWS Lambda S3 Access Denied

I have a lambda function using a role with the following policy excerpt
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::ipwl-lambda-config/*",
"arn:aws:s3:::ipwl-lambda-config"
]
}
My bucket policy looks like the following
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnEncryptedObjectUploads",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::ipwl-lambda-config/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "aws:kms"
}
}
},
{
"Sid": "AllowLambda",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::accountid:role/iam_for_lambda"
},
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::ipwl-lambda-config/*",
"arn:aws:s3:::ipwl-lambda-config"
]
}
]
}
I've allowed GetObject and ListBucket on both the role and the bucket policy. However when my function runs
s3_obj = s3_res.Object(s3_bucket, s3_object)
I get
[ERROR] ClientError: An error occurred (AccessDenied) when calling the
GetObject operation: Access Denied
What more permissions do I have to add? The object is there, I can get it when I run the code locally using an admin role.
Update
I've checked to make sure the bucket and object names are correct dozens of times. The exception is actually coming from the second line here according to the stacktrace
s3_res = boto3.resource('s3')
s3_obj = s3_res.Object(s3_bucket, s3_object)
data = s3_obj.get()['Body'].read()
KMS should only be a factor for PutObject. We have a support account so I may check with them and update with their findings.
To download a KMS-encrypted object from S3, you not only need to be able to get the object. You also need to be able to decrypt the AWS KMS key.
Here's an example of an IAM policy that your Lambda function should have:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "s3get",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::ipwl-lambda-config/*"
},
{
"Sid": "kmsdecrypt",
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:example-region-1:123456789012:key/example-key-id"
}
]
}
The key policy also needs to allow the IAM role to decrypt the key, something like this:
{
"Sid": "kmsdecrypt",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/xyz"
},
"Action": "kms:Decrypt",
"Resource": "*"
}

S3 Private Bucket

I'm trying to create a private S3 bucket with limited access. I only want myself as a user and an EC2 role to have access to the bucket. The purpose of the bucket is to store encrypted SSH keys that will be copied onto machines in an autoscaling group. Right now, when I run aws sync against the bucket, here is the output:
cogility#ip-10-10-200-113:~$ aws s3 sync s3://sshfolder.companycloud.com/cogility /home/cogility/.ssh
download failed: s3://sshfolder.companycloud.com/cogility/id_rsa to ../cogility/.ssh/id_rsa An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
download failed: s3://sshfolder.companycloud.com/cogility/id_rsa.pub to ../cogility/.ssh/id_rsa.pub An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
I create the EC2 instances with an EC2 role with the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"kms:List*",
"kms:Get*",
"kms:Describe*"
],
"Resource": "arn:aws:kms:us-west-2:0000000000:key/kms-id-01234567890"
},
{
"Sid": "",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sshfolder.companycloud.com/*",
"arn:aws:s3:::sshfolder.companycloud.com"
]
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"elasticloadbalancing:*",
"ec2:*",
"cloudwatch:*",
"autoscaling:*"
],
"Resource": "*"
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"lambda:List*",
"lambda:Invoke*",
"lambda:Get*"
],
"Resource": "*"
}
]
}
And here is the bucket policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sshfolder.companycloud.com",
"arn:aws:s3:::sshfolder.companycloud.com/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"AROAXXXXXXXXXXXXXXXXX", <-- autoscaling-ec2-role user id
"AROAXXXXXXXXXXXXXXXXX",
"AIDAXXXXXXXXXXXXXXXXX",
"AIDAXXXXXXXXXXXXXXXXX"
],
"aws:sourceVpce": "vpce-abc82480d"
},
"ArnNotLike": {
"aws:SourceArn": "arn:aws:sts::000000000000:assumed-role/autoscaling-ec2-role/"
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::000000000000:root"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sshfolder.companycloud.com",
"arn:aws:s3:::sshfolder.companycloud.com/*"
]
}
]
}
Any idea why I'm not able to access the S3 bucket from my EC2 instance?
Amazon S3 buckets are private by default. Therefore, one approach would be:
Do not use a Bucket Policy
Add permissions to your IAM User and the IAM Role to access the bucket
Alternatively:
Use a Bucket Policy to grant access to the IAM User and IAM Role
Both would be sufficient to meet your needs.
However, if you are further paranoid that somebody might accidentally grant access to the bucket (eg with s3:* and a principal of *), then your approach of explicitly Denying access to anyone other than that User & Role is a good approach.
deny trumps allow in your bucket policy. You need to use not principal to achieve this.
"Statement": [
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": "arn:aws:iam::000000000000:root"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sshfolder.companycloud.com",
"arn:aws:s3:::sshfolder.companycloud.com/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"AROAXXXXXXXXXXXXXXXXX", <-- autoscaling-ec2-role user id
"AROAXXXXXXXXXXXXXXXXX",
"AIDAXXXXXXXXXXXXXXXXX",
"AIDAXXXXXXXXXXXXXXXXX"
],
"aws:sourceVpce": "vpce-abc82480d"
},
"ArnNotLike": {
"aws:SourceArn": "arn:aws:sts::000000000000:assumed-role/autoscaling-ec2-role/"
}
}
}
]
It just inverts the principal element. You can similarly use NotAction and NotResource as appropriate. You could do away with your conditionals altogether and just use NotPrincipal for all of them, it's generally better practice than conditionals.
Here is a resource on it: https://aws.amazon.com/blogs/security/how-to-create-a-policy-that-whitelists-access-to-sensitive-amazon-s3-buckets/

How to create a folder in AWS S3 using AWS Lambda for a user authenticated by Cognito

I am trying to invoke a lambda function that creates AWS resources (S3 folder and DynamoDB Item) for authenticated users. Lambda function will be invoked from client side after the user is logged in through AWS Cognito.
Making an S3 putObject request from client-side works fine. However, if I make the same request from the invoked Lambda function, it fails.
Client --> S3 --> Works
Client --> Lambda --> S3 --> Does not work
Here is my Lambda function:
s3 = boto3.resource('s3')
bucket = s3.Bucket('BUCKET_NAME')
id = str(context.identity.cognito_identity_id)
bucket.put_object(Key='cognito/users/{}/'.format(id))
I get the following error
ClientError: An error occurred (AccessDenied) when calling the PutObject operation:
Access Denied
Both Cognito Authenticated Role and Lambda Role is pointing to the same role:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["lambda:InvokeFunction"],
"Effect": "Allow",
"Resource": "arn:aws:lambda:us-east-1:ACCOUNT_ID:function:CreateResources"
},
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::BUCKET_NAME"],
"Condition": {
"StringLike": {
"s3:prefix": ["cognito/users/${cognito-identity.amazonaws.com:sub}/*"]
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::BUCKET_NAME/cognito/users/${cognito-identity.amazonaws.com:sub}",
"arn:aws:s3:::BUCKET_NAME/cognito/users/${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}
And the trust relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:IDENTITY_POOL_ID"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
},
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": [
"sts:AssumeRole",
"sts:AssumeRoleWithWebIdentity"
]
}
]
}
How can I achieve this or is there a better way to do this?