serverless-domain-manager
Version:
Serverless plugin for managing custom domains with API Gateways.
152 lines (151 loc) • 7.96 kB
JavaScript
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 };
};
const globals_1 = __importDefault(require("../globals"));
const logging_1 = __importDefault(require("../logging"));
const client_route_53_1 = require("@aws-sdk/client-route-53");
const utils_1 = require("../utils");
class Route53Wrapper {
constructor(credentials, region) {
// not null and not undefined
const serviceEndpoint = globals_1.default.getServiceEndpoint("route53");
if (credentials) {
this.region = region || globals_1.default.getRegion();
this.route53 = new client_route_53_1.Route53Client({
credentials,
region: this.region,
retryStrategy: globals_1.default.getRetryStrategy(),
requestHandler: globals_1.default.getRequestHandler(),
endpoint: serviceEndpoint
});
}
else {
this.region = globals_1.default.getRegion();
this.route53 = new client_route_53_1.Route53Client({
region: this.region,
retryStrategy: globals_1.default.getRetryStrategy(),
requestHandler: globals_1.default.getRequestHandler(),
endpoint: serviceEndpoint
});
}
}
/**
* Gets Route53 HostedZoneId from user or from AWS
*/
getRoute53HostedZoneId(domain, isHostedZonePrivate) {
return __awaiter(this, void 0, void 0, function* () {
if (domain.hostedZoneId) {
logging_1.default.logInfo(`Selected specific hostedZoneId ${domain.hostedZoneId}`);
return domain.hostedZoneId;
}
const isPrivateDefined = typeof isHostedZonePrivate !== "undefined";
if (isPrivateDefined) {
const zoneTypeString = isHostedZonePrivate ? "private" : "public";
logging_1.default.logInfo(`Filtering to only ${zoneTypeString} zones.`);
}
let hostedZones = [];
try {
hostedZones = yield (0, utils_1.getAWSPagedResults)(this.route53, "HostedZones", "Marker", "NextMarker", new client_route_53_1.ListHostedZonesCommand({}));
logging_1.default.logInfo(`Found hosted zones list: ${hostedZones.map((zone) => zone.Name)}.`);
}
catch (err) {
throw new Error(`Unable to list hosted zones in Route53.\n${err.message}`);
}
// removing the first part of the domain name, api.test.com => test.com
const domainNameHost = domain.givenDomainName.substring(domain.givenDomainName.indexOf(".") + 1);
const targetHostedZone = hostedZones
.filter((hostedZone) => {
return !isPrivateDefined || isHostedZonePrivate === hostedZone.Config.PrivateZone;
})
.filter((hostedZone) => {
const hostedZoneName = hostedZone.Name.replace(/\.$/, "");
return domain.givenDomainName === hostedZoneName || domainNameHost.endsWith(hostedZoneName);
})
.sort((zone1, zone2) => zone2.Name.length - zone1.Name.length)
.shift();
if (targetHostedZone) {
return targetHostedZone.Id.replace("/hostedzone/", "");
}
else {
throw new Error(`Could not find hosted zone '${domain.givenDomainName}'`);
}
});
}
/**
* Change A Alias record through Route53 based on given action
* @param action: String descriptor of change to be made. Valid actions are ['UPSERT', 'DELETE']
* @param domain: DomainInfo object containing info about custom domain
*/
changeResourceRecordSet(action, domain) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c;
if (domain.createRoute53Record === false) {
logging_1.default.logInfo(`Skipping ${action === client_route_53_1.ChangeAction.DELETE ? "removal" : "creation"} of Route53 record.`);
return;
}
logging_1.default.logInfo(`Creating/updating route53 record for '${domain.givenDomainName}'.`);
// Set up parameters
const route53HostedZoneId = yield this.getRoute53HostedZoneId(domain, domain.hostedZonePrivate);
const route53Params = domain.route53Params;
const route53healthCheck = route53Params.healthCheckId ? { HealthCheckId: route53Params.healthCheckId } : {};
const domainInfo = (_a = domain.domainInfo) !== null && _a !== void 0 ? _a : {
domainName: domain.givenDomainName,
hostedZoneId: route53HostedZoneId
};
let routingOptions = {};
if (route53Params.routingPolicy === globals_1.default.routingPolicies.latency) {
routingOptions = Object.assign({ Region: this.region, SetIdentifier: (_b = route53Params.setIdentifier) !== null && _b !== void 0 ? _b : domainInfo.domainName }, route53healthCheck);
}
if (route53Params.routingPolicy === globals_1.default.routingPolicies.weighted) {
routingOptions = Object.assign({ Weight: route53Params.weight, SetIdentifier: (_c = route53Params.setIdentifier) !== null && _c !== void 0 ? _c : domainInfo.domainName }, route53healthCheck);
}
let hostedZoneIds;
if (domain.splitHorizonDns) {
hostedZoneIds = yield Promise.all([
this.getRoute53HostedZoneId(domain, false),
this.getRoute53HostedZoneId(domain, true)
]);
}
else {
hostedZoneIds = [route53HostedZoneId];
}
const recordsToCreate = domain.createRoute53IPv6Record ? [client_route_53_1.RRType.A, client_route_53_1.RRType.AAAA] : [client_route_53_1.RRType.A];
for (const hostedZoneId of hostedZoneIds) {
const changes = recordsToCreate.map((Type) => ({
Action: action,
ResourceRecordSet: Object.assign({ AliasTarget: {
DNSName: domainInfo.domainName,
EvaluateTargetHealth: false,
HostedZoneId: domainInfo.hostedZoneId
}, Name: domain.givenDomainName, Type }, routingOptions)
}));
const params = {
ChangeBatch: {
Changes: changes,
Comment: `Record created by "${globals_1.default.pluginName}"`
},
HostedZoneId: hostedZoneId
};
// Make API call
try {
yield this.route53.send(new client_route_53_1.ChangeResourceRecordSetsCommand(params));
}
catch (err) {
throw new Error(`Failed to ${action} ${recordsToCreate.join(",")} Alias for '${domain.givenDomainName}':\n
${err.message}`);
}
}
});
}
}
module.exports = Route53Wrapper;
;