diff --git a/packages/token-providers/package.json b/packages/token-providers/package.json index a382363bcdd0..87e88288350b 100644 --- a/packages/token-providers/package.json +++ b/packages/token-providers/package.json @@ -15,7 +15,9 @@ "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", "extract:docs": "api-extractor run --local", "test": "yarn g:vitest run", - "test:watch": "yarn g:vitest watch" + "test:watch": "yarn g:vitest watch", + "test:integration": "yarn g:vitest run -c vitest.config.integ.ts", + "test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.ts" }, "keywords": [ "aws", diff --git a/packages/token-providers/src/fromEnvSigningName.integ.spec.ts b/packages/token-providers/src/fromEnvSigningName.integ.spec.ts new file mode 100644 index 000000000000..e3ae6c9a368d --- /dev/null +++ b/packages/token-providers/src/fromEnvSigningName.integ.spec.ts @@ -0,0 +1,81 @@ +import { requireRequestsFrom } from "@aws-sdk/aws-util-test/src"; +import { Bedrock } from "@aws-sdk/client-bedrock"; +import { BedrockRuntime } from "@aws-sdk/client-bedrock-runtime"; +import { afterEach, beforeEach, describe, it } from "vitest"; + +describe("from env signing name integration", () => { + const mockBearerToken = "mock-bearer-token"; + const credentials = { + accessKeyId: "INTEG", + secretAccessKey: "INTEG", + }; + const region = "us-west-2"; + + beforeEach(() => { + delete process.env.AWS_BEARER_TOKEN_BEDROCK; + }); + + afterEach(() => { + delete process.env.AWS_BEARER_TOKEN_BEDROCK; + }); + + function expectBearerToken(client: Bedrock | BedrockRuntime) { + requireRequestsFrom(client).toMatch({ + headers: { + authorization: `Bearer ${mockBearerToken}`, + }, + }); + } + + function expectSigV4(client: Bedrock | BedrockRuntime) { + requireRequestsFrom(client).toMatch({ + hostname: /bedrock/, + headers: { + authorization: /AWS4-HMAC-SHA256 Credential/, + }, + }); + } + + describe("when environment bearer token is set", () => { + it("bedrock", async () => { + process.env.AWS_BEARER_TOKEN_BEDROCK = mockBearerToken; + const client = new Bedrock({ region, credentials }); + expectBearerToken(client); + await client.listCustomModels(); + }); + + it("bedrock runtime", async () => { + process.env.AWS_BEARER_TOKEN_BEDROCK = mockBearerToken; + const client = new BedrockRuntime({ + region, + credentials, + }); + expectBearerToken(client); + await client.listAsyncInvokes(); + }); + + it("can be overridden by auth scheme preference", async () => { + process.env.AWS_BEARER_TOKEN_BEDROCK = mockBearerToken; + const client = new Bedrock({ region, credentials, authSchemePreference: ["sigv4"] }); + expectSigV4(client); + await client.listCustomModels(); + }); + }); + + describe("when environment bearer token is not set", () => { + it("bedrock", async () => { + const client = new Bedrock({ region, credentials }); + expectSigV4(client); + await client.listCustomModels(); + }); + + it("bedrock runtime", async () => { + const client = new BedrockRuntime({ + region, + credentials, + }); + expectSigV4(client); + await client.listAsyncInvokes(); + }); + }); +}); diff --git a/packages/token-providers/vitest.config.integ.ts b/packages/token-providers/vitest.config.integ.ts new file mode 100644 index 000000000000..5802db1ac64a --- /dev/null +++ b/packages/token-providers/vitest.config.integ.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + include: ["**/*.integ.spec.ts"], + environment: "node", + }, +}); diff --git a/private/aws-util-test/src/requests/test-http-handler.ts b/private/aws-util-test/src/requests/test-http-handler.ts index 7fdb9077e5ce..29f0d0d27806 100644 --- a/private/aws-util-test/src/requests/test-http-handler.ts +++ b/private/aws-util-test/src/requests/test-http-handler.ts @@ -122,9 +122,9 @@ export class TestHttpHandler implements HttpHandler { this.check(m.hostname, request.hostname); this.check(m.port, request.port); this.check(m.path, request.path); - this.checkAll(m.query, request.query); + this.checkAll(m.query ?? {}, request.query, "query"); - this.checkAll(m.headers, request.headers); + this.checkAll(m.headers ?? {}, request.headers, "header"); this.check(m.body, request.body); this.check(m.method, request.method); @@ -189,7 +189,11 @@ export class TestHttpHandler implements HttpHandler { this.assertions++; } - private checkAll(matchers?: Record | Map, observed?: any) { + private checkAll( + matchers: Record | Map, + observed: any, + type: "header" | "query" + ) { if (matchers == null) { return; } @@ -201,7 +205,11 @@ export class TestHttpHandler implements HttpHandler { if (key.startsWith("/") && key.endsWith("/")) { key = new RegExp(key); } else { - this.check(matcher, observed[key]); + const matchingValue = + type === "header" + ? observed[Object.keys(observed).find((k) => k.toLowerCase() === String(key).toLowerCase()) ?? ""] + : observed[key]; + this.check(matcher, matchingValue); } } if (key instanceof RegExp) {