Created
May 1, 2018 18:38
-
-
Save dcinzona/ad6d5aab61008694135dcf8255f1b873 to your computer and use it in GitHub Desktop.
Salesforce Apex AWS S3 Signature Helper class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by gtandeciarz on 12/14/16. | |
*/ | |
public class AWS_Helper { | |
public string secret { get; set; } | |
public string key { get; set; } | |
public string bucket {get;set;} | |
public String endpoint_x = 'https://s3.amazonaws.com/'; | |
public Integer version = 2; | |
public static AWS_Setting__c settings; | |
static { | |
settings = AWS_Setting__c.getInstance('CaseAttachments'); | |
} | |
public AWS_Helper() { | |
this.secret = AWS_Helper.settings.Access_Secret__c; | |
this.key = AWS_Helper.settings.Access_Key__c; | |
this.bucket = AWS_Helper.settings.Bucket__c; | |
} | |
public AWS_Helper(Integer versionInt) { | |
this.secret = AWS_Helper.settings.Access_Secret__c; | |
this.key = AWS_Helper.settings.Access_Key__c; | |
this.bucket = AWS_Helper.settings.Bucket__c; | |
this.version = versionInt; | |
} | |
public Blob createCanonicalRequest(String method, String queryString, Map<String, String> headers, String payload) { | |
String canonicalRequest = method + '\n'; | |
canonicalRequest += '/' + '\n'; | |
canonicalRequest += queryString + '\n'; | |
List<String> headersList = new List<String>(headers.keySet()); | |
headersList.sort(); | |
for (String header : headersList) { | |
String headerContent = header.toLowerCase() + ':' + headers.get(header).trim(); | |
canonicalRequest += headerContent + '\n'; | |
} | |
for (String header : headersList) { | |
canonicalRequest += header.toLowerCase() + ';'; | |
} | |
canonicalRequest = canonicalRequest.removeEnd(';'); | |
canonicalRequest += '\n'; | |
canonicalRequest += EncodingUtil.convertToHex(Crypto.generateDigest('SHA256', Blob.valueOf(payload))).toLowerCase(); | |
return Crypto.generateDigest('SHA256', Blob.valueOf(canonicalRequest)); | |
} | |
public String getStringToSignV4(Blob canonicalRequest, Datetime requestdate, String region, String service) { | |
String stringToSign = 'AWS4-HMAC-SHA256' + '\n'; | |
String formatedDate = requestdate.formatGmt('yyyyMMdd') + 'T' + requestdate.formatGmt('hhmmss') + 'Z'; | |
stringToSign += formatedDate + '\n'; | |
stringToSign += requestdate.formatGmt('yyyyMMdd') + '/' + region + '/' + service + '/aws4_request\n'; | |
//stringToSign += String.valueOf(canonicalRequest); | |
// stringToSign += EncodingUtil.base64Encode(canonicalRequest); COMMENTED OUT THIS LINE AND REPLACED WITH THE ONE BELOW | |
stringToSign += EncodingUtil.convertToHex(Crypto.generateDigest('SHA-256', canonicalRequest)); | |
return stringToSign; | |
} | |
public String signatureV4(String secret, String today, String region, String service, String stringToSign) { | |
Blob privateKey = Crypto.generateMac('HmacSHA256', Crypto.generateMac('HmacSHA256', Crypto.generateMac('HmacSHA256', Crypto.generateMac('HmacSHA256', | |
Blob.valueOf(today), Blob.valueOf('AWS4' + secret)), | |
Blob.valueOf(region)), | |
Blob.valueOf(service)), | |
Blob.valueOf('aws4_request')); | |
return EncodingUtil.convertToHex(Crypto.generateMac('HmacSHA256', Blob.valueOf(stringToSign), privateKey)); | |
} | |
public static string GetSigningSignatureV2(string stringToSign, string key){ | |
Blob mac = Crypto.generateMac('HMACSHA1', blob.valueOf(stringToSign), blob.valueof(key)); | |
String signed = EncodingUtil.base64Encode(mac); | |
return signed; | |
} | |
public String GetAuthHeaderStringV2(String stringToSign){ | |
return 'AWS' + ' ' + this.key + ':' + AWS_Helper.GetSigningSignatureV2(stringToSign, this.secret); | |
} | |
public HttpRequest generateHttpRequest(Attachment a, String fileName){ | |
return this.generateHttpRequest(a.Name, a.contentType,a.Body,fileName); | |
} | |
public HttpRequest generateHttpRequest(String attachmentName, string attachmentContentType, Blob body, String fileName){ | |
string extension = '.' + attachmentName.substringAfterLast('.'); | |
String contentType = attachmentContentType == null ? 'binary/octet-stream' : attachmentContentType; | |
System.debug('extension: ' + extension); | |
System.debug('Filename: ' + fileName); | |
String attachmentBody = EncodingUtil.base64Encode(body); | |
String formattedDateString = DateTime.now().formatGMT('EEE, dd MMM yyyy HH:mm:ss z');// + '+0000'; | |
String bucketname = this.bucket;//you can write the bucket name where files should be uploaded | |
String host = 's3.amazonaws.com';//aws server base url'https://s3.amazonaws.com/'+bucketName+'/'+uploadedFilename | |
String method = 'PUT'; | |
String endpointUrl = 'https://' + host + '/' + bucketname + '/' + filename; | |
//endpointUrl = 'https://' + bucketname + '.' + host + '/' + filename; | |
HttpRequest req = new HttpRequest(); | |
req.setMethod(method); | |
req.setEndpoint(endpointUrl); | |
//host = bucketname + '.' + host; | |
//req.setHeader('Host', host); | |
req.setHeader('Content-Length', String.valueOf(attachmentBody.length())); | |
req.setHeader('Content-Type', contentType); | |
req.setHeader('Connection', 'keep-alive'); | |
req.setHeader('Date', formattedDateString); | |
req.setHeader('x-amz-server-side-encryption', 'AES256'); | |
req.setHeader('ACL', 'public-read'); | |
Blob blobBody = EncodingUtil.base64Decode(attachmentBody); | |
req.setBodyAsBlob(blobBody); | |
String stringToSign = method+'\n\n' | |
+ contentType + '\n' | |
+ formattedDateString + '\n' | |
+ 'x-amz-server-side-encryption:AES256\n' | |
+ '/' + bucketname | |
+ '/' | |
+ filename; | |
System.debug(stringToSign); | |
System.debug('key: ' + this.key); | |
System.debug('secret: ' + this.secret); | |
req.setHeader('Authorization', GetAuthHeaderStringV2(stringToSign)); | |
return req; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment