From 6c116acff521e8494e3ff266bb951260a04c86e0 Mon Sep 17 00:00:00 2001 From: Expand-sys Date: Wed, 5 May 2021 19:29:34 +1000 Subject: [PATCH] First Edition: does _acme-challenge dns records --- .gitignore | 2 + index.js | 217 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 59 +++++++++++++ package.json | 24 +++++ 4 files changed, 302 insertions(+) create mode 100644 .gitignore create mode 100644 index.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc150eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/node_modules +.env diff --git a/index.js b/index.js new file mode 100644 index 0000000..1adb6f5 --- /dev/null +++ b/index.js @@ -0,0 +1,217 @@ +const fetch = require('node-fetch'); +const dotenv = require('dotenv') +const nodemailer = require('nodemailer') +dotenv.config(); + + +let transporter = nodemailer.createTransport({ + host: process.env.HOST, + port: 465, + secure: true, // true for 465, false for other ports + auth: { + user: process.env.SENDER, // generated ethereal user + pass: process.env.SPASS, // generated ethereal password + }, +}) +let message = []; +async function grabdomainnames(){ + let domains = []; + await fetch('https://'+process.env.PLESKURL+'/api/v2/domains', { + method:"GET", + headers: { + 'X-API-Key': process.env.PLESKKEY, + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + }).then(response => response.json()) + .then(data => { + for(i in data){ + domains.push(data[i].name) + } + + }); + return domains +} +let domainInfo = [] +async function grabCloudflaredomains(){ + let domains = []; + await fetch('https://api.cloudflare.com/client/v4/zones?match=all&account.id='+process.env.CLOUDACCOUNTID, { + method: 'GET', + headers: { + 'X-Auth-Email': process.env.CLOUDEMAIL, + 'X-Auth-Key': process.env.CLOUDKEY, + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + }) + .then(response => response.json()) + .then(async data => { + for(i in data.result){ + domainInfo.push(data.result[i]) + domains.push(data.result[i].name) + } + + if(data.result_info.total_pages > 1){ + let count = 1 + while(count < data.result_info.total_pages){ + count = count+1 + await fetch('https://api.cloudflare.com/client/v4/zones?match=all&account.id='+process.env.CLOUDACCOUNTID+'&page='+count, { + method: 'GET', + headers: { + 'X-Auth-Email': process.env.CLOUDEMAIL, + 'X-Auth-Key': process.env.CLOUDKEY, + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + }) + .then(response => response.json()) + .then(data => { + for(i in data.result){ + domainInfo.push(data.result[i]) + domains.push(data.result[i].name) + } + + }) + + } + + } + }); + return domains + +} + + +async function filterDomains(){ + let cloudflare = await grabCloudflaredomains(); + let plesk = await grabdomainnames(); + let result = await cloudflare.filter( ( el ) => plesk.includes( el ) ); + return result + +} + + + + + + + +async function dns(){ + let domains = await filterDomains() + let records = [] + for(i in domains){ + let res = await fetch('https://'+process.env.PLESKURL+'/api/v2/cli/dns/call', { + method: 'POST', + headers: { + 'X-API-Key': process.env.PLESKKEY, + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + body: JSON.stringify({ "params": [ "--info", domains[i]]}) + }) + .then(response => response.json()) + .then(data => { + let string = data.stdout.split("\n") + let acme = "_acme-challenge" + length = acme.length; + for(i in string){ + if (string[i].indexOf(acme)!=-1) { + // one of the substrings is in yourstring + records.push(string[i]) //result + } + } + }); + } + let finalarray = [] + for(i in records){ + finalarray.push(records[i].split(' ')) + } + return finalarray +} + +async function mergedns(){ + let finalarray = await dns() + for(i in finalarray){ + for(x in domainInfo){ + if(finalarray[i][0].includes(domainInfo[x].name)){ + finalarray[i].push(domainInfo[x].id); + finalarray[i].push(domainInfo[x].name) + } + } + } + for(i in finalarray){ + let zone = finalarray[i][4]; + + await fetch('https://api.cloudflare.com/client/v4/zones/'+zone+'/dns_records?type=TXT&name=_acme-challenge.'+finalarray[i][5], { + method: 'GET', + headers: { + 'X-Auth-Email': process.env.CLOUDEMAIL, + 'X-Auth-Key': process.env.CLOUDKEY, + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + + }) + .then(response => response.json()) + .then(data => { + if(data.result[0] == undefined){ + finalarray[i].push("create") + }else{ + finalarray[i].push(data.result[0].id) + finalarray[i].push(data.result[0].content) + } + }) + } + return finalarray +} +senddns() +async function senddns(){ + let finalarray = await mergedns() + + for(i in finalarray){ + if(finalarray[i][6] == 'create'){ + fetch("https://api.cloudflare.com/client/v4/zones/"+finalarray[i][4]+"/dns_records", { + body: JSON.stringify({type:finalarray[i][1], name:finalarray[i][0], content:finalarray[i][3], ttl:1}), + headers: { + "Content-Type": "application/json", + "X-Auth-Email": process.env.CLOUDEMAIL, + "X-Auth-Key": process.env.CLOUDKEY, + }, + method: "POST" + }) + } else if(finalarray[i][3] ==finalarray[i][7]){ + message.push("punching sand for this turn") + console.log("punching sand for this turn") + }else{ + await fetch('https://api.cloudflare.com/client/v4/zones/'+finalarray[i][4]+'/dns_records/'+finalarray[i][6], { + method: 'PUT', + headers: { + 'X-Auth-Email': process.env.CLOUDEMAIL, + 'X-Auth-Key': process.env.CLOUDKEY, + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + body: JSON.stringify({type:finalarray[i][1], name:finalarray[i][0], content:finalarray[i][3], ttl:1}), + }) + .then(response => response.json()) + .then(data => { + message.push(data) + console.log(data) + }) + } + + } + message.push(finalarray) + console.log(finalarray) + mail() +} +async function mail(){ + let info = await transporter.sendMail({ + from: '"DNSBOT" <'+process.env.SENDER+'>', + to: process.env.EMAIL, + subject: "DNS updates "+ new Date, + text: message.toString().replaceAll(',', "\n"), + }) + console.log(info) + console.log("Message sent to "+process.env.EMAIL) +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..096c214 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,59 @@ +{ + "name": "cloudflareplesk-link", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "cloudflareplesk-link", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "dotenv": "^8.5.1", + "node-fetch": "^2.6.1", + "nodemailer": "^6.6.0" + } + }, + "node_modules/dotenv": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.5.1.tgz", + "integrity": "sha512-qC1FbhCH7UH7B+BcRNUDhAk04d/n+tnGGB1ctwndZkVFeehYJOn39pRWWzmdzpFqImyX1KB8tO0DCHLf8yRaYQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/nodemailer": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.0.tgz", + "integrity": "sha512-ikSMDU1nZqpo2WUPE0wTTw/NGGImTkwpJKDIFPZT+YvvR9Sj+ze5wzu95JHkBMglQLoG2ITxU21WukCC/XsFkg==", + "engines": { + "node": ">=6.0.0" + } + } + }, + "dependencies": { + "dotenv": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.5.1.tgz", + "integrity": "sha512-qC1FbhCH7UH7B+BcRNUDhAk04d/n+tnGGB1ctwndZkVFeehYJOn39pRWWzmdzpFqImyX1KB8tO0DCHLf8yRaYQ==" + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "nodemailer": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.0.tgz", + "integrity": "sha512-ikSMDU1nZqpo2WUPE0wTTw/NGGImTkwpJKDIFPZT+YvvR9Sj+ze5wzu95JHkBMglQLoG2ITxU21WukCC/XsFkg==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9cf80aa --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "cloudflareplesk-link", + "version": "1.0.0", + "description": "A Link between Cloudflare DNS and Plesk for renewing lets encrypt certificates", + "main": "index.js", + "scripts": { + "test": "node index.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Expand-sys/CloudflarePlesk-Link.git" + }, + "author": "Expand", + "license": "ISC", + "bugs": { + "url": "https://github.com/Expand-sys/CloudflarePlesk-Link/issues" + }, + "homepage": "https://github.com/Expand-sys/CloudflarePlesk-Link#readme", + "dependencies": { + "dotenv": "^8.5.1", + "node-fetch": "^2.6.1", + "nodemailer": "^6.6.0" + } +}