FHIR Chat · general auditevent generator · hapi

Stream: hapi

Topic: general auditevent generator


view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:49):

Has anyone in the HAPI community done some of the grunt interceptor code work publicly that generates proper auditevents when poking the HAPI FHIR server?

view this post on Zulip Grahame Grieve (Jul 30 2019 at 07:50):

I've done it in my server. It's similar logic, but I haven't done it in HAPI. Is that at all relevant?

view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:52):

yes, hence the question. Besides being able to generate an audit log, I ( and maybe others) are in the need to runtime send an audit log to national services

view this post on Zulip Grahame Grieve (Jul 30 2019 at 07:53):

right. So if the question is about the HAPI integration part, anything I did on my server is irrelevant. but if it's about the auditevent side, then the logic is basically the same...

view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:53):

I found https://github.com/nhsconnect/careconnect-reference-implementation/blob/020665c5216ae614402f46d7f01bce9228d231e5/cc-core/src/main/java/uk/org/hl7/fhir/core/Stu3/CareConnectAuditEvent.java and https://github.com/jamesagnew/hapi-fhir/blob/f7029b9a0f91da772499a8cbdba4ee8f8994dd10/hapi-fhir-structures-dstu/src/main/java/ca/uhn/fhir/rest/server/interceptor/AuditingInterceptor.java in where I may find inspiration

view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:53):

Its the auditevent generation on the server side I'm fishing for

view this post on Zulip Grahame Grieve (Jul 30 2019 at 07:54):

which vesrion?

view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:54):

STU3

view this post on Zulip Grahame Grieve (Jul 30 2019 at 07:55):

https://github.com/grahamegrieve/fhirserver/blob/master/Server/FHIR.Server.OperationsR3.pas#L599 - different language and server framework, but the logic should be similar and applicable

view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:55):

I believe @Kevin Mayfield is the author of one of those

view this post on Zulip Grahame Grieve (Jul 30 2019 at 07:58):

some parameters to that call:
- session - links to information about the client and any authentication provided
- intreqid - intrernal unique id for the request
- extreqid - client provided id using the relevant X- header
- ip - IP of the client (not sure what that doesn't come from the session)

view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:58):

@Grahame Grieve something like that, yes. Now that function/method is some 140 lines ... including testcode that probably would accumulate to some 500-1000 lines that I wondered if already existed in some other project that I could use

view this post on Zulip Grahame Grieve (Jul 30 2019 at 07:59):

I don't know of any. Just trying to help here ;-)

view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:59):

I know

view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:59):

And its appreciated

view this post on Zulip Jens Villadsen (Jul 30 2019 at 07:59):

But as most developers of nature, I'm lazy

view this post on Zulip Jens Villadsen (Jul 30 2019 at 08:00):

and want quality at the same time

view this post on Zulip Grahame Grieve (Jul 30 2019 at 08:00):

naturally

view this post on Zulip Jens Villadsen (Jul 30 2019 at 08:01):

I'll guess I'll have to do a (non-existing) brush up on my Delphi ;)

view this post on Zulip Grahame Grieve (Jul 30 2019 at 08:03):

not a lot of deep pascal knowledge required there; most of your questions will be about the implied knowledge of the server framework, not the langauge. ask away....

view this post on Zulip Jens Villadsen (Jul 30 2019 at 08:08):

Yep ... I'll let you know

view this post on Zulip Kevin Mayfield (Jul 30 2019 at 08:16):

We didn't finish that code. We put in a stub (best guess) to form a basis for future work.

view this post on Zulip Jens Villadsen (Jul 30 2019 at 08:18):

@Kevin Mayfield I had a feeling of that. I couldn't find much coverage of it neither. And the "System.out.println(operationOutcome.getIssue().get(0).getCode());" gave it away

view this post on Zulip Jens Villadsen (Jul 30 2019 at 08:21):

@Grahame Grieve how does one select among http://build.fhir.org/valueset-audit-event-action.html - more specifically R vs. E. Isn't it sort of expected that information that is searched for ('E') is also read ('R')?

view this post on Zulip Kevin Mayfield (Jul 30 2019 at 08:21):

:) we intended to build AuditEvent on top of the logs in elastic.

