Why AWS CloudWatch Alarm cannot send notification to encrypted SNS Topic? - amazon-cloudwatch

I set up alerts to notify me if my lambda function memory usage is more than 80% of the lambda memory size. I'm capturing the data points using custom metrics and I am able to see the alerts in the cloudwatch console when the the memory usage is over the threshold. But when Alarm takes the action to send a notification to the corresponding SNS topic is failed with this message:
{
"actionState": "Failed",
"stateUpdateTimestamp": 1558142246126,
"notificationResource": "arn:aws:sns:us-east-1:5847563209:<myTopic>",
"publishedMessage": null,
"error": "null (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: 6b7806a6-2c16-4582-9ecd-05100161746e)"
}
The SNS topic is encrypted with KMS key and I allowed cloudwatch to access the key in the key policy:
{
"Sid": "Allow CloudWatch to use the key",
"Effect": "Allow",
"Principal": {
"Service": "cloudwatch.amazonaws.com"
},
"Action": [
"kms:GenerateDataKey",
"kms:Decrypt"
],
"Resource": "*"
}
But still the action is being failed. I've also tried events.amazonaws.com as the principal but no luck. I appreciate any help on this.

Looks like it's not yet supported. From here: https://aws.amazon.com/blogs/compute/encrypting-messages-published-to-amazon-sns-with-aws-kms/
As of November 2018, Amazon CloudWatch alarms don’t yet work with
Amazon SNS encrypted topics.

Related

Unable to read file from encrypted s3 bucket

I'm unable to read a file from encrypted s3 bucket in a lambda.
Below is my policy document where i'm giving access to s3 as well as kms. I've attached this policy to lambda.
When i try to read a file from the bucket, I get Access Denied error.
I'm adding kms:RequestAlias condition to kms statement so that the lambda will only have access to keys which has mytoken in the alias.
I suspect this is where i'm making mistake because if i remove the condition, the lambda gets access to all keys and read the encrypted file without any issues.
Can someone help me restrict access to only keys which has mytoken in the alias
data "aws_iam_policy_document" "lambda_s3_policy_doc" {
statement {
sid = ""
effect = "Allow"
resources = [
"arn:aws:s3:::mybucket*",
"arn:aws:s3:::mybucket*/*"
]
actions = [
"s3:AbortMultipartUpload",
"s3:CreateBucket",
"s3:DeleteObject",
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket",
"s3:ListBucketMultipartUploads",
"s3:ListMultipartUploadParts",
"s3:PutObject"
]
}
statement {
effect = "Allow"
actions = [
"kms:Decrypt",
"kms:DescribeKey",
"kms:Encrypt",
"kms:GenerateDataKey"
]
resources = ["*"]
condition {
test = "StringLike"
variable = "kms:RequestAlias"
values = [
"alias/*mytoken*"
]
}
}
}
What worked for me (I was trying to download the files from a couple of encrypted buckets directly from the AWS console and your case is in fact slightly different) was replacing kms:RequestAlias with kms:ResourceAliases.
statement {
sid = "AllowKMSAccessUsingAliases"
effect = "Allow"
actions = [
"kms:Decrypt",
]
resources = [
"arn:aws:kms:eu-central-1:111111111111:key/*",
]
condition {
test = "ForAnyValue:StringEquals"
variable = "kms:ResourceAliases"
values = [
"alias/alias-bucket-1",
"alias/alias-bucket-2",
]
}
}
According to what the AWS documentation says, it makes sense at least for me: it seems that you should use kms:RequestAlias when you are including the alias as part of your KMS request like in the image below:
When you use kms:ResourceAliases what gets checked is the alias associated to the KMS resource involved in the operation regardless of whether the alias was explicitly included in the request or not
So probably, your lambda function, when asking for the un-encryption of a file in a bucket, is using the KMS id in the request instead of the KMS alias and if that is the case kms:RequestAlias won't work because there is no alias in the request to be checked.

aws cloudsearch uploadDocument returning signaturedoesnotmatch

Im using com.amazonaws.services.cloudsearchdomain.AmazonCloudSearchDomainClient to uploadDocuments() with passing AWS secretkey and access id, End points .
Access Policy - Access all for all services
It is returning
Service: AmazonCloudSearchDomain; Status Code: 403; Error Code:
SignatureDoesNotMatch;
But with same package i have tried search() with same credentials , im getting search result correctly as expected.
Some one please help for above exception
This may be caused by your access policy allowing public access to search requests, but not upload. So there may be an issue with the credentials being passed, but you don't see that error when performing search requests, because credentials aren't necessary for that type of request.
For example, this access policy below would allow anyone to search without presenting credentials. But any other operation (like uploading documents) would require a valid set of credentials that have access to the CloudSearch domain.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "cloudsearch:search"
}
]
}

