Based on the documentation, I understand how to create IoT things and also how to create authenticated users using AWS IoT. My question is geared towards how to effectively combine these services so that each user can access several of his or her devices securely.
Let's say Jane has just signed up for the platform and wants to connect her lightbulb device to her account. Let's also assume that her lightbulb device already has a certificate on it and a policy in IoT so that it can connect to the IoT platform and then publish and subscribe to a few topics. For the sake of simplicity, let's say that Jane can create this connection by simply making an API call named pairDevice which takes in a cognito identity (i.e. 59700b18-94c7-XXXX-857a-d820a68c0ec6) and a device serial number.
Basically I envision this function doing two things:
It will call "AttachPrincipalPolicy" that will link the policy associated with that lightbulb to the cognito user. Which I would assume at this point the cognito user would be able to publish and subscribe to topics for that particular lightbulb and only that lightbulb.
It would add a DynamoDB entry in the users account of the thing ARN so that way it can be easily referenced and queried later.
So if my understanding is correct I would have a policy like this for each of my devices in IoT (should they also publish and subscribe to topics with the the serial number too? I want to make sure that users cannot connect to devices they aren't allowed to obviously):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:Connect"
],
"Resource": [
"arn:aws:iot:us-west-1:123456789012:client/SerialNumber",
]
},
{
"Effect": "Allow",
"Action": [
"iot:Publish",
"iot:Subscribe",
"iot:Receive"
],
"Resource": [
"*"
]
}
]
}
And then I would simply attach this policy using AttachPrincipalPolicy to the cognito user? Do I need to have an explicit policy in Amazon Cognito identity pool for IoT Access, or is that linkage done specifically through AttachPrincipalPolicy?
In order to authenticate an Amazon Cognito identity to publish MQTT messages over HTTP, you must specify two policies. The first policy must be attached to an Amazon Cognito identity pool role. This first policy is most likely the managed policy AWSIoTDataAccess.
The second policy must be attached to an Amazon Cognito user using the AWS IoT AttachPrincipalPolicy API.
An example application demonstrating this is:
https://github.com/awslabs/aws-iot-chat-example
For explicit instructions, you can read:
https://github.com/awslabs/aws-iot-chat-example/blob/master/docs/authentication.md
Related
I'm new to AWS. I'm developing an application using Spring boot. I use AWS cognito for the sign in and sign up. I created a group called ROLE_ADMIN in cognito and connect with IAM role which was also created by me as ROLE_ADMIN_IAM.
I'm using AWS Api gateway (HTTP Apis, but similarly REST Apis) to communicate with Apis. Then integrated the Cognito jwt authorizer in Api gateway.
Everything working perfectly. The problem I'm facing now is, when a user sign in, I need to prevent few Apis based on his role which is in cognito groups. So I tried to attach policies to IAM role (ROLE_ADMIN_IAM already created), but it doesn't work.
This is what I attached to ROLE_ADMIN_IAM
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"apigateway:GET"
],
"Resource": [
"arn:aws:apigateway:ap-south-1::/apis/09bccr0"
]
}
]
}
I tried restrict every resources also. But doesn't work
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "*",
"Resource": "*"
}
]
}
I'm afraid whether the way I tried is wrong or correct? I've been working for days. But couldn't find any solution. Please anyone give me a solution. Thanks in advance.
Update 1.
Since this doesn't work, I created a Identity pool and attached user pool Id and client id with it. It automatically creates two Roles for authentication user and unauthentication user. Then I went to Api gateway and changed the authorizer to IAM. The documentation itself says when we use IAM as an authorizer we need to use Signature 4 version. (I switched to IAM form cognito jwt, because I don't find any documentation or article say I can go with cognito jwt when we use Identity pool to define roles).
In the react application, I use amplify. When I configure Identity pool, it provides temporary Accesskey and SecretKey after a successful login. I tried to use it with postman -> Authorization -> AWS Signature, it always gives {"message":"Forbidden"}
When you create a group in a Cognito user pool you need to attach proper IAM role to that group. IAM policy that allows actual API calls should look like that:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": [
"arn:aws:execute-api:us-east-1:*:a123456789/test/POST/mydemoresource/*"
]
}
]
}
You just need to replace demo string with your API Gateway ARN, method and endpoint. Pay attention to the "execute-api:Invoke" action.
Permission "apigateway:GET" does not allow you to call an API but to get service information about API. "apigateway:*" permissions allow you to make management AWS API call not actual API call.
For more information please check these articles:
Management calls
Execution calls
I want to give some AWS account ids access to call the api gateway that is in my account. What is the best way to do this?
I think there is a way to add resource policy that gives that AWS account access. Is that a good way to do that? I am talking about a production kind of service?
Also, does all the resouces of AWS account will get access to API gateway?
For each API Gateway endpoint we can change the Authorization option from None to AWS_IAM:
Then we can configure access to the API from the Resource Policy section of the API Gateway. From the Resource Policy page, click on the "AWS Account Whitelist" button to get a policy template, excerpted below:
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::{{otherAWSAccountID}}:root",
"arn:aws:iam::{{otherAWSAccountID}}:user/{{otherAWSUserName}}",
"arn:aws:iam::{{otherAWSAccountID}}:role/{{otherAWSRoleName}}"
]
},
"Action": "execute-api:Invoke",
"Resource": [
"execute-api:/{{stageNameOrWildcard*}}/{{httpVerbOrWildcard*}}/{{resourcePathOrWildcard*}}"
]
}
As an alternative (or in addition) to IAM authorization, we can control usage with API Keys, which enables the ability to rate limit (throttle) API calls and to set quotas.
More info:
https://aws.amazon.com/blogs/compute/control-access-to-your-apis-using-amazon-api-gateway-resource-policies/
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html
With the recent release of API Gateway Cognito Custom Authorizers, I'm attempting to use Cognito, API Gateway and S3 together for authenticated access control without Lambdas.
Authorizing with API Gateway works as it should (with Trust Relationships for the API Gateway execution role set correctly) but I can't seem to get the resource policy to capture the Cognito User ID Sub variable for fine grain access control to S3 resources based on User ID.
Here's the current flow I'm trying to accomplish:
Authenticate with Cognito and get valid token
Send token to API Gateway to gain access to S3 bucket (through AWS Service integration type)
Fine grain access to only User ID's directory
Return S3 object (based on API endpoint)
Here's my current resource policy for the API Gateway execution role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cognito-idp:*",
"cognito-sync:*",
"cognito-identity:*"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:Get*",
],
"Resource": [
"arn:aws:s3:::mybucket/${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}
Everything works as it should but this IAM variable (in the policy attached to the API Gateway execution role) doesn't seem to be right.
I came across this StackOverflow article and tried using both formats us-east-1:xxxx-xxxx-xxxx-xxxx and xxxx-xxxx-xxxx-xxxx but both didn't seem to work. I'm using the sub attribute found in the Cognito User Pool User info. If I hard code the folder in S3 to the Cognito User ID Sub it works just fine.
How do I get the Cognito variable to work in the API Gateway's execution role policy?
Here are a couple other articles I found related to the question on the AWS forums:
Cognito IAM variables not working for assumed-role policies
What cognito information can we use as IAM Variables?
That's not the sub that the variable expects. There is no way to use cognito user pool attributes in policy. The sub that you want is the cognito identity id which is the id of the user in the cognito Identity (federated identity pool). You can get this ID by using the get id method. I would suggest you store this ID as a custom attribute variable in your cognito user pool so you don't have to keep making the call.
You can read more about this identity id here.
I have problem with AWS API Gateway.
I create my own API and now i want that other users which are in the same group as me and have same roles to access this API via AWS Management console.
The problem is that other users can't see the API which i created (same problem with Lambda functions and DynamoDB which is also visible only for me, not for other users in group).
A simple but less secure solution is to assign the AmazonAPIGatewayAdministrator policy to the IAM Users, Groups, or Roles you want to be able to use the API Gateway. This will give them access to all APIs.
If you want to restrict access to a specific API or set of APIs you can create a custom IAM Policy for that API. You will then assign that Policy to the Roles and Groups you want to have access to the API. To create the policy, you will need the ID of the API. It's a long and convoluted process, but it works. Here are the steps:
Determine the ID of the API you want to provide access to by selecting the API Gateway service and clicking on the API. The URL in the browser will look like the following:
https://console.aws.amazon.com/apigateway/home?region=us-east-1#/apis/API_ID/resources/RESOURCE_ID
Copy the API_ID to your clipboard for use later.
Alternatively you can use the AWS CLI command: aws apigateway get-rest-apis and copy the ID from the result.
Create a new IAM Policy like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"apigateway:GET"
],
"Resource": [
"arn:aws:apigateway:*::/clientcertificates",
"arn:aws:apigateway:*::/restapis",
"arn:aws:apigateway:*::/restapis/*"
]
},
{
"Effect": "Allow",
"Action": [
"apigateway:*"
],
"Resource": [
"arn:aws:apigateway:us-east-1::/restapis/API_ID/*"
]
}
]
}
Attach the policy to the Users/Groups/Roles you want to have access. The first Effect allows the user to see all of the APIs but not modify them. You may want to remove this if you want to be more restrictive.
Amazon has a decent write-up of the IAM Policies for API Gateway here: http://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html
It is possible to use IAM credentials to allow to send mails from specific sender?
I mean, for example, I have two different domains and senders configurated into SES: info#example1.com and info#example2.com. Is there any way to limit a IAM user and its credentials to just send mails from info#example1.com?
I tried to specify a condition in a IAM policy defined into to the user permissions. However I could not find a condition that can solve my problem.
Also I tried to solve the issue using STMP credentials, but I have the same problem. Any ideas?
This may have changed since the original answer. You can now do something like:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["ses:SendEmail"],
"Resource":"*",
"Condition": {
"StringEquals": {
"ses:FromAddress": "here#somewhere.com"
}
}
}
]
}
The AWS docs now reflect this: http://docs.aws.amazon.com/ses/latest/DeveloperGuide/control-user-access.html
It is possible to use IAM credentials to allow to send mails from
specific sender?
NO
See: http://docs.aws.amazon.com/ses/latest/DeveloperGuide/control-user-access.html
You can't specify a particular Amazon SES resource in an IAM policy.
You only control access to Amazon SES actions. Therefore, Amazon SES
does not use Amazon Resource Names (ARNs), which identify resources in
a policy. When you write a policy to control access to Amazon SES
actions, you use * as the resource.
(emphasis mine)
You can control what API calls IAM accounts can make(like ses:SendEmail), but you can not restrict what parameters they can use with those API calls(like the source email address)