text: // Generated by CoffeeScript 2.4.1
  // # `nikita.ssh.root`
  
  // Prepare the system to receive password-less root login with SSL/TLS keys.
  
  // Prior executing this handler, a user with appropriate sudo permissions must be 
  // created. The script will use those credentials
  // to loggin and will try to become root with the "sudo" command. Use the "cmd" 
  // property if you must use a different command (such as "sudo su -").
  
  // Additionnally, it disables SELINUX which require a restart. The restart is 
  // handled by Masson and the installation procedure will continue as soon as an 
  // SSH connection is again available.
  
  // ## Options
  
  // * `cmd` (string | function)   
  //   Command used to become the root user on the remote server, for exemple 
  //   `su -`.
  // * `public_key` (string | Buffer)   
  //   Public key added to "authorized_keys" to enable the root user.
  // * `public_key_path` (string | Buffer)   
  //   Local path to the public key added to "authorized_keys" to enable the root 
  //   user.
  // * `username` (string)   
  //   Username of the user with sudo permissions to establish the SSH connection.
  // * `password` (string)   
  //   Password of the user with sudo permissions to establish the SSH connection 
  //   if no private key is provided.
  // * `private_key` (string)   
  //   Private key of the user with sudo permissions to establish the SSH 
  //   connection if no password is provided.
  // * `private_key_path` (string)   
  //   Local path to the private key of the user with sudo permissions to 
  //   establish the SSH connection if no password is provided.
  // * `selinux` (string | boolean)   
  //   Controls the state of SELinux on the system, values are "enforcing", 
  //   "permissive", "disabled".
  
  // ## Exemple
  
  // ```js
  // require('nikita')
  // .ssh.root({
  //   "username": "vagrant",
  //   "private_key_path": "/Users/wdavidw/.vagrant.d/insecure_private_key"
  //   "public_key_path": "~/.ssh/id_rsa.pub"
  // }, function(err){
  //   console.log(err || "Public key updoaded for root user");
  // });
  // ```
  
  // ## Source code
  var connect, exec, fs, misc, util;
  
  module.exports = {
    handler: function({options}) {
      var rebooting, ref;
      this.log({
        message: "Entering ssh.root",
        level: 'DEBUG',
        module: 'nikita/lib/ssh/root'
      });
      if (options.host == null) {
        options.host = options.ip;
      }
      // options.cmd ?= 'su -'
      if (options.username == null) {
        options.username = null;
      }
      if (options.password == null) {
        options.password = null;
      }
      if (options.selinux == null) {
        options.selinux = false;
      }
      if (options.selinux === true) {
        options.selinux = 'permissive';
      }
      if (options.selinux && ((ref = options.selinux) !== 'enforcing' && ref !== 'permissive' && ref !== 'disabled')) {
        // Validation
        throw Error(`Invalid option "selinux": ${options.selinux}`);
      }
      rebooting = false;
      // Read public key if option is a path
      this.call({
        if: options.public_key_path,
        unless: options.public_key
      }, function({}, callback) {
        return misc.path.normalize(options.public_key_path, (location) => {
          return fs.readFile(location, 'ascii', (err, data) => {
            if (err && err.code === 'ENOENT') {
              return callback(Error(`Private key doesnt exists: ${JSON.stringify(location)}`));
            }
            if (err) {
              return callback(err);
            }
            options.public_key = data;
            return callback();
          });
        });
      });
      // Read private key if option is a path
      this.call({
        if: options.private_key_path,
        unless: options.private_key
      }, function({}, callback) {
        this.log({
          message: `Read Private Key: ${JSON.stringify(options.private_key_path)}`,
          level: 'DEBUG',
          module: 'nikita/lib/ssh/root'
        });
        return misc.path.normalize(options.private_key_path, function(location) {
          return fs.readFile(location, 'ascii', function(err, data) {
            if (err && err.code === 'ENOENT') {
              return callback(Error(`Private key doesnt exists: ${JSON.stringify(location)}`));
            }
            if (err) {
              return callback(err);
            }
            options.private_key = data;
            return callback();
          });
        });
      });
      this.call(function({}, callback) {
        this.log({
          message: "Connecting",
          level: 'DEBUG',
          module: 'nikita/lib/ssh/root'
        });
        return connect(options, (err, ssh) => {
          var child, cmd;
          if (err) {
            return callback(err);
          }
          this.log({
            message: "Connected",
            level: 'INFO',
            module: 'nikita/lib/ssh/root'
          });
          cmd = [];
          cmd.push("sed -i.back 's/.*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config;");
          if (options.public_key) {
            cmd.push(`mkdir -p /root/.ssh; chmod 700 /root/.ssh;\necho '${options.public_key}' >> /root/.ssh/authorized_keys;`);
          }
          cmd.push(`sed -i.back 's/.*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config;\nselinux="${options.selinux || ''}";\nif [ -n "$selinux" ] && [ -f /etc/selinux/config ] && grep ^SELINUX="$selinux" /etc/selinux/config;\nthen\n  sed -i.back "s/^SELINUX=enforcing/SELINUX=$selinux/" /etc/selinux/config;\n  ( reboot )&\n  exit 2;\nfi;`);
          cmd = cmd.join('\n');
          if (options.username !== 'root') {
            cmd = cmd.replace(/\n/g, ' ');
            if (typeof options.cmd === 'function') {
              cmd = options.cmd(cmd);
            } else if (typeof options.cmd === 'string') {
              cmd = `${options.cmd} ${cmd}`;
            } else {
              options.cmd = 'sudo ';
              if (options.user) {
                options.cmd += `-u ${options.user} `;
              }
              if (options.password) {
                options.cmd = `echo -e "${options.password}\\n" | ${options.cmd} -S `;
              }
              options.cmd += `-- sh -c "${cmd}"`;
              cmd = options.cmd;
            }
          }
          this.log({
            message: "Enable Root Access",
            level: 'DEBUG',
            module: 'nikita/lib/ssh/root'
          });
          this.log({
            message: cmd,
            type: 'stdin',
            module: 'nikita/lib/ssh/root'
          });
          child = exec({
            ssh: ssh,
            cmd: cmd
          }, (err) => {
            if ((err != null ? err.code : void 0) === 2) {
              this.log({
                message: "Root Access Enabled",
                level: 'WARN',
                module: 'nikita/lib/ssh/root'
              });
              err = null;
              rebooting = true;
            }
            return callback(err);
          });
          child.stdout.on('data', (data) => {
            return this.log({
              message: data,
              type: 'stdout',
              module: 'nikita/lib/ssh/root'
            });
          });
          child.stdout.on('end', (data) => {
            return this.log({
              message: null,
              type: 'stdout',
              module: 'nikita/lib/ssh/root'
            });
          });
          child.stderr.on('data', (data) => {
            return this.log({
              message: data,
              type: 'stderr',
              module: 'nikita/lib/ssh/root'
            });
          });
          return child.stderr.on('end', (data) => {
            return this.log({
              message: null,
              type: 'stderr',
              module: 'nikita/lib/ssh/root'
            });
          });
        });
      });
      return this.call({
        retry: true,
        sleep: 3000,
        if: (function() {
          return rebooting;
        })
      }, function({}, callback) {
        return connect(options, (err, conn) => {
          if (err) {
            return callback(err);
          }
          conn.end();
          conn.on('error', callback);
          return conn.on('end', callback);
        });
      });
    }
  };
  
  // ## Dependencies
  fs = require('fs');
  
  util = require('util');
  
  connect = require('ssh2-connect');
  
  exec = require('ssh2-exec');
  
  misc = require('../misc');
  