getting bucket access error in AWS - aws-lambda

I want to execute a lambda function whenever an item gets uploaded on S3. My function was invoked but there seem to be access error. What is the mistake?
I have defined a role lambdas3. Its trusted entity is lambda. It has following policy called s3lambda
Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1509114309000",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mybucketname"
]
},
{
"Sid": "Stmt1509114340000",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:*:*:*"
]
}
]
}
This is the lambda function
var aws = require('aws-sdk');
var s3 = new aws.S3();
exports.handler = function(event,context){
var bucket = event.Records[0].s3.bucket.name;
var key = decodeURIComponent(
event.Records[0].s3.object.key.replace(/\+/g,''));
var params = {
Bucket:bucket,
Key:key
};
s3.getObject(params,function(err,data){
if(err){
console.log(err);
context.fail('Error getting object'+
key+' from bucket'+bucket);
}else{
context.succeed('hello '+data.Body);
}
});
};
The function takes lambdas3 role during execution.

You need to add /* at the Resource S3 ARN in GetObject policy. S3:GetObject works for S3’s object ARN. For instance:
arn:aws:s3:::mybucketname/*

If you want to give permission to all objects in the bucket then you have to give full permission ('*' in Resource). Please find the update policy below,
Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1509114309000",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mybucketname/*"
]
},
{
"Sid": "Stmt1509114340000",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:*:*:*"
]
}
]
}

Related

What policies are required when using hadoop command with S3

I want to copy the data in on-pre to S3.
I tried to use the following command for that.
hadoop fs -Dfs.s3a.access.key=******* -Dfs.s3a.secret.key=******* -cp -f hdfs://on-pre/cluster/mydata/dt=20200601/ s3a://some-bucket/somewhere/
When I run this command, I get the following error (The path are all fakes):
cp: s3a://some-bucket/somewhere/dt=20200601/000000_0.gz: getFileStatus on s3a://some-bucket/somewhere/dt=20200601/000000_0.gz: com.amazonaws.services.s3.model.AmazonS3Exception: Forbidden (Service: Amazon S3; Status Code: 403; Error Code: 403 Forbidden; Request ID: xxxxxxxxxxxxx), S3 Extended Request ID: xxxxxxxxxxxxxxxxxxxxxxx
I set S3 policies following.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::9999999999:user/john"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::some-bucket/somewhere/*"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::9999999999:user/john"
},
"Action": "s3:List*",
"Resource": "arn:aws:s3:::some-bucket",
"Condition": {
"StringLike": {
"s3:prefix": [
"somewhere/*"
]
}
}
}
]
}
What S3 policy should I set to use hadoop fs cp?
A ListBucket was needed for the subdirectory itself
The necessary permissions may change as noted in the comments.
However, here's the code that solved it for your reference
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::9999999999:user/john"
},
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:AbortMultipartUpload"
],
"Resource": [
"arn:aws:s3:::some-bucket/somewhere/*"
]
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::9999999999:user/john"
},
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::some-bucket"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"somewhere",
"somewhere/*"
]
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::9999999999:user/john"
},
"Action": [
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::some-bucket"
]
}
]
}
Note This IAM declaration worked on June 5 2020 with Hadoop 3.2.1 or earlier. Future Hadoop releases may change the rules as they or AWS change the connector's or S3's capabilities respectively.

How to access aws resources created in other account

In my use case, I want to access DynamoDB table created in AWS account A and Lambda created in account B. For this I have followed many references on Internet which suggests me to use AWS assume role feature.
I have added following permission in Lambda execution role
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::aws-account-A-number:role/test-db-access"
}
}
Following is the trust relationship of Lambda
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::aws-account-A-number:root"
},
"Action": "sts:AssumeRole"
}
]
}
In account A, I have created role(test-db-access) for allowing others to access this account and added AmazonDynamoDBFullAccess and AdministratorAccess policies. Following is the trust relationship I have added in this account
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::aws-account-B-number:role/sam-dev-test-
TestLambda-LambdaRole-1FH5IC18J0MYT"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Following is the Java code I have added to access Dynamo DB instance
AssumeRoleRequest assumeRequest = new AssumeRoleRequest()
.withRoleArn("arn:aws:iam::aws-account-A-number:role/test-db-access").withRoleSessionName("cross_acct_lambda").withDurationSeconds(900);
final AWSSecurityTokenService sts = AWSSecurityTokenServiceClientBuilder.standard().withRegion("eu-west-1").build();
final Credentials credentials = sts.assumeRole(assumeRequest).getCredentials();
following is the crash log coming on executing lambda
{
"errorMessage": "User: arn:aws:sts::aws-account-B-number:assumed-role/sam-dev-test-TestLambda-LambdaRole-1FH5IC18J0MYT/sam-dev-test-TestLambda-LambdaFunction-73TVOBN6VXXX is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::aws-account-A-number:role/test-db-access (Service: AWSSecurityTokenService; Status Code: 403; Error Code: AccessDenied; Request ID: 100bd3a3-3f9c-11ea-b642-d3b4d9ff35de)",
"errorType": "com.amazonaws.services.securitytoken.model.AWSSecurityTokenServiceException"
}
It appears your requirements are:
From an AWS Lambda function in Account-B, access a DynamoDB table in Account-A
To reproduce your situation I did the following:
Created a DynamoDB table in Account-A
Created an IAM Role (Role-A) in Account-A with the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": "arn:aws:dynamodb:ap-southeast-2:<Account-A>:table/Inventory"
}
]
}
And this Trust Relationship (pointing to the Role created in the next step):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<Account-B>:role/role-b"
},
"Action": "sts:AssumeRole"
}
]
}
Created an IAM Role (Role-B) in Account-B for use with the Lambda function, with this policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<Account-A>:role/role-a"
}
]
}
And with this Trust Relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Created an AWS Lambda function in Account-B that will:
Assume Role-A in Account-A
Access the DynamoDB table in Account-A
I'm a Python person, so my function is:
import boto3
def lambda_handler(event, context):
# Assume Role
sts_client = boto3.client('sts')
response = sts_client.assume_role(
RoleArn='arn:aws:iam::<Account-A>:role/stack-role-a',
RoleSessionName='bar')
session = boto3.Session(
aws_access_key_id=response['Credentials']['AccessKeyId'],
aws_secret_access_key=response['Credentials']['SecretAccessKey'],
aws_session_token=response['Credentials']['SessionToken']
)
# Update DynamoDB
dynamodb_client = session.client('dynamodb')
dynamodb_client.update_item(
TableName='Inventory',
Key={'Item': {'S': 'foo'}},
UpdateExpression="ADD #count :increment",
ExpressionAttributeNames = {
'#count': 'count'
},
ExpressionAttributeValues = {
':increment': {'N': '1'},
}
)
I tested this by clicking Test on the Lambda function in Account-B. It successfully updated the DynamoDB table in Account-A.
I suspect the difference is with your trust policies, which appear to be a little bit different.

How to provide selective access for lambda execution to a federated user in AWS IAM policy?

I am trying to give lambda execution access to select members within a group. Users are authenticated via PingFederate. I am having issue granting this selective access to federated user.
I have a custom IAM policy (allow-lambda-invocation-selective) attached to this role. Although the policy seems to pass validation and policy simulation shows access is allowed, when I try to execute the lambda function I get message
Calling the invoke API action failed with this message: User:arn:aws:sts::123456789012:assumed-role/role-for-grp-l2/myuser1234 is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:123456789012:function:my-lambda-function
Here is my policy: allow-lambda-invocation-selective
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction",
"lambda:InvokeAsync",
"lambda:ListVersionsByFunction",
"lambda:GetFunction",
"lambda:ListAliases"
],
"Resource": "arn:aws:lambda:*:123456789012:function:my-lambda-function",
"Condition": {
"StringEquals": {
"aws:userid": "arn:aws:sts::123456789012:assumed-role/role-for-grp-l2/myuser1234"
}
}
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"lambda:ListFunctions",
"lambda:ListEventSourceMappings",
"lambda:ListLayers",
"lambda:ListLayerVersions"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:userid": "arn:aws:sts::123456789012:assumed-role/role-for-grp-l2/myuser1234"
}
}
}
]
}
Am i missing something?
I'm trying to understand your problem. Correct me if I made a wrong supposition.
Every group/user already have its own role.
When you authenticate your users, they have their assumed role. myuser1234, when authenticated, will receive arn:aws:sts::123456789012:assumed-role/role-for-grp-l2/myuser1234 role, right? Is it possible to create one role for each group and remove the conditions property (check item 2 explaining why)?
// role-for-grp-l2
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction",
"lambda:InvokeAsync",
"lambda:ListVersionsByFunction",
"lambda:GetFunction",
"lambda:ListAliases"
],
"Resource": "arn:aws:lambda:*:123456789012:function:my-lambda-function"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"lambda:ListFunctions",
"lambda:ListEventSourceMappings",
"lambda:ListLayers",
"lambda:ListLayerVersions"
],
"Resource": "*"
}
]
}
The problem with aws:userid
Reading the docs about the key aws:userid we can find this key has the value given by role id:caller-specified-role-name,
where role id is the unique id of the role and the caller-specified-role-name is specified by the RoleSessionName parameter passed to the AssumeRole request.
So aws:userid has value like AIDAJQABLZS4A3QDU576Q:SomeNameYouGive. Because this, your condition never match arn:aws:sts::123456789012:assumed-role/role-for-grp-l2/myuser1234 and then user cannot assume that actions.
Using conditions another way
Assuming RoleSessionName is the user name, you can use conditions this way:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction",
"lambda:InvokeAsync",
"lambda:ListVersionsByFunction",
"lambda:GetFunction",
"lambda:ListAliases"
],
"Resource": "arn:aws:lambda:*:123456789012:function:my-lambda-function",
"Condition": {
"StringLike": {
"aws:userid": "*:myuser1234"
}
}
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"lambda:ListFunctions",
"lambda:ListEventSourceMappings",
"lambda:ListLayers",
"lambda:ListLayerVersions"
],
"Resource": "*",
"Condition": {
"StringLike": {
"aws:userid": "*:myuser1234"
}
}
}
]
}
if you prefer, you may remove * wildcard getting role id using AWS CLI with the command:
aws iam get-role --role-name ROLE_NAME
and changing condition as follows:
"Condition": {
"StringEquals": {
"aws:userid": "ROLE_ID:myuser1234"
}
}

IAM Tag Policy with Condition

I am trying to create an IAM policy that gives a user full admin rights to all EC2 and RDS resources tagged with sf_env:dev.
I can't seem to figure out the syntax.
The AWS policy simulator displayed
Parse error on line 10: ..._env":"dev"}}}]}{"Statement": [{"A -------------------^ Expecting 'EOF', '}', ',', ']', got '{'
{
"Version": "2012-10-17",
"Statement": [{
"Action": "ec2:*",
"Effect": "Allow",
"Resource": "*",
"Condition": {"StringEquals": {"ec2:ResourceTag/sf_env":"dev"}}
}
]
}
{
"Statement": [{
"Action": "rds:"*",
"Effect": "Allow",
"Resource": "*",
"Condition": {"StringEquals": {"ec2:ResourceTag/sf_env":"dev"}}
}
]
}
Thanks. I used the AWS policy simulator which also checks your syntax automatically. I used this article to find out what I did wrong. http://blogs.aws.amazon.com/security/post/Tx1LYOT2FQML4UG/-Back-to-School-Understanding-the-IAM-span-class-matches-Policy-span-Grammar. I had multiple policy statements in one statement block which was an issue. I made one policy block with a single statement of arrays.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:*"
],
"Resource": [
"*"
],
"Condition": {
"StringEquals": {
"ec2:ResourceTag/sf_env": "dev"
}
}
},
{
"Effect": "Allow",
"Action": [
"rds:*"
],
"Resource": [
"*"
],
"Condition": {
"StringEquals": {
"ec2:ResourceTag/sf_env": "dev"
}
}
}
]
}

Error in creating a custom run instances policy

I am new to IAM in AWS. I have created a policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TheseActionsDontSupportResourceLevelPermissions",
"Effect": "Allow",
"Action": "ec2:DescribeImages",
"Resource": "*"
},
{
"Sid": "TheseActionsSupportResourceLevelPermissions",
"Effect": "Allow",
"Action": "ec2:RunInstances",
"Resource": [
"arn:aws:ec2:us-east-1:109027:instance/*",
"arn:aws:ec2:us-east-1:10927:image/*",
"arn:aws:ec2:us-east-1:109027:security-group/Test_hin",
"arn:aws:ec2:us-east-1:109027:subnet/subnet-b",
"arn:aws:ec2:us-east-1:109527:key-pair/*",
"arn:aws:ec2:us-east-1:10903527:network-interface/vpc-e4",
"arn:aws:ec2:us-east-1:107:volume/*"
]
}
]
}
whenever I am trying to launch an instance using console, It gives me an error that i am not authorized to perform this action.
Thanks
Try with the key pair and the network interface resources (Looks like you are trying to launch into a VPC). Also, allow the volume resources.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:RunInstances",
"Resource": [
"arn:aws:ec2:us-east-1:acct:instance/*",
"arn:aws:ec2:us-east-1:acct:image/*",
"arn:aws:ec2:us-east-1:acct:security-group/*",
"arn:aws:ec2:us-east-1:acct:subnet/*",
"arn:aws:ec2:us-east-1:acct:key-pair/*",
"arn:aws:ec2:us-east-1:acct:network-interface/*",
"arn:aws:ec2:us-east-1:acct:volume/*"
]
}
]
}

Resources