FHIR Chat · AuditEvent for Patient · Security and Privacy

Stream: Security and Privacy

Topic: AuditEvent for Patient


view this post on Zulip John Moehrke (Aug 30 2019 at 00:44):

I have noticed that in FHIR we have not made clear a rule that we have had in IHE for 15 years. That rule is that when recording any security / privacy relevant event, WHEN YOU KNOW the patient identity, include the patient identity as another .entity. This rule has "when you know" because there are plenty of times that you don't know. But when doing operations on patient relevant resources in FHIR the patient id is right there in the patient relevant resource (e.g. Observation.subject), or clear on query where a ?patient parameter is used... Thus the existance of an .entiity of the Patient becomes a required-if-known. If we did that, then the AuditEvents would show up in the patient compartment, and be more easy to find.
Seems we should have a profile in the core specification on AuditEvent to define this... right?

view this post on Zulip John Moehrke (Aug 30 2019 at 12:57):

Patient as a user -- note that accesses by the patient would all be audited with the patient's user identity in the auditEvent.agent; so these are all fully covered and the situation context is understood. It is possible that their delegated agent might also be understood...

view this post on Zulip Michele Mottini (Aug 30 2019 at 13:01):

We do record the patient being accessed in our audit - and the audit is searchable by patient
Not sure about a profile: how (and which) event are recorded does not seem something a FHIR profile could specify

view this post on Zulip John Moehrke (Aug 30 2019 at 13:07):

Query/Search/Operations -- these are not fully covered in a simple "reasonable effort" rule, so might need special handling that is not today recommended in IHE (often). In IHE a query/search or operation are just logged as an Execute with the parameters encoded. with an exception where the query specifically identifies the patient. So the cases that are not covered are those search/query/operations where there is not a patient identified in the request. This is seen as a gap caused by it being too hard to properly handle the result. This gap is not a problem when the audit analysis is occasional deep inspection (user is suspected of bad behavior, patient complains of bad behavior, malpractice suit needs evidence, law asks for specific evidence); these cases can re-create the results. The problem is that this solution does not work well for Patient Access/Accounting of Disclosures function. The solution is to tell the server audit logging agent to wait until the response is known, then iterate through the response for all indications of patient(s). In these cases one needs to log as many auditEvent records as there were patients exposed in that one search/query/operation. This is done in a few cases in IHE that were seen as specifically Privacy problems, and we could leave this to specific FHIR IG too. The need to make many audit events is because of the privacy use-case.

view this post on Zulip John Moehrke (Aug 30 2019 at 13:10):

We do record the patient being accessed in our audit - and the audit is searchable by patient
Not sure about a profile: how (and which) event are recorded does not seem something a FHIR profile could specify

Im just wondering how to drive everyone to include the patient when they can... vs today where it is not said, and thus I have found audit logs with no patient.. and because there is no patient, then the patient user can't see those audit logs.. so looking for a mechanism to drive better logging. So I think the profile would simply be a generic AuditEvent that has a .entity that is a Patient with the entity.role of "1" - Patient

view this post on Zulip Michele Mottini (Aug 30 2019 at 13:16):

Only some AuditEvent in a system could match such a profile though . . .so what would be gained to create it?

view this post on Zulip John Moehrke (Aug 30 2019 at 13:18):

true statement, but isn't that true about all profiles? The point of a profile is not always to tag compliant or tag non-compliant; but rather to set a good pattern that is highly encouraged to follow...

view this post on Zulip John Moehrke (Aug 30 2019 at 13:21):

the easy solution is to add a section to the AuditEvent narrative (like 6.4.4.7 - Identify Patient whenever possible). Add the above explanation and exceptions. -- hopefully others help with that text.

view this post on Zulip John Moehrke (Aug 30 2019 at 13:29):

Note that this solution would also solve a problem identified that the Patient "Compartment" doesn't include the AuditEvent records...

view this post on Zulip John Moehrke (Aug 30 2019 at 13:30):

But mostly this will enable a Privacy Empowering feature of knowing where and when your data is used.
https://healthcaresecprivacy.blogspot.com/2019/06/patient-engagement-access-log.html

view this post on Zulip Michele Mottini (Aug 30 2019 at 13:36):

but isn't that true about all profiles?

