Skip to content

Commit

Permalink
Emit Audit Message on failed attempts to initiate association to a re…
Browse files Browse the repository at this point in the history
…mote AE #1565

Emit Audit Message on rejection of an association request from a remote AE #1564
  • Loading branch information
vrindanayak committed Oct 23, 2018
1 parent b90f7d2 commit 0fb3bc1
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.dcm4chee.arc.audit;

import org.dcm4che3.audit.*;
import org.dcm4che3.net.Association;
import org.dcm4che3.util.ReverseDNS;
import org.dcm4chee.arc.AssociationEvent;
import java.util.Calendar;

/**
* @author Vrinda Nayak <vrinda.nayak@j4care.com>
* @since Oct 2018
*/
class AssociationEventsAuditService {

static AuditInfoBuilder associationFailureAuditInfo(AssociationEvent associationEvent) {
return associationEvent.getType() == AssociationEvent.Type.FAILED
? associationFailedAuditInfo(associationEvent) : associationRejectAuditInfo(associationEvent);
}

private static AuditInfoBuilder associationFailedAuditInfo(AssociationEvent associationEvent) {
Association association = associationEvent.getAssociation();
return new AuditInfoBuilder.Builder()
.callingUserID(association.getLocalAET())
.callingHost(association.getConnection().getHostname())
.calledUserID(association.getRemoteAET())
.calledHost(ReverseDNS.hostNameOf(association.getSocket().getInetAddress()))
.outcome(associationEvent.getException().getMessage())
.build();
}

private static AuditInfoBuilder associationRejectAuditInfo(AssociationEvent associationEvent) {
Association association = associationEvent.getAssociation();
return new AuditInfoBuilder.Builder()
.callingUserID(association.getRemoteAET())
.callingHost(ReverseDNS.hostNameOf(association.getSocket().getInetAddress()))
.calledUserID(association.getLocalAET())
.calledHost(association.getConnection().getHostname())
.outcome(associationEvent.getException().getMessage())
.build();
}

static AuditMessage associationFailureAuditMsg(
AuditInfo auditInfo, AuditServiceUtils.EventType eventType, Calendar eventTime) {
EventIdentificationBuilder eventIdentificationBuilder = new EventIdentificationBuilder.Builder(
eventType.eventID, eventType.eventActionCode, eventTime, AuditMessages.EventOutcomeIndicator.MinorFailure)
.outcomeDesc(auditInfo.getField(AuditInfo.OUTCOME))
.eventTypeCode(eventType.eventTypeCode)
.build();

ActiveParticipantBuilder[] activeParticipantBuilders = new ActiveParticipantBuilder[2];
activeParticipantBuilders[0] = new ActiveParticipantBuilder.Builder(
auditInfo.getField(AuditInfo.CALLING_USERID), auditInfo.getField(AuditInfo.CALLING_HOST))
.userIDTypeCode(AuditMessages.UserIDTypeCode.StationAETitle)
.isRequester()
.build();
activeParticipantBuilders[1] = new ActiveParticipantBuilder.Builder(
auditInfo.getField(AuditInfo.CALLED_USERID), auditInfo.getField(AuditInfo.CALLED_HOST))
.userIDTypeCode(AuditMessages.UserIDTypeCode.StationAETitle)
.build();

return AuditMessages.createMessage(eventIdentificationBuilder, activeParticipantBuilders);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import org.dcm4che3.net.service.DicomServiceException;
import org.dcm4che3.util.ReverseDNS;
import org.dcm4che3.util.StringUtils;
import org.dcm4chee.arc.AssociationEvent;
import org.dcm4chee.arc.HL7ConnectionEvent;
import org.dcm4chee.arc.conf.*;
import org.dcm4chee.arc.event.ArchiveServiceEvent;
Expand Down Expand Up @@ -167,6 +168,9 @@ private void aggregateAuditMessage(AuditLogger auditLogger, Path path) {
case IMPAX:
auditPatientMismatch(auditLogger, path, eventType);
break;
case ASSOCIATION_FAILURE:
auditAssociationFailure(auditLogger, path, eventType);
break;
}
} catch (Exception e) {
LOG.warn("Failed in audit : " + e);
Expand Down Expand Up @@ -2045,6 +2049,20 @@ private SOPClass[] toSOPClasses(HashMap<String, HashSet<String>> sopClassMap, bo
return sopClasses;
}

void spoolAssociationFailure(AssociationEvent associationEvent) {
writeSpoolFile(
AuditServiceUtils.EventType.ASSOC_FAIL,
AssociationEventsAuditService.associationFailureAuditInfo(associationEvent));
}

private void auditAssociationFailure(AuditLogger auditLogger, Path path, AuditServiceUtils.EventType et) {
SpoolFileReader reader = new SpoolFileReader(path);
AuditInfo auditInfo = new AuditInfo(reader.getMainInfo());
emitAuditMessage(
AssociationEventsAuditService.associationFailureAuditMsg(auditInfo, et, getEventTime(path, auditLogger)),
auditLogger);
}

private String outcome(Exception e) {
return e != null ? e.getMessage() : null;
}
Expand Down Expand Up @@ -2222,6 +2240,15 @@ private void emitAuditMessage(
}
}

private void emitAuditMessage(AuditMessage msg, AuditLogger logger) {
msg.getAuditSourceIdentification().add(logger.createAuditSourceIdentification());
try {
logger.write(logger.timeStamp(), msg);
} catch (Exception e) {
LOG.warn("Failed to emit audit message", logger.getCommonName(), e);
}
}

private EventIdentificationBuilder toCustomBuildEventIdentification(AuditServiceUtils.EventType et, String failureDesc, String warningDesc, Calendar t) {
return failureDesc != null
? toBuildEventIdentification(et, failureDesc, t)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class AuditServiceUtils {

enum EventClass {
QUERY, USER_DELETED, SCHEDULER_DELETED, STORE_WADOR, CONN_REJECT, RETRIEVE, APPLN_ACTIVITY, HL7, PROC_STUDY, PROV_REGISTER,
STGCMT, INST_RETRIEVED, LDAP_CHANGES, QUEUE_EVENT, IMPAX
STGCMT, INST_RETRIEVED, LDAP_CHANGES, QUEUE_EVENT, IMPAX, ASSOCIATION_FAILURE
}
enum EventType {
WADO___URI(EventClass.STORE_WADOR, AuditMessages.EventID.DICOMInstancesTransferred, AuditMessages.EventActionCode.Read,
Expand Down Expand Up @@ -136,6 +136,9 @@ enum EventType {
IMPAX_MISM(EventClass.IMPAX, AuditMessages.EventID.SecurityAlert, AuditMessages.EventActionCode.Execute,
null, null, null),

ASSOC_FAIL(EventClass.ASSOCIATION_FAILURE, AuditMessages.EventID.SecurityAlert, AuditMessages.EventActionCode.Execute,
null, null, AuditMessages.EventTypeCode.AssociationFailure),

CANCEL_TSK(EventClass.QUEUE_EVENT, AuditMessages.EventID.SecurityAlert, AuditMessages.EventActionCode.Execute,
null, null, AuditMessages.EventTypeCode.CancelTask),
RESCHD_TSK(EventClass.QUEUE_EVENT, AuditMessages.EventID.SecurityAlert, AuditMessages.EventActionCode.Execute,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.dcm4che3.audit.AuditMessages;
import org.dcm4che3.net.Device;
import org.dcm4che3.net.audit.AuditLoggerDeviceExtension;
import org.dcm4chee.arc.AssociationEvent;
import org.dcm4chee.arc.HL7ConnectionEvent;
import org.dcm4chee.arc.event.ArchiveServiceEvent;
import org.dcm4chee.arc.ConnectionEvent;
Expand Down Expand Up @@ -189,6 +190,20 @@ public void onHL7Message(@Observes HL7ConnectionEvent hl7ConnectionEvent) {
auditService.spoolHL7Message(hl7ConnectionEvent);
}

public void onAssociation(@Observes AssociationEvent associationEvent) {
if (deviceHasAuditLoggers()) {
switch (associationEvent.getType()) {
case ACCEPTED:
case ESTABLISHED:
break;
case FAILED:
case REJECTED:
auditService.spoolAssociationFailure(associationEvent);
break;
}
}
}

private boolean deviceHasAuditLoggers() {
AuditLoggerDeviceExtension ext = device.getDeviceExtension(AuditLoggerDeviceExtension.class);
return ext != null && !ext.getAuditLoggers().isEmpty();
Expand Down

0 comments on commit 0fb3bc1

Please sign in to comment.