Graph API Subscription Notification Fires Continuously

I am creating subscriptions to a OneDrive folder using the Graph API and I am receiving change notifications continuously (every half a second) even when the contents of the folder (or even the drive itself) is not changing. (Obviously I was expecting that I would receive notifications only when the folder contents change).
I post the following JSON to create the subscription:-
{
"clientState": "GraphAPITest1 2018/05/01 11:31:26",
"notificationUrl": "https://123e7ff5.ngrok.io/notification/listen",
"resource": "/drives/b!X5kF-EHEkECCcjyJ3Fh1CTQI-5nOBktJv57zZdpp13CPQb_8FIV-RIPt-7fnzyxP/root",
"expirationDateTime": "2018-05-02T11:31:26.0881202+01:00",
"changeType": "updated"
}
The notification that my service receives is:-
{
"value": [
{
"subscriptionId": "2467af01-a616-4493-8947-220146c4828a",
"clientState": "GraphAPITest1 2018/05/01 11:23:13",
"resource": "/drives/b!X5kF-EHEkECCcjyJ3Fh1CTQI-5nOBktJv57zZdpp13CPQb_8FIV-RIPt-7fnzyxP/root",
"resourceData": null,
"changeType": "updated",
"subscriptionExpirationDateTime": "2018-05-02T10:23:13.3640899+00:00"
}
]
}
I get the same behaviour in my own code as well as in Microsoft's example app (https://github.com/OneDrive/onedrive-webhooks-aspnet). My code uses an app-only authentication token but the Microsoft example forces user authentication - both suffer from the same behaviour.
Any idea what I need to do to only get notifications when the contents of the folder actually changes?
Barry

Terraform s3 event notification error

I am having trouble trying to create s3 event notifications. Does anyone know the resolutions to this?
Error is:
*Error applying plan:
1 error(s) occurred:
* module.Test-S3-Bucket.aws_s3_bucket_notification.s3-notification: 1 error(s) occurred:
* aws_s3_bucket_notification.s3-notification: Error putting S3 notification configuration: InvalidArgument: Unable to validate the following destination configurations
status code: 400, request id: AD9B5BF2FF84A6CB, host id: ShUVJ+TdkpqAZfpeDM3grkF9Vue3Q/AF0LydchperKTF6XdQyDM6BisZi/38pGAh/ZqS+gNyrSM=*
Below is the code that gives me the error:
resource "aws_s3_bucket" "s3-bucket" {
bucket = "${var.bucket_name}"
acl = ""
lifecycle_rule {
enabled = true
prefix = ""
expiration {
days = 45
}
}
tags {
CostC = "${var.tag}"
}
}
resource "aws_s3_bucket_notification" "s3-notification" {
bucket = "${var.bucket_name}"
topic {
topic_arn = "arn:aws:sns:us-east-1:1223445555:Test"
events = [ "s3:ObjectCreated:*", "s3:ObjectRemoved:*" ]
filter_prefix = "test1/"
}
}
If you haven't done it already, you need to specify a policy on the topic that grants the SNS:Publish permission to S3 (only from the bucket specified in the Condition attribute) - if you are also provisioning the topic via Terraform then something like this should do it (we know, as it caught us out just a few days ago too!):
resource "aws_sns_topic" "my-sns-topic" {
name = "Test"
policy = <<POLICY
{
"Version":"2012-10-17",
"Statement":[{
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "SNS:Publish",
"Resource": "arn:aws:sns:us-east-1:1223445555:Test",
"Condition":{
"ArnLike":{"aws:SourceArn":"${aws_s3_bucket.s3-bucket.arn}"}
}
}]
}
POLICY
}
Hope that helps.
Well, I know that this is not your exact case, but I had the same error and I didn't manage to find an answer here, and because this post is the first that Google gave me, I will leave the answer to my case here in the hope that it will help someone else.
So, I notice that after Terraform apply I had this error and I went to the UI to see what happened and found this message:
The Lambda console can't validate one or more event sources for this trigger. The most common cause is when a source ARN includes a wildcard (*) character. You can manage unvalidated triggers using the AWS CLI or AWS SDK.
And guess what? I really had a wildcard (*) character in ARN like this:
source_arn = "{aws_s3_bucket.bucket.arn}/*"
So I changed it to:
source_arn = aws_s3_bucket.bucket.arn
And it worked. So, if you read this - there might be the same mistake in your case.

