/upload/system/storage/vendor/aws/aws-sdk-php/src/Signature/S3SignatureV4.php

https://github.com/ocStore/ocStore · PHP · 156 lines · 119 code · 9 blank · 28 comment · 8 complexity · 92ecc99f4c6e036a7d7f5bc470e1fc27 MD5 · raw file

  1. <?php
  2. namespace Aws\Signature;
  3. use Aws\Credentials\CredentialsInterface;
  4. use AWS\CRT\Auth\SignatureType;
  5. use AWS\CRT\Auth\Signing;
  6. use AWS\CRT\Auth\SigningAlgorithm;
  7. use AWS\CRT\Auth\SigningConfigAWS;
  8. use AWS\CRT\Auth\StaticCredentialsProvider;
  9. use AWS\CRT\HTTP\Request;
  10. use AWS\CRT\Auth\Signable;
  11. use Aws\Exception\CommonRuntimeException;
  12. use Psr\Http\Message\RequestInterface;
  13. /**
  14. * Amazon S3 signature version 4 support.
  15. */
  16. class S3SignatureV4 extends SignatureV4
  17. {
  18. /**
  19. * S3-specific signing logic
  20. *
  21. * {@inheritdoc}
  22. */
  23. public function signRequest(
  24. RequestInterface $request,
  25. CredentialsInterface $credentials,
  26. $signingService = null
  27. ) {
  28. // Always add a x-amz-content-sha-256 for data integrity
  29. if (!$request->hasHeader('x-amz-content-sha256')) {
  30. $request = $request->withHeader(
  31. 'x-amz-content-sha256',
  32. $this->getPayload($request)
  33. );
  34. }
  35. $useCrt =
  36. strpos($request->getUri()->getHost(), "accesspoint.s3-global")
  37. !== false;
  38. if (!$useCrt) {
  39. if (strpos($request->getUri()->getHost(), "s3-object-lambda")) {
  40. return parent::signRequest($request, $credentials, "s3-object-lambda");
  41. }
  42. return parent::signRequest($request, $credentials);
  43. }
  44. return $this->signWithV4a($credentials, $request, $signingService);
  45. }
  46. /**
  47. * Always add a x-amz-content-sha-256 for data integrity.
  48. *
  49. * {@inheritdoc}
  50. */
  51. public function presign(
  52. RequestInterface $request,
  53. CredentialsInterface $credentials,
  54. $expires,
  55. array $options = []
  56. ) {
  57. if (!$request->hasHeader('x-amz-content-sha256')) {
  58. $request = $request->withHeader(
  59. 'X-Amz-Content-Sha256',
  60. $this->getPresignedPayload($request)
  61. );
  62. }
  63. if (strpos($request->getUri()->getHost(), "accesspoint.s3-global")) {
  64. $request = $request->withHeader("x-amz-region-set", "*");
  65. }
  66. return parent::presign($request, $credentials, $expires, $options);
  67. }
  68. /**
  69. * Override used to allow pre-signed URLs to be created for an
  70. * in-determinate request payload.
  71. */
  72. protected function getPresignedPayload(RequestInterface $request)
  73. {
  74. return SignatureV4::UNSIGNED_PAYLOAD;
  75. }
  76. /**
  77. * Amazon S3 does not double-encode the path component in the canonical request
  78. */
  79. protected function createCanonicalizedPath($path)
  80. {
  81. // Only remove one slash in case of keys that have a preceding slash
  82. if (substr($path, 0, 1) === '/') {
  83. $path = substr($path, 1);
  84. }
  85. return '/' . $path;
  86. }
  87. /**
  88. * @param CredentialsInterface $credentials
  89. * @param RequestInterface $request
  90. * @param $signingService
  91. * @return RequestInterface
  92. */
  93. private function signWithV4a(CredentialsInterface $credentials, RequestInterface $request, $signingService)
  94. {
  95. if (!extension_loaded('awscrt')) {
  96. throw new CommonRuntimeException(
  97. "AWS Common Runtime for PHP is required to use Signature V4A and multi-region"
  98. . " access points. Please install it using the instructions found at"
  99. . " https://github.com/aws/aws-sdk-php/blob/master/CRT_INSTRUCTIONS.md"
  100. );
  101. }
  102. $credentials_provider = new StaticCredentialsProvider([
  103. 'access_key_id' => $credentials->getAccessKeyId(),
  104. 'secret_access_key' => $credentials->getSecretKey(),
  105. 'session_token' => $credentials->getSecurityToken(),
  106. ]);
  107. $signingService = $signingService ?: 's3';
  108. $sha = $this->getPayload($request);
  109. $signingConfig = new SigningConfigAWS([
  110. 'algorithm' => SigningAlgorithm::SIGv4_ASYMMETRIC,
  111. 'signature_type' => SignatureType::HTTP_REQUEST_HEADERS,
  112. 'credentials_provider' => $credentials_provider,
  113. 'signed_body_value' => $sha,
  114. 'region' => "*",
  115. 'service' => $signingService,
  116. 'date' => time(),
  117. ]);
  118. $sha = $request->getHeader("x-amz-content-sha256");
  119. $request = $request->withoutHeader("x-amz-content-sha256");
  120. $invocationId = $request->getHeader("aws-sdk-invocation-id");
  121. $retry = $request->getHeader("aws-sdk-retry");
  122. $request = $request->withoutHeader("aws-sdk-invocation-id");
  123. $request = $request->withoutHeader("aws-sdk-retry");
  124. $http_request = new Request(
  125. $request->getMethod(),
  126. (string) $request->getUri(),
  127. [],
  128. array_map(function ($header) {
  129. return $header[0];
  130. }, $request->getHeaders())
  131. );
  132. Signing::signRequestAws(
  133. Signable::fromHttpRequest($http_request),
  134. $signingConfig, function ($signing_result, $error_code) use (&$http_request) {
  135. $signing_result->applyToHttpRequest($http_request);
  136. });
  137. $sigV4AHeaders = $http_request->headers();
  138. foreach ($sigV4AHeaders->toArray() as $h => $v) {
  139. $request = $request->withHeader($h, $v);
  140. }
  141. $request = $request->withHeader("aws-sdk-invocation-id", $invocationId);
  142. $request = $request->withHeader("x-amz-content-sha256", $sha);
  143. $request = $request->withHeader("aws-sdk-retry", $retry);
  144. $request = $request->withHeader("x-amz-region-set", "*");
  145. return $request;
  146. }
  147. }