Uh, no? The way I always understood it is that if a server complies with a profile for a specific resource all instances of that resource must conform to that profile

view this post on Zulip John Moehrke (Aug 30 2019 at 13:38):

but isn't that true about all profiles?

Uh, no? The way I always understood it is that if a server complies with a profile for a specific resource all instances of that resource must conform to that profile

there are those religions.. but too far off the audit event topic

view this post on Zulip John Moehrke (Aug 30 2019 at 15:38):

Note that this proposal to add patient entity to auditEvent records is independent of the decision to make auditEvent records available to the Patient. I think they should be available to the Patient, but THIS thread is more about getting useful AuditEvent records. The addition of a Patient entity, where ever possible, enhances all use-cases for AuditEvent and not just Patient access.

view this post on Zulip Grahame Grieve (Aug 30 2019 at 22:21):

I do not think that this is something that the core specification should rule on, but it is something it can describe and make suggestions about.

view this post on Zulip Grahame Grieve (Aug 30 2019 at 22:22):

I will update my server but I'm having trouble imagining how to decide which operations to match to a patient when more than one patient is in scope for an operation

view this post on Zulip Grahame Grieve (Aug 30 2019 at 22:22):

otoh, production servers, where the audit logs are driven off decisions lower down in the system than the FHIR API would not generally have this problem... right?

view this post on Zulip John Moehrke (Aug 31 2019 at 02:00):

For transactions that return potentially different patients, you wait to log based on the results. Oh, and best to log one entry for every patient.

view this post on Zulip John Moehrke (Sep 03 2019 at 15:00):

Created GF#23835 - likely to discuss on the FHIR Security call today.

view this post on Zulip Grahame Grieve (Sep 03 2019 at 19:30):

any update?

view this post on Zulip John Moehrke (Sep 03 2019 at 19:47):

Created GF#23835 - likely to discuss on the FHIR Security call today.

security wg approved

view this post on Zulip Grahame Grieve (Sep 04 2019 at 03:58):

