197 lines
4.9 KiB
JavaScript
197 lines
4.9 KiB
JavaScript
'use strict';
|
|
var request = require('@root/request');
|
|
request = require('util').promisify(request);
|
|
var crypto = require('crypto');
|
|
var querystring = require('querystring');
|
|
|
|
var defaults = {
|
|
region:'ovh-eu',
|
|
basePath:'/1.0'
|
|
};
|
|
|
|
var recordsStore = {};
|
|
|
|
module.exports.create = function(config) {
|
|
var applicationKey = config.applicationKey||null;
|
|
var applicationSecret = config.applicationSecret||null;
|
|
var consumerKey = config.consumerKey||null;
|
|
// one of ovh-eu, ovh-ca, kimsufi-eu, kimsufi-ca, soyoustart-eu, soyoustart-ca, runabove-ca
|
|
var region = config.region || defaults.region;
|
|
var apiTimeDiff = config.apiTimeDiff || null;
|
|
var basePath = config.basePath || defaults.basePath;
|
|
|
|
if (typeof(applicationKey) !== 'string' || typeof(applicationSecret) !== 'string') {
|
|
throw new Error('[OVH] You should precise an application key / secret');
|
|
}
|
|
|
|
var endpoints = {
|
|
'ovh-eu': 'eu.api.ovh.com',
|
|
'ovh-ca': 'ca.api.ovh.com',
|
|
'kimsufi-eu': 'eu.api.kimsufi.com',
|
|
'kimsufi-ca': 'ca.api.kimsufi.com',
|
|
'soyoustart-eu': 'eu.api.soyoustart.com',
|
|
'soyoustart-ca': 'ca.api.soyoustart.com',
|
|
'runabove-ca': 'api.runabove.com'
|
|
};
|
|
|
|
var baseUrl = 'https://' + endpoints[region] + basePath;
|
|
|
|
/**
|
|
* Signs an API request
|
|
*
|
|
* @param {String} httpMethod
|
|
* @param {String} url
|
|
* @param {String} body
|
|
* @param {Number|String} timestamp
|
|
* @return {String} The signature
|
|
*/
|
|
function signRequest(httpMethod, url, body, timestamp) {
|
|
var s = [
|
|
applicationSecret,
|
|
consumerKey,
|
|
httpMethod,
|
|
url,
|
|
body || '',
|
|
timestamp
|
|
];
|
|
return '$1$' + crypto.createHash('sha1').update(s.join('+')).digest('hex');
|
|
}
|
|
|
|
function api(httpMethod, path, params) {
|
|
// Time drift
|
|
if (apiTimeDiff === null && path !== '/auth/time') {
|
|
return api('GET', '/auth/time', {})
|
|
.then(function(res) {
|
|
|
|
apiTimeDiff = res.body - Math.round(Date.now() / 1000);
|
|
return api(httpMethod, path, params);
|
|
}).catch(function(err) {
|
|
// todo
|
|
throw new Error('[OVH] Unable to fetch OVH API time');
|
|
});
|
|
}
|
|
|
|
var headers = {
|
|
'X-Ovh-Application': applicationKey
|
|
};
|
|
|
|
if (httpMethod === 'GET') {
|
|
path += '?' + querystring.stringify(params);
|
|
}
|
|
|
|
var url = baseUrl + path;
|
|
|
|
if (path.indexOf('/auth') < 0) {
|
|
headers['X-Ovh-Timestamp'] = Math.round(Date.now() / 1000) + apiTimeDiff;
|
|
// Sign request
|
|
if (typeof(consumerKey) === 'string') {
|
|
headers['X-Ovh-Consumer'] = consumerKey;
|
|
headers['X-Ovh-Signature'] = signRequest(
|
|
httpMethod, url, params, headers['X-Ovh-Timestamp']
|
|
);
|
|
}
|
|
}
|
|
|
|
console.debug(
|
|
'[OVH] API call:',
|
|
httpMethod,
|
|
path,
|
|
params || ''
|
|
);
|
|
|
|
return request({
|
|
method: httpMethod,
|
|
url: url,
|
|
headers: headers,
|
|
json: true,
|
|
form: params
|
|
});
|
|
}
|
|
|
|
return {
|
|
init: function(deps) {
|
|
request = deps.request;
|
|
return null;
|
|
},
|
|
zones: function(data) {
|
|
return api('GET', '/domain/zone')
|
|
.then(function(resp) {
|
|
if (200 !== resp.statusCode) {
|
|
console.error(resp.statusCode);
|
|
console.error(resp.body);
|
|
throw new Error('Could not get list of zones.');
|
|
}
|
|
|
|
// list of zones
|
|
return resp.body;
|
|
|
|
}).catch(function(err) {
|
|
|
|
});
|
|
},
|
|
set: function(data) {
|
|
var ch = data.challenge;
|
|
var txt = ch.dnsAuthorization;
|
|
|
|
// record name received as argument : www.qwerty.sampledomain.com
|
|
// received zone id : sampledomain.com required record name by OVH : www.qwerty
|
|
//console.debug('adding txt', data);
|
|
return api('POST', '/domain/zone/' + ch.dnsZone + '/record', {
|
|
fieldType: 'TXT',
|
|
subDomain: ch.dnsPrefix,
|
|
target: txt,
|
|
ttl: 1
|
|
}).then(function(resp) {
|
|
if (200 !== resp.statusCode) {
|
|
console.error(resp.statusCode);
|
|
console.error(resp.body);
|
|
throw new Error('record did not set.');
|
|
}
|
|
// save id for remove
|
|
recordsStore[ch.dnsPrefix] = resp.body['id']
|
|
|
|
}).then(function() {
|
|
// Apply zone modification on DNS servers
|
|
return api('POST', '/domain/zone/' + ch.dnsZone + '/record', {})
|
|
.then(function() {
|
|
return true;
|
|
});
|
|
});
|
|
},
|
|
remove: function(data) {
|
|
var ch = data.challenge;
|
|
return api('DELETE', '/domain/zone/' + ch.dnsZone + '/record/'+recordsStore[ch.dnsPrefix])
|
|
.then(function(resp) {
|
|
if (200 !== resp.statusCode) {
|
|
throw new Error('record did not remove.');
|
|
}
|
|
})
|
|
.then(function() {
|
|
return api('POST', '/domain/zone/' + ch.dnsZone + '/record', {})
|
|
.then(function(resp) {
|
|
if (200 !== resp.statusCode) {
|
|
console.error(resp.statusCode);
|
|
console.error(resp.body);
|
|
throw new Error('record did not remove.');
|
|
}
|
|
return true;
|
|
});
|
|
});
|
|
},
|
|
get: function(data) {
|
|
var ch = data.challenge;
|
|
|
|
return api('GET', '/domain/zone/' + ch.dnsZone + '/record/'+recordsStore[ch.dnsPrefix])
|
|
.then(function(resp) {
|
|
if (200 !== resp.statusCode) {
|
|
throw new Error('record did not remove.');
|
|
}
|
|
return {
|
|
dnsAuthorization:resp.body.target
|
|
};
|
|
|
|
});
|
|
}
|
|
};
|
|
};
|