view this post on Zulip Jens Villadsen (Jul 30 2019 at 08:25):

@Kevin Mayfield interesting. Do you intend to store it separately afterwards?

view this post on Zulip Grahame Grieve (Jul 30 2019 at 09:57):

I don’t recall, and don’t have the code in front of me right now. but search is read, for me, usually.

view this post on Zulip Grahame Grieve (Jul 30 2019 at 09:57):

Execute is a $operation

view this post on Zulip Jens Villadsen (Jul 30 2019 at 11:04):

pasted image @Grahame Grieve

view this post on Zulip Jens Villadsen (Jul 30 2019 at 11:04):

query/search => E

view this post on Zulip Jens Villadsen (Jul 30 2019 at 11:07):

May I suggest that the sentence is then rephrased

view this post on Zulip Jens Villadsen (Jul 30 2019 at 11:07):

to omit the query/search thingy

view this post on Zulip Grahame Grieve (Jul 30 2019 at 11:34):

make a task for... Security, I think (@John Moehrke)

view this post on Zulip John Moehrke (Jul 30 2019 at 18:38):

which way are we wanting? I see the spec today as saying that a query is an action == execute... this is what the text, codes, and examples say... right?

view this post on Zulip Grahame Grieve (Jul 30 2019 at 19:31):

@John Moehrke - we don't agree. FHIR Search is primarily a wide spread read, not an execute.

view this post on Zulip John Moehrke (Jul 30 2019 at 19:33):

okay. I can understand that. It was just not clear in the zulip discussion thread what the conclusion was.. So the CR would switch all mentions (narrative, model, codes, and examples).

view this post on Zulip Grahame Grieve (Jul 30 2019 at 19:35):

yes. though it might switch examples to actual execute examples

view this post on Zulip John Moehrke (Jul 30 2019 at 19:36):

yes we need an execute example... likely one of the many operations we now have. Right?

view this post on Zulip John Moehrke (Jul 30 2019 at 19:36):

I can bring in the audit example from IHE PIXm, which is an operation

view this post on Zulip Grahame Grieve (Jul 30 2019 at 19:37):

yes, any $operation is clearly an execute

view this post on Zulip John Moehrke (Jul 30 2019 at 19:44):

The difficulty we do need to deal with is that AuditEvent is derived from DICOM AuditMessage, which defined these vocabulary. In that specification they do describe query as a form of execute -- http://dicom.nema.org/medical/dicom/current/output/html/part15.html#sect_A.5.3.10

view this post on Zulip Grahame Grieve (Jul 30 2019 at 19:46):

FHIR search is not query. I think that's the difference. We should be able to clarify that. a _query (or the mpi operation) can be called a query. See http://hl7.org/fhir/search.html#query

view this post on Zulip John Moehrke (Jul 30 2019 at 19:49):

I am missing some elegant difference you imply between query and search...

view this post on Zulip John Moehrke (Jul 30 2019 at 19:51):

I think we should move this discussion to a broader stream than HAPI

view this post on Zulip Grahame Grieve (Jul 30 2019 at 19:51):

sure

view this post on Zulip Jens Villadsen (Jul 30 2019 at 19:59):

Wow ... Had forgot about the query param

view this post on Zulip Jens Villadsen (Jul 30 2019 at 21:28):

@John Moehrke let me know where you move it to

view this post on Zulip Jens Villadsen (Aug 01 2019 at 07:40):

While we're at the query/search discussion: Couldn't the https://www.hl7.org/fhir/operation-patient-match.html just as well have been expressed as a 'query' profile then?

view this post on Zulip Grahame Grieve (Aug 01 2019 at 07:42):

it could have been, yes. In fact, the very first cut, it was. But there's more than a few people who don't like _query and it was kind of a style question, in the end.

view this post on Zulip Jens Villadsen (Aug 01 2019 at 11:35):

okay @Grahame Grieve - let me know when you open up the 'query vs search'-distinction-terminology discussion ... its of interest for me as well

view this post on Zulip Grahame Grieve (Aug 01 2019 at 11:58):

well, that'll be up to @John Moehrke I think

view this post on Zulip Brian Postlethwaite (Aug 01 2019 at 12:17):

