Comparing version 0.4.0 to 0.5.0
131
index.js
@@ -5,3 +5,2 @@ 'use strict'; | ||
var os = require('os'); | ||
var fs = require('fs'); | ||
@@ -43,2 +42,25 @@ // Event Outcome Indicator | ||
// Participant Object Type Code Role | ||
exports.OBJ_TYPE_CODE_ROLE_PATIENT = 1; | ||
exports.OBJ_TYPE_CODE_ROLE_LOCATION = 2; | ||
exports.OBJ_TYPE_CODE_ROLE_REPORT = 3; | ||
exports.OBJ_TYPE_CODE_ROLE_RESOURCE = 4; | ||
exports.OBJ_TYPE_CODE_ROLE_MASTER_FILE = 5; | ||
exports.OBJ_TYPE_CODE_ROLE_USER = 6; | ||
exports.OBJ_TYPE_CODE_ROLE_LIST = 7; | ||
exports.OBJ_TYPE_CODE_ROLE_DOCTOR = 8; | ||
exports.OBJ_TYPE_CODE_ROLE_SUBSCRIBER = 9; | ||
exports.OBJ_TYPE_CODE_ROLE_GUARANTOR = 10; | ||
exports.OBJ_TYPE_CODE_ROLE_SECURITY_USER_ENTITY = 11; | ||
exports.OBJ_TYPE_CODE_ROLE_SECURITY_USER_GROUP = 12; | ||
exports.OBJ_TYPE_CODE_ROLE_SECURITY_RESOURCE = 13; | ||
exports.OBJ_TYPE_CODE_ROLE_SECURITY_GRANULARITY = 14; | ||
exports.OBJ_TYPE_CODE_ROLE_PROVIDER = 15; | ||
exports.OBJ_TYPE_CODE_ROLE_DATA_DESTINATION = 16; | ||
exports.OBJ_TYPE_CODE_ROLE_DATA_REPOSITORY = 17; | ||
exports.OBJ_TYPE_CODE_ROLE_SCHEDULE = 18; | ||
exports.OBJ_TYPE_CODE_ROLE_CUSTOMER = 19; | ||
exports.OBJ_TYPE_CODE_ROLE_JOB = 20; | ||
exports.OBJ_TYPE_CODE_ROLE_JOB_STREAM = 21; | ||
// Participant Object ID Type Code | ||
@@ -58,8 +80,11 @@ exports.OBJ_ID_TYPE_MRN = 1; | ||
function Code(code, displayName, codeSystemName) { | ||
function Code(code, originalText, codeSystemName, displayName) { | ||
this['@'] = { | ||
code: code, | ||
displayName: displayName, | ||
'csd-code': code, | ||
originalText: originalText, | ||
codeSystemName: codeSystemName | ||
}; | ||
if (displayName) { | ||
this['@'].displayName = displayName; | ||
} | ||
} | ||
@@ -72,13 +97,19 @@ Code.prototype.constructor = Code; | ||
function TypeValue(type, val) { | ||
/** | ||
* ValuePair class | ||
* | ||
* @param {String} type the type | ||
* @param {String} val the value, this will be automatically base64 encoded | ||
*/ | ||
function ValuePair(type, val) { | ||
this['@'] = { | ||
type: type, | ||
value: val | ||
value: new Buffer(val).toString('base64') | ||
}; | ||
} | ||
TypeValue.prototype.constructor = TypeValue; | ||
TypeValue.prototype.toXML = function() { | ||
return js2xml('TypeValue', this); | ||
ValuePair.prototype.constructor = ValuePair; | ||
ValuePair.prototype.toXML = function() { | ||
return js2xml('ValuePair', this); | ||
}; | ||
exports.TypeValue = TypeValue; | ||
exports.ValuePair = ValuePair; | ||
@@ -92,3 +123,5 @@ function EventIdentification(actionCode, datetime, outcome, eventID, typeCode) { | ||
this.EventID = eventID; | ||
this.EventTypeCode = typeCode; | ||
if (typeCode) { | ||
this.EventTypeCode = typeCode; | ||
} | ||
} | ||
@@ -156,5 +189,7 @@ EventIdentification.prototype.constructor = EventIdentification; | ||
AuditEnterpriseSiteID: auditEnterpriseSiteId, | ||
AuditSourceID: auditSourceId | ||
AuditSourceID: auditSourceId, | ||
code: auditSourceTypeCode['@']['csd-code'], | ||
codeSystemName: auditSourceTypeCode['@'].codeSystemName, | ||
originalText: auditSourceTypeCode['@'].originalText | ||
}; | ||
this.AuditSourceTypeCode = auditSourceTypeCode; | ||
} | ||
@@ -174,8 +209,8 @@ AuditSourceIdentification.prototype.constructor = AuditSourceIdentification; | ||
} | ||
if (participantObjs && participantObjs.lenght > 0) { | ||
this.ParticipantObjectIdentification = participantObjs; | ||
} | ||
if (auditSources && auditSources.length > 0) { | ||
this.AuditSourceIdentification = auditSources; | ||
} | ||
if (participantObjs && participantObjs.length > 0) { | ||
this.ParticipantObjectIdentification = participantObjs; | ||
} | ||
} | ||
@@ -199,3 +234,3 @@ AuditMessage.prototype.constructor = AuditMessage; | ||
var sysRoleCode = new Code(110150, 'Application', 'DCM'); | ||
var sysParticipant = new ActiveParticipant(sysname, '', true, hostname, exports.NET_AP_TYPE_DNS, [sysRoleCode]); | ||
var sysParticipant = new ActiveParticipant(sysname, '', false, hostname, exports.NET_AP_TYPE_DNS, [sysRoleCode]); | ||
@@ -227,3 +262,3 @@ var userRoleCodeDef = new Code(userRole, userRole, userRoleCode); | ||
var sysRoleCode = new Code(110150, 'Application', 'DCM'); | ||
var sysParticipant = new ActiveParticipant(sysname, '', true, hostname, exports.NET_AP_TYPE_DNS, [sysRoleCode]); | ||
var sysParticipant = new ActiveParticipant(sysname, '', false, hostname, exports.NET_AP_TYPE_DNS, [sysRoleCode]); | ||
@@ -239,1 +274,61 @@ var userRoleCodeDef = new Code(110151, 'Application Launcher', 'DCM'); | ||
}; | ||
/** | ||
* Generates a 'Audit Log Used' audit message in XML format | ||
* @param {Number} outcome the desired outcome, e.g. atna.OUTCOME_SUCCESS. | ||
* @param {String} sysname the system name of the system that generated this audit. | ||
* @param {String} hostname the hostname of the system that generated this audit. | ||
* @param {String} username the username of the person viewing the audit | ||
* @param {String} userRole the user role of the person viewing the audit | ||
* @param {String} userRoleCode the role code of the person viewing the audit | ||
* @param {String} auditLogURI a URI identifying the used audit message | ||
* @param {Object} objDetails (optional) participant object details. Should be a ValuePair object | ||
* @return {String} the xml of this audit message. | ||
*/ | ||
exports.auditLogUsedAudit = function(outcome, sysname, hostname, username, userRole, userRoleCode, auditLogURI, objDetails) { | ||
var eventID = new Code(110101, 'Audit Log Used', 'DCM'); | ||
var eIdent = new EventIdentification(exports.EVENT_ACTION_READ, new Date(), outcome, eventID, null); | ||
var sysRoleCode = new Code(110150, 'Application', 'DCM'); | ||
var sysParticipant = new ActiveParticipant(sysname, '', false, hostname, exports.NET_AP_TYPE_DNS, [sysRoleCode]); | ||
var userRoleCodeDef = new Code(userRole, userRole, userRoleCode); | ||
var userParticipant = new ActiveParticipant(username, '', true, null, null, [userRoleCodeDef]); | ||
var sourceTypeCode = new Code(exports.AUDIT_SRC_TYPE_UI, '', ''); | ||
var sourceIdent = new AuditSourceIdentification(null, sysname, sourceTypeCode); | ||
var objIdTypeCode = new Code(exports.OBJ_ID_TYPE_URI, 'URI'); | ||
var participantObj = new ParticipantObjectIdentification( | ||
auditLogURI, exports.OBJ_TYPE_SYS_OBJ, exports.OBJ_TYPE_CODE_ROLE_SECURITY_RESOURCE, null, null, objIdTypeCode, 'Security Audit Log', objDetails | ||
); | ||
var audit = new AuditMessage(eIdent, [sysParticipant, userParticipant], [participantObj], [sourceIdent]); | ||
return audit.toXML(); | ||
} | ||
/* | ||
* Generates a node authentication audit. | ||
* | ||
* @param {String} nodeIP the IP address of the node that attempted authentication. | ||
* @param {String} sysname the system name of the system that generated this audit. | ||
* @param {String} hostname the hostname of the system that generated this audit. | ||
* @param {Number} outcome the desired outcome, for authentication failure use atna.OUTCOME_MINOR_FAILURE. | ||
* @return {String} the xml of this audit message. | ||
*/ | ||
exports.nodeAuthentication = function (nodeIP, sysname, hostname, outcome) { | ||
var eventID = new Code(110113, 'Security Alert', 'DCM'); | ||
var typeCode = new Code(110126, 'Node Authentication', 'DCM'); | ||
var eIdent = new EventIdentification(exports.EVENT_ACTION_EXECUTE, new Date(), outcome, eventID, typeCode); | ||
var sysRoleCode = new Code(110150, 'Application', 'DCM'); | ||
var sysParticipant = new ActiveParticipant(sysname, '', false, hostname, exports.NET_AP_TYPE_DNS, [sysRoleCode]); | ||
var objIdTypeCode = new Code(110182, 'Node ID', 'DCM'); | ||
var nodeParticipant = new ParticipantObjectIdentification(nodeIP, 2, null, null, null, objIdTypeCode, nodeIP, null, null); | ||
var sourceTypeCode = new Code(exports.AUDIT_SRC_TYPE_WEB_SERVER, '', ''); | ||
var sourceIdent = new AuditSourceIdentification(null, sysname, sourceTypeCode); | ||
var audit = new AuditMessage(eIdent, [sysParticipant], [nodeParticipant], [sourceIdent]); | ||
return audit.toXML(); | ||
}; |
{ | ||
"name": "atna-audit", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "Assists in the creation of ATNA audit trail messages for IHE profiles.", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node test" | ||
"pretest": "npm run gen:rng", | ||
"test": "tap --cov test.js", | ||
"gen:rng": "sed 's/#.*//' dicom.rnc > temp.rnc && trang temp.rnc dicom.rng && rm temp.rnc" | ||
}, | ||
@@ -15,4 +17,4 @@ "author": "Jembi Health Systems NPC", | ||
"devDependencies": { | ||
"libxmljs": "^0.15.0", | ||
"eslint": "^1.7.3" | ||
"eslint": "^1.7.3", | ||
"tap": "^5.0.1" | ||
}, | ||
@@ -19,0 +21,0 @@ "repository": { |
@@ -1,2 +0,2 @@ | ||
[![Build Status](https://travis-ci.org/jembi/atna-audit.svg)](https://travis-ci.org/jembi/atna-audit) | ||
[![Build Status](https://travis-ci.org/jembi/atna-audit.svg)](https://travis-ci.org/jembi/atna-audit) [![codecov.io](https://codecov.io/github/jembi/atna-audit/coverage.svg?branch=master)](https://codecov.io/github/jembi/atna-audit?branch=master) | ||
@@ -35,1 +35,7 @@ # ATNA Audit Trail library | ||
``` | ||
## Testing | ||
To test the code you will need `xmllint` and `trang` on your PATH. `sudo apt-get install xmllint trang` | ||
Then run `npm test` |
71
test.js
'use strict'; | ||
var atna = require('./index'); | ||
var exec = require('child_process').exec; | ||
var fs = require('fs'); | ||
var libxml = require('libxmljs'); | ||
var atna = require('./index'); | ||
var tap = require('tap'); | ||
function validateAudit(auditXml) { | ||
var xsd = fs.readFileSync(__dirname + '/rfc-3881.xsd').toString(); | ||
var xsdDoc = libxml.parseXml(xsd); | ||
var xml = libxml.parseXml(auditXml); | ||
if (!xml.validate(xsdDoc)) { | ||
throw new Error('XML audit not valid according to XSD:\n' + xml.validationErrors); | ||
} | ||
function validateAudit(auditXml, callback) { | ||
fs.writeFileSync('test.xml', auditXml); | ||
exec('xmllint --noout --relaxng dicom.rng test.xml', function(err, stdout, stderr) { | ||
if (err) { return callback(err); } | ||
fs.unlinkSync('test.xml'); | ||
if (/test\.xml validates/.test(stderr)) { | ||
callback(null, true); | ||
} else { | ||
callback(null, false); | ||
} | ||
}); | ||
} | ||
exports.validateAudit = validateAudit; | ||
var syslog = atna.wrapInSyslog('test'); | ||
console.log(syslog); | ||
tap.test('should wrap an audit message in syslog format', function (t) { | ||
var syslog = atna.wrapInSyslog('test'); | ||
t.match(syslog, /<85>1 \S* \S* atna-audit\.js \d* IHE\+RFC-3881 - test/); | ||
t.end(); | ||
}); | ||
var audit = atna.userLoginAudit(atna.OUTCOME_SUCCESS, 'openhim', 'openhim.org', 'testUser', 'testRole', '123'); | ||
validateAudit(audit); | ||
console.log(audit); | ||
tap.test('Login audit should validate against relax ng schema', function (t) { | ||
var audit = atna.userLoginAudit(atna.OUTCOME_SUCCESS, 'openhim', 'openhim.org', 'testUser', 'testRole', '123'); | ||
validateAudit(audit, function (err, valid) { | ||
t.error(err); | ||
t.ok(valid); | ||
t.end(); | ||
}); | ||
}); | ||
audit = atna.appActivityAudit(true, 'openhim', 'openhim.org'); | ||
validateAudit(audit); | ||
console.log(audit); | ||
tap.test('App Activity audit should validate against relax ng schema', function (t) { | ||
var audit = atna.appActivityAudit(true, 'openhim', 'openhim.org'); | ||
validateAudit(audit, function (err, valid) { | ||
t.error(err); | ||
t.ok(valid); | ||
t.end(); | ||
}); | ||
}); | ||
tap.test('Audit log used audit should validate against relax ng schema', function (t) { | ||
var audit = atna.auditLogUsedAudit(atna.OUTCOME_SUCCESS, 'openhim', 'openhim.org', 'testUser', 'testRole', '123', 'localhost:8080/audits/1234', null, null); | ||
validateAudit(audit, function (err, valid) { | ||
t.error(err); | ||
t.ok(valid); | ||
t.end(); | ||
}); | ||
}); | ||
tap.test('Node authentication audit should validate against relax ng schema', function (t) { | ||
var audit = atna.nodeAuthentication('1.2.3.4', 'openhim', 'openhim.org', atna.OUTCOME_MINOR_FAILURE); | ||
validateAudit(audit, function (err, valid) { | ||
t.error(err); | ||
t.ok(valid); | ||
t.end(); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
341
41
1
25942
2