function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Brice Mbouani 9Brice Mbouani 9 

AWS CloudFront Signed URL from APEX

I'm struggling to build a signed URL to access S3 object from CloudFront. When i test my signed url i've an access denied error message from AWS :
 
<Error>
     <Code>AccessDenied</Code>
     <Message>Access denied</Message>
    </Error>



I've (normally) followed all the steps provided by Amazon (https://docs.aws.amazon.com/fr_fr/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html) to configure a distribution and build a signed url :

 - I've created a cdn distribution
 - Configure an origin access identity (OAI) for this distribution
 - This OAI is configured to access my S3 object
 - Users can access my S3 objects only by using cloudfront URL.

Below is my S3 bucket policy :

 
{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "2",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity myawesomeOAI"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::myawesomebucket/*"
        }
    ]
   }

And of course my apex code :  
public class cloudFrontContentUriBuilder {
        final static String cloudFrontHost = 'myawesomecloudfront.cloudfront.net';
        final static String cloudFrontKeyPairId = 'cdnkeypairid';
        
        public static String getSignURL() {
            Blob privateKey = cfPrivateKey();
            String policy = cfPolicy('http://' + cloudFrontHost + '/' + s3ObjectEndpoint, expiry);            ResponseData responseData = new ResponseData();
            
            s3ObjectEndpoint = 'imageL.png';
            String method = 'GET';
                       
            try{
                Blob mac = Crypto.Sign(
                    'RSA-SHA1',
                    Blob.valueOf(rPolicy),
                    privateKey
                );
        
                String signature = cfReplace(EncodingUtil.base64Encode(mac));
        
                String u  = 'http://' + cloudFrontHost + '/' + s3ObjectEndpoint + '?Policy=' +
                    policyEnc + '&Signature=' + signature + '&Key-Pair-Id=' +
                    cloudFrontKeyPairId;
        
                Map<String, String> r = new Map<String, String>();
        
                r.put('url', u);
                responseData.results = r;    
                
            } catch (Exception e) {
                responseData.addError(e.getMessage());
            }

            return responseData.getJsonString();
        }
        

    }

Do you guys think i'm using the right way to build my signature?

Thanks a lot for your help! I've been spending days on this !
Justin Davis 11Justin Davis 11
Yeah that should work!
https://www.cloudcreations.com
Brice Mbouani 9Brice Mbouani 9
What do you mean by 'that should work' ? have you ever experienced this issue?
Thank  a lot!