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 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 'list': default: listCloud(); }