9 changed files with 3207 additions and 148 deletions
			
			
		@ -0,0 +1,2 @@ | 
				
			|||
node_modules/ | 
				
			|||
public/ | 
				
			|||
@ -0,0 +1,47 @@ | 
				
			|||
{ | 
				
			|||
  "extends": "standard", | 
				
			|||
  "env": { | 
				
			|||
    "es6": true, | 
				
			|||
    "jest": true, | 
				
			|||
    "node": true | 
				
			|||
  }, | 
				
			|||
  "globals": { | 
				
			|||
    "GENTLY": true | 
				
			|||
  }, | 
				
			|||
  "rules": { | 
				
			|||
    "no-multi-spaces": 0, | 
				
			|||
    "comma-dangle": [ | 
				
			|||
      "error", | 
				
			|||
      "always-multiline" | 
				
			|||
    ], | 
				
			|||
    "key-spacing": [ | 
				
			|||
      "error", | 
				
			|||
      { | 
				
			|||
        "multiLine": { | 
				
			|||
          "beforeColon": false, | 
				
			|||
          "afterColon": true | 
				
			|||
        }, | 
				
			|||
        "align": { | 
				
			|||
          "beforeColon": false, | 
				
			|||
          "afterColon": true, | 
				
			|||
          "on": "colon", | 
				
			|||
          "mode": "strict" | 
				
			|||
        } | 
				
			|||
      } | 
				
			|||
    ], | 
				
			|||
    "semi": [ | 
				
			|||
      "error", | 
				
			|||
      "always" | 
				
			|||
    ], | 
				
			|||
    "no-var": [ | 
				
			|||
      "error" | 
				
			|||
    ], | 
				
			|||
    "prefer-const": [ | 
				
			|||
      "error", | 
				
			|||
      { | 
				
			|||
        "destructuring": "any", | 
				
			|||
        "ignoreReadBeforeAssign": false | 
				
			|||
      } | 
				
			|||
    ] | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -1,15 +1,12 @@ | 
				
			|||
FROM node:0.10.38 | 
				
			|||
FROM node:boron | 
				
			|||
MAINTAINER Nathan LeClaire <nathan@docker.com> | 
				
			|||
 | 
				
			|||
ADD . /app | 
				
			|||
WORKDIR /app | 
				
			|||
RUN apt-get update && apt-get upgrade | 
				
			|||
RUN npm install | 
				
			|||
RUN apt-get update | 
				
			|||
RUN apt-get install -y vim | 
				
			|||
RUN useradd -d /home/term -m -s /bin/bash term | 
				
			|||
RUN echo 'term:term' | chpasswd | 
				
			|||
 | 
				
			|||
EXPOSE 3000 | 
				
			|||
 | 
				
			|||
ENTRYPOINT ["node"] | 
				
			|||
CMD ["app.js", "-p", "3000"] | 
				
			|||
CMD ["app.js"] | 
				
			|||
 | 
				
			|||
@ -1,37 +1,36 @@ | 
				
			|||
module.exports = function (grunt) { | 
				
			|||
module.exports = grunt => { | 
				
			|||
  require('load-grunt-tasks')(grunt); | 
				
			|||
 | 
				
			|||
    require('load-grunt-tasks')(grunt); | 
				
			|||
 | 
				
			|||
    var config = { | 
				
			|||
        mkdir: { | 
				
			|||
            tmp: { | 
				
			|||
                options: { | 
				
			|||
                    create: ['tmp'] | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
  const config = { | 
				
			|||
    mkdir: { | 
				
			|||
      tmp: { | 
				
			|||
        options: { | 
				
			|||
          create: ['tmp'], | 
				
			|||
        }, | 
				
			|||
        gitclone: { | 
				
			|||
            hterm: { | 
				
			|||
                options: { | 
				
			|||
                    cwd: './tmp', | 
				
			|||
                    repository: 'https://chromium.googlesource.com/apps/libapps' | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
      }, | 
				
			|||
    }, | 
				
			|||
    gitclone: { | 
				
			|||
      hterm: { | 
				
			|||
        options: { | 
				
			|||
          cwd       : './tmp', | 
				
			|||
          repository: 'https://chromium.googlesource.com/apps/libapps', | 
				
			|||
        }, | 
				
			|||
        shell: { | 
				
			|||
            build_hterm: { | 
				
			|||
                command: 'LIBDOT_SEARCH_PATH=$(pwd) ./libdot/bin/concat.sh -i ./hterm/concat/hterm_all.concat -o ../../public/wetty/hterm_all.js', | 
				
			|||
                options: { | 
				
			|||
                    execOptions: { | 
				
			|||
                        cwd: './tmp/libapps' | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
      }, | 
				
			|||
    }, | 
				
			|||
    shell: { | 
				
			|||
      build_hterm: { | 
				
			|||
        command: 'LIBDOT_SEARCH_PATH=$(pwd) ./libdot/bin/concat.sh -i ./hterm/concat/hterm_all.concat -o ../../public/wetty/hterm_all.js', | 
				
			|||
        options: { | 
				
			|||
          execOptions: { | 
				
			|||
            cwd: './tmp/libapps', | 
				
			|||
          }, | 
				
			|||
        }, | 
				
			|||
        clean: ['./tmp'] | 
				
			|||
    }; | 
				
			|||
      }, | 
				
			|||
    }, | 
				
			|||
    clean: ['./tmp'], | 
				
			|||
  }; | 
				
			|||
 | 
				
			|||
    grunt.initConfig(config); | 
				
			|||
  grunt.initConfig(config); | 
				
			|||
 | 
				
			|||
    grunt.registerTask('update-hterm', ['mkdir:tmp', 'gitclone:hterm', 'shell:build_hterm', 'clean']); | 
				
			|||
  grunt.registerTask('update-hterm', ['mkdir:tmp', 'gitclone:hterm', 'shell:build_hterm', 'clean']); | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
@ -1,142 +1,149 @@ | 
				
			|||
var express = require('express'); | 
				
			|||
var http = require('http'); | 
				
			|||
var https = require('https'); | 
				
			|||
var path = require('path'); | 
				
			|||
var server = require('socket.io'); | 
				
			|||
var pty = require('pty.js'); | 
				
			|||
var fs = require('fs'); | 
				
			|||
const express = require('express'); | 
				
			|||
const http = require('http'); | 
				
			|||
const https = require('https'); | 
				
			|||
const path = require('path'); | 
				
			|||
const server = require('socket.io'); | 
				
			|||
const pty = require('pty.js'); | 
				
			|||
const fs = require('fs'); | 
				
			|||
 | 
				
			|||
var opts = require('optimist') | 
				
			|||
    .options({ | 
				
			|||
        sslkey: { | 
				
			|||
            demand: false, | 
				
			|||
            description: 'path to SSL key' | 
				
			|||
        }, | 
				
			|||
        sslcert: { | 
				
			|||
            demand: false, | 
				
			|||
            description: 'path to SSL certificate' | 
				
			|||
        }, | 
				
			|||
        sshhost: { | 
				
			|||
            demand: false, | 
				
			|||
            description: 'ssh server host' | 
				
			|||
        }, | 
				
			|||
        sshport: { | 
				
			|||
            demand: false, | 
				
			|||
            description: 'ssh server port' | 
				
			|||
        }, | 
				
			|||
        sshuser: { | 
				
			|||
            demand: false, | 
				
			|||
            description: 'ssh user' | 
				
			|||
        }, | 
				
			|||
        sshauth: { | 
				
			|||
            demand: false, | 
				
			|||
            description: 'defaults to "password", you can use "publickey,password" instead' | 
				
			|||
        }, | 
				
			|||
        port: { | 
				
			|||
            demand: true, | 
				
			|||
            alias: 'p', | 
				
			|||
            description: 'wetty listen port' | 
				
			|||
        }, | 
				
			|||
    }).boolean('allow_discovery').argv; | 
				
			|||
const opts = require('optimist') | 
				
			|||
  .options({ | 
				
			|||
    sslkey: { | 
				
			|||
      demand     : false, | 
				
			|||
      description: 'path to SSL key', | 
				
			|||
    }, | 
				
			|||
    sslcert: { | 
				
			|||
      demand     : false, | 
				
			|||
      description: 'path to SSL certificate', | 
				
			|||
    }, | 
				
			|||
    sshhost: { | 
				
			|||
      demand     : false, | 
				
			|||
      description: 'ssh server host', | 
				
			|||
    }, | 
				
			|||
    sshport: { | 
				
			|||
      demand     : false, | 
				
			|||
      description: 'ssh server port', | 
				
			|||
    }, | 
				
			|||
    sshuser: { | 
				
			|||
      demand     : false, | 
				
			|||
      description: 'ssh user', | 
				
			|||
    }, | 
				
			|||
    sshauth: { | 
				
			|||
      demand     : false, | 
				
			|||
      description: 'defaults to "password", you can use "publickey,password" instead', | 
				
			|||
    }, | 
				
			|||
    port: { | 
				
			|||
      demand     : false, | 
				
			|||
      alias      : 'p', | 
				
			|||
      description: 'wetty listen port', | 
				
			|||
    }, | 
				
			|||
  }) | 
				
			|||
  .boolean('allow_discovery').argv; | 
				
			|||
 | 
				
			|||
var runhttps = false; | 
				
			|||
var sshport = 22; | 
				
			|||
var sshhost = 'localhost'; | 
				
			|||
var sshauth = 'password'; | 
				
			|||
var globalsshuser = ''; | 
				
			|||
let runhttps = process.env.HTTPS || false; | 
				
			|||
let globalsshuser = process.env.SSHUSER || ''; | 
				
			|||
let sshhost = process.env.SSHHOST || 'localhost'; | 
				
			|||
let sshauth = process.env.SSHAUTH || 'password'; | 
				
			|||
let sshport = process.env.SSHPOST || 22; | 
				
			|||
let port = process.env.PORT || 3000; | 
				
			|||
 | 
				
			|||
if (opts.sshport) { | 
				
			|||
    sshport = opts.sshport; | 
				
			|||
  sshport = opts.sshport; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
if (opts.sshhost) { | 
				
			|||
    sshhost = opts.sshhost; | 
				
			|||
  sshhost = opts.sshhost; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
if (opts.sshauth) { | 
				
			|||
	sshauth = opts.sshauth | 
				
			|||
  sshauth = opts.sshauth; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
if (opts.sshuser) { | 
				
			|||
    globalsshuser = opts.sshuser; | 
				
			|||
  globalsshuser = opts.sshuser; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
if (opts.port) { | 
				
			|||
  port = opts.port; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
if (opts.sslkey && opts.sslcert) { | 
				
			|||
    runhttps = true; | 
				
			|||
    opts['ssl'] = {}; | 
				
			|||
    opts.ssl['key'] = fs.readFileSync(path.resolve(opts.sslkey)); | 
				
			|||
    opts.ssl['cert'] = fs.readFileSync(path.resolve(opts.sslcert)); | 
				
			|||
  runhttps = true; | 
				
			|||
  opts['ssl'] = {}; | 
				
			|||
  opts.ssl['key'] = fs.readFileSync(path.resolve(opts.sslkey)); | 
				
			|||
  opts.ssl['cert'] = fs.readFileSync(path.resolve(opts.sslcert)); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
process.on('uncaughtException', function(e) { | 
				
			|||
    console.error('Error: ' + e); | 
				
			|||
process.on('uncaughtException', e => { | 
				
			|||
  console.error(`Error: ${e}`); | 
				
			|||
}); | 
				
			|||
 | 
				
			|||
var httpserv; | 
				
			|||
let httpserv; | 
				
			|||
 | 
				
			|||
var app = express(); | 
				
			|||
app.get('/wetty/ssh/:user', function(req, res) { | 
				
			|||
    res.sendfile(__dirname + '/public/wetty/index.html'); | 
				
			|||
const app = express(); | 
				
			|||
app.get('/wetty/ssh/:user', (req, res) => { | 
				
			|||
  res.sendfile(`${__dirname}/public/wetty/index.html`); | 
				
			|||
}); | 
				
			|||
app.use('/', express.static(path.join(__dirname, 'public'))); | 
				
			|||
 | 
				
			|||
if (runhttps) { | 
				
			|||
    httpserv = https.createServer(opts.ssl, app).listen(opts.port, function() { | 
				
			|||
        console.log('https on port ' + opts.port); | 
				
			|||
    }); | 
				
			|||
  httpserv = https.createServer(opts.ssl, app).listen(port, () => { | 
				
			|||
    console.log(`https on port ${port}`); | 
				
			|||
  }); | 
				
			|||
} else { | 
				
			|||
    httpserv = http.createServer(app).listen(opts.port, function() { | 
				
			|||
        console.log('http on port ' + opts.port); | 
				
			|||
    }); | 
				
			|||
  httpserv = http.createServer(app).listen(port, () => { | 
				
			|||
    console.log(`http on port ${port}`); | 
				
			|||
  }); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
var io = server(httpserv,{path: '/wetty/socket.io'}); | 
				
			|||
io.on('connection', function(socket){ | 
				
			|||
    var sshuser = ''; | 
				
			|||
    var request = socket.request; | 
				
			|||
    console.log((new Date()) + ' Connection accepted.'); | 
				
			|||
    if (match = request.headers.referer.match('/wetty/ssh/.+$')) { | 
				
			|||
        sshuser = match[0].replace('/wetty/ssh/', '') + '@'; | 
				
			|||
    } else if (globalsshuser) { | 
				
			|||
        sshuser = globalsshuser + '@'; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    var term; | 
				
			|||
    if (process.getuid() == 0 && sshhost == 'localhost') { | 
				
			|||
        term = pty.spawn('/bin/login', [], { | 
				
			|||
            name: 'xterm-256color', | 
				
			|||
            cols: 80, | 
				
			|||
            rows: 30 | 
				
			|||
        }); | 
				
			|||
    } else if (sshuser) { | 
				
			|||
        term = pty.spawn('ssh', [sshuser + sshhost, '-p', sshport, '-o', 'PreferredAuthentications=' + sshauth], { | 
				
			|||
            name: 'xterm-256color', | 
				
			|||
            cols: 80, | 
				
			|||
            rows: 30 | 
				
			|||
        }); | 
				
			|||
    } else { | 
				
			|||
        term = pty.spawn('./bin/ssh', [sshhost, '-p', sshport, '-o', 'PreferredAuthentications=' + sshauth], { | 
				
			|||
            name: 'xterm-256color', | 
				
			|||
            cols: 80, | 
				
			|||
            rows: 30 | 
				
			|||
        }); | 
				
			|||
    } | 
				
			|||
const io = server(httpserv, { path: '/wetty/socket.io' }); | 
				
			|||
io.on('connection', socket => { | 
				
			|||
  let sshuser = ''; | 
				
			|||
  const request = socket.request; | 
				
			|||
  console.log(`${new Date()} Connection accepted.`); | 
				
			|||
  const match = request.headers.referer.match('/wetty/ssh/.+$'); | 
				
			|||
  if (match) { | 
				
			|||
    sshuser = `${match[0].replace('/wetty/ssh/', '')}@`; | 
				
			|||
  } else if (globalsshuser) { | 
				
			|||
    sshuser = `${globalsshuser}@`; | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
    console.log((new Date()) + " PID=" + term.pid + " STARTED on behalf of user=" + sshuser) | 
				
			|||
    term.on('data', function(data) { | 
				
			|||
        socket.emit('output', data); | 
				
			|||
  let term; | 
				
			|||
  if (process.getuid() === 0 && sshhost === 'localhost') { | 
				
			|||
    term = pty.spawn('/bin/login', [], { | 
				
			|||
      name: 'xterm-256color', | 
				
			|||
      cols: 80, | 
				
			|||
      rows: 30, | 
				
			|||
    }); | 
				
			|||
    term.on('exit', function(code) { | 
				
			|||
        console.log((new Date()) + " PID=" + term.pid + " ENDED"); | 
				
			|||
        socket.emit('logout'); | 
				
			|||
  } else if (sshuser) { | 
				
			|||
    term = pty.spawn('ssh', [sshuser + sshhost, '-p', sshport, '-o', `PreferredAuthentications=${sshauth}`], { | 
				
			|||
      name: 'xterm-256color', | 
				
			|||
      cols: 80, | 
				
			|||
      rows: 30, | 
				
			|||
    }); | 
				
			|||
    socket.on('resize', function(data) { | 
				
			|||
        term.resize(data.col, data.row); | 
				
			|||
  } else { | 
				
			|||
    term = pty.spawn('./bin/ssh', [sshhost, '-p', sshport, '-o', `PreferredAuthentications=${sshauth}`], { | 
				
			|||
      name: 'xterm-256color', | 
				
			|||
      cols: 80, | 
				
			|||
      rows: 30, | 
				
			|||
    }); | 
				
			|||
    socket.on('input', function(data) { | 
				
			|||
        term.write(data); | 
				
			|||
    }); | 
				
			|||
    socket.on('disconnect', function() { | 
				
			|||
        term.end(); | 
				
			|||
    }); | 
				
			|||
}) | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  console.log(`${new Date()} PID=${term.pid} STARTED on behalf of user=${sshuser}`); | 
				
			|||
  term.on('data', data => { | 
				
			|||
    socket.emit('output', data); | 
				
			|||
  }); | 
				
			|||
  term.on('exit', code => { | 
				
			|||
    console.log(`${new Date()} PID=${term.pid} ENDED`); | 
				
			|||
    socket.emit('logout'); | 
				
			|||
  }); | 
				
			|||
  socket.on('resize', ({ col, row }) => { | 
				
			|||
    term.resize(col, row); | 
				
			|||
  }); | 
				
			|||
  socket.on('input', data => { | 
				
			|||
    term.write(data); | 
				
			|||
  }); | 
				
			|||
  socket.on('disconnect', () => { | 
				
			|||
    term.end(); | 
				
			|||
  }); | 
				
			|||
}); | 
				
			|||
 | 
				
			|||
@ -1,3 +1,3 @@ | 
				
			|||
#!/usr/bin/env node
 | 
				
			|||
 | 
				
			|||
require("../app"); | 
				
			|||
require('../app'); | 
				
			|||
 | 
				
			|||
@ -0,0 +1,15 @@ | 
				
			|||
version: "3" | 
				
			|||
 | 
				
			|||
services: | 
				
			|||
  wetty: | 
				
			|||
    image: node:boron | 
				
			|||
    container_name: wetty | 
				
			|||
    build: . | 
				
			|||
    tty: true | 
				
			|||
    working_dir: /app | 
				
			|||
    ports: | 
				
			|||
      - "3000:3000" | 
				
			|||
    environment: | 
				
			|||
      PORT: 3000 | 
				
			|||
      SSHHOST: 'localhost' | 
				
			|||
      SSHPORT: 22 | 
				
			|||
								
									
										File diff suppressed because it is too large
									
								
							
						
					
					Loading…
					
					
				
		Reference in new issue