• Doug (Wenchang) Liu
  • NEWBIE
  • 0 Points
  • Member since 2019

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 1
    Questions
  • 3
    Replies
Hi guys,

I'm trying to send a put request from salesforce to Amazon S3. Somehow, my code is always not working with following response:
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>

I'm hundred percent sure my key and credential is correct since it works on aws cli.

Could any one help me find the issue?
Here is the code:
 
try{
    AwsCredentialServices awsService = new AwsCredentialServices();
    // To get the stored key and secret
    SecurityInfo__c awsS3Info = awsService.getS3SecurityInfo();
    File__c imageFile = [
        SELECT Id, File_Url__c, RecordType.Name
        FROM File__c
        WHERE File_Url__c != null
        ORDER BY CreatedDate
        LIMIT 1
    ];
    String endpoint = imageFile.File_Url__c;
    String method = 'GET';
    Http httpLink=new Http();
    HttpRequest request=new HttpRequest();
    request.setMethod(method);
    request.setEndpoint(endpoint);
    request.setHeader('Authorization', awsS3Info.AWSKey__c);
    HTTPResponse res = httpLink.send(request);
    System.debug('Get Success: TEST');
    System.debug(res.getStatus());
    System.debug(res.getStatusCode());
    //System.debug(res.getBody());


    String host = 's3.amazonaws.com';
    String formattedDateString = Datetime.now().formatGMT('EEE, dd MMM yyyy HH:mm:ss z');
    System.debug(formattedDateString);
    String fileName = 'test001.png';
    method = 'PUT';
    request.setMethod(method);

    request.setEndpoint('https://' + awsS3Info.S3Bucket__c + '.' + host + '/' + fileName);//'test001.png'
    request.setHeader('Authorization', awsS3Info.AWSKey__c);
    request.setHeader('Content-type', 'image/png');
    request.setHeader('Content-Length', String.valueOf(res.getBody().length()));
    request.setHeader('Host', awsS3Info.S3Bucket__c + '.' + host);
    request.setHeader('Content-Encoding', 'UTF-8');
    request.setHeader('Connection', 'keep-alive');
    request.setHeader('Date', formattedDateString);
    request.setHeader('ACL', 'public-read');
    request.setBodyAsBlob(Blob.valueOf(res.getBody()));

    String stringToSign = 'PUT\n\n' +
                    'image/png\n' +
                    formattedDateString + '\n' +
                    '/' + awsS3Info.S3Bucket__c + fileName;
    String encodedStringToSign = EncodingUtil.urlEncode(stringToSign, 'UTF-8');
    //Blob mac = Crypto.generateMac('HMACSHA1', blob.valueof(stringToSign),blob.valueof(awsS3Info.Private_S3AWSSecurityToken__c));
    String signedKey  = EncodingUtil.base64Encode(
        Crypto.generateMac(
            'HMACSHA256',
            blob.valueof(encodedStringToSign),
            blob.valueof(awsS3Info.AWSSecurityToken__c)
        )
    );
    //String authHeader = 'AWS' + ' ' + awsS3Info.Private_S3AWSKey__c + ':' + signedKey ;
    String authHeader = 'AWS ' + awsS3Info.AWSKey__c + ':' + signedKey ;
    System.debug(authHeader);
    request.setHeader('Authorization', authHeader);

    res = httpLink.send(request);
    System.debug('Put Success: Response');
    System.debug(res.getStatus());
    System.debug(res.getStatusCode());
    System.debug(res.getBody());
} catch(Exception e){
    throw e;
}

 
Hi guys,

I'm trying to send a put request from salesforce to Amazon S3. Somehow, my code is always not working with following response:
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>

I'm hundred percent sure my key and credential is correct since it works on aws cli.

Could any one help me find the issue?
Here is the code:
 
try{
    AwsCredentialServices awsService = new AwsCredentialServices();
    // To get the stored key and secret
    SecurityInfo__c awsS3Info = awsService.getS3SecurityInfo();
    File__c imageFile = [
        SELECT Id, File_Url__c, RecordType.Name
        FROM File__c
        WHERE File_Url__c != null
        ORDER BY CreatedDate
        LIMIT 1
    ];
    String endpoint = imageFile.File_Url__c;
    String method = 'GET';
    Http httpLink=new Http();
    HttpRequest request=new HttpRequest();
    request.setMethod(method);
    request.setEndpoint(endpoint);
    request.setHeader('Authorization', awsS3Info.AWSKey__c);
    HTTPResponse res = httpLink.send(request);
    System.debug('Get Success: TEST');
    System.debug(res.getStatus());
    System.debug(res.getStatusCode());
    //System.debug(res.getBody());


    String host = 's3.amazonaws.com';
    String formattedDateString = Datetime.now().formatGMT('EEE, dd MMM yyyy HH:mm:ss z');
    System.debug(formattedDateString);
    String fileName = 'test001.png';
    method = 'PUT';
    request.setMethod(method);

    request.setEndpoint('https://' + awsS3Info.S3Bucket__c + '.' + host + '/' + fileName);//'test001.png'
    request.setHeader('Authorization', awsS3Info.AWSKey__c);
    request.setHeader('Content-type', 'image/png');
    request.setHeader('Content-Length', String.valueOf(res.getBody().length()));
    request.setHeader('Host', awsS3Info.S3Bucket__c + '.' + host);
    request.setHeader('Content-Encoding', 'UTF-8');
    request.setHeader('Connection', 'keep-alive');
    request.setHeader('Date', formattedDateString);
    request.setHeader('ACL', 'public-read');
    request.setBodyAsBlob(Blob.valueOf(res.getBody()));

    String stringToSign = 'PUT\n\n' +
                    'image/png\n' +
                    formattedDateString + '\n' +
                    '/' + awsS3Info.S3Bucket__c + fileName;
    String encodedStringToSign = EncodingUtil.urlEncode(stringToSign, 'UTF-8');
    //Blob mac = Crypto.generateMac('HMACSHA1', blob.valueof(stringToSign),blob.valueof(awsS3Info.Private_S3AWSSecurityToken__c));
    String signedKey  = EncodingUtil.base64Encode(
        Crypto.generateMac(
            'HMACSHA256',
            blob.valueof(encodedStringToSign),
            blob.valueof(awsS3Info.AWSSecurityToken__c)
        )
    );
    //String authHeader = 'AWS' + ' ' + awsS3Info.Private_S3AWSKey__c + ':' + signedKey ;
    String authHeader = 'AWS ' + awsS3Info.AWSKey__c + ':' + signedKey ;
    System.debug(authHeader);
    request.setHeader('Authorization', authHeader);

    res = httpLink.send(request);
    System.debug('Put Success: Response');
    System.debug(res.getStatus());
    System.debug(res.getStatusCode());
    System.debug(res.getBody());
} catch(Exception e){
    throw e;
}

 
Hi All i am using amazon s3 rest API For put copyhttp://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectCOPY.html.

I am sending all the header and required parameters but i am getting exception

<Error><Code>RequestTimeout</Code><Message>Your socket connection to the server was not read from or written to within the timeout period. Idle connections will be closed.</Message><RequestId>29BB7877BC9BBB2F</RequestId><HostId>AzGJ4IF1Uf4olokB9eB13kNFHQTKns0jCpUqXy2HnHKZQzoEPFgd+y1DYXrV8yWUq+PmZk+dV9gkDXpEIVYK5V1ouB0WfgTP</HostId></Error>

Below is Code i am using , this can be executed from console also.

String region='us-west-2';
        
        String method = 'PUT';
        String key= 'XXXXXXXX';
        String secret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
        String filename = 'Doc.pdf';
        String formattedDateString = Datetime.now().format('EEE, dd MMM yyyy HH:mm:ss z','America/Denver');    
        HttpRequest req = new HttpRequest();
        Http http = new Http();
          
        
        req.setHeader('Host','DestinationBucket.s3.amazonaws.com');  //path style
        req.setHeader('x-amz-copy-source','SourceBucket/SourceObject');
        req.setHeader('x-amz-metadata-directive', 'COPY');
        req.setHeader('x-amz-copy-source-if-match','eTAG');
        req.setHeader('x-amz-copy-source-if-none-match','etag');
        req.setHeader('x-amz-copy-source-if-unmodified-since', formattedDateString );
        req.setHeader('x-amz-copy-source-if-modified-since', formattedDateString );
        req.setHeader('x-amz-acl','private');
        req.setHeader('x-amz-bucket-region','us-west-2');
        req.setHeader('Content-Length', '332876');
        req.setHeader('Date', formattedDateString);
        req.setHeader('Content-Type' ,'pdf');
        req.setEndpoint('https://DestinationBucket.s3.amazonaws.com/DestinationObject');
       
        req.settimeout(120000);
        req.setMethod(method);
        string auth;
        String stringToSign = method+'\n\n'+'docx'+'\n'+formattedDateString+'\n/DestinationBucket/DestinationObject';
        Blob mac = Crypto.generateMac('HMACSHA1', blob.valueof(stringToSign),blob.valueof(secret));
        String sig = EncodingUtil.base64Encode(mac);
        auth = 'AWS' + ' ' + key + ':' + sig;
        req.setHeader('Authorization',auth);
        
            //Execute web service call
            try {
                HTTPResponse res = http.send(req);
                System.debug('REKHA-Resp:' + String.ValueOF(res.getBody()));
           
                
            } catch(System.CalloutException e) {
                system.debug(' AWS Service Callout Exception on : ERROR: ' + e.getMessage());
            }