Forked from anthonyeden/AWS_S3_Presign_Download.php
Created
February 17, 2022 15:27
-
-
Save rafpro/ff20c120db53865adba427e376876c52 to your computer and use it in GitHub Desktop.
AWS S3: Pre-sign Upload & Download Requests [PHP]
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
| <?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; | |
| } | |
| ?> |
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
| <?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 | |
| ); | |
| } | |
| ?> |
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
| 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