0

I am trying to call AWS S3 DeleteObjects REST API from Apex. I am able to successfully perform this operation in Postman using their Sig4 Auth tool but I am struggling to get this working in Apex.

I have tried a few different approaches,

1.) using Named Credentials (Focus of this question)

2.) using sfdcfox's AWS class (referenced in the answer here.)

For both of these approaches I was able to get basic GET and PUT functionality working but the POST seems to require a different approach. This question is focused on the Named Credential approach as I feel it will be the simplest solution. If I am unable to do this using Named Credentials, I will ask a separate question with more details on approach #2.

This POST method requires a content-MD5 header which is generated from the body of the request. By default, the AWS Sig4 Named Credential does not have this header when working in Apex. After I set the body, I generate the content-md5 header, add it to the request, and send the request. This generates an error saying the following:

There were headers present in the request which were not signed

Here is the code performing the callout:

    HttpRequest req = new HttpRequest();
    String body = '<Delete ><Object><Key>test.png</Key></Object><Object><Key>test1.png</Key></Object></Delete>';
    Blob targetBlob = Blob.valueOf(body);
    Blob md5checksum = Crypto.generateDigest('MD5',targetBlob);
    string ContentMD5 = EncodingUtil.base64Encode(md5checksum);
    
    req.setMethod('POST');
    
    req.setBody(body);
    req.setHeader('content-md5', ContentMD5);
    req.setEndpoint('callout:aws/?delete');
    
    Http http = new Http();
    HTTPResponse res = http.send(req);
    system.debug(res.getBody());

Here is a screenshot of the Named Credential config:

AWS NC

3
  • This could be an AWS-side issue, see stackoverflow.com/questions/52667434/… for a related discussion. On SF side, there are 2 issues with your example: trailing slash in the URL in Named Credential and that MD5 header is clearly a no go. Named Creds inserts all necessary headers. Your body (XML) is malformed: there's a space in <Delete > and required XML namespace is missing from the <Delete> element. The bad XML would have resulted in a different error, you didn't get that far.
    – identigral
    Dec 6, 2022 at 5:29
  • @identigral I worked through all your comments and still no luck. I am hesitant to believe it is a Policy issue as I am able to perform the operation from Postman with the same credentials. I tried removing the '/' from NC and there was no change in error message. Without adding the setHeader for content-md5 I am getting an error saying the header is not present and required. This is after removing the white space in the xml (which also was not an issue in Postman.)
    – Rory
    Dec 6, 2022 at 15:41
  • Cheers for trying, see answer.
    – identigral
    Dec 6, 2022 at 19:35

1 Answer 1

0

AWS S3 REST API allows one to delete a single or multiple objects via DeleteObject or DeleteObjects API call respectively. DeleteObjects requires Content-MD5 header. S3 uses the value of this header to ensure that your request body has not been altered in transit. This is an "extra" header that is not required by DeleteObject. Content-MD5 is also not required for a number of other typical API calls to S3 such as listing the contents of the bucket or adding an object.

Named Credentials does not emit Content-MD5 header. We've tried this on both legacy and current External Cred-linked flavor of the Named Credential. Speaking with Product Management team, we've been told this is working as designed, it's the expected outcome.

If you don't have many objects to delete, a workaround is to grab the object keys, then delete them one at a time via DeleteObject:

String key = 'TestObject.txt';
HttpRequest request = new HttpRequest();
request.setMethod('DELETE');
request.setEndpoint('callout:aws/' + key);
Http http = new Http();
HTTPResponse res = http.send(request);
Assert.areEqual(204,res.getStatusCode()); 

Note: DeleteObject responds with 204 even if the target object doesn't exist.

1
  • 1
    Thank you for the info. I will use the delete as a last resort. The function I had in mind would process hundreds of records at once so a single delete operation is not ideal. I am going to try to accomplish this without Named Credentials (option 2 in my post)
    – Rory
    Dec 6, 2022 at 22:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .