UNPKG

@aws/cloudfront-hosting-toolkit

Version:

CloudFront Hosting Toolkit offers the convenience of a managed frontend hosting service while retaining full control over the hosting and deployment infrastructure to make it your own.

269 lines (260 loc) 10.8 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { CrtSignerV4: () => CrtSignerV4 }); module.exports = __toCommonJS(src_exports); var import_signature_v4_multi_region = require("@aws-sdk/signature-v4-multi-region"); var import_util_user_agent_node = require("@aws-sdk/util-user-agent-node"); // src/CrtSignerV4.ts var import_querystring_parser = require("@smithy/querystring-parser"); var import_signature_v4 = require("@smithy/signature-v4"); var import_util_middleware = require("@smithy/util-middleware"); var import_aws_crt = require("aws-crt"); // src/constants.ts var AMZ_DATE_QUERY_PARAM = "X-Amz-Date"; var SIGNATURE_QUERY_PARAM = "X-Amz-Signature"; var TOKEN_QUERY_PARAM = "X-Amz-Security-Token"; var AMZ_DATE_HEADER = AMZ_DATE_QUERY_PARAM.toLowerCase(); var SIGNATURE_HEADER = SIGNATURE_QUERY_PARAM.toLowerCase(); var SHA256_HEADER = "x-amz-content-sha256"; var TOKEN_HEADER = TOKEN_QUERY_PARAM.toLowerCase(); var MAX_PRESIGNED_TTL = 60 * 60 * 24 * 7; // src/headerUtil.ts function deleteHeader(soughtHeader, headers) { soughtHeader = soughtHeader.toLowerCase(); for (const headerName of Object.keys(headers)) { if (soughtHeader === headerName.toLowerCase()) { delete headers[headerName]; } } } __name(deleteHeader, "deleteHeader"); // src/CrtSignerV4.ts function sdkHttpRequest2crtHttpRequest(sdkRequest) { deleteHeader(SHA256_HEADER, sdkRequest.headers); const headersArray = Object.entries(sdkRequest.headers); const crtHttpHeaders = new import_aws_crt.http.HttpHeaders(headersArray); const queryString = (0, import_signature_v4.getCanonicalQuery)(sdkRequest); return new import_aws_crt.http.HttpRequest(sdkRequest.method, sdkRequest.path + "?" + queryString, crtHttpHeaders); } __name(sdkHttpRequest2crtHttpRequest, "sdkHttpRequest2crtHttpRequest"); var _CrtSignerV4 = class _CrtSignerV4 { constructor({ credentials, region, service, sha256, applyChecksum = true, uriEscapePath = true, signingAlgorithm = import_aws_crt.auth.AwsSigningAlgorithm.SigV4 }) { this.service = service; this.sha256 = sha256; this.uriEscapePath = uriEscapePath; this.signingAlgorithm = signingAlgorithm; this.applyChecksum = applyChecksum; this.regionProvider = (0, import_util_middleware.normalizeProvider)(region); this.credentialProvider = (0, import_util_middleware.normalizeProvider)(credentials); import_aws_crt.io.enable_logging(import_aws_crt.io.LogLevel.ERROR); } async options2crtConfigure({ signingDate = /* @__PURE__ */ new Date(), signableHeaders, unsignableHeaders, signingRegion, signingService } = {}, viaHeader, payloadHash, expiresIn, _credentials) { const credentials = _credentials ?? await this.credentialProvider(); const region = signingRegion ?? await this.regionProvider(); const service = signingService ?? this.service; if ((signableHeaders == null ? void 0 : signableHeaders.has("x-amzn-trace-id")) || (signableHeaders == null ? void 0 : signableHeaders.has("user-agent"))) { throw new Error("internal check (x-amzn-trace-id, user-agent) is not supported to be included to sign with CRT."); } const headersUnsignable = getHeadersUnsignable(unsignableHeaders, signableHeaders); return { algorithm: this.signingAlgorithm, signature_type: viaHeader ? import_aws_crt.auth.AwsSignatureType.HttpRequestViaHeaders : import_aws_crt.auth.AwsSignatureType.HttpRequestViaQueryParams, provider: sdk2crtCredentialsProvider(credentials), region, service, date: new Date(signingDate), header_blacklist: headersUnsignable, use_double_uri_encode: this.uriEscapePath, /* Always set the body value by the result from SDK */ signed_body_value: payloadHash, signed_body_header: this.applyChecksum && viaHeader ? import_aws_crt.auth.AwsSignedBodyHeaderType.XAmzContentSha256 : import_aws_crt.auth.AwsSignedBodyHeaderType.None, expiration_in_seconds: expiresIn }; } async presign(originalRequest, options = {}) { if (options.expiresIn && options.expiresIn > MAX_PRESIGNED_TTL) { return Promise.reject( "Signature version 4 presigned URLs must have an expiration date less than one week in the future" ); } const request = (0, import_signature_v4.moveHeadersToQuery)((0, import_signature_v4.prepareRequest)(originalRequest)); const crtSignedRequest = await this.signRequest( request, await this.options2crtConfigure( options, false, await (0, import_signature_v4.getPayloadHash)(originalRequest, this.sha256), options.expiresIn ? options.expiresIn : 3600 ) ); request.query = this.getQueryParam(crtSignedRequest.path); return request; } async sign(toSign, options) { const request = (0, import_signature_v4.prepareRequest)(toSign); const crtSignedRequest = await this.signRequest( request, await this.options2crtConfigure(options, true, await (0, import_signature_v4.getPayloadHash)(toSign, this.sha256)) ); request.headers = crtSignedRequest.headers._flatten().reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); return request; } /** * Sign with alternate credentials to the ones provided in the constructor. */ async signWithCredentials(toSign, credentials, options) { const request = (0, import_signature_v4.prepareRequest)(toSign); const crtSignedRequest = await this.signRequest( request, await this.options2crtConfigure( options, true, await (0, import_signature_v4.getPayloadHash)(toSign, this.sha256), void 0, credentials ) ); request.headers = crtSignedRequest.headers._flatten().reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); return request; } /* Get the query parameters from crtPath */ getQueryParam(crtPath) { const start = crtPath.search(/\?/); const startHash = crtPath.search(/\#/); const end = startHash == -1 ? void 0 : startHash; const queryParam = {}; if (start == -1) { return queryParam; } const queryString = crtPath.slice(start + 1, end); return (0, import_querystring_parser.parseQueryString)(queryString); } async signRequest(requestToSign, crtConfig) { const request = sdkHttpRequest2crtHttpRequest(requestToSign); try { return await import_aws_crt.auth.aws_sign_request(request, crtConfig); } catch (error) { throw new Error(error); } } /** * Test-only API used for cross-library signing verification tests. Verify sign. * * Verifies: * (1) The canonical request generated during sigv4a signing of the request matches what is passed in * (2) The signature passed in is a valid ECDSA signature of the hashed string-to-sign derived from the * canonical request * * @param request The original request used for signing * @param signature the actual signature computed from a previous signing of the signable * @param expectedCanonicalRequest expected result when building the canonical request * @param eccPubKeyX the x coordinate of the public part of the ecc key to verify the signature * @param eccPubKeyY the y coordinate of the public part of the ecc key to verify the signature * @param options the RequestSigningArguments used for signing * * @return True, if the verification succeed. Otherwise, false. */ async verifySigv4aSigning(request, signature, expectedCanonicalRequest, eccPubKeyX, eccPubKeyY, options = {}) { const sdkRequest = (0, import_signature_v4.prepareRequest)(request); const crtRequest = sdkHttpRequest2crtHttpRequest(sdkRequest); const payloadHash = await (0, import_signature_v4.getPayloadHash)(request, this.sha256); const crtConfig = await this.options2crtConfigure(options, true, payloadHash); return import_aws_crt.auth.aws_verify_sigv4a_signing( crtRequest, crtConfig, expectedCanonicalRequest, signature, eccPubKeyX, eccPubKeyY ); } /* Verify presign */ async verifySigv4aPreSigning(request, signature, expectedCanonicalRequest, eccPubKeyX, eccPubKeyY, options = {}) { if (typeof signature != "string") { return false; } const sdkRequest = (0, import_signature_v4.prepareRequest)(request); const crtRequest = sdkHttpRequest2crtHttpRequest(sdkRequest); const crtConfig = await this.options2crtConfigure( options, false, await (0, import_signature_v4.getPayloadHash)(request, this.sha256), options.expiresIn ? options.expiresIn : 3600 ); return import_aws_crt.auth.aws_verify_sigv4a_signing( crtRequest, crtConfig, expectedCanonicalRequest, signature, eccPubKeyX, eccPubKeyY ); } }; __name(_CrtSignerV4, "CrtSignerV4"); var CrtSignerV4 = _CrtSignerV4; function sdk2crtCredentialsProvider(credentials) { return import_aws_crt.auth.AwsCredentialsProvider.newStatic( credentials.accessKeyId, credentials.secretAccessKey, credentials.sessionToken ); } __name(sdk2crtCredentialsProvider, "sdk2crtCredentialsProvider"); function getHeadersUnsignable(unsignableHeaders, signableHeaders) { if (!unsignableHeaders) { return []; } if (!signableHeaders) { return [...unsignableHeaders]; } const result = /* @__PURE__ */ new Set([...unsignableHeaders]); for (let it = signableHeaders.values(), val = null; val = it.next().value; ) { if (result.has(val)) { result.delete(val); } } return [...result]; } __name(getHeadersUnsignable, "getHeadersUnsignable"); // src/index.ts import_signature_v4_multi_region.signatureV4CrtContainer.CrtSignerV4 = CrtSignerV4; import_util_user_agent_node.crtAvailability.isCrtAvailable = true; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { CrtSignerV4 });