infracloud/scripts/sync-vault.js

151 lines
4.4 KiB
JavaScript

const AWS = require('aws-sdk');
const fs = require('fs');
const path = require('path');
const sshPath = process.env.USERPROFILE || process.env.HOME;
const vaultPath = path.join(sshPath, '.ssh');
const civo = new AWS.S3({
endpoint: 'https://objectstore.nyc1.civo.com',
accessKeyId: process.env.CIVO_ACCESS_KEY || '0UZ69TH03Q292DMTB82B',
secretAccessKey: process.env.CIVO_SECRET_KEY || 'JJ5XXZYvoWdnqBCNP5oREjACyrXeH6EgSqeSybT7',
s3ForcePathStyle: true,
signatureVersion: 'v4'
});
const euronodes = new AWS.S3({
endpoint: 'https://eu-west-1.euronodes.com',
accessKeyId: process.env.EURONODES_ACCESS_KEY || 'XZNFA56V35MUY605XOUL',
secretAccessKey: process.env.EURONODES_SECRET_KEY || 'FYATWkgSafaEMRQlFNdSQ6BoCSxG74MY9Cd7D8AF',
s3ForcePathStyle: true,
signatureVersion: 'v4'
});
async function listObjects(s3, bucket, prefix) {
return new Promise((resolve, reject) => {
s3.listObjectsV2({ Bucket: bucket, Prefix: prefix }, (err, data) => {
if (err) reject(err);
else resolve(data.Contents || []);
});
});
}
async function uploadFile(s3, bucket, key, body) {
return new Promise((resolve, reject) => {
s3.putObject({ Bucket: bucket, Key: key, Body: body }, (err, data) => {
if (err) reject(err);
else resolve(data);
});
});
}
async function downloadFile(s3, bucket, key) {
return new Promise((resolve, reject) => {
s3.getObject({ Bucket: bucket, Key: key }, (err, data) => {
if (err) reject(err);
else resolve(data.Body);
});
});
}
async function syncToCloud() {
console.log('=== Sincronizando ~/.ssh/ para Object Storages ===\n');
const files = fs.readdirSync(vaultPath).filter(f =>
!f.startsWith('known_hosts') &&
!f.endsWith('.pub') &&
f !== 'authorized_keys' &&
!fs.statSync(path.join(vaultPath, f)).isDirectory()
);
console.log(`Encontrados ${files.length} arquivos locais\n`);
for (const file of files) {
const filePath = path.join(vaultPath, file);
const key = `ssh/${file}`;
const body = fs.readFileSync(filePath);
try {
await uploadFile(civo, 'rede5', `vault/${key}`, body);
console.log(`[CIVO] ✅ ${key}`);
} catch (err) {
console.log(`[CIVO] ❌ ${key}: ${err.message}`);
}
try {
await uploadFile(euronodes, 'vault', key, body);
console.log(`[EURONODES] ✅ ${key}`);
} catch (err) {
console.log(`[EURONODES] ❌ ${key}: ${err.message}`);
}
}
}
async function syncFromCloud() {
console.log('=== Sincronizando Object Storages para ~/.ssh/ ===\n');
const civoFiles = await listObjects(civo, 'rede5', 'vault/ssh/');
console.log(`Civo: ${civoFiles.length} arquivos`);
for (const obj of civoFiles) {
const key = obj.Key.replace('vault/', '');
const filePath = path.join(vaultPath, path.basename(key));
try {
const body = await downloadFile(civo, 'rede5', obj.Key);
fs.writeFileSync(filePath, body);
console.log(`[DOWNLOAD] ✅ ${key}`);
} catch (err) {
console.log(`[DOWNLOAD] ❌ ${key}: ${err.message}`);
}
}
}
async function syncCivoToEuronodes() {
console.log('=== Sincronizando Civo -> Euronodes ===\n');
const civoFiles = await listObjects(civo, 'rede5', 'vault/ssh/');
console.log(`Encontrados ${civoFiles.length} arquivos no Civo\n`);
for (const obj of civoFiles) {
const key = obj.Key.replace('vault/', '');
try {
const body = await downloadFile(civo, 'rede5', obj.Key);
await uploadFile(euronodes, 'vault', key, body);
console.log(`[EURONODES] ✅ ${key}`);
} catch (err) {
console.log(`[EURONODES] ❌ ${key}: ${err.message}`);
}
}
}
async function listCloud() {
console.log('=== Listando arquivos nos Object Storages ===\n');
const civoFiles = await listObjects(civo, 'rede5', 'vault/ssh/');
console.log(`Civo (rede5/vault/ssh/): ${civoFiles.length} arquivos`);
civoFiles.forEach(f => console.log(` ${f.Key}`));
console.log('');
const euronodesFiles = await listObjects(euronodes, 'vault', 'ssh/');
console.log(`Euronodes (vault/ssh/): ${euronodesFiles.length} arquivos`);
euronodesFiles.forEach(f => console.log(` ${f.Key}`));
}
const action = process.argv[2] || 'list';
switch (action) {
case 'upload':
syncToCloud();
break;
case 'download':
syncFromCloud();
break;
case 'sync-civo':
syncCivoToEuronodes();
break;
case 'list':
default:
listCloud();
}