The patient match can take up to a whole patient resource, not just the fields that happen to be in the search parameters. A query style wouldn't meet that. So you could be more careful on matching the names in the resource.

view this post on Zulip Jens Villadsen (Apr 22 2020 at 10:19):

back to this: @John Moehrke, @Grahame Grieve never moved the discussion (or at least it is not present in this discussion). Bottom line is that http://build.fhir.org/auditevent.html#6.4.4.4 still lists search and search-type as 'E' where it IMHO better fits to 'R'. Should I make a CR on this or should it be moved to another stream first?

view this post on Zulip Grahame Grieve (Apr 22 2020 at 12:21):

#implementers I guess. but search is R for me not E

view this post on Zulip John Moehrke (Apr 22 2020 at 12:47):

The discussion has happened. Search/Query do not identify the instance in the request, one must execute a search on the parameters provided to get the result. This is why search/query is an execute. The discussion did result in a clarification in the section pointed at, that explains this.

Agent for logged in user, if available, and one object with a query element. The Execute action is used as the server must execute the search parameters to get the results, whereas a Read action identifies a specific object.

I have not heard any reason why this conclusion is so difficult to live with. Can this be explained, other than a rhetorical argument about the HTTP GET verb?

view this post on Zulip Jens Villadsen (Apr 22 2020 at 13:18):

While it does not identify a single resource it identifies multiple resources - as such I would even call it multiple reads - which I would simply to an 'R', not an 'E'

view this post on Zulip John Moehrke (Apr 22 2020 at 13:27):

there is indeed a degenerate query on the _id that could be seen as identical to a read. but this does produce a bundle , and as an exception does not invalidate the dominant fact that the query parameters do not identify objects, but rather parameters that must be searched on to discover the results.

view this post on Zulip Jens Villadsen (Apr 22 2020 at 13:41):

query parameters do not identify objects

indeed query parameters identifies objects. If I search a database for all males named ' @John Moehrke ' I'm pretty sure those objects are identified, aren't they?

view this post on Zulip John Moehrke (Apr 22 2020 at 14:05):

no, they were 'found' at a moment in time. But they are not known. As in a DELETE operation seconds after that query will produce nothing. Yet a GET on an ID will be clear what it was that was retrieved regardless of the DELETE operation.

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:07):

everything is found in a moment of time

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:08):

and at that time they will be identified with those parameters

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:09):

and at that time they are known

view this post on Zulip John Moehrke (Apr 22 2020 at 14:10):

can you explain what is wrong with Execute? I have explained that consensus (actually multiple standards organizations) have agreed it is execute.

view this post on Zulip John Moehrke (Apr 22 2020 at 14:10):

I simply have not heard any reason why execute is problematic

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:10):

'R' simply fits better to the picture

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:11):

multiple standard organizations would have multiple takes on it

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:11):

ask those that standardize SQL

view this post on Zulip John Moehrke (Apr 22 2020 at 14:11):

and AuditEvent is designed for multiple uses

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:11):

sure

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:11):

which basically means that multiple uses would have multiple takes on it

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:12):

everything is an 'execute' if you go deep enough

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:12):

i think

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:12):

it is a matter of abstraction

view this post on Zulip John Moehrke (Apr 22 2020 at 14:12):

or one person has a different view than others

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:12):

and from my point of view (and maybe others) 'R' fits better into the picture

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:13):

sure

view this post on Zulip Jens Villadsen (Apr 22 2020 at 14:14):

maybe only @Grahame Grieve and me thinks 'R' is a better fit. That might be plausible

view this post on Zulip John Moehrke (Apr 22 2020 at 14:52):

there are historic reasons, companion standards reasons, modeling reasons, etc... that up against the only argument against "R fits better into the picture". Which is a very REST flavor of FHIR specific viewpoint (picture). Given this is your answer to what is wrong with "E", I am not persuaded.

view this post on Zulip Jens Villadsen (Apr 22 2020 at 16:05):

Just to be clear: in your book, searching for multiple entites resulting in the return of multiple instances that are associated to that search is not a read of data?

view this post on Zulip John Moehrke (Apr 22 2020 at 16:33):

