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.
1153 lines
52 KiB
1153 lines
52 KiB
var path = require('path')
|
|
var fs = require('fs')
|
|
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))
|
|
console.log ("Sikuliaq Cyber Asset Manager - Data Analyzer")
|
|
console.log (" - Version: v" + process['CONFIG']['LOCAL']['PACKAGE']['version'] + ' ' + process['CONFIG']['LOCAL']['PACKAGE']['version_date'] + ' (Beta)')
|
|
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('Data Dir: ' + path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR']))
|
|
|
|
let hostdir_base = path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'hosts')
|
|
let hostdirs = fs.readdirSync(hostdir_base)
|
|
|
|
let index_keys = [
|
|
'DATA_TIMESTAMP',
|
|
'AM_ID',
|
|
'AM_HOSTNAME',
|
|
'INVENTORIED_BY',
|
|
'DESCRIPTION',
|
|
'LOCAL_HOSTNAME',
|
|
'SYSTEM_OWNER',
|
|
'IP_ADDR',
|
|
'OS',
|
|
'OS_VERSION',
|
|
'OS_ARCH',
|
|
'OS_INSTALL_DATE',
|
|
'KERNEL',
|
|
'KERNEL_VERSION',
|
|
'HW_MAKE',
|
|
'HW_MODEL',
|
|
'HW_SERIAL_NUMBER',
|
|
'HW_BIOS_VENDOR',
|
|
'HW_BIOS_VERSION',
|
|
'HW_BIOS_DATE',
|
|
'HW_CPU_MODEL',
|
|
'HW_CPU_CORES',
|
|
'HW_RAM_MB',
|
|
'HW_NETWORK'
|
|
]
|
|
|
|
let sw_index_keys = [
|
|
"NAME",
|
|
"VERSION",
|
|
"KERNEL",
|
|
"ARCH",
|
|
"INSTALL_DATE",
|
|
"ORIGIN"
|
|
]
|
|
|
|
// console.log(JSON.stringify(hostdirs, null, 2))
|
|
|
|
try {
|
|
fs.mkdirSync(path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'reports'), { recursive: true })
|
|
} catch (e) {
|
|
console.log('ERROR: Could not mkdir: ' + path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'reports'))
|
|
process.exit(1)
|
|
}
|
|
|
|
try {
|
|
fs.mkdirSync(path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'proc'), { recursive: true })
|
|
} catch (e) {
|
|
console.log('ERROR: Could not mkdir: ' + path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'proc'))
|
|
process.exit(1)
|
|
}
|
|
|
|
let index_data_file = path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'proc', 'index-data.json')
|
|
let index_data = {}
|
|
|
|
try {
|
|
index_data = JSON.parse(fs.readFileSync(index_data_file, 'utf8'))
|
|
} catch (e) {
|
|
// Do Nothing
|
|
}
|
|
|
|
let sw_index_data_file = path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'proc', 'sw-index-data.json')
|
|
let sw_index_data = {}
|
|
|
|
try {
|
|
sw_index_data = JSON.parse(fs.readFileSync(sw_index_data_file, 'utf8'))
|
|
} catch (e) {
|
|
// Do Nothing
|
|
}
|
|
|
|
|
|
for (hd in hostdirs) {
|
|
let data_files = fs.readdirSync(path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'hosts', hostdirs[hd], 'raw'))
|
|
|
|
// console.log(JSON.stringify(data_files, null, 2))
|
|
// console.log ("LATEST DATA: " + path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'hosts', hostdirs[hd], 'raw', data_files[(data_files.length - 1)]))
|
|
|
|
// Get Latest Data
|
|
let host_data = JSON.parse(fs.readFileSync(path.join(__dirname, process['CONFIG']['GLOBAL']['ITAM_DATA_DIR'], 'hosts', hostdirs[hd], 'raw', data_files[(data_files.length - 1)]), 'utf8'))
|
|
|
|
// console.log("DEUG: " + JSON.stringify(host_data['ITAM'], null, 2))
|
|
if (host_data['ITAM'].hasOwnProperty('SKQITAM_VERSION')) {
|
|
console.log("------------------- ASSET ID: " + host_data['ITAM']['ID'] + " -------------------")
|
|
console.log(" " + host_data['ITAM']['STARTTIME'] + ' on ' + host_data['ITAM']['HOSTNAME'] + ' by ITAM v' + host_data['ITAM']['SKQITAM_VERSION'] + "\n");
|
|
// console.log(JSON.stringify(host_data['ITAM'], null, 2))
|
|
|
|
if (!index_data.hasOwnProperty(host_data['ITAM']['ID'])) {
|
|
index_data[ host_data['ITAM']['ID'] ] = {}
|
|
}
|
|
|
|
// Initialize
|
|
for (ik in index_keys) {
|
|
if (!index_data[ host_data['ITAM']['ID'] ].hasOwnProperty(index_keys[ik])) {
|
|
index_data[ host_data['ITAM']['ID'] ][ index_keys[ik] ] = ''
|
|
}
|
|
}
|
|
|
|
for (ik in sw_index_keys) {
|
|
if (!index_data[ host_data['ITAM']['ID'] ].hasOwnProperty(sw_index_keys[ik])) {
|
|
index_data[ host_data['ITAM']['ID'] ][ sw_index_keys[ik] ] = ''
|
|
}
|
|
}
|
|
// console.log('DATA INIT: ' + JSON.stringify(index_data[ host_data['ITAM']['ID'] ], null, 2))
|
|
|
|
index_data[ host_data['ITAM']['ID'] ]['DATA_TIMESTAMP'] = host_data['ITAM']['STARTTIME'].replace(' (UTC)', '')
|
|
index_data[ host_data['ITAM']['ID'] ]['AM_ID'] = host_data['ITAM']['ID']
|
|
index_data[ host_data['ITAM']['ID'] ]['AM_HOSTNAME'] = host_data['ITAM']['HOSTNAME']
|
|
index_data[ host_data['ITAM']['ID'] ]['INVENTORIED_BY'] = "ITAM: " + host_data['ITAM']['SKQITAM_VERSION']
|
|
index_data[ host_data['ITAM']['ID'] ]['DESCRIPTION'] = ''
|
|
index_data[ host_data['ITAM']['ID'] ]['LOCAL_HOSTNAME'] = host_data['SOURCE']['NODEJS']['HOST']['HOSTNAME']
|
|
index_data[ host_data['ITAM']['ID'] ]['IP_ADDR'] = host_data['SOURCE']['NODEJS']['HOST']['IP_ADDR'][0]['address']
|
|
index_data[ host_data['ITAM']['ID'] ]['OS'] = host_data['SOURCE']['NODEJS']['OS']['DISTRO']
|
|
index_data[ host_data['ITAM']['ID'] ]['OS_VERSION'] = host_data['SOURCE']['NODEJS']['OS']['DISTRO_VERSION']
|
|
index_data[ host_data['ITAM']['ID'] ]['OS_ARCH'] = host_data['SOURCE']['NODEJS']['OS']['ARCH']
|
|
index_data[ host_data['ITAM']['ID'] ]['OS_INSTALL_DATE'] = host_data['SOURCE']['OS_INSTALL_ISO_DATE']
|
|
index_data[ host_data['ITAM']['ID'] ]['KERNEL'] = host_data['SOURCE']['NODEJS']['OS']['KERNEL']
|
|
index_data[ host_data['ITAM']['ID'] ]['KERNEL_VERSION'] = host_data['SOURCE']['NODEJS']['OS']['KERNEL_VERSION']
|
|
// index_data[ host_data['ITAM']['ID'] ]['HW_MAKE'] = ''
|
|
// index_data[ host_data['ITAM']['ID'] ]['HW_MODEL'] = ''
|
|
// index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = ''
|
|
// index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VENDOR'] = ''
|
|
// index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VERSION'] = ''
|
|
// index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_DATE'] = ''
|
|
|
|
|
|
if (host_data['SOURCE'].hasOwnProperty('DMIDECODE')) {
|
|
// console.log(JSON.stringify(host_data['SOURCE']['DMIDECODE'], null, 2));
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MAKE'] = host_data['SOURCE']['DMIDECODE']['baseboard-manufacturer']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MODEL'] = host_data['SOURCE']['DMIDECODE']['baseboard-product-name']
|
|
switch (host_data['SOURCE']['DMIDECODE']['baseboard-serial-number']) {
|
|
case 'None':
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = host_data['SOURCE']['DMIDECODE']['system-uuid']
|
|
break;
|
|
case 'Default string':
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = host_data['SOURCE']['DMIDECODE']['system-uuid']
|
|
break;
|
|
default:
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = host_data['SOURCE']['DMIDECODE']['baseboard-serial-number']
|
|
}
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VENDOR'] = host_data['SOURCE']['DMIDECODE']['bios-vendor']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VERSION'] = host_data['SOURCE']['DMIDECODE']['bios-version']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_DATE'] = host_data['SOURCE']['DMIDECODE']['bios-release-date']
|
|
}
|
|
|
|
if (host_data['SOURCE'].hasOwnProperty('FACTER')) {
|
|
if (!index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER']) {
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = host_data['SOURCE']['FACTER']['uniqueid']
|
|
}
|
|
|
|
if (host_data['SOURCE']['FACTER']['is_virtual'] == "true") {
|
|
switch (host_data['SOURCE']['FACTER']['virtual']) {
|
|
case 'vmware':
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MAKE'] = 'VMware'
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MODEL'] = 'ESXi v6.7.0'
|
|
break;
|
|
case 'virtualbox':
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MAKE'] = 'Oracle Corporation'
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MODEL'] = 'VirtualBox'
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (host_data['SOURCE'].hasOwnProperty('RASPBERRY_SERIALNUMBER')) {
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = host_data['SOURCE']['RASPBERRY_SERIALNUMBER']
|
|
}
|
|
|
|
if (host_data['SOURCE'].hasOwnProperty('RASPBERRY_PI_MODEL')) {
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MAKE'] = 'Raspberry Pi'
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MODEL'] = host_data['SOURCE']['RASPBERRY_PI_MODEL']
|
|
}
|
|
|
|
if (index_data[ host_data['ITAM']['ID'] ]['KERNEL'] == 'Linux') {
|
|
if (host_data['SOURCE'].hasOwnProperty('ETC_PASSWD')) {
|
|
if (host_data['SOURCE']['ETC_PASSWD'].hasOwnProperty('sqadmin')) {
|
|
index_data[ host_data['ITAM']['ID'] ]['SYSTEM_OWNER'] = 'SKQ IT'
|
|
} else if (host_data['SOURCE'].hasOwnProperty('HOME_DIRS')) {
|
|
index_data[ host_data['ITAM']['ID'] ]['SYSTEM_OWNER'] = JSON.stringify(host_data['SOURCE']['HOME_DIRS'])
|
|
}
|
|
}
|
|
}
|
|
|
|
if (host_data['SOURCE'].hasOwnProperty('SYSTEMINFO')) {
|
|
if (host_data['SOURCE']['SYSTEMINFO']['System Manufacturer'] == "VMware, Inc.") {
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MAKE'] = 'VMware'
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MODEL'] = 'ESXi v6.7.0'
|
|
} else {
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MAKE'] = host_data['SOURCE']['SYSTEMINFO']['System Manufacturer']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MODEL'] = host_data['SOURCE']['SYSTEMINFO']['System Model']
|
|
}
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = host_data['SOURCE']['SYSTEMINFO']['baseboard-serial-number']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VENDOR'] = host_data['SOURCE']['SYSTEMINFO']['BIOS Version']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VERSION'] = host_data['SOURCE']['SYSTEMINFO']['BIOS Version']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_DATE'] = host_data['SOURCE']['SYSTEMINFO']['BIOS Version']
|
|
index_data[ host_data['ITAM']['ID'] ]['SYSTEM_OWNER'] = host_data['SOURCE']['SYSTEMINFO']['Registered Owner']
|
|
}
|
|
|
|
if (host_data['SOURCE'].hasOwnProperty('WMIC_SERIALNUMBER')) {
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = host_data['SOURCE']['WMIC_SERIALNUMBER']
|
|
}
|
|
|
|
if (host_data['SOURCE'].hasOwnProperty('SYSTEM_PROFILER')) {
|
|
if (host_data['SOURCE']['SYSTEM_PROFILER']['SPHardwareDataType'].hasOwnProperty('Hardware')) {
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MAKE'] = 'Apple Inc.'
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MODEL'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPHardwareDataType']['Hardware']['Hardware Overview']['Model Identifier']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPHardwareDataType']['Hardware']['Hardware Overview']['Serial Number (system)']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VENDOR'] = 'Apple Inc.'
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VERSION'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPHardwareDataType']['Hardware']['Hardware Overview']['Boot ROM Version']
|
|
index_data[ host_data['ITAM']['ID'] ]['SYSTEM_OWNER'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPSoftwareDataType']['Software']['System Software Overview']['User Name']
|
|
} else if (host_data['SOURCE']['SYSTEM_PROFILER']['SPHardwareDataType'][0].hasOwnProperty('serial_number')) {
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MAKE'] = 'Apple Inc.'
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_MODEL'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPHardwareDataType'][0]['machine_model']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_SERIAL_NUMBER'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPHardwareDataType'][0]['serial_number']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VENDOR'] = 'Apple Inc.'
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_BIOS_VERSION'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPHardwareDataType'][0]['boot_rom_version']
|
|
index_data[ host_data['ITAM']['ID'] ]['SYSTEM_OWNER'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPSoftwareDataType'][0]['user_name']
|
|
}
|
|
}
|
|
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_CPU_MODEL'] = host_data['SOURCE']['NODEJS']['HW']['CPU']['MODEL']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_CPU_CORES'] = host_data['SOURCE']['NODEJS']['HW']['CPU']['CORES']
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_RAM_MB'] = host_data['SOURCE']['NODEJS']['HW']['RAM_MEMORY']['MB']
|
|
|
|
// console.log(JSON.stringify())
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_NETWORK'] = ''
|
|
for (nic in host_data['SOURCE']['NODEJS']['HW']['NETWORK']) {
|
|
for (addr in host_data['SOURCE']['NODEJS']['HW']['NETWORK'][nic]) {
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_NETWORK'] += "," + nic + '_' + host_data['SOURCE']['NODEJS']['HW']['NETWORK'][nic][addr]['family'] + '_' + host_data['SOURCE']['NODEJS']['HW']['NETWORK'][nic][addr]['mac'] + '_' + host_data['SOURCE']['NODEJS']['HW']['NETWORK'][nic][addr]['family'] + '_' + host_data['SOURCE']['NODEJS']['HW']['NETWORK'][nic][addr]['cidr']
|
|
}
|
|
}
|
|
index_data[ host_data['ITAM']['ID'] ]['HW_NETWORK'] = index_data[ host_data['ITAM']['ID'] ]['HW_NETWORK'].replace(/^,/, '')
|
|
|
|
|
|
|
|
// for (ik in index_keys) {
|
|
// if (!index_data[ host_data['ITAM']['ID'] ].hasOwnProperty(index_keys[ik])) {
|
|
// console.log('MISSING: ' + index_keys[ik])
|
|
// index_data[ host_data['ITAM']['ID'] ][ index_keys[ik] ] = ''
|
|
// }
|
|
// }
|
|
|
|
// console.log(index_data[ host_data['ITAM']['ID'] ]['AM_ID'] + ' : ' + index_data[ host_data['ITAM']['ID'] ]['AM_HOSTNAME'])
|
|
// console.log('DATA: ' + JSON.stringify(index_data[ host_data['ITAM']['ID'] ], null, 2))
|
|
// console.log(Object.keys(index_data[ host_data['ITAM']['ID'] ]))
|
|
|
|
|
|
// Software Analysis
|
|
|
|
// console.log("Software Analysis")
|
|
// console.log(JSON.stringify(Object.keys(host_data['SOURCE']['SW']), null, 2))
|
|
// console.log(host_data['ITAM']['ID'])
|
|
// console.log(host_data['SOURCE']['NODEJS']['OS']['DISTRO'])
|
|
sw_index_data[ host_data['ITAM']['ID'] ] = {}
|
|
|
|
if (host_data['SOURCE'].hasOwnProperty("SYSTEM_PROFILER")) {
|
|
// console.log("SYSTEM_PROFILER")
|
|
// for (sw in host_data['SOURCE']['SYSTEM_PROFILER']['SPInstallHistoryDataType']) {
|
|
// console.log(' SPInstallHistoryDataType: ' + host_data['SOURCE']['SYSTEM_PROFILER']['SPInstallHistoryDataType'][sw]['_name'])
|
|
// }
|
|
|
|
if (host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'].hasOwnProperty('Applications')) {
|
|
for (sw in host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications']) {
|
|
// console.log('SW: ' + sw)
|
|
sw_idx = sw
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx] = {}
|
|
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['NAME'] = sw
|
|
|
|
if (host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications'][sw].hasOwnProperty('Version')) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications'][sw]['Version']
|
|
} else {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications'][sw]['Last Modified']
|
|
}
|
|
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['KERNEL'] = host_data['SOURCE']['NODEJS']['OS']['KERNEL']
|
|
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = ''
|
|
|
|
if (host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications'][sw_idx].hasOwnProperty("64-Bit (Intel)")) {
|
|
if (host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications'][sw_idx]['64-Bit (Intel)'] == "Yes") {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = 'Intel x64'
|
|
} else {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications'][sw]['Kind']
|
|
}
|
|
} else {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications'][sw]['Kind']
|
|
}
|
|
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications'][sw]['Last Modified']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ORIGIN'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']['Applications'][sw]['Signed by']
|
|
}
|
|
} else { // SYSTEM_PROFILER Supports JSON
|
|
for (sw in host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType']) {
|
|
// console.log('SW: ' + sw + ' ' + host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['_name'])
|
|
sw_idx = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['_name']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx] = {}
|
|
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['NAME'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['_name']
|
|
if (host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw].hasOwnProperty('version')) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['version']
|
|
} else {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['lastModified']
|
|
}
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['KERNEL'] = host_data['SOURCE']['NODEJS']['OS']['KERNEL']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['arch_kind']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['lastModified']
|
|
if (host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw].hasOwnProperty('signed_by')) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ORIGIN'] = JSON.stringify(host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['signed_by'])
|
|
// for (sdx in host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['signed_by']) {
|
|
// // console.log(sdx + ' ' + host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['signed_by'][sdx])
|
|
// if (sdx == 1) {
|
|
// sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ORIGIN'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['signed_by'][sdx]
|
|
// }
|
|
// }
|
|
} else if (host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw].hasOwnProperty('obtained_from')) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ORIGIN'] = host_data['SOURCE']['SYSTEM_PROFILER']['SPApplicationsDataType'][sw]['obtained_from']
|
|
} else {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ORIGIN'] = ''
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (swsrc in host_data['SOURCE']['SW']) {
|
|
switch (swsrc) {
|
|
case 'DEB':
|
|
// console.log(swsrc)
|
|
|
|
for (sw in host_data['SOURCE']['SW'][swsrc]) {
|
|
sw_idx = sw
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx] = {}
|
|
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['NAME'] = sw
|
|
|
|
if (Object.keys(host_data['SOURCE']['SW'][swsrc][sw]['DPKG_LIST']).length > 0) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION'] = host_data['SOURCE']['SW'][swsrc][sw]['DPKG_LIST']['VERSION']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['KERNEL'] = host_data['SOURCE']['NODEJS']['OS']['KERNEL']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = host_data['SOURCE']['SW'][swsrc][sw]['DPKG_LIST']['ARCH']
|
|
} else if (Object.keys(host_data['SOURCE']['SW'][swsrc][sw]['APT_CACHE']).length > 0) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION'] = host_data['SOURCE']['SW'][swsrc][sw]['APT_CACHE']['Version']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['KERNEL'] = host_data['SOURCE']['NODEJS']['OS']['KERNEL']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = host_data['SOURCE']['SW'][swsrc][sw]['APT_CACHE']['Architecture']
|
|
}
|
|
|
|
if (Object.keys(host_data['SOURCE']['SW'][swsrc][sw]['APT_HISTORY']).length > 0) {
|
|
// console.log ("APT_HISTORY")
|
|
for (ah in host_data['SOURCE']['SW'][swsrc][sw]['APT_HISTORY']) {
|
|
// console.log(sw_idx + ' ' + ah + ' ' + host_data['SOURCE']['SW'][swsrc][sw]['APT_HISTORY'][ah]['EVENT'])
|
|
switch (host_data['SOURCE']['SW'][swsrc][sw]['APT_HISTORY'][ah]['EVENT']) {
|
|
case 'Install':
|
|
if (host_data['SOURCE']['SW'][swsrc][sw]['APT_HISTORY'][ah]['VERSION'] == sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION']) {
|
|
if (sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] && (sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] > ah)) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] = ah
|
|
} else {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] = ah
|
|
}
|
|
}
|
|
break;
|
|
case 'Upgrade':
|
|
if (host_data['SOURCE']['SW'][swsrc][sw]['APT_HISTORY'][ah]['VERSION'] == sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION']) {
|
|
if (sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] && (sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] > ah)) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] = ah
|
|
} else {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] = ah
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (Object.keys(host_data['SOURCE']['SW'][swsrc][sw]['APT_CACHE']).length > 0) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ORIGIN'] = host_data['SOURCE']['SW'][swsrc][sw]['APT_CACHE']['Maintainer']
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case 'RPM':
|
|
// console.log(swsrc)
|
|
|
|
for (sw in host_data['SOURCE']['SW'][swsrc]) {
|
|
sw_idx = host_data['SOURCE']['SW'][swsrc][sw]['Name']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx] = {}
|
|
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['NAME'] = host_data['SOURCE']['SW'][swsrc][sw]['Name']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION'] = host_data['SOURCE']['SW'][swsrc][sw]['Version']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['KERNEL'] = host_data['SOURCE']['NODEJS']['OS']['KERNEL']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = host_data['SOURCE']['SW'][swsrc][sw]['Architecture']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] = host_data['SOURCE']['SW'][swsrc][sw]['InstallDate']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ORIGIN'] = host_data['SOURCE']['SW'][swsrc][sw]['Packager']
|
|
}
|
|
break;
|
|
|
|
case 'GET_ITEMPROPERTY':
|
|
// console.log(swsrc)
|
|
for (sw in host_data['SOURCE']['SW'][swsrc]) {
|
|
|
|
sw_idx = host_data['SOURCE']['SW'][swsrc][sw]['DisplayName']
|
|
// console.log(sw + ' : ' + sw_idx)
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx] = {}
|
|
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['NAME'] = host_data['SOURCE']['SW'][swsrc][sw]['DisplayName']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['VERSION'] = host_data['SOURCE']['SW'][swsrc][sw]['DisplayVersion']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['KERNEL'] = host_data['SOURCE']['NODEJS']['OS']['KERNEL']
|
|
if (host_data['SOURCE']['SW'][swsrc][sw]['InstallLocation']) {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = host_data['SOURCE']['SW'][swsrc][sw]['InstallLocation']
|
|
} else {
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ARCH'] = ''
|
|
}
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['INSTALL_DATE'] = host_data['SOURCE']['SW'][swsrc][sw]['DisplayVersion']
|
|
sw_index_data[ host_data['ITAM']['ID'] ][sw_idx]['ORIGIN'] = host_data['SOURCE']['SW'][swsrc][sw]['Publisher']
|
|
}
|
|
break;
|
|
default:
|
|
console.log('WARNING: Unknown Software Source: ' + swsrc)
|
|
}
|
|
}
|
|
}
|
|
|
|
} // END if (host_data['ITAM'].hasOwnProperty('SKQITAM_VERSION')) {
|
|
|
|
} // END for (hd in hostdirs) {
|
|
|
|
|
|
// Stats
|
|
console.log('---------- Generating Statistics ------------')
|
|
|
|
let kernel_map = {}
|
|
kernel_map['Linux'] = 'Linux'
|
|
kernel_map['Darwin'] = 'OS X'
|
|
kernel_map['Windows_NT'] = 'Windows'
|
|
|
|
let stats = {}
|
|
stats['HISTOGRAMS'] = {}
|
|
stats['HISTOGRAMS']['KERNEL'] = {}
|
|
stats['HISTOGRAMS']['OS'] = {}
|
|
stats['HISTOGRAMS']['OS_VERSIONS'] = {}
|
|
stats['HISTOGRAMS']['INSTALL_DATES_YYYY'] = {}
|
|
stats['HISTOGRAMS']['INSTALL_DATES_YYYY-MM-DD'] = {}
|
|
stats['HISTOGRAMS']['SW_APPLICATIONS'] = {}
|
|
stats['HISTOGRAMS']['SW_VERSIONS'] = {}
|
|
stats['HISTOGRAMS']['SW_INSTALL_DATES'] = {}
|
|
stats['HISTOGRAMS']['SW_AGE_DAYS'] = {}
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'] = {}
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'] = {}
|
|
stats['HISTOGRAMS']['SW_VERSIONS_STATUS'] = {}
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION_SCORES'] = {}
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION_SCORES'] = {}
|
|
|
|
for (h in index_data) {
|
|
let isd = skqlib.tell_time(index_data[h]['OS_INSTALL_DATE'])
|
|
|
|
if ( !stats['HISTOGRAMS']['INSTALL_DATES_YYYY'].hasOwnProperty(isd['UTC']['YYYY']) ) {
|
|
stats['HISTOGRAMS']['INSTALL_DATES_YYYY'][ isd['UTC']['YYYY'] ] = 0
|
|
}
|
|
stats['HISTOGRAMS']['INSTALL_DATES_YYYY'][ isd['UTC']['YYYY'] ]++
|
|
|
|
if ( !stats['HISTOGRAMS']['INSTALL_DATES_YYYY-MM-DD'].hasOwnProperty(isd['UTC']['YYYY-MM-DD']) ) {
|
|
stats['HISTOGRAMS']['INSTALL_DATES_YYYY-MM-DD'][ isd['UTC']['YYYY-MM-DD'] ] = 0
|
|
}
|
|
stats['HISTOGRAMS']['INSTALL_DATES_YYYY-MM-DD'][ isd['UTC']['YYYY-MM-DD'] ]++
|
|
|
|
if (!stats['HISTOGRAMS']['KERNEL'].hasOwnProperty(kernel_map [ index_data[h]['KERNEL'] ])) {
|
|
stats['HISTOGRAMS']['KERNEL'][ kernel_map [ index_data[h]['KERNEL'] ] ] = 0
|
|
}
|
|
stats['HISTOGRAMS']['KERNEL'][ kernel_map [ index_data[h]['KERNEL'] ] ]++
|
|
|
|
if (!stats['HISTOGRAMS']['OS'].hasOwnProperty(index_data[h]['OS'])) {
|
|
stats['HISTOGRAMS']['OS'][ index_data[h]['OS'] ] = 0
|
|
}
|
|
stats['HISTOGRAMS']['OS'][ index_data[h]['OS'] ]++
|
|
|
|
if (!stats['HISTOGRAMS']['OS_VERSIONS'].hasOwnProperty(String(index_data[h]['OS'])[0].toUpperCase() + String(index_data[h]['OS']).slice(1) + ' ' + index_data[h]['OS_VERSION'])) {
|
|
stats['HISTOGRAMS']['OS_VERSIONS'][ String(index_data[h]['OS'])[0].toUpperCase() + String(index_data[h]['OS']).slice(1) + ' ' + index_data[h]['OS_VERSION'] ] = 0
|
|
}
|
|
stats['HISTOGRAMS']['OS_VERSIONS'][ String(index_data[h]['OS'])[0].toUpperCase() + String(index_data[h]['OS']).slice(1) + ' ' + index_data[h]['OS_VERSION'] ]++
|
|
|
|
}
|
|
|
|
|
|
// Software Stats
|
|
let now = skqlib.tell_time()
|
|
|
|
let regx_swver = []
|
|
rx = 0
|
|
// regx_swver[rx++] = '/^(\d+)\.$/'
|
|
// regx_swver[rx++] = /^(\d+)[.:~](\d+)[.:~](\d+)[.:~](\d+)[+\-_:](\S+)$/
|
|
// regx_swver[rx++] = /^(\d+)[.:~](\d+)[.:~](\d+)[+\-_:](\S+)$/
|
|
// regx_swver[rx++] = /^(\d+)[.:~](\d+)[+\-_:](\S+)$/
|
|
// regx_swver[rx++] = /^(\d+)[+\-_:](\S+)$/
|
|
regx_swver[rx++] = /^(\d+)[\.\:\~](\d+)[\.\:\~](\d+)[\.\:\~](\d+)/
|
|
regx_swver[rx++] = /^(\d+)[\.\:\~](\d+)[\.\:\~](\d+)/
|
|
regx_swver[rx++] = /^(\d+)[\.\:\~](\d+)/
|
|
regx_swver[rx++] = /^(\d+)/
|
|
// console.log(JSON.stringify(regx_swver, null, 2))
|
|
|
|
let swver_status = {}
|
|
swver_status['MATCH'] = 0
|
|
swver_status['MISMATCH'] = 0
|
|
swver_status['MISSING'] = 0
|
|
swver_status['TOTAL'] = 0
|
|
|
|
for (h in sw_index_data) {
|
|
for (sw in sw_index_data[h]) {
|
|
|
|
swver_status['TOTAL']++
|
|
|
|
let swisd = {}
|
|
swisd['UTC'] = {}
|
|
swisd['UTC']['YYYY-MM-DD'] = 'YYYY-MM-DD'
|
|
|
|
if (sw_index_data[h][sw].hasOwnProperty('INSTALL_DATE')) {
|
|
swisd = skqlib.tell_time(sw_index_data[h][sw]['INSTALL_DATE'])
|
|
}
|
|
|
|
if (!stats['HISTOGRAMS']['SW_APPLICATIONS'].hasOwnProperty(sw)) {
|
|
stats['HISTOGRAMS']['SW_APPLICATIONS'][sw] = 0
|
|
}
|
|
stats['HISTOGRAMS']['SW_APPLICATIONS'][sw]++
|
|
|
|
// console.log(h + ' ' + sw + ' ' + swisd['UTC']['YYYY-MM-DD'])
|
|
if (!stats['HISTOGRAMS']['SW_INSTALL_DATES'].hasOwnProperty( swisd['UTC']['YYYY-MM-DD'] )) {
|
|
stats['HISTOGRAMS']['SW_INSTALL_DATES'][ swisd['UTC']['YYYY-MM-DD'] ] = 0
|
|
}
|
|
stats['HISTOGRAMS']['SW_INSTALL_DATES'][ swisd['UTC']['YYYY-MM-DD'] ]++
|
|
|
|
if (swisd['UTC']['YYYY-MM-DD'].match(/^\d{4}\-\d{2}\-\d{2}$/)) {
|
|
let sw_age_days = Math.round( (Number(now['UTC']['EPOCH']) - Number(swisd['UTC']['EPOCH'])) / (24*3600) )
|
|
if (!stats['HISTOGRAMS']['SW_AGE_DAYS'].hasOwnProperty( sw_age_days )) {
|
|
stats['HISTOGRAMS']['SW_AGE_DAYS'][ sw_age_days ] = 0
|
|
}
|
|
stats['HISTOGRAMS']['SW_AGE_DAYS'][ sw_age_days ]++
|
|
} else {
|
|
swage = 'UNKNOWN'
|
|
if (!stats['HISTOGRAMS']['SW_AGE_DAYS'].hasOwnProperty( swage )) {
|
|
stats['HISTOGRAMS']['SW_AGE_DAYS'][ swage ] = 0
|
|
}
|
|
stats['HISTOGRAMS']['SW_AGE_DAYS'][ swage ]++
|
|
}
|
|
|
|
if (!stats['HISTOGRAMS']['SW_VERSIONS'].hasOwnProperty(sw)) {
|
|
stats['HISTOGRAMS']['SW_VERSIONS'][sw] = {}
|
|
}
|
|
|
|
|
|
// VooDoo BUG:
|
|
// -------------
|
|
// 3c9f9ad652a4aa092fb0696e679d546e3d82b7a9a6bb5a80ac83acdaf2c6636d:NVM for Windows :{
|
|
// "NAME": "NVM for Windows ",
|
|
// "KERNEL": "Windows_NT",
|
|
// "ARCH": "C:\\Users\\cfosadmin\\AppData\\Roaming\\nvm\\",
|
|
// "ORIGIN": "Ecor Ventures LLC"
|
|
// }
|
|
// DEBUG: NAME => NVM for Windows
|
|
// DEBUG: VERSION => undefined
|
|
// DEBUG: KERNEL => Windows_NT
|
|
// DEBUG: ARCH => C:\Users\cfosadmin\AppData\Roaming\nvm\
|
|
// DEBUG: INSTALL_DATE => undefined
|
|
// DEBUG: ORIGIN => Ecor Ventures LLC
|
|
// DEBUG: VERSION true
|
|
// DEBUG: VERSION undefined
|
|
// DEBUG: Success Version NVM for Windows undefined
|
|
|
|
|
|
// console.log('-------------')
|
|
//
|
|
// console.log(h + ':' + sw + ':' + JSON.stringify(sw_index_data[h][sw], null, 2))
|
|
// for (k in sw_index_data[h][sw]) {
|
|
// console.log('DEBUG: ' + k + ' => ' + sw_index_data[h][sw][k])
|
|
// }
|
|
//
|
|
// console.log('DEBUG: VERSION ' + (sw_index_data[h][sw]['VERSION'] === undefined))
|
|
// console.log('DEBUG: VERSION ' + sw_index_data[h][sw]['VERSION'])
|
|
//
|
|
// if (sw_index_data[h][sw].hasOwnProperty("VERSION")) {
|
|
// console.log('DEBUG: Success Version ' + sw + ' ' + sw_index_data[h][sw]['VERSION'])
|
|
// } else {
|
|
// console.log('DEBUG: Failed Version')
|
|
// }
|
|
|
|
let sw_version = ''
|
|
let version_match = false
|
|
|
|
for (rx in regx_swver) {
|
|
regx = RegExp(regx_swver[rx])
|
|
|
|
// if (sw_index_data[h][sw].hasOwnProperty('VERSION')) {
|
|
if (!(sw_index_data[h][sw]['VERSION'] === undefined)) {
|
|
// console.log(JSON.stringify(sw_index_data[h][sw], null, 2))
|
|
// console.log(sw + ' REGX: ' + regx + ' ' + sw_index_data[h][sw]['VERSION'])
|
|
if (!version_match && (swver_mch = sw_index_data[h][sw]['VERSION'].match(regx))) {
|
|
// console.log(sw + ' ' + sw_index_data[h][sw]['VERSION'] + ' ' + rx + ': ' + regx + ' => ' + JSON.stringify(swver_mch, null, 2))
|
|
version_match = true
|
|
swver_status['MATCH']++
|
|
for (iv=1; iv<swver_mch.length; iv++) {
|
|
if (swver_mch[iv].match(/^\d+$/)) {
|
|
sw_version += swver_mch[iv] + '.'
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// console.log("MISSING VERSION: \n" + h + "\n" + JSON.stringify(sw_index_data[h][sw], null, 2))
|
|
sw_version = 'NULL'
|
|
swver_status['MISSING']++
|
|
}
|
|
}
|
|
|
|
if (!version_match) {
|
|
// console.log("WARNING: Unmatched Version Pattern (" + sw_index_data[h][sw]['VERSION'] + ")")
|
|
sw_version = 'ERROR: ' + sw_index_data[h][sw]['VERSION']
|
|
swver_status['MISMATCH']++
|
|
}
|
|
|
|
sw_version = sw_version.replace(RegExp(/\.$/), '')
|
|
// console.log(sw + ' ' + sw_version)
|
|
|
|
if (!stats['HISTOGRAMS']['SW_VERSIONS'][sw].hasOwnProperty(sw_version)) {
|
|
stats['HISTOGRAMS']['SW_VERSIONS'][sw][ sw_version ] = []
|
|
}
|
|
stats['HISTOGRAMS']['SW_VERSIONS'][sw][ sw_version ]++
|
|
|
|
}
|
|
}
|
|
|
|
stats['HISTOGRAMS']['SW_VERSIONS_STATUS'] = swver_status
|
|
// console.log('swver_status: ' + "\n" + JSON.stringify(swver_status, null, 2))
|
|
|
|
let sorted_vers = []
|
|
for (h in sw_index_data) {
|
|
for (sw in sw_index_data[h]) {
|
|
// console.log(sw)
|
|
if (Object.keys(stats['HISTOGRAMS']['SW_VERSIONS'][sw]).length > 1) {
|
|
// console.log(JSON.stringify(stats['HISTOGRAMS']['SW_VERSIONS'][sw], null, 2))
|
|
// console.log(JSON.stringify(Object.keys(stats['HISTOGRAMS']['SW_VERSIONS'][sw]), null, 2))
|
|
sorted_vers = sort_versions(Object.keys(stats['HISTOGRAMS']['SW_VERSIONS'][sw]))
|
|
} else {
|
|
sorted_vers.push( Object.keys( stats['HISTOGRAMS']['SW_VERSIONS'][sw] )[0] )
|
|
}
|
|
// console.log(JSON.stringify(sorted_vers, null, 2))
|
|
let lastest_version = false
|
|
let regx = RegExp('^' + sorted_vers[ (sorted_vers.length-1) ].replace(/\./g, '\\.'))
|
|
// console.log(regx)
|
|
if (String(sw_index_data[h][sw]['VERSION']).match(regx)) {
|
|
lastest_version = true
|
|
}
|
|
// console.log(h + ' : ' + sw + ' ' + sw_index_data[h][sw]['VERSION'] + ' <=> ' + sorted_vers[ (sorted_vers.length-1) ] + ' UPTODATE: ' + lastest_version)
|
|
|
|
if (!stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'].hasOwnProperty(sw)) {
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw] = {}
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['UP_TO_DATE'] = 0
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['OUT_OF_DATE'] = 0
|
|
}
|
|
if (lastest_version) {
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['UP_TO_DATE']++
|
|
} else {
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['OUT_OF_DATE']++
|
|
}
|
|
|
|
if (!stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'].hasOwnProperty(h)) {
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h] = {}
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['UP_TO_DATE'] = 0
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['OUT_OF_DATE'] = 0
|
|
}
|
|
if (lastest_version) {
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['UP_TO_DATE']++
|
|
} else {
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['OUT_OF_DATE']++
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
for (sw in stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION']) {
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['UP_TO_DATE_SCORE'] = Number(stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['UP_TO_DATE'])/(Number(stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['UP_TO_DATE']) + Number(stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['OUT_OF_DATE']))
|
|
|
|
for (scr=0; scr<=1; scr+=0.1) {
|
|
scridx = Number(scr).toPrecision(2)
|
|
if (!stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION_SCORES'].hasOwnProperty(scridx)) {
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION_SCORES'][scridx] = 0
|
|
}
|
|
|
|
if ( (Number(scridx) <= stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['UP_TO_DATE_SCORE']) && (stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION'][sw]['UP_TO_DATE_SCORE'] < (Number(scridx)+0.1)) ) {
|
|
stats['HISTOGRAMS']['SW_PER_APP_LATEST_VERSION_SCORES'][scridx]++
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
for (h in stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION']) {
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['UP_TO_DATE_SCORE'] = Number(stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['UP_TO_DATE'])/(Number(stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['UP_TO_DATE']) + Number(stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['OUT_OF_DATE']))
|
|
|
|
for (scr=0; scr<=1; scr+=0.1) {
|
|
scridx = Number(scr).toPrecision(2)
|
|
if (!stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION_SCORES'].hasOwnProperty(scridx)) {
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION_SCORES'][scridx] = 0
|
|
}
|
|
|
|
if ( (Number(scridx) <= stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['UP_TO_DATE_SCORE']) && (stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION'][h]['UP_TO_DATE_SCORE'] < (Number(scridx)+0.1)) ) {
|
|
stats['HISTOGRAMS']['SW_PER_HOST_LATEST_VERSION_SCORES'][scridx]++
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// console.log(JSON.stringify(stats, null, 2))
|
|
|
|
// Save Data Files
|
|
console.log('---------- Writing Files ------------')
|
|
// console.log(JSON.stringify(index_data, null, 2))
|
|
console.log('WRITING: ' + index_data_file)
|
|
fs.writeFileSync(index_data_file, JSON.stringify(index_data, null, 2), 'utf8')
|
|
|
|
console.log('WRITING: ' + sw_index_data_file)
|
|
fs.writeFileSync(sw_index_data_file, JSON.stringify(sw_index_data, null, 2), 'utf8')
|
|
|
|
console.log('WRITING: ' + index_data_file.replace(/json$/, 'csv'))
|
|
fs.writeFileSync(index_data_file.replace(/json$/, 'csv'), index_data_to_csv(index_keys, index_data), 'utf8')
|
|
|
|
|
|
console.log('WRITING: ' + sw_index_data_file.replace(/json$/, 'csv'))
|
|
fs.writeFileSync(sw_index_data_file.replace(/json$/, 'csv'), sw_index_data_to_csv(sw_index_keys, sw_index_data), 'utf8')
|
|
|
|
|
|
let stats_file = path.join(__dirname, 'itam-data', 'proc', 'stats.json')
|
|
console.log('WRITING: ' + stats_file)
|
|
fs.writeFileSync(stats_file, JSON.stringify(stats, null, 2), 'utf8')
|
|
|
|
|
|
// Sikuliaq CSV Reports
|
|
console.log('WRITING: ' + path.join(__dirname, 'itam-data', 'reports', 'skq_appendix_d_hw.csv'))
|
|
fs.writeFileSync(path.join(__dirname, 'itam-data', 'reports', 'skq_appendix_d_hw.csv'), skq_index_data_to_app_d_hw_csv(index_keys, index_data), 'utf8')
|
|
|
|
console.log('WRITING: ' + path.join(__dirname, 'itam-data', 'reports', 'skq_appendix_d_sw.csv'))
|
|
fs.writeFileSync(path.join(__dirname, 'itam-data', 'reports', 'skq_appendix_d_sw.csv'), skq_index_data_to_app_d_sw_csv(sw_index_keys, sw_index_data), 'utf8')
|
|
|
|
|
|
function index_data_to_csv(keys, data) {
|
|
let csv = ""
|
|
|
|
for (k in keys) {
|
|
csv += '"' + keys[k] + '"'
|
|
if (k < (keys.length-1)) { csv += ","} else { csv += "\n" }
|
|
}
|
|
|
|
for (i in data) {
|
|
for (k in keys) {
|
|
if (data[i].hasOwnProperty(keys[k]) && data[i][ keys[k] ]) {
|
|
csv += '"' + data[i][ keys[k] ] + '"'
|
|
} else {
|
|
csv += '""'
|
|
}
|
|
if (k < (keys.length-1)) { csv += ","} else { csv += "\n" }
|
|
}
|
|
}
|
|
|
|
return csv
|
|
}
|
|
|
|
function sw_index_data_to_csv(keys, data) {
|
|
let csv = ""
|
|
|
|
keys.push('INSTALL_HOST_ID')
|
|
|
|
for (k in keys) {
|
|
csv += '"' + keys[k] + '"'
|
|
if (k < (keys.length-1)) { csv += ","} else { csv += "\n" }
|
|
}
|
|
|
|
for (h in data) {
|
|
for (i in data[h]) {
|
|
for (k in keys) {
|
|
if(keys[k] == "INSTALL_HOST_ID") {
|
|
csv += '"' + h + '"'
|
|
} else {
|
|
if (data[h][i].hasOwnProperty(keys[k]) && data[h][i][ keys[k] ]) {
|
|
csv += '"' + data[h][i][ keys[k] ] + '"'
|
|
} else {
|
|
csv += '""'
|
|
}
|
|
}
|
|
|
|
if (k < (keys.length-1)) { csv += ","} else { csv += "\n" }
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return csv
|
|
}
|
|
|
|
function skq_index_data_to_app_d_sw_csv(keys, data) {
|
|
let csv = ''
|
|
|
|
let keymap = {}
|
|
keymap['AM_ID'] = 'Asset IDs'
|
|
keymap['NAME'] = 'Name of Software'
|
|
keymap['VERSION'] = 'Installed Version'
|
|
keymap['INSTALL_DATE'] = 'Date of Install'
|
|
|
|
|
|
let reverse_keymap = {}
|
|
for (k in keymap) { reverse_keymap[ keymap[k] ] = k }
|
|
|
|
// CSV Header
|
|
let hk = 0
|
|
for (k in keymap) {
|
|
csv += '"' + keymap[k] + '"'
|
|
if (hk < (Object.keys(keymap).length-1)) { csv += ","} else { csv += "\n" }
|
|
hk++
|
|
}
|
|
|
|
let apps = {}
|
|
|
|
for (amid in data) {
|
|
// console.log(amid)
|
|
// console.log(JSON.stringify(data[amid], null, 2))
|
|
for (sw in data[amid]) {
|
|
if (!apps.hasOwnProperty(data[amid][sw]['NAME'] + ':-:' + data[amid][sw]['VERSION'])) {
|
|
apps[ data[amid][sw]['NAME'] + ':-:' + data[amid][sw]['VERSION'] ] = {}
|
|
apps[ data[amid][sw]['NAME'] + ':-:' + data[amid][sw]['VERSION'] ]['Asset IDs'] = ''
|
|
apps[ data[amid][sw]['NAME'] + ':-:' + data[amid][sw]['VERSION'] ]['Name of Software'] = data[amid][sw]['NAME']
|
|
apps[ data[amid][sw]['NAME'] + ':-:' + data[amid][sw]['VERSION'] ]['Installed Version'] = data[amid][sw]['VERSION']
|
|
apps[ data[amid][sw]['NAME'] + ':-:' + data[amid][sw]['VERSION'] ]['Date of Install'] = ''
|
|
}
|
|
apps[ data[amid][sw]['NAME'] + ':-:' + data[amid][sw]['VERSION'] ]['Asset IDs'] += amid + ', '
|
|
if (data[amid][sw]['INSTALL_DATE']) {
|
|
let inst = skqlib.tell_time(data[amid][sw]['INSTALL_DATE'])
|
|
apps[ data[amid][sw]['NAME'] + ':-:' + data[amid][sw]['VERSION'] ]['Date of Install'] += inst['UTC']['YYYY-MM-DD'] + ', '
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
for (a in apps) {
|
|
for (k in apps[a]) {
|
|
if (k != 'Date of Install') {
|
|
csv += '"' + String(apps[a][k]).replace(RegExp(', $'), '') + '",'
|
|
} else {
|
|
csv += '"' + String(apps[a][k]).replace(RegExp(', $'), '') + '"' + "\n"
|
|
}
|
|
}
|
|
}
|
|
|
|
// console.log(JSON.stringify(apps, null, 2))
|
|
// console.log(JSON.stringify(Object.keys(apps), null, 2))
|
|
|
|
return csv
|
|
}
|
|
|
|
function skq_index_data_to_app_d_hw_csv(keys, data) {
|
|
// Sikuliaq Appendix D Hardware CSV
|
|
let keymap = {}
|
|
keymap['AM_HOSTNAME'] = 'Machine Name'
|
|
keymap['AM_ID'] = 'Asset ID'
|
|
keymap['HW_MAKE'] = 'Manufacturer'
|
|
keymap['HW_MODEL'] = 'Model Number'
|
|
keymap['HW_SERIAL_NUMBER'] = 'Serial Number'
|
|
keymap['OS'] = 'Operating System'
|
|
keymap['OS_INSTALL_DATE'] = 'Install Date'
|
|
keymap['SYSTEM_OWNER'] = 'Administrator/Custodian/POC'
|
|
|
|
let reverse_keymap = {}
|
|
for (k in keymap) { reverse_keymap[ keymap[k] ] = k }
|
|
reverse_keymap['Type of Equipment'] = 'ASSET_TYPE'
|
|
|
|
let appendix_d_hw_keys = [
|
|
"Type of Equipment",
|
|
"Machine Name",
|
|
"Asset ID",
|
|
"Manufacturer",
|
|
"Model Number",
|
|
"Serial Number",
|
|
"Operating System and/or Firmware Version",
|
|
"Install Date",
|
|
"Network",
|
|
"Internet Access",
|
|
"System Classification",
|
|
"Administrator/Custodian/POC"
|
|
]
|
|
|
|
|
|
let skq_network_regx = {}
|
|
skq_network_regx['Shrnet'] = RegExp(/^10\.0\.0\./)
|
|
skq_network_regx['Infrastructure'] = RegExp(/^10\.1\.0\./)
|
|
skq_network_regx['Core'] = RegExp(/^10\.2\.0\./)
|
|
skq_network_regx['Data'] = RegExp(/^10\.3\.0\./)
|
|
skq_network_regx['Video'] = RegExp(/^10\.4\.0\./)
|
|
skq_network_regx['Shipwide'] = RegExp(/^10\.5\./)
|
|
skq_network_regx['WAN_Stack'] = RegExp(/^199\.123\.165\./)
|
|
// skq_network_regx['CCTV'] = RegExp(/^10\.1\.0\./)
|
|
// skq_network_regx['IBS'] = RegExp(/^10\.1\.0\./)
|
|
// skq_network_regx['IAS'] = RegExp(/^10\.1\.0\./)
|
|
|
|
let skq_sys_class = {}
|
|
skq_sys_class['Shrnet'] = "IT-Inf"
|
|
skq_sys_class['Infrastructure'] = "IT-Inf"
|
|
skq_sys_class['Core'] = "IT-Sci"
|
|
skq_sys_class['Data'] = "IT-Data Aq"
|
|
skq_sys_class['Video'] = "IT-Inf"
|
|
skq_sys_class['Shipwide'] = "IT-end user"
|
|
skq_sys_class['WAN_Stack'] = "IT-WAN"
|
|
// "IT-LAN",
|
|
// "OT-Sci",
|
|
// "OT-Eng",
|
|
// "OT-Brdg"
|
|
|
|
let csv = ""
|
|
let data_csv = ""
|
|
|
|
// CSV Header
|
|
for (k in appendix_d_hw_keys) {
|
|
csv += '"' + appendix_d_hw_keys[k] + '"'
|
|
if (k < (appendix_d_hw_keys.length-1)) { csv += ","} else { csv += "\n" }
|
|
}
|
|
|
|
|
|
for (i in data) {
|
|
data_csv = ""
|
|
// console.log("App-D: " + i)
|
|
data[i]['ASSET_TYPE'] = 'Networked Computer'
|
|
for (k in appendix_d_hw_keys) {
|
|
// console.log(' ' + appendix_d_hw_keys[k] + ' ' + reverse_keymap[ appendix_d_hw_keys[k] ] + ' ' + data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ])
|
|
// console.log(JSON.stringify(reverse_keymap, null, 2))
|
|
|
|
switch (appendix_d_hw_keys[k]) {
|
|
case "Type of Equipment":
|
|
data_csv += '"Networked Computer"'
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
break;
|
|
case "Machine Name":
|
|
if (data[i].hasOwnProperty(reverse_keymap[ appendix_d_hw_keys[k] ]) && data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ]) {
|
|
data_csv += '"' + data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ] + '"'
|
|
} else {
|
|
data_csv += '""'
|
|
}
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
break;
|
|
case "Asset ID":
|
|
if (data[i].hasOwnProperty(reverse_keymap[ appendix_d_hw_keys[k] ]) && data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ]) {
|
|
data_csv += '"' + data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ] + '"'
|
|
} else {
|
|
data_csv += '""'
|
|
}
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
break;
|
|
case "Manufacturer":
|
|
if (data[i].hasOwnProperty(reverse_keymap[ appendix_d_hw_keys[k] ]) && data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ]) {
|
|
data_csv += '"' + data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ] + '"'
|
|
} else {
|
|
data_csv += '""'
|
|
}
|
|
if (k < (appendix_d_hw_keys.length-1)) {
|
|
data_csv += ","
|
|
} else {
|
|
data_csv += "\n"
|
|
}
|
|
break;
|
|
case "Model Number":
|
|
if (data[i].hasOwnProperty(reverse_keymap[ appendix_d_hw_keys[k] ]) && data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ]) {
|
|
data_csv += '"' + data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ] + '"'
|
|
} else {
|
|
data_csv += '""'
|
|
}
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
break;
|
|
case "Serial Number":
|
|
if (data[i].hasOwnProperty(reverse_keymap[ appendix_d_hw_keys[k] ]) && data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ]) {
|
|
data_csv += '"' + data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ] + '"'
|
|
} else {
|
|
data_csv += '""'
|
|
}
|
|
if (k < (appendix_d_hw_keys.length-1)) {
|
|
data_csv += ","
|
|
} else {
|
|
data_csv += "\n"
|
|
}
|
|
break;
|
|
case "Operating System and/or Firmware Version":
|
|
data_csv += '"' + data[i]['OS'] + ' (' + data[i]['OS_VERSION'] + ') ' + data[i]['OS_ARCH'] + '"'
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
break;
|
|
case "Install Date":
|
|
if (data[i].hasOwnProperty(reverse_keymap[ appendix_d_hw_keys[k] ]) && data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ]) {
|
|
data_csv += '"' + data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ] + '"'
|
|
} else {
|
|
data_csv += '""'
|
|
}
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
break;
|
|
case "Network":
|
|
net = false
|
|
for (n in skq_network_regx) {
|
|
// console.log(n)
|
|
if (!net) {
|
|
if (data[i]['IP_ADDR'].match(skq_network_regx[n])) {
|
|
net = true
|
|
data_csv += '"' + n + '"'
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
}
|
|
}
|
|
}
|
|
if (!net) {
|
|
data_csv += '"UNKNOWN"'
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
}
|
|
break;
|
|
case "Internet Access":
|
|
net = false
|
|
for (n in skq_network_regx) {
|
|
if (!net) {
|
|
if (data[i]['IP_ADDR'].match(skq_network_regx[n])) {
|
|
if (n == 'Shrnet' || n == 'Infrastructure' || n == 'Shipwide') {
|
|
net = true
|
|
data_csv += '"YES"'
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!net) {
|
|
data_csv += '"NO"'
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
}
|
|
break;
|
|
case "System Classification":
|
|
net = false
|
|
for (n in skq_network_regx) {
|
|
if (!net) {
|
|
if (data[i]['IP_ADDR'].match(skq_network_regx[n])) {
|
|
net = true
|
|
data_csv += '"' + skq_sys_class[n] + '"'
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
}
|
|
}
|
|
}
|
|
if (!net) {
|
|
data_csv += '"UNKNOWN"'
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
}
|
|
break;
|
|
case "Administrator/Custodian/POC":
|
|
if (data[i].hasOwnProperty(reverse_keymap[ appendix_d_hw_keys[k] ]) && data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ]) {
|
|
data_csv += '"' + data[i][ reverse_keymap[ appendix_d_hw_keys[k] ] ] + '"'
|
|
} else {
|
|
data_csv += '""'
|
|
}
|
|
if (k < (appendix_d_hw_keys.length-1)) { data_csv += ","} else { data_csv += "\n" }
|
|
break;
|
|
|
|
default:
|
|
console.log('ERROR: Unknown Key' + appendix_d_hw_keys[k]);
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
// console.log("CSV: " + data_csv)
|
|
if (data_csv != "undefined") {
|
|
csv += data_csv
|
|
}
|
|
|
|
}
|
|
|
|
return csv
|
|
}
|
|
|
|
|
|
function sort_versions (version_array) {
|
|
// Takes in a array of semver (w.x.y.z) values and sort them numerically by version
|
|
// Supports up to 4 numeric version levels
|
|
let sorted = []
|
|
|
|
let version_obj = {}
|
|
for (v in version_array) {
|
|
if(version_split = String(version_array[v]).split(/\./)) {
|
|
// console.log(JSON.stringify(version_split, null, 2))
|
|
for (i=0; i<version_split.length; i++) {
|
|
// console.log(i + ' < ' + version_split.length + ' ' + version_array[v])
|
|
switch (i) {
|
|
case 0:
|
|
if (version_split.hasOwnProperty(0) && !version_obj.hasOwnProperty( version_split[0] )) {
|
|
version_obj[ version_split[0] ] = {}
|
|
}
|
|
case 1:
|
|
if (version_split.hasOwnProperty(1) && !version_obj[ version_split[0] ].hasOwnProperty( version_split[1] )) {
|
|
version_obj[ version_split[0] ][ version_split[1] ] = {}
|
|
}
|
|
case 2:
|
|
if (version_split.hasOwnProperty(2) && !version_obj[ version_split[0] ][ version_split[1] ].hasOwnProperty( version_split[2] )) {
|
|
version_obj[ version_split[0] ][ version_split[1] ][ version_split[2] ] = {}
|
|
}
|
|
case 3:
|
|
if (version_split.hasOwnProperty(3) && !version_obj[ version_split[0] ][ version_split[1] ][ version_split[2] ].hasOwnProperty( version_split[3] )) {
|
|
version_obj[ version_split[0] ][ version_split[1] ][ version_split[2] ][ version_split[3] ] = {}
|
|
}
|
|
break;
|
|
}
|
|
// console.log(i + JSON.stringify(version_obj, null, 2))
|
|
}
|
|
} else {
|
|
console.log('ERROR: Version Split Parser: ' + version_array[v])
|
|
}
|
|
}
|
|
// console.log(JSON.stringify(version_obj, null, 2))
|
|
|
|
for (v1 in version_obj) {
|
|
// console.log('ln ' + Object.keys(version_obj[v1]).length)
|
|
if (Object.keys(version_obj[v1]).length == 0) {
|
|
// console.log ('ver: ' + v1)
|
|
sorted.push(v1)
|
|
}
|
|
for (v2 in version_obj[v1]) {
|
|
if (Object.keys(version_obj[v1][v2]).length == 0) {
|
|
// console.log ('ver: ' + v1 + '.' + v2)
|
|
sorted.push(v1 + '.' + v2)
|
|
}
|
|
for (v3 in version_obj[v1][v2]) {
|
|
if (Object.keys(version_obj[v1][v2][v3]).length == 0) {
|
|
// console.log ('ver: ' + v1 + '.' + v2 + '.' + v3)
|
|
sorted.push(v1 + '.' + v2 + '.' + v3)
|
|
}
|
|
for (v4 in version_obj[v1][v2][v3]) {
|
|
if (Object.keys(version_obj[v1][v2][v3][v4]).length == 0) {
|
|
// console.log ('ver: ' + v1 + '.' + v2 + '.' + v3 + '.' + v4)
|
|
sorted.push(v1 + '.' + v2 + '.' + v3 + '.' + v4)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return sorted
|
|
}
|