Versions 3.1.1 and 3.1.2 of the fhir-works-on-aws-authz-smart
package have been deprecated for necessary security updates. Please upgrade to version 3.1.3 or higher. For more information, see the fhir-works-on-aws-authz-smart security advisory.
FHIR Works on AWS is a framework that can be used to deploy a FHIR server on AWS. Using this framework, you can customize and add different FHIR functionality to best serve your use cases. When deploying this framework, by default Cognito and role based access control is used. However, if preferred, you can be authenticated and authorized to access the FHIR server’s resources by using SMART instead of Cognito. Cognito is the default AuthN/AuthZ provider because it is easier to configure than SMART. It doesn’t require setting up a separate IDP server outside of AWS as compared to SMART. However, Cognito authentication is not granular. When a new user is created, it is assigned into the auditor, practitioner, or non-practitioner groups. Depending on the group, the user gets access to different groups of FHIR resources.
The AuthN/Z providers are defined in package.json
and config.ts
. You can choose appropriate providers. SMART allows greater granularity into authentication than Cognito and is the FHIR standard. It allows you to access a FHIR record only if that record has reference to the user.
FHIR Works on AWS utilizes AWS Lambda, Amazon DynamoDB, Amazon S3 and Amazon Elasticsearch Service to provide the following FHIR features:
The easiest and quickest way to access FHIR Works on AWS is by using AWS solution. To modify the code and set up a developer environment, follow the steps below:
Note: AWS Solution provides an earlier version(See Solutions CHANGELOG for more details) of FWoA install. Please follow the instruction below to install from GitHub repository if you wish to install the latest version.
Example:
git clone https://github.com/awslabs/fhir-works-on-aws-deployment.git
Note: To modify FHIR Works on AWS, create your own fork of the GitHub repository. This allows you to check in any changes you make to your private copy of the code.
If you intend to use FHIR Implementation Guides read the Using Implementation Guides documentation first.
If you intend to do a multi-tenant deployment read the Using Multi-Tenancy documentation first.
If you intend to use FHIR Subscriptions read the Using Subscriptions documentation first.
The system architecture consists of multiple layers of AWS serverless services. The endpoint is hosted using API Gateway. The database and storage layer consists of Amazon DynamoDB and S3, with Elasticsearch as the search index for the data written to DynamoDB. The endpoint is secured by API keys and Cognito for user-level authentication and user-group authorization. The diagram below shows the FHIR server’s system architecture components and how they are related.
FHIR Works on AWS is powered by single-function components. These functions provide you the flexibility to plug your own implementations, if needed. The components used in this deployment are:
config.ts
, by specifying the maxBatchSize
when constructing the DynamoDBBundleService
.This project is licensed under the Apache-2.0 license.
After installation, all user-specific variables (such as USER_POOL_APP_CLIENT_ID
) can be found in the Info_Output.log
file. You can also retrieve these values by running the following command:
serverless info --verbose --region <REGION> --stage <STAGE>.
Note: The default stage is dev
and region is us-west-2
.
If you are receiving Error: EACCES: permission denied
when running a command, try re-running it using sudo
.
The FHIR API can be accessed through API_URL
using the following REST syntax:
curl -H "Accept: application/json" -H "Authorization: Bearer <COGNITO_AUTH_TOKEN>" -H "x-api-key:<API_KEY>" <API_URL>
For more information, click here.
To access APIs, you can use Postman as well. Postman is an API Client for RESTful services that can run on your development desktop for making requests to the FHIR Server. Postman is highly suggested and enables easier access to the FHRI API. You can use Postman to make API requests by following the steps below:
Importing the collection file
Under the Postman folder, you can access the JSON definitions for some API requests that you can make against the server. To import these requests into your Postman application, click here.
Note: Ensure that you import the Fhir.postman_collection.json collection file.
After you import the collection, set up your environment. You can set up a local environment, a development environment, and a production environment. Each environment should have the correct values configured. For example, the value for API_URL
for the local environment might be localhost:3000
while the API_URL
for the development environment would be your API gateway’s endpoint.
Setting up environment variables
Set up the following three Postman environments:
Fhir_Local_Env.json
Fhir_Dev_Env.json
Fhir_Prod_Env.json
For instructions on importing the environment JSON, click here.
The COGNITO_AUTH_TOKEN
required for each of these files can be obtained by following the instructions under Authorizing a user.
The following variables required in the Postman collection can be found in Info_Output.log
:
To find what FHIR Server supports, use the GET Metadata
Postman request to retrieve the Capability Statement
Authorizing a user
FHIR Works on AWS uses Role-Based Access Control (RBAC) to determine what operations and what resource types a user can access. The default rule set can be found in RBACRules.ts. To access the API, you must use the ID token. This ID token must include scopes of either openid
, profile
or aws.cognito.signin.user.admin
.
Using either of these scopes provide information about users and their group. It helps determine what resources/records they can access.
openid
scope returns all user attributes in the ID token that are readable by the client. The ID token is not returned if the openid scope is not requested by the client.profile
scope grants access to all user attributes that are readable by the client. This scope can only be requested with the openid scope.aws.cognito.signin.user.admin
scope grants access to Amazon Cognito User Pool API operations that require access tokens, such as UpdateUserAttributes
and VerifyUserAttribute
.For more information, click here.
Retrieving an ID token using aws.cognito.signin.user.admin
To access the FHIR API, an ID token is required. A Cognito ID token can be obtained using the following command substituting all variables with their values from Info_Output.log
.
scripts/init-auth.py <CLIENT_ID> <REGION>
python3 scripts/init-auth.py <CLIENT_ID> <REGION>
The return value is the COGNITO_AUTH_TOKEN
(found in the postman collection) to be used for access to the FHIR APIs.
Binary resources are FHIR resources that consist of binary/unstructured data of any kind. This could be X-rays, PDF, video or other files. This implementation of the FHIR API has a dependency on the API Gateway and Lambda services, which currently have limitations in request/response sizes of 10 MB and 6 MB respectively. The workaround for this limitation is a hybrid approach of storing a binary resource’s metadata in DynamoDB and using S3's get/putPreSignedUrl APIs. So in your requests to the FHIR API, you will store/get the Binary's metadata from DynamoDB and in the response object it will also contain a pre-signed S3 URL, which should be used to interact directly with the binary file.
Using Postman
To test, use Postman. For steps, click here.
Note: We recommend you to test binary resources by using the Binary
folder in Postman.
Using cURL
To test this with cURL, follow these steps:
curl -H "Accept: application/json" -H "Authorization: Bearer <COGNITO_AUTH_TOKEN>" -H "x-api-key:<API_KEY>" --request POST \
--data '{"resourceType": "Binary", "contentType": "image/jpeg"}' \
<API_URL>/Binary
curl -v -T "<LOCATION_OF_FILE_TO_UPLOAD>" "<PRESIGNED_PUT_URL>"
Bulk Export allows you to export all of your data from DDB to S3. We currently support the System Level export. For more information about bulk export, refer to the FHIR Implementation Guide.
To test this feature on FHIR Works on AWS, make API requests using the Fhir.postman_collection.json file by following these steps:
GET System Export
request to initiate an export request.<base-url>/$export/<jobId>
format.jobId
value from step 2 in that request.GET System Job Status
. If the job is in progress, the response header will have the field x-progress: in-progress
. Keep polling that URL every 10 seconds until the job is complete. Once the job is complete, you'll get a JSON body with presigned S3 URLs of your exported data. You can download the exported data using those URLs.
Example:
{
"transactionTime": "2021-03-29T16:49:00.819Z",
"request": "https://xyz.execute-api.us-west-2.amazonaws.com/$export?_outputFormat=ndjson&_since=1800-01-01T00%3A00%3A00.000Z&_type=Patient",
"requiresAccessToken": false,
"output":
[
{
"type": "Patient",
"url": "https://fhir-service-dev-bulkexportresultsbucket-.com/abc"
}
],
"error": []
}
Note: To cancel an export job, use the Cancel Export Job
request in the "Export" folder located in the Postman collections.
If changes are required for the Elasticsearch instances, you may have to redeploy. Redeployment deletes the Elasticsearch cluster and creates a new one. Redeployment also deletes the data inside your cluster. In future releases, we will create a one-off lambda instance that can retrieve the data from DynamoDB to Elasticsearch. To do this, you can currently use either of the following options:
Support for STU3 and R4 releases of FHIR is based on the JSON schema provided by HL7. The schema for R4 is more restrictive than the schema for STU3. The STU3 schema doesn’t restrict appending additional fields into the POST/PUT requests of a resource, whereas the R4 schema has a strict definition of what is permitted in the request. You can access the schema here.
Note: We are using the official schema provided by HL7.
POST
/PUT
request to the server, if you get an error that includes the text Failed to parse request body as JSON resource
, check that you've set the request headers correctly. The header for Content-Type
should be either application/json
or application/fhir+json
. If you're using Postman for making requests, in the Body tab, make sure to change the setting to raw
and JSON
.
We'd love to hear from you! Please reach out to our team via Github Issues for any feedback.