mirror of
				https://github.com/whyour/qinglong.git
				synced 2025-11-04 02:56:07 +08:00 
			
		
		
		
	重构私有仓库ssh配置逻辑
This commit is contained in:
		
							parent
							
								
									083c8869aa
								
							
						
					
					
						commit
						b27ee23cc3
					
				
							
								
								
									
										4
									
								
								.github/workflows/build_docker_image.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/build_docker_image.yml
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -44,8 +44,6 @@ jobs:
 | 
			
		|||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v3
 | 
			
		||||
      - uses: pnpm/action-setup@v2
 | 
			
		||||
        with:
 | 
			
		||||
          version: 7
 | 
			
		||||
 | 
			
		||||
      - uses: actions/setup-node@v3
 | 
			
		||||
        with:
 | 
			
		||||
| 
						 | 
				
			
			@ -98,8 +96,6 @@ jobs:
 | 
			
		|||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v3
 | 
			
		||||
      - uses: pnpm/action-setup@v2
 | 
			
		||||
        with:
 | 
			
		||||
          version: 7
 | 
			
		||||
      - uses: actions/setup-node@v3
 | 
			
		||||
        with:
 | 
			
		||||
          cache: 'pnpm'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ const bakPath = path.join(dataPath, 'bak/');
 | 
			
		|||
const logPath = path.join(dataPath, 'log/');
 | 
			
		||||
const dbPath = path.join(dataPath, 'db/');
 | 
			
		||||
const uploadPath = path.join(dataPath, 'upload/');
 | 
			
		||||
const sshdPath = path.join(dataPath, 'ssh.d/');
 | 
			
		||||
 | 
			
		||||
const envFile = path.join(configPath, 'env.sh');
 | 
			
		||||
const confFile = path.join(configPath, 'config.sh');
 | 
			
		||||
