+ Start a Discussion
Anil_VaishnavAnil_Vaishnav 

How to generate AWS cloudfront singed url in apex?

I am trying to generate AWS Cloudfront singed url using apex but every time get Access Denied.

public url is working fine. i.e. jueh890044563.cloudfront.net/test.pdf

But I need a singed url of cloudfront.

I have already done following things in AWS.

S3 bucket is private.
test.pdf is private.
Created cloudfront Distribution (domain name is : jueh890044563.cloudfront.net)

Apex code

String keyPairId = 'YTEHJLKFHHRKF';
Datetime now = DateTime.now();
Datetime expireson = now.addDays(2);
Long Lexpires = expireson.getTime()/1000;

String policyStatement = '{"Statement":[{"Resource":"jueh890044563.cloudfront.net/test.pdf","Condition":{"DateLessThan":{"AWS:EpochTime":'+Lexpires+'}}}]}';

policyStatement = EncodingUtil.base64Encode(Blob.valueOf(policyStatement));

String privateKey = 'dfgdfgtgdfgdfgdfsgdfgdfsgdfgdfgdfgsdf'+
'dfgdfgdfgdfgdfgdfgdfgdfgdfgfgdfgdfsdf'+
'dfdfgdfgdfgdfgdfgfdgdfg/i0AB1Jz20QlGy'+
'dsfgdfgdfgdfgdfgdfgdsfgdfgdfgffdfgdfg';

Blob mac = Crypto.generateMac('HmacSHA1', blob.valueof(policyStatement),blob.valueof(privateKey));
String signed = EncodingUtil.base64Encode(mac);

String downloadUrl = 'jueh890044563.cloudfront.net/test.pdf?Policy='+policyStatement+'&Signature='+signed+'&Key-Pair-Id='+keyPairId;

Is downloadUrl is singedUrl? When we run this url then return Access Denied.

Thanks in advance.
Dr. Thomas MillerDr. Thomas Miller
Hi Anil,

I am investigating the same. Have you been successful by now?
To separate SF domain from Amazon domain I would try to create the signed URL in UNIX shell or Java and compare the signatures. If they are the same then the problem is not on Salesforce side.
Dr. Thomas MillerDr. Thomas Miller
Here is code that works:

String keyPairId = 'AXXXXXXXXXXXXXXXXEFA';

String privateKey = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCds4huFsMlcqRJ'+
'InSvSsm1m3GoS4Lk/pBgN6hcU++ojh2iv00d9dQ0d3c1GMedNc+p3GvHas9IiWC1'+
'many more lines';
//this needs to come from a pkcs8 file

urlToSign = 'https://d3m1gol86ahpmn.cloudfront.net/sfroot/file.html;

policyStatementText = '{"Statement":[{"Resource":"' + urlToSign + '","Condition":{"DateLessThan":{"AWS:EpochTime":2000000000}}}]}';
String policyStatement = EncodingUtil.base64Encode(Blob.valueOf(policyStatementText ));
policyStatement = policyStatement .replace('+','-');
policyStatement = policyStatement .replace('=','_');
policyStatement = policyStatement .replace('/','~');

Blob mac = Crypto.sign('RSA-SHA1', blob.valueof(policyStatementText ),privateKeyBlob );
String signed = EncodingUtil.base64Encode(mac);


signed = signed.replace('+','-');
signed = signed.replace('=','_');
signed = signed.replace('/','~');

signedURL = urlToSign + '&Policy=' + policyStatement +  '&Signature=' + signed  + '&Key-Pair-Id=' + keyPairId ;

 
Brice Mbouani 9Brice Mbouani 9
Do you guys succeed to get your cdn signed url works from apex? i'm facing the same issue and i don't figure out how to make it work!!