@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
JavaScript
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
});