Signing a request to setup a custom Amazon CloudFront Distrubution with C#
I love most of Amazons Web Services (AWS). CloudFront is their CDN service and they have a awesome feature that lets you host your files on your own server and then Amazon automatically grabs the files from your server and put them on their CDN. This makes it possible to easily modify your files without having to download them from some S3 bucket or something to make changes.
Unfortunatley Amazon doesn’t provide a UI to set up a “Custom Distribution” so you have to do a post request to a URL and send them some XML. It’s maybe not that hard but i really think they could provide us with some simple page where you just paste some XML and sent the request. But you have to do it yourself. The only thing i had issues with was to sign the request and get your “encrypted” secret.
I found some code on Stack Overflow (as usually) and just made some small modification to it for doing a Cloud Front setup request.
public static void InvalidateContent() { string httpDate = Helper.GetHttpDate(); string AWSSecret = "YOUR SECRET"; string AWSAccessKeyId = "YOUR ACCESS KEY"; ASCIIEncoding encoding = new ASCIIEncoding(); string postData = @"<DistributionConfig xmlns='http://cloudfront.amazonaws.com/doc/2010-11-01/'> <CustomOrigin> <DNSName>dist.alternativeto.net</DNSName> <HTTPPort>80</HTTPPort> <HTTPSPort>443</HTTPSPort> <OriginProtocolPolicy>match-viewer</OriginProtocolPolicy> </CustomOrigin> <CallerReference>" + httpDate + @"</CallerReference> <CNAME>static.alternativeto.net</CNAME> <Comment>My comments</Comment> <Enabled>true</Enabled> <Logging> <Bucket>mylogs.s3.amazonaws.com</Bucket> <Prefix>myprefix/</Prefix> </Logging> </DistributionConfig>"; byte[] data = encoding.GetBytes(postData); // Prepare web request... HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://cloudfront.amazonaws.com/2010-11-01/distribution"); webRequest.Method = "POST"; webRequest.ContentType = "text/xml"; webRequest.Headers.Add("x-amz-date", httpDate); Encoding ae = new UTF8Encoding(); HMACSHA1 signature = new HMACSHA1(ae.GetBytes(AWSSecret.ToCharArray())); string b64 = Convert.ToBase64String(signature.ComputeHash(ae.GetBytes(webRequest.Headers["x-amz-date"].ToCharArray()))); webRequest.Headers.Add(HttpRequestHeader.Authorization, "AWS" + " " + AWSAccessKeyId + ":" + b64); webRequest.ContentLength = data.Length; Stream newStream = webRequest.GetRequestStream(); // Send the data. newStream.Write(data, 0, data.Length); newStream.Close(); } /// <summary> /// Gets a proper HTTP date /// </summary> public static string GetHttpDate() { // Setting the Culture will ensure we get a proper HTTP Date. string date = System.DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH:mm:ss ", System.Globalization.CultureInfo.InvariantCulture) + "GMT"; return date; }
For some reason, links to .mov files do not encrypt correctly. Can you review the code and see if there’s a simple fix you can post?
Thanks for the plugin.