Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const {deployStack, deployParts, deployFull} = require('./lib/deployStack')
const {deployTemplate} = require('./lib/deployTemplate')
const deleteStack = require('./lib/deleteStack')
const stackExists = require('./lib/stackExists')
const stackResourceExists = require('./lib/stackResourceExists')
const resourceExists = require('./lib/resourceExists')

module.exports.generateTemplate = generateTemplate;
Expand All @@ -12,6 +13,7 @@ module.exports.deployFull = deployFull;
module.exports.deployTemplate = deployTemplate;
module.exports.deleteStack = deleteStack;
module.exports.stackExists = stackExists;
module.exports.stackResourceExists = stackResourceExists;
module.exports.resourceExists = resourceExists;


2 changes: 1 addition & 1 deletion lib/deleteStack.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require('dotenv').config();
//require('dotenv').config();
var AWS = require('aws-sdk');
var cloudformation = new AWS.CloudFormation({apiVersion: '2010-05-15'});

Expand Down
68 changes: 68 additions & 0 deletions lib/deployCertificate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
require('dotenv').config();
var AWS = require('aws-sdk');
var acm = new AWS.ACM({apiVersion: '2015-12-08'});
var dns = require('@torus-tools/domains')
var {AcmCertificate} = require('./resourceExists')

function createCertificate(domain){
return new Promise((resolve, reject) => {
AcmCertificate(domain).then(data=>{
if(data) resolve(data)
else {
var params = {
DomainName: domain, /* required */
DomainValidationOptions: [
{
DomainName: domain,
ValidationDomain: domain,
},
],
SubjectAlternativeNames: [
`*.${domain}`,
],
ValidationMethod: 'DNS'
};
acm.requestCertificate(params).promise()
.then(data=>resolve(data.CertificateArn))
.catch(err=>reject(err))
}
}).catch(err=>reject(err))
})
}


function getCname(certificateArn){
return new Promise((resolve, reject) => {
var params = {CertificateArn: certificateArn};
acm.describeCertificate(params).promise()
.then(data=> {
if(data.Certificate.DomainValidationOptions[0].ResourceRecord){
let cName = data.Certificate.DomainValidationOptions[0].ResourceRecord.Name;
let cValue = data.Certificate.DomainValidationOptions[0].ResourceRecord.Value;
resolve({"cName": cName, "cValue": cValue});
}
else reject('error no CNAME available for the given certificate')
})
})
}

function validateCertificate(config, cName, cValue) {
return new Promise((resolve, reject) => {
let records = [
{
data: cValue,
name: cName,
type: 'CNAME'
}
]
dns[config.providers.dns].upsertRecords(domain, records)
.then(resolve('All Done!'))
.catch(err=>reject(err))
})
}

module.exports = {
createCertificate,
getCname,
validateCertificate,
}
215 changes: 97 additions & 118 deletions lib/deployStack.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ const AWS = require('aws-sdk');
var cloudformation = new AWS.CloudFormation({apiVersion: '2010-05-15'});

const supported_providers = {
domain:['aws', 'godaddy'],
registrar:['aws', 'godaddy'],
bucket: ['aws'],
dns:['aws', 'godaddy'],
storage: ['aws'],
cdn: ['aws'],
certificate: ['aws']
ssl: ['aws']
}

