S3SignatureV4.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <?php
  2. namespace Aws\Signature;
  3. use Aws\Credentials\CredentialsInterface;
  4. use AWS\CRT\Auth\SignatureType;
  5. use AWS\CRT\Auth\SigningAlgorithm;
  6. use AWS\CRT\Auth\SigningConfigAWS;
  7. use Psr\Http\Message\RequestInterface;
  8. /**
  9. * Amazon S3 signature version 4 support.
  10. */
  11. class S3SignatureV4 extends SignatureV4
  12. {
  13. /**
  14. * S3-specific signing logic
  15. *
  16. * {@inheritdoc}
  17. */
  18. use SignatureTrait;
  19. public function signRequest(
  20. RequestInterface $request,
  21. CredentialsInterface $credentials,
  22. $signingService = null
  23. ) {
  24. // Always add a x-amz-content-sha-256 for data integrity
  25. if (!$request->hasHeader('x-amz-content-sha256')) {
  26. $request = $request->withHeader(
  27. 'x-amz-content-sha256',
  28. $this->getPayload($request)
  29. );
  30. }
  31. $useCrt =
  32. strpos($request->getUri()->getHost(), "accesspoint.s3-global")
  33. !== false;
  34. if (!$useCrt) {
  35. if (strpos($request->getUri()->getHost(), "s3-object-lambda")) {
  36. return parent::signRequest($request, $credentials, "s3-object-lambda");
  37. }
  38. return parent::signRequest($request, $credentials);
  39. }
  40. $signingService = $signingService ?: 's3';
  41. return $this->signWithV4a($credentials, $request, $signingService);
  42. }
  43. /**
  44. * @param CredentialsInterface $credentials
  45. * @param RequestInterface $request
  46. * @param $signingService
  47. * @param SigningConfigAWS|null $signingConfig
  48. * @return RequestInterface
  49. *
  50. * Instantiates a separate sigv4a signing config. All services except S3
  51. * use double encoding. All services except S3 require path normalization.
  52. */
  53. protected function signWithV4a(
  54. CredentialsInterface $credentials,
  55. RequestInterface $request,
  56. $signingService,
  57. SigningConfigAWS $signingConfig = null
  58. ){
  59. $this->verifyCRTLoaded();
  60. $credentials_provider = $this->createCRTStaticCredentialsProvider($credentials);
  61. $signingConfig = new SigningConfigAWS([
  62. 'algorithm' => SigningAlgorithm::SIGv4_ASYMMETRIC,
  63. 'signature_type' => SignatureType::HTTP_REQUEST_HEADERS,
  64. 'credentials_provider' => $credentials_provider,
  65. 'signed_body_value' => $this->getPayload($request),
  66. 'region' => "*",
  67. 'should_normalize_uri_path' => false,
  68. 'use_double_uri_encode' => false,
  69. 'service' => $signingService,
  70. 'date' => time(),
  71. ]);
  72. return parent::signWithV4a($credentials, $request, $signingService, $signingConfig);
  73. }
  74. /**
  75. * Always add a x-amz-content-sha-256 for data integrity.
  76. *
  77. * {@inheritdoc}
  78. */
  79. public function presign(
  80. RequestInterface $request,
  81. CredentialsInterface $credentials,
  82. $expires,
  83. array $options = []
  84. ) {
  85. if (!$request->hasHeader('x-amz-content-sha256')) {
  86. $request = $request->withHeader(
  87. 'X-Amz-Content-Sha256',
  88. $this->getPresignedPayload($request)
  89. );
  90. }
  91. if (strpos($request->getUri()->getHost(), "accesspoint.s3-global")) {
  92. $request = $request->withHeader("x-amz-region-set", "*");
  93. }
  94. return parent::presign($request, $credentials, $expires, $options);
  95. }
  96. /**
  97. * Override used to allow pre-signed URLs to be created for an
  98. * in-determinate request payload.
  99. */
  100. protected function getPresignedPayload(RequestInterface $request)
  101. {
  102. return SignatureV4::UNSIGNED_PAYLOAD;
  103. }
  104. /**
  105. * Amazon S3 does not double-encode the path component in the canonical request
  106. */
  107. protected function createCanonicalizedPath($path)
  108. {
  109. // Only remove one slash in case of keys that have a preceding slash
  110. if (substr($path, 0, 1) === '/') {
  111. $path = substr($path, 1);
  112. }
  113. return '/' . $path;
  114. }
  115. }