Skip to content

Commit

Permalink
Merge pull request #255 from DFE-Digital/feature/prod-deployment
Browse files Browse the repository at this point in the history
Terraform and pipeline for deployment to production
  • Loading branch information
RobertGHippo authored Jul 25, 2024
2 parents 95c9794 + ba83191 commit a169fcb
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 85 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/main-build-and-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,45 @@ jobs:
- name: Swap to the production slot
run: |
az webapp deployment slot swap --resource-group ${{ vars.RESOURCE_NAME_PREFIX }}-rg --name ${{ vars.WEBAPP_NAME }} --slot ${{ vars.WEBAPP_SLOT_NAME }} --target-slot production
deploy-to-production:
runs-on: ubuntu-22.04
needs: [create-and-publish-image, deploy-to-staging]
name: Deploy to production
environment: production
# Permissions for OIDC authentication
permissions:
id-token: write
contents: write
issues: write
steps:
- name: Check out repository
uses: actions/checkout@v4

# Login to Azure using OIDC
- name: Login to Azure CLI
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

# Deploy Web Application
- name: Deploy to Azure App Services
uses: azure/webapps-deploy@v3
with:
app-name: ${{ vars.WEBAPP_NAME }}
images: ${{ needs.create-and-publish-image.outputs.dockerImageTag }}
slot-name: "${{ vars.WEBAPP_SLOT_NAME }}"

# Make a request to the health check endpoint
- name: Make request to health check endpoint
uses: ./.github/actions/health-check
with:
webapp_name: ${{ vars.WEBAPP_NAME }}
slot_name: ${{ vars.WEBAPP_SLOT_NAME }}

# Swap the slots
- name: Swap to the production slot
run: |
az webapp deployment slot swap --resource-group ${{ vars.RESOURCE_NAME_PREFIX }}-rg --name ${{ vars.WEBAPP_NAME }} --slot ${{ vars.WEBAPP_SLOT_NAME }} --target-slot production
2 changes: 1 addition & 1 deletion .github/workflows/tf-azure-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
options:
- development
- staging
# - production
- production

