AWS Serverless DynamoDB Row Level Authorization With Cognito and Lambda Functions - amazon-web-services

Alright, so I currently have almost everything working by following this guide here and pieces of several others.
https://aws.amazon.com/blogs/mobile/building-fine-grained-authorization-using-amazon-cognito-user-pools-groups/
However, instead of giving users direct access to the DynamoDB, I am running it through an API Gateway and then a Lambda Function using an Authorization header and the Cognito session id.
I have that part working.
In my lambda function I call the update function
const data = await documentClient.update(params).promise();
I have AWSLambdaBasicExecutionRole policy and the following policy added to my lambda function role to allow the row level access for Update
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"dynamodb:UpdateItem"
],
"Resource": [
"arn:aws:dynamodb:us-east-2:mydynamodbid:table/userdata"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "${cognito-identity.amazonaws.com:sub}"
}
}
}
]
It works fine with the AmazonDynamoDBFullAccess but I am not sure that is accomplishing what I am looking for as I think it just completely bypasses the condition.
I am getting the following error though
"User: arn:aws:sts::**********:assumed-role/db-crud/update-user-info-by-id is not
authorized to perform: dynamodb:UpdateItem on resource: arn:aws:dynamodb:us-east-
2:************:table/userdata"
Has anyone encountered anything like this or see where I am possibly going wrong?
This is the flow I am going for, and this is related to step 6

Related

New AWS Lambda URLs - has anyone got the 'secure' version with the AWS_IAM working?

I have a simple function that returns an item of text.
When I set auth to NONE it works fine.
When I set auth to AWS_IAM and create the resource based policy within the permissions section of AWS Lambda I set the following:
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "sid8",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxx:user/xxxxxxxxxx"
},
"Action": "lambda:InvokeFunctionUrl",
"Resource": "arn:aws:lambda:eu-west-1:xxxxxxxxx:function:simpleFunction",
"Condition": {
"StringEquals": {
"lambda:FunctionUrlAuthType": "AWS_IAM"
}
}
}
]
}
On this I get a forbidden error.
Every demo / example on the internet uses NONE for auth.
I have also tried adding the lambda:InvokeFunctionUrl to the IAM policy of the user for the specified resource but still getting a forbidden error.
Am I missing something or does this aspect of the new function not work?
The problem is that when you are using IAM_AUTH you're required to sign your requests with SigV4. Essentially, this is identical to using API Gateway with IAM_AUTH type.
There are multiple ways of signing requests you can even use botocore functionality to do so. The easiest would be to use awscurl or postman, also check this doco that confirms this requirement https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html

AWS/Cognito/IAM Error with Unauth role

This message was originally posted on the AWS Developer Forums, but it seems like the AWS crowd is on SO, so I'm duplicating it here.
Hi there, I'm an absolute AWS beginner so I'll try to be as clear as possible.
I'm trying to use the JS API to allow any user on my site to upload videos to S3 (this works well) and then convert the uploaded files to other formats (with Elastic Transcoder).
I've set up:
an input (not public) and an output (public) buckets on S3. The input receives the user-submitted videos, that part works :)
an Elastic Transcoder pipeline (video-converter-test-pipeline-01)
a federated identity on Cognito (video_converter_test_02)
matching Auth and Unauth roles on IAM (Cognito_video_converter_test_02Auth_Role and Cognito_video_converter_test_02Unauth_Role)
The pipeline has the following permission summary: "The following IAM roles have been granted access to this pipeline: arn:aws:iam::529773801731:role/Elastic_Transcoder_Default_Role"
Cognito_video_converter_test_02Unauth_Role has two attached policies:
oneClick_Cognito_video_converter_test_02Unauth_Role_1522923667877
video-converter-policy, that I made myself.
Here's its JSON representation:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "elastictranscoder:CreateJob",
"Resource": [
"arn:aws:elastictranscoder:*:*:pipeline/*",
"arn:aws:elastictranscoder:*:*:preset/*"
]
}
]
}
Here's how I try to create a transcoding job using the JS API:
function createJob(uploadedFileKey) {
console.log("Create job", uploadedFileKey);
var params = {
PipelineId: PipelineId,
Input: {
Key: uploadedFileKey
},
Output: {
PresetId: PresetId
}
};
elastictranscoder.createJob(params, function (err, data) {
if (err) console.error(err, err.stack); // an error occurred
else console.log(data); // successful response
});
}
When executing it, I get the following error:
Error: User: arn:aws:sts::529773801731:assumed-role/Cognito_video_converter_test_02Unauth_Role/CognitoIdentityCredentials is not authorized to perform: elastictranscoder:CreateJob on resource: arn:aws:elastictranscoder:eu-west-1:529773801731:pipeline/1522763370759-mmowmr
I tried using IAM Policy Simulator to understand what was wrong, but when doing so with the same parameters, I get "allowed"...
I'm sure I'm doing something wrong here, but can't understand what. I've tried many things but nothing worked. Any help would be appreciated :)
Thanks in advance, bye!
I contacted AWS Developer Support and the solution seems to be to have these in the IAM Policy:
{
"Sid": "VisualEditor3",
"Effect": "Allow",
"Action": "cognito-sync:*",
"Resource": "*"
},
{
"Sid": "VisualEditor3",
"Effect": "Allow",
"Action": "mobileanalytics:PutEvents",
"Resource": "*"
}

