openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
282 lines (216 loc) • 9.42 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.processAuditMeta = processAuditMeta;
exports.processAudit = processAudit;
exports.sendAuditEvent = sendAuditEvent;
var _winston = _interopRequireDefault(require("winston"));
var _glossy = require("glossy");
var _xml2js = require("xml2js");
var _dgram = _interopRequireDefault(require("dgram"));
var _tls = _interopRequireDefault(require("tls"));
var _net = _interopRequireDefault(require("net"));
var _audits = require("./model/audits");
var tlsAuthentication = _interopRequireWildcard(require("./middleware/tlsAuthentication"));
var _config = require("./config");
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_config.config.auditing = _config.config.get('auditing');
const {
firstCharLowerCase
} = require('xml2js').processors;
function parseAuditRecordFromXML(xml, callback) {
// DICOM mappers
function csdCodeToCode(name) {
if (name === 'csd-code') {
return 'code';
}
return name;
}
function originalTextToDisplayName(name) {
if (name === 'originalText') {
return 'displayName';
}
return name;
}
const options = {
mergeAttrs: true,
explicitArray: false,
tagNameProcessors: [firstCharLowerCase],
attrNameProcessors: [firstCharLowerCase, csdCodeToCode, originalTextToDisplayName]
};
return (0, _xml2js.parseString)(xml, options, (err, result) => {
if (err) {
return callback(err);
}
if (!(result != null ? result.auditMessage : undefined)) {
return callback(new Error('Document is not a valid AuditMessage'));
}
const audit = {};
if (result.auditMessage.eventIdentification) {
audit.eventIdentification = result.auditMessage.eventIdentification;
}
audit.activeParticipant = [];
if (result.auditMessage.activeParticipant) {
// xml2js will only use an array if multiple items exist (explicitArray: false), else it's an object
if (result.auditMessage.activeParticipant instanceof Array) {
for (const ap of Array.from(result.auditMessage.activeParticipant)) {
audit.activeParticipant.push(ap);
}
} else {
audit.activeParticipant.push(result.auditMessage.activeParticipant);
}
}
if (result.auditMessage.auditSourceIdentification) {
audit.auditSourceIdentification = result.auditMessage.auditSourceIdentification;
}
audit.participantObjectIdentification = [];
if (result.auditMessage.participantObjectIdentification) {
// xml2js will only use an array if multiple items exist (explicitArray: false), else it's an object
if (result.auditMessage.participantObjectIdentification instanceof Array) {
for (const poi of Array.from(result.auditMessage.participantObjectIdentification)) {
audit.participantObjectIdentification.push(poi);
}
} else {
audit.participantObjectIdentification.push(result.auditMessage.participantObjectIdentification);
}
}
return callback(null, audit);
});
}
function codeInArray(code, arr) {
return arr.map(a => a.code).includes(code);
}
function processAuditMeta(audit, callback) {
_audits.AuditMetaModel.findOne({}, (err, auditMeta) => {
if (err) {
_winston.default.error(err);
return callback();
}
if (!auditMeta) {
auditMeta = new _audits.AuditMetaModel();
}
if (audit.eventIdentification != null && audit.eventIdentification.eventTypeCode != null && audit.eventIdentification.eventTypeCode.code && !codeInArray(audit.eventIdentification.eventTypeCode.code, auditMeta.eventType)) {
auditMeta.eventType.push(audit.eventIdentification.eventTypeCode);
}
if (audit.eventIdentification != null && audit.eventIdentification.eventID != null && audit.eventIdentification.eventID && !codeInArray(audit.eventIdentification.eventID.code, auditMeta.eventID)) {
auditMeta.eventID.push(audit.eventIdentification.eventID);
}
if (audit.activeParticipant) {
for (const activeParticipant of Array.from(audit.activeParticipant)) {
if ((activeParticipant.roleIDCode != null ? activeParticipant.roleIDCode.code : undefined) && !codeInArray(activeParticipant.roleIDCode.code, auditMeta.activeParticipantRoleID)) {
auditMeta.activeParticipantRoleID.push(activeParticipant.roleIDCode);
}
}
}
if (audit.participantObjectIdentification) {
for (const participantObject of Array.from(audit.participantObjectIdentification)) {
if ((participantObject.participantObjectIDTypeCode != null ? participantObject.participantObjectIDTypeCode.code : undefined) && !codeInArray(participantObject.participantObjectIDTypeCode.code, auditMeta.participantObjectIDTypeCode)) {
auditMeta.participantObjectIDTypeCode.push(participantObject.participantObjectIDTypeCode);
}
}
}
if ((audit.auditSourceIdentification != null ? audit.auditSourceIdentification.auditSourceID : undefined) && !Array.from(auditMeta.auditSourceID).includes(audit.auditSourceIdentification.auditSourceID)) {
auditMeta.auditSourceID.push(audit.auditSourceIdentification.auditSourceID);
}
auditMeta.save(err => {
if (err) {
_winston.default.error(err);
}
return callback();
});
});
}
function processAudit(msg, callback) {
if (callback == null) {
callback = function () {};
}
const parsedMsg = _glossy.Parse.parse(msg);
if (!parsedMsg || !parsedMsg.message) {
_winston.default.info('Invalid message received');
return callback();
}
parseAuditRecordFromXML(parsedMsg.message, (xmlErr, result) => {
const audit = new _audits.AuditModel(result);
audit.rawMessage = msg;
audit.syslog = parsedMsg;
delete audit.syslog.originalMessage;
delete audit.syslog.message;
return audit.save(saveErr => {
if (saveErr) {
_winston.default.error(`An error occurred while processing the audit entry: ${saveErr}`);
}
if (xmlErr) {
_winston.default.info(`Failed to parse message as an AuditMessage XML document: ${xmlErr}`);
}
processAuditMeta(audit, callback);
});
});
}
function sendUDPAudit(msg, callback) {
const client = _dgram.default.createSocket('udp4');
client.send(msg, 0, msg.length, _config.config.auditing.auditEvents.port, _config.config.auditing.auditEvents.host, err => {
client.close();
return callback(err);
});
}
const sendTLSAudit = (msg, callback) => tlsAuthentication.getServerOptions(true, (err, options) => {
if (err) {
return callback(err);
}
const client = _tls.default.connect(_config.config.auditing.auditEvents.port, _config.config.auditing.auditEvents.host, options, () => {
const {
rejectUnauthorized = true
} = options;
if (rejectUnauthorized && !client.authorized) {
return callback(client.authorizationError);
}
client.write(`${msg.length} ${msg}`);
return client.end();
});
client.resume();
client.on('error', err => _winston.default.error(err));
return client.on('close', () => callback());
});
function sendTCPAudit(msg, callback) {
const client = _net.default.connect(_config.config.auditing.auditEvents.port, _config.config.auditing.auditEvents.host, () => {
client.write(`${msg.length} ${msg}`);
return client.end();
});
client.resume();
client.on('error', err => {
if (err) {
return callback(err);
}
});
return client.on('close', () => callback());
} // Send an audit event
function sendAuditEvent(msg, callback) {
if (callback == null) {
callback = function () {};
}
function done(err) {
if (err) {
_winston.default.error(err);
}
return callback();
}
if ((_config.config.auditing != null ? _config.config.auditing.auditEvents : undefined) == null) {
return done(new Error('Unable to record audit event: Missing config.auditing.auditEvents'));
}
switch (_config.config.auditing.auditEvents.interface) {
case 'internal':
return processAudit(msg, done);
case 'udp':
return sendUDPAudit(msg, done);
case 'tls':
return sendTLSAudit(msg, done);
case 'tcp':
return sendTCPAudit(msg, done);
default:
return done(new Error(`Invalid audit event interface '${_config.config.auditing.auditEvents.interface}'`));
}
}
//# sourceMappingURL=auditing.js.map