| 
						 | 
				
			
			@ -95,4 +96,5 @@ export default {
 | 
			
		|||
  versionFile,
 | 
			
		||||
  lastVersionFile,
 | 
			
		||||
  sqliteFile,
 | 
			
		||||
  sshdPath,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ const sampleConfigFile = path.join(samplePath, 'config.sample.sh');
 | 
			
		|||
const sampleAuthFile = path.join(samplePath, 'auth.sample.json');
 | 
			
		||||
const homedir = os.homedir();
 | 
			
		||||
const sshPath = path.resolve(homedir, '.ssh');
 | 
			
		||||
const sshdPath = path.join(dataPath, 'ssh.d');
 | 
			
		||||
 | 
			
		||||
export default async () => {
 | 
			
		||||
  const authFileExist = await fileExist(authConfigFile);
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +30,7 @@ export default async () => {
 | 
			
		|||
  const uploadDirExist = await fileExist(uploadPath);
 | 
			
		||||
  const sshDirExist = await fileExist(sshPath);
 | 
			
		||||
  const bakDirExist = await fileExist(bakPath);
 | 
			
		||||
  const sshdDirExist = await fileExist(sshdPath);
 | 
			
		||||
 | 
			
		||||
  if (!configDirExist) {
 | 
			
		||||
    fs.mkdirSync(configPath);
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +64,10 @@ export default async () => {
 | 
			
		|||
    fs.mkdirSync(bakPath);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!sshdDirExist) {
 | 
			
		||||
    fs.mkdirSync(sshdPath);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  dotenv.config({ path: confFile });
 | 
			
		||||
 | 
			
		||||
  Logger.info('✌️ Init file down');
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,14 +5,25 @@ import os from 'os';
 | 
			
		|||
import path from 'path';
 | 
			
		||||
import { Subscription } from '../data/subscription';
 | 
			
		||||
import { formatUrl } from '../config/subscription';
 | 
			
		||||
import config from '../config';
 | 
			
		||||
 | 
			
		||||
@Service()
 | 
			
		||||
export default class SshKeyService {
 | 
			
		||||
  private homedir = os.homedir();
 | 
			
		||||
  private sshPath = path.resolve(this.homedir, '.ssh');
 | 
			
		||||
  private sshConfigFilePath = path.resolve(this.sshPath, 'config');
 | 
			
		||||
  private sshPath = config.sshdPath;
 | 
			
		||||
  private sshConfigFilePath = path.resolve(this.homedir, '.ssh', 'config');
 | 
			
		||||
  private sshConfigHeader = `Include ${this.sshPath}*.config`;
 | 
			
		||||
 | 
			
		||||
  constructor(@Inject('logger') private logger: winston.Logger) {}
 | 
			
		||||
  constructor(@Inject('logger') private logger: winston.Logger) {
 | 
			
		||||
    this.initSshConfigFile()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private initSshConfigFile() {
 | 
			
		||||
    const config = fs.readFileSync(this.sshConfigFilePath, { encoding: 'utf-8' })
 | 
			
		||||
    if (!config.includes(this.sshConfigHeader)) {
 | 
			
		||||
      fs.writeFileSync(this.sshConfigFilePath, `${this.sshConfigHeader}\n\n${config}`, { encoding: 'utf-8' });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private generatePrivateKeyFile(alias: string, key: string): void {
 | 
			
		||||
    try {
 | 
			
		||||
| 
						 | 
				
			
			@ -25,18 +36,11 @@ export default class SshKeyService {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private getConfigRegx(alias: string) {
 | 
			
		||||
    return new RegExp(
 | 
			
		||||
      `Host ${alias}\n.*[^StrictHostKeyChecking]*.*[\n]*.*StrictHostKeyChecking no`,
 | 
			
		||||
      'g',
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private removePrivateKeyFile(alias: string): void {
 | 
			
		||||
    try {
 | 
			
		||||
      const filePath = path.join(this.sshPath, alias);
 | 
			
		||||
      if (existsSync(filePath)) {
 | 
			
		||||
        fs.unlinkSync(`${this.sshPath}/${alias}`);
 | 
			
		||||
        fs.unlinkSync(filePath);
 | 
			
		||||
      }
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      this.logger.error('删除私钥文件失败', error);
 | 
			
		||||
| 
						 | 
				
			
			@ -47,34 +51,21 @@ export default class SshKeyService {
 | 
			
		|||
    alias: string,
 | 
			
		||||
    host: string,
 | 
			
		||||
    proxy?: string,
 | 
			
		||||
  ): string {
 | 
			
		||||
  ) {
 | 
			
		||||
    if (host === 'github.com') {
 | 
			
		||||
      host = `ssh.github.com\n    Port 443\n    HostkeyAlgorithms +ssh-rsa\n    PubkeyAcceptedAlgorithms +ssh-rsa`;
 | 
			
		||||
    }
 | 
			
		||||
    const proxyStr = proxy ? `    ProxyCommand nc -v -x ${proxy} %h %p\n` : '';
 | 
			
		||||
    return `Host ${alias}\n    Hostname ${host}\n    IdentityFile ${this.sshPath}/${alias}\n    StrictHostKeyChecking no\n${proxyStr}`;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private generateSshConfig(configs: string[]) {
 | 
			
		||||
    try {
 | 
			
		||||
      fs.writeFileSync(this.sshConfigFilePath, configs.join('\n'), {
 | 
			
		||||
        encoding: 'utf8',
 | 
			
		||||
      });
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      this.logger.error('写入ssh配置文件失败', error);
 | 
			
		||||
    }
 | 
			
		||||
    const config = `Host ${alias}\n    Hostname ${host}\n    IdentityFile ${this.sshPath}/${alias}\n    StrictHostKeyChecking no\n${proxyStr}`;
 | 
			
		||||
    fs.writeFileSync(`${this.sshPath}/${alias}.config`, config, { encoding: 'utf8' });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private removeSshConfig(alias: string) {
 | 
			
		||||
    try {
 | 
			
		||||
      const configRegx = this.getConfigRegx(alias);
 | 
			
		||||
      const data = fs
 | 
			
		||||
        .readFileSync(this.sshConfigFilePath, { encoding: 'utf8' })
 | 
			
		||||
        .replace(configRegx, '')
 | 
			
		||||
        .replace(/\n[\n]+/g, '\n');
 | 
			
		||||
      fs.writeFileSync(this.sshConfigFilePath, data, {
 | 
			
		||||
        encoding: 'utf8',
 | 
			
		||||
      });
 | 
			
		||||
      const filePath = path.join(this.sshPath, `${alias}.config`);
 | 
			
		||||
      if (existsSync(filePath)) {
 | 
			
		||||
        fs.unlinkSync(filePath);
 | 
			
		||||
      }
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      this.logger.error(`删除ssh配置文件${alias}失败`, error);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -87,32 +78,27 @@ export default class SshKeyService {
 | 
			
		|||
    proxy?: string,
 | 
			
		||||
  ): void {
 | 
			
		||||
    this.generatePrivateKeyFile(alias, key);
 | 
			
		||||
    const config = this.generateSingleSshConfig(alias, host, proxy);
 | 
			
		||||
    this.removeSshConfig(alias);
 | 
			
		||||
    this.generateSshConfig([config]);
 | 
			
		||||
    this.generateSingleSshConfig(alias, host, proxy);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public removeSSHKey(alias: string, host: string, proxy?: string): void {
 | 
			
		||||
    this.removePrivateKeyFile(alias);
 | 
			
		||||
    const config = this.generateSingleSshConfig(alias, host, proxy);
 | 
			
		||||
    this.removeSshConfig(config);
 | 
			
		||||
    this.removeSshConfig(alias);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public setSshConfig(docs: Subscription[]) {
 | 
			
		||||
    let result = [];
 | 
			
		||||
    for (const doc of docs) {
 | 
			
		||||
      if (doc.type === 'private-repo' && doc.pull_type === 'ssh-key') {
 | 
			
		||||
        const { alias, proxy } = doc;
 | 
			
		||||
        const { host } = formatUrl(doc);
 | 
			
		||||
        this.removePrivateKeyFile(alias);
 | 
			
		||||
        this.removeSshConfig(alias);
 | 
			
		||||
        this.generatePrivateKeyFile(
 | 
			
		||||
          alias,
 | 
			
		||||
          (doc.pull_option as any).private_key,
 | 
			
		||||
        );
 | 
			
		||||
        const config = this.generateSingleSshConfig(alias, host, proxy);
 | 
			
		||||
        result.push(config);
 | 
			
		||||
        this.generateSingleSshConfig(alias, host, proxy);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.generateSshConfig(result);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5930
									
								
								pnpm-lock.yaml
									
									
									
									
									
								
							
							
						
						
									
										5930
									
								
								pnpm-lock.yaml
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user