AWS IoT Policy overly permissive - amazon-web-services

I am trying to make an AWS IoT Policy for a Cognito Identity to be able to communicate with a AWS IoT Thing. However, the policy is overly permissive according to the AWS IoT Audit check: "Policy allows broad access to IoT data plane actions: [iot:Subscribe, iot:Connect, iot:Publish]." How can I fix this?
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:us-east-1:<aws account id>:client/${iot:ClientId}"
},
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:us-east-1:<aws account id>:topic/$aws/things/*/shadow/get"
},
{
"Effect": "Allow",
"Action": [
"iot:Subscribe"
],
"Resource": [
"arn:aws:iot:us-east-1:<aws account id>:topicfilter/$aws/events/presence/connected/*",
"arn:aws:iot:us-east-1:<aws account id>:topicfilter/$aws/events/presence/disconnected/*",
"arn:aws:iot:us-east-1:<aws account id>:topicfilter/$aws/things/*/shadow/update/accepted",
"arn:aws:iot:us-east-1:<aws account id>:topicfilter/$aws/things/*/shadow/get/accepted"
]
},
{
"Effect": "Allow",
"Action": [
"iot:Receive"
],
"Resource": "arn:aws:iot:us-east-1:<aws account id>:topic/$aws/things/*"
}
]
}

