AWS SNS Policy IP Address Access - amazon-web-services

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

Related

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

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.

How to send SMS through SNS and Cloudwatch?

I am trying to send SMS to my Mobile when my EC2 instance stops.
I am automatically stopping my EC2 instance and now I want to send SMS to my mobile when it stops.
I created SNS topic with my mobile no. as subscriber.
I created an Alarm when the EC2 stops.
Under SNS > Mobile > Text messaging (SMS) > Text messaging preferences (Edit):
a. I selected "Default message type" as "Transactional".
b. I created a new IAM role.
IAM role policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:PutMetricFilter",
"logs:PutRetentionPolicy"
],
"Resource": [
"*"
]
}
]
}
SNS topic access policy
{
"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:us-west-2:account-id:sns-topic-name",
"Condition": {
"StringEquals": {
"AWS:SourceOwner": "account-id"
},
"ArnLike": {
"AWS:SourceArn": "arn:aws:cloudwatch:us-west-2:account-id:alarm:*"
}
}
}
]
}
When the alarm is triggered, I am getting the below error:
{
"actionState": "Failed",
"stateUpdateTimestamp": 1561102479560,
"notificationResource": "arn:aws:sns:us-west-2:account-id:sns-topic-name",
"publishedMessage": null,
"error": "Resource: arn:aws:cloudwatch:us-west-2:account-id:alarm:alarm-name is not authorized to perform: SNS:Publish on resource: arn:aws:sns:us-west-2:account-id:sns-topic-name"
}
I am unable to understand what permission is it expecting.
The cause of the error is most likely due to the policy having incorrect values. I'm not sure which values you changed to protect sensitive values, but you'd need to update sns-topic-name and account-id.
However, I would recommend another way of achieving your goals...
You can use Amazon CloudWatch Events to look out for a specific event (eg an instance changing state to Stopped) and have it send a message to Amazon SNS directly (without using an Alarm).
The steps are:
In the Amazon CloudWatch console, click Rules
Create rule
Service name: EC2
Event type: EC2 Instance State-change Notification
Specific state(s): Stopped
Choose Any instance or Specific instance Id(s)
On the right, under Targets, click Add target
SNS topic
Select your topic
This will then send a message whenever the instance stops.
It seems the error is due to missing permissions on your IAM role for publishing messages to an SNS topic. Make arrangements to attach necessary permissions to the role you use or to the user, like this:
{
"Id": "Policy1415489375392",
"Statement": [
{
"Sid": "AWSConfigSNSPolicy20150201",
"Action": [
"SNS:Publish"
],
"Effect": "Allow",
"Resource": "arn:aws:sns:region:account-id:myTopic",
"Principal": {
"AWS": [
"account-id1",
"account-id2",
"account-id3",
]
}
}
]
}

IAM policy allowing SMS publishing but not denying all SNS

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.