updated IResourceAuditor interface

This commit is contained in:
lmds1 2014-11-10 18:09:11 -05:00
parent 025db56fe9
commit 5f3a366ab0
10 changed files with 193 additions and 90 deletions

View File

@ -38,20 +38,24 @@ public class UserInfoInterceptor implements IClientInterceptor {
public static final String HEADER_USER_ID = "fhir-user-id"; public static final String HEADER_USER_ID = "fhir-user-id";
public static final String HEADER_USER_NAME = "fhir-user-name"; public static final String HEADER_USER_NAME = "fhir-user-name";
public static final String HEADER_APPLICATION_NAME = "fhir-app-name";
private String myUserId; private String myUserId;
private String myUserName; private String myUserName;
private String myAppName;
public UserInfoInterceptor(String theUserId, String theUserName) { public UserInfoInterceptor(String theUserId, String theUserName, String theAppName) {
super(); super();
myUserId = theUserId; myUserId = theUserId;
myUserName = theUserName; myUserName = theUserName;
myAppName = theAppName;
} }
@Override @Override
public void interceptRequest(HttpRequestBase theRequest) { public void interceptRequest(HttpRequestBase theRequest) {
if(myUserId != null) theRequest.addHeader(HEADER_USER_ID, myUserId); if(myUserId != null) theRequest.addHeader(HEADER_USER_ID, myUserId);
if(myUserName != null) theRequest.addHeader(HEADER_USER_NAME, myUserName); if(myUserName != null) theRequest.addHeader(HEADER_USER_NAME, myUserName);
if(myAppName != null) theRequest.addHeader(HEADER_APPLICATION_NAME, myAppName);
} }
@Override @Override

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.rest.server.audit;
* #L% * #L%
*/ */
import java.util.List; import java.util.Map;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt; import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
@ -29,17 +29,53 @@ import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
public interface IResourceAuditor<T extends IResource> { public interface IResourceAuditor<T extends IResource> {
/**
* @return the resource to be audited
*/
public T getResource(); public T getResource();
/**
* @param resource the resource to be audited by this auditor
*/
public void setResource(T resource); public void setResource(T resource);
/**
* @return true if this resource is to be audited, false otherwise
*/
public boolean isAuditable(); public boolean isAuditable();
/**
* An instance-specific descriptor of the Participant Object ID audited, such as a person's name
* @return the descriptive name of the resource object
*/
public String getName(); public String getName();
/**
* @return the identifier of the resource to be audited
*/
public BaseIdentifierDt getIdentifier(); public BaseIdentifierDt getIdentifier();
/**
* @return the SecurityEventObjectTypeEnum of this resource
*/
public SecurityEventObjectTypeEnum getType(); public SecurityEventObjectTypeEnum getType();
/**
* @return a text description of the resource
*/
public String getDescription(); public String getDescription();
//public List<ObjectDetail> getDetail(); //see operationoutcome -- need to move specifics insto dstu and keep base objects in core
/**
* @return a map of additional details to be audited
*/
public Map<String, String> getDetail();
/**
* Denotes policy-defined sensitivity for the Participant Object ID such as VIP, HIV status, mental health status or similar topics
* @return the sensitivity of this resource
*/
public SecurityEventObjectSensitivityEnum getSensitivity(); public SecurityEventObjectSensitivityEnum getSensitivity();
} }

View File

@ -20,12 +20,11 @@ package ca.uhn.fhir.rest.server.audit;
* #L% * #L%
*/ */
import java.util.ArrayList; import java.util.HashMap;
import java.util.List; import java.util.Map;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt; import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport; import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ObjectDetail;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
@ -41,7 +40,7 @@ public class DiagnosticReportAuditor implements IResourceAuditor<DiagnosticRepor
@Override @Override
public String getName() { public String getName() {
if(myDiagnosticReport != null){ if(myDiagnosticReport != null){
return myDiagnosticReport.getName().getText().getValue(); return "Diagnostic Report: " + myDiagnosticReport.getName().getText().getValue();
} }
return null; return null;
} }
@ -75,25 +74,15 @@ public class DiagnosticReportAuditor implements IResourceAuditor<DiagnosticRepor
} }
@Override @Override
public List<ObjectDetail> getDetail() { public Map<String, String> getDetail() {
List<ObjectDetail> details = new ArrayList<ObjectDetail>(); Map<String, String> details = new HashMap<String, String>();
details.add(makeObjectDetail("dateIssued", myDiagnosticReport.getIssued().getValueAsString())); details.put("dateIssued", myDiagnosticReport.getIssued().getValueAsString());
details.add(makeObjectDetail("version", myDiagnosticReport.getId().getVersionIdPart())); details.put("version", myDiagnosticReport.getId().getVersionIdPart());
return details; return details;
} }
@Override @Override
public SecurityEventObjectSensitivityEnum getSensitivity() { public SecurityEventObjectSensitivityEnum getSensitivity() {
return null; //no sensitivity indicated return null; //no sensitivity indicated
} }
private ObjectDetail makeObjectDetail(String type, String value) {
ObjectDetail detail = new ObjectDetail();
if(type != null)
detail.setType(type);
if(value != null)
detail.setValue(value.getBytes());
return detail;
}
} }

