refactro: firstconnect with key instead of password
This commit is contained in:
		@@ -2,19 +2,19 @@ import * as fs from 'fs';
 | 
			
		||||
import * as path from 'path';
 | 
			
		||||
import * as os from 'os';
 | 
			
		||||
import * as vscode from 'vscode';
 | 
			
		||||
import * as rd from 'readline'
 | 
			
		||||
const { NodeSSH } = require('node-ssh')
 | 
			
		||||
 | 
			
		||||
import * as utils from './utils';
 | 
			
		||||
 | 
			
		||||
export default class RemoteContainer {
 | 
			
		||||
 | 
			
		||||
  async firstConnect(host: string, username: string, password: string, port: number): Promise<string> {
 | 
			
		||||
    return new Promise(async (resolve, reject) => {
 | 
			
		||||
      // connect the host and add the public key to the remote authorized_keys
 | 
			
		||||
      const defaultPublicKeyPath = path.join(os.homedir(), '.ssh', 'id_rsa.pub');
 | 
			
		||||
      // TODO: if there is no public key, generate one
 | 
			
		||||
      const publicKey = fs.readFileSync(defaultPublicKeyPath, 'utf8');
 | 
			
		||||
  async firstConnect(host: string, username: string, port: number): Promise<string>; // connect with key
 | 
			
		||||
  // deprecated
 | 
			
		||||
  async firstConnect(host: string, username: string, port: number, password: string): Promise<string>; 
 | 
			
		||||
 | 
			
		||||
      // first connect to the remote host using password
 | 
			
		||||
  async firstConnect(host: string, username: string, port: number, password?: string): Promise<string> {
 | 
			
		||||
    return new Promise(async (resolve, reject) => {
 | 
			
		||||
      const ssh = new NodeSSH();
 | 
			
		||||
      vscode.window.withProgress({
 | 
			
		||||
          location: vscode.ProgressLocation.Notification,
 | 
			
		||||
@@ -22,6 +22,40 @@ export default class RemoteContainer {
 | 
			
		||||
          cancellable: false
 | 
			
		||||
      }, async (progress) => {
 | 
			
		||||
      try {
 | 
			
		||||
 | 
			
		||||
        if (password === undefined) {
 | 
			
		||||
          // connect with key
 | 
			
		||||
          await ssh.connect({
 | 
			
		||||
            host: host,
 | 
			
		||||
            username: username,
 | 
			
		||||
            port: port,
 | 
			
		||||
            privateKey: utils.getDefaultPrivateKey()
 | 
			
		||||
          });
 | 
			
		||||
          progress.report({ message: "连接成功,开始安装" });
 | 
			
		||||
 | 
			
		||||
          // install vscode-server and devstar extension
 | 
			
		||||
          const vscodeCommitId = await utils.getVsCodeCommitId();
 | 
			
		||||
          const vscodeServerUrl = `https://vscode.download.prss.microsoft.com/dbazure/download/stable/${vscodeCommitId}/vscode-server-linux-x64.tar.gz`
 | 
			
		||||
          const installVscodeServerScript = `
 | 
			
		||||
          mkdir -p ~/.vscode-server/bin/${vscodeCommitId} && \\
 | 
			
		||||
          if [ "$(ls -A ~/.vscode-server/bin/${vscodeCommitId})" ]; then
 | 
			
		||||
              ~/.vscode-server/bin/${vscodeCommitId}/bin/code-server --install-extension mengning.devstar
 | 
			
		||||
          else
 | 
			
		||||
              wget ${vscodeServerUrl} -O vscode-server-linux-x64.tar.gz && \\
 | 
			
		||||
              mv vscode-server-linux-x64.tar.gz ~/.vscode-server/bin/${vscodeCommitId} && \\
 | 
			
		||||
              cd ~/.vscode-server/bin/${vscodeCommitId} && \\
 | 
			
		||||
              tar -xvzf vscode-server-linux-x64.tar.gz --strip-components 1 && \\
 | 
			
		||||
              rm vscode-server-linux-x64.tar.gz && \\
 | 
			
		||||
              ~/.vscode-server/bin/${vscodeCommitId}/bin/code-server --install-extension mengning.devstar
 | 
			
		||||
          fi
 | 
			
		||||
          `;
 | 
			
		||||
          await ssh.execCommand(installVscodeServerScript);
 | 
			
		||||
          console.log("vscode-server and extension installed");
 | 
			
		||||
          vscode.window.showInformationMessage('安装完成!');
 | 
			
		||||
 | 
			
		||||
          await ssh.dispose();
 | 
			
		||||
        } else {
 | 
			
		||||
          // connect with password (deprecate in future)
 | 
			
		||||
          await ssh.connect({
 | 
			
		||||
            host: host,
 | 
			
		||||
            username: username,
 | 
			
		||||
@@ -51,27 +85,58 @@ export default class RemoteContainer {
 | 
			
		||||
          vscode.window.showInformationMessage('安装完成!');
 | 
			
		||||
 | 
			
		||||
          // add the public key to the remote authorized_keys
 | 
			
		||||
          if (!utils.existDefaultPublicKey() || !utils.existDefaultPrivateKey()) {
 | 
			
		||||
            // if there is no public key, generate one
 | 
			
		||||
            utils.createSSHKey()
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          const publicKey = utils.getDefaultPublicKey();
 | 
			
		||||
          await ssh.execCommand(`mkdir -p ~/.ssh && echo '${publicKey}' >> ~/.ssh/authorized_keys`);
 | 
			
		||||
          console.log('Public key added to remote authorized_keys');
 | 
			
		||||
 | 
			
		||||
          await ssh.dispose();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error('Failed to install vscode-server and extension: ', error);
 | 
			
		||||
        await ssh.dispose();
 | 
			
		||||
        reject(error);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // only connect successfully then save the host info
 | 
			
		||||
        // TODO: request change password
 | 
			
		||||
        // TODO: use remote.SSH.configFile
 | 
			
		||||
      const sshConfigPath = path.join(os.homedir(), '.ssh', 'config');
 | 
			
		||||
        // append the host to the local ssh config file 
 | 
			
		||||
        const sshConfigContent =
 | 
			
		||||
      // check if the host and related info exist in local ssh config file before saving
 | 
			
		||||
      var canAppendSSHConfig = true
 | 
			
		||||
      if (fs.existsSync(sshConfigPath)) {
 | 
			
		||||
        var hasHost = false;
 | 
			
		||||
        var hasPort = false;
 | 
			
		||||
        var reader = rd.createInterface(fs.createReadStream(sshConfigPath))
 | 
			
		||||
        reader.on("line", (l:string) => {
 | 
			
		||||
          if (l.includes(`HostName ${host}`)) {
 | 
			
		||||
            hasHost = true
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (l.includes(`Port ${port}`)) {
 | 
			
		||||
            hasPort = true
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        if (hasHost && hasPort) {
 | 
			
		||||
          // the container ssh info exists
 | 
			
		||||
          canAppendSSHConfig = false
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (canAppendSSHConfig) {
 | 
			
		||||
        // save the host to the local ssh config file 
 | 
			
		||||
        const newSShConfigContent =
 | 
			
		||||
          `\nHost ${host}\n  HostName ${host}\n  Port ${port}\n  User ${username}\n  PreferredAuthentications publickey\n  IdentityFile ~/.ssh/id_rsa\n  `;
 | 
			
		||||
        // append the host to the local ssh config file
 | 
			
		||||
        fs.writeFileSync(sshConfigPath, sshConfigContent, { encoding: 'utf8', flag: 'a' });
 | 
			
		||||
        fs.writeFileSync(sshConfigPath, newSShConfigContent, { encoding: 'utf8', flag: 'a' });
 | 
			
		||||
        console.log('Host registered in local ssh config');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      resolve("success");
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error('Error adding public key: ', error);
 | 
			
		||||
        await ssh.dispose();
 | 
			
		||||
        reject("failed");
 | 
			
		||||
      }});
 | 
			
		||||
    });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user