Sikuliaq IT Asset Manager (skqitam)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

287 lines
10 KiB

var path = require('path')
var fs = require('fs')
var ecstatic = require('ecstatic')
const express = require('express')
const app = express()
var tar = require('tar')
const archiver = require('archiver');
var skqlib = require('./skq_modules/skq-lib')
// GLOBAL CONFIG
process['CONFIG'] = JSON.parse(fs.readFileSync(path.join(__dirname, 'config','skqitam-server-config.json'), 'utf8'))
process['CONFIG']['GLOBAL']['RUN_DIR'] = __dirname
process['CONFIG']['LOCAL']= skqlib.it_am_init()
// console.log(JSON.stringify(process['CONFIG'], null, 2))
// Generate Client Archive
console.log ('INFO: Generating: ' + path.join(__dirname, 'download', 'skqitam-client.tgz'))
tar.c(
{
gzip: true,
file: path.join(__dirname, 'download', 'skqitam-client.tgz')
},
[path.join('skqitam-client')]
)
// .then(_ => { .. tarball has been created .. })
// https://www.npmjs.com/package/archiver
console.log ('INFO: Generating: ' + path.join(__dirname, 'download', 'skqitam-client.zip'))
const ziparch = fs.createWriteStream(path.join(__dirname, 'download', 'skqitam-client.zip'))
const archive = archiver('zip', {
zlib: { level: 9 } // Sets the compression level.
})
archive.on('warning', function(err) {
if (err.code === 'ENOENT') {
// log warning
} else {
// throw error
throw err;
}
})
archive.pipe(ziparch)
archive.directory('skqitam-client/', true);
archive.finalize()
// Windows 7 Installers
try {
fs.mkdirSync(path.join(__dirname, 'download', 'win7-x64-installer'), { recursive: true })
let skqitam_setup_win7_bat = 'PowerShell.exe -ExecutionPolicy Unrestricted -command "%homedrive%%homepath%\\Downloads\\skqitam-client-win7-installer\\skqitam-setup-win7.ps1 http://' + process['CONFIG']['LOCAL']['HOST']['NETWORK']['IP_ADDR']['IPv4'][0] + ':' + process['CONFIG']['GLOBAL']['WEBUI_PORT']
try {
fs.copyFileSync(path.join(__dirname, 'download', 'skqitam-setup-win7.ps1'), path.join(__dirname, 'download', 'win7-x64-installer', 'skqitam-setup-win7.ps1'))
try {
fs.writeFileSync(path.join(__dirname, 'download', 'win7-x64-installer', 'skqitam-setup-win7.bat'), skqitam_setup_win7_bat, 'utf8')
// fs.copyFileSync(path.join(__dirname, 'download', 'skqitam-setup-win7.bat'), path.join(__dirname, 'download', 'win7-x64-installer', 'skqitam-setup-win7.bat'))
console.log ('INFO: Generating: ' + path.join(__dirname, 'download', 'skqitam-client-win7-installer.zip') + "\n")
const w7x64_ziparch = fs.createWriteStream(path.join(__dirname, 'download', 'skqitam-client-win7-installer.zip'))
const w7x64_archive = archiver('zip', {
zlib: { level: 9 } // Sets the compression level.
})
w7x64_archive.on('warning', function(err) {
if (err.code === 'ENOENT') {
// log warning
} else {
// throw error
throw err;
}
})
w7x64_archive.pipe(w7x64_ziparch)
// w7x64_archive.directory(path.join('download', 'win7-x64-installer'), 'win7-x64-installer');
w7x64_archive.directory(path.join('download', 'win7-x64-installer'), false);
w7x64_archive.finalize()
} catch (e) {
console.log ('ERROR: Could not copy: '+ path.join(__dirname, 'download', 'skqitam-setup-win7.bat'))
process.exit(1)
}
} catch (e) {
console.log ('ERROR: Could not copy: '+ path.join(__dirname, 'download', 'skqitam-setup-win7.ps1'))
process.exit(1)
}
} catch (e) {
console.log ('ERROR: Could not make directory: '+ path.join(__dirname, 'download', 'win7-x64-installer'))
process.exit(1)
}
// BEGIN DEV TEST FUNCTIONS - Disable for security purpose before deploying
app.use('/api/config', function(req, res) {
res.writeHead(200, {'Content-Type': 'application/json'})
res.end(JSON.stringify(process['CONFIG'], null, 2))
})
// END DEV TEST FUNCTIONS - Disable for security purpose before deploying
// API
// Web Config
app.use('/api/webconfig', function(req, res) {
res.writeHead(200, {'Content-Type': 'application/json'})
res.end(JSON.stringify(process['CONFIG']['LOCAL']['WEB'], null, 2))
})
// ITAM Data Uploads
app.use('/api/upload', function(req, res) {
let status = true
let now = skqlib.tell_time()
// console.log (req)
// console.log(req.headers)
if (req.query['ITAM_DATA']) {
// console.log(req.query['ITAM_DATA'])
try {
itam_data = JSON.parse(req.query['ITAM_DATA'])
// console.log(JSON.stringify(itam_data, null, 2))
// Log Dir
let log_dir = path.join(process['CONFIG']['LOCAL']['ITAM']['ITAM_DATA_DIR'], 'logs')
try {
fs.mkdirSync(log_dir, { recursive: true })
let log = {}
log['SERVER_UTC_TIMESTAMP'] = now['UTC']['ISO8601']
log['EVENT'] = 'CLIENT UPLOAD'
log['CLIENT_UTC_TIMESTAMP'] = itam_data['ITAM']['TIMESTAMP']
log['ITAM_ID'] = itam_data['ITAM']['ID']
log['HOSTNAME'] = itam_data['ITAM']['HOSTNAME']
let log_file = path.join(process['CONFIG']['LOCAL']['ITAM']['ITAM_DATA_DIR'], 'logs', now['UTC']['YYYY-MM-DD'] + '_itam-server.log')
try {
fs.appendFileSync(log_file, JSON.stringify(log) + "\n", 'utf8')
console.log (JSON.stringify(log))
} catch (err) {
console.log ("ERROR: Cannot LOG event to " + log_file)
}
} catch (err) {
console.log ("ERROR: Cannot make log dir: " + log_dir)
console.log (err)
status = false
}
// Data Dir
let sprgx = RegExp(/\s+/g)
data_dir = path.join(process['CONFIG']['LOCAL']['ITAM']['ITAM_DATA_DIR'], 'hosts', String(itam_data['ITAM']['HOSTNAME']).replace(sprgx, '_') + '_' + itam_data['ITAM']['ID'], 'raw')
try {
fs.mkdirSync(data_dir, { recursive: true })
let raw_data_file = path.join(data_dir, now['UTC']['ISO8601'] + '_' + String(itam_data['ITAM']['HOSTNAME']).replace(sprgx, '_') + '_' + itam_data['ITAM']['ID'] + '.json')
try {
fs.writeFileSync(raw_data_file, JSON.stringify(itam_data, null, 2), 'utf8')
itam_parse_data(itam_data)
// Host Map
let host_id_map_file = path.join(process['CONFIG']['LOCAL']['ITAM']['ITAM_DATA_DIR'], 'host-id-map.json')
try {
let host_id_map = JSON.parse(fs.readFileSync(host_id_map_file, 'utf8'))
host_id_map[itam_data['ITAM']['HOSTNAME']] = itam_data['ITAM']['ID']
try {
fs.writeFileSync(host_id_map_file, JSON.stringify(host_id_map, null, 2), 'utf8')
} catch (err) {
console.log ("ERROR: Cannot Write Host ID Map File " + host_id_map_file)
status = false
process.exit(1)
}
// fs.writeFileSync(raw_data_file, JSON.stringify(itam_data, null, 2), 'utf8')
} catch (err) {
console.log ("ERROR: Cannot Read Host ID Map File " + host_id_map_file)
status = false
process.exit(1)
}
} catch (err) {
console.log ("ERROR: Cannot Write Data File " + raw_data_file)
status = false
process.exit(1)
}
} catch (err) {
console.log ("ERROR: Cannot make data dir: " + data_dir)
console.log (err)
status = false
}
} catch (err) {
console.log ("ERROR: Cannot PARSE Client JSON Upload")
console.log (err)
status = false
}
} else {
console.log ("ERROR: Missing client ITAM_DATA Upload")
status = false
}
// res.writeHead(200, {'Content-Type': 'application/javascript'})
res.status(200)
res.send(status)
})
// Data
app.use('/api/data', express.static(path.join(__dirname, 'itam-data'), { index: false }))
// Downloads
app.use('/download', express.static(path.join(__dirname, 'download'), { index: false }))
// app.use('/download', ecstatic({
// root: path.join(__dirname, 'download'),
// showdir: true,
// // baseDir: '/download'
// }));
app.use('/download/nodejs', express.static(path.join(__dirname, 'nodejs'), { index: false }))
// WebUI Admin
app.use('/admin', express.static(path.join(__dirname, process['CONFIG']['GLOBAL']['WEBUI_ADMIN']['WEB_ROOT_DIR'])))
// WebUI Root
app.use('/', express.static(path.join(__dirname, process['CONFIG']['GLOBAL']['WEBUI_ROOT']['WEB_ROOT_DIR'])))
// 404 Errors
app.use(function (req, res, next) {
res.status(404).send("404 Page not found: " + req.url )
var remote_ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
remote_ip = remote_ip.replace(/^\:\:ffff\:/, '') // IPv4 part only
console.log('ERR ' + res.statusCode + ' ' + req.method + ' ' + remote_ip + ' [' + req.headers['user-agent'] + '] ' + ' ' + req.url)
})
// Starting Express Web Service
app.listen(process['CONFIG']['GLOBAL']['WEBUI_PORT'], function () {
console.log ("Sikuliaq Cyber Asset Manager Server")
console.log (" - Version: v" + process['CONFIG']['LOCAL']['PACKAGE']['version'] + ' ' + process['CONFIG']['LOCAL']['PACKAGE']['version_date'])
console.log (" - Copyright (C) 2021 University of Alaska Fairbanks - College of Fisheries and Ocean Sciences - R/V Sikuliaq")
console.log (" - Author: John Haverlack (jehaverlack@alaska.edu)\n")
console.log ("Status: STARTED")
console.log (" Node.JS: v" + process['CONFIG']['LOCAL']['PROC']['VERSIONS']['node'])
for (i in process['CONFIG']['LOCAL']['HOST']['NETWORK']['IP_ADDR']['IPv4']) {
console.log (" WebUI: http://" + process['CONFIG']['LOCAL']['HOST']['NETWORK']['IP_ADDR']['IPv4'][i] + ':' + process['CONFIG']['GLOBAL']['WEBUI_PORT'])
}
for (i in process['CONFIG']['LOCAL']['HOST']['NETWORK']['IP_ADDR']['IPv6']) {
console.log (" WebUI: http://[" + process['CONFIG']['LOCAL']['HOST']['NETWORK']['IP_ADDR']['IPv6'][i] + ']:' + process['CONFIG']['GLOBAL']['WEBUI_PORT'])
}
console.log ("\nNOTE: Be sure to open port " + process['CONFIG']['GLOBAL']['WEBUI_PORT'] + " to the above IP's\n on server and network firewalls.")
})
// -------------------------------- Functions --------------------------
function itam_parse_data(data) {
console.log(JSON.stringify(data['ITAM'], null, 2))
let itam_index = {}
try {
let itam_index = JSON.parse(fs.readFileSync(path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_INDEX']), 'utf8'))
} catch (e) {
}
// Host Index Update
// Hardware Statistics
// OS Statistics
// Software Statistics
// Appendix-D Hardware
// Appendix-D Software
}