feat(mikrotikBackupRoutes): add encryption and decryption for backup content to enhance security
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m42s

This commit is contained in:
2026-02-10 01:54:38 +07:00
parent 77ba6c1fa3
commit 0063e79a73
+31 -5
View File
@@ -16,9 +16,24 @@ const { sendError, sendOk } = require('../middleware/errorHandler');
const { writeS3TextObject, readS3TextObject, listS3Objects } = require('../services/s3Service');
const { readServersFromS3 } = require('./serversRoutes');
const { createRosClient, fetchExportViaFile } = require('../services/mikrotikApplyService');
const { decrypt } = require('../utils/encryption');
const { encrypt, decrypt } = require('../utils/encryption');
const BACKUP_PREFIX = 'backups/mikrotik';
const ENCRYPTED_PREFIX = 'ENC:';
/** Расшифровать содержимое бэкапа (поддерживает старые незашифрованные) */
function decryptBackupContent(raw) {
if (!raw || typeof raw !== 'string') return '';
if (raw.startsWith(ENCRYPTED_PREFIX)) {
try {
return decrypt(raw.slice(ENCRYPTED_PREFIX.length));
} catch (e) {
console.error('Backup decryption failed:', e?.message);
throw new Error(`Failed to decrypt backup: ${e?.message || 'decryption error'}`);
}
}
return raw;
}
function buildBackupKey(serverId, createdAt, suffix) {
const safeId = String(serverId || 'unknown').replace(/[^a-zA-Z0-9._-]/g, '_');
@@ -44,7 +59,17 @@ async function saveBackupForServer(serverId, config, { source, comment } = {}) {
'',
].filter(Boolean);
const content = `${headerLines.join('\n')}\n${String(config || '').replace(/^\uFEFF/, '')}`;
let content = `${headerLines.join('\n')}\n${String(config || '').replace(/^\uFEFF/, '')}`;
// Шифруем содержимое на S3, если задан ENCRYPTION_KEY
if (process.env.ENCRYPTION_KEY) {
try {
content = ENCRYPTED_PREFIX + encrypt(content);
} catch (e) {
console.error('Backup encryption failed:', e?.message);
throw new Error(`Failed to encrypt backup: ${e?.message || 'encryption error'}`);
}
}
const meta = await writeS3TextObject(key, content, 'text/plain');
return { key, createdAt: now.toISOString(), s3: meta };
@@ -132,11 +157,12 @@ async function getBackup(req, res) {
}
const data = await readS3TextObject(key);
const config = decryptBackupContent(data.body || '');
return res.json({
ok: true,
key,
config: data.body || '',
config,
etag: data.etag,
lastModified: data.lastModified,
contentLength: data.contentLength,
@@ -169,8 +195,8 @@ async function diffBackups(req, res) {
readS3TextObject(keyB),
]);
const bodyA = a.body || '';
const bodyB = b.body || '';
const bodyA = decryptBackupContent(a.body || '');
const bodyB = decryptBackupContent(b.body || '');
return res.json({
ok: true,