fleet/ee/vulnerability-dashboard/api/controllers/download-unpatched-hosts-csv.js
Eric b1945b2128
Add fleet-vulnerability-dashboard repo to ee/ folder (#17428)
Closes: https://github.com/fleetdm/confidential/issues/4057

Changes:
- Added the contents of the fleet-vulnerability-dashboard repo to
ee/vulnerability-dashboard
- Added a github workflow to deploy the vulnerability dashboard on
Heroku
- Added a github workflow to test changes to the vulnerability-dashboard
- Updated the website's custom configuration to enable
auto-approvals/review requests to files in the
ee/vulnerability-dashboard folder
2024-03-13 13:06:11 -05:00

124 lines
4.9 KiB
JavaScript

module.exports = {
friendlyName: 'Download unpatched hosts CSV',
description: 'Download unpatched hosts for a software type file (returning a stream).',
inputs: {
exportType: {
required: true,
type: 'string',
description: 'The type of CSV export that will be generated',
isIn: [
'operatingSystem',
'chrome',
'firefox',
'safari',
'microsoftOffice',
'flash',
]
},
teamApid: {
description: 'The ID of the Team to filter by, or 0 to only include hosts with no team, or undefined to not filter by any team.',
type: 'number',
},
},
exits: {
success: {
outputFriendlyName: 'File',
outputDescription: 'The streaming bytes of the file.',
outputType: 'ref'
},
},
fn: async function ({exportType, teamApid}) {
// Generate a random room name.
let roomId = await sails.helpers.strings.random();
if(this.req.isSocket) {
// Add the requesting socket to the room.
sails.sockets.join(this.req, roomId);
}
let stream = require('stream');
let csvString = '';
// Create a writeable stream we'll use to create the csvString.
let writableStream = new stream.Writable({//[?]: https://nodejs.org/api/stream.html#writable_writechunk-encoding-callback
write(chunk, encoding, callback) {
csvString += chunk.toString();
callback();
}
});
let csv = require('fast-csv');
let generatingCsv = csv.format({headers: true});
// Pass the writableStream into generatingCsv.
generatingCsv.pipe(writableStream);// [?]: https://c2fo.github.io/fast-csv/docs/formatting/methods#write
if(exportType === 'operatingSystem'){
// If exportType is operatingSystem, we
// Get the non-compliant operating systems
let nonCompliantOperatingSystems = await OperatingSystem.find({isCompliant: false});
// Note, if teamApid is undefined, this will get find hosts from all teams.
let hostsWithNonCompliantOperatingSystems = await Host.find({teamApid: teamApid, operatingSystem: {in: _.pluck(nonCompliantOperatingSystems, 'id')}}).populate('operatingSystem');
for(let host of hostsWithNonCompliantOperatingSystems){
let csvRowForThisHost = {};
csvRowForThisHost['Host display name'] = host.displayName;
csvRowForThisHost['OS name'] = host.operatingSystem.name;
csvRowForThisHost['OS version'] = host.operatingSystem.versionName;
csvRowForThisHost['Host Fleet URL'] = sails.config.custom.fleetBaseUrl + '/hosts/'+host.fleetApid;
csvRowForThisHost['Host serial number'] = host.hardwareSerialNumber;
csvRowForThisHost['Host team'] = host.teamDisplayName;
csvRowForThisHost['Host team ID'] = host.teamApid;
generatingCsv.write(csvRowForThisHost);
}
} else {
let userFriendlyPlatformNamesByCodeName = {
'darwin': 'macOS',
'windows': 'Windows',
'chrome': 'Chrome OS',
'ubuntu': 'Ubuntu',
'linux': 'Linux'
};
let hostIdsOnThisTeam = await Host.find({teamApid: teamApid}).select('id');
let nonComplaintSoftwareInstalls = await CriticalInstall.find({isCompliant: false, softwareType: exportType, host: {in: _.pluck(hostIdsOnThisTeam, 'id')}}).populate('host');
for(let install of nonComplaintSoftwareInstalls) {
let userFriendlyPlatformNameForThisVersion = userFriendlyPlatformNamesByCodeName[install.platform];
if(userFriendlyPlatformNameForThisVersion === undefined){
userFriendlyPlatformNameForThisVersion = install.platform;
}
let csvRowForThisInstall = {};
csvRowForThisInstall['Host display name'] = install.host.displayName;
csvRowForThisInstall['Software name'] = _.capitalize(install.softwareName);
csvRowForThisInstall['Software platform'] = userFriendlyPlatformNameForThisVersion;
csvRowForThisInstall['Software version'] = install.versionName;
csvRowForThisInstall['Host Fleet URL'] = sails.config.custom.fleetBaseUrl + '/hosts/'+install.host.fleetApid;
csvRowForThisInstall['Host serial number'] = install.host.hardwareSerialNumber;
csvRowForThisInstall['Host team'] = install.host.teamDisplayName;
csvRowForThisInstall['Host team ID'] = install.host.teamApid;
generatingCsv.write(csvRowForThisInstall);
}
}
generatingCsv.end();
// After the the csvString has been generated by the writableStream, broadcast the csvString to the requesting user's socket.
writableStream.on('finish', () => {
if(this.req.isSocket){
// Note: we're sending the cveId with the cvsString, this is so we can set the filename in our frontend code.
sails.sockets.broadcast(roomId, 'csvExportDone', csvString);
// Unsubscribe the socket from the room.
sails.sockets.leave(this.req, roomId);
} else {
return csvString;
}
});
}
};