2017-10-28 22:18:07 +02:00
'use strict' ;
module . exports = exports = {
add : add ,
get : get ,
getAll : getAll ,
update : update ,
del : del ,
2018-12-07 14:35:04 -08:00
clear : clear ,
2017-10-28 22:18:07 +02:00
2018-01-11 00:31:51 -08:00
fqdn : fqdn ,
2019-01-04 18:44:54 -08:00
getName : getName ,
2018-01-01 19:19:07 -08:00
2018-02-08 12:05:29 -08:00
getDnsRecords : getDnsRecords ,
upsertDnsRecords : upsertDnsRecords ,
removeDnsRecords : removeDnsRecords ,
2017-10-29 00:15:11 +02:00
2018-02-08 12:05:29 -08:00
waitForDnsRecord : waitForDnsRecord ,
2017-10-29 00:15:11 +02:00
2018-04-27 11:38:09 -07:00
removePrivateFields : removePrivateFields ,
2018-06-25 15:12:20 -07:00
removeRestrictedFields : removeRestrictedFields ,
2018-04-27 11:38:09 -07:00
2018-08-30 20:05:08 -07:00
validateHostname : validateHostname ,
2018-09-11 22:46:17 -07:00
makeWildcard : makeWildcard ,
2018-11-05 19:09:58 -08:00
parentDomain : parentDomain ,
2019-09-23 14:34:29 -07:00
checkDnsRecords : checkDnsRecords ,
2018-12-15 15:27:16 -08:00
prepareDashboardDomain : prepareDashboardDomain ,
2018-12-13 22:24:26 -08:00
2019-02-09 17:33:52 -08:00
SECRET _PLACEHOLDER : String . fromCharCode ( 0x25CF ) . repeat ( 8 )
2017-10-28 22:18:07 +02:00
} ;
var assert = require ( 'assert' ) ,
2018-12-14 09:57:28 -08:00
async = require ( 'async' ) ,
2019-10-23 10:02:04 -07:00
BoxError = require ( './boxerror.js' ) ,
2018-08-30 20:05:08 -07:00
constants = require ( './constants.js' ) ,
2017-12-06 11:33:09 +05:30
debug = require ( 'debug' ) ( 'box:domains' ) ,
2017-10-28 22:18:07 +02:00
domaindb = require ( './domaindb.js' ) ,
2018-11-10 00:43:46 -08:00
eventlog = require ( './eventlog.js' ) ,
2018-01-30 12:23:27 -08:00
reverseProxy = require ( './reverseproxy.js' ) ,
2018-01-30 11:30:35 -08:00
safe = require ( 'safetydance' ) ,
2019-07-26 10:49:29 -07:00
settings = require ( './settings.js' ) ,
2017-10-28 23:23:58 +02:00
sysinfo = require ( './sysinfo.js' ) ,
tld = require ( 'tldjs' ) ,
2018-04-27 11:38:09 -07:00
util = require ( 'util' ) ,
_ = require ( 'underscore' ) ;
2017-10-28 22:18:07 +02:00
2017-10-29 00:15:11 +02:00
// choose which subdomain backend we use for test purpose we use route53
function api ( provider ) {
assert . strictEqual ( typeof provider , 'string' ) ;
switch ( provider ) {
2017-11-21 19:18:03 -08:00
case 'caas' : return require ( './dns/caas.js' ) ;
case 'cloudflare' : return require ( './dns/cloudflare.js' ) ;
case 'route53' : return require ( './dns/route53.js' ) ;
case 'gcdns' : return require ( './dns/gcdns.js' ) ;
case 'digitalocean' : return require ( './dns/digitalocean.js' ) ;
2018-05-06 18:57:27 -07:00
case 'gandi' : return require ( './dns/gandi.js' ) ;
2018-05-06 22:22:42 -07:00
case 'godaddy' : return require ( './dns/godaddy.js' ) ;
2018-05-09 12:24:33 +02:00
case 'namecom' : return require ( './dns/namecom.js' ) ;
2019-01-16 18:05:42 +02:00
case 'namecheap' : return require ( './dns/namecheap.js' ) ;
2017-11-21 19:18:03 -08:00
case 'noop' : return require ( './dns/noop.js' ) ;
case 'manual' : return require ( './dns/manual.js' ) ;
2018-09-06 20:26:24 -07:00
case 'wildcard' : return require ( './dns/wildcard.js' ) ;
2017-11-21 19:18:03 -08:00
default : return null ;
2017-10-29 00:15:11 +02:00
}
}
2018-11-05 19:09:58 -08:00
function parentDomain ( domain ) {
assert . strictEqual ( typeof domain , 'string' ) ;
return domain . replace ( /^\S+?\./ , '' ) ; // +? means non-greedy
}
2019-01-04 18:44:54 -08:00
function verifyDnsConfig ( dnsConfig , domain , zoneName , provider , callback ) {
2018-09-11 21:24:04 -07:00
assert ( dnsConfig && typeof dnsConfig === 'object' ) ; // the dns config to test with
2017-10-29 00:15:11 +02:00
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof zoneName , 'string' ) ;
2018-01-09 14:46:38 -08:00
assert . strictEqual ( typeof provider , 'string' ) ;
2017-10-29 00:15:11 +02:00
assert . strictEqual ( typeof callback , 'function' ) ;
2018-01-09 14:46:38 -08:00
var backend = api ( provider ) ;
2019-10-23 10:02:04 -07:00
if ( ! backend ) return callback ( new BoxError ( BoxError . BAD _FIELD , 'Invalid provider' , { field : 'provider' } ) ) ;
2017-10-29 00:15:11 +02:00
2019-01-04 18:44:54 -08:00
const domainObject = { config : dnsConfig , domain : domain , zoneName : zoneName } ;
api ( provider ) . verifyDnsConfig ( domainObject , function ( error , result ) {
2020-01-01 16:17:16 -08:00
if ( error && error . reason === BoxError . ACCESS _DENIED ) return callback ( new BoxError ( BoxError . BAD _FIELD , ` Access denied: ${ error . message } ` ) ) ;
if ( error && error . reason === BoxError . NOT _FOUND ) return callback ( new BoxError ( BoxError . BAD _FIELD , ` Zone not found: ${ error . message } ` ) ) ;
if ( error && error . reason === BoxError . EXTERNAL _ERROR ) return callback ( new BoxError ( BoxError . BAD _FIELD , ` Configuration error: ${ error . message } ` ) ) ;
2019-10-23 10:02:04 -07:00
if ( error ) return callback ( error ) ;
2018-09-11 21:24:04 -07:00
result . hyphenatedSubdomains = ! ! dnsConfig . hyphenatedSubdomains ;
callback ( null , result ) ;
} ) ;
2018-08-22 11:53:23 +02:00
}
2017-10-29 00:15:11 +02:00
2019-01-04 18:44:54 -08:00
function fqdn ( location , domainObject ) {
return location + ( location ? ( domainObject . config . hyphenatedSubdomains ? '-' : '.' ) : '' ) + domainObject . domain ;
2018-08-30 20:05:08 -07:00
}
// Hostname validation comes from RFC 1123 (section 2.1)
// Domain name validation comes from RFC 2181 (Name syntax)
// https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names
// We are validating the validity of the location-fqdn as host name (and not dns name)
function validateHostname ( location , domainObject ) {
assert . strictEqual ( typeof location , 'string' ) ;
assert . strictEqual ( typeof domainObject , 'object' ) ;
2019-01-04 18:44:54 -08:00
const hostname = fqdn ( location , domainObject ) ;
2018-08-30 20:05:08 -07:00
const RESERVED _LOCATIONS = [
constants . SMTP _LOCATION ,
constants . IMAP _LOCATION
] ;
2019-10-23 10:02:04 -07:00
if ( RESERVED _LOCATIONS . indexOf ( location ) !== - 1 ) return new BoxError ( BoxError . BAD _FIELD , location + ' is reserved' , { field : 'location' } ) ;
2018-08-30 20:05:08 -07:00
2019-10-23 10:02:04 -07:00
if ( hostname === settings . adminFqdn ( ) ) return new BoxError ( BoxError . BAD _FIELD , location + ' is reserved' , { field : 'location' } ) ;
2018-08-30 20:05:08 -07:00
// workaround https://github.com/oncletom/tld.js/issues/73
var tmp = hostname . replace ( '_' , '-' ) ;
2019-10-23 10:02:04 -07:00
if ( ! tld . isValid ( tmp ) ) return new BoxError ( BoxError . BAD _FIELD , 'Hostname is not a valid domain name' , { field : 'location' } ) ;
2018-08-30 20:05:08 -07:00
2019-10-23 10:02:04 -07:00
if ( hostname . length > 253 ) return new BoxError ( BoxError . BAD _FIELD , 'Hostname length exceeds 253 characters' , { field : 'location' } ) ;
2018-08-30 20:05:08 -07:00
if ( location ) {
// label validation
2019-10-23 10:02:04 -07:00
if ( location . split ( '.' ) . some ( function ( p ) { return p . length > 63 || p . length < 1 ; } ) ) return new BoxError ( BoxError . BAD _FIELD , 'Invalid subdomain length' , { field : 'location' } ) ;
if ( location . match ( /^[A-Za-z0-9-.]+$/ ) === null ) return new BoxError ( BoxError . BAD _FIELD , 'Subdomain can only contain alphanumeric, hyphen and dot' , { field : 'location' } ) ;
if ( /^[-.]/ . test ( location ) ) return new BoxError ( BoxError . BAD _FIELD , 'Subdomain cannot start or end with hyphen or dot' , { field : 'location' } ) ;
2018-08-30 20:05:08 -07:00
}
2018-08-30 20:57:14 -07:00
if ( domainObject . config . hyphenatedSubdomains ) {
2019-10-23 10:02:04 -07:00
if ( location . indexOf ( '.' ) !== - 1 ) return new BoxError ( BoxError . BAD _FIELD , 'Subdomain cannot contain a dot' , { field : 'location' } ) ;
2018-08-30 20:57:14 -07:00
}
2018-08-30 20:05:08 -07:00
return null ;
}
2018-09-12 12:25:07 -07:00
function validateTlsConfig ( tlsConfig , dnsProvider ) {
2018-09-11 21:53:18 -07:00
assert . strictEqual ( typeof tlsConfig , 'object' ) ;
2018-09-12 12:25:07 -07:00
assert . strictEqual ( typeof dnsProvider , 'string' ) ;
switch ( tlsConfig . provider ) {
case 'letsencrypt-prod' :
case 'letsencrypt-staging' :
case 'fallback' :
case 'caas' :
break ;
default :
2019-10-23 10:02:04 -07:00
return new BoxError ( BoxError . BAD _FIELD , 'tlsConfig.provider must be caas, fallback, letsencrypt-prod/staging' , { field : 'tlsProvider' } ) ;
2018-09-12 12:25:07 -07:00
}
2018-09-11 21:53:18 -07:00
2018-09-12 12:25:07 -07:00
if ( tlsConfig . wildcard ) {
2019-10-23 10:02:04 -07:00
if ( ! tlsConfig . provider . startsWith ( 'letsencrypt' ) ) return new BoxError ( BoxError . BAD _FIELD , 'wildcard can only be set with letsencrypt' , { field : 'wildcard' } ) ;
if ( dnsProvider === 'manual' || dnsProvider === 'noop' || dnsProvider === 'wildcard' ) return new BoxError ( BoxError . BAD _FIELD , 'wildcard cert requires a programmable DNS backend' , { field : 'tlsProvider' } ) ;
2018-09-11 21:53:18 -07:00
}
return null ;
}
2018-11-10 00:43:46 -08:00
function add ( domain , data , auditSource , callback ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof domain , 'string' ) ;
2018-11-10 00:43:46 -08:00
assert . strictEqual ( typeof data . zoneName , 'string' ) ;
assert . strictEqual ( typeof data . provider , 'string' ) ;
assert . strictEqual ( typeof data . config , 'object' ) ;
assert . strictEqual ( typeof data . fallbackCertificate , 'object' ) ;
assert . strictEqual ( typeof data . tlsConfig , 'object' ) ;
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof callback , 'function' ) ;
2018-11-10 00:43:46 -08:00
let { zoneName , provider , config , fallbackCertificate , tlsConfig } = data ;
2019-10-23 10:02:04 -07:00
if ( ! tld . isValid ( domain ) ) return callback ( new BoxError ( BoxError . BAD _FIELD , 'Invalid domain' , { field : 'domain' } ) ) ;
if ( domain . endsWith ( '.' ) ) return callback ( new BoxError ( BoxError . BAD _FIELD , 'Invalid domain' , { field : 'domain' } ) ) ;
2018-01-23 18:54:05 -08:00
if ( zoneName ) {
2019-10-23 10:02:04 -07:00
if ( ! tld . isValid ( zoneName ) ) return callback ( new BoxError ( BoxError . BAD _FIELD , 'Invalid zoneName' , { field : 'zoneName' } ) ) ;
if ( zoneName . endsWith ( '.' ) ) return callback ( new BoxError ( BoxError . BAD _FIELD , 'Invalid zoneName' , { field : 'zoneName' } ) ) ;
2018-01-23 18:54:05 -08:00
} else {
2018-01-24 14:17:26 -08:00
zoneName = tld . getDomain ( domain ) || domain ;
2018-01-23 18:54:05 -08:00
}
2017-10-28 22:18:07 +02:00
2017-11-09 02:06:36 +01:00
if ( fallbackCertificate ) {
2018-11-10 00:43:46 -08:00
let error = reverseProxy . validateCertificate ( 'test' , { domain , config } , fallbackCertificate ) ;
2019-10-23 10:02:04 -07:00
if ( error ) return callback ( error ) ;
2018-11-05 19:09:58 -08:00
} else {
2018-11-10 00:43:46 -08:00
fallbackCertificate = reverseProxy . generateFallbackCertificateSync ( { domain , config } ) ;
2019-10-23 10:02:04 -07:00
if ( fallbackCertificate . error ) return callback ( error ) ;
2017-11-09 02:06:36 +01:00
}
2018-09-12 12:25:07 -07:00
let error = validateTlsConfig ( tlsConfig , provider ) ;
2018-09-11 21:53:18 -07:00
if ( error ) return callback ( error ) ;
2018-01-31 18:20:11 +01:00
2019-01-04 18:44:54 -08:00
verifyDnsConfig ( config , domain , zoneName , provider , function ( error , sanitizedConfig ) {
if ( error ) return callback ( error ) ;
2017-10-28 22:18:07 +02:00
2019-01-04 18:44:54 -08:00
domaindb . add ( domain , { zoneName : zoneName , provider : provider , config : sanitizedConfig , tlsConfig : tlsConfig } , function ( error ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( error ) ;
2017-10-28 23:23:58 +02:00
2019-01-04 18:44:54 -08:00
reverseProxy . setFallbackCertificate ( domain , fallbackCertificate , function ( error ) {
2019-10-23 10:02:04 -07:00
if ( error ) return callback ( error ) ;
2017-10-28 23:23:58 +02:00
2019-01-04 18:44:54 -08:00
eventlog . add ( eventlog . ACTION _DOMAIN _ADD , auditSource , { domain , zoneName , provider } ) ;
2018-01-26 19:16:43 -08:00
2019-01-04 18:44:54 -08:00
callback ( ) ;
2017-10-28 23:23:58 +02:00
} ) ;
} ) ;
2017-10-28 22:18:07 +02:00
} ) ;
}
function get ( domain , callback ) {
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
domaindb . get ( domain , function ( error , result ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( error ) ;
2017-10-28 22:18:07 +02:00
2019-10-22 16:46:24 -07:00
reverseProxy . getFallbackCertificate ( domain , function ( _ , bundle ) { // never returns an error
2018-01-31 18:20:29 -08:00
var cert = safe . fs . readFileSync ( bundle . certFilePath , 'utf-8' ) ;
var key = safe . fs . readFileSync ( bundle . keyFilePath , 'utf-8' ) ;
2018-01-30 11:30:35 -08:00
2019-11-19 09:36:33 -08:00
// do not error here. otherwise, there is no way to fix things up from the UI
if ( ! cert || ! key ) debug ( ` Unable to read fallback certificates of ${ domain } from disk ` ) ;
2018-01-30 11:30:35 -08:00
result . fallbackCertificate = { cert : cert , key : key } ;
2017-11-12 00:53:28 +01:00
return callback ( null , result ) ;
} ) ;
2017-10-28 22:18:07 +02:00
} ) ;
}
function getAll ( callback ) {
assert . strictEqual ( typeof callback , 'function' ) ;
domaindb . getAll ( function ( error , result ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( error ) ;
2017-10-28 22:18:07 +02:00
return callback ( null , result ) ;
} ) ;
}
2018-11-10 00:43:46 -08:00
function update ( domain , data , auditSource , callback ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof domain , 'string' ) ;
2018-11-10 00:43:46 -08:00
assert . strictEqual ( typeof data . zoneName , 'string' ) ;
assert . strictEqual ( typeof data . provider , 'string' ) ;
assert . strictEqual ( typeof data . config , 'object' ) ;
assert . strictEqual ( typeof data . fallbackCertificate , 'object' ) ;
assert . strictEqual ( typeof data . tlsConfig , 'object' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof callback , 'function' ) ;
2018-11-10 00:43:46 -08:00
let { zoneName , provider , config , fallbackCertificate , tlsConfig } = data ;
2018-11-05 19:09:58 -08:00
domaindb . get ( domain , function ( error , domainObject ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( error ) ;
2017-10-28 22:18:07 +02:00
2018-05-15 13:51:00 -07:00
if ( zoneName ) {
2019-10-23 10:02:04 -07:00
if ( ! tld . isValid ( zoneName ) ) return callback ( new BoxError ( BoxError . BAD _FIELD , 'Invalid zoneName' , { field : 'zoneName' } ) ) ;
2018-05-15 13:51:00 -07:00
} else {
2018-11-05 19:09:58 -08:00
zoneName = domainObject . zoneName ;
2018-05-15 13:51:00 -07:00
}
2017-11-09 02:06:36 +01:00
if ( fallbackCertificate ) {
2018-11-05 22:36:16 -08:00
let error = reverseProxy . validateCertificate ( 'test' , domainObject , fallbackCertificate ) ;
2019-10-23 10:02:04 -07:00
if ( error ) return callback ( error ) ;
2017-11-09 02:06:36 +01:00
}
2018-09-12 12:25:07 -07:00
error = validateTlsConfig ( tlsConfig , provider ) ;
2018-09-11 21:53:18 -07:00
if ( error ) return callback ( error ) ;
2018-01-31 18:20:11 +01:00
2019-02-09 17:59:32 -08:00
if ( provider === domainObject . provider ) api ( provider ) . injectPrivateFields ( config , domainObject . config ) ;
2019-02-09 19:08:15 +01:00
verifyDnsConfig ( config , domain , zoneName , provider , function ( error , sanitizedConfig ) {
2019-01-04 18:44:54 -08:00
if ( error ) return callback ( error ) ;
2017-10-28 23:23:58 +02:00
2019-02-09 19:08:15 +01:00
let newData = {
config : sanitizedConfig ,
zoneName : zoneName ,
provider : provider ,
tlsConfig : tlsConfig
} ;
2019-02-08 20:35:05 -08:00
domaindb . update ( domain , newData , function ( error ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( error ) ;
2017-10-28 23:23:58 +02:00
2019-01-04 18:44:54 -08:00
if ( ! fallbackCertificate ) return callback ( ) ;
2018-01-26 22:27:32 -08:00
2019-01-04 18:44:54 -08:00
reverseProxy . setFallbackCertificate ( domain , fallbackCertificate , function ( error ) {
2019-10-23 10:02:04 -07:00
if ( error ) return callback ( error ) ;
2018-01-30 12:23:27 -08:00
2019-01-04 18:44:54 -08:00
eventlog . add ( eventlog . ACTION _DOMAIN _UPDATE , auditSource , { domain , zoneName , provider } ) ;
2018-11-10 00:43:46 -08:00
2019-01-04 18:44:54 -08:00
callback ( ) ;
2017-10-28 23:23:58 +02:00
} ) ;
} ) ;
} ) ;
2017-10-28 22:18:07 +02:00
} ) ;
}
2018-11-10 00:43:46 -08:00
function del ( domain , auditSource , callback ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof domain , 'string' ) ;
2018-11-10 00:43:46 -08:00
assert . strictEqual ( typeof auditSource , 'object' ) ;
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-10-23 10:02:04 -07:00
if ( domain === settings . adminDomain ( ) ) return callback ( new BoxError ( BoxError . CONFLICT , 'Cannot remove admin domain' ) ) ;
2018-09-05 17:12:02 -07:00
2017-10-28 22:18:07 +02:00
domaindb . del ( domain , function ( error ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( error ) ;
2017-10-28 22:18:07 +02:00
2018-11-10 00:43:46 -08:00
eventlog . add ( eventlog . ACTION _DOMAIN _REMOVE , auditSource , { domain } ) ;
2017-10-28 22:18:07 +02:00
return callback ( null ) ;
} ) ;
}
2017-10-29 00:15:11 +02:00
2018-12-07 14:35:04 -08:00
function clear ( callback ) {
assert . strictEqual ( typeof callback , 'function' ) ;
domaindb . clear ( function ( error ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( error ) ;
2018-12-07 14:35:04 -08:00
return callback ( null ) ;
} ) ;
}
2018-08-30 16:17:56 -07:00
// returns the 'name' that needs to be inserted into zone
2019-01-04 18:44:54 -08:00
function getName ( domain , location , type ) {
2018-10-31 15:41:02 -07:00
const part = domain . domain . slice ( 0 , - domain . zoneName . length - 1 ) ;
2018-01-23 20:25:45 -08:00
2019-01-04 18:44:54 -08:00
if ( location === '' ) return part ;
2018-01-23 20:25:45 -08:00
2019-01-04 18:44:54 -08:00
if ( ! domain . config . hyphenatedSubdomains ) return part ? ` ${ location } . ${ part } ` : location ;
2018-10-31 15:41:02 -07:00
// hyphenatedSubdomains
2019-01-04 18:44:54 -08:00
if ( type !== 'TXT' ) return ` ${ location } - ${ part } ` ;
2018-10-31 15:41:02 -07:00
2019-01-04 18:44:54 -08:00
if ( location . startsWith ( '_acme-challenge.' ) ) {
return ` ${ location } - ${ part } ` ;
} else if ( location === '_acme-challenge' ) {
2018-10-31 15:41:02 -07:00
const up = part . replace ( /^[^.]*\.?/ , '' ) ; // this gets the domain one level up
2019-01-04 18:44:54 -08:00
return up ? ` ${ location } . ${ up } ` : location ;
2018-08-30 16:17:56 -07:00
} else {
2019-01-04 18:44:54 -08:00
return ` ${ location } . ${ part } ` ;
2018-08-30 16:17:56 -07:00
}
2018-01-23 20:25:45 -08:00
}
2019-01-04 18:44:54 -08:00
function getDnsRecords ( location , domain , type , callback ) {
assert . strictEqual ( typeof location , 'string' ) ;
2017-11-16 22:13:30 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2017-10-29 00:15:11 +02:00
assert . strictEqual ( typeof type , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2019-01-04 18:44:54 -08:00
get ( domain , function ( error , domainObject ) {
2019-09-19 15:10:27 -07:00
if ( error ) return callback ( error ) ;
2017-10-29 00:15:11 +02:00
2019-01-04 18:44:54 -08:00
api ( domainObject . provider ) . get ( domainObject , location , type , function ( error , values ) {
2017-10-29 00:15:11 +02:00
if ( error ) return callback ( error ) ;
callback ( null , values ) ;
} ) ;
} ) ;
}
2019-09-23 14:34:29 -07:00
function checkDnsRecords ( location , domain , callback ) {
assert . strictEqual ( typeof location , 'string' ) ;
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
getDnsRecords ( location , domain , 'A' , function ( error , values ) {
if ( error ) return callback ( error ) ;
2019-10-29 15:46:33 -07:00
sysinfo . getServerIp ( function ( error , ip ) {
2019-10-23 10:02:04 -07:00
if ( error ) return callback ( error ) ;
2019-09-23 14:34:29 -07:00
if ( values . length === 0 ) return callback ( null , { needsOverwrite : false } ) ; // does not exist
if ( values [ 0 ] === ip ) return callback ( null , { needsOverwrite : false } ) ; // exists but in sync
callback ( null , { needsOverwrite : true } ) ;
} ) ;
} ) ;
}
2018-09-27 20:17:39 -07:00
// note: for TXT records the values must be quoted
2019-01-04 18:44:54 -08:00
function upsertDnsRecords ( location , domain , type , values , callback ) {
assert . strictEqual ( typeof location , 'string' ) ;
2017-11-21 19:18:03 -08:00
assert . strictEqual ( typeof domain , 'string' ) ;
2017-10-29 00:15:11 +02:00
assert . strictEqual ( typeof type , 'string' ) ;
assert ( util . isArray ( values ) ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2019-01-04 18:44:54 -08:00
debug ( 'upsertDNSRecord: %s on %s type %s values' , location , domain , type , values ) ;
2017-10-29 00:15:11 +02:00
2019-01-04 18:44:54 -08:00
get ( domain , function ( error , domainObject ) {
2019-10-23 10:02:04 -07:00
if ( error ) return callback ( error ) ;
2017-10-29 00:15:11 +02:00
2019-01-04 18:44:54 -08:00
api ( domainObject . provider ) . upsert ( domainObject , location , type , values , function ( error ) {
2017-11-21 19:18:03 -08:00
if ( error ) return callback ( error ) ;
2017-10-29 00:15:11 +02:00
2018-06-29 22:25:34 +02:00
callback ( null ) ;
2017-11-21 19:18:03 -08:00
} ) ;
2017-10-29 00:15:11 +02:00
} ) ;
2017-11-21 19:18:03 -08:00
}
2017-10-29 00:15:11 +02:00
2019-01-04 18:44:54 -08:00
function removeDnsRecords ( location , domain , type , values , callback ) {
assert . strictEqual ( typeof location , 'string' ) ;
2017-11-16 22:13:30 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2017-10-29 00:15:11 +02:00
assert . strictEqual ( typeof type , 'string' ) ;
assert ( util . isArray ( values ) ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2019-01-04 18:44:54 -08:00
debug ( 'removeDNSRecord: %s on %s type %s values' , location , domain , type , values ) ;
2017-10-29 00:15:11 +02:00
2019-01-04 18:44:54 -08:00
get ( domain , function ( error , domainObject ) {
2018-01-10 21:25:51 -08:00
if ( error ) return callback ( error ) ;
2017-10-29 00:15:11 +02:00
2019-01-04 18:44:54 -08:00
api ( domainObject . provider ) . del ( domainObject , location , type , values , function ( error ) {
2019-10-23 10:02:04 -07:00
if ( error && error . reason !== BoxError . NOT _FOUND ) return callback ( error ) ;
2017-10-29 00:15:11 +02:00
callback ( null ) ;
} ) ;
} ) ;
}
2019-01-04 18:44:54 -08:00
function waitForDnsRecord ( location , domain , type , value , options , callback ) {
assert . strictEqual ( typeof location , 'string' ) ;
2017-12-06 11:33:09 +05:30
assert . strictEqual ( typeof domain , 'string' ) ;
2018-09-11 19:09:30 -07:00
assert ( type === 'A' || type === 'TXT' ) ;
2018-02-08 14:19:14 -08:00
assert . strictEqual ( typeof value , 'string' ) ;
2017-10-29 00:15:11 +02:00
assert ( options && typeof options === 'object' ) ; // { interval: 5000, times: 50000 }
assert . strictEqual ( typeof callback , 'function' ) ;
2018-09-22 11:25:58 -07:00
get ( domain , function ( error , domainObject ) {
2018-02-07 20:54:43 +01:00
if ( error ) return callback ( error ) ;
2018-01-10 21:37:12 -08:00
2019-01-04 18:44:54 -08:00
api ( domainObject . provider ) . wait ( domainObject , location , type , value , options , callback ) ;
2017-10-29 00:15:11 +02:00
} ) ;
2017-11-11 22:02:34 +01:00
}
2018-01-01 19:19:07 -08:00
2018-06-25 15:12:20 -07:00
// removes all fields that are strictly private and should never be returned by API calls
2018-04-27 11:38:09 -07:00
function removePrivateFields ( domain ) {
2018-09-05 22:58:43 -07:00
var result = _ . pick ( domain , 'domain' , 'zoneName' , 'provider' , 'config' , 'tlsConfig' , 'fallbackCertificate' , 'locked' ) ;
2019-02-08 11:11:49 +01:00
return api ( result . provider ) . removePrivateFields ( result ) ;
2018-04-29 11:20:12 -07:00
}
2018-06-25 15:12:20 -07:00
// removes all fields that are not accessible by a normal user
function removeRestrictedFields ( domain ) {
2018-09-05 22:58:43 -07:00
var result = _ . pick ( domain , 'domain' , 'zoneName' , 'provider' , 'locked' ) ;
2018-08-22 17:19:18 +02:00
// always ensure config object
result . config = { hyphenatedSubdomains : ! ! domain . config . hyphenatedSubdomains } ;
2018-06-25 15:12:20 -07:00
return result ;
2018-09-05 22:58:43 -07:00
}
2018-09-11 22:46:17 -07:00
function makeWildcard ( hostname ) {
assert . strictEqual ( typeof hostname , 'string' ) ;
let parts = hostname . split ( '.' ) ;
parts [ 0 ] = '*' ;
return parts . join ( '.' ) ;
}
2018-12-13 22:24:26 -08:00
2018-12-15 15:27:16 -08:00
function prepareDashboardDomain ( domain , auditSource , progressCallback , callback ) {
2018-12-13 22:24:26 -08:00
assert . strictEqual ( typeof domain , 'string' ) ;
2018-12-14 09:57:28 -08:00
assert . strictEqual ( typeof auditSource , 'object' ) ;
assert . strictEqual ( typeof progressCallback , 'function' ) ;
2018-12-13 22:24:26 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2018-12-14 09:57:28 -08:00
get ( domain , function ( error , domainObject ) {
2018-12-13 22:24:26 -08:00
if ( error ) return callback ( error ) ;
2019-08-07 06:23:28 -07:00
const adminFqdn = fqdn ( constants . ADMIN _LOCATION , domainObject ) ;
2019-10-29 15:46:33 -07:00
sysinfo . getServerIp ( function ( error , ip ) {
2019-10-23 10:02:04 -07:00
if ( error ) return callback ( error ) ;
2018-12-13 22:24:26 -08:00
2018-12-14 09:57:28 -08:00
async . series ( [
2019-08-07 06:23:28 -07:00
( done ) => { progressCallback ( { percent : 10 , message : ` Updating DNS of ${ adminFqdn } ` } ) ; done ( ) ; } ,
2018-12-14 09:57:28 -08:00
upsertDnsRecords . bind ( null , constants . ADMIN _LOCATION , domain , 'A' , [ ip ] ) ,
2019-08-07 06:23:28 -07:00
( done ) => { progressCallback ( { percent : 40 , message : ` Waiting for DNS of ${ adminFqdn } ` } ) ; done ( ) ; } ,
2018-12-14 09:57:28 -08:00
waitForDnsRecord . bind ( null , constants . ADMIN _LOCATION , domain , 'A' , ip , { interval : 30000 , times : 50000 } ) ,
2019-08-07 06:23:28 -07:00
( done ) => { progressCallback ( { percent : 70 , message : ` Getting certificate of ${ adminFqdn } ` } ) ; done ( ) ; } ,
2019-01-04 18:44:54 -08:00
reverseProxy . ensureCertificate . bind ( null , fqdn ( constants . ADMIN _LOCATION , domainObject ) , domain , auditSource )
2018-12-18 15:05:36 -08:00
] , function ( error ) {
if ( error ) return callback ( error ) ;
callback ( null ) ;
} ) ;
2018-12-13 22:24:26 -08:00
} ) ;
} ) ;
2019-02-09 17:33:52 -08:00
}