ok so I've just been looking at this. Some decisions for test.fhir.org:

  • I'm not logging the fact that a patient result was included in a search unless the resource was actually returned to the client (e.g. based on paging)
  • it's a big hit on my search performance since I now actually have to process the object (can't send out pre-prepared byte streams without parsing) (that's an implementation issue specific to me)
  • I'm not logging transactions and batches; I already log the individual operations in them, so patients won't see the transaction/batch
  • I am logging hits on the history too, but I think that must patients won't see that

view this post on Zulip Grahame Grieve (Sep 04 2019 at 03:59):

what a patient won't see is which resources were returned in search/history

view this post on Zulip Grahame Grieve (Sep 04 2019 at 04:52):

also: i do not know how to log a history response that includes a deleted patient record against the patient for the deleted record because I no longer know which patient the deleted record used to reference before it was deleted

view this post on Zulip John Moehrke (Sep 04 2019 at 18:18):

also: i do not know how to log a history response that includes a deleted patient record against the patient for the deleted record because I no longer know which patient the deleted record used to reference before it was deleted

in the case of Delete, wouldn't you capture the Patient being affected prior to the delete? Yes you would still need to wait to log until you knew success/failure... Given this is obvious, I am wondering what I a am missing. Or is this just code workflow that gets in your way?

view this post on Zulip John Moehrke (Sep 04 2019 at 18:19):

what a patient won't see is which resources were returned in search/history

correct. The results of query/search/operation are not logged. just the parameters of the request; but this new guidance does ask that an audit event is recorded with an .entity of the patient affected.

view this post on Zulip John Moehrke (Sep 04 2019 at 18:22):

I'm not logging the fact that a patient result was included in a search unless the resource was actually returned to the client (e.g. based on paging)
ah, I guess it is privacy best-practice to record that they asked, even if no results were found... But I do understand the technical approach of only looking at results. These two alternatives are likely correct for different environments... I hate to always fall back to "policy", aka configurable.

view this post on Zulip Grahame Grieve (Sep 04 2019 at 20:33):

in the case of Delete, wouldn't you capture the Patient being affected prior to the delete?

yes, that's what I do. But if then, later, someone syncs using a history request and is informed that this resource has been deleted, I can no longer link that to the patient since I no longer know what the resource said

view this post on Zulip John Moehrke (Sep 05 2019 at 01:19):

what response would you give to that request? would that not include the old Patient version? And thus, have the id?
Not sure this is all that realistic, but thanks for the detail

view this post on Zulip Grahame Grieve (Sep 05 2019 at 01:35):

to the history request? the deleted resource will look something like this:

<entry>
    <request>
      <method value="DELETE"/>
      <url value="observation/2123123"/>
    </request>
    <response>
      <lastModified value="2014-08-20T11:05:34.174Z"/>
    </response>
  </entry>

There's no resource, and my server no longer has the link to the patient. The system getting the history only gets the note that the resource that used to exist no longer does

view this post on Zulip John Moehrke (Sep 05 2019 at 14:09):

well, that doesn't look like it is exposing data, so that reason for logging is not present. It is however that someone is 'trying' to get at the data, which is interesting to privacy or security office. I suspect simply logging the request is sufficient. Makes me wonder how you would indicate it was a request for something that has been deleted. Not exactly success, nor failure. I guess you could use "Minor Failure", although the description for that is that it is like 4xx responses. Is there OperationOutcome encoding?

view this post on Zulip John Moehrke (Sep 05 2019 at 14:13):

what I am trying to define is how this gets logged such that a security office audit of the logs would see this 'unusual' interaction, as potential attack.

view this post on Zulip Grahame Grieve (Sep 05 2019 at 20:23):

this is not unusual. This is an inevitable consequence of the history operation - you might listen to a resource type. It's a request that says 'let me know of all changes to Observation since X' where X is the time from the header last time I made the request. You get all added / updated resources, and a note about any deleted resources so you know to delete them too. But all you get is the id of the deleted resource, so you can find it and delete it.

In this case, the patient audit trail will note that the resource was sent in a history when the history picks up it's creation/update, but won't when the history picks up the fact that it was deleted

view this post on Zulip Grahame Grieve (Sep 06 2019 at 05:33):

ok I upgraded my server so it implements all this (I hope). Please play with it and let me know how it goes

view this post on Zulip John Moehrke (Feb 03 2021 at 14:21):

I have drafted an IG on Basic Audit for REST operations. I welcome review, comments, discussion, and help. This is not a sanctioned project anywhere, it is my own effort, which I also welcome interest in making it more formal.
http://build.fhir.org/ig/JohnMoehrke/BasicAudit/branches/main/index.html

view this post on Zulip John Moehrke (Feb 03 2021 at 14:22):

@Grahame Grieve and @James Agnew I would be interested in your comments relative to the support your reference implementations include.

view this post on Zulip Lee Surprenant (Feb 03 2021 at 18:48):

cool, thanks for sharing. one thing i've always wondering is whether we should enumerate the specific resource that come back from a given search. this seems to stop short of that and instead just documents which patients had resources that were returned by the search, right?

view this post on Zulip John Moehrke (Feb 03 2021 at 19:12):

correct. a AuditEvent for a Query event just records the query that it responded to, with success vs failure. The presumption is that the results are deterministic, and could be re-created historically if needed. That the query parameters are far more important.

There are some proposals to include some request id that is internally useful, or possibly a response id.

Given REST, I could see an advanced version that enumerates just the id values of the resources returned.

But certainly shall NOT replicate in the audit log the resources that were returned. Otherwise your audit log becomes a huge replication upon replication of your database. And further the audit log would then become very sensitive.

I should explain this.. Ill add a TODO to explain this.

view this post on Zulip Lee Surprenant (Feb 03 2021 at 19:41):

The presumption is that the results are deterministic, and could be re-created historically if needed

I wonder if this presumes too much. The deterministic piece seems reasonable, but historically-accurate search requires something like time-travel query which not all datastores support, right?

But certainly shall NOT replicate in the audit log the resources that were returned

for sure

Given REST, I could see an advanced version that enumerates just the id values of the resources returned.

i was thinking resource type + id + version for each resource in the page that was retrieved

view this post on Zulip Lee Surprenant (Feb 03 2021 at 19:42):

maybe not needed for all use cases, but would make it much easier to answer questions like "who/what/when accessed resource xyz in a given period"

view this post on Zulip Grahame Grieve (Feb 05 2021 at 02:36):

Looking at this now @John Moehrke:

  • agree about type/subtype.
  • weird to fix the outcount to 0. I might return 4 or 8 in cases of error
  • isn't the server the source? what goes in source if server is an agent? (I'm using source)
  • I don't have a device for the server. What would it say?
  • and what's the network location for the server? it's public IP? which ?
  • The server is quite likely not going to have a resource that describes the client. At a minimum, I will have an IP address. I may have an openID connect url if I used OAuth to identify the client - but no, you split that out to a different agent, so all I'll have for the client is an IP address, and possibly a secret that implies a software id
  • the human - again, I may have an openIDConnect id, I may have a name, I may have an email address
  • is it reasonable to fix the human to requester = true? how would the server know?
  • you can't fix the cardinality of a the patient slice it 1..1 - there may not be a patient in context

