S3 and CloudFront signed URLs both solve the same problem: You have a resource that you want to keep private (i.e. no anonymous access), but you still want to make it available to a select set of users, for example, subscribers to your site. And you want all this utilizing Amazon's infrastructure and not streaming large files through your backend.
Both kinds of signed URLs work the same. You give access to the protected resource by signing a URL and while doing so, you decide if you want the requesting user to have access to it. The content itself is then served by S3 or CloudFront directly.
But while they are used for the same purpose, from a technological perspective they are radically different.
Let's see some of these differences, so you'll have an easier time when you need to choose between them.
What they actually do
In CloudFront, a signed URL allow access to a path. Therefore, if the user has a valid signature, he can access it, no matter the origin.
In S3, a signed URL issue a request as the signer user. When you sign a request, you need to provide IAM credentials, so accessing a signed URL has the same effect as that user would have done it.
Who can sign a request
In CloudFront, the signing uses an account-wide key pair, which only the root user can manage.
In S3, the signing uses the access keys of an IAM user.
How to revoke a signed URL
In CloudFront, you need to distrust the key pair used for signing. You can do it either by removing that from the account, or removing the account itself from the Trusted Signers list of the distribution.
In S3, you need to revoke the permission from the signer user. You can do it either by removing the access keys from the user or by removing its access to the object.
How is expiration defined in the URL
In CloudFront, the expiration is part of the policy, in the DateLessThan section. It is defined in absolute terms, in ms from the epoch.
In S3, the X-AMZ-Date contains the timestamp of the signing, and the expiration itself is relative to this, in the X-AMZ-Expires, which is in seconds.
What can be set for the URL
In CloudFront, besides the expiration, you can also set these parameters:
- the DateGreaterThan field, which is an "effective date" of the URL
- an IP, which is an IPv4 CIDR block that can further limit the access
- and the path, which can also contain wildcards, that might be useful for signed cookies
In S3, you can only set the bucket and the object keys.
How to rotate the keys
Key rotation is almost the same for the two solutions, the only difference is how you add new credentials.
In CloudFront, to rotate the keys:
- Using the root user, add a new key pair
- Update the backend to use the new key pair
- Wait until the expiration
- Remove the old key pair
This process requires the root user, and can not be automated.
- Generate a new access key for the IAM user
- Update the backend to use the new credentials
- Wait until the expiration
- Remove the old access keys
It only requires access to the IAM user and this process can be automated.
What is the granularity of the signers
In CloudFront, you can define accounts whose keys are accepted. If you need a key pair that only allows access to one protected path, you need a separate account.
In S3, the granularity is the IAM user. You can use different users for different buckets or even for a subset of objects.
What kind of access can be controlled
In CloudFront, you control access to a path, so that any origin is supported. You can protect not just static files, but also API Gateways, and custom origins.
In S3, you can only control access to S3 objects.
Which one to use
As when there are multiple approaches to the same problem, an obvious question arises: which one to choose?
As a rule of thumb, if the content is stored in S3 then opt for S3 signed URLs as they provide the greatest flexibility.
If you need to serve a lot of files and want to take advantage of the request multiplexing of HTTP/2, tunnel S3 signed URLs through CloudFront.
If you need to protect custom origins, and you have no way of circumventing it, then use CloudFront signed URLs.