aws-spa
Version:
A no-brainer script to deploy a single page app on AWS
216 lines (167 loc) • 6.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.updateRecord = exports.needsUpdateRecord = exports.findHostedZone = exports.createHostedZone = exports.createCertificateValidationDNSRecord = void 0;
var _inquirer = _interopRequireDefault(require("inquirer"));
var _awsHelper = require("./aws-helper");
var _awsServices = require("./aws-services");
var _logger = require("./logger");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const findHostedZone = async domainName => {
_logger.logger.info(`[route53] 🔍 Looking for a hosted zone matching "${domainName}"...`);
const hostedZones = await (0, _awsHelper.getAll)(async (nextMarker, page) => {
_logger.logger.info(`[route53] 🔍 List hosted zones (page ${page})...`);
const {
HostedZones,
NextMarker
} = await _awsServices.route53.listHostedZones({
Marker: nextMarker
});
if (!HostedZones) {
_logger.logger.info(`[route53] 🧐 No hosted zones found`);
return {
items: [],
nextMarker: undefined
};
}
return {
items: HostedZones,
nextMarker: NextMarker
};
});
const matchingHostedZones = hostedZones.filter(hostedZone => domainName.endsWith(hostedZone.Name.replace(/\.$/g, '')));
if (matchingHostedZones.length === 1) {
_logger.logger.info(`[route53] 👍 Found Hosted zone: "${matchingHostedZones[0].Name}"`);
return matchingHostedZones[0];
}
if (matchingHostedZones.length > 1) {
_logger.logger.warn(`[route53] ⚠️ Found multiple hosted zones: ${matchingHostedZones.map(hostedZone => `"${hostedZone.Name}"`).join(', ')}. There first hosted zone will be used. If this is an issue, please open an issue on https://github.com/lalalilo/aws-spa/issues`);
return matchingHostedZones[0];
}
_logger.logger.info(`[route53] 🧐 No matching hosted zones found`);
return null;
};
exports.findHostedZone = findHostedZone;
const createHostedZone = async domainName => {
_logger.logger.info(`[route53] ✏️ Creating hosted zone "${domainName}"...`);
const {
HostedZone
} = await _awsServices.route53.createHostedZone({
Name: domainName,
CallerReference: `aws-spa-${Date.now()}`
});
if (!HostedZone) {
throw new Error(`[route53] ❌ Failed to create hosted zone "${domainName}"`);
}
return HostedZone;
};
exports.createHostedZone = createHostedZone;
const needsUpdateRecord = async (hostedZoneId, domainName, cloudfrontDomainName) => {
if (!hostedZoneId) {
_logger.logger.warn(`[route53] 🧐 hostedZoneId is undefined`);
return false;
}
_logger.logger.info(`[route53] 🔍 Looking for a matching record...`);
const {
ResourceRecordSets
} = await _awsServices.route53.listResourceRecordSets({
HostedZoneId: hostedZoneId,
StartRecordName: domainName
});
if (!ResourceRecordSets || ResourceRecordSets.length === 0) {
_logger.logger.info(`[route53] 🔍 No matching record found.`);
return true;
}
for (const record of ResourceRecordSets) {
if (record.Name !== `${domainName}.`) {
continue;
}
if (record.Type === 'CNAME' && record.ResourceRecords) {
if (record.ResourceRecords[0].Value === `${cloudfrontDomainName}.`) {
_logger.logger.info(`[route53] 👍 Found well configured CNAME matching record`);
return false;
}
const {
continueUpdate
} = await _inquirer.default.prompt([{
type: 'confirm',
name: 'continueUpdate',
message: `[Route53] CNAME Record for "${domainName}" value is "${record.ResourceRecords[0].Value}". Would you like to update it to "${cloudfrontDomainName}."?`,
default: false
}]);
if (continueUpdate) {
return true;
} else {
_logger.logger.warn('⚠️ website might not be served correctly unless you allow route53 record update');
return false;
}
}
if (record.Type === 'A' && record.AliasTarget) {
if (record.AliasTarget.HostedZoneId === 'Z2FDTNDATAQYW2' && record.AliasTarget.DNSName === `${cloudfrontDomainName}.`) {
_logger.logger.info(`[route53] 👍 Found well configured A matching record`);
return false;
}
const {
continueUpdate
} = await _inquirer.default.prompt([{
type: 'confirm',
name: 'continueUpdate',
message: `[Route53] A Record for "${domainName}" value is "${record.AliasTarget.HostedZoneId}:${record.AliasTarget.DNSName}". Would you like to update it to "${record.AliasTarget.HostedZoneId}:${cloudfrontDomainName}."?`,
default: false
}]);
if (continueUpdate) {
return true;
} else {
_logger.logger.warn('⚠️ website might not be served correctly unless you allow route53 record update');
return false;
}
}
}
};
exports.needsUpdateRecord = needsUpdateRecord;
const updateRecord = async (hostedZoneId, domainName, cloudfrontDomainName) => {
if (!hostedZoneId) {
throw new Error(`[route53] ❌ hostedZoneId is undefined`);
}
_logger.logger.info(`[route53] ✏️ Upserting A: "${domainName}." → ${cloudfrontDomainName}...`);
await _awsServices.route53.changeResourceRecordSets({
HostedZoneId: hostedZoneId,
ChangeBatch: {
Changes: [{
Action: 'UPSERT',
ResourceRecordSet: {
Name: `${domainName}.`,
AliasTarget: {
HostedZoneId: 'Z2FDTNDATAQYW2',
// https://docs.aws.amazon.com/general/latest/gr/rande.html#cf_region
DNSName: `${cloudfrontDomainName}.`,
EvaluateTargetHealth: false
},
Type: 'A'
}
}]
}
});
};
exports.updateRecord = updateRecord;
const createCertificateValidationDNSRecord = async (record, hostedZoneId) => {
_logger.logger.info(`[Route53] Creating record ${record.Type}:${record.Name}=${record.Value} to validate SSL certificate`);
await _awsServices.route53.changeResourceRecordSets({
HostedZoneId: hostedZoneId,
ChangeBatch: {
Changes: [{
Action: 'UPSERT',
ResourceRecordSet: {
Name: record.Name,
Type: record.Type,
ResourceRecords: [{
Value: record.Value
}],
TTL: 3600
}
}]
}
});
};
exports.createCertificateValidationDNSRecord = createCertificateValidationDNSRecord;