defaults:
run:
Expand Down
1 change: 0 additions & 1 deletion terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ This module provisions a new Azure Resource Group that assembles together the in
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_admin_email_address"></a> [admin\_email\_address](#input\_admin\_email\_address) | Email Address of the Admin | `string` | n/a | yes |
| <a name="input_as_service_principal_object_id"></a> [as\_service\_principal\_object\_id](#input\_as\_service\_principal\_object\_id) | Object ID of the service principal for App Service | `string` | n/a | yes |
| <a name="input_asp_sku"></a> [asp\_sku](#input\_asp\_sku) | SKU name for the App Service Plan | `string` | `"S1"` | no |
| <a name="input_azure_region"></a> [azure\_region](#input\_azure\_region) | Name of the Azure region to deploy resources | `string` | `"westeurope"` | no |
| <a name="input_contentful_delivery_api_key"></a> [contentful\_delivery\_api\_key](#input\_contentful\_delivery\_api\_key) | Contentful delivery API key | `string` | n/a | yes |
Expand Down
7 changes: 5 additions & 2 deletions terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ resource "azurerm_resource_group" "rg" {
tags = local.common_tags

lifecycle {
ignore_changes = [tags]
ignore_changes = [
tags["Environment"],
tags["Product"],
tags["Service Offering"]
]
}
}

Expand Down Expand Up @@ -65,7 +69,6 @@ module "webapp" {
location = var.azure_region
resource_group = azurerm_resource_group.rg.name
resource_name_prefix = var.resource_name_prefix
as_service_principal_object_id = var.as_service_principal_object_id
asp_sku = var.asp_sku
webapp_admin_email_address = var.admin_email_address
webapp_worker_count = var.webapp_worker_count
Expand Down
1 change: 0 additions & 1 deletion terraform/modules/azure-network/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ No modules.
| Name | Type |
|------|------|
| [azurerm_key_vault.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) | resource |
| [azurerm_key_vault_access_policy.kv_ap](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) | resource |
| [azurerm_key_vault_access_policy.kv_gh_ap](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) | resource |
| [azurerm_key_vault_access_policy.kv_mi_ap](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) | resource |
| [azurerm_key_vault_certificate.kv_cert](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_certificate) | resource |
Expand Down
56 changes: 13 additions & 43 deletions terraform/modules/azure-network/key-vault.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ resource "azurerm_key_vault" "kv" {
sku_name = "standard"

lifecycle {
ignore_changes = [tags]
ignore_changes = [
tags["Environment"],
tags["Product"],
tags["Service Offering"]
]
}

#checkov:skip=CKV_AZURE_109:Access Policies configured
Expand All @@ -21,52 +25,14 @@ resource "azurerm_key_vault" "kv" {
}

resource "azurerm_user_assigned_identity" "kv_mi" {
# Key Vault only deployed to the Test and Production subscription
# Identity for App Gateway, only deployed to the Test and Production subscription
count = var.environment != "development" ? 1 : 0

name = "${var.resource_name_prefix}-agw-mi"
location = var.location
resource_group_name = var.resource_group
}

resource "azurerm_key_vault_access_policy" "kv_ap" {
# Key Vault only deployed to the Test and Production subscription
count = var.environment != "development" ? 1 : 0

key_vault_id = azurerm_key_vault.kv.id
tenant_id = data.azurerm_client_config.az_config.tenant_id
object_id = data.azurerm_client_config.az_config.object_id

key_permissions = [
"Create",
"Delete",
"Get",
"UnwrapKey",
"WrapKey"
]

secret_permissions = [
"Get"
]

certificate_permissions = [
"Create",
"Get",
"GetIssuers",
"Import",
"List",
"ListIssuers",
"ManageContacts",
"ManageIssuers",
"SetIssuers",
"Update"
]

lifecycle {
ignore_changes = [object_id]
}
}

# Access Policy for GitHub Actions
resource "azurerm_key_vault_access_policy" "kv_gh_ap" {
key_vault_id = azurerm_key_vault.kv.id
Expand Down Expand Up @@ -100,6 +66,10 @@ resource "azurerm_key_vault_access_policy" "kv_gh_ap" {
"SetIssuers",
"Update"
]

lifecycle {
ignore_changes = [object_id]
}
}

resource "azurerm_key_vault_access_policy" "kv_mi_ap" {
Expand All @@ -120,7 +90,7 @@ resource "azurerm_key_vault_access_policy" "kv_mi_ap" {
}

resource "azurerm_key_vault_certificate_issuer" "kv_ca" {
# Key Vault only deployed to the Test and Production subscription
# Certificate issuer only deployed to the Test and Production subscription
count = var.environment != "development" ? 1 : 0

name = var.kv_certificate_authority_label
Expand All @@ -138,7 +108,7 @@ resource "azurerm_key_vault_certificate_issuer" "kv_ca" {
}

resource "azurerm_key_vault_certificate" "kv_cert" {
# Key Vault only deployed to the Test and Production subscription
# Certificate only deployed to the Test and Production subscription
count = var.environment != "development" ? 1 : 0

name = var.kv_certificate_label
Expand Down Expand Up @@ -211,4 +181,4 @@ resource "azurerm_key_vault_secret" "contentful_space_id" {
name = "ContentfulOptions--SpaceId"
value = var.contentful_space_id
key_vault_id = azurerm_key_vault.kv.id
}
}
6 changes: 5 additions & 1 deletion terraform/modules/azure-network/public-ip.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ resource "azurerm_public_ip" "agw_pip" {
idle_timeout_in_minutes = 4

lifecycle {
ignore_changes = [tags]
ignore_changes = [
tags["Environment"],
tags["Product"],
tags["Service Offering"]
]
}
}
8 changes: 6 additions & 2 deletions terraform/modules/azure-network/vnet.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ resource "azurerm_virtual_network" "vnet" {
address_space = ["172.1.0.0/16"]

lifecycle {
ignore_changes = [tags]
ignore_changes = [
tags["Environment"],
tags["Product"],
tags["Service Offering"]
]
}
}

Expand Down Expand Up @@ -42,4 +46,4 @@ resource "azurerm_subnet" "agw_snet" {
service_endpoints = ["Microsoft.Storage", "Microsoft.Web"]

#checkov:skip=CKV2_AZURE_31:NSG not required
}
}
10 changes: 9 additions & 1 deletion terraform/modules/azure-storage/storage.tf
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ resource "azurerm_storage_account" "sa" {

tags = var.tags

lifecycle {
ignore_changes = [
tags["Environment"],
tags["Product"],
tags["Service Offering"]
]
}

#checkov:skip=CKV_AZURE_206:GRS not required
#checkov:skip=CKV_AZURE_59:Argument has been deprecated
#checkov:skip=CKV2_AZURE_18:Microsoft Managed keys are sufficient
Expand All @@ -51,4 +59,4 @@ resource "azurerm_storage_container" "data_protection" {
container_access_type = "private"

#checkov:skip=CKV2_AZURE_21:Logging not required
}
}
2 changes: 0 additions & 2 deletions terraform/modules/azure-web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ No modules.
| [azurerm_app_service_custom_hostname_binding.webapp_custom_domain](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service_custom_hostname_binding) | resource |
| [azurerm_application_gateway.agw](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/application_gateway) | resource |
| [azurerm_application_insights.web](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/application_insights) | resource |
| [azurerm_key_vault_access_policy.webapp_kv_ap](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) | resource |
| [azurerm_key_vault_access_policy.webapp_kv_app_service](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) | resource |
| [azurerm_key_vault_access_policy.webapp_kv_app_service_slot](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) | resource |
| [azurerm_linux_web_app.webapp](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_web_app) | resource |
Expand All @@ -47,7 +46,6 @@ No modules.
|------|-------------|------|---------|:--------:|
| <a name="input_agw_pip_id"></a> [agw\_pip\_id](#input\_agw\_pip\_id) | ID of the Public IP address for the App Gateway | `string` | n/a | yes |
| <a name="input_agw_subnet_id"></a> [agw\_subnet\_id](#input\_agw\_subnet\_id) | ID of the Subnet for the App Gateway | `string` | n/a | yes |
| <a name="input_as_service_principal_object_id"></a> [as\_service\_principal\_object\_id](#input\_as\_service\_principal\_object\_id) | Object ID of the service principal for App Service | `string` | n/a | yes |
| <a name="input_asp_sku"></a> [asp\_sku](#input\_asp\_sku) | SKU name for the App Service Plan | `string` | n/a | yes |
| <a name="input_environment"></a> [environment](#input\_environment) | Environment to deploy resources | `string` | n/a | yes |
| <a name="input_kv_cert_secret_id"></a> [kv\_cert\_secret\_id](#input\_kv\_cert\_secret\_id) | SSL certificate Secret ID | `string` | n/a | yes |
Expand Down
12 changes: 10 additions & 2 deletions terraform/modules/azure-web/app-gateway.tf
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ resource "azurerm_web_application_firewall_policy" "agw_wafp" {
}

lifecycle {
ignore_changes = [tags]
ignore_changes = [
tags["Environment"],
tags["Product"],
tags["Service Offering"]
]
}
}

Expand Down Expand Up @@ -178,7 +182,11 @@ resource "azurerm_application_gateway" "agw" {
}

lifecycle {
ignore_changes = [tags]
ignore_changes = [
tags["Environment"],
tags["Product"],
tags["Service Offering"]
]
}

#checkov:skip=CKV_AZURE_218:Secure transit protocols used
Expand Down
6 changes: 0 additions & 6 deletions terraform/modules/azure-web/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ variable "resource_name_prefix" {
type = string
}

variable "as_service_principal_object_id" {
description = "Object ID of the service principal for App Service"
type = string
sensitive = true
}

variable "asp_sku" {
description = "SKU name for the App Service Plan"
type = string
Expand Down
Loading

0 comments on commit a169fcb

Please sign in to comment.