var fs = require('fs'); var express = require('express'); //var https = require('https'); var http = require('http'); var app = express(); const cors = require('cors') const helmet = require('helmet'); var allowedOrigins = [ 'https://localhost:55543', 'http://localhost:3080', 'http://localhost:3088', 'http://localhost:8080' ]; app.use(cors({ origin: function(origin, callback){ // allow requests with no origin // (like mobile apps or curl requests) if(!origin) return callback(null, true); if(allowedOrigins.indexOf(origin) === -1){ var msg = 'The CORS policy for this site does not '; return callback(new Error(msg), false); } return callback(null, true); } })); //app.use(cors) app.use(helmet()); app.use(express.json()); var serverPort = 3080; /* // ssl enabled var options = { key: fs.readFileSync('./llo/swarmlab.key'), cert: fs.readFileSync('./llo/swarmlab.crt') }; var server = https.createServer(options, app); var io = require('socket.io')(server); */ var server = http.createServer(app); const io = require("socket.io")(server, { cors: { origin: "http://localhost:8080", methods: ["GET", "POST"] } }); const { spawn, exec } = require('child_process') const simpleGit = require('simple-git'); // const { exec } = require('child_process'); //const chokidar = require('chokidar'); //const logout = fs.openSync('./logs/out.log', 'a'); //const logerr = fs.openSync('./logs/out.log', 'a'); //const watcher = chokidar.watch('./logs/out.log', { persistent: true }); //const Tail = require('nodejs-tail'); //const tail = new Tail('./logs/out.log'); //tail.watch(); // tail.on('line', (line) => { // var n = {} // n.data = line // io.emit('message_out', n); // }) /* watcher .on('add', path => { var n = {} n.data = path.toString() }) .on('change', async path => { //var updateContent = await readLastLines.read(path, 1); tail.on('line', (line) => { var n = {} n.data = line io.emit('message_out', n); }) }) .on('unlink', path => { var n = {} n.data = path.toString() io.emit('message_out', n); }); */ // *************************************************** // rest get // *************************************************** app.get('/dockerservices', (req, res, next) => { var RES = new Object(); const page = req.query["page"] const per_page = req.query["per_page"] RES.sort = req.query["sort"] RES.filter = req.query["filter"] RES.type = req.query["type"] var showexec = `docker ps --format '{"ID":"{{ .ID }}", "Image": "{{ .Image }}", "Names":"{{ .Names }}", "Ports":"{{.Ports}}", "Networks":"{{.Networks}}", "Status":"{{.Status}}","RunningFor":"{{.RunningFor}}","CreatedAt":"{{.CreatedAt}}"}' | jq . -s ` exec(showexec, (err, stdout, stderr) => { if (err) { console.error(`exec error: ${err}`); return; } var nn = [] var string = stdout.toString() var datajson = JSON.parse(string); //console.log('Number of files ' + stdout); //console.log('Number string ' + string); //console.log('stringify ' + JSON.stringify(datajson)); var total = datajson.length; var perpage = per_page //var page = 1 var lastpage = Math.trunc(total/5); if(lastpage <= 1) { lastpage=1 }else{ lastpage++ } var next=(page+1); if(next >= lastpage){ next=lastpage; } var prev=(page-1); if(prev == 0){ prev=1; } var from=((page-1)*perpage)+1; var to=(perpage*page) var myplaybooks = new Object(); var links = ` { "pagination": { "total": ${total}, "per_page": ${perpage}, "current_page": ${page}, "last_page": ${lastpage}, "next_page_url": "?page=${next}", "prev_page_url": "?page=${prev}", "from": ${from}, "to": ${to}, "frommongo": ${from}, "tomongo": ${to} } } ` //"next_page_url": "?page="+${next}, //"prev_page_url": "?page="+${prev}, //console.log(JSON.stringify(links)) //myplaybooks.links = links myplaybooks.links = JSON.parse(links); myplaybooks.data = datajson; var RES = new Object(); RES.code = req.query["action"] RES.token = req.query["token"] RES.error = false RES.error_msg = "ok" RES.data = myplaybooks; res.json(RES.data) }); }); app.get('/getservicesinfo', (req, res, next) => { var RES = new Object(); RES.instance = req.query["instance"] var services_path = './instance/'+RES.instance //console.log(services_path) if (fs.existsSync(services_path)) { var found = 'yes' RES.error = false RES.error_msg = "ok" RES.data = found; res.json(RES) }else{ var found = 'no' RES.error = false RES.error_msg = "ok" RES.data = found; res.json(RES) } }); app.get('/getmountinfo', (req, res, next) => { var RES = new Object(); RES.instance = req.query["instance"] var showexec = `docker inspect --format='{{json .Mounts}}' ${RES.instance} | jq . -s` //console.log(JSON.stringify(showexec)) exec(showexec, (err, stdout, stderr) => { if (err) { console.error(`exec error: ${err}`); return; } if (stdout) { var string = stdout.toString() var datajson = JSON.parse(string); //console.log(JSON.stringify(string)) //console.log(JSON.stringify(datajson)) //var extenderror = new RegExp(RES.instance); /* var found = 'no'; for(var i = 0; i < datajson.length; i++) { var servicename = datajson[i].Names console.log(JSON.stringify(servicename)) if(extenderror.test(servicename)){ found = 'yes'; } } */ RES.error = false RES.error_msg = "ok" RES.test = datajson; //RES.data = found; res.json(RES) }else{ var found = 'no' RES.error = false RES.error_msg = "ok" //RES.data = found; res.json(RES) } }); }); app.get('/getservicesstatus', (req, res, next) => { var RES = new Object(); RES.instance = req.query["instance"] var showexec = `docker ps --format '{"Names":"{{ .Names }}", "Status":"{{.Status}}"}' | jq . -s ` exec(showexec, (err, stdout, stderr) => { if (err) { console.error(`exec error: ${err}`); return; } if (stdout) { var string = stdout.toString() var datajson = JSON.parse(string); //console.log(JSON.stringify(datajson.length)) //console.log(JSON.stringify(datajson)) var extenderror = new RegExp(RES.instance); var found = 'no'; for(var i = 0; i < datajson.length; i++) { var servicename = datajson[i].Names //console.log(JSON.stringify(servicename)) if(extenderror.test(servicename)){ found = 'yes'; } } RES.error = false RES.error_msg = "ok" RES.test = datajson; RES.data = found; res.json(RES) }else{ var found = 'no' RES.error = false RES.error_msg = "ok" RES.data = found; res.json(RES) } }); }); app.get('/get_config', (req, res, next) => { var mypath = process.cwd() var RES = new Object(); var found = 'yes' RES.error = false RES.error_msg = "ok" RES.data = found; RES.data = mypath res.json(RES) /* exec('pwd', (err, stdout, stderr) => { if (err) { console.error(`exec error: ${err}`); return; } if (stdout) { var string = stdout.toString() console.log(JSON.stringify(string)) var found = 'yes' RES.error = false RES.error_msg = "ok" RES.data = found; RES.data = string res.json(RES) }else{ var found = 'no' RES.error = false RES.error_msg = "ok" RES.data = found; res.json(RES) } }); */ }); app.get('/create_config', (req, res, next) => { var RES = new Object(); RES.value = req.query["value"] //console.log('value error '+JSON.stringify(RES.value)) //var showexec = `cd ./hybrid; /bin/bash ./create-keys.sh` fs.writeFileSync('./hybrid/keys.json', JSON.stringify(RES.value)); RES.value = JSON.parse(RES.value); var INTERFACE_IP=RES.value.wg_ip var endpoint_tmp=RES.value.server_ip var fields = endpoint_tmp.split(':'); var endpoint = fields[0]; var mypath = process.cwd() var swarmlab_config_template = ` DEV_NAME=wg0 INTERFACE_IP=${INTERFACE_IP}/16 INTERFACE_IProute=${INTERFACE_IP} ENDPOINT_IP=${endpoint} ip link set $DEV_NAME down ip link del $DEV_NAME # add wireguard interface ip link add $DEV_NAME type wireguard # set wireguard conf wg setconf $DEV_NAME ${mypath}/hybrid/connect/$DEV_NAME.conf # assign ip to wireguard interface ip addr add $INTERFACE_IP dev $DEV_NAME # set sysctl sysctl -w net.ipv4.conf.all.rp_filter=2 # set mtu for wireguard interface ip link set mtu 1420 up dev $DEV_NAME # bring wireguard interface up ip link set up dev $DEV_NAME # add route ip route add default via $INTERFACE_IProute metric 2 table 200 ip route show table 200 | grep -w $INTERFACE_IProute # add local lan route ip rule add table main suppress_prefixlength 0 ip rule show | grep -w "suppress_prefixlength" ` fs.writeFileSync('./hybrid/connect/swarmlab-connect.sh', swarmlab_config_template); var allowed_ips=RES.value.allowed_ips var swarmlab_public_wgkey=RES.value.swarmlab_public_wgkey var swarmlab_privatekey=RES.value.privatekey var swarmlab_wg_port=RES.value.wg_port var swarmlab_wg0_template = `[Interface] PrivateKey = ${swarmlab_privatekey} ListenPort = ${swarmlab_wg_port} [Peer] PublicKey = ${swarmlab_public_wgkey} Endpoint = ${endpoint_tmp} AllowedIPs = ${allowed_ips} PersistentKeepalive = 30 ` //fs.writeFileSync('./hybrid/connect/template-wg0.conf', swarmlab_wg0_template); fs.writeFileSync('./hybrid/connect/wg0.conf', swarmlab_wg0_template); var swarmlab_swarm=RES.value.workerkey var swarmlab_swarm_ip=RES.value.swarm_ip var swarmlab_swarm_template = ` docker swarm join --token ${swarmlab_swarm} ${swarmlab_swarm_ip} ` //fs.writeFileSync('./hybrid/connect/template-swarm.sh', swarmlab_swarm_template); fs.writeFileSync('./hybrid/connect/reload-swarmlab.sh', swarmlab_swarm_template); var swarmlab_swarm_join_template = ` function swarmlab_ifup() { swarmlab=$(/bin/bash ${mypath}/hybrid/connect/status.sh wg0 | jq .swarmlab) tempswarm="\${swarmlab%\\"}" tempswarm="\${tempswarm#\\"}" swarmlab=$tempswarm echo $swarmlab } function hybrid_ifup() { hybrid=$(/bin/bash ${mypath}/hybrid/connect/status.sh wg0 | jq .hybrid) tempswarm1="\${hybrid%\\"}" tempswarm1="\${tempswarm1#\\"}" hybrid=$tempswarm1 echo $hybrid } hybrid=$(hybrid_ifup) if [ $hybrid == 'NotOnline' ]; then /bin/bash ${mypath}/hybrid/connect/swarmlab-connect.sh echo "Start wg0 network interface" sleep 3 hybrid1=$(hybrid_ifup) if [ $hybrid1 == 'NotOnline' ]; then echo "Failed to start wg0 network interface" else echo "Swarmlab hybrid $hybrid" fi else echo "Swarmlab hybrid $hybrid" fi sleep 1 swarmlab=$(swarmlab_ifup) if [ $swarmlab != 'active' ]; then /bin/bash ${mypath}/hybrid/connect/reload-swarmlab.sh sleep 5 swarmlab1=$(swarmlab_ifup) if [ $swarmlab1 != 'active' ]; then echo "Failed to connect on swarmlab master" echo "Exec " echo "/bin/bash ${mypath}/hybrid/connect/reload-swarmlab.sh" echo "Please try again" fi else echo "Swarmlab master $swarmlab" fi /bin/bash ${mypath}/hybrid/connect/get-swarmlab-ca /bin/bash ${mypath}/hybrid/connect/get-base-ca ` fs.writeFileSync('./hybrid/connect/join.sh', swarmlab_swarm_join_template); var swarmlab_swarm_leave_template = ` function hybrid_ifup() { hybrid=$(/bin/bash ${mypath}/hybrid/connect/status.sh wg0 | jq .hybrid) tempswarm1="\${hybrid%\\"}" tempswarm1="\${tempswarm1#\\"}" hybrid=$tempswarm1 echo $hybrid } hybrid=$(hybrid_ifup) if [ $hybrid == 'NotOnline' ]; then echo "Swarmlab hybrid $hybrid" else ip link set wg0 down ip link del wg0 sleep 3 hybrid1=$(hybrid_ifup) if [ $hybrid1 == 'NotOnline' ]; then echo "Swarmlab hybrid $hybrid" else echo "Swarmlab hybrid $hybrid" fi fi ` fs.writeFileSync('./hybrid/connect/leave.sh', swarmlab_swarm_leave_template); RES.error = false RES.error_msg = "ok" res.json(RES) }); function create_project(swarmlabname,project){ var services_path = './instance/'+swarmlabname+'/'+project fs.mkdir(services_path, { recursive: true }, (err) => { var service_up = '/bin/bash ../install/usr/share/swarmlab.io/sec/swarmlab-sec create' create = spawn(service_up, { shell: true, cwd: services_path, //detached: true, detached: false, //stdio: [ 'ignore', logout, logerr ] stdio: 'pipe' }); create.stdout.on('data', function (data) { var n = {} n.data = data.toString() io.emit('message_out', n); }); create.stderr.on('data', function (data) { var n = {} n.data = data.toString() io.emit('message_err', n); }); create.on('close', function (code) { var n = {} n.data = code io.emit('message_close', n); }); }); } function myserverStatus(){ var serverStatus = '/bin/bash ./hybrid/connect/status.sh wg0'; exec(serverStatus, (err, stdout, stderr) => { if (err) { console.error(`exec error: ${err}`); return; } if (stdout) { var string = stdout.toString() string = JSON.parse(string); //var stringstr = string.replace(/^"(.*)"$/, '$1'); var n = {} n.data = string io.emit('message_hybrid_status', n); } }); } myserverStatus(); setInterval(function(){ myserverStatus() }, 30000) let child = []; var ppid = '' io.on('connection', function(socket) { console.log('new connection'); socket.on('start', (value) => { //console.log('start') //console.log('value '+JSON.stringify(value)) if(value.swarmlabname){ var service = value.swarmlabname var services_path = './instance/'+service+'/'+service var ENV_service_file_path = services_path+'/.env' var service_port = '' if(value.swarmlabname_size){ var service_size = value.swarmlabname_size }else{ var service_size = 3 } const apptest = require('express')(); const servertest = apptest.listen(0, () => { var newport = servertest.address().port servertest.close(); if(value.swarmlabname_port){ service_port = value.swarmlabname_port }else{ service_port = newport } var ENV_service_file = ` REGISTRY_ADDR=localhost REGISTRY_PORT=5000 IMAGE_NAME=${service} SSH_PORT=${service_port} TEST=${service} ` //console.log('value1 '+JSON.stringify(ENV_service_file_path)) //console.log('value2 '+JSON.stringify(ENV_service_file)) fs.writeFileSync(ENV_service_file_path, ENV_service_file ,{encoding:'utf8',flag:'w'}); var service_up = '/bin/bash ../install/usr/share/swarmlab.io/sec/swarmlab-sec up size='+service_size child[0] = spawn(service_up, { shell: true, cwd: services_path, //detached: true, detached: false, //stdio: [ 'ignore', logout, logerr ] stdio: 'pipe' }); ppid = child[0].pid; console.log(ppid) child[0].stdout.on('data', function (data) { var n = {} n.data = data.toString() io.emit('message_out', n); }); child[0].stderr.on('data', function (data) { var n = {} n.data = data.toString() io.emit('message_err', n); }); child[0].on('close', function (code) { var n = {} n.data = code io.emit('message_close', n); }); }); }else{ var n = {} n.data = 'NoSwarmlabname' io.emit('message_err', n); } }); socket.on('stop', (service) => { var services_path = './instance/'+service+'/'+service const stop = spawn('/bin/sh ./stop.sh', { stdio: 'pipe', shell: true, cwd: services_path }); stop.stdout.on('data', function (data) { var n = {} n.data = data.toString() io.emit('message_out', n); }); stop.stderr.on('data', function (data) { var n = {} n.data = data.toString() io.emit('message_err', n); }); stop.on('close', function (code) { var n = {} n.data = code io.emit('message_close', n); }); }); socket.on('install', (value) => { if(value.swarmlabname){ //console.log('install') var service = value.swarmlabname var service_git = value.git var services_path = './instance/'+service var ENV_service_dir = services_path+'/'+service var ENV_service_file_path = services_path+'/'+service+'/'.env if (fs.existsSync(services_path)) { const git = simpleGit( { baseDir: services_path, maxConcurrentProcesses: 10 }); try { git.pull() .then((status) => { var n = {} n.data = 'Updated' io.emit('message_out', n); n.data = '...' io.emit('message_close', n); create_project(service,service) }).catch((err) => { var n = {} n.data = err.toString() io.emit('message_err', n); console.log('error ' + JSON.stringify(err)) }); } catch (e) { var n = {} n.data = e.toString() io.emit('message_err', n); } }else{ fs.mkdir(services_path, { recursive: true }, (err) => { if (err){ console.log('error ' + JSON.stringify(err)) }else{ var ENV_service_file = ` REGISTRY_ADDR=localhost REGISTRY_PORT=5000 IMAGE_NAME=${service} SSH_PORT= ` const git = simpleGit( { baseDir: '.', maxConcurrentProcesses: 10 }); try { git.clone(service_git, services_path) .then((status) => { var n = {} n.data = 'Installed' io.emit('message_out', n); n.data = '...' io.emit('message_out', n); fs.writeFileSync(ENV_service_file_path, ENV_service_file); create_project(service,service) }).catch((err) => { var n = {} n.data = err.toString() io.emit('message_err', n); console.log('error ' + JSON.stringify(err)) }); } catch (e) { var n = {} n.data = e.toString() io.emit('message_err', n); } } }); } }else{ var n = {} n.data = 'no services' io.emit('message_err', n); } }); socket.on('container-stop', (service, id) => { var mypath = process.cwd() console.log(mypath); var containerrm = '/bin/sh ./hybrid/connect/container-stop.sh '+id const stop = spawn(containerrm, { stdio: 'pipe', shell: true, cwd: mypath }); stop.stdout.on('data', function (data) { var n = {} n.data = data.toString() io.emit('message_out', n); }); stop.stderr.on('data', function (data) { var n = {} n.data = data.toString() io.emit('message_err', n); }); stop.on('close', function (code) { var n = {} n.data = code io.emit('message_close', n); }); }); socket.on('kill', () => { //console.log(ppid) //process.kill(ppid, 'SIGHUP'); child[0].kill('SIGHUP'); //child[0].kill('SIGINT'); //child[0].kill(); }); socket.on('create-wirequard', (value) => { let rawdatafile = './hybrid/config.json' var workerkey = value.workerkey var privatekey = value.privatekey var publickey = value.publickey var server_ip = value.server_ip // 83.212.77.133:51820 var allowed_ips = value.allowed_ips // 10.13.13.0/16, 0.0.0.0/0, ::/0 var services_json = { workerkey: workerkey, privatekey: privatekey, publickey: publickey, server_ip: server_ip, allowed_ips: allowed_ips }; let datajson = JSON.stringify(services_json); fs.writeFileSync(rawdatafile, datajson); var services_path = ` ---------------- create a file /etc/wireguard/wg0.conf ----------------------- ` var ENV_service_file = ` create a file connect-server.sh [Interface] PrivateKey = ${privatekey} ListenPort = 51820 [Peer] PublicKey = ${publickey} Endpoint = ${server_ip} AllowedIPs = ${allowedOrigins} PersistentKeepalive = 30 ` var n = {} n.data = services_path io.emit('message_out', n); n.data = ENV_service_file io.emit('message_out', n); var n = {} n.data = 'bash ./connect-server.sh' io.emit('message_close', n); }); socket.on('get-serverconfig', () => { let rawdatafile = './hybrid/keys.json' if (fs.existsSync(rawdatafile)) { let rawdata = fs.readFileSync(rawdatafile); let config = JSON.parse(rawdata); var n = {} n.file = 'ok' n.data = config io.emit('message_config', n); }else{ var n = {} n.file = 'nodata' n.data = 'nodata' io.emit('message_config', n); } }); }); server.listen(serverPort, function() { console.log('server up and running at %s port', serverPort); });