0

I'm building an integration with S3 and I want to create a pre-signed URL so I can access S3 from SF with a single user.

I use the method below to generate a URL:

public static string getSignedURL(string file, String bucketName, String accessKey, String secretKey, String state) {
    String filename = EncodingUtil.urlEncode(file, 'UTF-8');
    Datetime now = DateTime.now();
    Datetime expireson = now.AddSeconds(60);
    Long Lexpires = expireson.getTime() / 1000;

    String stringtosign = 'GET\n\n\n' + Lexpires + '\n/' + BucketName + '/' + filename;
    Blob mac = Crypto.generateMac('HMacSHA1', blob.valueof(stringtosign), blob.valueof(SecretKey));
    String signed = EncodingUtil.base64Encode(mac);
    String url = 'https://' + BucketName + '.s3.us-east-1.amazonaws.com/' + filename + '?AWSAccessKeyId=' + AccessKey + '&Expires=' + Lexpires + '&Signature=' + signed;
    return url;

}

The method works, but the downside as you can see is that I need to send my accessKey and secretKey and I wish to avoid that.

So I want to use a Named Credential to authenticate, and then I want to call my method getSignedURL(). But I don't know how I can pass the secret and key to the getSignedURL() method using a Named Credential.

I didn't find a merge field related to AWS Signature Version 4 in the documentation. I was hoping to find something like:

{!$Credential.acessKey}
{!$Credential.secretKey}
6
  • You don't need to do anything special - this works out of the box with a Named Credential and AWS v4 signature. Check the referenced answer and other links in that answer.
    – identigral
    Oct 11 '20 at 23:25
  • It doesn't answer the question, because I'm looking for a way to generate pre-signed urls without hard coding my credentials.
    – Json
    Oct 12 '20 at 10:46
  • Your requested approach amounts to the same outcome. You want Named Credentials to store key/secret and use the merge to inject them into your function. This doesn't work because it is unsafe from a security perspective...and you're still "hardcoding" the creds in NC.
    – identigral
    Oct 12 '20 at 18:41
  • Ok, maybe I wasn't clear, I meant not in my Apex code
    – Json
    Oct 12 '20 at 18:55
  • No matter how you go about this, the creds have to come from somewhere. Storing them in NC is your safest option.
    – identigral
    Oct 12 '20 at 18:57
3

There's no way to use Named Credentials this way. The Named Credentials system works a bit like a black box; you specify the Named Credential to use, and when you call http.send(), the Named Credential does its magic. Coincidentally, this also wouldn't work even for the username and password, as the merge fields are never completed in the HttpRequest object. The server can see the data, but you, the developer, cannot. This is a security feature. You'll want to read Secure Coding: Storing Secrets for methods that you can use. For example, you might store the information in Custom Metadata.

1

Not the answer you're looking for? Browse other questions tagged or ask your own question.