Goal: Grant permissions to IAM user to confirm an SNS Topic Subscription
Problem: Using AWS Web Console, I am unable to grant the proper SNS permissions to the IAM user account no matter what permissive policies I attach to it.
Steps completed: I created a Topic which tracks changes to S3 objects and pushes that information to my application via an SNS subscription (HTTPS/JSON calls).
My code that receives the request:
def self.confirm(arn, token)
client = retrieve_client
client.confirm_subscription(topic_arn: arn, token: token)
end
def self.retrieve_client
creds = Aws::Credentials.new(
Rails.application.credentials.dig(:aws, :access_key_id),
Rails.application.credentials.dig(:aws, :secret_access_key)
)
Aws::SNS::Client.new(region: 'us-east-2', credentials: creds)
end
When my code receives the SNS confirmation request, I receive this error message:
Aws::SNS::Errors::AuthorizationError (User: arn:aws:iam::12345678912:user/user_name is not authorized to perform: SNS:ConfirmSubscription on resource: arn:aws:sns:us-east-2:12345678912:topic_name because no boundary policy allows the SNS:ConfirmSubscription action)
The above code works well with a different application (but different IAM user), so I don't believe the code is the culprit, yet.
I've attempted adding policies to a group, then the user to the group, nothing changes.
I've resorted to directly adding policies to the user, nothing changes.
Here are the two most permissive policies I've tried and I don't know what other blanket permissions I can give this user to make this subscription confirmation work.
Topic arn: arn:aws:sns:us-east-2:12345678912:topic_name
Topic access policy:
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:us-east-2:12345678912:topic_name
"StringEquals": {
"AWS:SourceAccount": "12345678912"
},
"ArnLike": {
"AWS:SourceArn": "arn:aws:s3:*:*:*"
}
}
}
]
}
Policy 1 (from the AWS Managed AmazonSNSFullAccess policy):
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sns:*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
Policy 2, where I just click as many Action selections as possible to see if anything will work:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"sns:TagResource",
"sns:DeleteTopic",
"sns:ListTopics",
"sns:Unsubscribe",
"sns:CreatePlatformEndpoint",
"sns:SetTopicAttributes",
"sns:UntagResource",
"sns:OptInPhoneNumber",
"sns:CheckIfPhoneNumberIsOptedOut",
"sns:ListEndpointsByPlatformApplication",
"sns:SetEndpointAttributes",
"sns:Publish",
"sns:DeletePlatformApplication",
"sns:SetPlatformApplicationAttributes",
"sns:VerifySMSSandboxPhoneNumber",
"sns:Subscribe",
"sns:ConfirmSubscription",
"sns:RemovePermission",
"sns:ListTagsForResource",
"sns:DeleteSMSSandboxPhoneNumber",
"sns:ListSubscriptionsByTopic",
"sns:GetTopicAttributes",
"sns:ListSMSSandboxPhoneNumbers",
"sns:CreatePlatformApplication",
"sns:SetSMSAttributes",
"sns:CreateTopic",
"sns:GetPlatformApplicationAttributes",
"sns:GetSubscriptionAttributes",
"sns:ListSubscriptions",
"sns:AddPermission",
"sns:ListOriginationNumbers",
"sns:DeleteEndpoint",
"sns:ListPhoneNumbersOptedOut",
"sns:GetEndpointAttributes",
"sns:SetSubscriptionAttributes",
"sns:GetSMSSandboxAccountStatus",
"sns:CreateSMSSandboxPhoneNumber",
"sns:ListPlatformApplications",
"sns:GetSMSAttributes"
],
"Resource": "*"
}
]
}
It's completely unclear to me what other policies are required to give this user the authorization necessary to confirm the SNS subscription.
Thanks to the question Marcin asked about the "boundary policy," I learned that the concept of an IAM boundary policy existed, what it was, and then fixed my problem.
At some point, when the IAM user was setup, a boundary policy was attached to the user account, which precludes any other policies that may be given to that user by other service or group policies.
Thus, when I inspected the IAM user in question, I found a boundary policy that only permitted access to AWS S3 services. This policy prevented my efforts to give the user access to AWS SNS services.
After removing the boundary policy, the IAM user settings now read "Permissions boundary (not set)" and the confirmation of the SNS subscriptions work as expected.
Thanks for the help, Marcin!
Related
I am trying to enable SMS message delivery logs in AWS SNS. But no matter what I do I get this error:
Couldn't set text messaging attributes. Error code: AuthorizationError
- Error message: You are not authorized to perform actions for the provided bucket
I have tried numerous IAM roles (including admin access role) and I am logged in as the root account owner.
What might I be missing? What can I try?
Thank you!
I found this specific documentation that solved it for me: https://docs.aws.amazon.com/sns/latest/dg/sms_stats_usage.html#example_bucket_policy
The key is that the bucket policy needs to list sns.amazonaws.com as the principal, and really only needs to allow these 3 actions to finish configuring SMS:
s3:GetBucketLocation
s3:ListBucket
s3:PutObject
{
"Version": "2012-10-17",
"Id": "Policy1653549854620",
"Statement": [
{
"Sid": "Stmt1653549853470",
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::BUCKETNAME"
}
]
}
Note: I have reviewed other questions and believe this is unique because it specifically pertains to cross-account secrets access using a glue job.
I am having an issue where a glue job, assuming a service role in one account, is unable to access a secret stored in another account, despite my policies which I believe should allow it to do so.
Error I'm seeing (with redacted values): An error occurred (AccessDeniedException) when calling the GetSecretValue operation: Access to KMS is not allowed. This version of secret is not encrypted with the current KMS key.
Question
What about the below setup is causing the permission failure?
Diagram of Current Situation
My Understanding of What Needs to be Done
Based on the AWS docs and a 2018 blog post, I think what we have to do is:
Add a Policy on the secret to allow access to service role
Add a Policy on the CMK to allow service role to decrypt
Add a Policy on Service role to allow access to secret
Add a Policy on Service role to allow CMK decryption
Current Policies
Policy on Secret
{
"Version" : "2012-10-17",
"Statement" : [ {
"Effect" : "Allow",
"Principal" : {
"AWS" : "arn:aws:iam::GLUE_ACCOUNT:role/GLUE_SERVICE_ROLE"
},
"Action" : "secretsmanager:GetSecretValue",
"Resource" : "*",
"Condition" : {
"ForAnyValue:StringEquals" : {
"secretsmanager:VersionStage" : "AWSCURRENT"
}
}
} ]
}
Policy on CMK
Note that the redacted SECRET_NAME below contains the few characters that AWS appends in the ARN, which it seems we need to include.
{
"Sid": "AllowUseOfTheKey",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::GLUE_ACCOUNT:role/GLUE_SERVICE_ROLE"
},
"Action": ["kms:Decrypt","kms:DescribeKey"],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "secretsmanager.us-east-1.amazonaws.com"
},
"StringLike": {
"kms:EncryptionContext:SecretARN": "arn:aws:secretsmanager:us-east-1:SECRET_ACCOUNT:secret:SECRET_NAME"
}
}
}
Policy Statements Attached to Glue Service Role in Glue Account
{
"Sid": "AllowGetSecretValue",
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:secretsmanager:us-east-1:SECRET_ACCOUNT:secret:SECRET_NAME"
]
},
{
"Sid": "AllowKMSDecrypt",
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": [
"arn:aws:kms:us-east-1:SECRET_ACCOUNT:key/CMK_KEY_ID"
]
},
Trust policy on the service role
Just to confirm that the glue job does indeed seem to have the authority to assume the service role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "glue.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Possible Next Steps
As thought experiments, I'm considering doing the below just to see if it works:
Removing the condition in the secret policy
Removing the conditions in the CMK policy
Adding kms:DescribeKey to the Service Account policy as well, though I don't think that's going to resolve things.
As sometimes happens with these involved questions, the piece of information to answer the question was found outside of the information I'd provided, despite my best efforts.
The solution was two-fold:
The authorization error that was part of the original question wasn't due to authentication access at all. It was because the code that used boto3 specified the name of the secret instead of the full ARN. Of course secrets manager wouldn't magically know that secret was in a different account.
A surprising thing in this case is that AWS threw an unauthorized exception, and not a not found exception, which would have been infinitely more useful to our efforts.
Once that was fixed, we saw the error that is currently in the ticket, around encrypting the CMK. Apparently when we changed the CMK, we did not select to automatically create a new version of the secret with that CMK. A simple edit and save of the secret by an authorized user was enough to re-encrypt it with the chosen CMK and resolve the issue.
I've recently setup AWS SES and continue to run into the following error when sending email from a local application.
User `arn:aws:iam::REDACTED:user/mail_user' is not authorized to perform `ses:SendEmail' on resource `arn:aws:ses:us-east-1:REDACTED:identity/mail#REDACTED.COM'
I've setup the below policy for the email mail#REDACTED.COM
{
"Version": "2012-10-17",
"Id": "SampleAuthorizationPolicy",
"Statement": [
{
"Sid": "AuthorizeEmail",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::REDACTED:user/mail_user"
},
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": "arn:aws:ses:us-east-1:REDACTED:identity/mail#REDACTED.COM"
}
]
}
Any suggestions as to why I'm continuing to receive the unauthorized error?
To resolve this issue I created an inline policy for the user via IAM (the permissions tab under the User).
I granted the following permissions to resource arn:aws:ses:us-east-1:REDACTED:identity/mail#REDACTED.COM
SendEmail
SendRawEmail
I did not need to create an identity policy via the SES management panel.
I am trying to configure the SQS policy for a queue to authorize all principles of an account to send messages to this queue, according to the documentation here:
{
"Version": "2012-10-17",
"Id": "sqspolicy",
"Statement": [
{
"Sid": "Sqs policy1",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789:root"
]
}
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:eu-west-1:123456789:my_queue"
}
]
}
Will this allow any principle of this account to send messages to my_queue or will it only allow the root user?
Or should I use the below policy with a condition instead?
{
"Version": "2012-10-17",
"Id": "sqspolicy",
"Statement": [
{
"Sid": "Sqs policy1",
"Effect": "Allow",
"Principal": {
"AWS": "*"
}
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:eu-west-1:123456789:my_queue"
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "123456789"
}
}
}
]
}
TIA
The documentation says:
When you use an AWS account identifier as the principal in a policy, you delegate authority to the account. All identities inside the account can access the resource if they have the appropriate IAM permissions attached to explicitly allow access. This includes IAM users and roles in that account.
According to this, your first approach will allow all of your users to send messages.
Only first policy is valid. The second policy will not work, the way you may think. The reason is that aws:SourceAccount is only used for service-to-service requests, not IAM users or roles. The most common example of when aws:SourceAccount is used is for S3:
For example, when an Amazon S3 bucket update triggers an Amazon SNS topic post, the Amazon S3 service invokes the sns:Publish API operation. The bucket is considered the source of the SNS request and the value of the key is the account ID associated with the bucket.
Send-messages requests made by IAM users/roles in the second account will be denied because for these entities there is no aws:SourceAccount.
I want to restrict access for a specific user to see just few EC2 instances. I created a new user in IAM Roles and I attached a new Policy to it. The content of that Policy is attached below. I tried to look over documentation and to do it myself like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": [
"arn:aws:ec2:eu-west-1:ACCOUNT_ID:instance/i-INSTANCE_ID1",
"arn:aws:ec2:eu-west-1:ACCOUNT_ID:instance/i-INSTANCE_ID2"
]
}
]
}
I placed my region,ACCOUNT_ID(the owner id, not of the new user created) and instance-id, but when I connect with that user and I go to list all Instances I got this An error occurred fetching instance data: You are not authorized to perform this operation..
After I placed the code in JSON editor, in Policy Review step I got this message:
This policy defines some actions, resources, or conditions that do not
provide permissions. To grant access, policies must have an action
that has an applicable resource or condition. For details, choose Show
remaining Learn more
The AWS documentation mention exactly the same configuration or these examples.
I assume you connect as that user in the console (but it would be the same with CLI) Here is what I think is happening:
To list all the instances, the console most probably calls the DescribeInstances API. As per the list of action/resources/tags that can be used in IAM policy, this API does not support the resource filter in IAM.
This means your user has no authorization to list instances and they will not be shown in the console. You can validate this theory by using the CLI to request the details of a specific instance id, if my hypothesis is correct, it will be authorized.
As DescribeInstances can not be restricted by resource or tags, I don't think it is possible to filter the instance list for a user.
To have the console working, you'll need to add the following statement in your IAM policy
"Statement": [
{ your existing statement },
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*"
}
]
Please report if I was right :-) The example you mentioned in your question shows exactly that : Resources = * on DescribeInstances and Resources specific InstanceId on other operations.
The previous answer is wrong, you can Conditionally allow access to ec2:DescribeInstances by tag names. It's an AWS best practice as well. Also explicitly deny access to the ec2:CreateTags and ec2:DeleteTags actions to prevent users from creating or deleting tags to take control of the instance.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:ResourceTag/UserName": "${aws:username}"
}
}
},
{
"Effect": "Deny",
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Resource": "*"
}
]
}
DescribeInstances action does not support condition.
https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html