AWS Cognito User Cannot Invoke Lambda (403 Not Authorized) - amazon-web-services

I’ve created a set of AWS Lambdas using the Serverless framework, and a React app which calls these. A user pool and an identity pool have been setup in AWS Cognito, and a table in DynamoDB. (I've followed the tutorial on serverless-stack.com). It's a simple notes app.
The client app is deployed to: https://dev.cakebook.co
The API is deployed: https://api.cakebook.co/dev/orders
However, after I log in using this Cognito user:
admin#example.com
Passw0rd!
I get a 403 response for the GET of the orders:
message: “User: arn:aws:sts::********8766:assumed-role/cakebook-api-dev-CognitoAuthRole-1DTRT5XGEGRXW/CognitoIdentityCredentials is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-east-2:********8766:sss6l7svxc/dev/GET/orders”
I'm new to all this, but it looks like my Cognito user does not have permission to call the Lambda (or API gateway?). Is that the issue? If so, how do I give the users permission to call the Lambdas?
UPDATE, requested JSON
Execution Role:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogStream"
],
"Resource": [
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-create:*",
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-get:*",
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-list:*",
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-update:*",
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-delete:*"
],
"Effect": "Allow"
},
{
"Action": [
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-create:*:*",
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-get:*:*",
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-list:*:*",
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-update:*:*",
"arn:aws:logs:us-east-2:********8766:log-group:/aws/lambda/cakebook-api-dev-delete:*:*"
],
"Effect": "Allow"
},
{
"Action": [
"dynamodb:DescribeTable",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem"
],
"Resource": [
"arn:aws:dynamodb:us-east-2:********8766:table/orders"
],
"Effect": "Allow"
},
{
"Sid": "1",
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-2:********8766:function:cakebook-api-dev-list",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:cognito-identity:us-east-2:********8766:identitypool/us-east-2:d9e4e505-c64a-4836-8e56-3af843dbe453"
}
}
}
]
}
Function Policy:
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "cakebook-api-dev-ListLambdaPermissionApiGateway-U7OCBI3JM44G",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-2:********8766:function:cakebook-api-dev-list",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:us-east-2:********8766:w5o4vxx4f0/*/*"
}
}
},
{
"Sid": "lambda-da48f6d0-6d3c-4bbf-a761-ca3510f79624",
"Effect": "Allow",
"Principal": {
"Service": "cognito-sync.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-2:********8766:function:cakebook-api-dev-list",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:cognito-identity:us-east-2:********8766:identitypool/us-east-2:d9e4e505-c64a-4836-8e56-3af843dbe453"
}
}
}
]
}

You need to update Lambda permission to allow invoking by Cognito user pool.
Option A - update permission in JSON format
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "lambda-something",
"Effect": "Allow",
"Principal": {
"Service": "cognito-sync.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:eu-west-1:__accountId__:__function_name__",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:cognito-identity:eu-west-1:__accountId__:identitypool/eu-west-1:....."
}
}
}
]
}
Option B - in console
Go to Lambda Configuration page
Add trigger Cognito Sync Trigger
During saving it will offer to configure Lambda permission automatically - agree

Related

Accessing an Encrypted SNS Topic with Access policy

I'm trying to get CloudWatch to send to my SNS topic. The topic is encrypted. However I get this error
Received error: "CloudWatch Alarms does not have authorization to access the SNS topic encryption key."
I have added KMS permissions to the access policy associated with the SNS topic but I get this error when I try to save the policy
Error code: InvalidParameter - Error message: An error occurred while setting the attribute access policy. Invalid parameter: Policy statement action out of service scope!
Is there something in the policy I am misisng?
{
"Version": "2012-10-17",
"Id": "SNS",
"Statement": [
{
"Sid": "SNSPolicy",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"SNS:GetTopicAttributes",
"SNS:SetTopicAttributes",
"SNS:AddPermission",
"SNS:RemovePermission",
"SNS:DeleteTopic",
"SNS:Subscribe",
"SNS:ListSubscriptionsByTopic",
"SNS:Publish"
],
"Resource": "arn:aws:sns:*:my-account-name:my-topic-name"
},
{
"Sid": "CloudWatch",
"Effect": "Allow",
"Principal": {
"Service": "cloudwatch.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": [
"arn:aws:kms:*:my-account-name:key/*"
],
"Condition": {
"StringEquals": {
"kms:RequestAlias": "alias/my-alias-name"
}
}
}
]
}
Cloudwatch is not having necessary permission to access the KMS key which is being used by the SNS topic.
Below SNS topic access policy will give access to the Amazon cloudwatch events.
{
"Version": "2012-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__default_statement_ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"SNS:GetTopicAttributes",
"SNS:SetTopicAttributes",
"SNS:AddPermission",
"SNS:RemovePermission",
"SNS:DeleteTopic",
"SNS:Subscribe",
"SNS:ListSubscriptionsByTopic",
"SNS:Publish"
],
"Resource": "arn:aws:sns:<region>:<account>:<snstopic>",
"Condition": {
"StringEquals": {
"AWS:SourceOwner": "<account>"
}
}
},
{
"Sid": "AWSEvents_test_Id10633056916634",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sns:Publish",
"Resource": "arn:aws:sns:<region>:<account>:<snstopic>"
}
]
}
Below customer managed KMS key policy, it will give access to Amazon cloudwatch event source.
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<account>:<iamuser>",
"Service": "cloudwatch.amazonaws.com"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
Several AWS services publish events to Amazon SNS topics. To know more, Kindly refer here

