So, I am new to Cognito and trying to link it with my Lambda Functions. I am trying to divide my API calls for different IAM roles. Here are the steps which I have already tried but the policy is not applied:
I created a User Pool and its App Client first, and divided the Pool into three Groups.
I created a Federated Identity with the User Pool Id and Client Id. For Role Selection I did
'Choose role from Token'.
I created a IAM Role with Identity ID, and attached this policy to it:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Deny",
"Action": "execute-api:*",
"Resource": "*"
}
]
}
I attached the IAM Role to the User Pool Group 1.
I created a Cognito Authorizer, and attached it to an API in API Gateway.
I created a User, and assigned it to Group 1. After logging in, I got an ID_Token whose JWT
decryption included the Role I had attached.
Finally, I made a Request from Postman with the token, and expected the Response to be
Forbidden as I had denied everything in the policy.
In the end, the Response I got was 200, and the access was not restricted.
APIGateway only checks with cognito if your token is valid or not. If you then use the token to generate temporary AWS credentials and use them to make any requests to AWS resources (including to APIGateway), then you will get the forbidden response for your requests.
Related
I am trying to upload an object to an S3 bucket using boto3 and a service account created by a user with readwrite permissions. The IAM policy for the user is:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
However, I am getting the following error:
boto3.exceptions.S3UploadFailedError: Failed to upload /tmp/tmpfnkhwptw/model/requirements.txt to ml-artifacts/1/02e5b8a81a834b6e83a3412745f4ff6a/artifacts/sklearn-model/requirements.txt: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied.
I've verified that the user is trying to upload the object to the correct bucket and prefix, and that the user has the correct permissions to write in the bucket -- this comes from a MLFlow example for a simple model using a wine dataset (can provide the code if wanted, but there's nothing special about it).
I am using MinIO as the object storage and the endpoint URL. The code works correctly if I use admin credentials, but not with user service account credentials.
What could be causing this error and how can I resolve it?
I'm afraid I didn't give the whole information on my question. I thought service accounts were always necessary (I'm inexperienced) and didn't say that I was using the service account credentials.
The answer is as simple as using the user credentials and not the service account (created by said user) credentials.
Another thing I have learned is that the service account didn't work because, for some reason, my MinIO version didn't give the same privileges as the user who created it to the account. When I opted for giving specific access privileges to the service account and pasted the "readwrite" JSON config into it, it worked.
By trying to get s3 object(of account1) from ec2 instance(of account2), the Sts session creation is failed with error:
"User arn:aws:sts::99*804963:assumed-role/i-9B6331541002f46-us-west is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::85*****15:role/MyS3DataReadRole
To provide access to fetch s3 object:
I've created permission in account2 with GetObject access to the s3 object(arn).
I've provided trust relationship for the role, where Principal.AWS = arn:aws:sts::99*804963:role/i-9B6331541002f46-us-west
The only suspicious point here is "assumed-role" instead of "role" in the user instance arn. AFAIK The user arn is calculated automatically by AWS SDK automatically, but I can't understand why "assumed-" prefix is added before the "role". I.e. in error message is mentioned: "arn:aws:sts::99804963:assumed-role/i-9B6331541002f46-us-west"
but in trust relationship I've provided correct arn, i.e. "arn:aws:sts::99804963:role/i-9B6331541002f46-us-west"
You also have to create the assume role policy and attach it to the EC2 instance role (99*804963) so that EC2 instance role can have permissions to assume the role (85*****15:role) which has read permissions for the S3 object.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::85*****15:role/MyS3DataReadRole"
}
]
}
Please update the account id in the above policy with actual one.
I have some set of users in cognito user pool under different groups . Example: 5 users in admin group, 20 users in supervisor group.I have created app client in cognito and enabled some Oauth2 scopes builtin and custom scopes.
Now i have API Gateway API's in which COGNITO AUTHORIZER is enabled for auth.These apis are working fine.
Problem faced:
With the above method i'm able to access my apis , but how to i control API access based on the user scope.
All users in the pool has all scopes enabled. The only things which will differentiate a user is the cognito:group , in api auth setting , I'm only able to set scope, in this case all users irrespective of group has all scopes, so they are getting authenticated. How to i control the flow based on type of users?
When you create an User group, you have an IAM role attached to it.
It will be on this that you can control access to your API by setting permission on execute api :
arn:aws:execute-api:{region}:{account}:{apiId}/{stage}/{method}/{ressource}
where all {parameter} can be wildcar * to match all.
You can find the IAM Role ARN of your user group on his description and so go in the IAM console and update this role permission
So your policy can be something like this :
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:eu-central-1:1564543246:badfg687e/*/*/petstore"
},
{
"Effect": "Deny",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:eu-central-1:1564543246:badfg687e/*/*/*"
}
]
}
By example, this permission allow users part of the group attached to this IAM role to execute all method on the ressource petstore of API badfg687e and deny all other access.
I'm creating an app that utilizes a feature similar to instagram -- users can upload images and view others'. They also need to be able to delete only their own.
I plan to store these images in S3. What's the safest way to allow users to upload, download, and delete their own? My current plan is to authenticate users through my own system, then exchange that login token for AWS Cognito credentials, which can upload and download to/from my S3 bucket.
Deleting I think will be more difficult. I imagine I will have clients send a request to a server that processes it, makes sure the requested deletion is allowed for that client, and then sends the request to S3 using admin credentials.
Is this a feasible way of managing all this, and how best can I disallow users from uploading random things to my bucket? I want them only to be able to upload images associated with their account and with my app, but presumably with the Cognito credentials they could upload anything.
Thanks, and let me know if I wasn't clear on anything.
When using Amazon Cognito, your mobile application users will assume an Identity and Access Management (IAM) role, which gives them permissions to access AWS resources.
A role could, for example, grant access to an Amazon S3 bucket to allow them to upload and download pictures. You can then limit their access to the S3 bucket such that they can only perform actions on objects within their own directory.
Here is an example policy that insert grants access to subdirectories based on their Cognito identity:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket"],
"Condition": {"StringLike": {"s3:prefix": ["${cognito-identity.amazonaws.com:sub}/*"]}}
},
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket/${cognito-identity.amazonaws.com:sub}/*"]
}
]
}
This way, you can allow the mobile app to directly interface with S3 for uploads, downloads and deletes, rather than having to request it through a back-end service. This will allow your app to scale without having to have as many servers (so it's cheaper, too!)
For more details, see:
Understanding Amazon Cognito Authentication Part 3: Roles and Policies
I'm trying to create a new bucket policy in the Amazon S3 console and get the error
Invalid principal in policy - "AWS" : "my_username"
The username I'm using in principal is my default bucket grantee.
My policy
{
"Id": "Policy14343243265",
"Statement": [
{
"Sid": "SSdgfgf432432432435",
"Action": [
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::my_bucket/*",
"Principal": {
"AWS": [
"my_username"
]
}
}
]
}
I don;t understand why I'm getting the error. What am I doing wrong?
As the error message says, your principal is incorrect. Check the S3 documentation on specifying Principals for how to fix it. As seen in the example policies, it needs to be something like arn:aws:iam::111122223333:root.
I was also getting the same error in the S3 Bucket policy generator. It turned out that one of the existing policies had a principal that had been deleted. The problem was not with the policy that was being added.
In this instance, to spot the policy that is bad you can look for a principal that does not have an account or a role in the ARN.
So, instead of looking like this:
"Principal": {
"AWS": "arn:aws:iam::123456789101:role/MyCoolRole"
}
It will look something like this:
"Principal": {
"AWS": "ABCDEFGHIJKLMNOP"
}
So instead of a proper ARN it will be an alphanumeric key like ABCDEFGHIJKLMNOP. In this case you will want to identify why the bad principal was there and most likely modify or delete it. Hopefully this will help someone as it was hard to track down for me and I didn't find any documentation to indicate this.
Better solution:
Create an IAM policy that gives access to the bucket
Assign it to a group
Put user into that group
Instead of saying "This bucket is allowed to be touched by this user", you can define "These are the people that can touch this".
It sounds silly right now, but wait till you add 42 more buckets and 60 users to the mix. Having a central spot to manage all resource access will save the day.
The value for Principal should be user arn which you can find in Summary section by clicking on your username in IAM.
It is because so that specific user can bind with the S3 Bucket Policy
In my case, it is arn:aws:iam::332490955950:user/sample ==> sample is the username
I was getting the same error message when I tried creating the bucket, bucket policy and principal (IAM user) inside the same CloudFormation stack. Although I could see that CF completed the IAM user creation before even starting the bucket policy creation, the stack deployment failed. Adding a DependsOn: MyIamUser to the BucketPolicy resource fixed it for me.
Why am I getting the error "Invalid principal in policy" when I try to update my Amazon S3 bucket policy?
Issue
I'm trying to add or edit the bucket policy of my Amazon Simple Storage Service (Amazon S3) bucket using the web console, awscli or terraform (etc). However, I'm getting the error message "Error: Invalid principal in policy." How can I fix this?
Resolution
You receive "Error: Invalid principal in policy" when the value of a Principal in your bucket policy is invalid. To fix this error, review the Principal elements in your bucket policy. Check that they're using one of these supported values:
The Amazon Resource Name (ARN) of an AWS Identity and Access Management (IAM) user or role --
Note: To find the ARN of an IAM user, run the [aws iam get-user][2] command. To find the ARN of an IAM role, run the [aws iam get-role][2] command or just go and check it from the IAM service in your account web console UI.
An AWS account ID
The string "*" to represent all users
Additionally, review the Principal elements in the policy and check that they're formatted correctly. If the Principal is one user, the element must be in this format:
"Principal": {
"AWS": "arn:aws:iam::AWS-account-ID:user/user-name1"
}
If the Principal is more than one user but not all users, the element must be in this format:
"Principal": {
"AWS": [
"arn:aws:iam::AWS-account-ID:user/user-name1",
"arn:aws:iam::AWS-account-ID:user/user-name2"
]
}
If the Principal is all users, the element must be in this format:
{
"Principal": "*"
}
If you find invalid Principal values, you must correct them so that you can save changes to your bucket policy.
Extra points!
AWS Policy Generator
Bucket Policy Examples
Ref-link: https://aws.amazon.com/premiumsupport/knowledge-center/s3-invalid-principal-in-policy-error/
I was facing the same issue when I've created a bash script to initiate my terraform s3 backend. After a few hours I've decided just to put sleep 5 after user creation and that made sense, you can notice it at the line 27 of my script
If you are getting the error Invalid principal in policy in S3 bucket policies, the following 3 steps are the way to resolve it.
1 Your bucket policy uses supported values for a Principal element
The Amazon Resource Name (ARN) of an IAM user or role
An AWS account ID
The string "*" to represent all users
2 The Principal value is formatted correctly
If the Principal is one user
"Principal": {
"AWS": "arn:aws:iam::111111111111:user/user-name1"
}
If the Principal is more than one user but not all users
"Principal": {
"AWS": [
"arn:aws:iam::111111111111:user/user-name1",
"arn:aws:iam::111111111111:user/user-name2"
]
}
If the Principal is all users
{
"Principal": "*"
}
3 The IAM user or role wasn't deleted
If your bucket policy uses IAM users or roles as Principals, then confirm that those IAM identities weren't deleted. When you edit and then try to save a bucket policy with a deleted IAM ARN, you get the "Invalid principal in policy" error.
Read more here.
FYI: If you are trying to give access to a bucket for a region that is not enabled it will give the same error.
From AWS Docs: If your S3 bucket is in an AWS Region that isn't enabled by default, confirm that the IAM principal's account has the AWS Region enabled. For more information, see Managing AWS Regions.
If you are trying to give Account_X_ID access to the my_bucket like below. You need to enable the region of my_bucket on Account_X_ID.
"Principal": {
"AWS": [
"arn:aws:iam::<Account_X_ID>:root"
]
}
"Resource": "arn:aws:s3:::my_bucket/*",
Hope this helps someone.