This means that you are trying an overexposed policy , since you have not mentioned the exact usecase i suppose that this policy is the least privileged policy i.e. the use case does not allow your policy to be more restrictive if that is not the case please restrict your policy to something like :
arn:aws:iot:region:account-id:client/*
to
arn:aws:iot:region:account-id:client/${iot:ClientId}
where iot:ClientId is a policy variable and refers to the clientId of the mqtt connection
Also please refer
https://docs.aws.amazon.com/iot/latest/developerguide/audit-chk-iot-policy-permissive.html

Related

S3 bucket policy to deny all except a particular AWS service role and IAM role

Can you write an s3 bucket policy that will deny access to all principals except a particular IAM role and AWS service role (e.g. billingreports.amazonaws.com).
I have tried using 'Deny' with 'NotPrincipal', but none of the below examples work as I don't think the ability to have multiple types of principals is supported by AWS?
This allows you to save the policy but locks out the bucket (warning: only root user can then update policy to unlock)
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::<account_id>:root",
"arn:aws:iam::<account_id>:role/specialBillingRole"
],
"Service": "billingreports.amazonaws.com"
}
Therefore I am trying to use conditions but can't find the right combinations that will work. Here is an example policy.
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "billingreports.amazonaws.com"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Sid": "",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket/*",
"arn:aws:s3:::my-bucket"
],
"Condition": {
"StringNotLike": {
"aws:PrincipalArn": [
"arn:aws:iam::<account_id>:role/specialBillingRole",
"billingreports.amazonaws.com",
"<account_id>"
]
}
}
}
]
}
UPDATED the question as per some comment suggestions.
2nd UPDATE Also tried the below, which still gives access to all roles/users in the account (can't use wildcards in the Principal).
{
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::<account_id>:root"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket/*",
"arn:aws:s3:::my-bucket"
],
"Condition": {
"ArnNotEquals": {
"aws:PrincipalArn": [
"arn:aws:iam::<account_id>:role/specialBillingRole",
"<account_id>"
]
}
}
}
You can certainly create a bucket policy that grants access only to a service role and an IAM role, but to be clear, a service role will still begin with "arn:aws:iam:::role...".
Are you instead trying to create a bucket policy that grants access both to a particular service and a service role? I'm asking because if you have a role created with billingreports.amazonaws.com as its trusted entity, and if that role is what's intended to access the bucket, then you do not need to list the service separately in your bucket policy (if the scenario is as I imagine).
Please do note, also, that you can indeed use wildcards with the principal, combined with a condition - I do so all the time (see my example policy below). When I want to restrict bucket access to a specific role, I simply include an Allow statement with a Principal of just the role I want to allow, and then a Deny statement with a Principal of "AWS": "*", followed by a condition, like so:
{
"Version": "2008-10-17",
"Id": "PolicyScopedToSecurity",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[accountID]:role/[roleName]",
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::[bucketName]",
"arn:aws:s3:::[bucketName]/*"
]
},
{
"Effect": "Deny",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::[bucketName]",
"arn:aws:s3:::[bucketName]/*"
],
"Condition": {
"StringNotLike": {
"aws:PrincipalArn": [
"arn:aws:iam::[accountID]:role/[roleName]",
"[accountID]"
]
}
}
}
]
}
If you truly need the service itself to access the bucket, the solution will be slightly different. My response assumes the service role needs access.

Cognito + IoT Integration - How to restrict a client so that it can subscribe to MQTT topic with name as Cognito user id only?

I am looking for a way to authenticate Cognito users to AWS IoT service so that a user can subscribe to an MQTT topic name as only user id (of identity pool of cognito). I do know that using a 2 step process it can be achieved.
What I don't know is a specific policy which we need to attach it to Cognito identity (a.k.a user), the policy must restrict a user to subscribe to his/her user id as MQTT topic. It implies the App can't subscribe to any other unintended topics.
Moreover, the policy needs to be dynamic (maybe using ${cognito-identity.amazonaws.com:sub} and conditions) to simplify development
It's worth noting that a user can login to multiple mobile app instances (Android and iOS) parallelly and if a user is logged in to both Android and iOS than both App instance should be able to subscribe the same topic (because user id will remain same for the same user).
Finally, I've solved. Sharing solution if it can help others. The steps are as follows:
We need to attach IAM policy to authenticated users' Cognito Role. The attached policy must ALLOW operations–iot:Subscribe, iot:Connect, iot:Receive.
Final policy should look as below.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1232909773123",
"Action": [
"iot:Connect",
"iot:Receive",
"iot:Subscribe"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
The IoT policy which needs to be attached to identity id (of cognito) should be as below.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:us-east-1:<account-number>:client/*"
},
{
"Effect": "Allow",
"Action": [
"iot:Receive"
],
"Resource": [
"arn:aws:iot:us-east-1:<account-number>:topic/${cognito-identity.amazonaws.com:sub}"
]
},
{
"Effect": "Allow",
"Action": [
"iot:Subscribe"
],
"Resource": [
"arn:aws:iot:us-east-1:<account-number>:topicfilter/${cognito-identity.amazonaws.com:sub}"
]
}
]
}
NOTE: for #2, you need to put your AWS account number in policy
Spent a lot of time on this particular issue. The documentation and error handling around variable substitution in MQTT IoT Policies are not great. The following worked for me as well. IF you're using Cognito Federated Identities, do ensure you add the IoT policy to the authenticated user role. Final note: the ${cognito-identity.amazonaws.com:sub} resolves to the identityId from Cognito developer identity, not the user-pool or JWT. At any rate, hope this helps someone else.
Cognito Authenticated Role Policy
Note: this is too permissive - refine as needed.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iot:*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
MQTT IoT Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:us-east-1:<account-id>:client/*"
},
{
"Effect": "Allow",
"Action": [
"iot:Publish",
"iot:Receive"
],
"Resource": [
"arn:aws:iot:us-east-1:<account-id>:topic/${cognito-identity.amazonaws.com:sub}/*"
]
},
{
"Effect": "Allow",
"Action": [
"iot:Subscribe"
],
"Resource": [
"arn:aws:iot:us-east-1:<account-id>:topicfilter/${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}

Invoking SNS from cross account using API Gateway

I am having an API gateway end point in my AWS account which will invoke a SNS in another AWS account in same region.
The access policy in API gateway in my account is like follows
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:ap-southeast-1:604970532282:PublishSourceMsgTopic"
}
]
}
The sns arn : arn:aws:sns:ap-southeast-1:604970532282:PublishSourceMsgTopic belongs to another AWS account in same region.
The json of the access policy configured in the above SNS is :
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__default_statement_ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"SNS:Publish",
"SNS:RemovePermission",
"SNS:SetTopicAttributes",
"SNS:DeleteTopic",
"SNS:ListSubscriptionsByTopic",
"SNS:GetTopicAttributes",
"SNS:Receive",
"SNS:AddPermission",
"SNS:Subscribe"
],
"Resource": "arn:aws:sns:ap-southeast-1:604970532282:PublishSourceMsgTopic",
"Condition": {
"StringEquals": {
"AWS:SourceOwner": "604970532282"
}
}
},
{
"Sid": "__console_pub_0",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::148445556582:root"
},
"Action": "SNS:Publish",
"Resource": "arn:aws:sns:ap-southeast-1:604970532282:PublishSourceMsgTopic"
}
]
}
When I am invoking the API Gateway its showing the following error :
User: arn:aws:sts::148445556582:assumed-role/api_gateway_sns_role/BackplaneAssumeRoleSession is not
authorized to perform: SNS:Publish on resource: arn:aws:sns:ap-southeast-
1:604970532282:PublishSourceMsgTopic
I am able to invoke the SNS successfully if i am giving SNS topic which is configured in my AWS account.
What am I missing here?
You are giving permission for the root owner of the external account to publish on the topic, but the actual publish request is using the role of the API gateway.
So in your access policy, you'll need to give the publish permission to the role the API Gateway is using, not the role of root.
Typically what you would do is set "Principal": "*" and then add conditions under resource in the policy to match the account and arn of the resource accessing SNS from another account.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": "SNS:Publish",
"Resource": "arn:aws:sns:us-east-2:444455556666:MyTopic",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:cloudwatch:us-east-2:111122223333:alarm:MyAlarm"
}
}
}]
}
There are several example access policies here, that should help you.

AWS IAM Policy to Grant All service permission to specific instances

I have setup separate IAM users from the root account with various privilege levels and I need provide all EC2 services access for 2 specific instances to a particular IAM user
I used AWS policy generator and got the below policy but it doesn't work
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "ec2:*",
"Effect": "Allow",
"Resource": [
"arn:aws:ec2:us-east-1:ACCOUNT_ID:instance/INSTANCE_ID",
"arn:aws:ec2:us-east-1:ACCOUNT_ID:instance/INSTANCE_ID"
]
}
]
}
How can I grant permission to the specific instances so the IAM user can only manage those specific instances without accessing any other instances or services.
You can achieve this via Tags. As stated by the AWS Docs, you can try the below policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:RebootInstances"
],
"Condition": {
"StringEquals": {
"ec2:ResourceTag/Owner": "Bob"
}
},
"Resource": [
"arn:aws:ec2:us-east-1:111122223333:instance/*"
],
"Effect": "Allow"
},
{
"Effect": "Allow",
"Action": "ec2:Describe*",
"Resource": "*"
}
]
}

S3 security policy seems to have no effect

I am trying to use S3 as maven repo. I created 2 IAM users for write and read, and used the Policy Generator to create the following bucket policy, which I added to the bucket.
{
"Id": "Policy1442851625435",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1442851437396",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::closeup-maven/*",
"Principal": {
"AWS": [
"arn:aws:iam::642063966117:user/maven-write"
]
}
},
{
"Sid": "Stmt1442851517972",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::closeup-maven/*",
"Principal": {
"AWS": [
"arn:aws:iam::642063966117:user/maven-read"
]
}
},
{
"Sid": "Stmt1442851587864",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::closeup-maven",
"Principal": {
"AWS": [
"arn:aws:iam::642063966117:user/maven-write",
"arn:aws:iam::642063966117:user/maven-read"
]
}
}
]
}
[anonymized]
When I run the Policy Simulator, I get denied for both users.
When I go to the bucket and set Everyone-access for everything, I still get denied in the Policy Simulator, when I am testing with these two users.
What am I missing?
I noticed a disclaimer in the IAM Policy Simulator that says it does not take into account policies attached to resources, like your bucket policy. Maybe if you had the policy attached separately to the IAM users, the simulator would evaluate them.
This action belongs to a service that supports access control mechanisms attached to resources.The policy simulator does not model these mechanisms, so results may differ in your production environment.