AWS IAM policy for Event-Bridge to SQS with deny

I want to restrict my sqs to accept only from event-bridge rule, below IAM rule looks correct with deny in place, but sqs not receiving message with this, any input appreciated.
{ "Id": "Policy", "Version": "2012-10-17", "Statement": [
{
"Sid": "sid",
"Action": [
"sqs:SendMessage"
],
"Effect": "Deny",
"Resource": "arn:aws:sqs:us-east-1:***:sri-test-queue-3",
"Condition": {
"ArnNotEquals": {
"aws:SourceArn": "arn:aws:events:us-east-1:***:rule/sri-test-bus/sri-test-sqs-rule"
}
},
"Principal": "*"
} ] }
The one generated by Event-bridge to allow sqs access looks like this
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "AWSEvents_sri-test-sqs-rule_Id12",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:***:sri-test-queue-3",
"Condition": {
"ArnEquals": {
"aws:SourceArn": "arn:aws:events:us-east-1:***:rule/sri-test-bus/sri-test-sqs-rule"
}
}
}
]
}
Use the bottom policy. SQS policy denies by default, so you do not need to worry about other resources posting messages to SQS. The policy would allow only arn:aws:events:us-east-1:***:rule/sri-test-bus/sri-test-sqs-rule to send the messages.
The problem with the policy statement you wrote was that you did not have an "Allow" statement, so SQS is denying SendMessage actions from every source.
We just had to put some combination of principalTypes to achieve this, below one worked finally
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ownerstatement",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:xxxx:sri-test-queue-3"
},
{
"Sid": "DenyAllExceptBus",
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:xxxx:sri-test-queue-3",
"Condition": {
"ArnNotEquals": {
"aws:SourceArn": [
"arn:aws:events:us-east-1:xxxx:rule/sri-test-bus/sri-test-sqs-rule"
]
}
}
}
]
}

IAM user is not allowed to perform

