access control for openEHR 'resources'

None that I’m aware of. Videos 2 to 5 were the presentations, that might be the most interesting (just 1h 15m :sweat_smile:). The rest of the time were discussions.

1 Like

No, there isn’t. But there is something wrong with an access policy that lets you query lab result analyte value, but not lab result point of care test.

Sorry if I expressed myself badly. I indeed argue for the first, not the second.

Yes, I’m trying to argue for limiting acces control scope at the composition level and the entry level (depending on context like read/write, AQL/GET composition, others?). Which is different from the current smart on openEHR spec, which supports authorising specific AQLs.
I also recognise there are niche use cases where more granular acces control is implemented. But I’d like to update the spec (both the smart and the entry and the ehr access) to make general recommendations.
(Currently I’m only in the orientation phase, I may sound convinced of a position, but this is mostly to challenge to show me where I’m wrong. Already I’m confined there should be exceptions allowed).

And also yes, I think we should take these access control principles into account when designing archetypes and templates.

I’ve found in designing templates for a (problem-goal-action) care plan this adds some complexity initially. Because it forces you to split it at a composition (instance) per problem (and tying those together using an indexing compositon with DV_EHR_URIs). But in the longer term I’m convinced it adds many benefits, other than just access control.

It is actually the specs that are potentially a bit misleading here, not you!!

I think there is room for all of these, including AQL authorisation, but I agree life is a hack of a lot easier if we can largely use compositions as the basis for access control, especially for create/update/delete.

I also think access control / permission checking should be limited by component (we need to define what a component is), and consider the whole architecture to provide a full solution, while defining the scope for the openEHR specs (we might not be able to define a full access control architecture).

When I say components, an example could be:

  • end user application
  • middleware (stuff in the middle of the end user app and the openEHR API implementation)
  • openEHR API
    • normal GET methods
    • query
    • POST/PUT/DELETE methods
  • repository / backend / archive (stuff behind the API)

Then we can say, at the end user application we should be able to say “this user, role or group doesn’t have access to this patient or EHR” or “has access” or “has access under certain conditions”, or “has access to partial information, like compositions of certain types or with certain setting code”, or “has access to information defined by certain archetype (compo, entry, cluster, element)”.

We know the application could just do all the filtering since it knows the user, it’s role/group, etc. but should also know openEHR. That will leave all the scope for RBAC outside openEHR. Even if the checks and filters are done in the middleware. Then we can put some of the checks at the API level, there the API needs to know more about the user/role/group and might be able to keep the openEHR functionality and the RBAC checks quite separated, but we need to add those checks to the spec somewhere. Lastly if the RBAC is at the CDR / backend, we might need a full RM for that, how that is constrained by ADL, and how permission are checked, so those are also fully modeled and managed by openEHR.

My personal preference would be to avoid the backend level and try to not depend on access permissions at the CDR / backend. Another personal preference would be to make the RBAC totally independent from the RM, and have a strict spec we can replicate in different implementations, even if we actually use different systems for implementing those checks. Though I’m not sure how much of openEHR the permission checking will need to implement the rules I mentioned above.

Anyway, I would like to analyze requirements and start documenting something concrete that can serve for further discussion and definition. Maybe the SMART thing is enough and I might be over complicating things, or maybe not, hehe

some nice first steps to define an access policy to openEHR data in OPA/Rego: Design an acces policy language for openEHR ‘resources’ based on nuts verifiable credentials · Issue #11 · jorritspee/openEHRxNuts · GitHub

1 Like

Hi folks!
I stumbled on this thread and thought to at least share some of the things that we at Karolinska University Hospital have found in case it helps to further any part of this for anyone.

First if you are using Kubernetes I would STRONGLY recommend using OPA kube-mgmt instead of OPAL as it is lightyears more simple – you just create ConfigMaps with your rego scripts and the right label, then your policies will be picked up by the service. Deploy these ConfigMap resources however you normally do (e.g. with ArgoCD, Flux, etc). Keep in mind that the name needs to be completely unique, so we usually prefix the name with our namespace’s name.

With OPAL you need a database and lots of other stuff that (IMO) just make it way more complex and non-Kubernetes-feeling :wink:

Then when it comes to actual policies… I am not exactly sure where we will go in the future (as we are moving things around a bit…), but what we have done in the past is create some policies for the REST APIs themselves. You can think of it more like an implementation of SMART on FHIR / SMART on openEHR where it is limiting access to certain HTTP methods based on the scopes that exist in the requestor’s token.

Here is an example of a FHIR API policy for the Patient resource just to give a taste:

default allow = false

allow {
	create_patient
}
allow {
	read_patient
}
allow {
    search_patient
}

read_patient {
	regex.match("/Patient/[A-Za-z0-9-]{36}$", input.request.http.path)
	input.request.http.method == "GET"
	scope[_] in ["user/Patient.rs", "system/Patient.rs"]
}

create_patient {
	regex.match("/Patient$", input.request.http.path)
	input.request.http.method == "POST"
	# Here we can also put a check on the body and/or existence and format of headers like "if-none-exist" etc
	scope[_] in ["user/Patient.c", "system/Patient.c"]
}

search_patient {
	regex.match("/Patient/_search$", input.request.http.path)
	input.request.http.method == "POST"
	# Here we can also put a check on the body and/or existence and format of headers like "content-type" etc
    regex.match("^application/x-www-form-urlencoded$", input.request.http.headers["content-type"])
	scope[_] in ["user/Patient.rs", "system/Patient.rs"]
}

...

Note that this isn’t 100% our “real” policy but it hopefully gives a rough idea. Basically this policy has a semi-opinionated view of how we wanted to allow usage of the Patient resources in our FHIR API.

We have done similar with the openEHR API… here is a small example of part of it:

default allow = false

allow {
	read_ehr
}
allow {
	write_ehr
}

read_ehr {
	# match on /ehr, /ehr?*, /ehr#*, /ehr/{uuid}, /ehr/{uuid}?*, /ehr/{uuid}#*
	# especially that we do not want to match /ehr/{uuid}/* as that pattern will be for other rules (compositions, contributions, etc)
	regex.match("/ehr(($|[?#])|(\/[A-z\\-0-9]{0,}($|[?#])))", input.request.http.path)
	input.request.http.method == "GET"
	scope[_] in ["user/openehr-ehr.rs", "system/openehr-ehr.rs"]
}

write_ehr {
	# match on /ehr, /ehr?*, /ehr#*, /ehr/{uuid}, /ehr/{uuid}?*, /ehr/{uuid}#*
	# especially that we do not want to match /ehr/{uuid}/* as that pattern will be for other rules (compositions, contributions, etc)
	regex.match("/ehr(($|[?#])|(\/[A-z\\-0-9]{0,}($|[?#])))", input.request.http.path)
	input.request.http.method in ["POST", "PUT"]
	scope[_] in ["user/openehr-ehr.cu", "system/openehr-ehr.cu"]
}

...

Note that the above scope names were before the SMART on openEHR proposal was created but hopefully this gives at an idea of what we have done so far (at least with the REST API).

It should be possible to in theory evaluate any input data; for example if you needed some kind of “gateway” service that needed to evaluate the response body from the openEHR API against something within the users’ context (their token or data from an external source) – the more complicated part there is how to package both incoming response and other external data together and how you want to treat/attempt to standardize all of the various external systems or data sources that could be used there, I guess?

4 Likes

This is really interesting @joshua.grisham. I’m presenting our work at the annual conference in the UK tomorrow. Are you there by any chance, so we can discuss?

2 Likes