diff --git a/packages/core/src/clients/middleware/signing/signer/signatureV4/presignUrl.ts b/packages/core/src/clients/middleware/signing/signer/signatureV4/presignUrl.ts index 0880e256714..d5415969720 100644 --- a/packages/core/src/clients/middleware/signing/signer/signatureV4/presignUrl.ts +++ b/packages/core/src/clients/middleware/signing/signer/signatureV4/presignUrl.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { AmplifyUrl } from '../../../../../utils/amplifyUrl'; +import { HttpRequest } from '../../../../types'; import { PresignUrlOptions, Presignable } from './types'; import { @@ -45,13 +46,16 @@ export const presignUrl = ( }).forEach(([key, value]) => { presignedUrl.searchParams.append(key, value); }); - const requestToSign = { - body, + const requestToSign: HttpRequest = { headers: { [HOST_HEADER]: url.host }, method, url: presignedUrl, }; + if (body) { + requestToSign.body = body; + } + // calculate and add the signature to the url const signature = getSignature(requestToSign, signingValues); presignedUrl.searchParams.append(SIGNATURE_QUERY_PARAM, signature); diff --git a/packages/storage/package.json b/packages/storage/package.json index 700f467486e..ed1090658b9 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -66,8 +66,12 @@ "s3" ], "dependencies": { + "@aws-sdk/s3-request-presigner": "3.637.0", "@aws-sdk/types": "3.398.0", + "@aws-sdk/util-format-url": "3.609.0", + "@smithy/hash-node": "3.0.3", "@smithy/md5-js": "2.0.7", + "@smithy/url-parser": "3.0.3", "buffer": "4.9.2", "fast-xml-parser": "^4.4.1", "tslib": "^2.5.0" diff --git a/packages/storage/src/providers/s3/apis/internal/getUrl.ts b/packages/storage/src/providers/s3/apis/internal/getUrl.ts index a5c319a1389..291dfff85ad 100644 --- a/packages/storage/src/providers/s3/apis/internal/getUrl.ts +++ b/packages/storage/src/providers/s3/apis/internal/getUrl.ts @@ -83,6 +83,7 @@ export const getUrl = async ( ...(getUrlOptions?.contentType && { ResponseContentType: getUrlOptions.contentType, }), + method: input.options?.method, }, ), expiresAt: new Date(Date.now() + urlExpirationInSec * 1000), diff --git a/packages/storage/src/providers/s3/utils/client/getObject.ts b/packages/storage/src/providers/s3/utils/client/getObject.ts index 322168e63fc..5bd53e296c5 100644 --- a/packages/storage/src/providers/s3/utils/client/getObject.ts +++ b/packages/storage/src/providers/s3/utils/client/getObject.ts @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 import { - EMPTY_SHA256_HASH, Endpoint, HttpRequest, HttpResponse, @@ -13,6 +12,10 @@ import { } from '@aws-amplify/core/internals/aws-client-utils'; import { AmplifyUrl } from '@aws-amplify/core/internals/utils'; import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers'; +import { S3RequestPresigner } from '@aws-sdk/s3-request-presigner'; +import { Hash } from '@smithy/hash-node'; +import { formatUrl } from '@aws-sdk/util-format-url'; +import { parseUrl } from '@smithy/url-parser'; import { S3EndpointResolverOptions, defaultConfig } from './base'; import type { @@ -150,10 +153,25 @@ export const getPresignedGetObjectUrl = async ( const endpoint = defaultConfig.endpointResolver(config, input); const { url, headers, method } = await getObjectSerializer(input, endpoint); + if (input.method === 'PUT') { + const presigner = new S3RequestPresigner({ + credentials: config.credentials, + region: config.region, + sha256: Hash.bind(null, 'sha256'), + }); + const signedUrlObject = await presigner.presign({ + ...parseUrl(url.toString()), + headers, + method, + }); + + return new AmplifyUrl(formatUrl(signedUrlObject)); + } + // TODO: set content sha256 query parameter with value of UNSIGNED-PAYLOAD instead of empty hash. // It requires changes in presignUrl. Without this change, the generated url still works, // but not the same as other tools like AWS SDK and CLI. - url.searchParams.append(CONTENT_SHA256_HEADER, EMPTY_SHA256_HASH); + url.searchParams.append(CONTENT_SHA256_HEADER, 'UNSIGNED-PAYLOAD'); if (config.userAgentValue) { url.searchParams.append( config.userAgentHeader ?? USER_AGENT_HEADER, diff --git a/yarn.lock b/yarn.lock index a55f7941b12..4386f68b900 100644 --- a/yarn.lock +++ b/yarn.lock @@ -777,6 +777,22 @@ fast-xml-parser "4.4.1" tslib "^2.6.2" +"@aws-sdk/core@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.635.0.tgz#74b7d0d7fa3aa39f87ea5cf4e6c97d4d84f4ef14" + integrity sha512-i1x/E/sgA+liUE1XJ7rj1dhyXpAKO1UKFUcTTHXok2ARjWTvszHnSXMOsB77aPbmn0fUp1JTx2kHUAZ1LVt5Bg== + dependencies: + "@smithy/core" "^2.4.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/signature-v4" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-middleware" "^3.0.3" + fast-xml-parser "4.4.1" + tslib "^2.6.2" + "@aws-sdk/credential-provider-env@3.620.1": version "3.620.1" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz#d4692c49a65ebc11dae3f7f8b053fee9268a953c" @@ -920,6 +936,26 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@aws-sdk/middleware-sdk-s3@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.635.0.tgz#be7f61c6033a803cde59ec5a29db266b42fdbc01" + integrity sha512-RLdYJPEV4JL/7NBoFUs7VlP90X++5FlJdxHz0DzCjmiD3qCviKy+Cym3qg1gBgHwucs5XisuClxDrGokhAdTQw== + dependencies: + "@aws-sdk/core" "3.635.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/core" "^2.4.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/signature-v4" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-stream" "^3.1.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@aws-sdk/middleware-signing@3.620.0": version "3.620.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.620.0.tgz#8aface959d610732b0a5ede6f2c48119b33c4f3f" @@ -956,6 +992,32 @@ "@smithy/util-middleware" "^3.0.3" tslib "^2.6.2" +"@aws-sdk/s3-request-presigner@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.637.0.tgz#7dda8becd71413601c408ae7f06cb71c35a539a9" + integrity sha512-URRiEDZEICyfAXmXcXREQCsvZrapITAymvg46p1Xjnuv7PTnUB0SF18B2omPL0E5d/X+T3O9NKdtot+BqJbIWw== + dependencies: + "@aws-sdk/signature-v4-multi-region" "3.635.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-format-url" "3.609.0" + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.635.0.tgz#76e8eb66bfd9b661b4f9768b18aca2e04dd781a2" + integrity sha512-J6QY4/invOkpogCHjSaDON1hF03viPpOnsrzVuCvJMmclS/iG62R4EY0wq1alYll0YmSdmKlpJwHMWwGtqK63Q== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.635.0" + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/signature-v4" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@aws-sdk/token-providers@3.614.0": version "3.614.0" resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz#88da04f6d4ce916b0b0f6e045676d04201fb47fd" @@ -991,6 +1053,13 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@aws-sdk/util-arn-parser@3.568.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz#6a19a8c6bbaa520b6be1c278b2b8c17875b91527" + integrity sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w== + dependencies: + tslib "^2.6.2" + "@aws-sdk/util-endpoints@3.614.0": version "3.614.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz#6564b0ffd7dc3728221e9f9821f5aab1cc58468e" @@ -1001,6 +1070,16 @@ "@smithy/util-endpoints" "^2.0.5" tslib "^2.6.2" +"@aws-sdk/util-format-url@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-format-url/-/util-format-url-3.609.0.tgz#f53907193bb636b52b61c81bbe6d7bd5ddc76c68" + integrity sha512-fuk29BI/oLQlJ7pfm6iJ4gkEpHdavffAALZwXh9eaY1vQ0ip0aKfRTiNudPoJjyyahnz5yJ1HkmlcDitlzsOrQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@aws-sdk/util-locate-window@^3.0.0": version "3.568.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz#2acc4b2236af0d7494f7e517401ba6b3c4af11ff" @@ -4305,7 +4384,7 @@ "@smithy/util-middleware" "^3.0.3" tslib "^2.6.2" -"@smithy/core@^2.3.1": +"@smithy/core@^2.3.1", "@smithy/core@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.4.0.tgz#56e917b6ab2dffeba681a05395c40a757d681147" integrity sha512-cHXq+FneIF/KJbt4q4pjN186+Jf4ZB0ZOqEaZMBhT79srEyGDDBV31NqBRBjazz8ppQ1bJbDJMY9ba5wKFV36w== @@ -4398,7 +4477,7 @@ "@smithy/util-base64" "^3.0.0" tslib "^2.6.2" -"@smithy/hash-node@^3.0.3": +"@smithy/hash-node@3.0.3", "@smithy/hash-node@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.3.tgz#82c5cb7b0f1a29ee7319081853d2d158c07dff24" integrity sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw== @@ -4601,7 +4680,7 @@ dependencies: tslib "^2.6.2" -"@smithy/url-parser@^3.0.3": +"@smithy/url-parser@3.0.3", "@smithy/url-parser@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.3.tgz#e8a060d9810b24b1870385fc2b02485b8a6c5955" integrity sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A== @@ -14782,7 +14861,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -14860,7 +14948,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -14874,6 +14962,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -16011,7 +16106,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -16038,6 +16133,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"