I created an IAM user at AWS that should be allowed to perform a couple of S3 bucket actions, but only when MFA is enabled. Therefore I added a policy according to the AWS documentation with the following content:
{
"Statement": [
{
"Action": [
"iam:ListVirtualMFADevices",
"iam:ListUsers"
],
"Effect": "Allow",
"Resource": "*",
"Sid": "AllowListActions"
},
{
"Action": "iam:ListMFADevices",
"Effect": "Allow",
"Resource": [
"arn:aws:iam::*:user/${aws:username}",
"arn:aws:iam::*:mfa/*"
],
"Sid": "AllowIndividualUserToListOnlyTheirOwnMFA"
},
{
"Action": [
"iam:ResyncMFADevice",
"iam:EnableMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:CreateVirtualMFADevice"
],
"Effect": "Allow",
"Resource": [
"arn:aws:iam::*:user/${aws:username}",
"arn:aws:iam::*:mfa/${aws:username}"
],
"Sid": "AllowIndividualUserToManageTheirOwnMFA"
},
{
"Action": "iam:DeactivateMFADevice",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
},
"Effect": "Allow",
"Resource": [
"arn:aws:iam::*:user/${aws:username}",
"arn:aws:iam::*:mfa/${aws:username}"
],
"Sid": "AllowIndividualUserToDeactivateOnlyTheirOwnMFAOnlyWhenUsingMFA"
},
{
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
},
"Effect": "Deny",
"NotAction": [
"iam:ResyncMFADevice",
"iam:ListVirtualMFADevices",
"iam:ListUsers",
"iam:ListMFADevices",
"iam:EnableMFADevice",
"iam:CreateVirtualMFADevice"
],
"Resource": "*",
"Sid": "BlockMostAccessUnlessSignedInWithMFA"
}
],
"Version": "2012-10-17"
}
This is simply the default policy, recommended by AWS. Nevertheless, when the particular user logs in and tries to add a virtual MFA, he sees the following error message:
User: arn:aws:iam::1234567890:user/users/user#example.com is not authorized to perform: iam:ListMFADevices on resource: user user#example.com because no identity-based policy allows the iam:ListMFADevices action
Do I miss something in the setup of the permissions?
I too had a similar error recently, the AWS docs are awful related to this. Once the MFA device it setup, everything works fine, but getting it set up, I couldn't find the permission to do this either.
One workaround, is to set this up for the user, send them a pic of the QR code, so they can complete the setup on their device.
It's not a perfect situation as this requires trust in a human to do this initial step.
If anyone has the actual answer for how to do this, I too would be interested in hearing as the AWS docs and content online I couldn't find the policy that needs to be applied for this to work without this manual intervention.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowManageOwnVirtualMFADevice",
"Effect": "Allow",
"Action": [
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice"
],
"Resource": "arn:aws:iam:::mfa/${aws:username}"
},
{
"Sid": "AllowManageOwnUserMFA",
"Effect": "Allow",
"Action": [
"iam:DeactivateMFADevice",
"iam:EnableMFADevice",
"iam:ListMFADevices",
"iam:ResyncMFADevice"
],
"Resource": "arn:aws:iam:::user/${aws:username}"
}
]
}

Access S3 bucket after logging on Cognito from other account

I have two AWS accounts. The account A has a Cognito identity pool configured with roles for Authenticated and Unauthenticated.
The trusted relationship policy for Authenticated role looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "<identity_pool_id>"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
There is also a policy for Authenticated role that looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::users-pictures/public/*",
"arn:aws:s3:::users-pictures/protected/${cognito-identity.amazonaws.com:sub}/*",
"arn:aws:s3:::users-pictures/private/${cognito-identity.amazonaws.com:sub}/*"
],
"Effect": "Allow"
},
{
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::users-pictures/uploads/*"
],
"Effect": "Allow"
},
{
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::users-pictures/protected/*"
],
"Effect": "Allow"
},
{
"Condition": {
"StringLike": {
"s3:prefix": [
"public/",
"public/*",
"protected/",
"protected/*",
"private/${cognito-identity.amazonaws.com:sub}/",
"private/${cognito-identity.amazonaws.com:sub}/*"
]
}
},
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::users-pictures"
],
"Effect": "Allow"
}
]
}
On account B I have an application that must authenticate on Cognito from account A, but needs to access a bucket on account B.
This application uses Storage from Amplify.
The bucket structure must be something like this:
users-pictures/private/${cognito-identity.amazonaws.com:sub}/*
When Amplify authenticates on account A and tries to access this bucket on account B, it gets an Access Denied (403).
Probably it's missing some configuration on account A and/or account B.
Could you help me, please?

Add multiple domain access policy to AWS Elasticsearch Service (Static IP and Lambda ARN)

After setting up AWS Elasticsearch, I installed Logstash and Kibana proxy on a static IP server, and added this domain access policy on ES and it's working fine:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:ap-southeast-1:323137313233:domain/sg-es-logs/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"192.192.192.192"
]
}
}
}
]
}
Now I need to allow Lambda function to execute es:ESHttpDelete action on AWS ES, so I created the function with the existing role service-role/Elasticsearch then copied the relevent ARN from IAM Managment console to add it to AWS ES access policy, to come up with this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam:: 323137313233:role/service-role/Elasticsearch"
]
},
"Action": [
"es:*"
],
"Resource": "arn:aws:es:ap-southeast-1:323137313233:domain/sg-es-logs/*"
}
]
}
The problem is on ES I should either choose domain access policy for Static IP or ARN but not both. When I tried to merge them manually not by using the console it didn't work. I checked AWS documentation but they didn't mention if is that possible or not.
You can add multiple policy statements inside the Statement array in the JSON format of policy. So, your final policy would be something like:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:ap-southeast-1:323137313233:domain/sg-es-logs/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"192.192.192.192"
]
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam:: 323137313233:role/service-role/Elasticsearch"
]
},
"Action": [
"es:*"
],
"Resource": "arn:aws:es:ap-southeast-1:323137313233:domain/sg-es-logs/*"
}
]
}