cognito fine grained access control and API gateway

In api gateway, I have the following resource ARN:
arn:aws:execute-api:us-east-2:XXXXXXXXXXXXX:syx381ecq9/*/GET/members/*
which provides a link to get a list of members based on a class_id - /members/{id}
A user that is in a class can only see the list of members that belong into that class.
I have specified cognito user pool with the following IAM policy (assume that class1 is class_id)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cognito-identity:*",
"mobileanalytics:PutEvents",
"cognito-sync:*",
"lambda:*",
"execute-api:*"
],
"Resource": [
"arn:aws:execute-api:us-east-2:XXXXXXXXXXXXX:syx381ecq9/*/GET/members/class1"
]
}
]
}
however, when used the link GET /members/class1, I get the following message:
Execution failed due to configuration error: API Gateway could not determine the callers credentials
I checked in cloudwatch, no log from lambda, therefore I think lambda was not executed.
I continued trying with class2. This time the following message was shown:
User:arn:aws:sts::XXXXXXXXXXXX:assumed-role/Cognito-sample_client1/CognitoIdentityCredentials is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-east-2:********8469:syx381ecq9/sample/GET/inspectors/client2
I have checked in policy stimulate and everything worked fine with message Allowed
I have no idea why I could not call lambda? how can I fix this problem?
Thanks
OK, I found the answer. The above policy only allows calling lambda function for
arn:aws:execute-api:us-east-2:XXXXXXXXXXXXX:syx381ecq9/*/GET/members/class1
therefore, when cognito credential has passed, api will try to call lambda but unfortunately, the policy restricts that. In order to get through it, we need to separate it into another statement like the following:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cognito-identity:*",
"mobileanalytics:PutEvents",
"cognito-sync:*",
"execute-api:*"
],
"Resource": [
"arn:aws:execute-api:us-east-2:XXXXXXXXXXXXX:syx381ecq9/*/GET/members/class1"
]
},
{
"Effect": "Allow",
"Action": [
"lambda:*"
],
"Resource": [
"*"
]
}
]
}
we can customized specific lambda's arn if required

AWS IAM SSM - Restrict Documents that Instances can run

Is there a way to restrict the IAM policy for an EC2 instance s.t. it can only run a short list of Documents - I tried restricting access to ssm:GetDocument like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetDocument"
],
"Resource": [
"arn:aws:ssm:ap-southeast-2:*:document/MyCommand"
]
}
]}
But I can run any command on the instance still including the AWS-RunPowershellScript document.
This link shows how users can be restricted with respect to ssm:sendCommand:
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/delegate-commands.html
I have not found a way to restrict SendCommand based on document. If a user does not have access, you get an error like this:
User: arn:aws:iam::123456789012:user/username is not authorized to perform: ssm:SendCommand on resource: arn:aws:ec2:us-east-1:123456789012:instance/i-01234567890abcdef
This indicates that the Resource in SendCommand can be limited based on instance ids. It would be nice if one of the Conditions was a Document ARN, but so far I haven't found any way to do it (it's not a condition in the policy generator wizard).
Update: I posted this question on the AWS forums, hopefully I'll get a response: https://forums.aws.amazon.com/thread.jspa?threadID=249039
Update 2: I got a response and the solution is that to accomplish this you must use Resource to specify both what instances you allow commands to be run on, and what document the user is allowed to run. For example, this is what I ended up with:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:SendCommand"
],
"Resource": [
"arn:aws:ec2:*:123456789012:instance/*",
"arn:aws:ssm:*:123456789012:document/RestartServices"
]
}
]
}

Aws S3 Only PutObject Policy

i'm trying to setup a Only PutObject policy to by bucket as following:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt####",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl"
],
"Resource": [
"arn:aws:s3:::my-bucket/*"
]
}
]
}
However when i try to upload a file thought AWS SDK I receive a 403 response from AWS.
I'm absolutely sure to use the correct access key of the IAM user that has this policy attached to it.
Anyone knows why AWS3 complain with this policy when it shouldn't?
Edit:
After hours of trials, I came across a weird behaviour which i would like to be explained.
If I add s3:ListBucket to the above policy it just works fine. Without it, it will return a 403. Why amazon force me to put ListBucket action when i don't want to have it?
Thanks
Best way to troubleshoot this is to give your policy following action and resources:
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
This will confirm you're using correct access key. If it goes through, you're most likely using unauthorized actions (e.g. s3:ListBucket). You can use CloudTrail to find which unauthorized actions are being called.