View File

@ -20,12 +20,11 @@ package ca.uhn.fhir.rest.server.audit;
* #L% * #L%
*/ */
import java.util.ArrayList; import java.util.HashMap;
import java.util.List; import java.util.Map;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt; import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Encounter; import ca.uhn.fhir.model.dstu.resource.Encounter;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ObjectDetail;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
@ -54,7 +53,7 @@ public class EncounterAuditor implements IResourceAuditor<Encounter> {
String id = myEncounter.getIdentifierFirstRep().getValue().getValue(); String id = myEncounter.getIdentifierFirstRep().getValue().getValue();
String system = myEncounter.getIdentifierFirstRep().getSystem().getValueAsString(); String system = myEncounter.getIdentifierFirstRep().getSystem().getValueAsString();
String service = myEncounter.getServiceProvider().getDisplay().getValue(); String service = myEncounter.getServiceProvider().getDisplay().getValue();
return id + "/" + system + ": " + service; return "Encounter: " + id + "/" + system + ": " + service;
} }
return null; return null;
} }
@ -79,31 +78,22 @@ public class EncounterAuditor implements IResourceAuditor<Encounter> {
String status = myEncounter.getStatus().getValueAsString(); String status = myEncounter.getStatus().getValueAsString();
String startDate = myEncounter.getPeriod().getStart().getValueAsString(); String startDate = myEncounter.getPeriod().getStart().getValueAsString();
String endDate = myEncounter.getPeriod().getEnd().getValueAsString(); String endDate = myEncounter.getPeriod().getEnd().getValueAsString();
return type + ": " + status +", "+ startDate + " - " + endDate; return "Encounter: " + type + ": " + status +", "+ startDate + " - " + endDate;
} }
return null; return null;
} }
@Override @Override
public List<ObjectDetail> getDetail() { public Map<String, String> getDetail() {
List<ObjectDetail> details = new ArrayList<ObjectDetail>(); Map<String, String> details = new HashMap<String, String>();
details.add(makeObjectDetail("startDate", myEncounter.getPeriod().getStart().getValueAsString())); details.put("startDate", myEncounter.getPeriod().getStart().getValueAsString());
details.add(makeObjectDetail("endDate", myEncounter.getPeriod().getEnd().getValueAsString())); details.put("endDate", myEncounter.getPeriod().getEnd().getValueAsString());
details.add(makeObjectDetail("service", myEncounter.getServiceProvider().getDisplay().getValue())); details.put("service", myEncounter.getServiceProvider().getDisplay().getValue());
details.add(makeObjectDetail("type", myEncounter.getTypeFirstRep().getText().getValue())); details.put("type", myEncounter.getTypeFirstRep().getText().getValue());
details.add(makeObjectDetail("status", myEncounter.getStatus().getValueAsString())); details.put("status", myEncounter.getStatus().getValueAsString());
return details; return details;
} }
private ObjectDetail makeObjectDetail(String type, String value) {
ObjectDetail detail = new ObjectDetail();
if(type != null)
detail.setType(type);
if(value != null)
detail.setValue(value.getBytes());
return detail;
}
@Override @Override
public SecurityEventObjectSensitivityEnum getSensitivity() { public SecurityEventObjectSensitivityEnum getSensitivity() {
//override this method to provide sensitivity information about the visit //override this method to provide sensitivity information about the visit

View File

@ -20,12 +20,11 @@ package ca.uhn.fhir.rest.server.audit;
* #L% * #L%
*/ */
import java.util.List; import java.util.Map;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt; import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Medication; import ca.uhn.fhir.model.dstu.resource.Medication;
import ca.uhn.fhir.model.dstu.resource.MedicationPrescription; import ca.uhn.fhir.model.dstu.resource.MedicationPrescription;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ObjectDetail;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
@ -44,10 +43,10 @@ public class MedicationPrescriptionAuditor implements IResourceAuditor<Medicatio
if(myMedicationPrescription.getMedication() != null){ if(myMedicationPrescription.getMedication() != null){
Medication m = (Medication) myMedicationPrescription.getMedication().getResource(); Medication m = (Medication) myMedicationPrescription.getMedication().getResource();
if(m != null){ if(m != null){
return m.getName().getValue(); return "Medication Prescription: " + m.getName().getValue();
} }
} }
return myMedicationPrescription.getId().getValueAsString(); //if we don't have a medication name, use the id as the name return "Medication Prescription: " + myMedicationPrescription.getId().getValueAsString(); //if we don't have a medication name, use the id as the name
} }
return ""; //no medication prescription, nothing to do here return ""; //no medication prescription, nothing to do here
} }
@ -81,7 +80,7 @@ public class MedicationPrescriptionAuditor implements IResourceAuditor<Medicatio
} }
@Override @Override
public List<ObjectDetail> getDetail() { public Map<String, String> getDetail() {
return null; //no additional details required for audit? return null; //no additional details required for audit?
} }

