Amazon cloudfront. Usage of Trusted Signers - amazon-web-services

We are using cloudfront for serving s3 resource and it is restricted.
In c#, while creating the presigned url using the "AmazonCloudFrontUrlSigner.SignUrlCanned" it does ask only for the cloudfront private key generated using the root credentials and doesn't ask for IAM user credentials.
In the distribution behavior, I can see there is an option to specify the "Trusted Signers" but not able to understand where it is being used. Any info on this would be great. Also is there a way to generate presigned cloudfront url using the IAM user credentials?

CloudFront does not support the use IAM credentials for generating signed URLs, nor does it use the signing algorithms common to other AWS services.
The process is, however, fully documented. CloudFront has its own method for accessing private objects in S3 on behalf of your users -- the origin access identity -- and will use this mechanism transparently when presented with a signed URL or signed cookies, generated using a keypair associated with a trusted signer.
See Serving Private Content through CloudFront for descriptions of the mechanisms and configuration walk-throughs.

Cloudfront does use IAM to generate signed urls. In distribution there is configuration for Trusted Signers where you can add other accounts ID in order to allow those accounts to generate signed urls. It means trusted signer can use there own generated keypair to sign a url of the distribution.
Any trusted signer that you configure for your CloudFront distribution will need to set up their own CloudFront key pair for their account in order to sign requests for your CloudFront private content Reference
This keypair is associated with account and it can have only max one active keypair at any point of the time

Related

Give access to specific user to files in private s3 bucket

I have a s3 bucket that is private and I want specific user to have access to some objects in this bucket. What is the correct way to do that?
For individuals objects, you should use Pre-signed URL.
It allows the user who access the URL to issue a request as the person who pre-signed the URL (inheriting the permissions of the IAM user that generated the URL). It can be generated with SDK or CLI. It is valid for 3600s by default, but you can change this duration.
https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html
For multiple objetcs (if you want a path with wildcard), you can use Signed cookies. It need you to first implements a CloudFront distribution in front of you s3 bucket.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
CloudFront also allow to provide Signed URLs, which are different from S3 Presigned-URL: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html

How to hide AWS S3 Bucket URL with custom CNAME

I want to connect CDN to an AWS S3 Bucket, but the AWS Document indicates that the bucket name must be the same as the CNAME. Therefore, it is very easy to guess the real s3 bucket url by others.
For example,
- My domain: example.com
- My S3 Bucket name: image.example.com
- My CDN CNAME(image.example.com) will point to image.example.com.s3.amazonaws.com
After that, people can access the CDN URL -> http://image.example.com to obtain the resources from my S3 Bucket. However, under this restriction, people can guess my real S3 bucket url from the CNAME (CNAME + s3.amazonaws.com) easily.
So, my question is that how can I hide my real s3 bucket url? Because I don't want to expose my real S3 url to anyone for preventing any attacks.
I am not sure I understand what you are asking for or what you are trying to do [hiding your bucket does not really help anything], however I will attempt to answer your question regarding "hiding" your bucket name. Before I answer, I would like to ask these two questions:
Why do you want to hide your S3 bucket url?
What kind of attacks are you trying to prevent?
You are correct that the S3 bucket name had to be the same as your URL. This is no longer a requirement as you can mask the S3 bucket using cloudfront. CloudFront as you know is a CDN from AWS. Thus the bucket name could be anything (randomstring).
You can restrict access to the bucket, such that only CloudFront can access it. Data in the bucket is then replicated to edge locations and served from there. Even if one knows the S3 URL, it will not do anything as access to the s3 bucket is restricted, an IAM rule grants CloudFront access and no one else.
Access restriction is done via origin access and while you can manually configure this using a bucket policy, you can also set a flag in CloudFront to do this on your behalf. More information is available here.
Use the CloudFront name in Route53. Do not use CNAME, but rather use A type, and set it up as an Alias. For more information see this document.
If you are using a different DNS provider, AWS aliases will naturally not be available. I suggest moving the zone file from your other provider to AWS. If you cannot do this, then you can still use a CNAME. Again see here for more information.
I suggest using your own domain name for CloudFront and setting up HTTPS. AWS offers certificates at no additional cost for services within AWS. You can register a certificate for your domain name which is either validated by a DNS entry or an Email. To set this up please see this document.
If you want to restrict access to specific files within AWS, you can use signed URLs. More information about that is provided here.

How to create session token for my file on AWS S3 if it connected to other CDN provider?

I have some video file stored on AWS S3 and I want to secure these files by adding session token with specific expiry time on the video URLs for preventing unauthorized access.
I know the s3 SDK can generate temporary credentials with Cloudfront to achieve this.
However, if I connected S3 to other CDN provider such as cloudflare. Will these temporary credentials work perfectly?
For example, my video file is stored on s3 -> http://files.video.com.s3.amazonaws.com/video.mp4
The cloudflare cdn url is -> http://files.video.com/video.mp4
If i generated temporary credentials for the file and access the url -> http://files.video.com/video.mp4?token=4180da90a6973bc8bd801bfe49f04a&expirey=1526231040535
Will it work?
It sounds like you're referring to S3 Presigned URLs. No, if your S3 bucket is private, CloudFlare will not be able to generate presigned URLs to access your files. AWS CloudFront uses an Origin Access Identity to resolve this issue. However with 3rd party CDNs, this is not possible.
There are 2 ways you could achieve better security (source).
Make your bucket public but restrict the allowed IPs for your S3 bucket to only CloudFlare IPs.
Make your bucket private and use CloudFlare workers to authorize its GET requests

