S3 Access Denied when specify the principal - amazon-web-services

Bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456784337:root",
"arn:aws:iam::123456784337:user/lambda-user"
]
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/*"
}
]
}
Initialize
AWS.config.update({
region: 'ap-southeast-1',
accessKey: 'abcxxxx',
secretAccessKey:'abcdxxx'
});
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'ap-southeast-1:12340000-5587-4d40-91fe-9fab5668c708'
});
S3 getObject
function (bucketName, key) {
const params = {
Bucket: bucketName,
Key: key,
};
return s3.getObject(params).promise()
.then((data) => {
console.log('Successfully read from S3!');
return data;
});
};
Congnito userUnauthenticated
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"lambda:InvokeFunction",
"mobileanalytics:PutEvents",
"dynamodb:Scan",
"lambda:InvokeAsync",
"cognito-sync:*"
],
"Resource": "*"
}
]
}
Failed to read to S3. AccessDenied: Access Denied
(node:73168) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): AccessDenied: Access Denied
It only works when Principal is wildcard but it is not advisable to have that configuration.

Here is the policy to read files from S3.
{
"Id": "Policy1528709447655",
"Version": "2012-10-17",
"Statement": [{
"Sid": "Stmt1528709412334",
"Action": [
"s3:GetBucketPolicy",
"s3:GetObject",
"s3:GetObjectTagging",
"s3:GetObjectAcl"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::bucket_name",
"arn:aws:s3:::bucket_name/*"
],
"Principal": {
"AWS": [
"arn:aws:iam::123456784337:root",
"arn:aws:iam::487686674337:user/lambda-user"
]
}
}]
}

Related

AWS Secrets Manager Resource Policy to Deny all roles Except one Role

I have a secret in secrets manager and there are multiple IAM roles in the system. I only want only one role to access the scecret. Unfortunately there are some other IAM roles that have full Secrets Manager privileges. So i want to restrict the access to the secret to all other roles except desired one by me.
roles
IAM_role_that_need_to_access_the_secret.
IAM_role_1_that_should_not_access_the_secret.
IAM_role_2_that_should_not_access_the_secret.
The following is working.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "secretsmanager:GetSecretValue",
"Principal": {
"AWS": "arn:aws:iam::IAM_role_1_that_should_not_access_the_secret",
"AWS": "arn:aws:iam::IAM_role_2_that_should_not_access_the_secret"
},
"Resource": "*"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::IAM_role_that_need_to_access_the_secret"
},
"Action": "secretsmanager:GetSecretValue",
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"secretsmanager:VersionStage": "AWSCURRENT"
}
}
}
]
}
But i want to Deny access to all roles without explicitly mentioning each of them in the Deny permission section. Something like below. But it will restrict to all roles including the desired role.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "secretsmanager:GetSecretValue",
"Principal": {"AWS": "*"},
"Resource": "*"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::IAM_role_that_need_to_access_the_secret"
},
"Action": "secretsmanager:GetSecretValue",
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"secretsmanager:VersionStage": "AWSCURRENT"
}
}
}
]
}
Update:
I asked AWS Support, and they said:
It is a known issue where NotPrinicipal fails the resource policy with an explicit deny.
The workaround is to use "StringNotEquals":"aws:PrincipalArn" condition key.
Previous answer:
You can use NotPrincipal:
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": "arn:aws:iam::IAM_role_that_need_to_access_the_secret"
},
"Action": "secretsmanager:GetSecretValue",
"Resource": "*",
...
You could create a KMS key then create a policy for the KMS key which grants access only to the roles you need. Something like below:
{
"Version": "2012-10-17",
"Id": "key-default-admin",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<AWS_ACCOUNT_ID>:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow administration of the key",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>",
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>"
]
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/AdminRole",
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>"
]
},
"Action": [
"kms:DescribeKey",
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey",
"kms:GenerateDataKeyWithoutPlaintext"
],
"Resource": "*"
},
{
"Sid": "Deny use of the key",
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::<AWS_ACCOUNT_ID>:root"
},
"Action": "kms:*",
"Resource": "*",
"Condition": {
"StringNotLike": {
"aws:PrincipalArn": [
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>",
"arn:aws:iam::<AWS_ACCOUNT_ID>:role/<ROLE_NAME>"
]
}
}
}
]
}
I was able to achieve this with using a Condition on the Resource Policy and specifying the ARN of the Role in aws:PrincipalArn (Ref: https://aws.amazon.com/blogs/security/iam-makes-it-easier-to-manage-permissions-for-aws-services-accessing-resources/)
{
"Version" : "2012-10-17",
"Statement" : [
{
"Sid" : "Get",
"Effect" : "Deny",
"Principal" : "*",
"Action" : "secretsmanager:GetSecretValue",
"Resource" : "<<ARN OF Secret>>",
"Condition" : {
"StringNotLike" : {
"aws:PrincipalArn" : [
"<<ARN of IAM_role_that_need_to_access_the_secret>>" ]
}
}
} ]
}

aws:RequestTag on s3 bucket is not working (while assuming a role)

i have the following policy on an IAM role which i'm assuming into:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": "arn:aws:s3:::mybucket/${aws:RequestTag/personalid}/*"
}
]
}
When performing assume role, i'm passing the tag:
response = sts_client.assume_role(
RoleArn=arn,
RoleSessionName=role_session_name,
Tags=[
{
'Key': 'personalid',
'Value':'a'
},
])
but i get access denied when trying to read an object under folder 'a':
s3 = boto3.resource(
's3',
aws_access_key_id=response['Credentials']['AccessKeyId'],
aws_secret_access_key=response['Credentials']['SecretAccessKey'],
aws_session_token=response['Credentials']['SessionToken'],
region_name=client_main_region
)
obj = s3.Object('mybucket', f'a/file.txt')
print(obj.get()['Body'].read().decode('utf-8'))
I've replaced the policy with "principalTag", while adding a tag to the role, and it works - what am i doing wrong?
=====
Another thing i tried, is to tag the s3 object with that ID, and with the following policy:
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Condition": {
"StringEqualsIfExists": {
"aws:RequestTag/personalid": "${s3:ExistingObjectTag/personalid}"
}
},
"Resource": "arn:aws:s3:::mybucket/*"
}
Not working
If anyone ever looks for this - apparently the trust relationship should declare those tags - so they will be available:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123:role/lambda_role"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123:role/lambda_role"
},
"Action": "sts:TagSession",
"Condition": {
"StringLike": {
"aws:RequestTag/personalid": "*"
}
}
}
]
}
Then, i could use this tag as principal tag in the assumed role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::mybucket/${aws:PrincipalTag/personalid}/*"
}
]
}

How to give permissions to my uploaded aws lambda function?

I need to give permission for all logged users on my application.
This is my code:
this.amplifyService.auth().currentUserCredentials().then(credentials => {
const lambda = new Lambda({
credentials: this.amplifyService.auth().essentialCredentials(credentials)
});
lambda.invoke({
FunctionName: 'my-function',
}, res => {
console.log(res);
});
});
And this is the return:
authRole/CognitoIdentityCredentials is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-2:function:my-function
I already try to create a IAM role manually:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:us-east-2:XXXXXXXXX:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-east-2:XXXXX:log-group:/aws/lambda/my-function:*"
]
},
{
"Effect": "Allow",
"Action": [
"lambda:*"
],
"Resource": [
"arn:aws:lambda:us-east-2:XXXXXXXXX:function:my-function"
]
}
]
}
But doesn't work yet.

Add aws lambda permissions to aws elasticsearch policy

I added the following IP access restriction to my aws elasticsearch access policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:us-west-2:000000000000:domain/tst/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"XX.XX.XX.XX"
]
}
}
}
]
}
I have a lambda function and a kinesis firehouse reading and writing the elasticsearch index. How could I add lambda and kenesis firehouse permisions to my elasticsearch access policy?
Finally I solved as follows:
Adding the following policy to aws elasticsearch:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<account-id>:user/admin"
},
"Action": "es: *",
"Resource": "example-domain.us-east-1.es.amazonaws.com:<account-id>:domain/ *"
},
{
"Effect": "Allow",
"Principal": {
"AWS": " * "
},
"Action": "es:*",
"Resource": "example-domain.us-east-1.es.amazonaws.com:<account-id>:domain/ *",
"Condition": {
"IpAddress": {
"aws:SourceIp": "<my-ip>"
}
}
}
]
}
Adding at the IAM user with the security credentials the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "elasticsearchFullAccess",
"Effect": "Allow",
"Action": [
"es: *"
],
"Resource": [
"arn:aws:es:us-east-1:<account-id>:domain/ *"
]
}
]
}
Sign requests using this.
I solved this thanks to this question

Amazon S3 Policy for only PUT,Read and List

I'm trying to create a policy for only read/put/list my bucket and a dir into it.
I've write this policy:
{
"Version": "2014-05-19",
"Statement": [
{
"Effect": "Allow",
"Action": [ "s3:Put*", "s3:Get*" ],
"Resource": "arn:aws:s3:::<mybucket>/<mydirectoryinbucket>/*"
}
]
}
{
"Version": "2014-05-19",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Condition": { "StringLike": { "s3:prefix": "<mydirectoryinbucket>/*"} },
"Resource": "arn:aws:s3:::<mybucket>"
}
]
}
But I get error on the last line of the first policy...the error is only syntax error, and no additional informations.
Where I did wrong ?
You're at the very least missing the principal, which defines the entity that is allowed or denied access to a resource.
I took your policy, added the wildcard * to denote 'any' principal, and regenerated it with the IAM Policy Generator. Try this:
{
"Id": "Policy1432045314996",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicGetAndPutPolicy",
"Action": [
"s3:Get*",
"s3:Put*"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::<mybucket>/<mydirectoryinbucket>/*",
"Principal": "*"
},
{
"Sid": "PublicListPolicy",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::<mybucket>",
"Condition": {
"StringLike": {
"s3:prefix": "<mydirectoryinbucket>/*"
}
},
"Principal": "*"
}
]
}
Documentation:
Specifying a Principal in a Policy