UNPKG

@aws-sdk/middleware-signing

Version:

[![NPM version](https://img.shields.io/npm/v/@aws-sdk/middleware-signing/latest.svg)](https://www.npmjs.com/package/@aws-sdk/middleware-signing) [![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/middleware-signing.svg)](https://www.npmjs.com/packag

222 lines (214 loc) 9.06 kB
'use strict'; var propertyProvider = require('@smithy/property-provider'); var signatureV4 = require('@smithy/signature-v4'); var utilMiddleware = require('@smithy/util-middleware'); var protocolHttp = require('@smithy/protocol-http'); const CREDENTIAL_EXPIRE_WINDOW = 300000; const resolveAwsAuthConfig = (input) => { const normalizedCreds = createConfigBoundCredentialProvider(input); const { signingEscapePath = true, systemClockOffset = input.systemClockOffset || 0, sha256 } = input; let signer; if (input.signer) { signer = utilMiddleware.normalizeProvider(input.signer); } else if (input.regionInfoProvider) { signer = () => utilMiddleware.normalizeProvider(input.region)() .then(async (region) => [ (await input.regionInfoProvider(region, { useFipsEndpoint: await input.useFipsEndpoint(), useDualstackEndpoint: await input.useDualstackEndpoint(), })) || {}, region, ]) .then(([regionInfo, region]) => { const { signingRegion, signingService } = regionInfo; input.signingRegion = input.signingRegion || signingRegion || region; input.signingName = input.signingName || signingService || input.serviceId; const params = { ...input, credentials: normalizedCreds, region: input.signingRegion, service: input.signingName, sha256, uriEscapePath: signingEscapePath, }; const SignerCtor = input.signerConstructor || signatureV4.SignatureV4; return new SignerCtor(params); }); } else { signer = async (authScheme) => { authScheme = Object.assign({}, { name: "sigv4", signingName: input.signingName || input.defaultSigningName, signingRegion: await utilMiddleware.normalizeProvider(input.region)(), properties: {}, }, authScheme); const isSigv4a = authScheme?.name === "sigv4a"; const signingRegion = authScheme.signingRegion; const signingService = authScheme.signingName; let regionForSigner; if (isSigv4a) { regionForSigner = input.signingRegion || signingRegion; } else { input.signingRegion = input.signingRegion || signingRegion; regionForSigner = input.signingRegion; } input.signingName = input.signingName || signingService || input.serviceId; const params = { ...input, credentials: normalizedCreds, region: regionForSigner, service: input.signingName, sha256, uriEscapePath: signingEscapePath, }; const SignerCtor = input.signerConstructor || signatureV4.SignatureV4; return new SignerCtor(params); }; } return Object.assign(input, { systemClockOffset, signingEscapePath, credentials: normalizedCreds, signer, }); }; const resolveSigV4AuthConfig = (input) => { const normalizedCreds = createConfigBoundCredentialProvider(input); const { signingEscapePath = true, systemClockOffset = input.systemClockOffset || 0, sha256 } = input; let signer; if (input.signer) { signer = utilMiddleware.normalizeProvider(input.signer); } else { signer = utilMiddleware.normalizeProvider(new signatureV4.SignatureV4({ credentials: normalizedCreds, region: input.region, service: input.signingName, sha256, uriEscapePath: signingEscapePath, })); } return Object.assign(input, { systemClockOffset, signingEscapePath, credentials: normalizedCreds, signer, }); }; const normalizeCredentialProvider = (credentials) => { if (typeof credentials === "function") { return propertyProvider.memoize(credentials, (credentials) => credentials.expiration !== undefined && credentials.expiration.getTime() - Date.now() < CREDENTIAL_EXPIRE_WINDOW, (credentials) => credentials.expiration !== undefined); } return utilMiddleware.normalizeProvider(credentials); }; const createConfigBoundCredentialProvider = (input) => { const normalizedCredentialsProvider = input.credentials ? normalizeCredentialProvider(input.credentials) : input.credentialDefaultProvider(Object.assign({}, input, { parentClientConfig: input, })); const normalizedCreds = async () => normalizedCredentialsProvider({ callerClientConfig: { region: utilMiddleware.normalizeProvider(input.region), profile: input.profile, }, }); return normalizedCreds; }; const getSkewCorrectedDate = (systemClockOffset) => new Date(Date.now() + systemClockOffset); const isClockSkewed = (clockTime, systemClockOffset) => Math.abs(getSkewCorrectedDate(systemClockOffset).getTime() - clockTime) >= 300000; const getUpdatedSystemClockOffset = (clockTime, currentSystemClockOffset) => { const clockTimeInMs = Date.parse(clockTime); if (isClockSkewed(clockTimeInMs, currentSystemClockOffset)) { return clockTimeInMs - Date.now(); } return currentSystemClockOffset; }; const awsAuthMiddleware = (options) => (next, context) => async function (args) { if (!protocolHttp.HttpRequest.isInstance(args.request)) return next(args); let authScheme; let signer; const firstAuthScheme = context.endpointV2?.properties?.authSchemes?.[0]; const secondAuthScheme = context.endpointV2?.properties?.authSchemes?.[1]; const firstAuthSchemeIsSigv4a = firstAuthScheme?.name === "sigv4a"; if (firstAuthSchemeIsSigv4a && secondAuthScheme) { signer = await options.signer((authScheme = firstAuthScheme)); const uncheckedSigner = signer; const sigv4aAvailable = (() => { if (typeof uncheckedSigner?.getSigv4aSigner === "function") { if (uncheckedSigner?.signerOptions?.runtime !== "node") { return false; } try { uncheckedSigner.getSigv4aSigner(); return true; } catch (e) { } } return false; })(); if (!sigv4aAvailable) { signer = await options.signer((authScheme = secondAuthScheme)); } } else { signer = await options.signer((authScheme = firstAuthScheme)); } let signedRequest; const multiRegionOverride = authScheme?.name === "sigv4a" ? authScheme?.signingRegionSet?.join(",") : undefined; const signingOptions = { signingDate: getSkewCorrectedDate(options.systemClockOffset), signingRegion: multiRegionOverride || context["signing_region"], signingService: context["signing_service"], }; if (context.s3ExpressIdentity) { const sigV4MultiRegion = signer; signedRequest = await sigV4MultiRegion.signWithCredentials(args.request, context.s3ExpressIdentity, signingOptions); if (signedRequest.headers["X-Amz-Security-Token"] || signedRequest.headers["x-amz-security-token"]) { throw new Error("X-Amz-Security-Token must not be set for s3-express requests."); } } else { signedRequest = await signer.sign(args.request, signingOptions); } const output = await next({ ...args, request: signedRequest, }).catch((error) => { const serverTime = error.ServerTime ?? getDateHeader(error.$response); if (serverTime) { options.systemClockOffset = getUpdatedSystemClockOffset(serverTime, options.systemClockOffset); } throw error; }); const dateHeader = getDateHeader(output.response); if (dateHeader) { options.systemClockOffset = getUpdatedSystemClockOffset(dateHeader, options.systemClockOffset); } return output; }; const getDateHeader = (response) => protocolHttp.HttpResponse.isInstance(response) ? response.headers?.date ?? response.headers?.Date : undefined; const awsAuthMiddlewareOptions = { name: "awsAuthMiddleware", tags: ["SIGNATURE", "AWSAUTH"], relation: "after", toMiddleware: "retryMiddleware", override: true, }; const getAwsAuthPlugin = (options) => ({ applyToStack: (clientStack) => { clientStack.addRelativeTo(awsAuthMiddleware(options), awsAuthMiddlewareOptions); }, }); const getSigV4AuthPlugin = getAwsAuthPlugin; exports.awsAuthMiddleware = awsAuthMiddleware; exports.awsAuthMiddlewareOptions = awsAuthMiddlewareOptions; exports.getAwsAuthPlugin = getAwsAuthPlugin; exports.getSigV4AuthPlugin = getSigV4AuthPlugin; exports.resolveAwsAuthConfig = resolveAwsAuthConfig; exports.resolveSigV4AuthConfig = resolveSigV4AuthConfig;