Relationship between Origin Access Identities (OAIs) and CloudFront Signed URLs

So I've been following guides on CloudFront and S3 and I feel like I am still missing a core piece of information in the relationship between Origin Access Identities (OAIs) and CloudFront Signed URLs.
What I want: a private CDN to host audio snippets (of a few seconds in length) and low-resolution images. I only want these files to be accessible when requested from a specific domain (i.e. the domain the web app will live on) and maybe a testing server, so that my web app can get the files but anyone else just can't access them without going through the web app.
What I'm confused about: I'm fuzzy on the relationship (if there is any) between CloudFront Origin Access Identities (OAIs) and Signed CloudFront URLs.
I have currently created a private S3 bucket, an OAI for my CloudFront distribution, and have generated a signed URL to an image through CloudFront. But I don't see how these things are related and how they prevent someone else from accessing CDN files (e.g. if they were able to inspect an element and get the signed URL).
Is the whole point to make sure the signed URLs expire quickly? And if so, how does the OAI play a role in it? Is this something set in CORS?
An origin access identity is an entity inside CloudFront that
can be authorized by bucket policy to access objects in a bucket. When CloudFront uses an origin access identity to access content in a bucket, CloudFront uses the OAI's credentials to generate a signed request that it sends to the bucket to fetch the content. This signature is not accessible to the viewer.
The meaning of the word "origin" as used here should not be confused with the word "origin" as used in other contexts, such as CORS, where "origin" refers to the site that is allowed to access the content.
The origin access identity has nothing to do with access being restricted to requests containing a specific Origin or Referer header.
Once a signed URL is validated by CloudFront as matching a CloudFront signing key associated with your AWS account (or another account that you designate as a trusted signer) the object is fetched from the bucket, using whatever permissions the origin access identity has been granted at the bucket.
Is the whole point to make sure the signed url's expire quickly?
Essentially, yes.
Authentication and Authorization of requests by trying to restrict access based on the site where the link was found is not a viable security measure. It prevents hot-linking from other sites, but does nothing to protect against anyone who can forge request headers. Defeating a measure like that is trivial.
Signed URLs, by contrast, are extremely tamper resistant to the point of computational infeasibility.
A signed URL is not only valid only until it expires, but can optionally also restrict access to a person having the same IP address that's included in the policy document, if you use a custom policy. Once signed, any change to the URL, including the policy statement, makes the entire URL unusable.
The OAI is only indirectly connected with CloudFront signed URLs -- they can be used individually, or together -- but without an OAI, CloudFront has no way to prove that it is authorized to request objects from your bucket, so the bucket would need to be public, which would defeat much of the purpose of signed URLs on CloudFront.
Add a new CNAME entry that points to your CloudFront domain. This entry should match that entered in the ‘Alternate Domain Names’ from within the CloudFront console.
By default CloudFront generate Domain name automatically (eg d3i29vunzqzxrt.cloudfront.net) but you can define your alternative domain name.
Also you can secure Cloudfront
Serving Private Content through CloudFront

How to disable Amazon S3 raw endpoint access

Say you want to host a static web site on S3 :
You create a bucket with name your-website.com and set it up for web hosting;
You add a CNAME in your domain's zone file to point to your S3 bucket.
Great. Everything works fine when you visit http://your-website.com. But you don't want the raw/"naked" endpoint to be accessible.
Is there any setting in the bucket to disable direct access to http://your-website.com.s3-website.your-region.amazonaws.com ?
The reason is that if your web site is accessible both through http://your-website.com and http://your-website.com.s3-website.your-region.amazonaws.com would hurt your SEO (duplicate content)
You mention your major concern is SEO. For that purpose, you could use a other techniques, that are probably easier to implement than the one you initially asked about.
One of the main techniques to deal with duplicate content is to use rel=canonical, which is probably fairly easy to implement. For more information, see http://googlewebmastercentral.blogspot.com.br/2013/04/5-common-mistakes-with-relcanonical.html
If you insist on the need to disable access to the bucket unless the client connects through your CNAME, your best bet is to use CloudFront. You disable the S3 website hosting option on your bucket, make your S3 bucket private (i.e., remove bucket policies or ACLs allowing public read), create a CloudFront distribution, define your bucket as the origin, configure a CNAME on your distribution, change your DNS records to point to your distribution instead of bucket, create an Origin Access Identity (OAI) on your distribution and grant access to your bucket for that OAI. Phew.
By doing all this, there's no way for a user to access the content on your S3 bucket (unless they have an AK/SK with permissions to read the bucket, and send a signed request, obviously). The only way will be through your domain.
For more detail on Origin Access Identity, see http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html