View File

@ -20,12 +20,11 @@ package ca.uhn.fhir.rest.server.audit;
* #L% * #L%
*/ */
import java.util.List; import java.util.Map;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt; import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Medication; import ca.uhn.fhir.model.dstu.resource.Medication;
import ca.uhn.fhir.model.dstu.resource.MedicationStatement; import ca.uhn.fhir.model.dstu.resource.MedicationStatement;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ObjectDetail;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
@ -43,9 +42,9 @@ public class MedicationStatementAuditor implements IResourceAuditor<MedicationSt
if(myMedicationStatement != null){ if(myMedicationStatement != null){
Medication m = (Medication) myMedicationStatement.getMedication().getResource(); Medication m = (Medication) myMedicationStatement.getMedication().getResource();
if(m != null){ if(m != null){
return m.getName().getValue(); return "Medication Statement: " + m.getName().getValue();
} }
return myMedicationStatement.getId().getValueAsString(); //if we don't have a medication name, use the id as the name return "Medication Statement: " + myMedicationStatement.getId().getValueAsString(); //if we don't have a medication name, use the id as the name
} }
return null; return null;
} }
@ -79,7 +78,7 @@ public class MedicationStatementAuditor implements IResourceAuditor<MedicationSt
} }
@Override @Override
public List<ObjectDetail> getDetail() { public Map<String, String> getDetail() {
return null; //no additional details required for audit? return null; //no additional details required for audit?
} }

View File