Amazon S3 Access image by url

I have uploaded an image to Amazon S3 storage. But how can I access this image by url? I have made the folder and file public but still get AccessDenied error if try to access it by url https://s3.amazonaws.com/bucket/path/image.png
This is an older question, but for anybody who comes across this question, once I made the file public I was able to access my image as https://mybucket.s3.amazonaws.com/myfolder/afile.jpg
in my case i have uploaded image privately so that i was unable to access. i did following code
const AWS = require('aws-sdk')
const myBucket = 'BUCKET_NAME'
const myKey = 'FILE_NAME.JPG'
const signedUrlExpireSeconds = 60 * 1
const s3 = new AWS.S3({
accessKeyId: "ACCESS_KEY_ID",
signatureVersion: 'v4',
region: 'S3_REGION',
secretAccessKey: "ACCESS_SECRET"
});
const url = s3.getSignedUrl('getObject', {
Bucket: myBucket,
Key: myKey,
Expires: signedUrlExpireSeconds
})
console.log(url)
You can access your image by using:
https://s3.amazonaws.com/bucketname/foldername/imagename.jpg
or if there are no folders, you can do:
https://s3.amazonaws.com/bucketname/imagename.jpg
upvote if helps. It conforms to present AWS dated 30 may 2017.
Seems like you can now simply right-click on any folder inside a bucket and select 'Make Public' to make everything in that folder public. It may not work at the bucket level itself.
One of easiest way is to make a bucket policy.
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "MakeItPublic",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::yourbucketname.com/*"
}]
}
make sure you access image using the same case as it was uploaded and stored on S3.
for example, if you uploaded image_name.JPG, you should use the same name, but not image_name.jpg
For future reference, if you want to access a file in Amazon S3 the URL needs to be something like:
bucketname.s3.region.amazonaws.com/foldername/image.png
Example: my-awesome-bucket.s3.eu-central-1.amazonaws.com/media/img/dog.png
Don't forget to set the object to public.
Inside S3 if you click on the object will you see a field called: Object URL. That's the object's web address.
On your console, right click on the image you want to access and click on "Make Public"; when thats done right click on the image again and click on "Properties" and copy the Link from the Extended view.
I came across this question whilst looking for a solution to a similar problem with being unable to access images.
It turns out that images with a % in their filename, when being accessed, must have the % symbol URL encoded to %25.
i.e. photo%20of%20a%20banana%20-%2019%20june%202016.jpg needs to be accessed via photo%2520of%2520a%2520banana%2520-%252019%2520june%25202016.jpg.
However, URL encoding the full path didn't work for us, since the slashes, etc would be encoded, and the path would not work. In our specific case, simply replacing % with %25 in all access paths made the difference.
I was having the same problem. I have the issue the spacing in image url. I did this to make it work:
String imgUrl=prizes.get(position).getImagePreview().replaceAll("\\s","%20");
now pass this url to picasso:
Picasso.with(mContext)
.load(imgUrl)
.into(mImageView);
Just add Permission to follow the below image.
To access private images via URL you must provide Query-string authentication. Query-string authentication version 4 requires the X-Amz-Algorithm, X-Amz-Credential, X-Amz-Signature, X-Amz-Date, X-Amz-SignedHeaders, and X-Amz-Expires parameters.
Just addon to #akotian answer, you can get the object URL by clicking the object as follows
and to access publically you can set the ACL programmatically while uploading the object to the bucket
i.e sample java request
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.contentType(contentType)
.bucket(LOGO_BUCKET_NAME)
.key(LOGO_FOLDER_PREFIX+fileName)
.acl(ObjectCannedACL.PUBLIC_READ)// this make public read
.metadata(metadata)
.build();
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
]
}
]
}
use this policy for that bucket, which makes it public.
Adding bucket policy worked for me
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::yourbucketname/*"
}
]
}
Turn off Block public access (bucket settings) from Permissions tab inside your bucket. You also need to Edit the permissions of the object. Provide Read access on Grantee Everyone (public access). Then chech "I understand the effects of these changes on this object." and Save changes.
Change your Bucket.. It may works