you are correct that in FHIR the results of a search is not just a list of id values. more reason that a search is an Execute, as one must understand the search must be looked at to understand what was exposed. Good point as to why E is correct.

view this post on Zulip Jens Villadsen (Apr 22 2020 at 17:20):

So if the result is in a bundle, it is E?

view this post on Zulip Jens Villadsen (Apr 22 2020 at 19:15):

(besides searching using _id)

view this post on Zulip Jens Villadsen (Apr 23 2020 at 19:33):

@John Moehrke

view this post on Zulip John Moehrke (Apr 24 2020 at 14:08):

I don't think that is a good definition of a query / search... especially given document bundles, message bundles, and collection bundles.. so, no.

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:22):

Given the context of a REST interface, would that change anything?

view this post on Zulip John Moehrke (Apr 24 2020 at 14:28):

as in a "searchset" bundle? well, yes a searchset bundle is the result of a search. / query. It also indicates this could be the result of an operation (clearly an Execute, right?), or a "message". Where I think the "message" here means a message bundle that had a search request in it, but that is not clear. http://build.fhir.org/codesystem-bundle-type.html#bundle-type-searchset

view this post on Zulip John Moehrke (Apr 24 2020 at 14:29):

but, a failed search / query does not result in a searchset bundle... and it too must be recorded as an Execute ... so searchset bundle is not sufficient clarification

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:32):

maybe 'R' is too narrow and 'E' is to wide. I my mind, 'E' is what cannot be categorized as neither CRU or D.

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:32):

E is: hey service, please fetch all y, extrapolate to x and combine with z

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:33):

or: hey service, please read from a third party register and do the fuzzy logic transformation for me

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:35):

searching is neither of those ... searching is ... well, search based on some optional filtering and restriction requirements

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:37):

I don't see searching as a way of transforming og altering data - which an execute would do - as it is anything else.

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:38):

what would your take be on that @John Moehrke

view this post on Zulip Keith Boone (Apr 24 2020 at 14:40):

Much of what is really useful in FHIR Search is "extrapolate to x [include, revinclude]", combine with (:in=ValueSet), and similar.
The set of required/optional parameters is really important. I know of few EHRs which would allow a user to search for Observation?code=X without specifying patient/subject also, unless it's a special kind of system that is allow to search across patients (e.g. for quality measurement).

A lot of what is in FHIR search isn't just read these things, it's "give me this view"

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:43):

@Keith Boone -yet the search does not transform the data. you ask for at set of filtered observations - and you get observations in return

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:43):

they will still be observations

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:44):

you do not transform nor manipulate it (besides including other items as mean of optimization)

view this post on Zulip John Moehrke (Apr 24 2020 at 14:45):

filtering is transforming... it is reducing the results based on the filter criteria

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:45):

how can filtering be transforming?

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:46):

reducing the set is filtering

view this post on Zulip Jens Villadsen (Apr 24 2020 at 14:48):

filtering on a search on observations still only gives you observations - it doesn't give you organizations, right?

view this post on Zulip Keith Boone (Apr 24 2020 at 14:53):

I think about it from a database permissions perspective. These kinds of searches with these parameters are allowed by people in this roles, those kinds of searches with those parameters are allowed by those others in that kind of role. This first "Search" with a fixed set of parameters is akin to a Stored procedure with one set of parameters, on which Role 1 has Execute privileges, but role 2 has not, while the second is allowed to be executed by both roles.

We can get hung up on whether R or E is right or wrong. That's actually less material than why or what impact it has on software that's being implemented and/or has been implemented. What's the use of E going to impact that is so fundamentally frustrating for use of it in audits is what I'd like to understand. Because changing the use of now is going to impact existing commercial and open source implementations and other published guides, so I'd like to see something other than what has been mostly an academic discussion about whether it's E or R.

view this post on Zulip Keith Boone (Apr 24 2020 at 18:47):

For what it's worth, I've implemented E twice for AuditEvent in commercially available products that have been in production for several years in one case, and a year in the other, and used it for several FHIR IGs as well. I'm not interested in seeing it change unless someone can come up with something other than an academic rationale.

view this post on Zulip Jens Villadsen (Apr 26 2020 at 13:52):

What's the use of E going to impact that is so fundamentally frustrating for use of it in audits is what I'd like to understand

