After a bit of a break and a rethink here is where I was going wrong. It isn't possible to have some content secured and other not secured in the same distribution. Either a whole distribution is secured or not. Here is my solution.
- Setup a new bucket for your secure items in AWS
- Add a new distribution in Cloudfront pointing to the new bucket created in 1 and choose Yes for 'Restrict Viewer Access' and 'Yes' for 'Forward Query Strings' (this is only to add the ability to add content disposition to specific downloads) and choose 'Self' for 'Trusted Signers'
- At the top of AWS click on your name and choose 'Security Credentials' and choose 'Continue' as we chose 'Self' above.
- Click on 'CloudFront Key Pairs' and choose 'Create New Key Pair'. Download the key files when offered (they won't be offered again), you need the private key. Also copy the Access Key ID as you'll need that.
- Go to your distributions, click on the i next to the secure distribution, click on the origins tab, click 'create origin' or select the origin and choose Edit then choose 'Yes' for Restrict Bucket Access, Create a New Identity and Yes Update Bucket Policy. This essentially means that Cloudfront can authenticate against your bucket.
- In your project go to NuGet and search for 'AWS' and install the AWS SDK.
- Copy the private key file (pk***.pem) to a folder above your website root (or somewhere relatively private)
- Add some code as per the following to generate a secure URL with a Content Disposition header.
I have to say that I couldn't have solved this without the help of Torsten's post on https://forums.aws.amazon.com/thread.jspa?messageID=421768 which is in PHP but pointed me in the right direction:
string cloudFrontKeyPairID = "myaccesskeyidfrompoint4";
string pathtokey = HttpContext.Current.Request.MapPath("~/").Replace("wwwroot", "ssl") + "pk-mykeyidfilenamesavedin4.pem";
FileInfo privateKey = new FileInfo(pathtokey);
string file = "folder/mytrack.mp3?response-content-disposition=" +
HttpContext.Current.Server.UrlEncode("attachment;filename='a_filename_with_no_spaces.mp3'");
//I can't figure out how to do spaces or odd characters.
url = AmazonCloudFrontUrlSigner.GetCannedSignedURL(
AmazonCloudFrontUrlSigner.Protocol.http,
"customcname.mydomain.com",
privateKey,
file,
cloudFrontKeyPairID,
DateTime.Now.AddDays(2));
I hope that helps someone, I will be using this as a personal resource anyway! Enabling the Origin Access Identity on an existing bucket which doesn't have 'Restrict Viewer Access' set it essentially opens up permissions for all items on your bucket. This may or may not be desirable! If I have anything wrong please let me know, this is all pretty new to me.