Skip to content

Commit

Permalink
Audit services code cleanup #3262
Browse files Browse the repository at this point in the history
  • Loading branch information
vrindanayak committed Jul 26, 2024
1 parent b60908f commit c1cf9e0
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class AuditInfo {
static final int QUEUE_NAME = 38;
static final int STATUS = 39;
static final int FHIR_WEB_APP_NAME = 40;
static final int ARCHIVE_USER_ID = 41;

private final String[] fields;

Expand Down Expand Up @@ -143,7 +144,8 @@ class AuditInfo {
encode(i.findSCP),
encode(i.queueName),
encode(i.status),
encode(i.fhirWebAppName)
encode(i.fhirWebAppName),
encode(i.archiveUserID)
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class AuditInfoBuilder {
final String queueName;
final String status;
final String fhirWebAppName;
final String archiveUserID;

static class Builder {
private String callingHost;
Expand Down Expand Up @@ -144,6 +145,7 @@ static class Builder {
private String queueName;
private String status;
private String fhirWebAppName;
private String archiveUserID;

Builder callingHost(String val) {
callingHost = val;
Expand Down Expand Up @@ -337,6 +339,10 @@ Builder fhirWebAppName(String val) {
fhirWebAppName = val;
return this;
}
Builder archiveUserID(String val) {
archiveUserID = val;
return this;
}
AuditInfoBuilder build() {
return new AuditInfoBuilder(this);
}
Expand Down Expand Up @@ -388,6 +394,7 @@ private AuditInfoBuilder(Builder builder) {
queueName = builder.queueName;
status = builder.status;
fhirWebAppName = builder.fhirWebAppName;
archiveUserID = builder.archiveUserID;
}

private static String idWithIssuer(ArchiveDeviceExtension arcDev, String cx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ private void aggregateAuditMessage(AuditLogger auditLogger, Path path) throws Ex
auditExternalRetrieve(auditLogger, path, eventType);
break;
case LDAP_CHANGES:
auditSoftwareConfiguration(auditLogger, path, eventType);
SoftwareConfigurationAuditService.audit(auditLogger, path, eventType);
break;
case QUEUE_EVENT:
TaskAuditService.audit(auditLogger, path, eventType);
Expand Down Expand Up @@ -429,27 +429,31 @@ void spoolBulkTasksEvent(BulkTaskEvent bulkTasksEvent) {
}

void spoolSoftwareConfiguration(SoftwareConfiguration softwareConfiguration) {
String callingUser = softwareConfiguration.getRequest() != null
? KeycloakContext.valueOf(softwareConfiguration.getRequest()).getUserName()
: softwareConfiguration.getDeviceName();
try {
writeSpoolFile(
SoftwareConfigurationAuditService.auditInfo(softwareConfiguration, callingUser),
AuditUtils.EventType.LDAP_CHNGS,
if (softwareConfiguration.getRequest() == null) {
writeSpoolFile(AuditUtils.EventType.LDAP_CHNGS.name(),
new AuditInfoBuilder.Builder()
.archiveUserID(softwareConfiguration.getDeviceName())
.toAuditInfo(),
softwareConfiguration.getLdapDiff().toString().getBytes());
return;
}

HttpServletRequestInfo httpServletRequestInfo = HttpServletRequestInfo.valueOf(softwareConfiguration.getRequest());
writeSpoolFile(AuditUtils.EventType.LDAP_CHNGS.name(),
new AuditInfoBuilder.Builder()
.callingUserID(httpServletRequestInfo.requesterUserID)
.callingHost(httpServletRequestInfo.requesterHost)
.calledUserID(httpServletRequestInfo.requestURI)
.archiveUserID(softwareConfiguration.getDeviceName())
.toAuditInfo(),
softwareConfiguration.getLdapDiff().toString().getBytes());
} catch (Exception e) {
LOG.info("Failed to spool Software Configuration Changes for [Device={}] done by [CallingUser={}]\n",
softwareConfiguration.getDeviceName(), callingUser, e);
LOG.info("Failed to spool Software Configuration Changes for [Device={}] \n",
softwareConfiguration.getDeviceName(), e);
}
}

private void auditSoftwareConfiguration(AuditLogger auditLogger, Path path, AuditUtils.EventType eventType)
throws Exception {
emitAuditMessage(
SoftwareConfigurationAuditService.auditMsg(auditLogger, path, eventType),
auditLogger);
}

void spoolExternalRetrieve(ExternalRetrieveContext ctx) {
try {
writeSpoolFile(AuditUtils.EventType.INST_RETRV, null,
Expand Down Expand Up @@ -1447,6 +1451,48 @@ void spoolQStarVerification(QStarVerification qStarVerification) {
}
}

//, byte[]... data
void writeSpoolFile(String fileName, AuditInfo auditInfo, byte[]... data) {
if (auditInfo == null) {
LOG.info("Attempt to write empty file : " + fileName);
return;
}

FileTime eventTime = null;
AuditLoggerDeviceExtension ext = device.getDeviceExtension(AuditLoggerDeviceExtension.class);
for (AuditLogger auditLogger : ext.getAuditLoggers()) {
if (!auditLogger.isInstalled())
continue;

try {
Path dir = toDirPath(auditLogger);
Files.createDirectories(dir);
Path filePath = Files.createTempFile(dir, fileName, null);
try (BufferedOutputStream out = new BufferedOutputStream(
Files.newOutputStream(filePath, StandardOpenOption.APPEND))) {
try (SpoolFileWriter writer = new SpoolFileWriter(Files.newBufferedWriter(
filePath, StandardCharsets.UTF_8, StandardOpenOption.APPEND))) {
writer.writeLine(auditInfo);
}
out.write(data[0]);
if (data.length > 1 && data[1].length > 0)
out.write(data[1]);
}

if (eventTime == null)
eventTime = Files.getLastModifiedTime(filePath);
else
Files.setLastModifiedTime(filePath, eventTime);

if (!getArchiveDevice().isAuditAggregate())
auditAndProcessFile(auditLogger, filePath);
} catch (Exception e) {
LOG.info("Failed to write [AuditSpoolFile={}] at [AuditLogger={}]\n",
fileName, auditLogger.getCommonName(), e);
}
}
}

void writeSpoolFile(String fileName, boolean aggregate, AuditInfo... auditInfos) {
if (auditInfos == null) {
LOG.info("Attempt to write empty file : " + fileName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,4 @@ private static ParticipantObjectDescriptionBuilder participantObjDesc(InstanceIn
.acc(instanceInfo.getAcc())
.mpps(instanceInfo.getMppsArray());
}

static ParticipantObjectIdentification softwareConfParticipant(SpoolFileReader reader, AuditInfo auditInfo) {
return new ParticipantObjectIdentificationBuilder(
auditInfo.getField(AuditInfo.CALLED_USERID),
AuditMessages.ParticipantObjectIDTypeCode.DeviceName,
AuditMessages.ParticipantObjectTypeCode.SystemObject,
null)
.detail(AuditMessages.createParticipantObjectDetail("Alert Description",
!reader.getInstanceLines().isEmpty()
? String.join("\n", reader.getInstanceLines())
: null))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,67 +39,96 @@
*/
package org.dcm4chee.arc.audit;

import jakarta.servlet.http.HttpServletRequest;
import org.dcm4che3.audit.ActiveParticipant;
import org.dcm4che3.audit.ActiveParticipantBuilder;
import org.dcm4che3.audit.AuditMessage;
import org.dcm4che3.audit.AuditMessages;
import org.dcm4che3.audit.*;
import org.dcm4che3.net.audit.AuditLogger;
import org.dcm4chee.arc.event.SoftwareConfiguration;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* @author Vrinda Nayak <[email protected]>
* @author Gunter Zeilinger <[email protected]>
* @since Oct 2018
*/
class SoftwareConfigurationAuditService {
class SoftwareConfigurationAuditService extends AuditService {

static AuditInfoBuilder auditInfo(SoftwareConfiguration softwareConfiguration, String callingUser) {
HttpServletRequest request = softwareConfiguration.getRequest();
return request != null
? buildSoftwareConfAuditForWeb(request, callingUser)
: new AuditInfoBuilder.Builder().calledUserID(callingUser).build();
static void audit(AuditLogger auditLogger, Path path, AuditUtils.EventType eventType) {
SpoolFileReader reader = new SpoolFileReader(path);
AuditInfo auditInfo = new AuditInfo(reader.getMainInfo());
EventIdentification eventIdentification = getEventIdentification(auditInfo, eventType);
eventIdentification.setEventDateTime(getEventTime(path, auditLogger));
String archiveUserID = auditInfo.getField(AuditInfo.ARCHIVE_USER_ID);
ParticipantObjectIdentification archivePOI = archive(archiveUserID);
if (auditInfo.getField(AuditInfo.CALLING_USERID) == null) {
ActiveParticipant archive = archive(archiveUserID, AuditMessages.UserIDTypeCode.DeviceName, auditLogger);
emitAuditMessage(auditLogger, eventIdentification, Collections.singletonList(archive), archivePOI);
return;
}

List<ActiveParticipant> activeParticipants = new ArrayList<>();
activeParticipants.add(archive(auditInfo.getField(AuditInfo.CALLED_USERID),
AuditMessages.UserIDTypeCode.URI,
auditLogger));
activeParticipants.add(requestor(auditInfo));
emitAuditMessage(auditLogger, eventIdentification, activeParticipants, archivePOI);
}

private static AuditInfoBuilder buildSoftwareConfAuditForWeb(HttpServletRequest request, String callingUser) {
return new AuditInfoBuilder.Builder()
.callingUserID(callingUser)
.callingHost(request.getRemoteAddr())
.calledUserID(request.getRequestURI())
.build();
private static EventIdentification getEventIdentification(AuditInfo auditInfo, AuditUtils.EventType eventType) {
String outcome = auditInfo.getField(AuditInfo.OUTCOME);
EventIdentification ei = new EventIdentification();
ei.setEventID(eventType.eventID);
ei.setEventActionCode(eventType.eventActionCode);
ei.setEventOutcomeDescription(outcome);
ei.setEventOutcomeIndicator(outcome == null
? AuditMessages.EventOutcomeIndicator.Success
: AuditMessages.EventOutcomeIndicator.MinorFailure);
ei.getEventTypeCode().add(eventType.eventTypeCode);
return ei;
}

static AuditMessage auditMsg(AuditLogger auditLogger, Path path, AuditUtils.EventType eventType) {
SpoolFileReader reader = new SpoolFileReader(path);
AuditInfo auditInfo = new AuditInfo(reader.getMainInfo());
return AuditMessages.createMessage(
EventID.toEventIdentification(auditLogger, path, eventType, auditInfo),
activeParticipants(auditLogger, auditInfo),
ParticipantObjectID.softwareConfParticipant(reader, auditInfo));
private static ParticipantObjectIdentification archive(String archiveUserID) {
ParticipantObjectIdentification archive = new ParticipantObjectIdentification();
archive.setParticipantObjectID(archiveUserID);
archive.setParticipantObjectIDTypeCode(AuditMessages.ParticipantObjectIDTypeCode.DeviceName);
archive.setParticipantObjectTypeCode(AuditMessages.ParticipantObjectTypeCode.SystemObject);
return archive;
}

private static ActiveParticipant[] activeParticipants(AuditLogger auditLogger, AuditInfo auditInfo) {
ActiveParticipant[] activeParticipants = new ActiveParticipant[2];
String callingUserID = auditInfo.getField(AuditInfo.CALLING_USERID);
String calledUserID = auditInfo.getField(AuditInfo.CALLED_USERID);
if (callingUserID != null) {
activeParticipants[0] = new ActiveParticipantBuilder(calledUserID, getLocalHostName(auditLogger))
.userIDTypeCode(AuditMessages.UserIDTypeCode.URI).build();
activeParticipants[1]
= new ActiveParticipantBuilder(callingUserID, auditInfo.getField(AuditInfo.CALLING_HOST))
.userIDTypeCode(AuditMessages.userIDTypeCode(callingUserID))
.isRequester().build();
} else
activeParticipants[0] = new ActiveParticipantBuilder(calledUserID, getLocalHostName(auditLogger))
.userIDTypeCode(AuditMessages.UserIDTypeCode.DeviceName)
.isRequester().build();
return activeParticipants;
private static ActiveParticipant archive(
String archiveUserID, AuditMessages.UserIDTypeCode archiveUserIDTypeCode, AuditLogger auditLogger) {
ActiveParticipant archive = new ActiveParticipant();
archive.setUserID(archiveUserID);
archive.setUserIDTypeCode(archiveUserIDTypeCode);
archive.setAlternativeUserID(AuditLogger.processID());
archive.setUserTypeCode(AuditMessages.UserTypeCode.Application);
archive.setUserIsRequestor(archiveUserIDTypeCode == AuditMessages.UserIDTypeCode.DeviceName);
String auditLoggerHostName = auditLogger.getConnections().get(0).getHostname();
archive.setNetworkAccessPointID(auditLoggerHostName);
archive.setNetworkAccessPointTypeCode(
AuditMessages.isIP(auditLoggerHostName)
? AuditMessages.NetworkAccessPointTypeCode.IPAddress
: AuditMessages.NetworkAccessPointTypeCode.MachineName);
return archive;
}

private static String getLocalHostName(AuditLogger auditLogger) {
return auditLogger.getConnections().get(0).getHostname();
private static ActiveParticipant requestor(AuditInfo auditInfo) {
String requestorID = auditInfo.getField(AuditInfo.CALLING_USERID);
String requestorHost = auditInfo.getField(AuditInfo.CALLING_HOST);
ActiveParticipant requestor = new ActiveParticipant();
requestor.setUserID(requestorID);
requestor.setUserIDTypeCode(
AuditMessages.isIP(requestorID)
? AuditMessages.UserIDTypeCode.NodeID
: AuditMessages.UserIDTypeCode.PersonID);
requestor.setUserIsRequestor(true);
requestor.setNetworkAccessPointID(requestorHost);
requestor.setNetworkAccessPointTypeCode(
AuditMessages.isIP(requestorHost)
? AuditMessages.NetworkAccessPointTypeCode.IPAddress
: AuditMessages.NetworkAccessPointTypeCode.MachineName);
return requestor;
}

}

0 comments on commit c1cf9e0

Please sign in to comment.