From 25343b9a75787642751d671222e5a9719355f0fb Mon Sep 17 00:00:00 2001 From: vrinda Date: Tue, 23 Oct 2018 17:30:30 +0200 Subject: [PATCH] - Mandatory UserID and Network Access Point info is missing in Destination Active Participant for Scheduler Triggered XDS Export Audit Message #1633 - Refactor #566 --- .../org/dcm4chee/arc/audit/AuditService.java | 64 ++------- .../ProvideAndRegisterAuditInfoBuilder.java | 114 --------------- .../audit/ProvideAndRegisterAuditService.java | 133 ++++++++++++++++++ 3 files changed, 141 insertions(+), 170 deletions(-) delete mode 100644 dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/ProvideAndRegisterAuditInfoBuilder.java create mode 100644 dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/ProvideAndRegisterAuditService.java diff --git a/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/AuditService.java b/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/AuditService.java index 49a3dfbdc2..6bbe9e0b93 100644 --- a/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/AuditService.java +++ b/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/AuditService.java @@ -1836,13 +1836,12 @@ private ActiveParticipantBuilder[] buildProcedureRecordActiveParticipants(AuditL } void spoolProvideAndRegister(ExportContext ctx) { - try { - ProvideAndRegisterAuditInfoBuilder provideAndRegisterInfo = new ProvideAndRegisterAuditInfoBuilder(ctx, getArchiveDevice()); - AuditInfoBuilder auditInfoBuilder = provideAndRegisterInfo.getAuditInfoBuilder(); - if (auditInfoBuilder == null) - return; + if (ctx.getXDSiManifest() == null) + return; - writeSpoolFile(AuditServiceUtils.EventType.PROV_REGIS, auditInfoBuilder); + try { + writeSpoolFile(AuditServiceUtils.EventType.PROV_REGIS, + ProvideAndRegisterAuditService.provideRegisterAuditInfo(ctx, getArchiveDevice())); } catch (Exception e) { LOG.warn("Failed to spool Provide and Register : " + e); } @@ -1851,47 +1850,9 @@ void spoolProvideAndRegister(ExportContext ctx) { private void auditProvideAndRegister(AuditLogger auditLogger, Path path, AuditServiceUtils.EventType et) { SpoolFileReader reader = new SpoolFileReader(path); AuditInfo auditInfo = new AuditInfo(reader.getMainInfo()); - EventIdentificationBuilder ei = toBuildEventIdentification(et, auditInfo.getField(AuditInfo.OUTCOME), getEventTime(path, auditLogger)); - - ActiveParticipantBuilder[] activeParticipantBuilder = buildProvideRegisterActiveParticipants(auditLogger, et, auditInfo); - - emitAuditMessage(auditLogger, ei, activeParticipantBuilder, patientPOI(auditInfo), submissionSetPOI(auditInfo)); - } - - private ActiveParticipantBuilder[] buildProvideRegisterActiveParticipants( - AuditLogger auditLogger, AuditServiceUtils.EventType et, AuditInfo ai) { - ActiveParticipantBuilder[] activeParticipantBuilder = new ActiveParticipantBuilder[3]; - activeParticipantBuilder[0] = new ActiveParticipantBuilder.Builder( - ai.getField(AuditInfo.DEST_USER_ID), - ai.getField(AuditInfo.DEST_NAP_ID)) - .userIDTypeCode(AuditMessages.UserIDTypeCode.URI) - .roleIDCode(et.destination) - .build(); - if (isServiceUserTriggered(ai.getField(AuditInfo.CALLING_USERID))) { - activeParticipantBuilder[1] = new ActiveParticipantBuilder.Builder( - ai.getField(AuditInfo.CALLED_USERID), - getLocalHostName(auditLogger)) - .userIDTypeCode(AuditMessages.UserIDTypeCode.URI) - .altUserID(AuditLogger.processID()) - .roleIDCode(et.source) - .build(); - String callingUserID = ai.getField(AuditInfo.CALLING_USERID); - activeParticipantBuilder[2] = new ActiveParticipantBuilder.Builder( - callingUserID, - ai.getField(AuditInfo.CALLING_HOST)) - .userIDTypeCode(AuditMessages.userIDTypeCode(callingUserID)) - .isRequester() - .build(); - } else - activeParticipantBuilder[1] = new ActiveParticipantBuilder.Builder( - device.getDeviceName(), - getLocalHostName(auditLogger)) - .altUserID(AuditLogger.processID()) - .userIDTypeCode(AuditMessages.UserIDTypeCode.DeviceName) - .isRequester() - .roleIDCode(et.source) - .build(); - return activeParticipantBuilder; + emitAuditMessage( + ProvideAndRegisterAuditService.provideRegisterAuditMsg(auditInfo, auditLogger, et, getEventTime(path, auditLogger)), + auditLogger); } private boolean isServiceUserTriggered(Object val) { @@ -2274,15 +2235,6 @@ private ParticipantObjectIdentificationBuilder patientPOI(AuditInfo auditInfo) { .build(); } - private ParticipantObjectIdentificationBuilder submissionSetPOI(AuditInfo auditInfo) { - return new ParticipantObjectIdentificationBuilder.Builder( - auditInfo.getField(AuditInfo.SUBMISSION_SET_UID), - AuditMessages.ParticipantObjectIDTypeCode.IHE_XDS_METADATA, - AuditMessages.ParticipantObjectTypeCode.SystemObject, - AuditMessages.ParticipantObjectTypeCodeRole.Job) - .build(); - } - private AuditMessages.UserIDTypeCode archiveUserIDTypeCode(String userID) { return userID.indexOf('/') != -1 ? AuditMessages.UserIDTypeCode.URI diff --git a/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/ProvideAndRegisterAuditInfoBuilder.java b/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/ProvideAndRegisterAuditInfoBuilder.java deleted file mode 100644 index f2960d8f1d..0000000000 --- a/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/ProvideAndRegisterAuditInfoBuilder.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * *** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is part of dcm4che, an implementation of DICOM(TM) in - * Java(TM), hosted at https://github.com/dcm4che. - * - * The Initial Developer of the Original Code is - * J4Care. - * Portions created by the Initial Developer are Copyright (C) 2017 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * See @authors listed below - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * *** END LICENSE BLOCK ***** - */ - -package org.dcm4chee.arc.audit; - -import org.dcm4che3.data.Attributes; -import org.dcm4chee.arc.conf.ArchiveDeviceExtension; -import org.dcm4chee.arc.exporter.ExportContext; -import org.dcm4chee.arc.qmgt.HttpServletRequestInfo; - -import java.net.URI; - -/** - * @author Vrinda Nayak - * @since Sep 2017 - */ - -class ProvideAndRegisterAuditInfoBuilder { - private final ExportContext ctx; - private final ArchiveDeviceExtension arcDev; - private URI dest; - private String destHost; - private String submissionSetUID; - private String outcome; - private Attributes xdsiManifest; - private HttpServletRequestInfo httpServletRequestInfo; - private AuditInfoBuilder auditInfoBuilder; - - ProvideAndRegisterAuditInfoBuilder(ExportContext ctx, ArchiveDeviceExtension arcDev) { - this.ctx = ctx; - this.arcDev = arcDev; - auditInfoBuilder = processProvideAndRegister(); - } - - private AuditInfoBuilder processProvideAndRegister() { - xdsiManifest = ctx.getXDSiManifest(); - if (xdsiManifest == null) - return null; - - dest = ctx.getExporter().getExporterDescriptor().getExportURI(); - String schemeSpecificPart = dest.getSchemeSpecificPart(); - httpServletRequestInfo = ctx.getHttpServletRequestInfo(); - destHost = schemeSpecificPart.substring(schemeSpecificPart.indexOf("://")+3, schemeSpecificPart.lastIndexOf(":")); - submissionSetUID = ctx.getSubmissionSetUID(); - outcome = buildOutcome(); - return httpServletRequestInfo != null ? restfulTriggeredProvideRegisterAuditInfo() : schedulerTriggeredProvideRegisterAuditInfo(); - } - - private AuditInfoBuilder restfulTriggeredProvideRegisterAuditInfo() { - return new AuditInfoBuilder.Builder() - .callingUserID(httpServletRequestInfo.requesterUserID) - .callingHost(httpServletRequestInfo.requesterHost) - .calledUserID(httpServletRequestInfo.requestURI) - .destUserID(dest.toString()) - .destNapID(destHost) - .outcome(outcome) - .pIDAndName(xdsiManifest, arcDev) - .submissionSetUID(submissionSetUID).build(); - } - - private AuditInfoBuilder schedulerTriggeredProvideRegisterAuditInfo() { - return new AuditInfoBuilder.Builder() - .calledUserID(dest.toString()) - .calledHost(destHost) - .outcome(outcome) - .pIDAndName(xdsiManifest, arcDev) - .submissionSetUID(submissionSetUID).build(); - } - - private String buildOutcome() { - return null != ctx.getException() ? ctx.getException().getMessage() : null; - } - - AuditInfoBuilder getAuditInfoBuilder() { - return auditInfoBuilder; - } -} diff --git a/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/ProvideAndRegisterAuditService.java b/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/ProvideAndRegisterAuditService.java new file mode 100644 index 0000000000..3d4066a0ef --- /dev/null +++ b/dcm4chee-arc-audit/src/main/java/org/dcm4chee/arc/audit/ProvideAndRegisterAuditService.java @@ -0,0 +1,133 @@ +package org.dcm4chee.arc.audit; + +import org.dcm4che3.audit.*; +import org.dcm4che3.net.audit.AuditLogger; +import org.dcm4chee.arc.conf.ArchiveDeviceExtension; +import org.dcm4chee.arc.exporter.ExportContext; +import org.dcm4chee.arc.qmgt.HttpServletRequestInfo; + +import java.net.URI; +import java.util.Calendar; + +/** + * @author Vrinda Nayak + * @since Oct 2018 + */ +class ProvideAndRegisterAuditService { + + static AuditInfoBuilder provideRegisterAuditInfo(ExportContext ctx, ArchiveDeviceExtension arcDev) { + return ctx.getHttpServletRequestInfo() != null + ? restfulTriggeredProvideRegisterAuditInfo(ctx, arcDev) + : schedulerTriggeredProvideRegisterAuditInfo(ctx, arcDev); + } + + private static AuditInfoBuilder restfulTriggeredProvideRegisterAuditInfo( + ExportContext ctx, ArchiveDeviceExtension arcDev) { + HttpServletRequestInfo httpServletRequestInfo = ctx.getHttpServletRequestInfo(); + URI destination = ctx.getExporter().getExporterDescriptor().getExportURI(); + return new AuditInfoBuilder.Builder() + .callingUserID(httpServletRequestInfo.requesterUserID) + .callingHost(httpServletRequestInfo.requesterHost) + .calledUserID(httpServletRequestInfo.requestURI) + .destUserID(destination.toString()) + .destNapID(destinationHost(destination)) + .outcome(outcome(ctx)) + .pIDAndName(ctx.getXDSiManifest(), arcDev) + .submissionSetUID(ctx.getSubmissionSetUID()).build(); + } + + private static AuditInfoBuilder schedulerTriggeredProvideRegisterAuditInfo( + ExportContext ctx, ArchiveDeviceExtension arcDev) { + URI destination = ctx.getExporter().getExporterDescriptor().getExportURI(); + return new AuditInfoBuilder.Builder() + .callingUserID(arcDev.getDevice().getDeviceName()) + .destUserID(destination.toString()) + .destNapID(destinationHost(destination)) + .outcome(outcome(ctx)) + .pIDAndName(ctx.getXDSiManifest(), arcDev) + .submissionSetUID(ctx.getSubmissionSetUID()).build(); + } + + private static String destinationHost(URI destination) { + String schemeSpecificPart = destination.getSchemeSpecificPart(); + return schemeSpecificPart.substring(schemeSpecificPart.indexOf("://") + 3, schemeSpecificPart.lastIndexOf(":")); + } + + private static String outcome(ExportContext ctx) { + return ctx.getException() != null ? ctx.getException().getMessage() : null; + } + + static AuditMessage provideRegisterAuditMsg( + AuditInfo auditInfo, AuditLogger auditLogger, AuditServiceUtils.EventType eventType, Calendar eventTime) { + String outcome = auditInfo.getField(AuditInfo.OUTCOME); + EventIdentificationBuilder eventIdentificationBuilder + = new EventIdentificationBuilder.Builder( + eventType.eventID, + eventType.eventActionCode, + eventTime, + outcome != null ? AuditMessages.EventOutcomeIndicator.MinorFailure : AuditMessages.EventOutcomeIndicator.Success) + .outcomeDesc(outcome) + .eventTypeCode(eventType.eventTypeCode).build(); + + ParticipantObjectIdentificationBuilder patientPOI = new ParticipantObjectIdentificationBuilder.Builder( + auditInfo.getField(AuditInfo.P_ID), + AuditMessages.ParticipantObjectIDTypeCode.PatientNumber, + AuditMessages.ParticipantObjectTypeCode.Person, + AuditMessages.ParticipantObjectTypeCodeRole.Patient) + .name(auditInfo.getField(AuditInfo.P_NAME)) + .build(); + + ParticipantObjectIdentificationBuilder submissionSetPOI = new ParticipantObjectIdentificationBuilder.Builder( + auditInfo.getField(AuditInfo.SUBMISSION_SET_UID), + AuditMessages.ParticipantObjectIDTypeCode.IHE_XDS_METADATA, + AuditMessages.ParticipantObjectTypeCode.SystemObject, + AuditMessages.ParticipantObjectTypeCodeRole.Job) + .build(); + + return AuditMessages.createMessage( + eventIdentificationBuilder, + activeParticipantBuilders(auditLogger, eventType, auditInfo), + patientPOI, + submissionSetPOI); + } + + private static ActiveParticipantBuilder[] activeParticipantBuilders( + AuditLogger auditLogger, AuditServiceUtils.EventType eventType, AuditInfo auditInfo) { + ActiveParticipantBuilder[] activeParticipantBuilder = new ActiveParticipantBuilder[3]; + activeParticipantBuilder[0] = new ActiveParticipantBuilder.Builder( + auditInfo.getField(AuditInfo.DEST_USER_ID), + auditInfo.getField(AuditInfo.DEST_NAP_ID)) + .userIDTypeCode(AuditMessages.UserIDTypeCode.URI) + .roleIDCode(eventType.destination) + .build(); + String callingUserID = auditInfo.getField(AuditInfo.CALLING_USERID); + if (auditInfo.getField(AuditInfo.CALLING_HOST) != null) { + activeParticipantBuilder[1] = new ActiveParticipantBuilder.Builder( + auditInfo.getField(AuditInfo.CALLED_USERID), + getLocalHostName(auditLogger)) + .userIDTypeCode(AuditMessages.UserIDTypeCode.URI) + .altUserID(AuditLogger.processID()) + .roleIDCode(eventType.source) + .build(); + activeParticipantBuilder[2] = new ActiveParticipantBuilder.Builder( + callingUserID, + auditInfo.getField(AuditInfo.CALLING_HOST)) + .userIDTypeCode(AuditMessages.userIDTypeCode(callingUserID)) + .isRequester() + .build(); + } else + activeParticipantBuilder[1] = new ActiveParticipantBuilder.Builder( + callingUserID, + getLocalHostName(auditLogger)) + .altUserID(AuditLogger.processID()) + .userIDTypeCode(AuditMessages.UserIDTypeCode.DeviceName) + .isRequester() + .roleIDCode(eventType.source) + .build(); + return activeParticipantBuilder; + } + + private static String getLocalHostName(AuditLogger auditLogger) { + return auditLogger.getConnections().get(0).getHostname(); + } +}