1
votes

Any help would be appreciated please, I am fairly new to Amazon CloudFront but I will tell you what I have done so far. I have a CloudFront distribution that displays content from an S3 Bucket and I have stopped access from the browser to the S3 bucket.

I have associated the CF Behaviour to a Lambda function, where I am re-routing the request URI to the S3 Bucket location so the end user doesn't know where on the S3 bucket the location is. Everything is working absolutely fine, so I then moved to what I wanted to achieve next:

  • Using KMS encryption on the PHP level encrypt the CF request URI
  • Using Lambda function decrypt in NodeJS the request URI and re-route it to S3 bucket location

Again, the above two points are working absolutely fine when testing the Lambda function and checking the CloudWatch Logs. I am now facing a problem viewing it from the browser as it keeps giving me a 404 error, but the logs are saying the function is working when testing.

How the URLs are displayed:

I am just wondering if anyone else has came across this problem in the past, or does CF allow for encrypted URLs to be requested from the browser? From research, I have gathered that Amazon offer a service called API Gateway, do I have to use the API Gateway to achieve this?

Apologies, if I have wrote a lot to describe my problem and I would really appreciate any help please.

Code Snippet:

'use strict';

var AWS = require('aws-sdk');
var kms = new AWS.KMS();

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const uri_orig = request.uri;

    if( request.uri.match('/documents_property/') ){
        decryptValue( request, uri_orig.replace('/documents_property/', '') , 'UpLoaDs/documents/property/', callback );
        return;
    }

    if( request.uri.match('/inspection_report/') ){
        request.uri = uri_orig.replace('/inspection_report/', 'UpLoaDs/files/inspection/');
    }

    callback(null, request);
};

function decryptValue( request, encrypted, destination_path, callback ){
    encrypted = unescape(encrypted);

    kms.decrypt({CiphertextBlob: new Buffer(encrypted, 'base64')}, (err, data) => {
        if( err ){
            console.log('Decrypt error:', err);
            return callback(err);
        }

        var decrypted = data.Plaintext.toString('ascii');
        request.uri = destination_path + decrypted;
        callback(null, request);
    });
}
1

1 Answers

1
votes

I have done that before and ran into the same issue.

lfjeroqgo2747453/shuh+sdkfjirogvoniuhreg3974 -- If you notice the / in the url, it is treated as a different section of the path. You need to do a URL Encode and do a URL decode and perform decryption.

The encrypted string contains / that causes the issue. Also when you decrypt you can check for the result of decryption to be the expected filename. If it is not, print the string before decryption and after encryption to make sure they are same when feeding it to the application.

Hope this helps.