UNPKG

aws4-axios

Version:

Axios request interceptor for signing requests with AWSv4

243 lines (242 loc) 10.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const client_sts_1 = require("@aws-sdk/client-sts"); const axios_1 = __importDefault(require("axios")); const __1 = require(".."); const methods = ["GET", "DELETE"]; const dataMethods = ["POST", "PATCH", "PUT"]; const region = process.env.AWS_REGION; const apiGateway = process.env.API_GATEWAY_URL; const clientRoleArn = process.env.CLIENT_ROLE_ARN; const assumedClientRoleArn = process.env.ASSUMED_CLIENT_ROLE_ARN; const service = "execute-api"; let clientCredentials; beforeAll(() => __awaiter(void 0, void 0, void 0, function* () { const sts = new client_sts_1.STSClient({ region }); const { Credentials: credentials } = yield sts.send(new client_sts_1.AssumeRoleCommand({ RoleArn: clientRoleArn, RoleSessionName: "integration-tests", })); clientCredentials = { accessKeyId: (credentials === null || credentials === void 0 ? void 0 : credentials.AccessKeyId) || "", secretAccessKey: (credentials === null || credentials === void 0 ? void 0 : credentials.SecretAccessKey) || "", sessionToken: (credentials === null || credentials === void 0 ? void 0 : credentials.SessionToken) || "", }; cleanEnvCredentials(); })); const setEnvCredentials = () => { process.env.AWS_ACCESS_KEY_ID = clientCredentials === null || clientCredentials === void 0 ? void 0 : clientCredentials.accessKeyId; process.env.AWS_SECRET_ACCESS_KEY = clientCredentials === null || clientCredentials === void 0 ? void 0 : clientCredentials.secretAccessKey; process.env.AWS_SESSION_TOKEN = clientCredentials === null || clientCredentials === void 0 ? void 0 : clientCredentials.sessionToken; }; const cleanEnvCredentials = () => { delete process.env.AWS_PROFILE; delete process.env.AWS_ACCESS_KEY_ID; delete process.env.AWS_SECRET_ACCESS_KEY; delete process.env.AWS_SESSION_TOKEN; }; describe("check that API is actually protected", () => { it.each([...methods, ...dataMethods])("checks that HTTP %s is protected", (method) => __awaiter(void 0, void 0, void 0, function* () { yield expect(axios_1.default.request({ url: apiGateway, method })).rejects.toMatchObject({ response: { status: 403, }, }); })); }); describe("with credentials from environment variables", () => { let client; const data = { foo: "bar", }; beforeAll(() => { setEnvCredentials(); }); afterAll(() => { cleanEnvCredentials(); }); beforeEach(() => { client = axios_1.default.create(); client.interceptors.request.use((0, __1.aws4Interceptor)({ options: { region, service }, instance: client })); }); it.each(methods)("HTTP %s", (method) => __awaiter(void 0, void 0, void 0, function* () { let error; let result; try { result = yield client.request({ url: apiGateway, method }); } catch (err) { error = (0, __1.getAuthErrorMessage)(err); } expect(error).toBe(undefined); expect(result === null || result === void 0 ? void 0 : result.status).toEqual(200); expect(result && result.data.requestContext.http.method).toBe(method); expect(result && result.data.requestContext.http.path).toBe("/"); })); it.each(dataMethods)("HTTP %s", (method) => __awaiter(void 0, void 0, void 0, function* () { let error; let result; try { result = yield client.request({ url: apiGateway, method, data, headers: { foo: "bar" }, }); } catch (err) { error = (0, __1.getAuthErrorMessage)(err); } expect(error).toBe(undefined); expect(result === null || result === void 0 ? void 0 : result.status).toEqual(200); expect(result === null || result === void 0 ? void 0 : result.data.requestContext.http.method).toBe(method); expect(result === null || result === void 0 ? void 0 : result.data.requestContext.http.path).toBe("/"); expect(result && JSON.parse(result.data.body)).toStrictEqual(data); expect(result === null || result === void 0 ? void 0 : result.data.headers.foo).toEqual("bar"); })); it("handles path", () => __awaiter(void 0, void 0, void 0, function* () { let error; let result; try { result = yield client.request({ url: apiGateway + "/some/path", }); } catch (err) { error = (0, __1.getAuthErrorMessage)(err); } expect(error).toBe(undefined); expect(result === null || result === void 0 ? void 0 : result.status).toEqual(200); expect(result && result.data.requestContext.http.path).toBe("/some/path"); })); it("handles query parameters", () => __awaiter(void 0, void 0, void 0, function* () { let error; let result; try { result = yield client.request({ url: apiGateway, params: { lorem: 42, }, }); } catch (err) { error = (0, __1.getAuthErrorMessage)(err); } expect(error).toBe(undefined); expect(result === null || result === void 0 ? void 0 : result.status).toEqual(200); expect(result && result.data.rawQueryString).toBe("lorem=42"); })); it("handles custom headers", () => __awaiter(void 0, void 0, void 0, function* () { let error; let result; try { result = yield client.request({ url: apiGateway, method: "POST", headers: { "X-Custom-Header": "Baz" }, data, }); } catch (err) { error = (0, __1.getAuthErrorMessage)(err); } expect(error).toBe(undefined); expect(result === null || result === void 0 ? void 0 : result.status).toEqual(200); expect(result === null || result === void 0 ? void 0 : result.data.headers["x-custom-header"]).toBe("Baz"); })); it("handles custom Content-Type header", () => __awaiter(void 0, void 0, void 0, function* () { let error; let result; try { result = yield client.request({ url: apiGateway, method: "POST", headers: { "Content-Type": "application/xml" }, data, }); } catch (err) { error = (0, __1.getAuthErrorMessage)(err); } expect(error).toBe(undefined); expect(result === null || result === void 0 ? void 0 : result.status).toEqual(200); expect(result === null || result === void 0 ? void 0 : result.data.headers["content-type"]).toBe("application/xml"); })); it("sets content type as application/json when the body is an object", () => __awaiter(void 0, void 0, void 0, function* () { let error; let result; try { result = yield client.request({ url: apiGateway, method: "POST", data, }); } catch (err) { error = (0, __1.getAuthErrorMessage)(err); } expect(error).toBe(undefined); expect(result === null || result === void 0 ? void 0 : result.status).toEqual(200); expect(result === null || result === void 0 ? void 0 : result.data.headers["content-type"]).toBe("application/json"); })); }); describe("signQuery", () => { beforeAll(() => { setEnvCredentials(); }); afterAll(() => { cleanEnvCredentials(); }); it("respects signQuery option", () => __awaiter(void 0, void 0, void 0, function* () { const client = axios_1.default.create(); client.interceptors.request.use((0, __1.aws4Interceptor)({ instance: client, options: { region, service, signQuery: true, }, })); const result = yield client.request({ url: apiGateway + "/some/path", method: "GET", params: { foo: "bar" }, }); expect(result === null || result === void 0 ? void 0 : result.status).toEqual(200); })); }); describe("with role to assume", () => { let client; const assumedRoleName = assumedClientRoleArn === null || assumedClientRoleArn === void 0 ? void 0 : assumedClientRoleArn.substr(assumedClientRoleArn.indexOf("/") + 1); beforeAll(() => { setEnvCredentials(); }); afterAll(() => { cleanEnvCredentials(); }); beforeEach(() => { client = axios_1.default.create(); client.interceptors.request.use((0, __1.aws4Interceptor)({ options: { region, service, assumeRoleArn: assumedClientRoleArn }, instance: client, })); }); it.each([...methods, ...dataMethods])("signs HTTP %s request with assumed role credentials", (method) => __awaiter(void 0, void 0, void 0, function* () { const result = yield client.request({ url: apiGateway, method }); expect(result === null || result === void 0 ? void 0 : result.status).toEqual(200); expect(result && result.data.requestContext.authorizer.iam.userArn).toContain("/" + assumedRoleName + "/"); })); });