I would like the use of the model to reflect the actual use as correctly as possible. I don't find 'E' doing that. Especially as I would like to differentiate between 'searches' and 'executions'. Searches in my system are expected to be idempotent whereas the same cannot be said about executions

Because changing the use of now is going to impact existing commercial and open source implementations and other published guides, so I'd like to see something other than what has been mostly an academic discussion about whether it's E or R.

That is of course a valid concern - but that goes for any change to future versions and time/money can be a reason not to change it. My system is a greenfield national solution where we besides the actual system also bridges AuditEvents from multiple sources with no ties to ATNA, IHE or DICOM. Processing the AuditEvent and the ability to filter e.g. whether an action is a search or not may not be the most central piece of information as every request and response is saved anyways and eventually indexed. I do however like to keep my model tight and clean - and the categorization of whether an action is potentially modifying data or not is part of that process. I don't find that approach particularly academic.

view this post on Zulip Keith Boone (Apr 27 2020 at 09:58):

Practically, Execute never has had the meaning of modify in any sense. An execution can modify, but it can also just read.

Green field ... "reflect actual use". But your definition of actual use and my definition of actual use come to different answers. There is no right or perfect answer to that question, and there's history, and an agreement as to what was selected, and implementations in place that use that answer.

FHIR defines E as follows:
E Execute Perform a system or application function such as log-on, program execution or use of an object's method, or perform a query/search operation.

That vocabulary is defined in terms of FHIR operations:
C = create
R = read or vread
U = update or patch (since patch is defined in terms of update)
D = delete
E = just about everything else.

Looking at it from that perspective, I feel even more strongly. E is operations other than CRUD, and search with ANY sort of complexity isn't CRUD. And the FHIR restful API is normative. I'd rather all search be E than some be R and some be E, and at least some of it needs to be E.

view this post on Zulip Jens Villadsen (Apr 27 2020 at 11:55):

How would you categorize the following @Keith Boone :
1) A transaction that does a single entity create
1) A transaction where two entities are created
2) A transaction that does a single entity read
3) A transaction where two entities are read
4) A query where two entities are read by id

view this post on Zulip Jens Villadsen (Apr 27 2020 at 11:55):

In terms of CRUDE

view this post on Zulip Keith Boone (Apr 27 2020 at 13:29):

When I implemented this using interceptors, prior to HAPI cutting over to the current format, but basically after it had processed the parameters. 1) Create operations went to create (C) 2) I didn't implement transaction, but did implement batch in one case, so a batch that created 2 entities uing batch went to (E), 3) went to read (R), 4) didn't implement a batch read, but it would have gone to (E) the same way that batch writes went to (E), 5) GET Resource?_id=1,2 would have gone to (E) if I had allowed it, both times I implemented search, I disallowed query by more than one id. Since it entered as Search, it would again have been (E).

view this post on Zulip John Moehrke (Apr 27 2020 at 13:33):

I would say they all should result in an "E" record, but items 1-4 would ALSO result in some CRUD audit entries.

view this post on Zulip Keith Boone (Apr 27 2020 at 13:34):

If using FHIR transaction or FHIR batch, I would agree, these would all have been (E) in the implementation I did. If using FHIR operations (read,vread, create, delete, etc), these would have gone as I've indicated.

view this post on Zulip John Moehrke (Apr 27 2020 at 13:34):

Someone might notice the query of _id, and recognize that as a Read; but they still should record it as a E/query. Just because the _id parameter is used does not mean it should not be recorded as an E/query. The nice part about E for query is that it works ALWAYS the same way.

view this post on Zulip Jens Villadsen (Apr 27 2020 at 20:42):

John Moehrke said:

I would say they all should result in an "E" record, but items 1-4 would ALSO result in some CRUD audit entries.

Ain't that a bit too ambiguous

view this post on Zulip Jens Villadsen (Apr 27 2020 at 20:55):

I believe we can agree to disagree on this matter ;)

view this post on Zulip Jens Villadsen (Apr 28 2020 at 08:30):

To me, a search/query that is idempotent that does filtering and/or narrowing and optional includes is a read of data


Last updated: Apr 12 2022 at 19:14 UTC