view this post on Zulip John Moehrke (Feb 05 2021 at 11:40):

Thanks for the comments @Grahame Grieve

  • I only profiled success. I stated this in the sushi, but forgot to bring that forward in narrative. Errors would be reported as normal errors would be reported, I can add them. Is there specific errors ? I don't want to profile all possible errors.
  • The server is the source, when the server is the one detecting and reporting the audit event. But the client can also record an audit event, and I would encourage the clients to also record the audit events. The reason is that it creates a pattern that can be watched and deviations flagged for followup. Such as when the client stops recording an audit log, is likely a case where the client credentials have been stolen. You would notice this far sooner when both parties are recording.
  • The Device resource just seems the closest thing , from the possible agents, that we have to a resource for identifying an app or a server. I imagine it is just described in terms of the identifier. Thus the degenerate form is to use who.identifier. I didn't go into all of these as they are generic auditEvent use, not specific to REST operations when a Patient is a subject.
  • network can be the domain name, it does not need to be IP.
  • I am fixing the patient to 1..1 because I am only profiling REST operations that involve a patient as the subject.

view this post on Zulip Grahame Grieve (Feb 05 2021 at 20:04):

I think that we certainly don't to profile all errors, but we do want to provide guidance around errors. In my server I have 3 kinds of errors - definitely client errors, definitely server errors, and unexpected errors (I'm not sure about). I log these 3 kinds differently in the AuditEvent

view this post on Zulip Grahame Grieve (Feb 05 2021 at 20:05):

do we need different profiles for server and client?

view this post on Zulip John Moehrke (Feb 08 2021 at 13:14):

In theory the difference between a client recording and a server recording the same fact is simply that the .source is different. All the other information would be profiled the same for both.. In fact something I should have included is that these AuditEvents could also be recorded by the OAuth authorization service. Thus in FHIR one might have three AuditEvents for the same event, although given OAuth token re-use this is likely to not be one-for-one, but would be visible over a session. I should add this?

view this post on Zulip John Moehrke (Feb 08 2021 at 13:18):

Client v Server logging is likely to be different in practice. When success happens, they are closest, but the client might know more about the reason the transaction was requested, like the context within an episode of care or care plan. Information that is not needed in the FHIR REST interaction. This could be put into the one AuditEvent from the client. When failures happen, the client is at a disadvantage, the server is more likely to be able to elaborate on the detail.

view this post on Zulip John Moehrke (Feb 08 2021 at 13:18):

I am not sure if these differences are specific enough to end up in a Profile.

view this post on Zulip John Moehrke (Feb 08 2021 at 13:22):

IHE has historically defined both client and server audit messages. But these are in the context of the audit requirements given some other transaction (e.g. XDS Query). Thus the goal is to profile the AuditEvent more tightly to the expectations of that other transaction context. I think this kind of specialization will happen.

view this post on Zulip John Moehrke (Feb 08 2021 at 13:24):

On errors... I would like to start cataloging common errors and the resulting AuditEvent. I think that catalog might drive the profiling methods. I could see an IG that does nothing but profile this error catalog. No one would declare conformance to that IG. But other IGs could pull the profiled AuditEvents from this IG.

view this post on Zulip Grahame Grieve (Feb 08 2021 at 22:39):

i was talking about the difference between client caused error and server caused error there

view this post on Zulip John Moehrke (Feb 08 2021 at 23:55):

okay, then yes... when I get to errors there will likely be different groups of errors typical for clients and others typical for servers.


Last updated: Apr 12 2022 at 19:14 UTC