async function deployStack(domain, stack, config, content, overwrite, local, cli){
Expand Down Expand Up @@ -75,8 +75,6 @@ async function deployStack(domain, stack, config, content, overwrite, local, cli
function deployParts(domain, stack, config, partialTemplate, partialStack, fullTemplate, template, content, cli){
return new Promise((resolve, reject) => {
let size = 0;
//console.log('PARTIAL STACK ', partialStack)
//console.log(template)
for(let key in partialStack) {
size += 1;
//should add an or at the end if the template does exist but the bucket policy isnt public
Expand All @@ -103,134 +101,115 @@ function deployParts(domain, stack, config, partialTemplate, partialStack, fullT
//before deploy full must obtain nameservers for route53
function deployFull(domain, stack, config, fullTemplate, partialTemplate, content, cli){
return new Promise((resolve, reject) => {
const url = `http://${domain}.s3-website-${process.env.AWS_REGION}.amazonaws.com`;
let arb = []
let arr = []
let ns = ''
//Upload Files
if(content) {
arb.push('content')
listFiles().then(data => {
uploadContent(domain, data, false, false, null, cli).then(()=>{
arr.push(1)
if(arb.includes('ns')) cli? cli.action.start('Updating domain nameservers') : console.log('Updating domain nameservers...')
else if(arb.includes('mns')) console.log('\n\x1b[33mPlease update the nameservers for this domain to the following:\x1b[0m\n'+ns)
if(arr.length >= 3) resolve(url)
}).catch(err => reject(err))
}).catch(err => reject(err))
}
else {
arr.push(1)
if(arr.length >= 3) resolve(url)
}
let fullstack = false
let done = false
//Transfer Nameservers
if(stack.dns && config.providers.dns !== config.providers.domain){
transferNs(domain, stack, config, cli).then(data=>{
if(content) {
listFiles().then(data => {
uploadContent(domain, data, false, false, null, cli).then(()=>{
done? resolve('All Done!'): done=true
if(fullstack) cli? cli.action.start('Deploying additional resources'): console.log('Deploying additional resources')
}).catch(err => reject(err))
}).catch(err => reject(err))
}
if(JSON.stringify(fullTemplate) !== JSON.stringify(partialTemplate)){
fullstack = true
deployTemplate(domain, fullTemplate).then(()=>{
if(cli) cli.action.stop()
CloudFrontDist(domain).then(data => {
cli? cli.action.start('creating records'): console.log('creating records...')
createRecords(domain, stack, config, data.domain, cli)
.then(data=>{
if(cli) cli.action.stop()
done? resolve('All Done!'): done=true
})
})
})
}
else done? resolve('All Done!'): done=true
})
})
}

function transferNs(domain, stack, config, cli){
return new Promise((resolve, reject)=>{
let ns = ''
if(stack.dns && config.providers.dns !== config.providers.registrar){
domains[config.providers.dns].getNameservers(domain).then(nameservers => {
if(supported_providers.domain.includes(config.providers.domain)) {
arb.push('ns')
//cli? cli.action.start('Updating domain nameservers') : console.log('Updating domain nameservers...')
domains[config.providers.domain].updateNameservers(domain, nameservers).then(data=>{
arr.push(2)
if(cli) cli.action.stop()
if(arb.includes('stack')) cli? cli.action.start('Deploying additional reosurces'): console.log('Deploying additional resources...')
if(arr.length >= 3) resolve(url)
if(supported_providers.registrar.includes(config.providers.registrar)) {
//update nameservers automatrically for godaddy & AWS
cli? cli.action.start('Updating domain nameservers') : console.log('Updating domain nameservers...')
domains[config.providers.registrar].updateNameservers(domain, nameservers).then(data=>{
resolve(data)
}).catch(err => reject(err))
}
else {
arb.push('mns')
//manually update unsupported providers
//manually update nameservers for unsupported providers
for(let n of nameservers) ns += n+'\n'
//console.log('Please update the nameservers for this domain to the following:\n', ns)
arr.push(2)
if(cli) cli.action.stop()
if(arb.includes('stack')) cli? cli.action.start('Deploying additional reosurces'): console.log('Deploying additional resources...')
if(arr.length >= 3) resolve(url)
console.log('\n\x1b[33mPlease update the nameservers for this domain to the following:\x1b[0m\n'+ns)
cli.prompt('Have you finished updating the nameservers?').then(res=>{
if(res==='y' || res==='yes' || res==='Y' || res==='YES') resolve('done')
else reject('You must update your nameservers when the DNS is different to the registrar')
})
}
}).catch(err => reject(err))
}
else {
arr.push(2)
if(arr.length >= 3) resolve(url)
}
//create and verify certificate then
//Deploy the Full Stack with CDN
if(JSON.stringify(fullTemplate) !== JSON.stringify(partialTemplate)){
arb.push('stack')
//cli? cli.action.start('Deploying additional reosurces') : console.log('Deploying additional resources...')
deployTemplate(domain, fullTemplate).then(()=>{
//if(cli) cli.action.stop()
CloudFrontDist(domain).then(data => {
//must get the SSL certificate created for the stack
let records = [
{
data: data.domain,
name: 'www',
ttl: 3600,
type: 'CNAME'
}
]
if(config.providers['dns'] !== 'aws') {
if(supported_providers.dns.includes(config.providers.dns)){
cli? cli.action.start('creating DNS records'): console.log('creating DNS records...')
let recordReroute = false
let redirectUrl = stack.https?'https://www.'+domain:'http://www.'+domain
domains[config.providers.dns].upsertRecords(domain, records).then(()=>{
if(recordReroute) {
arr.push(3)
if(cli) cli.action.stop()
if(arr.length >= 3) resolve(url)
}
else recordReroute = true
}).catch(err => reject(err))
domains[config.providers.dns].createRedirect(domain, redirectUrl).then(()=>{
if(recordReroute) {
arr.push(3)
if(cli) cli.action.stop()
if(arr.length >= 3) resolve(url)
}
else recordReroute = true
}).catch(err => reject(err))
}
else {
console.log('Please create a DNS record with the following properties:\n', records[0], '\n', 'Then create a 301 redirect from the root to www.')
arr.push(3)
if(arr.length >= 3) resolve(url)
}
}
else {
arr.push(3)
if(arr.length >= 3) resolve(url)
}
})
})
}
else {
arr.push(3)
if(arr.length >= 3) resolve(url)
}
})
}

/* function transferDns(domain, domainProvider, dnsProvider){
if(domainProvider === dnsProvider) resolve(null)
else {
//get the nameservers
if(providers.domain.includes(provider)) updateNameservers(nameservers).then(()=>resolve({auotmatic:true, nameservers:nameservers}))
else resolve({auotmatic:false, nameservers:nameservers})
}
} */
function createRecords(domain, stack, config, url, cli){
return new Promise((resolve, reject)=> {
let records = [
{
data: url,
name: 'www',
ttl: 3600,
type: 'CNAME'
}
]
if(config.providers['dns'] !== 'aws') {
if(supported_providers.dns.includes(config.providers.dns)){
cli? cli.action.start('creating DNS records'): console.log('creating DNS records...')
let recordReroute = false
let redirectUrl = stack.https?'https://www.'+domain:'http://www.'+domain
domains[config.providers.dns].upsertRecords(domain, records).then(()=>{
recordReroute? resolve('All Done'): recordReroute = true
}).catch(err => reject(err))
domains[config.providers.dns].createRedirect(domain, redirectUrl).then(()=>{
recordReroute? resolve('All Done'): recordReroute = true
}).catch(err => reject(err))
}
else {
console.log('Please create a DNS record with the following properties:\n', records[0], '\n', 'Then create a 301 redirect from the root to www.')
resolve('All Done')
}
}
})
}

/* function publishUpdatedContent(uploads, files, force){
let filesArr = uploads.keys()
if(files) filesArr = files
if(force) for(let key of filesArr) upload(key)
else for(let key of filesArr) if(uploads[key].last_mod > uploads[key].last_upload) upload(key)
//FOR S3
/* ResourceRecordSet: {
AliasTarget: {
DNSName: `s3-website-${process.env.AWS_REGION}.amazonaws.com`,
EvaluateTargetHealth: false,
HostedZoneId: 'Z3AQBSTGFYJSTF' // a code depending on your region and resource for more info refer to https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_website_region_endpoints
},
Name: wname,
Type: "A"
} */

/*
function upload(filePath){
file = fs.readFileSync(filePath)
uploadFile(file, filePath)
//FOR CLOUDFRONT
/* ResourceRecordSet: {
Name: domain,
Type: 'A',
ResourceRecords: [],
AliasTarget:
{
HostedZoneId: obj.hostedZoneId,
DNSName: data.Distribution.DomainName,
EvaluateTargetHealth: false
}
} */


Expand Down
8 changes: 4 additions & 4 deletions lib/generateTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ module.exports = function genTemplate(domain, stack, config, template, records,
}
//console.log('STACK ', stack, template)
let defaults = templateDefaults(domain, stack, config)
if(!config || !config.index) config.index = 'index.html'
if(!config || !config.error) config.error = 'error.html'
//if(!config || !config.options || !config.options.index) config.index = 'index.html'
//if(!config || !config.options || !config.options.error) config.error = 'error.html'
let new_temp = template? template : initialTemplate
if(stack.bucket) new_temp.Resources['BucketPolicy'] = defaults['BucketPolicy']
if(records && stack.dns && config.providers.dns === 'aws') new_temp.Resources['RecordSet'] = defaults['RecordSet']
Expand All @@ -52,8 +52,8 @@ module.exports = function genTemplate(domain, stack, config, template, records,
}
//console.log('STACK2 ', stack, new_temp)
}
//custom stuff for the CDN depending on the https option
if(stack.https && config.providers.https === 'aws'){
//custom stuff for the CDN depending on the ssl option
if(stack.ssl && config.providers.ssl === 'aws'){
new_temp.Resources.CloudFrontDist.Properties.DistributionConfig["ViewerCertificate"] = {
"AcmCertificateArn" : { "Ref": "AcmCertificate"},
"MinimumProtocolVersion" : "TLSv1.2_2018",
Expand Down
2 changes: 1 addition & 1 deletion lib/resourceExists.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//load files from the .env file
require('dotenv').config();
//require('dotenv').config();
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
var route53 = new AWS.Route53({apiVersion: '2013-04-01'});
Expand Down
15 changes: 15 additions & 0 deletions lib/stackResourceExists.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require('dotenv').config();
var AWS = require('aws-sdk');
var cloudformation = new AWS.CloudFormation({apiVersion: '2010-05-15'});

module.exports = function getStackResources(domain){
return new Promise((resolve, reject)=> {
let stackName = domain.split('.').join('') + 'Stack'
var params = {StackName: stackName};
cloudformation.describeStackResources(params).promise().then(data=>{
let resources = {}
for(let obj of data.StackResources) resources[obj.LogicalResourceId]=obj.PhysicalResourceId
resolve(resources)
}).catch(err=> reject(err))
})
}
Loading