@ -20,13 +20,12 @@ package ca.uhn.fhir.rest.server.audit;
* #L% * #L%
*/ */
import java.io.UnsupportedEncodingException; import java.util.HashMap;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt; import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Patient; import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ObjectDetail;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectSensitivityEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
@ -52,7 +51,7 @@ public class PatientAuditor implements IResourceAuditor<Patient> {
@Override @Override
public String getName() { public String getName() {
if(myPatient != null){ if(myPatient != null){
return myPatient.getNameFirstRep().getText().getValue(); return "Patient: " + myPatient.getNameFirstRep().getText().getValue();
} }
return null; return null;
} }
@ -76,22 +75,17 @@ public class PatientAuditor implements IResourceAuditor<Patient> {
} }
@Override @Override
public List<ObjectDetail> getDetail() { public Map<String, String> getDetail() {
if(myPatient != null){ if(myPatient != null){
List<IdentifierDt> ids = myPatient.getIdentifier(); List<IdentifierDt> ids = myPatient.getIdentifier();
if(ids != null && !ids.isEmpty()){ if(ids != null && !ids.isEmpty()){
List<ObjectDetail> detailList = new ArrayList<ObjectDetail>(ids.size()); Map<String, String> detailMap = new HashMap<String, String>();
for(IdentifierDt id: ids){ for(IdentifierDt id: ids){
ObjectDetail detail = new ObjectDetail(); String key = id.getSystem().getValueAsString();
detail.setType(id.getSystem().getValueAsString()); String value = id.getValue().getValueAsString();
try { detailMap.put(key, value);
detail.setValue(id.getValue().getValueAsString().getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
detail.setValue(id.getValue().getValueAsString().getBytes());
}
detailList.add(detail);
} }
return detailList; return detailMap;
} }
} }

View File

@ -26,6 +26,7 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -35,19 +36,23 @@ import org.apache.commons.lang3.NotImplementedException;
import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry; import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent; import ca.uhn.fhir.model.dstu.resource.SecurityEvent;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.Event; import ca.uhn.fhir.model.dstu.resource.SecurityEvent.Event;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ObjectDetail;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ObjectElement; import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ObjectElement;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.Participant; import ca.uhn.fhir.model.dstu.resource.SecurityEvent.Participant;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ParticipantNetwork; import ca.uhn.fhir.model.dstu.resource.SecurityEvent.ParticipantNetwork;
import ca.uhn.fhir.model.dstu.resource.SecurityEvent.Source; import ca.uhn.fhir.model.dstu.resource.SecurityEvent.Source;
import ca.uhn.fhir.model.dstu.valueset.ResourceTypeEnum;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum; import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventActionEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventActionEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectLifecycleEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectLifecycleEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventOutcomeEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventOutcomeEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventParticipantNetworkTypeEnum; import ca.uhn.fhir.model.dstu.valueset.SecurityEventParticipantNetworkTypeEnum;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventSourceTypeEnum;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.client.interceptor.UserInfoInterceptor; import ca.uhn.fhir.rest.client.interceptor.UserInfoInterceptor;
import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
@ -68,12 +73,20 @@ public class AuditingInterceptor extends InterceptorAdapter {
private IAuditDataStore myDataStore = null; private IAuditDataStore myDataStore = null;
private Map<String, Class<? extends IResourceAuditor<? extends IResource>>> myAuditableResources = new HashMap<String, Class<? extends IResourceAuditor<? extends IResource>>>(); private Map<String, Class<? extends IResourceAuditor<? extends IResource>>> myAuditableResources = new HashMap<String, Class<? extends IResourceAuditor<? extends IResource>>>();
private boolean myClientParamsOptional = false; private boolean myClientParamsOptional = false;
protected String mySiteId;
public AuditingInterceptor() { public AuditingInterceptor() {
myClientParamsOptional = false; mySiteId = "NONE";
myClientParamsOptional = false;
} }
public AuditingInterceptor(boolean theClientParamsOptional){ public AuditingInterceptor(String theSiteId) {
mySiteId = theSiteId;
myClientParamsOptional = false;
}
public AuditingInterceptor(String theSiteId, boolean theClientParamsOptional){
mySiteId = theSiteId;
myClientParamsOptional = theClientParamsOptional; myClientParamsOptional = theClientParamsOptional;
} }
@ -91,8 +104,14 @@ public class AuditingInterceptor extends InterceptorAdapter {
auditEvent.setEvent(getEventInfo(theRequestDetails)); auditEvent.setEvent(getEventInfo(theRequestDetails));
//get user info from request if available //get user info from request if available
Participant participant = getParticipant(theServletRequest); Participant participant = getParticipant(theServletRequest);
if(participant == null) return true; //no user to audit - throws exception if client params are required if(participant == null){
log.debug("No participant to audit");
return true; //no user to audit - throws exception if client params are required
}
List<Participant> participants = new ArrayList<SecurityEvent.Participant>(1);
participants.add(participant);
auditEvent.setParticipant(participants);
SecurityEventObjectLifecycleEnum lifecycle = mapResourceTypeToSecurityLifecycle(theRequestDetails.getResourceOperationType()); SecurityEventObjectLifecycleEnum lifecycle = mapResourceTypeToSecurityLifecycle(theRequestDetails.getResourceOperationType());
byte[] query = getQueryFromRequestDetails(theRequestDetails); byte[] query = getQueryFromRequestDetails(theRequestDetails);
List<ObjectElement> auditableObjects = new ArrayList<SecurityEvent.ObjectElement>(); List<ObjectElement> auditableObjects = new ArrayList<SecurityEvent.ObjectElement>();
@ -101,8 +120,14 @@ public class AuditingInterceptor extends InterceptorAdapter {
ObjectElement auditableObject = getObjectElement(resource, lifecycle , query); ObjectElement auditableObject = getObjectElement(resource, lifecycle , query);
if(auditableObject != null) auditableObjects.add(auditableObject); if(auditableObject != null) auditableObjects.add(auditableObject);
} }
if(!auditableObjects.isEmpty()) return true; //no PHI to audit if(auditableObjects.isEmpty()){
log.debug("No auditable resources to audit.");
return true; //no PHI to audit
}else{
log.debug("Auditing " + auditableObjects.size() + " resources.");
}
auditEvent.setObject(auditableObjects); auditEvent.setObject(auditableObjects);
auditEvent.setSource(getSourceElement(theServletRequest));
store(auditEvent); store(auditEvent);
return true; //success return true; //success
}catch(Exception e){ }catch(Exception e){
@ -126,15 +151,26 @@ public class AuditingInterceptor extends InterceptorAdapter {
//get user info from request if available //get user info from request if available
Participant participant = getParticipant(theServletRequest); Participant participant = getParticipant(theServletRequest);
if(participant == null) return true; //no user to audit - throws exception if client params are required if(participant == null){
log.debug("No participant to audit");
return true; //no user to audit - throws exception if client params are required
}
List<Participant> participants = new ArrayList<SecurityEvent.Participant>(1);
participants.add(participant);
auditEvent.setParticipant(participants);
byte[] query = getQueryFromRequestDetails(theRequestDetails); byte[] query = getQueryFromRequestDetails(theRequestDetails);
SecurityEventObjectLifecycleEnum lifecycle = mapResourceTypeToSecurityLifecycle(theRequestDetails.getResourceOperationType()); SecurityEventObjectLifecycleEnum lifecycle = mapResourceTypeToSecurityLifecycle(theRequestDetails.getResourceOperationType());
ObjectElement auditableObject = getObjectElement(theResponseObject, lifecycle , query); ObjectElement auditableObject = getObjectElement(theResponseObject, lifecycle , query);
if(auditableObject == null) return true; //nothing to audit if(auditableObject == null){
log.debug("No auditable resources to audit");
return true;
}
List<ObjectElement> auditableObjects = new ArrayList<SecurityEvent.ObjectElement>(1); List<ObjectElement> auditableObjects = new ArrayList<SecurityEvent.ObjectElement>(1);
auditableObjects.add(auditableObject); auditableObjects.add(auditableObject);
auditEvent.setObject(auditableObjects); auditEvent.setObject(auditableObjects);
auditEvent.setSource(getSourceElement(theServletRequest));
log.debug("Auditing one resource.");
store(auditEvent); store(auditEvent);
return true; return true;
}catch(Exception e){ }catch(Exception e){
@ -143,7 +179,6 @@ public class AuditingInterceptor extends InterceptorAdapter {
} }
} }
protected void store(SecurityEvent auditEvent) throws Exception { protected void store(SecurityEvent auditEvent) throws Exception {
if(myDataStore == null) throw new InternalErrorException("No data store provided to persist audit events"); if(myDataStore == null) throw new InternalErrorException("No data store provided to persist audit events");
myDataStore.store(auditEvent); myDataStore.store(auditEvent);
@ -182,7 +217,8 @@ public class AuditingInterceptor extends InterceptorAdapter {
protected ObjectElement getObjectElement(IResource resource, SecurityEventObjectLifecycleEnum lifecycle, byte[] query) throws InstantiationException, IllegalAccessException { protected ObjectElement getObjectElement(IResource resource, SecurityEventObjectLifecycleEnum lifecycle, byte[] query) throws InstantiationException, IllegalAccessException {
String resourceType = resource.getResourceName(); String resourceType = resource.getResourceName();
if(myAuditableResources.containsKey(resourceType)){ if(myAuditableResources.containsKey(resourceType)){
log.debug("Found auditable resource of type: " + resourceType);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
IResourceAuditor<IResource> auditableResource = (IResourceAuditor<IResource>) myAuditableResources.get(resourceType).newInstance(); IResourceAuditor<IResource> auditableResource = (IResourceAuditor<IResource>) myAuditableResources.get(resourceType).newInstance();
auditableResource.setResource(resource); auditableResource.setResource(resource);
@ -192,19 +228,44 @@ public class AuditingInterceptor extends InterceptorAdapter {
object.setLifecycle(lifecycle); object.setLifecycle(lifecycle);
object.setQuery(query); object.setQuery(query);
object.setName(auditableResource.getName()); object.setName(auditableResource.getName());
object.setIdentifier(auditableResource.getIdentifier()); object.setIdentifier((IdentifierDt) auditableResource.getIdentifier());
object.setType(auditableResource.getType()); object.setType(auditableResource.getType());
object.setDescription(auditableResource.getDescription()); object.setDescription(auditableResource.getDescription());
object.setDetail(auditableResource.getDetail()); Map<String, String> detailMap = auditableResource.getDetail();
object.setSensitivity(auditableResource.getSensitivity()); if(detailMap != null && !detailMap.isEmpty()){
List<ObjectDetail> details = new ArrayList<SecurityEvent.ObjectDetail>();
for(Entry<String, String> entry: detailMap.entrySet()){
ObjectDetail detail = makeObjectDetail(entry.getKey(), entry.getValue());
details.add(detail);
}
object.setDetail(details);
}
object.setSensitivity(auditableResource.getSensitivity());
return object; return object;
} }else{
} log.debug("Resource is not auditable");
}
}else{
log.debug("No auditor configured for resource type " + resourceType);
}
return null; //not something we care to audit return null; //not something we care to audit
} }
protected ObjectDetail makeObjectDetail(String type, String value) {
ObjectDetail detail = new ObjectDetail();
if(type != null)
detail.setType(type);
if(value != null)
detail.setValue(value.getBytes());
return detail;
}
protected Participant getParticipant(HttpServletRequest theServletRequest) throws InvalidRequestException, NotImplementedException { protected Participant getParticipant(HttpServletRequest theServletRequest) throws InvalidRequestException, NotImplementedException {
if(theServletRequest.getHeader(Constants.HEADER_AUTHORIZATION) != null && theServletRequest.getHeader(Constants.HEADER_AUTHORIZATION).startsWith("OAuth")){ if(theServletRequest.getHeader(Constants.HEADER_AUTHORIZATION) != null && theServletRequest.getHeader(Constants.HEADER_AUTHORIZATION).startsWith("OAuth")){
if(myClientParamsOptional){
log.debug("OAuth request received but no auditing required.");
return null;
}
//TODO: get user info from token //TODO: get user info from token
throw new NotImplementedException("OAuth user auditing not yet implemented."); throw new NotImplementedException("OAuth user auditing not yet implemented.");
}else { //no auth or basic auth or anything else, use HTTP headers for user info }else { //no auth or basic auth or anything else, use HTTP headers for user info
@ -224,7 +285,38 @@ public class AuditingInterceptor extends InterceptorAdapter {
network.setIdentifier(userIp); network.setIdentifier(userIp);
return participant; return participant;
} }
}
protected Source getSourceElement(HttpServletRequest theServletRequest) {
if(theServletRequest.getHeader(Constants.HEADER_AUTHORIZATION) != null && theServletRequest.getHeader(Constants.HEADER_AUTHORIZATION).startsWith("OAuth")){
if(myClientParamsOptional) return null; //no auditing required
//TODO: get application info from token
throw new NotImplementedException("OAuth auditing not yet implemented.");
}else { //no auth or basic auth or anything else, use HTTP headers for audit info
String appId = theServletRequest.getHeader(UserInfoInterceptor.HEADER_APPLICATION_NAME);
Source source = new Source();
source.setIdentifier(appId);
source.setType(getAccessType(theServletRequest));
source.setSite(getSiteId(theServletRequest));
return source;
}
}
protected StringDt getSiteId(HttpServletRequest theServletRequest) {
return new StringDt(mySiteId); //override this method to pull the site id from the request info
}
protected List<CodingDt> getAccessType(HttpServletRequest theServletRequest) {
List<CodingDt> types = new ArrayList<CodingDt>();
if(theServletRequest.getHeader(Constants.HEADER_AUTHORIZATION) != null && theServletRequest.getHeader(Constants.HEADER_AUTHORIZATION).startsWith("OAuth")){
types.add(new CodingDt(SecurityEventSourceTypeEnum.USER_DEVICE.getSystem(), SecurityEventSourceTypeEnum.USER_DEVICE.getCode()));
}else{
String userId = theServletRequest.getHeader(UserInfoInterceptor.HEADER_USER_ID);
String appId = theServletRequest.getHeader(UserInfoInterceptor.HEADER_APPLICATION_NAME);
if (userId == null && appId != null) types.add(new CodingDt(SecurityEventSourceTypeEnum.APPLICATION_SERVER.getSystem(), SecurityEventSourceTypeEnum.APPLICATION_SERVER.getCode()));
else types.add(new CodingDt(SecurityEventSourceTypeEnum.USER_DEVICE.getSystem(), SecurityEventSourceTypeEnum.USER_DEVICE.getCode()));
}
return types;
} }
protected SecurityEventActionEnum mapResourceTypeToSecurityEventAction(RestfulOperationTypeEnum resourceOperationType) { protected SecurityEventActionEnum mapResourceTypeToSecurityEventAction(RestfulOperationTypeEnum resourceOperationType) {

View File

@ -201,7 +201,7 @@ public class ResourceWithExtensionsA extends BaseResource {
} }
@Override @Override
public ResourceTypeEnum getResourceType() { public String getResourceName() {
return null; //not implemented return null; //not implemented
} }

View File

@ -108,8 +108,8 @@ public class Patient extends BaseResource implements IResource {
@Override @Override
public ResourceTypeEnum getResourceType() { public String getResourceName() {
return ResourceTypeEnum.PATIENT; return Patient.class.getName();
} }