Skip to content

Commit

Permalink
fix(s3-request-presigner): enable overriding hoistable headers
Browse files Browse the repository at this point in the history
  • Loading branch information
kuhe committed Sep 30, 2024
1 parent dddd164 commit c797084
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 4 deletions.
22 changes: 22 additions & 0 deletions packages/s3-request-presigner/src/presigner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,28 @@ describe("s3 presigner", () => {
expect(signedHeaders).toContain("x-amz-server-side-encryption-customer-algorithm");
});

it("should allow hoisting server-side-encryption headers to query when overridden", async () => {
const signer = new S3RequestPresigner(s3ResolvedConfig);
const signed = await signer.presign(
{
...minimalRequest,
headers: {
...minimalRequest.headers,
"x-amz-server-side-encryption": "kms",
"x-amz-server-side-encryption-customer-algorithm": "AES256",
},
},
{
hoistableHeaders: new Set(["x-amz-server-side-encryption", "x-amz-server-side-encryption-customer-algorithm"]),
}
);
const signedHeadersHeader = signed.query?.["X-Amz-SignedHeaders"];
const signedHeaders =
typeof signedHeadersHeader === "string" ? signedHeadersHeader.split(";") : signedHeadersHeader;
expect(signedHeaders).not.toContain("x-amz-server-side-encryption");
expect(signedHeaders).not.toContain("x-amz-server-side-encryption-customer-algorithm");
});

it("should inject host header with port if not supplied", async () => {
const signer = new S3RequestPresigner(s3ResolvedConfig);
const port = 12345;
Expand Down
34 changes: 30 additions & 4 deletions packages/s3-request-presigner/src/presigner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,17 @@ export class S3RequestPresigner implements RequestPresigner {

public presign(
requestToSign: IHttpRequest,
{ unsignableHeaders = new Set(), unhoistableHeaders = new Set(), ...options }: RequestPresigningArguments = {}
{
unsignableHeaders = new Set(),
hoistableHeaders = new Set(),
unhoistableHeaders = new Set(),
...options
}: RequestPresigningArguments = {}
): Promise<IHttpRequest> {
this.prepareRequest(requestToSign, {
unsignableHeaders,
unhoistableHeaders,
hoistableHeaders,
});
return this.signer.presign(requestToSign, {
expiresIn: 900,
Expand All @@ -43,11 +49,17 @@ export class S3RequestPresigner implements RequestPresigner {
public presignWithCredentials(
requestToSign: IHttpRequest,
credentials: AwsCredentialIdentity,
{ unsignableHeaders = new Set(), unhoistableHeaders = new Set(), ...options }: RequestPresigningArguments = {}
{
unsignableHeaders = new Set(),
hoistableHeaders = new Set(),
unhoistableHeaders = new Set(),
...options
}: RequestPresigningArguments = {}
): Promise<IHttpRequest> {
this.prepareRequest(requestToSign, {
unsignableHeaders,
unhoistableHeaders,
hoistableHeaders,
});
return this.signer.presignWithCredentials(requestToSign, credentials, {
expiresIn: 900,
Expand All @@ -59,15 +71,29 @@ export class S3RequestPresigner implements RequestPresigner {

private prepareRequest(
requestToSign: IHttpRequest,
{ unsignableHeaders = new Set(), unhoistableHeaders = new Set() }: RequestPresigningArguments = {}
{
unsignableHeaders = new Set(),
unhoistableHeaders = new Set(),
hoistableHeaders = new Set(),
}: RequestPresigningArguments = {}
) {
unsignableHeaders.add("content-type");

Object.keys(requestToSign.headers)
.map((header) => header.toLowerCase())
.filter((header) => header.startsWith("x-amz-server-side-encryption"))
.forEach((header) => {
unhoistableHeaders.add(header);
if (!hoistableHeaders.has(header)) {
/**
* For smoother backwards compatibility with pre-GA PR
* https://github.com/aws/aws-sdk-js-v3/issues/1576,
* x-amz-sse headers are by default unhoisted,
* but can be overridden.
*/
unhoistableHeaders.add(header);
}
});

requestToSign.headers[SHA256_HEADER] = UNSIGNED_PAYLOAD;

const currentHostHeader = requestToSign.headers.host;
Expand Down

0 comments on commit c797084

Please sign in to comment.