By Srikantan Sankaran | March 2018 | Get the Code
Azure Key Vault is a cloud-based service that lets organizations securely store sensitive business information. It lets you perform cryptographic operations on the data, and provides a framework for implementing policies to regulate access to applications, as well as an API model for applications to work with the keys, secrets and certificates stored in it. The SDKs that Azure Key Vault provides support a variety of device platforms and programming languages, allowing you to choose your preferred language and to deploy these applications to Azure App Service as managed Web applications. To expose these business applications securely to users both within an organization and outside, Azure Active Directory (Azure AD) and Azure Active Directory B2C (Azure AD B2C) provide turnkey implementations to enable authentication and authorization to the applications with minimal or no custom code. In this article I’ll present a solution that demonstrates how Azure Key Vault can bring enhanced security to your organization.
A central agency is tasked with implementing a solution to issue, track and manage insurance policies for vehicles. The agency generates unique document serial numbers on receipt of orders and payment from insurance companies. These companies, either directly or through their brokers, assign insurance policies to the document serial numbers as they’re sold to motorists. Document serial numbers are unique across all insurance companies.
The goal of the solution is to track the lifecycle of the document serial number. When created, a document serial number contains only its number and the name of the insurance company to which it’s sold. Further into the business process, additional information, such as the vehicle registration, policy document number, identity of the customer and validity period of the insurance policy, will be added. All versions of this record must be tracked, including any changes made, the date and time of the changes, and the identity of the application that made the change.
Customers should be able to access the policy electronically and download the information securely for verification and easy reference.Architecture of the Solution
The solution uses Azure Key Vault to store the document serial number, along with the properties of the associated insurance policy, as a secret. For additional security, the data that’s stored as a secret is encrypted beforehand using asymmetric keys generated in Azure Key Vault. While only the bare minimum data required to secure and validate each policy gets captured in the secret, additional supporting information is stored in an Azure SQL Database. The database also implements constraints on the data, to ensure, for example, that a registered vehicle has a single active policy number, that the same policy number hasn’t been used for multiple records, and so forth. Figure 1 represents the architecture used in the Solution.
Figure 1 Solution Architecture
I’ve implemented two portal applications in this solution, one that’s used by the central agency and insurance companies, and the other by customers who buy insurance policies and by regulatory authorities who need to ascertain the validity of the policies.
The admin portal and the customer portal are ASP.NET 2.0 Core MVC applications that use Entity Framework to store policy data in an Azure SQL Database, after it has first been stored in Azure Key Vault. The .NET SDK for Azure Key Vault is used to perform the cryptographic operations on the data, such as the creation of secrets and their versions and the encryption and decryption of the secrets using keys. Users of the admin portal are authenticated with Azure AD, while customers, who are external users, use Azure AD B2C to self-register and sign in to the customer portal.
Separate service principals in Azure AD are created for the admin and customer portals, and separate policies are set that lock down their access to operations in Azure Key Vault. The admin portal policy permits the creation of keys and secrets, as well as the performance of operations like the encryption and decryption of data. The customer portal, in contrast, is assigned a policy that permits only the “get” operation on a secret and the “decrypt” operation on the secret retrieved. This ensures that individual applications don’t have more access than needed to Azure Key Vault.
The policy data stored as a secret in Azure Key Vault is first encrypted, for additional security. Every time the secret is updated, a new version gets created, and previous versions of the data are preserved. An audit trail is also maintained for all operations performed in the Key Vault, which is archived to meet statutory compliance requirements.
The attribute bundle of the secrets stored in Azure Key Vault captures the policy start and end dates, which are used to ascertain the validity of the policy. Tags and content-type parameters of secrets are used to store additional information pertaining to the insurance policy.
The following code snippet shows how the attributes, tags and content types are added to the policy data stored as a secret:
Let’s take a closer look at the use case scenario that’s implemented by the solution. Here are the basic steps:
Purchase of Unique Codes by Insurance Companies: On receipt of orders from the insurance companies, the central agency uses the admin portal to generate an inventory of document serial numbers and store them as secrets in Azure Key Vault. The admin portal creates the first version of a secret in Azure Key Vault and then creates a record in Azure SQL Database.
Policy Generation: When a customer purchases a vehicle policy, an unassigned secret from the previous step is chosen and additional information, such as the vehicle registration number, the identity of the customer, the policy document number generated and the validity period of the policy, is added. A new version of the original secret containing this additional information is created in the process, and the corresponding record in Azure SQL Database is also updated.
Activation of Policy by Customer: Once all the details of a policy are captured in the secret, a notification is sent to the customer (outside the scope of this article) with instructions for activating the policy. Users can self-register on the customer portal either using their social credentials or the credentials stored in Azure AD B2C. When the customer is signed into the portal, the policy details are displayed along with an option to activate it. On activation, the user downloads a QR code from the portal and affixes its image to the insured vehicle.
Policy Validation: Customers or regulatory authorities can validate the policy anytime using a native Xamarin app that reads the QR code on the vehicle and displays the policy details in it, to be tallied with that on the vehicle. This validation doesn’t require an Internet connection and can be done offline. When connected to the Internet, additional validation can be performed. The native app invokes a REST API that’s exposed in the customer portal MVC application, passing the data from the QR code. The API first matches this data with the data in Azure SQL Database, and additionally with the data stored in the secret in Azure Key Vault.Technical Aspects of the Solution
Now let’s delve into the source code and automation scripts used in the solution. Keep in mind that the code and scripts shared in this article are by no means intended to be a complete solution, nor do they necessarily handle all validations, exceptions or best practices required in a production-ready application. They are meant rather to illustrate specific aspects of a technology area or to provide guidance toward developing a full-fledged solution.
Create and Configure Azure Key Vault The PowerShell script files PrepareContosoAKV.ps1 and PrepareContosousersAKV.ps1, included with the accompanying download, are used to provision and configure the key vault used in this article. Here’s what they accomplish:
- Creation of self-signed certificates (to be used only in dev scenarios) for the admin and custmer portal ASP.NET MVC applications, which are used when creating the service principals in Azure AD.
- Creation of a service principal in Azure AD that’s assigned to the admin portal. The access policy that’s set for this service principal permits creation and update of keys and secrets, and the performance of operations like encryption and decryption:
- Creation of a service principal in Azure AD that’s assigned to the customer portal. The access policy that’s set for this service principal permits Get operations on keys and secrets, and the decryption of data:
- Note that there’s an alternative to creating these service principals with PowerShell, which is to use the Managed Service Identity feature in Azure App Service. This is actually recommended. Refer to the guidance at bit.ly/2BgB6mu for more details.
- Creation of a key used for the encryption and decryption of a secret.
- Creation of a secret that stores the connection string to the Azure SQL Database. (This can be done directly on the Azure Portal, as can the other steps.)
For simplicity, this solution uses a single key vault, and a single set of keys for all insurance companies and brokers to encrypt and decrypt the data. In the real world, for added isolation and security, separate Azure Key Vault instances should be created for each insurance company, and grouped by region, for example, or any other criteria. This ensures that the data maintained by one insurance company can’t be read by others because they wouldn’t share the same encryption key.
Keep in mind that secrets stored in Azure Key Vault must be no more than 25KB in size. Hence, to avoid bloat, only certain properties of the policy data are stored in it, such as ID (document serial number), secret name, user ID, policy number and insurance company ID. The Entity Insdata.cs file in the Visual Studio 2017 solution ContosoInsAuthorityAdminPortal.sln contains these properties. Other properties, like the effective start and end dates, content type, and so on, are stored as attributes of the secret in the key vault.
Build the Admin and Customer Portal Applications Refer to the Visual Studio 2017 solution ContosoInsAuthorityAdminPortal.sln in the download for the admin portal source code, and to ContosoinsExtPortal.sln for the customer portal code.
Both the admin and customer portals are built using ASP.NET Core 2.0, which supports dependency injection to add framework services—like Entity Framework integration and custom service modules to access the Azure Key Vault APIs—to the application in the start-up class.
Visual Studio 2017 project templates provide turnkey integration with Azure AD and Azure AD B2C for user sign-in and sign-up experiences to secure access to the portal applications.
The connection string for the Azure SQL Database is stored in Azure Key Vault and is retrieved by the portal Web application at start up.
The code snippet in Figure 2 shows how dependency injection in ASP.NET 2.0 Core is added for Entity Framework Azure AD authentication and for the access provider, Azure Key Vault Service API, access and to read application configuration data from the appsettings.json file.
The Azure Key Vault configuration provider for ASP.NET Core 2.0 (bit.ly/2DfOXeq), available as a NuGet package, provides a turnkey implementation to retrieve all secrets from Azure Key Vault at application start. However, this feature is not used in the solution to avoid loading all the business data unnecessarily on application start, that is, the insurance policy secrets, along with other secrets that application requires, such as the connection string to access the Azure SQL Database. This feature could be used when one key vault instance is used to store all connection strings required by the application, and a separate key vault instance is used for the business data.
App Service Creation The admin and customer portal applications are deployed as Azure App Service Web apps using the built-in tools in Visual Studio 2017. Both Web apps are hosted inside a single App Service Plan.
During development, the ASP.NET Core MVC applications can be deployed locally using Visual Studio 2017. When the PowerShell scripts I discussed earlier are run, two digital certificates are generated, one for each portal application. The .pfx files are added to the current user’s certificate store. These are embedded in the requests that the ASP.NET MVC applications make to access the Azure Key Vault APIs. The thumbprints of these certificates are added to the appsettings.json file in the Visual Studio 2017 solution of the respective ASP.NET MVC applications.
When deploying the application to Azure App Service, you must:
- Upload both.pfx files to the Azure App Service instance from the Azure Portal.
- Create the entry “WEBSITE_LOAD_CERTIFICATES” in the App Settings blades of both the admin and customer portal Web apps in the Azure Portal, and add the thumbprint of the respective .pfx file.
Refer to the documentation at bit.ly/2mVEKOq for more details on the steps to be performed.
Database Creation The script file used to create the database for the solution is available for download along with the other artifacts of the solution. Transparent data encryption (TDE) and audit is enabled on the database.
Azure AD and Azure AD B2C Tenant Creation The default Azure AD tenant in the Azure subscription is used as the identity provider for the internal users of the central agency accessing the admin portal. A separate Azure AD tenant is created in this subscription where the users representing the insurance companies are registered. These users are added as guest users to the default Azure AD tenant to access the portal applications. If the insurance companies have their own Azure AD tenant, Azure AD B2B can be used to federate that tenant with the default Azure AD tenant in this subscription.
From the Azure Portal, an Azure AD B2C tenant is created in the Azure subscription and policies are defined to permit customers to self-signup for access to the customer portal. In the identity providers section of the Azure AD B2C configuration, local accounts in this tenant are set to “user name” as opposed to e-mail address, and e-mail verification on user signup is disabled, for simplicity. Refer to the documentation of Azure AD B2C for guidance on creating and configuring policies for the sign-in and sign-up experiences (bit.ly/2n7Vro9).
To allow you to run this solution, I’ve provided sample credentials for signing in to the admin and customer portals in the GitHub repository associated with this article.
To keep the solution simple for this article, I haven’t implemented the step in which insurance companies purchase unique codes. Instead, users of the admin portal would directly execute the next step, where the document serial number, customer information, policy and vehicle details are captured all in one shot.
Figure 3 shows the landing page of the admin portal—Contoso Insurance. You can sign in to the admin portal using the credentials of an insurance company user and select Create New to enter the details for a new document. The document serial number is auto-generated by the application and can be viewed only in the New or Edit Item Form.
Figure 3 Insurance Policies List on the Contoso Insurance Admin Portal Landing Page
Figure 4 shows different versions of the insurance policy data stored as a secret. You can also view additional information, such as content type, tags and attributes. Notice that the Secret is encrypted before it’s stored.
Figure 4 Different Versions of the Insurance Policy Data Stored as a Secret, as Seen on the Azure Portal
If you sign in to the customer portal, you can view all the insurance policies that were purchased and are ready for activation. The Edit policy page provides an option to activate the policy, which then updates the status of the policy in Azure SQL Database to Active. Once the policy is activated, you can use the Download Policy option, which generates a QR code for the policy data.
Figure 5 shows the user experience on the customer portal for downloading the QR code. Also shown is the JSON data that is read from the QR code using an app on a mobile device. A native app scans the QR code and displays formatted policy details on the screen, for easy offline verification.
Figure 5 QR Code Generation
Additional security could be implemented by having the customer portal sign the JSON data using a private key in Azure Key Vault and generating a QR code on the signed data. The native mobile app could be shipped with the public key required to verify the signed data before displaying the JSON data on the device for verification.
Policies can be validated either offline or online. Offline validation can be performed using any QR code reader app on a mobile device, or by using a native Xamarin app. After the QR code is scanned, the results are displayed in a user-friendly way for verification.
In contrast, Figure 6 shows a request for validation sent using the Postman tool (getpostman.com) to the API in the MVC application, which returns the outcome of the validation as a Boolean. In this case, the policy start date is later than the current date so the outcome of the validation is “false.” A Xamarin app is used to sign the user in, scan and view the QR code data and make a request to this API to perform online validation.
Figure 6 REST API Call to Validate a Policy
All operations on Azure Key Vault can be audited and the logs archived for compliance with statutory regulations. You can enable auditing from the Settings blade in the Azure Portal for the Azure Key Vault service instance. To view the logs, navigate to the Azure storage resource configured for the logs. You could use role-based access control (RBAC) in the Azure Portal to ensure only designated users can access this information.
All operations on the data in Azure SQL Database can also be enabled for audit, from the Settings blade of the database instance in the Azure Portal. Transparent data encryption of the data at rest in Azure SQL Database is by enabled by default.Deploying the Solution
If you’d like to try out this solution on your own, you can download the source files and scripts from the GitHub repository at bit.ly/2DRvwdh. You’ll need the following software to implement this solution:
- Visual Studio 2017 Preview, Community or Enterprise Edition with update 3
- An Azure subscription
- A Windows PowerShell script editor
To deploy the solution in your own subscription, you’ll need to update the config entries in the appsettings.json file after the PowerShell Scripts are executed and the other resources are provisioned in the Azure subscription. The steps to do this have been provided in the GitHub repository along with the source code and solution files described in this article. Many thanks to Bindu Chinnasamy of the Microsoft CSE team for help with building the solution accompanying the article.Wrapping Up
Azure Key Vault provides a helpful, efficient platform for businesses to securely manage their sensitive information, using industry standard algorithms and techniques to perform cryptographic operations. It lets developers use the SDKs for the platforms and languages to which they’re accustomed. This, coupled with the rich set of additional services in Azure, such as Azure App Service, Azure AD and Azure B2C, and the elaborate tooling support these services provide, lets developers focus on building core business features, thereby significantly reducing the time required to develop and deploy an end-to-end solution.
In the sequel to this article, I will be demonstrating how the same application could, without significant changes, be deployed to Azure Container Service using Docker Containers and Kubernetes.
Srikantan Sankaran is a principal technical evangelist from the One Commercial Partner team in India, based out of Bangalore. He works with numerous ISVs in India and helps them architect and deploy their solutions on Microsoft Azure. Reach him at [email protected]
Thanks to the following Microsoft technical expert for reviewing this article: Frank Hokhold, Bindu Chinnasamy
Many thanks to Frank Hokhold for reviewing this article. Frank is a Developer Experience Program Manager from the Azure Key Vault Team.
Many thanks also to Bindu Chinnasamy, from the Microsoft CSE Team, for help with building the Solution accompanying this article.