Field notes #3

Securing our CDN

In my last post I talked about how Aevocam delivers feed photos to your browser very quickly using an S3-backed CDN. You might have wondered if that is insecure, since CDNs are designed to make content easy to access and cache. How was I going to prevent someone from simply guessing photo URLs and downloading images they weren't supposed to see?

The traditional answer would be to have a web service that checks some authentication token from the browser to see if that user has permission to view a requested photo. But that doesn't fit how CDNs work at all! If you want a CDN to be fast it has to be able to cache. Especially if it delivers the same content many times in a short time period. You want to have static URLs for assets as much as possible.

AWS CloudFront does provide a slick answer. You can create edge functions — little JavaScript programs — that run on the CloudFront server hosting your cached content. So I chose a stateless approach to this problem. My own app server generates a signed access policy and appends it to URLs for your camera feed's photos. The CDN server runs that edge function. It's a gatekeeper. If that digital signature is invalid then it rejects the request for the photo. And if the image requested does not fit the access control constraints then the request is also rejected. One cool thing about these signed specs is that they are time-limited. The app server needs to keep generating new ones periodically for the currently logged in user.

There's one subtle wrinkle. Because the tokens are time-limited, the URLs themselves have to change. Doesn't that defeat caching? Well, for your browser, it technically does. But not for the CDN. We've configured the CDN to ignore the signed query string when deciding whether it already has a cached copy of an image.

The result is secure. There's no real sacrifice to performance. It scales well, even with a modest app server. And even if a hacker were to somehow gain access to one of these valid URLs, they'd only have access for a very short time to the narrow slice of image content indicated by that access policy. If they looked at the browser history later, the URL would be useless to them. Another cool use of stateless cryptography.

< More field notes