Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Vijaysinh/54ad561a1a3c6217db511ee25eaf5301 to your computer and use it in GitHub Desktop.
Save Vijaysinh/54ad561a1a3c6217db511ee25eaf5301 to your computer and use it in GitHub Desktop.
AWS S3: Pre-sign Upload & Download Requests [PHP]
<?php
function AWS_S3_PresignDownload($AWSAccessKeyId, $AWSSecretAccessKey, $BucketName, $AWSRegion, $canonical_uri, $expires = 8400) {
// Creates a signed download link for an AWS S3 file
// Based on https://gist.github.com/kelvinmo/d78be66c4f36415a6b80
$encoded_uri = str_replace('%2F', '/', rawurlencode($canonical_uri));
// Specify the hostname for the S3 endpoint
if($AWSRegion == 'us-east-1') {
$hostname = trim($BucketName .".s3.amazonaws.com");
$header_string = "host:" . $hostname . "\n";
$signed_headers_string = "host";
} else {
$hostname = trim($BucketName . ".s3-" . $AWSRegion . ".amazonaws.com");
$header_string = "host:" . $hostname . "\n";
$signed_headers_string = "host";
}
$date_text = gmdate('Ymd', time());
$time_text = $date_text . 'T000000Z';
$algorithm = 'AWS4-HMAC-SHA256';
$scope = $date_text . "/" . $AWSRegion . "/s3/aws4_request";
$x_amz_params = array(
'X-Amz-Algorithm' => $algorithm,
'X-Amz-Credential' => $AWSAccessKeyId . '/' . $scope,
'X-Amz-Date' => $time_text,
'X-Amz-SignedHeaders' => $signed_headers_string
);
if ($expires > 0) {
// 'Expires' is the number of seconds until the request becomes invalid
$x_amz_params['X-Amz-Expires'] = $expires;
}
ksort($x_amz_params);
$query_string = "";
foreach ($x_amz_params as $key => $value) {
$query_string .= rawurlencode($key) . '=' . rawurlencode($value) . "&";
}
$query_string = substr($query_string, 0, -1);
$canonical_request = "GET\n" . $encoded_uri . "\n" . $query_string . "\n" . $header_string . "\n" . $signed_headers_string . "\nUNSIGNED-PAYLOAD";
$string_to_sign = $algorithm . "\n" . $time_text . "\n" . $scope . "\n" . hash('sha256', $canonical_request, false);
$signing_key = hash_hmac('sha256', 'aws4_request', hash_hmac('sha256', 's3', hash_hmac('sha256', $AWSRegion, hash_hmac('sha256', $date_text, 'AWS4' . $AWSSecretAccessKey, true), true), true), true);
$signature = hash_hmac('sha256', $string_to_sign, $signing_key);
return 'https://' . $hostname . $encoded_uri . '?' . $query_string . '&X-Amz-Signature=' . $signature;
}
?>
<?php
function AWS_S3_hmac_sha256($key, $msg, $binary = true) {
return hash_hmac("sha256", $msg, $key, $binary);
}
function AWS_S3_PresignUpload($BucketName, $AWSAccessKeyId, $AWSSecretAccessKey, $AWSRegion, $UploadFilenameStartsWith) {
/* Function to presign an AWS S3 file upload.
This method of uploading can allow clients to securely upload files
directly to S3, while ensuring certian conditions are enforced (e.g. upload filename)
Written by Anthony Eden http://mediarealm.com.au/
*/
$AWSService = "s3";
$AWSRequest = "aws4_request";
$date = date("Ymd");
$AWSPolicy = '{ "expiration": "'.gmdate("Y-m-d", strtotime("tomorrow")).'T12:00:00.000Z",
"conditions": [
{"bucket": "'.$BucketName.'"},
["starts-with", "$key", "'.$UploadFilenameStartsWith.'"],
{"x-amz-server-side-encryption": "AES256"},
{"x-amz-credential": "'.$AWSAccessKeyId.'/'.$date.'/'.$AWSRegion.'/'.$AWSService.'/'.$AWSRequest.'"},
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
{"x-amz-date": "'.$date.'T000000Z" }
]
}';
$StringToSign = base64_encode($AWSPolicy);
$DateKey = AWS_S3_hmac_sha256("AWS4" . $AWSSecretAccessKey, $date);
$DateRegionKey = AWS_S3_hmac_sha256($DateKey, $AWSRegion);
$DateRegionServiceKey = AWS_S3_hmac_sha256($DateRegionKey, $AWSService);
$SigningKey = AWS_S3_hmac_sha256($DateRegionServiceKey, $AWSRequest);
$Signature = AWS_S3_hmac_sha256($SigningKey, $StringToSign, false);
return array(
"BucketName" => $BucketName,
"KeyPrefix" => $UploadFilenameStartsWith,
"x-amz-server-side-encryption" => "AES256",
"X-Amz-Credential" => $AWSAccessKeyId.'/'.$date.'/'.$AWSRegion.'/'.$AWSService.'/'.$AWSRequest,
"X-Amz-Algorithm" => "AWS4-HMAC-SHA256",
"X-Amz-Date" => $date.'T000000Z',
"Policy" => $StringToSign,
"X-Amz-Signature" => $Signature
);
}
?>
import os
import requests
def uploadS3(srcFilename, S3Upload):
# This method uploads a file to a S3 bucket using pre-signed credentials
# S3Upload is a dictionary returned by AWS_S3_Presign_Upload.php
# Determine the extension of the original file
filename, file_extension = os.path.splitext(srcFilename)
# Perform the upload
r = requests.post(
'http://' + S3Upload['BucketName'] + '.s3.amazonaws.com/',
files = {
'file': open(srcFilename, 'rb')
},
data = {
"key": S3Upload['KeyPrefix'] + file_extension,
"x-amz-server-side-encryption": S3Upload['x-amz-server-side-encryption'],
"X-Amz-Algorithm": S3Upload['X-Amz-Algorithm'],
"X-Amz-Credential": S3Upload['X-Amz-Credential'],
"X-Amz-Date": S3Upload['X-Amz-Date'],
"Policy": S3Upload['Policy'],
"X-Amz-Signature": S3Upload['X-Amz-Signature']
}
)
if r.status_code == 200 or r.status_code == 204:
# Success!
return True
else:
# Debug output
print "ERROR: Cannot upload file to S3", srcFilename
print r.status_code, r.reason
print r.text
return False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment