IAM policy allowing SMS publishing but not denying all SNS - amazon-web-services

I want to set up IAM policies to allow an user to publish to SNS to send SMS and to publish to a specific SNS arn.
I have found a way to allow SMS publish without allowing any SNS publish :
Authorization when sending a text message using AmazonSNSClient
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"sns:Publish"
],
"Resource": "arn:aws:sns:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "*"
}
]
}
But this policy is explicitly denying all other SNS publish, so I can't add a policy allowing a specific SNS.
The problem is that SMS publish does not have a specific arn.
So I am looking at conditions to find a way to limit the allow to publish only SMS. But the specific SMS parameters (PhoneNumber cf https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SNS.html#publish-property) cannot be filtered in condition :
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "*",
"Condition": {"Null":{"PhoneNumber":"false"}}
}
]
}
Is there a way to accomplish such a policy ?

Actually to do the trick I found a way using an allow whit the NotResource JSON Policy Element (spec). I use this property to match the resources which do NOT have an ARN:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"NotResource": "arn:aws:sns:*:*:*"
}
]
}
With this trick I can allow all sns Publish without ARN (but I don't know if there is any other services then SMS...).
This also allow me to allow specifics ARN in another policy.

Related

Forbidden on sns:ListTopics with wildcard resources

My team has an account with full permission on SNS as long as we act on resources based on a certain prefix
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:CreateTopic",
// ...
"sns:ListTopics",
// ...
],
"Resource": "arn:aws:sns:eu-west-1:{redacted}:team-prefix-*"
},
We can do most operations just fine, at least the ones we most need, but if we try to list the topics we get a forbidden error
SNS: ListTopics, AuthorizationError: User xxx is not authorized to perform: SNS:ListTopics on resource: arn:aws:sns:eu-west-1:{redacted}:*
We are using the new go SDK v2, and we cannot find a way to query only for our topics, is there a way to list them or do we need list permissions on all the account topics?
sns:ListTopics does not have a resource filter per (https://docs.aws.amazon.com/sns/latest/api/API_ListTopics.html) its an all or nothing operation.
Except from amazon docs: if you specify a resource type in a statement with an action that does not support that resource type, then the statement doesn't allow access. link
Typically, this is what the IAM document should look like if you want to be able to list.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:CreateTopic"
],
"Resource": "arn:aws:sns:eu-west-1:{redacted}:team-prefix-*"
},
{
"Effect": "Allow",
"Action": [
"sns:ListTopics",
],
"Resource": "*"
},
...
If separation at the granular level is really that big of a concern, separate AWS accounts should be used.

Access control of AWS SQS subscription for AWS SNS topic

I have a NodeJS application that publishes message to AWS SNS topic string and a AWS SQS subscription for the same. On the SQS console, I can see the published message. However, I am not clear with the access policy of the SQS queue.
This answer mentions the use of "Principal": "*" - but, that is very broad. One could probably use "Principal" : {"AWS": "*"}; but, that isn't narrow either.
{
"Version": "2012-10-17",
"Id": "Policy1607949016538",
"Statement": [
{
"Sid": "Stmt1607949012567",
"Effect": "Allow",
"Principal": "*",
"Action": [
"sqs:ReceiveMessage",
"sqs:SendMessage"
],
"Resource": "arn:aws:sqs:ap-south-1:463113000000:orders"
}
]
}
Questions
While delivering a message to SQS queue, as a result of subscription, which user is in effect? Same as the one who published to the topic?
I could get the messages to flow into the queue only when I used "Principal" : {"AWS": "*"}. So, how should I define a restrictive policy such that messages are written to queues only as a result of subscription?
What is the equivalent in the AWS SQS CLI to create a queue with "Principal" : {"AWS": "*"} permissions?
The only user that matters is the one that qualifies for the policy as defined for subscription and SQS access policy.
The Condition in policy document can make the overall policy restrictive. See example below.
Adding SQS Permissions with conditions using AWS CLI Command
Example policy document restricting access to account ID.
{
"Version": "2012-10-17",
"Id": "Policy1607960702002",
"Statement": [
{
"Sid": "Stmt1607960701004",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"sqs:ReceiveMessage",
"sqs:SendMessage"
],
"Resource": "arn:aws:sqs:ap-south-1:463113000000:orders",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "463113000000"
}
}
}
]
}

AWS IoT Policy overly permissive

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

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}/*"
]
}
]
}

AWS SNS Policy IP Address Access

In SNS, I set up a topic.
In IAM, I have set up a policy to allow access to the topics ARN from only from a specific IP address:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"sns:Publish",
"sns:Subscribe"
],
"Resource": "arn:aws:sns:us-east-1:111111111111:topic_name",
"Condition": {
"IpAddress": {
"aws:SourceIp": "xxx.xxx.xxx.x"
}
}
}
]
}
I have attached this policy to a group, and added a user to this group.
From a C# windows application, I can now subscribe and publish the topic from the specified SourceIp listed in the policy.
But in this case, I need to use the AccessKey and SecretAccessKey of the IAM user.
Is there a way that I can bypass needing the AccessKey and SecretKey as long as the SourceIp is correct?
I see that the SNS topic "topic policy", but I could not figure out how to add the IpAddress Condition. Is that possible?
topic policy:
{
"Version": "2008-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",
"SNS:Receive"
],
"Resource": "arn:aws:sns:us-east-1:111111111111:topic_name",
"Condition": {
"StringEquals": {
"AWS:SourceOwner": "111111111111"
}
}
}
]
}
Amazon SNS requires authentication and authorization to use the service. This means either an IAM user or role. This means you must use credentials to access the service.
I would combine IAM User Policies with SNS Policies to control who (user or service) can publish / subscribe to SNS.
There are many AWS services that can use SNS. Your IP address policy may break them.
SNS: Controlling User Access to Your AWS Account