Reputation: 101
Cloudfront supports signed cookies for serving up private content but I cant find any examples on how to do this.
I have found examples on how to sign URLs with the Java AWS API but not Cookies, can someone please share their experiences with doing this and is this the best way to secure multiple forms of media being served from CloudFront.
Our site has images and video that are uploaded by the user, which can then be viewed by searches on our site, I want to make sure that these images can only be served by our site and not copied for later use.
Upvotes: 6
Views: 3524
Reputation: 690
In AWS JAVA SDK version 1.10.73 introduced class CloudFrontCookieSigner for Signed Cookies with custom policies. Using this class and methods we can generate cookies.
CloudFront-Key-Pair-Id
Note that Java only supports SSL certificates in DER format,so you will need to convert your PEM-formatted file to DER format.
To do this, you can use openssl:
Command to Generate .der File from .pem
openssl pkcs8 -topk8 -nocrypt -in origin.pem -inform PEM -out new.der -outform DER
Reference:- http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CFPrivateDistJavaDevelopment.html
String privateKeyFilecdr = "/home/ec2-user/cookie.der";
String distributionDomain = "xxxxxxxx.cloudfront.net";
String s3ObjectKey = "signed-cookie.png";
String distributionid = "X4X4X4Y5Y5"; //Cloud Front Distribution id
String KeyFileId = "MPSIKFGHLMNSTOP" //AWS PEM KEY FILE ID
Date expiresOn = DateUtils.parseISO8601Date("2012-11-14T22:20:00.000Z");
String policyResourcePath = "https://" + distributionDomain + "/" + s3ObjectKey;
File privateKeyFile = new File(privateKeyFilecdr);
CookiesForCannedPolicy cookies = null;
try {
cookies = CloudFrontCookieSigner.getCookiesForCannedPolicy(policyResourcePath, KeyFileId, privateKeyFile, expiresOn);
// @SuppressWarnings({ "resource", "deprecation" })
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(SignerUtils.generateResourcePath(Protocol.https, distributionDomain,
s3ObjectKey));
httpGet.addHeader("Cookie", cookies.getExpires().getKey() + "=" +
cookies.getExpires().getValue());
httpGet.addHeader("Cookie", cookies.getSignature().getKey() + "=" +
cookies.getSignature().getValue());
httpGet.addHeader("Cookie", cookies.getKeyPairId().getKey() + "=" +
cookies.getKeyPairId().getValue());
HttpResponse responsevalues = client.execute(httpGet);
// System.out.println(responsevalues);
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Upvotes: 2
Reputation: 71
We were able to introduce signed cookies with custom policies using this library
You need three cookies created by your app as described here http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-custom-policy.html
Please read that carefully. Especially the part on how to create a policy.
The three cookies are:
First create a policy
Date expirationTime = (new LocalDate()).plusYears(1).toDate();
String customPolicy = CloudFrontService.buildPolicyForSignedUrl(basePath, expirationTime, null, null);
//and assign it to a cookie
Cookie signedCookiePolicy = new Cookie("CloudFront-Policy", ServiceUtils.toBase64(customPolicy.getBytes()));
signedCookiePolicy.setMaxAge(365 * 24 * 60 * 60);
signedCookiePolicy.setPath("/");
response.addCookie(signedCookiePolicy);
The signature is the tricky part but all tools are available once you use this jets3t thing
byte[] signatureBytes = EncryptionUtil.signWithRsaSha1(getDerPrivateKey(), customPolicy.getBytes("UTF-8"));
String signature = ServiceUtils.toBase64(signatureBytes).replace('+', '-').replace('=', '_').replace('/', '~');
Cookie signedCookieSignagture = new Cookie("CloudFront-Signature",cdnSignService.signBaseUrl(basePath, expirationTime));
signedCookieSignagture.setMaxAge(365 * 24 * 60 * 60);
signedCookieSignagture.setPath("/");
response.addCookie(signedCookieSignagture);
The third cookie only holds the key-id of your AWS account.
Cookie signedCookieKeyPairId = new Cookie("CloudFront-Key-Pair-Id","YOUR_AWS_CF_KEY_ID");
signedCookieKeyPairId.setMaxAge(365 * 24 * 60 * 60);
signedCookieKeyPairId.setPath("/");
response.addCookie(signedCookieKeyPairId);
The above only introduces you to concepts of using the correct libs to create the signed cookies. Its not executable or runnable on its own.
Be nice, its my first overflow contribution..
Upvotes: 7