♻️ 重构本地数据库-host模块
This commit is contained in:
parent
a72ab84cee
commit
5724ede172
@ -1,4 +1,7 @@
|
||||
const { readGroupList, writeGroupList, readHostList, writeHostList } = require('../utils/storage')
|
||||
const { readGroupList, writeGroupList } = require('../utils/storage')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
async function getGroupList({ res }) {
|
||||
let data = await readGroupList()
|
||||
@ -41,16 +44,17 @@ const removeGroup = async ({ res, request }) => {
|
||||
if (idx === -1) return res.fail({ msg: '分组不存在' })
|
||||
|
||||
// 移除分组将所有该分组下host分配到default中去
|
||||
let hostList = await readHostList()
|
||||
hostList = hostList?.map((item) => {
|
||||
if (item.group === groupList[idx]._id) item.group = 'default'
|
||||
return item
|
||||
})
|
||||
await writeHostList(hostList)
|
||||
|
||||
let hostList = await hostListDB.findAsync({})
|
||||
if (Array.isArray(hostList) && hostList.length > 0) {
|
||||
for (let item of hostList) {
|
||||
if (item.group === groupList[idx]._id) {
|
||||
item.group = 'default'
|
||||
await hostListDB.updateAsync({ _id: item._id }, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
groupList.splice(idx, 1)
|
||||
await writeGroupList(groupList)
|
||||
|
||||
res.success({ data: '移除成功' })
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,16 @@
|
||||
const { readHostList, writeHostList } = require('../utils/storage')
|
||||
const { RSADecryptSync, AESEncryptSync, AESDecryptSync } = require('../utils/encrypt')
|
||||
const { RSADecryptAsync, AESEncryptAsync, AESDecryptAsync } = require('../utils/encrypt')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
async function getHostList({ res }) {
|
||||
// console.log('get-host-list')
|
||||
let data = await readHostList()
|
||||
let data = await hostListDB.findAsync({})
|
||||
data?.sort((a, b) => Number(b.index || 0) - Number(a.index || 0))
|
||||
for (const item of data) {
|
||||
try {
|
||||
let { username, port, authType, _id: id, credential } = item
|
||||
// console.log('解密凭证title: ', credential)
|
||||
if (credential) credential = await AESDecryptSync(credential)
|
||||
if (credential) credential = await AESDecryptAsync(credential)
|
||||
const isConfig = Boolean(username && port && (item[authType]))
|
||||
Object.assign(item, { id, isConfig, password: '', privateKey: '', credential })
|
||||
} catch (error) {
|
||||
@ -19,9 +20,7 @@ async function getHostList({ res }) {
|
||||
res.success({ data })
|
||||
}
|
||||
|
||||
async function addHost({
|
||||
res, request
|
||||
}) {
|
||||
async function addHost({ res, request }) {
|
||||
let {
|
||||
body: {
|
||||
name, host, index, expired, expiredNotify, group, consoleUrl, remark,
|
||||
@ -30,21 +29,19 @@ async function addHost({
|
||||
} = request
|
||||
// console.log(request)
|
||||
if (!host || !name) return res.fail({ msg: 'missing params: name or host' })
|
||||
let hostList = await readHostList()
|
||||
let record = {
|
||||
name, host, index, expired, expiredNotify, group, consoleUrl, remark,
|
||||
port: newPort, clientPort, username, authType, password, privateKey, credential, command
|
||||
}
|
||||
if (record[authType]) {
|
||||
const clearTempKey = await RSADecryptSync(tempKey)
|
||||
const clearTempKey = await RSADecryptAsync(tempKey)
|
||||
console.log('clearTempKey:', clearTempKey)
|
||||
const clearSSHKey = await AESDecryptSync(record[authType], clearTempKey)
|
||||
const clearSSHKey = await AESDecryptAsync(record[authType], clearTempKey)
|
||||
console.log(`${ authType }原密文: `, clearSSHKey)
|
||||
record[authType] = await AESEncryptSync(clearSSHKey)
|
||||
record[authType] = await AESEncryptAsync(clearSSHKey)
|
||||
// console.log(`${ authType }__commonKey加密存储: `, record[authType])
|
||||
}
|
||||
hostList.push(record)
|
||||
await writeHostList(hostList)
|
||||
await hostListDB.insertAsync(record)
|
||||
res.success()
|
||||
}
|
||||
|
||||
@ -60,78 +57,65 @@ async function updateHost({ res, request }) {
|
||||
let isBatch = Array.isArray(hosts)
|
||||
if (isBatch) {
|
||||
if (!hosts.length) return res.fail({ msg: 'hosts为空' })
|
||||
let hostList = await readHostList()
|
||||
let newHostList = []
|
||||
let hostList = await hostListDB.findAsync({})
|
||||
for (let oldRecord of hostList) {
|
||||
let record = hosts.find(item => item.id === oldRecord._id)
|
||||
if (!record) {
|
||||
newHostList.push(oldRecord)
|
||||
continue
|
||||
}
|
||||
let { authType } = record
|
||||
let target = hosts.find(item => item.id === oldRecord._id)
|
||||
if (!target) continue
|
||||
let { authType } = target
|
||||
// 如果存在原认证方式则保存下来
|
||||
if (!record[authType] && oldRecord[authType]) {
|
||||
record[authType] = oldRecord[authType]
|
||||
if (!target[authType]) {
|
||||
target[authType] = oldRecord[authType]
|
||||
} else {
|
||||
const clearTempKey = await RSADecryptSync(record.tempKey)
|
||||
const clearTempKey = await RSADecryptAsync(target.tempKey)
|
||||
// console.log('批量解密tempKey:', clearTempKey)
|
||||
const clearSSHKey = await AESDecryptSync(record[authType], clearTempKey)
|
||||
const clearSSHKey = await AESDecryptAsync(target[authType], clearTempKey)
|
||||
// console.log(`${ authType }原密文: `, clearSSHKey)
|
||||
record[authType] = await AESEncryptSync(clearSSHKey)
|
||||
// console.log(`${ authType }__commonKey加密存储: `, record[authType])
|
||||
target[authType] = await AESEncryptAsync(clearSSHKey)
|
||||
// console.log(`${ authType }__commonKey加密存储: `, target[authType])
|
||||
}
|
||||
delete oldRecord.monitorData
|
||||
delete record.monitorData
|
||||
newHostList.push(Object.assign(oldRecord, record))
|
||||
delete target._id
|
||||
delete target.monitorData
|
||||
delete target.tempKey
|
||||
Object.assign(oldRecord, target)
|
||||
await hostListDB.updateAsync({ _id: oldRecord._id }, oldRecord)
|
||||
}
|
||||
await writeHostList(newHostList)
|
||||
return res.success({ msg: '批量修改成功' })
|
||||
}
|
||||
if (!newHost || !newName || !oldHost) return res.fail({ msg: '参数错误' })
|
||||
|
||||
let hostList = await readHostList()
|
||||
if (!hostList.some(({ host }) => host === oldHost)) return res.fail({ msg: `原实例[${ oldHost }]不存在,请尝试添加实例` })
|
||||
|
||||
let record = {
|
||||
let updateRecord = {
|
||||
name: newName, host: newHost, index, expired, expiredNotify, group, consoleUrl, remark,
|
||||
port, clientPort, username, authType, password, privateKey, credential, command
|
||||
}
|
||||
|
||||
let idx = hostList.findIndex(({ _id }) => _id === id)
|
||||
const oldRecord = hostList[idx]
|
||||
let oldRecord = await hostListDB.findOneAsync({ _id: id })
|
||||
// 如果存在原认证方式则保存下来
|
||||
if (!record[authType] && oldRecord[authType]) {
|
||||
record[authType] = oldRecord[authType]
|
||||
if (!updateRecord[authType] && oldRecord[authType]) {
|
||||
updateRecord[authType] = oldRecord[authType]
|
||||
} else {
|
||||
const clearTempKey = await RSADecryptSync(tempKey)
|
||||
const clearTempKey = await RSADecryptAsync(tempKey)
|
||||
// console.log('clearTempKey:', clearTempKey)
|
||||
const clearSSHKey = await AESDecryptSync(record[authType], clearTempKey)
|
||||
const clearSSHKey = await AESDecryptAsync(updateRecord[authType], clearTempKey)
|
||||
// console.log(`${ authType }原密文: `, clearSSHKey)
|
||||
record[authType] = await AESEncryptSync(clearSSHKey)
|
||||
// console.log(`${ authType }__commonKey加密存储: `, record[authType])
|
||||
updateRecord[authType] = await AESEncryptAsync(clearSSHKey)
|
||||
// console.log(`${ authType }__commonKey加密存储: `, updateRecord[authType])
|
||||
}
|
||||
hostList.splice(idx, 1, record)
|
||||
await writeHostList(hostList)
|
||||
res.success()
|
||||
await hostListDB.updateAsync({ _id: oldRecord._id }, updateRecord)
|
||||
res.success({ msg: '修改成功' })
|
||||
}
|
||||
|
||||
async function removeHost({
|
||||
res, request
|
||||
}) {
|
||||
async function removeHost({ res, request }) {
|
||||
let { body: { ids } } = request
|
||||
let hostList = await readHostList()
|
||||
if (!Array.isArray(ids)) return res.fail({ msg: '参数错误' })
|
||||
hostList = hostList.filter(({ _id }) => !ids.includes(_id))
|
||||
await writeHostList(hostList)
|
||||
res.success({ data: '已移除' })
|
||||
const numRemoved = await hostListDB.removeAsync({ _id: { $in: ids } }, { multi: true })
|
||||
// console.log('numRemoved: ', numRemoved)
|
||||
res.success({ data: `已移除,数量: ${ numRemoved }` })
|
||||
}
|
||||
|
||||
async function importHost({
|
||||
res, request
|
||||
}) {
|
||||
async function importHost({ res, request }) {
|
||||
let { body: { importHost, isEasyNodeJson = false } } = request
|
||||
if (!Array.isArray(importHost)) return res.fail({ msg: '参数错误' })
|
||||
let hostList = await readHostList()
|
||||
let hostList = await hostListDB.findAsync({})
|
||||
// 考虑到批量导入可能会重复太多,先过滤已存在的host:port
|
||||
let hostListSet = new Set(hostList.map(({ host, port }) => `${ host }:${ port }`))
|
||||
let newHostList = importHost.filter(({ host, port }) => !hostListSet.has(`${ host }:${ port }`))
|
||||
@ -157,8 +141,7 @@ async function importHost({
|
||||
return Object.assign(item, { ...extraFiels })
|
||||
})
|
||||
}
|
||||
hostList.push(...newHostList)
|
||||
await writeHostList(hostList)
|
||||
await hostListDB.insertAsync(newHostList)
|
||||
res.success({ data: { len: newHostList.length } })
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
const { readSSHRecord, writeSSHRecord, readHostList, writeHostList } = require('../utils/storage')
|
||||
const { RSADecryptSync, AESEncryptSync, AESDecryptSync } = require('../utils/encrypt')
|
||||
const { readSSHRecord, writeSSHRecord } = require('../utils/storage')
|
||||
const { RSADecryptAsync, AESEncryptAsync, AESDecryptAsync } = require('../utils/encrypt')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
async function getSSHList({ res }) {
|
||||
// console.log('get-host-list')
|
||||
@ -19,11 +21,11 @@ const addSSH = async ({ res, request }) => {
|
||||
let sshRecord = await readSSHRecord()
|
||||
if (sshRecord.some(item => item.name === name)) return res.fail({ data: false, msg: '已存在同名凭证' })
|
||||
|
||||
const clearTempKey = await RSADecryptSync(tempKey)
|
||||
const clearTempKey = await RSADecryptAsync(tempKey)
|
||||
console.log('clearTempKey:', clearTempKey)
|
||||
const clearSSHKey = await AESDecryptSync(record[authType], clearTempKey)
|
||||
const clearSSHKey = await AESDecryptAsync(record[authType], clearTempKey)
|
||||
// console.log(`${ authType }原密文: `, clearSSHKey)
|
||||
record[authType] = await AESEncryptSync(clearSSHKey)
|
||||
record[authType] = await AESEncryptAsync(clearSSHKey)
|
||||
// console.log(`${ authType }__commonKey加密存储: `, record[authType])
|
||||
|
||||
sshRecord.push({ ...record, date: Date.now() })
|
||||
@ -46,11 +48,11 @@ const updateSSH = async ({ res, request }) => {
|
||||
if (!record[authType] && oldRecord[authType]) {
|
||||
record[authType] = oldRecord[authType]
|
||||
} else {
|
||||
const clearTempKey = await RSADecryptSync(tempKey)
|
||||
const clearTempKey = await RSADecryptAsync(tempKey)
|
||||
console.log('clearTempKey:', clearTempKey)
|
||||
const clearSSHKey = await AESDecryptSync(record[authType], clearTempKey)
|
||||
const clearSSHKey = await AESDecryptAsync(record[authType], clearTempKey)
|
||||
// console.log(`${ authType }原密文: `, clearSSHKey)
|
||||
record[authType] = await AESEncryptSync(clearSSHKey)
|
||||
record[authType] = await AESEncryptAsync(clearSSHKey)
|
||||
// console.log(`${ authType }__commonKey加密存储: `, record[authType])
|
||||
}
|
||||
record._id = sshRecord[idx]._id
|
||||
@ -67,12 +69,15 @@ const removeSSH = async ({ res, request }) => {
|
||||
if (idx === -1) return res.fail({ msg: '凭证不存在' })
|
||||
sshRecord.splice(idx, 1)
|
||||
// 将删除的凭证id从host中删除
|
||||
let hostList = await readHostList()
|
||||
hostList = hostList.map(item => {
|
||||
if (item.credential === id) item.credential = ''
|
||||
return item
|
||||
})
|
||||
await writeHostList(hostList)
|
||||
let hostList = await hostListDB.findAsync({})
|
||||
if (Array.isArray(hostList) && hostList.length > 0) {
|
||||
for (let item of hostList) {
|
||||
if (item.credential === id) {
|
||||
item.credential = ''
|
||||
await hostListDB.updateAsync({ _id: item._id }, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
consola.info('移除凭证:', id)
|
||||
await writeSSHRecord(sshRecord)
|
||||
res.success({ data: '移除成功' })
|
||||
@ -81,7 +86,7 @@ const removeSSH = async ({ res, request }) => {
|
||||
const getCommand = async ({ res, request }) => {
|
||||
let { hostId } = request.query
|
||||
if (!hostId) return res.fail({ data: false, msg: '参数错误' })
|
||||
let hostInfo = await readHostList()
|
||||
let hostInfo = await hostListDB.findAsync({})
|
||||
let record = hostInfo?.find(item => item._id === hostId)
|
||||
consola.info('查询登录后执行的指令:', hostId)
|
||||
if (!record) return res.fail({ data: false, msg: 'host not found' }) // host不存在
|
||||
|
@ -2,7 +2,7 @@ const jwt = require('jsonwebtoken')
|
||||
const axios = require('axios')
|
||||
const { asyncSendNotice } = require('../utils/notify')
|
||||
const { readKey, writeKey, writeLog } = require('../utils/storage')
|
||||
const { RSADecryptSync, AESEncryptSync, SHA1Encrypt } = require('../utils/encrypt')
|
||||
const { RSADecryptAsync, AESEncryptAsync, SHA1Encrypt } = require('../utils/encrypt')
|
||||
const { getNetIPInfo } = require('../utils/tools')
|
||||
|
||||
const getpublicKey = async ({ res }) => {
|
||||
@ -52,7 +52,7 @@ const login = async ({ res, request }) => {
|
||||
// 登录流程
|
||||
try {
|
||||
// console.log('ciphertext', ciphertext)
|
||||
let loginPwd = await RSADecryptSync(ciphertext)
|
||||
let loginPwd = await RSADecryptAsync(ciphertext)
|
||||
// console.log('Decrypt解密password:', loginPwd)
|
||||
let { user, pwd } = await readKey()
|
||||
if (loginName === user && loginPwd === 'admin' && pwd === 'admin') {
|
||||
@ -76,7 +76,7 @@ const beforeLoginHandler = async (clientIp, jwtExpires) => {
|
||||
// 生产token
|
||||
let { commonKey } = await readKey()
|
||||
let token = jwt.sign({ date: Date.now() }, commonKey, { expiresIn: jwtExpires }) // 生成token
|
||||
token = await AESEncryptSync(token) // 对称加密token后再传输给前端
|
||||
token = await AESEncryptAsync(token) // 对称加密token后再传输给前端
|
||||
|
||||
// 记录客户端登录IP(用于判断是否异地且只保留最近10条)
|
||||
const clientIPInfo = await getNetIPInfo(clientIp)
|
||||
@ -92,13 +92,13 @@ const beforeLoginHandler = async (clientIp, jwtExpires) => {
|
||||
|
||||
const updatePwd = async ({ res, request }) => {
|
||||
let { body: { oldLoginName, oldPwd, newLoginName, newPwd } } = request
|
||||
let rsaOldPwd = await RSADecryptSync(oldPwd)
|
||||
let rsaOldPwd = await RSADecryptAsync(oldPwd)
|
||||
oldPwd = rsaOldPwd === 'admin' ? 'admin' : SHA1Encrypt(rsaOldPwd)
|
||||
let keyObj = await readKey()
|
||||
let { user, pwd } = keyObj
|
||||
if (oldLoginName !== user || oldPwd !== pwd) return res.fail({ data: false, msg: '原用户名或密码校验失败' })
|
||||
// 旧密钥校验通过,加密保存新密码
|
||||
newPwd = await RSADecryptSync(newPwd) === 'admin' ? 'admin' : SHA1Encrypt(await RSADecryptSync(newPwd))
|
||||
newPwd = await RSADecryptAsync(newPwd) === 'admin' ? 'admin' : SHA1Encrypt(await RSADecryptAsync(newPwd))
|
||||
keyObj.user = newLoginName
|
||||
keyObj.pwd = newPwd
|
||||
await writeKey(keyObj)
|
||||
|
@ -1,50 +0,0 @@
|
||||
db目录,初始化后自动生成
|
||||
|
||||
**host.db**
|
||||
|
||||
> 存储服务器基本信息
|
||||
|
||||
**key.db**
|
||||
|
||||
> 用于加密的密钥相关
|
||||
|
||||
**credentials.db**
|
||||
|
||||
> ssh密钥记录(加密存储)
|
||||
|
||||
**email.db**
|
||||
|
||||
> 邮件配置
|
||||
|
||||
- port: 587 --> secure: false
|
||||
```db
|
||||
// Gmail调试不通过, 暂缓
|
||||
{
|
||||
"name": "Google邮箱",
|
||||
"target": "google",
|
||||
"host": "smtp.gmail.com",
|
||||
"port": 465,
|
||||
"secure": true,
|
||||
"tls": {
|
||||
"rejectUnauthorized": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**notify.db**
|
||||
|
||||
> 通知配置
|
||||
|
||||
**group.db**
|
||||
|
||||
> 服务器分组配置
|
||||
|
||||
|
||||
**scripts.db**
|
||||
|
||||
> 脚本库
|
||||
|
||||
|
||||
**onekey.db**
|
||||
|
||||
> 批量指令记录
|
@ -1,7 +1,7 @@
|
||||
const NodeRSA = require('node-rsa')
|
||||
const { readKey, writeKey } = require('./utils/storage')
|
||||
const { randomStr } = require('./utils/tools')
|
||||
const { AESEncryptSync } = require('./utils/encrypt')
|
||||
const { AESEncryptAsync } = require('./utils/encrypt')
|
||||
|
||||
// 初始化公私钥, 供登录、保存ssh密钥/密码等加解密
|
||||
async function initRsa() {
|
||||
@ -11,7 +11,7 @@ async function initRsa() {
|
||||
key.setOptions({ encryptionScheme: 'pkcs1', environment: 'browser' })
|
||||
let privateKey = key.exportKey('pkcs1-private-pem')
|
||||
let publicKey = key.exportKey('pkcs8-public-pem')
|
||||
keyObj.privateKey = await AESEncryptSync(privateKey) // 加密私钥
|
||||
keyObj.privateKey = await AESEncryptAsync(privateKey) // 加密私钥
|
||||
keyObj.publicKey = publicKey // 公开公钥
|
||||
await writeKey(keyObj)
|
||||
consola.info('Task: 已生成新的非对称加密公私钥')
|
||||
|
@ -1,11 +1,12 @@
|
||||
const schedule = require('node-schedule')
|
||||
const { asyncSendNotice } = require('../utils/notify')
|
||||
const { readHostList } = require('../utils/storage')
|
||||
const { formatTimestamp } = require('../utils/tools')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
const expiredNotifyJob = async () => {
|
||||
consola.info('=====开始检测服务器到期时间=====', new Date())
|
||||
const hostList = await readHostList()
|
||||
const hostList = await hostListDB.findAsync({})
|
||||
for (const item of hostList) {
|
||||
if (!item.expiredNotify) continue
|
||||
const { host, name, expired, consoleUrl } = item
|
||||
|
@ -1,15 +1,16 @@
|
||||
const { Server: ServerIO } = require('socket.io')
|
||||
const { io: ClientIO } = require('socket.io-client')
|
||||
const { readHostList } = require('../utils/storage')
|
||||
const { defaultClientPort } = require('../config')
|
||||
const { verifyAuthSync } = require('../utils/verify-auth')
|
||||
const { isAllowedIp } = require('../utils/tools')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
let clientSockets = []
|
||||
let clientsData = {}
|
||||
|
||||
async function getClientsInfo(clientSockets) {
|
||||
let hostList = await readHostList()
|
||||
let hostList = await hostListDB.findAsync({})
|
||||
clientSockets.forEach((clientItem) => {
|
||||
// 被删除的客户端断开连接
|
||||
if (!hostList.some(item => item.host === clientItem.host)) clientItem.close && clientItem.close()
|
||||
|
@ -1,11 +1,13 @@
|
||||
const { Server } = require('socket.io')
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
const { asyncSendNotice } = require('../utils/notify')
|
||||
const { readSSHRecord, readHostList, writeOneKeyRecord } = require('../utils/storage')
|
||||
const { readSSHRecord, writeOneKeyRecord } = require('../utils/storage')
|
||||
const { verifyAuthSync } = require('../utils/verify-auth')
|
||||
const { shellThrottle } = require('../utils/tools')
|
||||
const { AESDecryptSync } = require('../utils/encrypt')
|
||||
const { AESDecryptAsync } = require('../utils/encrypt')
|
||||
const { isAllowedIp } = require('../utils/tools')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
const execStatusEnum = {
|
||||
connecting: '连接中',
|
||||
@ -129,7 +131,7 @@ module.exports = (httpServer) => {
|
||||
console.log('hostIds:', hostIds)
|
||||
// console.log('token:', token)
|
||||
console.log('command:', command)
|
||||
const hostList = await readHostList()
|
||||
const hostList = await hostListDB.findAsync({})
|
||||
const targetHostsInfo = hostList.filter(item => hostIds.some(id => item._id === id)) || {}
|
||||
// console.log('targetHostsInfo:', targetHostsInfo)
|
||||
if (!targetHostsInfo.length) return socket.emit('create_fail', `未找到【${ hostIds }】服务器信息`)
|
||||
@ -145,13 +147,13 @@ module.exports = (httpServer) => {
|
||||
execResult.push(curRes)
|
||||
try {
|
||||
if (authType === 'credential') {
|
||||
let credentialId = await AESDecryptSync(hostInfo['credential'])
|
||||
let credentialId = await AESDecryptAsync(hostInfo['credential'])
|
||||
const sshRecordList = await readSSHRecord()
|
||||
const sshRecord = sshRecordList.find(item => item._id === credentialId)
|
||||
authInfo.authType = sshRecord.authType
|
||||
authInfo[authInfo.authType] = await AESDecryptSync(sshRecord[authInfo.authType])
|
||||
authInfo[authInfo.authType] = await AESDecryptAsync(sshRecord[authInfo.authType])
|
||||
} else {
|
||||
authInfo[authType] = await AESDecryptSync(hostInfo[authType])
|
||||
authInfo[authType] = await AESDecryptAsync(hostInfo[authType])
|
||||
}
|
||||
consola.info('准备连接终端执行一次性指令:', host)
|
||||
consola.log('连接信息', { username, port, authType })
|
||||
|
@ -5,9 +5,11 @@ const CryptoJS = require('crypto-js')
|
||||
const { Server } = require('socket.io')
|
||||
const { sftpCacheDir } = require('../config')
|
||||
const { verifyAuthSync } = require('../utils/verify-auth')
|
||||
const { AESDecryptSync } = require('../utils/encrypt')
|
||||
const { readSSHRecord, readHostList } = require('../utils/storage')
|
||||
const { AESDecryptAsync } = require('../utils/encrypt')
|
||||
const { readSSHRecord } = require('../utils/storage')
|
||||
const { isAllowedIp } = require('../utils/tools')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
// 读取切片
|
||||
const pipeStream = (path, writeStream) => {
|
||||
@ -230,7 +232,7 @@ module.exports = (httpServer) => {
|
||||
return
|
||||
}
|
||||
|
||||
const hostList = await readHostList()
|
||||
const hostList = await hostListDB.findAsync({})
|
||||
const targetHostInfo = hostList.find(item => item.host === ip) || {}
|
||||
let { authType, host, port, username } = targetHostInfo
|
||||
if (!host) return socket.emit('create_fail', `查找【${ ip }】凭证信息失败`)
|
||||
@ -238,16 +240,16 @@ module.exports = (httpServer) => {
|
||||
|
||||
// 解密放到try里面,防止报错【commonKey必须配对, 否则需要重新添加服务器密钥】
|
||||
if (authType === 'credential') {
|
||||
let credentialId = await AESDecryptSync(targetHostInfo[authType])
|
||||
let credentialId = await AESDecryptAsync(targetHostInfo[authType])
|
||||
const sshRecordList = await readSSHRecord()
|
||||
const sshRecord = sshRecordList.find(item => item._id === credentialId)
|
||||
authInfo.authType = sshRecord.authType
|
||||
authInfo[authInfo.authType] = await AESDecryptSync(sshRecord[authInfo.authType])
|
||||
authInfo[authInfo.authType] = await AESDecryptAsync(sshRecord[authInfo.authType])
|
||||
} else {
|
||||
authInfo[authType] = await AESDecryptSync(targetHostInfo[authType])
|
||||
authInfo[authType] = await AESDecryptAsync(targetHostInfo[authType])
|
||||
}
|
||||
consola.info('准备连接Sftp面板:', host)
|
||||
targetHostInfo[targetHostInfo.authType] = await AESDecryptSync(targetHostInfo[targetHostInfo.authType])
|
||||
targetHostInfo[targetHostInfo.authType] = await AESDecryptAsync(targetHostInfo[targetHostInfo.authType])
|
||||
|
||||
consola.log('连接信息', { username, port, authType })
|
||||
sftpClient
|
||||
|
@ -1,10 +1,12 @@
|
||||
const { Server } = require('socket.io')
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
const { verifyAuthSync } = require('../utils/verify-auth')
|
||||
const { AESDecryptSync } = require('../utils/encrypt')
|
||||
const { readSSHRecord, readHostList } = require('../utils/storage')
|
||||
const { AESDecryptAsync } = require('../utils/encrypt')
|
||||
const { readSSHRecord } = require('../utils/storage')
|
||||
const { asyncSendNotice } = require('../utils/notify')
|
||||
const { isAllowedIp, ping } = require('../utils/tools')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
function createInteractiveShell(socket, sshClient) {
|
||||
return new Promise((resolve) => {
|
||||
@ -51,7 +53,7 @@ function createInteractiveShell(socket, sshClient) {
|
||||
async function createTerminal(hostId, socket, sshClient) {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve) => {
|
||||
const hostList = await readHostList()
|
||||
const hostList = await hostListDB.findAsync({})
|
||||
const targetHostInfo = hostList.find(item => item._id === hostId) || {}
|
||||
let { authType, host, port, username, name } = targetHostInfo
|
||||
if (!host) return socket.emit('create_fail', `查找hostId【${ hostId }】凭证信息失败`)
|
||||
@ -60,16 +62,16 @@ async function createTerminal(hostId, socket, sshClient) {
|
||||
try {
|
||||
// 解密放到try里面,防止报错【commonKey必须配对, 否则需要重新添加服务器密钥】
|
||||
if (authType === 'credential') {
|
||||
let credentialId = await AESDecryptSync(targetHostInfo[authType])
|
||||
let credentialId = await AESDecryptAsync(targetHostInfo[authType])
|
||||
const sshRecordList = await readSSHRecord()
|
||||
const sshRecord = sshRecordList.find(item => item._id === credentialId)
|
||||
authInfo.authType = sshRecord.authType
|
||||
authInfo[authInfo.authType] = await AESDecryptSync(sshRecord[authInfo.authType])
|
||||
authInfo[authInfo.authType] = await AESDecryptAsync(sshRecord[authInfo.authType])
|
||||
} else {
|
||||
authInfo[authType] = await AESDecryptSync(targetHostInfo[authType])
|
||||
authInfo[authType] = await AESDecryptAsync(targetHostInfo[authType])
|
||||
}
|
||||
consola.info('准备连接终端:', host)
|
||||
// targetHostInfo[targetHostInfo.authType] = await AESDecryptSync(targetHostInfo[targetHostInfo.authType])
|
||||
// targetHostInfo[targetHostInfo.authType] = await AESDecryptAsync(targetHostInfo[targetHostInfo.authType])
|
||||
consola.log('连接信息', { username, port, authType })
|
||||
sshClient
|
||||
.on('ready', async() => {
|
||||
|
@ -15,6 +15,7 @@ module.exports.KeyDB = class KeyDB {
|
||||
constructor() {
|
||||
if (!KeyDB.instance) {
|
||||
KeyDB.instance = new Datastore({ filename: keyDBPath, autoload: true })
|
||||
KeyDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -26,6 +27,7 @@ module.exports.HostListDB = class HostListDB {
|
||||
constructor() {
|
||||
if (!HostListDB.instance) {
|
||||
HostListDB.instance = new Datastore({ filename: hostListDBPath, autoload: true })
|
||||
HostListDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -37,6 +39,7 @@ module.exports.SshRecordDB = class SshRecordDB {
|
||||
constructor() {
|
||||
if (!SshRecordDB.instance) {
|
||||
SshRecordDB.instance = new Datastore({ filename: credentialsDBPath, autoload: true })
|
||||
SshRecordDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -48,6 +51,8 @@ module.exports.NotifyDB = class NotifyDB {
|
||||
constructor() {
|
||||
if (!NotifyDB.instance) {
|
||||
NotifyDB.instance = new Datastore({ filename: notifyDBPath, autoload: true })
|
||||
NotifyDB.instance.setAutocompactionInterval(5000)
|
||||
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -59,6 +64,7 @@ module.exports.NotifyConfigDB = class NotifyConfigDB {
|
||||
constructor() {
|
||||
if (!NotifyConfigDB.instance) {
|
||||
NotifyConfigDB.instance = new Datastore({ filename: notifyConfigDBPath, autoload: true })
|
||||
NotifyConfigDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -70,6 +76,7 @@ module.exports.GroupDB = class GroupDB {
|
||||
constructor() {
|
||||
if (!GroupDB.instance) {
|
||||
GroupDB.instance = new Datastore({ filename: groupConfDBPath, autoload: true })
|
||||
GroupDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -81,6 +88,7 @@ module.exports.ScriptsDB = class ScriptsDB {
|
||||
constructor() {
|
||||
if (!ScriptsDB.instance) {
|
||||
ScriptsDB.instance = new Datastore({ filename: scriptsDBPath, autoload: true })
|
||||
ScriptsDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -92,6 +100,7 @@ module.exports.OnekeyDB = class OnekeyDB {
|
||||
constructor() {
|
||||
if (!OnekeyDB.instance) {
|
||||
OnekeyDB.instance = new Datastore({ filename: onekeyDBPath, autoload: true })
|
||||
OnekeyDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -103,6 +112,7 @@ module.exports.LogDB = class LogDB {
|
||||
constructor() {
|
||||
if (!LogDB.instance) {
|
||||
LogDB.instance = new Datastore({ filename: logDBPath, autoload: true })
|
||||
LogDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
|
@ -4,10 +4,10 @@ const NodeRSA = require('node-rsa')
|
||||
const { readKey } = require('./storage.js')
|
||||
|
||||
// rsa非对称 私钥解密
|
||||
const RSADecryptSync = async (ciphertext) => {
|
||||
const RSADecryptAsync = async (ciphertext) => {
|
||||
if (!ciphertext) return
|
||||
let { privateKey } = await readKey()
|
||||
privateKey = await AESDecryptSync(privateKey) // 先解密私钥
|
||||
privateKey = await AESDecryptAsync(privateKey) // 先解密私钥
|
||||
const rsakey = new NodeRSA(privateKey)
|
||||
rsakey.setOptions({ encryptionScheme: 'pkcs1', environment: 'browser' }) // Must Set It When Frontend Use jsencrypt
|
||||
const plaintext = rsakey.decrypt(ciphertext, 'utf8')
|
||||
@ -15,7 +15,7 @@ const RSADecryptSync = async (ciphertext) => {
|
||||
}
|
||||
|
||||
// aes对称 加密(default commonKey)
|
||||
const AESEncryptSync = async (text, key) => {
|
||||
const AESEncryptAsync = async (text, key) => {
|
||||
if (!text) return
|
||||
let { commonKey } = await readKey()
|
||||
let ciphertext = CryptoJS.AES.encrypt(text, key || commonKey).toString()
|
||||
@ -23,7 +23,7 @@ const AESEncryptSync = async (text, key) => {
|
||||
}
|
||||
|
||||
// aes对称 解密(default commonKey)
|
||||
const AESDecryptSync = async (ciphertext, key) => {
|
||||
const AESDecryptAsync = async (ciphertext, key) => {
|
||||
if (!ciphertext) return
|
||||
let { commonKey } = await readKey()
|
||||
let bytes = CryptoJS.AES.decrypt(ciphertext, key || commonKey)
|
||||
@ -37,8 +37,8 @@ const SHA1Encrypt = (clearText) => {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
RSADecryptSync,
|
||||
AESEncryptSync,
|
||||
AESDecryptSync,
|
||||
RSADecryptAsync,
|
||||
AESEncryptAsync,
|
||||
AESDecryptAsync,
|
||||
SHA1Encrypt
|
||||
}
|
@ -64,43 +64,43 @@ const writeSSHRecord = async (record = []) => {
|
||||
})
|
||||
}
|
||||
|
||||
const readHostList = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
hostListDB.find({}, (err, docs) => {
|
||||
if (err) {
|
||||
consola.error('读取host-list-db错误:', err)
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(docs)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// const readHostList = async () => {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// const hostListDB = new HostListDB().getInstance()
|
||||
// hostListDB.find({}, (err, docs) => {
|
||||
// if (err) {
|
||||
// consola.error('读取host-list-db错误:', err)
|
||||
// reject(err)
|
||||
// } else {
|
||||
// resolve(docs)
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
|
||||
const writeHostList = async (record = []) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
hostListDB.remove({}, { multi: true }, (err) => {
|
||||
if (err) {
|
||||
consola.error('清空HostList出错:', err)
|
||||
reject(err)
|
||||
} else {
|
||||
hostListDB.compactDatafile()
|
||||
// 插入新的数据列表
|
||||
hostListDB.insert(record, (err, newDocs) => {
|
||||
if (err) {
|
||||
consola.error('写入新的HostList出错:', err)
|
||||
reject(err)
|
||||
} else {
|
||||
hostListDB.compactDatafile()
|
||||
resolve(newDocs)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// const writeHostList = async (record = []) => {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// const hostListDB = new HostListDB().getInstance()
|
||||
// hostListDB.remove({}, { multi: true }, (err) => {
|
||||
// if (err) {
|
||||
// consola.error('清空HostList出错:', err)
|
||||
// reject(err)
|
||||
// } else {
|
||||
// hostListDB.compactDatafile()
|
||||
// // 插入新的数据列表
|
||||
// hostListDB.insert(record, (err, newDocs) => {
|
||||
// if (err) {
|
||||
// consola.error('写入新的HostList出错:', err)
|
||||
// reject(err)
|
||||
// } else {
|
||||
// hostListDB.compactDatafile()
|
||||
// resolve(newDocs)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
|
||||
const readNotifyConfig = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -329,7 +329,7 @@ const writeLog = async (records = {}) => {
|
||||
|
||||
module.exports = {
|
||||
readSSHRecord, writeSSHRecord,
|
||||
readHostList, writeHostList,
|
||||
// readHostList, writeHostList,
|
||||
readKey, writeKey,
|
||||
readNotifyList, writeNotifyList,
|
||||
readNotifyConfig, writeNotifyConfig, getNotifySwByType,
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
const { AESDecryptSync } = require('./encrypt')
|
||||
const { AESDecryptAsync } = require('./encrypt')
|
||||
const { readKey } = require('./storage')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
@ -13,7 +13,7 @@ const enumLoginCode = {
|
||||
const verifyAuthSync = async (token, clientIp) => {
|
||||
consola.info('verifyAuthSync IP:', clientIp)
|
||||
try {
|
||||
token = await AESDecryptSync(token) // 先aes解密
|
||||
token = await AESDecryptAsync(token) // 先aes解密
|
||||
const { commonKey } = await readKey()
|
||||
const { exp } = jwt.verify(token, commonKey)
|
||||
if (Date.now() > (exp * 1000)) return { code: -1, msg: 'token expires' } // 过期
|
||||
|
@ -356,7 +356,7 @@ const setDefaultData = () => {
|
||||
|
||||
const setBatchDefaultData = () => {
|
||||
if (!isBatchModify.value) return
|
||||
Object.assign(hostForm.value, { ...formField }, { group: '', port: '', username: '', authType: '' })
|
||||
Object.assign(hostForm.value, { ...formField }, { group: '', port: '', username: '', authType: '', clientPort: '' })
|
||||
}
|
||||
const handleOpen = async () => {
|
||||
setDefaultData()
|
||||
@ -416,7 +416,7 @@ const handleSave = () => {
|
||||
// eslint-disable-next-line
|
||||
let updateFileData = Object.fromEntries(Object.entries(formData).filter(([key, value]) => Boolean(value))) // 剔除掉未更改的值
|
||||
if (Object.keys(updateFileData).length === 0) return $message.warning('没有任何修改')
|
||||
// console.log(updateFileData)
|
||||
console.log(updateFileData)
|
||||
let newHosts = batchHosts.value
|
||||
.map(item => ({ ...item, ...updateFileData }))
|
||||
.map(item => {
|
||||
|
@ -168,7 +168,6 @@ let handleBatchOnekey = async () => {
|
||||
let handleBatchExport = () => {
|
||||
collectSelectHost()
|
||||
if (!selectHosts.value.length) return $message.warning('请选择要批量操作的实例')
|
||||
console.log(selectHosts.value)
|
||||
let exportData = JSON.parse(JSON.stringify(selectHosts.value))
|
||||
exportData = exportData.map(item => {
|
||||
delete item.monitorData
|
||||
|
Loading…
x
Reference in New Issue
Block a user