Skip to content

This repo holds the OpenSRP permissions checker and data access checker

License

Notifications You must be signed in to change notification settings

onaio/fhir-gateway-extension

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build codecov

fhir-gateway-extension

This repository extends the FHIR Info Gateway code base release artifact found here https://github.com/google/fhir-gateway and adds custom OpenSRP logic.

The custom functionality added includes:

  • Permissions Checker - Authorization per FHIR Endpoint per HTTP Verb
  • Data Access Checker - Data filtering based on user assignment (Sync strategy enhancements) i.e. Support for sync by Team/Organization, Location, Practitioner, Careteam
  • Custom FHIR resources REST endpoints i.e. PractitionerDetails and LocationHierarchy.

Getting Started

Pre requisites

FHIR Server (JPA Server):

The FHIR server must be configured to accept connections from the FHIR Info Gateway plugin.

Project and documentation can be found here https://github.com/hapifhir/hapi-fhir-jpaserver-starter

Keycloak Server

The keycloak server must be configured to perform authentication via the FHIR Info Gateway plugin.

Project and documentation can be found here https://github.com/keycloak/keycloak

Development setup

Modules

plugins

There is a module plugins that holds custom access checkers and custom end-points built on top of the Google's FHIR Info Gateway server and HAPI FHIR instance.

exec

There is also a sample exec module which shows how all pieces can be woven together into a single Spring Boot application.
See documention here

Generating the Plugins JAR

To generate the plugins JAR file, execute the following command from the plugins module:

$ mvn clean package

The generated JAR file can be found in the exec/target directory. Please note, we are not running the plugins jar explicitly. Instead we are running an exec module.

Configuration Parameters

Most of the configuration parameters are inherited from the FHIR Info Gateway and provided as environment variables. Below is a list of the required configurations.

  • ACCESS_CHECKER: Specify the OpenSRP Access Checker e.g.

     export ACCESS_CHECKER=permission

    For more on Access Checkers read documentation here.

  • PROXY_TO: The base url of the FHIR store e.g.

       export PROXY_TO=https://example.com/fhir
  • TOKEN_ISSUER: The URL of the access token issuer, e.g.

    export TOKEN_ISSUER=http://localhost:9080/auth/realms/test
  • ALLOWED_QUERIES_FILE: A list of URL requests that should bypass the access checker and always be allowed. AllowedQueriesChecker compares the incoming request with a configured set of allowed-queries. The intended use of this checker is to override all other access-checkers for certain user-defined criteria. The user defines their criteria in a config file and if the URL query matches an entry in the config file, access is granted. AllowedQueriesConfig provides all the supported configurations. An example of this is hapi_page_url_allowed_queries.json. To use this file with ALLOWED_QUERIES_FILE:

    export ALLOWED_QUERIES_FILE="resources/hapi_page_url_allowed_queries.json"
  • SYNC_FILTER_IGNORE_RESOURCES_FILE: A list of URL requests that should bypass the sync filter (sync by strategy) IgnoredResourcesConfig

    An example of this is hapi_sync_filter_ignored_queries.json. To use this file with ALLOWED_QUERIES_FILE:

    export SYNC_FILTER_IGNORE_RESOURCES_FILE="resources/hapi_sync_filter_ignored_queries.json"
  • BACKEND_TYPE: The type of backend, either HAPI or GCP. HAPI should be used for most FHIR servers, while GCP should be used for GCP FHIR stores.

  • CORS_ALLOW_ORIGIN: Specifies the CORS allowed origin. Only a single origin can be specified. It defaults to * if not set

Logging

The OpenSRP FHIR Gateway uses Sentry to capture exception logs. The Sentry integration is optional but if you enable it the following environment variables are required.

  • SENTRY_DSN - The Sentry DSN to send event logs to. Read more about Sentry DSN here. (Leave empty to disable sentry integration)
  • SENTRY_RELEASE - The release version of the Gateway you are running e.g. v1.0.8
  • SENTRY_ENVIRONMENT - The server environment you are running e.g. production
  • SENTRY_LOG_LEVEL - The minimum log level from which you wish to capture e.g. error

Note, Sentry can also be configured using an application.properties file in the classpath e.g.

# ../plugins/resources/application.properties

sentry.dsn=<dsn url>
sentry.logging.minimum-event-level=error
sentry.logging.minimum-breadcrumb-level=debug
sentry.environment=<environment> #e.g. production
sentry.release=1.0.8

or as JSON data through the SPRING_APPLICATION_JSON environment variable e.g.

{
  "sentry": {
    "dsn": "<sentry dsn>",
    "debug": false,
    "environment": "staging",
    "release": "1.0.8",
    "tags": {
      "release-name": "OpenSRP FHIR Gateway"
    }
  }
}

Note: If you want to disable Sentry integration just leave out the SENTRY_DSN configuration.

Caching

The plugins implementation supports caching for the sync strategy details which are expensive to fetch per request. By default, the sync strategy ids are cached for 60 seconds. You can however override this by passing a value to the OPENSRP_CACHE_EXPIRY_SECONDS environment variable. For this to work, one needs to pass a value greater than 0 e.g.

export OPENSRP_CACHE_EXPIRY_SECONDS=30

To disable caching, set the value to 0. Note, the value provided is in seconds. This configuration is optional.

Sync Filter Tags

Configurable sync filter tags parameters are now supported using the following environment variables

Monitoring

Spring actuator dependency has been added to provide monitoring for the application and its components using HTTP endpoints or with JMX. By default, the health endpoint is exposed over HTTP and JMX. To expose other endpoints e.g. prometheus, one has to update the application configuration.

Run project

As documented on the Info Gateway modules section here, the command to run is:

$ java -jar exec/target/opensrp-gateway-plugin-exec.jar --server.port=8081

After a successful build, the built-in Tomcat container will automatically deploy your Spring Boot application. You can access your application in a web browser by navigating to http://localhost:8080 (default) or the specified port in your application's configuration.

Tests

To run the unit tests use the command below which both runs tests and generates a code coverage report.

$ mvn clean test jacoco:report

The test report is located at /plugins/target/site/jacoco/index.html

Accessing FHIR and Custom Endpoints with the New Gateway

With the recent refactor in the gateway-plugin repository, accessing FHIR and custom endpoints through the new gateway has undergone changes. This section outlines the updated approach for accessing different types of endpoints.

FHIR Endpoints

When utilizing the (new) gateway, it is now mandatory to include the /fhir/ part in the URL when accessing FHIR endpoints. This adjustment aligns our structure with Google's gateway.

Example:

https://gateway.example.com/fhir/Patient

Custom Endpoints

For custom endpoints such as /PractitionerDetail and /LocationHierarchy, there is no need to include the /fhir/ part. Directly use the endpoint in the URL:

This approach ensures consistency and clarity when accessing various endpoint types through the gateway.

Custom Headers

FHIR-Gateway-Mode

Overview

The FHIR Gateway Mode allows for custom processing of responses from the FHIR server.

FHIR-Gateway-Mode: list-entries (Deprecated)

This mode is used when using the /List endpoint. Normally, fetching using this endpoint returns a list of references which can then be used to query for the actual resources. With this header value configured the response is instead a Bundle that contains all the actual (referenced) resources. This is now deprecated in favor of the mode query parameter. See below.

Custom Query Parameters

Mode

Pagination

Pagination is supported in fetching the data from a FHIR server. This can be useful when dealing with List resources that have a large number of referenced entries like Locations.

To enable pagination, you need to include two parameters in the request URL:

  • _page: This parameter specifies the page number and has a default value of 1.
  • _count: This parameter sets the number of items per page and has a default value of 20.

Example:

[GET] /List?_id=<some-id>&_count=<page-size>&_page=<page-number>&_sort=<some-sort>
LocationHierarchy list mode

The LocationHierarchy endpoint supports two response formats: tree and list. By default, the response format remains a tree, providing hierarchical location data. In addition, clients can request the endpoint to return location resources in a flat list format by providing a request parameter mode=list.

Example:

[GET] /LocationHierarchy?_id=<some-location-id>&mode=list&_count=<page-size>&_page=<page-number>&_sort=<some-sort>
LocationHierarchy Dynamic Identifier

The LocationHierarchy endpoint has the following supported functionalities when the _id is not provided as a parameter.

  1. Build location hierarchies of the User Assigned Locations: The LocationHierarchy endpoint will build location hierarchies of all user assigned locations

Example:

[GET] /LocationHierarchy
  1. Build location hierarchies of the User Selected Locations: The LocationHierarchy endpoint will build locations hierarchies of the locations provided by the user via the _syncLocations parameter.

    Conditions for User Selected LocationsHierarchies
    • The deployment/app user should have Related Entity Location as its sync strategy
    • The deployment/app user should have ALL_LOCATIONS role on keycloak.
    • The request should have _syncLocations parameter set

Example:

[GET] /LocationHierarchy?_syncLocations=<some-location-id>,<some-location-id>,<some-location-id>

All other valid parameters can be used on this endpoint.

LocationHierarchy Administrative Level Filters

The LocationHierarchy endpoint supports filtering by administrative levels. This is useful for querying locations at specific levels within the hierarchy. The following search parameters are available:

  • administrativeLevelMin: Specifies the minimum administrative level to include in the response. Locations at this level and above will be included.
  • administrativeLevelMax: Specifies the maximum administrative level to include in the response. Locations at this level and below will be included. If not set, it defaults to the value of DEFAULT_MAX_ADMIN_LEVEL set in the Constants.java file.

Behavior based on parameters:

  • No Parameters Defined: The endpoint works as it does currently, returning the full hierarchy.
  • Only administrativeLevelMin Defined: The response will include all locations from the specified minimum administrative level up to the root.
  • Only administrativeLevelMax Defined: The response will include all locations from the root down to the specified maximum administrative level.
  • Both Parameters Defined: The response will include locations only within the specified range of administrative levels.

Example:

[GET] /LocationHierarchy?_id=<some-location-id>&administrativeLevelMin=2&administrativeLevelMax=4&_count=<page-size>&_page=<page-number>&_sort=<some-sort>
Inventory Filters

The LocationHierarchy endpoint supports filtering by inventory availability, allowing users to specify whether they want to retrieve only locations that have associated inventories. This filter can be particularly useful for narrowing down the results to locations that are actively involved in inventory management.

The following search parameter is available:

  • filterInventory: A boolean parameter that specifies whether the response should be filtered by locations with inventories.
    • filterInventory=true: Only locations with inventories will be included in the response.
    • filterInventory=false (or not set): Locations with or without inventories will be returned. This effectively disables inventory-based filtering. The response will include all locations, regardless of their inventory status. Both locations with and without inventories will be returned.

Example:

[GET] /LocationHierarchy?_id=<some-location-id>&filterInventory=true&_count=<page-size>&_page=<page-number>&_sort=<some-sort>

Important Note:

Developers, please update your client applications accordingly to accommodate these changes in the endpoint structure.

Documentation