Introduction
Open Policy Agent (OPA) is a general-purpose policy engine that includes a high-level declarative language that you can use to define access control policies, enabling fine-grained access control in applications that leverage SMART on FHIR for authorisation and FHIR for data exchange.
SMART on FHIR
Let's take a look at how OPA can be used to support SMART on FHIR authorisation.
Policy Definition
OPA uses a declarative language called Rego to define policies. Rego allows you to specify rules for authorisation and other security aspects of your SMART on FHIR application.
For example, you could define a policy that uses request attributes (e.g., method and path), data elements in a Bearer Token (i.e., JSON Web Token (JWT)) (e.g., scope, roles, etc.) and other constraints:
package organization.read
methods := "GET HEAD"
path := "/fhir/Organization"
scope := "system/Organization.read"
default allow := false
allow if {
is_method
is_request_path
is_scope
}
is_method if contains(methods, input.request.method)
is_request_path if input.request.path == path
is_scope if contains(token.scope, scope)
bearer_token := t if {
v := input.request.headers.authorization
startswith(v, "Bearer ")
t := substring(v, count("Bearer "), -1)
}
token := payload if {
[_, payload, _] := io.jwt.decode(bearer_token)
}
Policy Evaluation
When a SMART on FHIR application requests access to a FHIR resource, OPA can act as a policy decision point. The request can be intercepted by an API Gateway and routed to OPA.
For example:
- name: provider-directory-api-organization-read
uri: /fhir/Organization*
methods: [ "GET", "HEAD" ]
upstream_id: 1
plugins:
opa:
host: "https://opa:8282"
policy: "organization/read"
- name: provider-directory-api-organization-write
uri: /fhir/Organization*
methods: [ "POST", "PUT", "PATCH", "DELETE" ]
upstream_id: 1
plugins:
opa:
host: "https://opa:8282"
policy: "organization/write"
OPA evaluates the (access control) policy and decides if the request should be 'allowed' or 'denied'.
Benefits of using Open Policy Agent
Fine-grained Access Control
OPA enables granular control over FHIR resource access, allowing you to specify exactly which FHIR resources an application can access and under what conditions.
Centralised Policy Management
OPA provides a central point for managing and enforcing policies, making it easier to maintain a consistent approach to access control across your application portfolio.
Improved Security
By decoupling policy enforcement from application logic, OPA helps reduce the risk of vulnerabilities and improves the overall security posture of your organisation.
Auditability
OPA policies are code, making them version-controlled and auditable.
Flexibility and Extensibility
OPA's Rego language is flexible and extensible, allowing you to define complex access control rules based on your specific needs.
Example Use Case
Imagine a SMART on FHIR application that needs to access a patient's medication information.
Using OPA, you could define a policy that allows access to medication information only if the application is launched by a clinician and if the patient has consented to data sharing.
When the application requests access to medication data, OPA would evaluate the request against the defined policy. If the conditions are met, OPA would grant access; otherwise, access would be denied.
In essence, OPA provides a powerful way to enhance the security and flexibility of SMART on FHIR applications by enabling fine-grained, policy-based access control, making it a valuable tool for organisations looking to leverage the benefits of both SMART on FHIR and a general-purpose policy engine.
Source Code
References
OAuth 2.0
- IETF: The OAuth 2.0 Authorization Framework
- IETF: The OAuth 2.0 Authorization Framework: Bearer Token Usage
- IETF: OAuth 2.0 Dynamic Client Registration Protocol
- IETF: OAuth 2.0 Token Exchange
- IETF: OAuth 2.0 for Browser-Based Applications
- Spring docs: Implementation Guidelines for Browser-Based Applications
HL7
- HL7: Implementation Guide
- HL7: FHIR NPM Packages
- AU Core: Publication (Version) History
- AU Core FHIR Implementation Guide: AU Core - 1.0.0-preview
- AU Core FHIR Implementation Guide: Testing FAQs
- Sparked AU Core Test Data: Postman collection
- HL7 AU: Australian Provider Directory Implementation Guide
Keycloak
- Keycloak docs: Configuring Keycloak for production
- Keycloak docs: Configuring TLS
- Keycloak docs: Configuring trusted certificates
- Keycloak docs: Configuring the hostname
- Keycloak docs: Using a reverse proxy
- Keycloak docs: Running Keycloak in a container
- Keycloak docs: Migrating to the Quarkus distribution
- Keycloak docs: Upgrading Guide - 26.1.0
- Keycloak docs: Authorization Services Guide
Keycloak-based Development
- GitHub: Keycloak Project Example
- GitHub: Awesome Keycloak
Keycloak Support
- Google Group: Keycloak User
- Google Group: Keycloak Dev
APISIX
- APISIX docs: Deployment modes
- APISIX docs: SSL Protocol
- APISIX docs: Certificate
- APISIX docs: Plugins - OpenID Connect
Open Policy Agent
- Open Policy Agent docs: Introduction
- Styra docs: Rego Style Guide
- GitHub: Awesome OPA - A curated list of awesome OPA-related tools, frameworks and articles
- Open Policy Agent: Playground
- Styra Academy courses: OPA Policy Authoring
- Open Policy Agent: Ecosystem
Provider Directory
- HAPI FHIR: Website
- HAPI FHIR: Documentation
- Google Group: HAPI FHIR