// Shared Atlas InfoSec API helpers // Centralizes HTTP calls so the atlas router uses a single implementation. // Follows the same promise-based pattern as ivantiApi.js. const https = require('https'); const http = require('http'); // --------------------------------------------------------------------------- // Configuration — read from process.env at module load // --------------------------------------------------------------------------- const ATLAS_API_URL = process.env.ATLAS_API_URL || ''; const ATLAS_API_USER = process.env.ATLAS_API_USER || ''; const ATLAS_API_PASS = process.env.ATLAS_API_PASS || ''; const ATLAS_SKIP_TLS = process.env.ATLAS_SKIP_TLS === 'true'; const requiredVars = ['ATLAS_API_URL', 'ATLAS_API_USER', 'ATLAS_API_PASS']; const missingVars = requiredVars.filter((v) => !process.env[v]); if (missingVars.length > 0) { console.warn(`[atlas-api] WARNING: Missing required environment variables: ${missingVars.join(', ')}. Atlas API calls will fail.`); } const isConfigured = missingVars.length === 0; // --------------------------------------------------------------------------- // Generic request — supports GET, PUT, PATCH, POST // --------------------------------------------------------------------------- function atlasRequest(method, urlPath, body, options) { const timeout = (options && options.timeout) || 15000; const authString = Buffer.from(ATLAS_API_USER + ':' + ATLAS_API_PASS).toString('base64'); const fullUrl = new URL(ATLAS_API_URL + urlPath); const isHttps = fullUrl.protocol === 'https:'; const transport = isHttps ? https : http; const headers = { 'accept': 'application/json', 'authorization': 'Basic ' + authString }; let bodyStr = null; if (body !== null && body !== undefined) { bodyStr = JSON.stringify(body); headers['content-type'] = 'application/json'; headers['content-length'] = Buffer.byteLength(bodyStr); } return new Promise((resolve, reject) => { const reqOptions = { hostname: fullUrl.hostname, port: fullUrl.port || (isHttps ? 443 : 80), path: fullUrl.pathname + fullUrl.search, method: method, headers: headers, timeout: timeout }; if (isHttps) { reqOptions.rejectUnauthorized = !ATLAS_SKIP_TLS; } const req = transport.request(reqOptions, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => resolve({ status: res.statusCode, body: data })); }); req.on('timeout', () => req.destroy(new Error(method + ' ' + urlPath + ' timed out'))); req.on('error', (err) => { reject(new Error(method + ' ' + urlPath + ' failed: ' + err.message)); }); if (bodyStr) { req.write(bodyStr); } req.end(); }); } // --------------------------------------------------------------------------- // Convenience wrappers // --------------------------------------------------------------------------- function atlasGet(urlPath, options) { return atlasRequest('GET', urlPath, null, options); } function atlasPut(urlPath, body, options) { return atlasRequest('PUT', urlPath, body, options); } function atlasPatch(urlPath, body, options) { return atlasRequest('PATCH', urlPath, body, options); } function atlasPost(urlPath, body, options) { return atlasRequest('POST', urlPath, body, options); } module.exports = { isConfigured, atlasRequest, atlasGet, atlasPut, atlasPatch, atlasPost };