This project allows to expose a DICOM WADO / QIDO endpoint on top of an AHI datastore. The project depends on the AHI metadata index project configured with the RDBMS mode. See how to deploy the metadata index in RDBMS mode 1st, before this AHI DICOMWeb proxy can be used.
This project is 100% python based and can be installed simply by copying the content of this repository onto an EC2 instance running ubuntu 22.04. The DICOMWeb proxy service needs to connect to the metadata-index MYSQL database with a database user granted with read-only permissions, and to the AHI datastore(s) referenced in the metadata index database. Upon start-up the service gets the database information and user credentials from AWS Secrets Manager. Here is a TODO list of what should be configured and installed for this project to function, below are also more detailed steps if needed :
- Create a read-only database user in the RDBMS metadata index MYSQL database.
- Create a Secrets Manager secret representing the read-only user and database connection information.
- Create an IAM policy and IAM role that will be used by the EC2 instance to access to the secret in Secrets Manager and the AHI datastore.
- Create an EC2 instance with the Ubuntu 22.04 Linux image.
- Assign the newly created role to the instance.
- Update the RDS instance security group to allow the EC2 instance to access to the database.
- Install the project files from the repository and execute it via python.
- [Optional] : Install systemctl config files for the DICOMWeb proxy application to be managed as a Linux service.
- With your preferred database client, connect to the RDS MYSQL instance created by the metadata index project deployment with an admin user.
- Once connected, run the following command:
CREATE USER 'dicomwebproxy'@'localhost' IDENTIFIED BY '[Replace this by your own password]';
GRANT SELECT, SHOW VIEW ON `ahiindex`.* TO 'dicomwebproxy'@'localhost'
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'dicomwebproxy'@'localhost'
- Navigate in the AWS console Secrets Manager menu.
- Click on the
[ Store a new secret ]
button. - Create the secret with the following parameters:
Secret Type: Credentials for Amazon RDS database
User name: dicomwebproxy
Password: Enter the password you have entered while creating the database user.
Database: Select the database cluster hosting the AHI metadata index.
Secret name: ahi-dicomwebproxy.
Description: "This secret is used by the DICOMWeb proxy service to connect to the AHI metadata index."
- After the Review menu, click
[ Store ]
. - Refesh the secret list and click on the new secret.
- In the secret detail menu, note down the secret ARN. It will be used in the next steps.
We will create an IAM role that will be assigned to the EC2 instance running the DICOMWeb proxy service. This role is given privileges to access to the secret in Secrets Manager secret and to the AHI datastore with read-only permissions only.
- In the AWS Console IAM service menu, select
Policies
in the left navigation menu and click[ Create Policy ]
. - In the
Specifiy permissions
menu , click on the [JSON] button, and copy the following policy in the text editor:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "[Replace this value with the secret ARN noted above.]"
}
]
}
- Click
[ Next ]
. - In the Policy details menu, enter the following information, then click
[ Create Policy ]
.
Policy Name: ahi-dicomwebproxy-secretmanager-access
Description: This policy allows the DICOMWeb Proxy service to access to the database secret.
- In the AWS Console IAM service menu, select
Policies
in the left navigation menu and click[ Create Policy ]
. - In the
Specifiy permissions
menu , click on the [JSON] button, and copy the following policy in the text editor:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"medical-imaging:GetImageSet",
"medical-imaging:GetImageSetMetadata",
"medical-imaging:GetImageFrame"
],
"Resource": [
"[Replace this by your AHI datastore ARN]/imageset/*",
"[Replace this by your AHI datastore ARN]"
]
}
]
}
- Click
[ Next ]
. - In the Policy details menu, enter the following information, then click
[ Create Policy ]
.
Policy Name: ahi-dicomwebproxy-ahi-access
Description: This policy allows the DICOMWeb Proxy service to access to the AHI datastore.
- In the AWS Console IAM service menu, select
Roles
in the left navigation menu and click[ Create role ]
. - Enter the following parameters :
Trusted Entitiy type: AWS service.
Use case: EC2.
- Click
[ Next ]
. - In the Add permissions menu , select the policy
ahi-dicomwebproxy-secretmanager-access
. - In the Add permissions menu , select the policy
ahi-dicomwebproxy-ahi-access
and click[ Next ]
. - In the Name, review, and create menu, enter the following parameters, then click
[ Create role ]
:
Role Name: ahi-dicomwebproxy-ec2-role
Description: This role allows the DICOMWeb Proxy service to access to the database secret and AHI datastore.
At this point we have configured the database user, created a secret in Secrets Manager and created the IAM policy and role. We can now create the EC2 instance that will host the DICOMWeb service. Configure the EC2 instance with the following parameters :
Name: ahi-dicomweb-proxy.
Application and OS Images: Select ubuntu 22.04 LTS.
Instance type: Select an instance with 4 CPUs and 8GB of RAM or above. Eg: c6a.xlarge.
Key pair: Select your preferred key pair.
Network settings: Click on [ Edit ]
and enter the following parameters :
VPC: Select the same VPC as the one hosting the metadata index database.
Subnet: Select a public subnet.
Firewall:
Select Create security group
Security group name : ahi-dicomwebproxy
Description : Security group for ahi-dicomweb proxy service.
Inbound Securty Group Rules : Add a new rule of type Custom TCP
with the port 8080
. The source depends on your on needs. If you are unsure select My IP
for the source type, this will only allow accessing the DICOMWeb service from the public IP address you are currently accessing to the AWS Web Console with. These settings can be changed later on.
Configure Storage: Configure the storage with 150GB
of capacity and type GP3
.
- Click
[ Launch Instance ]
. This will create the instance.
Configure the security group of the RDS instance for the metadata index database to allow the security group of the EC2 instance created above to access to the RDS instance on port 3306
.
The service requires python 3.10 which should come by default on ubuntu 22.04 python. To simplify its usage we can install the python-is-python3 package which allows to link the python
command to the latest python3.x version.
sudo apt update -y && sudo apt upgrade -y
sudo apt install python-is-python3 -y
sudo apt install python3-pip -y
cd ~
git clone https://github.com/aws-samples/aws-healthimaging-samples.git
cd aws-healthimaging-samples
cd ./dicomweb-proxy
python -m pip install -r requirements.txt
The application can then be executed with the following command:
DB_SECRET_ARN=[Secrets Manager secret ARN created in the Creating the secret in Secrets Manager section] AWS_DEFAULT_REGION=[The AWS region where this instance is hosted] python main.py
The service startup log should look like this :
INFO:botocore.credentials:Found credentials in shared credentials file: ~/.aws/credentials
INFO:root:[Startup] - Forking FrameFetcher FF0
INFO:root:[Startup] - Forking FrameFetcher FF1
INFO:root:[Startup] - Forking FrameFetcher FF2
INFO:root:[Startup] - Forking FrameFetcher FF3
INFO:root:[Startup] - Forking FrameFetcher FF4
INFO:root:[Startup] - Forking FrameFetcher FF5
INFO:root:[Startup] - Forking FrameFetcher FF6
INFO:botocore.credentials:Found credentials in shared credentials file: ~/.aws/credentials
INFO:root:QIDO/WADO-RS service started.
INFO:waitress:Serving on http://0.0.0.0:8080
Optionally the code can be turned into a standalone one file application for better portability.
python -m pip install nuitka
nuitka3 --follow-imports --include-package=pydicom --standalone --onefile main.py
Once compiled the application is bundled into the main.bin exectuable. In this form the applicaiton can be executed with the followinf command:
DB_SECRET_ARN=[Secrets Manager secret ARN created in the Creating the secret in Secrets Manager section] AWS_DEFAULT_REGION=[The AWS region where this instance is hosted] ./main.bin
Once installed and started the service listens on the port 8080 by default
. It exposes the below resources :
Resource | Description |
---|---|
/aetitle/health | Health monitoring resource. Returns HTTP response code 200 and responde body : OK when the service is functional. |
/aetitle/studies | QIDO resource for querying at the study level. |
/aetitle/studies/<studyInstanceUID>/series | QIDO resource for querying at the series level in the context of a study. |
/aetitle/studies/<studyInstanceUID>/instances | QIDO resource for querying at the instance level in the context of a study. |
/aetitle/series | QIDO resource for querying at the series level. |
/aetitle/studies/<studyInstanceUID>/series/<seriesInstanceUID>/instances | QIDO resource for querying at the instance level in the context of a series. |
/aetitle/instances | QIDO resource for querying at the instance level. |
/aetitle/studies/<StudyInstanceUID>/metadata | WADO resource for querying study metadata. |
/aetitle/studies/<StudyInstanceUID>/series/<SeriesInstanceUID> | WADO resource to retrieve instances of the series as multipart HTTP response. |
/aetitle/studies/<StudyInstanceUID>/series/<SeriesInstanceUID>/metadata | WADO resource to retrieve metadata of a series. |
/aetitle/studies/<StudyInstanceUID>/series/<SeriesInstanceUID>/instances/<InstanceUID> | WADO resource to retrieve a bulk instance as multipart HTTP response. |
/aetitle/studies/<StudyInstanceUID>/series/<SeriesInstanceUID>/instances/<InstanceUID>/rendered | WADO resource to retrieve a rendered representation of the image in JPEG format. |
/aetitle/studies/<StudyInstanceUID>/series/<SeriesInstanceUID>/instances/<InstanceUID>/metadata | WADO resource to retrieve the metadata of an instance. |
/aetitle/studies/<StudyInstanceUID>/series/<SeriesInstanceUID>/instances/<InstanceUID>/frames/<Frames> | WADO query to retrieve the frame of an instance. Unlike the standard that allows multiple frames to be requested at once, this resource only allow 1 frame to be returned. (Fits most open source viewers implementation) |
The service can be used by configuring the DICOMWeb endpoint of your client with the public DNS or IP address of the EC2 instance in the following URL to http://[EC2 instance IP or DNS]:8080/aetitle
. See an example below with the WEASIS application: