Skip to main content

Adoption

Code Repositories

Clone/fork the following repositories:

The latter 2 produce Nuget packages, which if made public, could remove the need to clone their repositories.

Nugets

HACT.Dtos and HousingRepairsOnline.Authentication produce Nuget packages which are consumed by other components.

Each repository contains setup instructions which can be followed to establish connectivity.

Infrastructure

Azure is the supported Cloud platform.

Create the following resouces in Azure:

APIs

  • Azure app service plan
    • Consider which service plan would best suit the needs. Premium V2 (P1v2: 1) is recommended
    • Use a region which is geographically close to the users/residents and the 3rd party data
  • Azure app service for each API
    • Create a 'staging' deployment slot
    • Each app service (and it's deployment slot) will have a publish profile which needs to be added to the repository secrets1
  • Cosmos DB
    • 2 databases - production and staging
    • Each with repair-requests collections
  • Blob storage account
    • Create 2 containers - production and staging for the storage of user-uploaded images
    • Create a container for Terraform State Storage - 'tfstate'
    • Create a container for insight report address .csv files: 'insight-report-addresses'
  • Resource Provider Registrations
    • Some resources require that the subscription is registered to use their respective namespace.
    • Key vault and managed identity are examples of such resources. See here.
  • Key Vault
    • Consider whether to have a key vault per environment e.g Staging API key vault, Production API key vault.
    • Create a key vault for each API at least, best practice is not to have one key vault to hold all secrets.
    • Seperate the key vaults appropriately based on needs, cost and use.
  • Managed Identity for Key Vault
    • Create a managed identity for each API (would recommend creating a user assigned identity).
    • Add key vault permissions to the identity so that the attached app service has access the relevant key vault.

Frontend

  • Create Azure Static Web App
    • A deployment token will need to be added to the repository secrets1
  • (Optional) Add a custom domain to the Azure Static Web App2
    • e.g. repairs.abc_council.test.uk

Deploying to Azure

An Azure service principal is an identity created that can be used for automated tools such as GitHub actions to access Azure resources. This access is restricted by the roles assigned to the service principal, giving you control over which resources can be accessed and at which level. In order to assign access to the service principal, you must have the necessary access to so.

Create a service principal

  1. Ask your subscription administrator to add you to the User Access Administrator role. See documentation. (If the subscription administrator is creating the service principal, ensure that you request the environment variables as specified in the Adding GitHub actions job and secrets step)
  2. Create the service principal. See documentation.
  3. Assign a role to the service principal as per this documentation. If you are not able to do this, contact your subscription administrator as you do not have the permission to do so
  4. Create a client secret for your service principal. See documentation. Make sure to keep a note of the secret or copy it to your clipboard

Terraform state storage

Terraform is an infrastructure as code tool which we will be using to provision the Azure resources to deploy our application. Terraform needs to be able to store its state so it is aware of what resources it has created/destroyed/updated etc. This state will be stored remotely in an Azure storage container. Complete the following steps in the Azure web portal to create the storage container:

  1. Create a resource group for your infrastructure or use an existing one where your resources can be deployed. This resource group will be used for all other resources you provision so you should make it generic, e.g. housing-repairs-online. Add the resource group name and location as RESOURCE_GROUP_NAME and RESOURCE_GROUP_LOCATION respectively to github actions secrets.
  2. Create a storage account use the resource group you created above. Add the name of the storage account you created to github secrets as STORAGE_ACCOUNT_NAME.
  3. In that storage account, create a container called tfstate. This is where your state files will live. Create a github action secret called CONTAINER_NAME with the value tfstate
  4. Create github actions secret called STATE_KEY_NAME with the value {SERVICE_NAME}.tfstate

Adding GitHub actions job and secrets

Once you have added a remote backend to your Terraform and created a service principal, GitHub actions should be configured to deploy resources to Azure using Terraform. We will be using the setup-terraform action to run Terraform in github actions

  1. Add the following secrets as your github repository secrets, these are only available to you if you have access to create a service principal so ensure to request these if the service principal is being created for you, (Note: navigate to your Service principal under Active Directory → App registrations → select your app registration and navigate to overview):

    Secret nameValueMandatory?
    AZURE_AD_CLIENT_SECRETThis is the client secret value that was generated for the service principal in section 4 of Create a service.YES
    AZURE_AD_CLIENT_IDThis is the Application (client) IDYES
    AZURE_AD_TENANT_IDThis is the Directory (tenant) IDYES
    AZURE_SUBSCRIPTION_IDNavigate to subscriptions and select the Subscription ID for your subscriptionYES
    STATIC_SITE_NAMEThe name of your static siteYES
    CUSTOM_DOMAIN_NAMEThe custom domain name you wish to attach to your static site. See below.NO
    REPAIRS_API_BASE_URLHousing repairs online API URL, this can obtained from the App Service the API was deployed toYES
    REPAIRS_API_IDENTIFIERA unique identifier used to validate access in productionYES
    REPAIRS_API_BASE_URL_STAGINGHousing repairs online API Staging URL, this can obtained from the App Service the API was deployed toYES
    REPAIRS_API_IDENTIFIER_STAGINGA unique identifier used to validate access in stagingYES
  1. You will then reference these as environment variables in your github actions workflow. There will be an example provided further down which you can replicate. This allows the setup-terraform action to use the service principal credentials to provision your resources.

  2. Add STATE_KEY_NAME as a repository secret. This is the storage account key for your Terraform backend. You can obtain this value if you navigate to Storage accounts, select the storage account for your Terraform backend, select Access Keys, click on show keys and copy the top key value. (Note: These are rotating keys and are subject to change, this tutorial does not investigate how to work around this)

  3. This is a link for an example workflow

Deploy housing-repairs-online-frontend

Now you have added all the resources that you need in Azure in Terraform, you are ready for the CI to apply the Terraform and deploy. The first CI run will provision the Azure static web app resource (however the deployment will fail and this is expected). Log in to the Azure web portal, navigate to the static webb app you provisioned and copy the Manage deployment token value. Add this to github actions secret with the name AZURE_STATIC_WEB_APPS_API_TOKEN. As you have now added this secret, the deployment should pass successfully on the second run.

Note: There will be some future work to prevent the manual entry of the AZURE STATIC WEB APPS API TOKEN secret

Notes: Adding a custom domain (Optional)

When creating a static web app, Azure will automatically auto-generate a domain name for the website but if you have a custom domain ready for your site, add the value to the Github secret called CUSTOM_DOMAIN_NAME and this will map a your custom domain to the site.

When a value for CUSTOM_DOMAIN_NAME is given, terraform will create the azurerm_static_site_custom_domain resource using the given value and attach it to the static web app.

If you have not given a custom domain, the custom domain resource will not be added.

Read the Azure guidance and Terraform guidance for more information on how custom domain names are added to static web apps in Azure.

Deploying the API's

Each of the API's will be deployed to Azure App service. They will all exist under the same App Service Plan, which will be created manually. To create an App Service Plan, search App service plans on the azure portal, select Create, ensure you select the resource group created above and select an appropriate name for the App Service Plan e.g. housing-repairs-online-{LOCAL_AUTHORITY_NAME}

Deploy Housing Management System API

To deploy the Housing Management System API, you must populate github actions with the following secrets:

Secret nameDescription
APP_SERVICE_NAMEApp Service name (must be unique across whole of Azure), e.g. HousingManagementSystemApi-{LOCAL_AUTHORITY_NAME}
SERVICE_PLAN_NAMEApp Service Plan name, e.g. housing-repairs-online
AUTHENTICATION_IDENTIFIER_PRODUCTIONA unique identifier used to validate access in production
AUTHENTICATION_IDENTIFIER_STAGINGA unique identifier used to validate access in staging
AZURE_AD_CLIENT_SECRETThis is the client secret value that was generated for the service principal in section 4 of Create a service
AZURE_AD_CLIENT_IDThis is the Application (client) ID
AZURE_AD_TENANT_IDThis is the Directory (tenant) ID
AZURE_SUBSCRIPTION_IDNavigate to subscriptions and select the Subscription ID for your subscription
ANCM_ADDITIONAL_ERROR_PAGE_LINK_PRODUCTIONLink to an optional error page for production ASP.NET Core Module
ANCM_ADDITIONAL_ERROR_PAGE_LINK_STAGINGLink to an optional error page for staging ASP.NET Core Module
JWT_SECRET_PRODUCTIONJWT secret generated for for production
JWT_SECRET_STAGINGJWT secret generated for for staging
NUGET_AUTH_GITHUB_TOKENAuthentication token for authenticating with GitHub NuGet feed
NUGET_AUTH_GITHUB_USERNAMEUsername for authenticating with GitHub NuGet feed
SENTRY_DSNSentry Data Source Name
RESOURCE_GROUP_LOCATIONThe resource group location housing your Terraform state file, e.g. UK South
RESOURCE_GROUP_NAMEThe resource group name housing your Terraform state file
STORAGE_ACCOUNT_NAMEThe name of the Azure Storage Account to house your Terraform state file
STATE_CONTAINER_NAMEThe name of the Azure Blob Storage container to house your Terraform state file
STATE_KEY_NAMEThe file path and name of your Terraform state file
COSMOS_DATABASE_IDDocumentDB (e.g. CosmosDB) database name
COSMOS_TENANT_CONTAINER_IDDocumentDB (e.g. CosmosDB) container name for tenant addresses, e.g. addresses
COSMOS_COMMUNAL_STAGING_CONTAINER_IDDocumentDB (e.g. CosmosDB) container name for staging communal addresses, e.g. addresses
COSMOS_COMMUNAL_PRODUCTION_CONTAINER_IDDocumentDB (e.g. CosmosDB) container name for production communal addresses, e.g. addresses
COSMOS_LEASEHOLD_STAGING_CONTAINER_IDDocumentDB (e.g. CosmosDB) container name for staging leasehold addresses, e.g. addresses
COSMOS_LEASEHOLD_PRODUCTION_CONTAINER_IDDocumentDB (e.g. CosmosDB) container name for production leasehold addresses, e.g addresses
COSMOS_ENDPOINT_URLDocumentDB (e.g. CosmosDB) account endpoint URL
COSMOS_AUTHORIZATION_KEYDocumentDB (e.g. CosmosDB) account primary key
CAPITA_URL_STAGINGCapita Service URL for staging
CAPITA_URL_PRODUCTIONCapita Service URL for Production
CAPITA_USERNAME_STAGINGCapita Service username for staging
CAPITA_USERNAME_PRODUCTIONCapita Service username for production
CAPITA_PASSWORD_STAGINGCapita Service password for staging
CAPITA_PASSWORD_PRODUCTIONCapita Service password for production
CAPITA_STDJOBCODE_STAGINGCapita Service stdjobcode for staging
CAPITA_STDJOBCODE_PRODUCTIONCapita Service stdjobcode for production
CAPITA_SOURCE_STAGINGCapita Service source for staging
CAPITA_SOURCE_PRODUCTIONCapita Service source for production
CAPITA_SUBLOCATION_STAGINGCapita Service sublocation for staging
CAPITA_SUBLOCATION_PRODUCTIONCapita Service sublocation for production

Once you have entered all of the environment variables, you should rerun the workflow in the main branch. The first run will fail Deploy Staging and Deploy Production step (which is expected, following steps will resolve). However, the Provision Infrastructure step should pass and deploy all the infrastructure.

Once this is done, we will need to set the AZUREAPPSERVICE_PUBLISHPROFILE_... secrets, by downloading the publish profiles from the Azure web portal setting the secrets to their contents. To do this, navigate to App Services and from here navigate to the housing repairs online API App Service. Click Get publish profile to download the production publish profile. Now click Deployment slots (in the navigation pane on the left) and select the staging slot. Now click Get publish profile to download the staging publish profile.

Finally, in GitHub actions secrets, set AZUREAPPSERVICE_PUBLISHPROFILE_PRODUCTION and AZUREAPPSERVICE_PUBLISHPROFILE_STAGING to the contents of the respective publish profiles downloaded previously. Once this is complete, you can rerun the workflow and all of the steps should pass.

Deploy Scheduling API

To deploy the Scheduling API, you must populate the GitHub repository the following secrets:

Secret nameDescription
APP_SERVICE_NAMEService name (must be unqiue across whole of Azure) e.g. housing-repairs-scheduling-api-{LOCAL_AUTHORITY_NAME}
AUTHENTICATION_IDENTIFIER_PRODUCTIONA unique identifier used to validate access used to validate access in production
AUTHENTICATION_IDENTIFIER_STAGINGA unique identifier used to validate access used to validate access in staging
AZURE_AD_TENANT_IDThis is the Directory (tenant) ID
DRS_API_ADDRESS_PRODUCTIONLive/production DRS API address, e.g. https://yourserver/OTWebServiceGateway_INSTANCENAME/ws/soap?wsdl
DRS_API_ADDRESS_STAGINGTest/staging DRS API address, e.g. https://yourserver/OTWebServiceGateway_INSTANCENAME/ws/soap?wsdl
DRS_CONTRACT_PRODUCTIONContract value to use when making requests to DRS in production
DRS_CONTRACT_STAGINGContract value to use when making requests to DRS in staging
DRS_LOGIN_PRODUCTIONDRS login/user name in production
DRS_LOGIN_STAGINGDRS login/user name in staging
DRS_PASSWORD_PRODUCTIONDRS password in production
DRS_PASSWORD_STAGINGDRS password in staging
DRS_PRIORITY_PRODUCTIONPriority to use when making requests to DRS in production
DRS_PRIORITY_STAGINGPriority to use when making requests to DRS in staging
JWT_SECRET_PRODUCTIONJWT secret generated for production
JWT_SECRET_STAGINGJWT secret generated for staging
NUGET_AUTH_GITHUB_TOKENAuthentication token for authenticating with GitHub NuGet feed
NUGET_AUTH_GITHUB_USERNAMEUsername for authenticating with GitHub NuGet feed
RESOURCE_GROUP_LOCATIONAzure Resource Group location, e.g. UK South
RESOURCE_GROUP_NAMEAzure Resource Group name
SENTRY_DSNSentry Data Source Name
SERVICE_PLAN_NAMEService plan name (must be unique across whole of Azure) e.g. housing-repairs-schduling-api-{LOCAL_AUTHORITY_NAME}
STATE_CONTAINER_NAMEThe name of the container to store Terraform state in
STATE_KEY_NAMEThe file path and name of your Terraform state file
STORAGE_ACCOUNT_NAMEStorage account name for Terraform state, e.g. housing-repairs-online

Once you have entered all of the environment variables, you should re-run the workflow in the main branch. The first run will fail Deploy Staging and Deploy Production step (which is expected, following steps will resolve). However, the Provision Infrastructure step should pass and deploy all the infrastructure.

Once this is done, we will need to set the AZUREAPPSERVICE_PUBLISHPROFILE_... secrets, by downloading the publish profiles from the Azure web portal setting the secrets to their contents. To do this, navigate to App Services and from here navigate to the housing repairs scheduling API App Service. Click Get publish profile to download the production publish profile. Now click Deployment slots (in the navigation pane on the left) and select the staging slot. Now click Get publish profile to download the staging publish profile.

Finally, in GitHub actions secrets, set AZUREAPPSERVICE_PUBLISHPROFILE_PRODUCTION and AZUREAPPSERVICE_PUBLISHPROFILE_STAGING to the contents of the respective publish profiles downloaded previously. Once this is complete, you can rerun the workflow and all of the steps should pass.

Deploy housing-repairs-online-api

Github Action logs Masking Secrets

The below secrets must be entered to reduce the risk of them leaking in the Github actions logs when debug logging is enabled. In github actions, we use masks to obscure secrets. The values of these secrets can be obtained from their Cloud resources dashboard, once the Terraform deploy is run for the first time.

⚠ WARNING: Without the below secrets saved in Github, you will not be able to use Github action's mask command with the secret. Github action's mask command need to be explicitly told each secret it should obscure in logs. Any values in the app settings config not saved as a Github secret will have the risk of being publically exposed whenever the deploy job is run with debug enabled.

Populate github secrets with the following values so that we can add the use the masking commands on them. Do this before deploying the app with it's publish profile.

Secret nameDescription
COSMOS_CONTAINER_NAME_PRODUCTIONDocumentDB (e.g. CosmosDB) container name for Production, e.g. housing-repairs-online-production
COSMOS_CONTAINER_NAME_STAGINGDocumentDB (e.g. CosmosDB) container name for Staging, e.g. housing-repairs-online-staging
COSMOS_ACCOUNT_PRIMARY_KEYDocumentDB (e.g. CosmosDB) account primary key
COSMOS_DATABASE_NAME_PRODUCTIONDocumentDB (e.g. CosmosDB) database name for Production, e.g. housing-repairs-production
COSMOS_DATABASE_NAME_STAGINGDocumentDB (e.g. CosmosDB) database name for Staging, e.g. housing-repairs-staging
COSMOS_ACCOUNT_ENDPOINTDocumentDB (e.g. CosmosDB) account endpoint URL
STORAGE_ACCOUNT_PRIMARY_CONNECTION_STRINGStorage account primary connection string

To deploy the housing repairs api, you must first deploy HousingRepairsSchedulingApi and HousingManagementSystemApi. Once this has been deployed, populate github actions with the following secrets:

Secret nameDescription
ADDRESSES_API_URL_PRODUCTIONRetrieve from App Service once HousingManagementSystemApi is deployed
ADDRESSES_API_URL_STAGINGRetrieve from App Service Staging slot once HousingManagementSystemApi is deployed
SCHEDULING_API_URL_PRODUCTIONRetrieve from App Service once HousingRepairsSchedulingApi is deployed
SCHEDULING_API_URL_STAGINGRetrieve from App Service Staging slot once HousingRepairsSchedulingApi is deployed
AUTHENTICATION_IDENTIFIER_PRODUCTIONA unique identifier used to validate access for Production
AUTHENTICATION_IDENTIFIER_STAGINGA unique identifier used to validate access for Staging
TENANT_CONFIRMATION_EMAIL_NOTIFY_TEMPLATE_IDGov notify email template ID for tenant repairs, this is available once the template is created
TENANT_CONFIRMATION_SMS_NOTIFY_TEMPLATE_IDGov notify sms template ID for tenant repairs, this is available once the template is created
TENANT_INTERNAL_EMAIL_NOTIFY_TEMPLATE_IDGov notify internal email template ID for tenant repairs, this is available once the template is created
COMMUNAL_CONFIRMATION_EMAIL_NOTIFY_TEMPLATE_IDGov notify email template ID for communal repairs, this is available once the template is created
COMMUNAL_CONFIRMATION_SMS_NOTIFY_TEMPLATE_IDGov notify sms template ID for communal repairs, this is available once the template is created
COMMUNAL_INTERNAL_EMAIL_NOTIFY_TEMPLATE_IDGov notify internal email template ID for communal repairs, this is available once the template is created
LEASEHOLD_CONFIRMATION_EMAIL_NOTIFY_TEMPLATE_IDGov notify email template ID for leasehold repairs, this is available once the template is created
LEASEHOLD_CONFIRMATION_SMS_NOTIFY_TEMPLATE_IDGov notify sms template ID for leasehold repairs, this is available once the template is created
LEASEHOLD_INTERNAL_EMAIL_NOTIFY_TEMPLATE_IDGov notify internal email template ID for leasehold repairs, this is available once the template is created
CANCELLATION_INTERNAL_EMAIL_NOTIFY_TEMPLATE_IDGov notify internal email template ID for cancellation of repairs, this is available once the template is created
APPOINTMENT_CHANGED_SMS_NOTIFY_TEMPLATE_IDGov notify sms template ID for changed appointments, this is available once the template is created
APPOINTMENT_CHANGED_EMAIL_NOTIFY_TEMPLATE_IDGov notify email template ID for changed appointments, this is available once the template is created
DAYS_UNTIL_IMAGE_EXPIRY_PRODUCTIONNumber in days before image uploaded by customer expires for Production, e.g. 14 days
DAYS_UNTIL_IMAGE_EXPIRY_STAGINGNumber in days before image uploaded by customer expires for Staging, e.g. 14 days
GOV_NOTIFY_KEY_PRODUCTIONStaging gov notify key
GOV_NOTIFY_KEY_STAGINGProduction gov notify key
INTERNAL_EMAIL_PRODUCTIONInternal email address for receiving repair request details, for any manual follow-on process in Production
INTERNAL_EMAIL_STAGINGInternal email address for receiving repair request details, for any manual follow-on process in Staging
JWT_SECRET_PRODUCTIONJWT secret generated for for Production
JWT_SECRET_STAGINGJWT secret generated for for Staging
NUGET_AUTH_GITHUB_TOKENAuthentication token for authenticating with GitHub NuGet feed
NUGET_AUTH_GITHUB_USERNAMEUsername for authenticating with GitHub NuGet feed
SENTRY_DSNSentry Data Source Name
SERVICE_NAMEService name (must be unique across whole of Azure) e.g. housing-repairs-online-api-{LOCAL_AUTHORITY_NAME}
SOR_CONFIG_PRODUCTIONSOR codes in JSON format for Production
SOR_CONFIG_STAGINGSOR codes in JSON format for Staging
STATE_KEY_NAMEThe file path and name of your Terraform state file
STORAGE_CONTAINER_NAME_PRODUCTIONStorage container name for Production, e.g. housing-repairs-online
STORAGE_CONTAINER_NAME_STAGINGStorage container name for Staging, e.g. housing-repairs-online-staging
SOR_CONFIGURATION_TENANT_PRODUCTIONSchedule of Rates configuration that specifies tenant options to offer and their SoR code for Production
SOR_CONFIGURATION_COMMUNAL_PRODUCTIONSchedule of Rates configuration that specifies communal options to offer and their SoR code for Production
SOR_CONFIGURATION_LEASEHOLD_PRODUCTIONSchedule of Rates configuration that specifies leasehold options to offer and their SoR code for Production
SOR_CONFIGURATION_TENANT_STAGINGSchedule of Rates configuration that specifies tenant options to offer and their SoR code for Staging
SOR_CONFIGURATION_COMMUNAL_STAGINGSchedule of Rates configuration that specifies communal options to offer and their SoR code for Staging
SOR_CONFIGURATION_LEASEHOLD_STAGINGSchedule of Rates configuration that specifies leasehold options to offer and their SoR code for Staging
ALLOWED_APPOINTMENT_SLOTSSpecifies which appointment slots are allowed (see below for details)
REPAIR_PRIORITY_TO_DAYS_PRODUCTIONRepair priority to days mapping for communal repairs for Staging.
REPAIR_PRIORITY_TO_DAYS_STAGINGRepair priority to days mapping for communal repairs for Production.

Once you have entered all of the environment variables, you should rerun the workflow in the main branch. The first run will fail Deploy Staging and Deploy Production step (which is expected, following steps will resolve). However, the Provision Infrastructure step should pass and deploy all the infrastructure.

Once this is done, we will need to set the AZUREAPPSERVICE_PUBLISHPROFILE_... secrets, by downloading the publish profiles from the Azure web portal setting the secrets to their contents. To do this, navigate to App Services and from here navigate to the housing repairs online API App Service. Click Get publish profile to download the production publish profile. Now click Deployment slots (in the navigation pane on the left) and select the staging slot. Now click Get publish profile to download the staging publish profile.

Finally, in GitHub actions secrets, set AZUREAPPSERVICE_PUBLISHPROFILE_PRODUCTION and AZUREAPPSERVICE_PUBLISHPROFILE_STAGING to the contents of the respective publish profiles downloaded previously. Once this is complete, you can rerun the workflow and all of the steps should pass.

Integration

Components

Some of the Housing Repairs Online components will need to integrate to one another. This is by means of setting environment variables which is detailed within the documentation for each component.

3rd Party Systems

Connectivity needs to be establish to each 3rd party system requiring integration.

Each component would require access to the system it is integrating with, i.e. Housing Management System API needs Housing Management System (i.e. Universal Housing) connectivity.

If data is stored on premise, a VPN or other datalink should be setup so that cloud deployed infrastructure has visibility of on premise infrastructure.

Alerting & Monitoring

See Alerting & Monitoring for details.

Configuration

Each component's configuration is outlined in their own specific documentation.

Please refer to this documentation to configure each component.

Documentation

This documentation uses Docusaurus and is generated via Github actions.

After the housing-repairs-online repository has been cloned/forked, follow these steps to ensure GitHub regenerates documentation when changes are made:

  • Set the branch to use for GitHub pages to gh-pages (see here)
  • Configure the repository by adding a Deploy Key and ACTIONS_DEPLOY_KEY Secret (see here)

  1. When creating resource in Azure, if using Github integration, some of these secrets will be automatically added to the repository.
  2. If you are not ready to add a custom domain, the site will continue to use the auto generated Azure domain. Add the custom domain when this is ready and it will be mapped to the site.