Files
DLE/webssh-agent/utils/sshUtils.js
2025-11-06 18:07:18 +03:00

131 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { exec } = require('child_process');
const fs = require('fs-extra');
const os = require('os');
const path = require('path');
const log = require('./logger');
const sshDir = path.join(os.homedir(), '.ssh');
const privateKeyPath = path.join(sshDir, 'id_rsa');
const publicKeyPath = `${privateKeyPath}.pub`;
const sshConfigPath = path.join(sshDir, 'config');
const ensureSshPermissions = async () => {
try {
await fs.ensureDir(sshDir);
await fs.chmod(sshDir, 0o700).catch(() => {});
await fs.chmod(privateKeyPath, 0o600).catch(() => {});
await fs.chmod(publicKeyPath, 0o644).catch(() => {});
await fs.chmod(sshConfigPath, 0o600).catch(() => {});
} catch (error) {
log.warn('Не удалось скорректировать права доступа к SSH директории: ' + error.message);
}
};
const execSshCommand = async (command, options = {}) => {
const {
sshHost,
sshPort = 22,
sshConnectUser,
sshConnectPassword,
vdsIp
} = options;
await ensureSshPermissions();
const privateKeyExists = await fs.pathExists(privateKeyPath);
const escapedCommand = command.replace(/"/g, '\\"');
let sshCommand = `ssh -p ${sshPort} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${sshConnectUser}@${sshHost || vdsIp} "${escapedCommand}"`;
if (privateKeyExists) {
sshCommand = `ssh -i "${privateKeyPath}" -p ${sshPort} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${sshConnectUser}@${sshHost || vdsIp} "${escapedCommand}"`;
}
log.info(`🔍 Выполняем SSH команду: ${sshCommand}`);
return new Promise((resolve) => {
exec(sshCommand, (error, stdout, stderr) => {
log.info(`📤 SSH результат - код: ${error ? error.code : 0}, stdout: "${stdout}", stderr: "${stderr}"`);
if (error && error.code === 255 && sshConnectPassword) {
log.info('SSH ключи не сработали, пробуем с паролем...');
const passwordCommand = `sshpass -p "${sshConnectPassword}" ssh -p ${sshPort} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${sshConnectUser}@${sshHost || vdsIp} "${escapedCommand}"`;
exec(passwordCommand, (passwordError, passwordStdout, passwordStderr) => {
log.info(`📤 SSH с паролем результат - код: ${passwordError ? passwordError.code : 0}, stdout: "${passwordStdout}", stderr: "${passwordStderr}"`);
resolve({
code: passwordError ? passwordError.code : 0,
stdout: passwordStdout || '',
stderr: passwordStderr || ''
});
});
} else {
resolve({
code: error ? error.code : 0,
stdout: stdout || '',
stderr: stderr || ''
});
}
});
});
};
const execScpCommand = async (sourcePath, targetPath, options = {}) => {
const {
sshHost,
sshPort = 22,
sshConnectUser,
sshConnectPassword,
vdsIp
} = options;
await ensureSshPermissions();
const privateKeyExists = await fs.pathExists(privateKeyPath);
let scpCommand = `scp -P ${sshPort} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${sourcePath} ${sshConnectUser}@${sshHost || vdsIp}:${targetPath}`;
if (privateKeyExists) {
scpCommand = `scp -i "${privateKeyPath}" -P ${sshPort} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${sourcePath} ${sshConnectUser}@${sshHost || vdsIp}:${targetPath}`;
}
return new Promise((resolve) => {
exec(scpCommand, (error, stdout, stderr) => {
if (error && error.code === 255 && sshConnectPassword) {
log.info('SCP с ключами не сработал, пробуем с паролем...');
const passwordScpCommand = `sshpass -p "${sshConnectPassword}" scp -P ${sshPort} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${sourcePath} ${sshConnectUser}@${sshHost || vdsIp}:${targetPath}`;
exec(passwordScpCommand, (passwordError, passwordStdout, passwordStderr) => {
if (passwordError) {
log.error('❌ Ошибка SCP: ' + passwordError.message);
} else {
log.success('✅ SCP успешно выполнен');
}
resolve({
code: passwordError ? passwordError.code : 0,
stdout: passwordStdout || '',
stderr: passwordStderr || ''
});
});
} else {
if (error) {
log.error('❌ Ошибка SCP: ' + error.message);
} else {
log.success('✅ SCP успешно выполнен');
}
resolve({
code: error ? error.code : 0,
stdout: stdout || '',
stderr: stderr || ''
});
}
});
});
};
module.exports = {
execSshCommand,
execScpCommand,
fixSshPermissions: ensureSshPermissions
};