Invoking SNS from cross account using API Gateway - amazon-web-services

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.

Related

AWS: Permissions for exporting logs from Cloudwatch to Amazon S3

I am trying to export logs from one of my CloudWatch log groups into Amazon S3, using AWS console.
I followed the guide from AWS documentation but with little success. My organization does not allow me to manage IAM roles/policies, however I was able to find out that my role is allowed all log-related operations (logs:* on all resources within the account).
Currently, I am stuck on the following error message:
Could not create export task. PutObject call on the given bucket failed. Please check if CloudWatch Logs has been granted permission to perform this operation.
My bucket policy is set in the following way:
{
[
...
{
"Sid": "Cloudwatch Log Export 1",
"Effect": "Allow",
"Principal": {
"Service": "logs.eu-central-1.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::my-bucket"
},
{
"Sid": "Cloudwatch Log Export 2",
"Effect": "Allow",
"Principal": {
"Service": "logs.eu-central-1.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
Prior to editing bucket policy, my error message had been
Could not create export task. GetBucketAcl call on the given bucket failed. Please check if CloudWatch Logs has been granted permission to perform this operation.
but editing the bucket policy fixed that. I would expect allowing PutObject to do the same, but this has not been the case.
Thank you for help.
Ensure when exporting the data you configure the following aptly
S3 bucket prefix - optional This would be the object name you want to use to store the logs.
While creating the policy for PutBucket, you must ensure the object/prefix is captured adequately. See the diff for the PutBucket statement Resource:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "s3:GetBucketAcl",
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-exported-logs",
"Principal": { "Service": "logs.us-east-2.amazonaws.com" }
},
{
"Action": "s3:PutObject" ,
"Effect": "Allow",
- "Resource": "arn:aws:s3:::my-exported-logs/*",
+ "Resource": "arn:aws:s3:::my-exported-logs/**_where_i_want_to_store_my_logs_***",
"Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } },
"Principal": { "Service": "logs.us-east-2.amazonaws.com" }
}
]
}
Please check this guide Export log data to Amazon S3 using the AWS CLI
Policy's looks like the document that you share but slight different.
Assuming that you are doing this in same account and same region, please check that you are placing the right region ( in this example is us-east-2)
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "s3:GetBucketAcl",
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-exported-logs",
"Principal": { "Service": "logs.us-east-2.amazonaws.com" }
},
{
"Action": "s3:PutObject" ,
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-exported-logs/*",
"Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } },
"Principal": { "Service": "logs.us-east-2.amazonaws.com" }
}
]
}
I think that bucket owner full control is not the problem here, the only chance is the region.
Anyway, take a look to the other two examples in case that you were in different accounts/ using role instead user.
This solved my issue, that was the same that you mention.
One thing to check is your encryption settings. According to https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/S3ExportTasksConsole.html
Exporting log data to Amazon S3 buckets that are encrypted by AWS KMS is not supported.
Amazon S3-managed keys (SSE-S3) bucket encryption might solve your problem. If you use SSE-KMS, Cloudwatch can't access your encryption key in order to properly encrypt the objects as they are put into the bucket.
I had the same situation and what worked for me is to add the bucket name itself as a resource in the Allow PutObject Sid, like:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLogsExportGetBucketAcl",
"Effect": "Allow",
"Principal": {
"Service": "logs.eu-west-1.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::my-bucket"
},
{
"Sid": "AllowLogsExportPutObject",
"Effect": "Allow",
"Principal": {
"Service": "logs.eu-west-1.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": [
"my-bucket",
"my-bucket/*"
]
}
]
}
I also believe that all the other answers are relevant, especially using the time in milliseconds.

Why is this bucket policy being shown as public

I am relatively new to AWS.
So recently, we creates an AWS S3 bucket through the AWS console. Then we set the following policy on the bucket:
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AddJPGImageFilter",
"Effect": "Allow",
"Principal": {
"AWS": "IAM user ARN"
},
"Action": "s3:PutObject",
"Resource": "bucket_name/*.jpg"
},
{
"Sid": "AddJPEGImageFilter",
"Effect": "Allow",
"Principal": {
"AWS": ""IAM user ARN""
},
"Action": "s3:PutObject",
"Resource": "bucket_name/*.jpeg"
},
{
"Sid": "AddPNGImageFilter",
"Effect": "Allow",
"Principal": {
"AWS": ""IAM user ARN""
},
"Action": "s3:PutObject",
"Resource": "bucket_name/*.png"
}
]
}
Now from what I understand the above policy means the resource would be accessible (with the S3:PutObject action allowed) to only the IAM user ARN mentioned in the Principal.
For it to be public, the Principal would need to be *.
Is my understanding correct ?
If yes, why is the AWS console still showing the above bucket as Public ?
AWS web console has page caching issues. Try logout, clear your cache and re-login again.
Thanks
Sanjog

How to set up AWS SNS in one account to be able to receive notifications from SES of other account?

I have two AWS accounts:
Account 1 (111111111111) contains Simple Notification Service Topic (Email Events Topic)
Account 2 (222222222222) contains Simple Email Service with Configuration Set (Configuration_Set_01).
I want to add SNSDestination to Configuration_Set_01 - to be able to publish SES event notifications to Email Events Topic
I’ve set up following Topic Policy for Email Events Topic:
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__console_pub_0",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::2222222222222:root"
},
"Action": "SNS:Publish",
"Resource": "arn:aws:sns:us-east-1:111111111111:email-events-topic"
}
]
}
When I try to add SNSDestination to Configuration_Set_01, referring Email Events Topic, it gives me an error Could not access SNS topic <…> …:
If Email Events Topic's policy is as follows, destination can be added successfully:
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__console_pub_0",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "SNS:Publish",
"Resource": "arn:aws:sns:us-east-1:111111111111:email-events-topic"
}
]
}
This works:
"Principal": {
"AWS": "*"
}
This doesn't work:
"Principal": {
"AWS": "arn:aws:iam::222222222222:root"
}
As I can see here https://docs.aws.amazon.com/AmazonS3/latest/dev/s3-bucket-user-policy-specifying-principal-intro.html - the syntax for Principal.AWS value in the second option is correct.
How can I correctly set up Topic Policy on Email Events Topic to be able to add it as an event destination only to Account 2's SES Configuration Sets (or any Account 2's services)?
What else should be done to solve the problem in case the problem is not only with the Topic Policy?
The sample link you shared is for S3 resource policy. Could you please try to edit the policy as following which is from SNS document?
{
"Version":"2012-10-17",
"Id":"AWSAccountTopicAccess",
"Statement" :[
{
"Sid":"give-1234-publish",
"Effect":"Allow",
"Principal" :{
"AWS":"111122223333"
},
"Action":["sns:Publish"],
"Resource":"arn:aws:sns:us-east-1:444455556666:MyTopic"
}
]
}
Additionally, you can also use "AWS:SourceAccount" condition key with Principal *.
Here is the Topic Policy, which works for the described situation:
{
"Version": "2012-10-17",
"Id": "MyTopicPolicy",
"Statement": [
{
"Sid": "sid001",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "sns:Publish",
"Resource": "arn:aws:sns:us-east-1:111111111111:email-events-topic",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:ses:us-east-1:222222222222:*"
}
}
}
]
}
The tricky part was Condition -> ArnLike:
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:ses:us-east-1:222222222222:*"
}
}

S3 Private Bucket

I'm trying to create a private S3 bucket with limited access. I only want myself as a user and an EC2 role to have access to the bucket. The purpose of the bucket is to store encrypted SSH keys that will be copied onto machines in an autoscaling group. Right now, when I run aws sync against the bucket, here is the output:
cogility#ip-10-10-200-113:~$ aws s3 sync s3://sshfolder.companycloud.com/cogility /home/cogility/.ssh
download failed: s3://sshfolder.companycloud.com/cogility/id_rsa to ../cogility/.ssh/id_rsa An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
download failed: s3://sshfolder.companycloud.com/cogility/id_rsa.pub to ../cogility/.ssh/id_rsa.pub An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
I create the EC2 instances with an EC2 role with the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"kms:List*",
"kms:Get*",
"kms:Describe*"
],
"Resource": "arn:aws:kms:us-west-2:0000000000:key/kms-id-01234567890"
},
{
"Sid": "",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sshfolder.companycloud.com/*",
"arn:aws:s3:::sshfolder.companycloud.com"
]
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"elasticloadbalancing:*",
"ec2:*",
"cloudwatch:*",
"autoscaling:*"
],
"Resource": "*"
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"lambda:List*",
"lambda:Invoke*",
"lambda:Get*"
],
"Resource": "*"
}
]
}
And here is the bucket policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sshfolder.companycloud.com",
"arn:aws:s3:::sshfolder.companycloud.com/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"AROAXXXXXXXXXXXXXXXXX", <-- autoscaling-ec2-role user id
"AROAXXXXXXXXXXXXXXXXX",
"AIDAXXXXXXXXXXXXXXXXX",
"AIDAXXXXXXXXXXXXXXXXX"
],
"aws:sourceVpce": "vpce-abc82480d"
},
"ArnNotLike": {
"aws:SourceArn": "arn:aws:sts::000000000000:assumed-role/autoscaling-ec2-role/"
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::000000000000:root"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sshfolder.companycloud.com",
"arn:aws:s3:::sshfolder.companycloud.com/*"
]
}
]
}
Any idea why I'm not able to access the S3 bucket from my EC2 instance?
Amazon S3 buckets are private by default. Therefore, one approach would be:
Do not use a Bucket Policy
Add permissions to your IAM User and the IAM Role to access the bucket
Alternatively:
Use a Bucket Policy to grant access to the IAM User and IAM Role
Both would be sufficient to meet your needs.
However, if you are further paranoid that somebody might accidentally grant access to the bucket (eg with s3:* and a principal of *), then your approach of explicitly Denying access to anyone other than that User & Role is a good approach.
deny trumps allow in your bucket policy. You need to use not principal to achieve this.
"Statement": [
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": "arn:aws:iam::000000000000:root"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sshfolder.companycloud.com",
"arn:aws:s3:::sshfolder.companycloud.com/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"AROAXXXXXXXXXXXXXXXXX", <-- autoscaling-ec2-role user id
"AROAXXXXXXXXXXXXXXXXX",
"AIDAXXXXXXXXXXXXXXXXX",
"AIDAXXXXXXXXXXXXXXXXX"
],
"aws:sourceVpce": "vpce-abc82480d"
},
"ArnNotLike": {
"aws:SourceArn": "arn:aws:sts::000000000000:assumed-role/autoscaling-ec2-role/"
}
}
}
]
It just inverts the principal element. You can similarly use NotAction and NotResource as appropriate. You could do away with your conditionals altogether and just use NotPrincipal for all of them, it's generally better practice than conditionals.
Here is a resource on it: https://aws.amazon.com/blogs/security/how-to-create-a-policy-that-whitelists-access-to-sensitive-amazon-s3-buckets/

How do I write the policy statement of an encrypted SQS for S3 events?

I have an SQS queue which used to have the following policy doc. for receiving S3 events from a bucket:
{
"Version": "2008-10-17",
"Id": "example-ID",
"Statement": [
{
"Sid": "example-statement-ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"sqs:SendMessage",
"sqs:ReceiveMessage"
],
"Resource": "arn:aws:sqs:us-east-1:<>:cypher-queue",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:s3:*:*:cypher-secondarybucket"
}
}
}
]
}
Now, I have enabled Server-side encryption(SSE) for the queue. And, I have followed this doc for writing the policy statement for encryption. The policy statement now, looks like this:
{
"Version": "2008-10-17",
"Id": "example-ID",
"Statement": [
{
"Sid": "example-statement-ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"sqs:SendMessage",
"sqs:ReceiveMessage"
],
"Resource": "arn:aws:sqs:us-east-1:<>:cypher-queue",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:s3:*:*:cypher-secondarybucket"
}
}
},
{
"Effect": "Allow",
"Action": [
"kms:GenerateDataKey",
"kms:Decrypt"
],
"Resource": "arn:aws:sqs:us-east-1:<>:cypher-queue",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:s3:*:*:cypher-secondarybucket"
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:<>:cypher-queue",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:s3:*:*:cypher-secondarybucket"
}
}
}
]
}
But now, the queue is not getting any messages from the bucket on file additions. Is there something wrong which I did with the permissions?
This is now possible. From the AWS documentation:
https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#grant-destinations-permissions-to-s3 under the section AWS KMS Key Policy
If the SQS queue is SSE enabled, you can attach the following key
policy to the associated AWS Key Management Service (AWS KMS) customer
managed customer master key (CMK). The policy grants the Amazon S3
service principal permission for specific AWS KMS actions that are
necessary for to encrypt messages added to the queue.
{
"Version": "2012-10-17",
"Id": "example-ID",
"Statement": [
{
"Sid": "example-statement-ID",
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": [
"kms:GenerateDataKey",
"kms:Decrypt"
],
"Resource": "*"
}
]
}
I have missed the following announcement from the same article. A very silly mistake on my part. Will need to wait for sending S3 events to encrypted SQS.
The following features of AWS services aren't currently compatible
with encrypted queues:
Amazon CloudWatch Events
Amazon S3 Event Notifications
Amazon SNS Topic Subscriptions
Auto Scaling Lifecycle Hooks
AWS IoT Rule Actions
AWS Lambda Dead-Letter Queues