diff options
Diffstat (limited to 'aws/aws-sdk-php/src/Signature/SignatureV4.php')
-rw-r--r-- | aws/aws-sdk-php/src/Signature/SignatureV4.php | 90 |
1 files changed, 86 insertions, 4 deletions
diff --git a/aws/aws-sdk-php/src/Signature/SignatureV4.php b/aws/aws-sdk-php/src/Signature/SignatureV4.php index 71e75c70..4f937139 100644 --- a/aws/aws-sdk-php/src/Signature/SignatureV4.php +++ b/aws/aws-sdk-php/src/Signature/SignatureV4.php @@ -2,6 +2,14 @@ namespace Aws\Signature; use Aws\Credentials\CredentialsInterface; +use AWS\CRT\Auth\Signable; +use AWS\CRT\Auth\SignatureType; +use AWS\CRT\Auth\Signing; +use AWS\CRT\Auth\SigningAlgorithm; +use AWS\CRT\Auth\SigningConfigAWS; +use AWS\CRT\Auth\StaticCredentialsProvider; +use AWS\CRT\HTTP\Request; +use Aws\Exception\CommonRuntimeException; use Aws\Exception\CouldNotCreateChecksumException; use GuzzleHttp\Psr7; use Psr\Http\Message\RequestInterface; @@ -21,11 +29,14 @@ class SignatureV4 implements SignatureInterface private $service; /** @var string */ - private $region; + protected $region; /** @var bool */ private $unsigned; + /** @var bool */ + private $useV4a; + /** * The following headers are not signed because signing these headers * would potentially cause a signature mismatch when sending a request @@ -33,7 +44,7 @@ class SignatureV4 implements SignatureInterface * * @return array */ - private function getHeaderBlacklist() + protected function getHeaderBlacklist() { return [ 'cache-control' => true, @@ -55,6 +66,7 @@ class SignatureV4 implements SignatureInterface 'from' => true, 'referer' => true, 'user-agent' => true, + 'X-Amz-User-Agent' => true, 'x-amzn-trace-id' => true, 'aws-sdk-invocation-id' => true, 'aws-sdk-retry' => true, @@ -73,6 +85,7 @@ class SignatureV4 implements SignatureInterface $this->service = $service; $this->region = $region; $this->unsigned = isset($options['unsigned-body']) ? $options['unsigned-body'] : false; + $this->useV4a = isset($options['use_v4a']) && $options['use_v4a'] === true; } /** @@ -92,6 +105,11 @@ class SignatureV4 implements SignatureInterface $parsed['headers']['X-Amz-Security-Token'] = [$token]; } $service = isset($signingService) ? $signingService : $this->service; + + if ($this->useV4a) { + return $this->signWithV4a($credentials, $request, $service); + } + $cs = $this->createScope($sdt, $this->region, $service); $payload = $this->getPayload($request); @@ -323,11 +341,11 @@ class SignatureV4 implements SignatureInterface ksort($query); foreach ($query as $k => $v) { if (!is_array($v)) { - $qs .= rawurlencode($k) . '=' . rawurlencode($v) . '&'; + $qs .= rawurlencode($k) . '=' . rawurlencode($v !== null ? $v : '') . '&'; } else { sort($v); foreach ($v as $value) { - $qs .= rawurlencode($k) . '=' . rawurlencode($value) . '&'; + $qs .= rawurlencode($k) . '=' . rawurlencode($value !== null ? $value : '') . '&'; } } } @@ -366,6 +384,9 @@ class SignatureV4 implements SignatureInterface private function moveHeadersToQuery(array $parsedRequest) { + //x-amz-user-agent shouldn't be put in a query param + unset($parsedRequest['headers']['X-Amz-User-Agent']); + foreach ($parsedRequest['headers'] as $name => $header) { $lname = strtolower($name); if (substr($lname, 0, 5) == 'x-amz') { @@ -417,4 +438,65 @@ class SignatureV4 implements SignatureInterface $req['version'] ); } + + /** + * @param CredentialsInterface $credentials + * @param RequestInterface $request + * @param $signingService + * @return RequestInterface + */ + protected function signWithV4a(CredentialsInterface $credentials, RequestInterface $request, $signingService) + { + if (!extension_loaded('awscrt')) { + throw new CommonRuntimeException( + "AWS Common Runtime for PHP is required to use Signature V4A" + . ". Please install it using the instructions found at" + . " https://github.com/aws/aws-sdk-php/blob/master/CRT_INSTRUCTIONS.md" + ); + } + $credentials_provider = new StaticCredentialsProvider([ + 'access_key_id' => $credentials->getAccessKeyId(), + 'secret_access_key' => $credentials->getSecretKey(), + 'session_token' => $credentials->getSecurityToken(), + ]); + $sha = $this->getPayload($request); + $signingConfig = new SigningConfigAWS([ + 'algorithm' => SigningAlgorithm::SIGv4_ASYMMETRIC, + 'signature_type' => SignatureType::HTTP_REQUEST_HEADERS, + 'credentials_provider' => $credentials_provider, + 'signed_body_value' => $sha, + 'region' => "*", + 'service' => $signingService, + 'date' => time(), + ]); + $sha = $this->getPayload($request); + $invocationId = $request->getHeader("aws-sdk-invocation-id"); + $retry = $request->getHeader("aws-sdk-retry"); + $request = $request->withoutHeader("aws-sdk-invocation-id"); + $request = $request->withoutHeader("aws-sdk-retry"); + $http_request = new Request( + $request->getMethod(), + (string) $request->getUri(), + [], + array_map(function ($header) { + return $header[0]; + }, $request->getHeaders()) + ); + + Signing::signRequestAws( + Signable::fromHttpRequest($http_request), + $signingConfig, function ($signing_result, $error_code) use (&$http_request) { + $signing_result->applyToHttpRequest($http_request); + }); + $sigV4AHeaders = $http_request->headers(); + foreach ($sigV4AHeaders->toArray() as $h => $v) { + $request = $request->withHeader($h, $v); + } + $request = $request->withHeader("aws-sdk-invocation-id", $invocationId); + $request = $request->withHeader("x-amz-content-sha256", $sha); + $request = $request->withHeader("aws-sdk-retry", $retry); + $request = $request->withHeader("x-amz-region-set", "*"); + + return $request; + } } |