( read )

Securing an Azure-hosted FHIR API over HSCN/N3

Topics: DrDoctor tech

At DrDoctor we’re determined to push ahead with FHIR as the standard for interoperability in UK healthcare. Microsoft have developed an open source FHIR server that uses Azure services to deliver a fully operational API backed by a data repository. This is an enormous head start for anyone wanting to move to FHIR. 

Our first challenge with our shiny new Azure-hosted FHIR server was how to deliver the API securely over the NHS private HSCN network. Azure services are accessed using HTTPS over the internet. Cloud services require a mental shift: if you use an Azure Cosmos database for example, then it is accessed over the internet, even by the other components of your own application. How you secure it is important! If you get it wrong, it’s a bit like your house having a 3-inch thick steel front door with iris recognition, and a normal wooden back door with a standard mortice lock. 

Having decided our FHIR API was only going to be available over HSCN, we needed to be certain that the backend of it was going to be completely inaccessible via the public internet. The normal access controls used to restrict access to Azure services wouldn’t suffice 

The rest of this article is a how-to that might be useful to anyone wanting to get an Azure-hosted API working over HSCN with its associated backend services properly secured. Bottom line: we did it! 

Using an Application Gateway to control App Service access 

By deploying an Azure Application Gateway in a new subnet in the HSCN VNet and only configuring it with a private IP address we can use it to control access to the FHIR App Service. 

To configure an Application Gateway to make an App Service only visible via an ExpressRoute: 

  1. Create a new subnet in the HSCN VNet. Application Gateways can only be deployed in their own subnet they cannot share it with other Azure resources. 
  2. Enable the Web Service Endpoint for that subnet. This allows web requests to be routed to Azure web services via the Azure backbone instead of the internet. 
  3. Deploy an Application Gateway in the new subnet and configure it for the FHIR service. There are various options that need selecting in order to support an App Service as backend target 
  4. In the FHIR App Service under the networking option connect it to the subnet that contains the Application Gateway created above, then add a networking rule that only allows requests from the subnet 
  5. The FHIR App service should now only be available on private IP address assigned to the Application Gateway. You can test this from a virtual machine that is in the same VNet as the Application Gateway. 
  6. Configure IP forwarding for one of your HSCN addresses to the private IP address of the Application Gateway 
  7. Request NHS Digital to add a DNS entry to point to the HSCN IP address used. Now your partners can access the FHIR API using a URL 
  8. Obtain an SSL certificate that matches the DNS name and install it to the FHIR App Service. 

Securing Cosmos DB so it can only be accessed by other services in our VNet 

To make sure Cosmos DB could only be accessed by our own FHIR service, we used VNet Service Endpoint in combination with a new VNet Integration for the App Service. 

Using Vnet Service Endpoint, you can configure Azure Cosmos DB to allow access only from a specific subnet of a VNet: only requests originating from those subnets will get a valid response, whereas requests originating from any other source will receive a 403 (Forbidden) response. 

There is also a new VNet Integration, in preview at time of writing, that allows you to configure an App Service to access a resource across Service Endpoints. It’s currently only available from newer Azure App Service scale units. 

Configuring App Service with New VNet Integration 

The new VNet Integration capability is only available from newer Azure App Service scale units. If you can scale to PremiumV2, then you are in a newer App Service scale unit. 

For this we will be using subnet created for our FHIR service in the previous section. Make sure that it doesn't have any Service Endpoints or Subnet Delegation configured.  

  1. In the Azure Portal, select the App Service that you want to configure, click on Networking. Then under VNet Integration click on Click here to configure. Please note that if the SKU for the App Service is not Standard or Premium, the next page will show "Upgrade to a Standard or Premium Plan to configure a VNet." and you'll not be able to go on with the configuration 
  1. Click on Add VNet (preview). Make sure NOT to click on Add VNet as that is the old VNet integration. Note that if the SKU is not a V2, the Add VNet (preview) will not appear 
  1. In the blade Network Feature Status select the VNet 

References 

Configuring Cosmos DB with VNet Service Endpoint 

  1. In the Azure Portal, select the the Cosmos DB you want to configure, then click on Firewall and Virtual Networks. 
  1. Under Allow access from, choose Selected Network 
  1. Click on Add existing virtual network 
  1. Select the Virtual Network and then the subnet  
  1. Click on Enable and then Save 
  1. Usually the Firewall setup takes more than 5 minutes. When the operation is marked as done in the portal the configuration will be effective after few more minutes. 

References 

A couple of other options we tried and discarded 

It would be possible to use an Azure App Service Environment (ASE) to run the FHIR App Service in an isolated environment, and pair that environment to a VNet. This would keep traffic between other Azure services and the ASE on the Azure backbone network. The cost of an ASE is high (around £800/month at time of writing) so we didn't explore this option any further. For more info on these Azure services see here and here. 

We thought we could force Cosmo DB to accept connections only from the FHIR App Service through IP rules, but the App Service outbound IPs are not static. In the App Service properties there is a list of possible IPs, but they could change when the application scales between different tiers (see: https://docs.microsoft.com/en-gb/azure/app-service/overview-inbound-outbound-ips#when-outbound-ips-change).