1
votes

I am creating a website, in which there is a feature that if user delete a image/video it will be archived, I am using AWS S3 for storing and on delete want to move it on Glacier, I dont want to use AWS SDK, so i am creating Raw request using PHP cURL, from this link i tried to Put bucket lifecycle on an object, http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTlifecycle.html and done some code, but it give me error of mismatch signature,

SignatureDoesNotMatch-The request signature we calculated does not match the signature you provided. Check your key and signing method.

This is my code, in this i want to apply lifecycle on x.php which is inside a bucket, apply lifecycle for expire it, What i am doing wrong? Help me,

$AWSaccessKey = 'xxxxxxxxxxxxxxxx';
$AWSsecretKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
$AWSregion = 'xxxxxxxxx';

// bucket
$bucket   = 'xxxxxxxx';
$postdata = $filedata = '<LifecycleConfiguration>
  <Rule>
    <Filter>
      <Prefix>/</Prefix>
    </Filter>
    <Status>Enabled</Status>
    <Expiration>
      <Days>0</Days>
    </Expiration>
  </Rule>
</LifecycleConfiguration>';
$filetype = 'text/plain';
$path     = '/x.php'; // file on which i want to put lifecycle to move it to GLACIER

// file md5
$file_md5 = base64_encode(md5($filedata, true));

// file size
$filesize = strlen($filedata);

// date
$date = gmdate('D, d M Y H:i:s').' +0000';

// -> for putting lifecycle config
$params = array(
    'x-amz-date'          => gmdate('D, d M Y H:i:s \\G\\M\\T'),
);
//'x-amz-security-token'=> $auth['Token']

// sort and stringify params (different to other requests, this is formatted like headers)
$params_str = '';
uksort($params, 'strcmp');
foreach($params as $k=>$v){
    $params_str .= $k.': '.$v."\\n";
}

// -> for putting lifecycle config
$to_sign = "PUT\\n$file_md5\\n$filetype\\n\\n".$params_str.'/'.$bucket.$path;

// create signature
// Note: S3 uses SHA1 instead of 256!
$signature = base64_encode(hash_hmac('SHA1', $to_sign, $AWSsecretKey, true));

$headers = "Host: $bucket.s3.amazonaws.com\\n"; // change to your region
$headers .= $params_str;  // note that the params get added to the header
$headers .= 'Content-MD5: '.$file_md5."\\n";
$headers .= 'Authorization: AWS '.$AWSaccessKey.':'.$signature."\\n";
$headers .= 'Content-Length: '.$filesize."\\n";

$ch = curl_init("http://$bucket.s3-$AWSregion.amazonaws.com");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, explode('\n', $headers));
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, fopen(dirname(__FILE__).'/errorlog.txt', 'w'));

$result = curl_exec($ch); 
var_dump($result);
1
It might be easier to define a permanent lifecycle rule on a specific path (eg s3::bucket/archive/). Then, move the file to that path to have it archived. (Of course, there is no 'move', it would actually involve a Copy and a Delete.)John Rotenstein

1 Answers

1
votes

I think you do not fully understand how the lifecycle policy works.

$path = '/x.php'; // file on which i want to put lifecycle to move it to GLACIER

You do not move individual files. You configure a prefix. that should be in your XML document. You already have this

<Prefix>/</Prefix>

  1. PUT lifecycle should always be to /?lifecycle. And you put it as /x.php
  2. It would probably be better to use AWS Signature V4 as opposed to V2 as some newer regions do not support Signature V2 but all regions support Signature V4. More info here: http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
  3. With Signature V4, even if you do see the error message SignatureDoesNotMatch you should also see other messages, <StringToSignBytes></StringToSignBytes> and <CanonicalRequest></CanonicalRequest>. These should be more than enough for you to isolate and solve this issue.
  4. You mention you want to move it to GLACIER but you do not mention this in your XML content. Refer to "Example 1: Add lifecycle configuration - bucket not versioning-enabled" section on this page for http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTlifecycle.html You would need <StorageClass>GLACIER</StorageClass> in your XML.

Hope this helps.