Created
April 16, 2019 05:27
-
-
Save porjo/9de1ea33329ddf9049599564d8e19a9d to your computer and use it in GitHub Desktop.
PHP function to generate curl headers suitable for signed requests agains AWS API
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
// Sign the request and return header array for use by curl | |
// | |
// For HTTP methods with no payload (GET,DELETE) leave $Payload , $ContentType empty | |
// | |
// Based on: http://usefulangle.com/post/34/aws-s3-upload-api-php-curl | |
private function SignRequest($Method, $URL, $Payload='', $ContentType='') | |
{ | |
if(!defined('AWS_ACCESS_KEY_ID') || !defined('AWS_SECRET_ACCESS_KEY') || !defined('AWS_REGION')) | |
return null; | |
// AWS API keys | |
$aws_access_key_id = AWS_ACCESS_KEY_ID; | |
$aws_secret_access_key = AWS_SECRET_ACCESS_KEY; | |
$aws_region = AWS_REGION; | |
$aws_service_name = 'es'; | |
// UTC timestamp and date | |
$timestamp = gmdate('Ymd\THis\Z'); | |
$date = gmdate('Ymd'); | |
$URLBits = parse_url($URL); | |
$host_name = $URLBits['host']; | |
$path = $URLBits['path']; | |
$queryStr = $URLBits['query']; | |
// HTTP request headers as key & value | |
$request_headers = array(); | |
if($ContentType) | |
$request_headers['Content-Type'] = $ContentType; | |
$request_headers['x-amz-date'] = $timestamp; | |
$request_headers['Host'] = $host_name; | |
// Sort it in ascending order | |
ksort($request_headers); | |
// Canonical headers | |
$canonical_headers = []; | |
foreach($request_headers as $key => $value) { | |
$canonical_headers[] = strtolower($key) . ":" . $value; | |
} | |
$canonical_headers = implode("\n", $canonical_headers); | |
// Signed headers | |
$signed_headers = []; | |
foreach($request_headers as $key => $value) { | |
$signed_headers[] = strtolower($key); | |
} | |
$signed_headers = implode(";", $signed_headers); | |
// AWS requires bits between slashes to be uri encoded | |
$pathSegments = explode('/', $path); | |
foreach($pathSegments as $i => $ps) | |
{ | |
$pathSegments[$i] = rawurlencode($ps); | |
} | |
// uri encode query string | |
parse_str($queryStr, $queryVals); | |
ksort($queryVals); | |
$queryStr = ''; | |
foreach($queryVals as $key => $val) | |
{ | |
$queryStr .= rawurlencode($key)."=".rawurlencode($val).'&'; | |
} | |
$queryStr = rtrim($queryStr, '&'); | |
// Cannonical request | |
$canonical_request = []; | |
$canonical_request[] = $Method; | |
$canonical_request[] = implode('/', $pathSegments); | |
$canonical_request[] = $queryStr; | |
$canonical_request[] = $canonical_headers; | |
$canonical_request[] = ""; | |
$canonical_request[] = $signed_headers; | |
$canonical_request[] = hash('sha256', $Payload); | |
$canonical_request = implode("\n", $canonical_request); | |
$hashed_canonical_request = hash('sha256', $canonical_request); | |
// AWS Scope | |
$scope = []; | |
$scope[] = $date; | |
$scope[] = $aws_region; | |
$scope[] = $aws_service_name; | |
$scope[] = "aws4_request"; | |
// String to sign | |
$string_to_sign = []; | |
$string_to_sign[] = "AWS4-HMAC-SHA256"; | |
$string_to_sign[] = $timestamp; | |
$string_to_sign[] = implode('/', $scope); | |
$string_to_sign[] = $hashed_canonical_request; | |
$string_to_sign = implode("\n", $string_to_sign); | |
// Signing key | |
$kSecret = 'AWS4' . $aws_secret_access_key; | |
$kDate = hash_hmac('sha256', $date, $kSecret, true); | |
$kRegion = hash_hmac('sha256', $aws_region, $kDate, true); | |
$kService = hash_hmac('sha256', $aws_service_name, $kRegion, true); | |
$kSigning = hash_hmac('sha256', 'aws4_request', $kService, true); | |
// Signature | |
$signature = hash_hmac('sha256', $string_to_sign, $kSigning); | |
// Authorization | |
$authorization = [ | |
'Credential=' . $aws_access_key_id . '/' . implode('/', $scope), | |
'SignedHeaders=' . $signed_headers, | |
'Signature=' . $signature | |
]; | |
$authorization = 'AWS4-HMAC-SHA256' . ' ' . implode( ',', $authorization); | |
// Curl headers | |
$curl_headers = [ 'Authorization: ' . $authorization ]; | |
foreach($request_headers as $key => $value) { | |
$curl_headers[] = $key . ": " . $value; | |
} | |
return $curl_headers; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment