Skip to content

Commit

Permalink
Initial commit of the terraform scripts (#8)
Browse files Browse the repository at this point in the history
* Initial commit of the terraform scripts to start creating the initial environment

* Added the azure remote state scripts to store terraform state in blob storage

* Added network resources

* Added web app infrastructure scripts

* Updated to add in temp values for the contentful key vault secrets

* Updated secrets permission

* Updated file names, removed some of the variables we don't need and changed a couple of minor things in the scripts

* Removed app settings that is not needed

* Removed concurrency setting as not needed

* Updated the tags and added the new terraform.tf file
  • Loading branch information
sam-c-dfe authored Feb 1, 2024
1 parent 6788c72 commit 9a4111d
Show file tree
Hide file tree
Showing 19 changed files with 1,433 additions and 0 deletions.
6 changes: 6 additions & 0 deletions terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Azure Root Module

This module provisions a new Azure Resource Group that assembles together the infrastructure for hosting the web application.

## Prerequisites
* The [Remote State module](./azure-remote-state/README.md) must first be applied **independently** before this configuration can be used.
3 changes: 3 additions & 0 deletions terraform/azure-network/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Azure Network Module

This module provisions the necessary network related resources such as a VNET, Subnets & KeyVault.
203 changes: 203 additions & 0 deletions terraform/azure-network/key-vault.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# Create Key Vault
data "azurerm_client_config" "az_config" {}

resource "azurerm_key_vault" "kv" {
name = "${var.resource_name_prefix}-kv"
resource_group_name = var.resource_group
location = var.location
tenant_id = data.azurerm_client_config.az_config.tenant_id
enabled_for_disk_encryption = true
soft_delete_retention_days = 7
purge_protection_enabled = true
sku_name = "standard"

lifecycle {
ignore_changes = [tags]
}

#checkov:skip=CKV_AZURE_109:Access Policies configured
#checkov:skip=CKV_AZURE_189:Access Policies configured
#checkov:skip=CKV2_AZURE_32:VNET configuration adequate
}

resource "azurerm_user_assigned_identity" "kv_mi" {
# Key Vault 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[0].id
tenant_id = data.azurerm_client_config.az_config.tenant_id
object_id = data.azurerm_client_config.az_config.object_id

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 only deployed to the Test and Production subscription
count = var.environment != "development" ? 1 : 0

key_vault_id = azurerm_key_vault.kv[0].id
tenant_id = data.azurerm_client_config.az_config.tenant_id
object_id = data.azurerm_client_config.az_config.object_id

secret_permissions = [
"Get"
]

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

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

key_vault_id = azurerm_key_vault.kv[0].id
tenant_id = data.azurerm_client_config.az_config.tenant_id
object_id = azurerm_user_assigned_identity.kv_mi[0].principal_id

secret_permissions = [
"Get"
]

certificate_permissions = [
"Get"
]
}

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

name = var.kv_certificate_authority_label
key_vault_id = azurerm_key_vault.kv[0].id
provider_name = var.kv_certificate_authority_name
account_id = var.kv_certificate_authority_username
password = var.kv_certificate_authority_password

admin {
email_address = var.kv_certificate_authority_admin_email
first_name = var.kv_certificate_authority_admin_first_name
last_name = var.kv_certificate_authority_admin_last_name
phone = var.kv_certificate_authority_admin_phone_no
}
}

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

name = var.kv_certificate_label
key_vault_id = azurerm_key_vault.kv[0].id

certificate_policy {
issuer_parameters {
name = var.kv_certificate_authority_label
}

key_properties {
exportable = true
key_size = 2048
key_type = "RSA"
reuse_key = true
}

lifetime_action {
action {
action_type = "AutoRenew"
}

trigger {
days_before_expiry = 30
}
}

secret_properties {
content_type = "application/x-pkcs12"
}

x509_certificate_properties {
extended_key_usage = ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"]
key_usage = ["digitalSignature", "keyEncipherment"]
subject = var.kv_certificate_subject
validity_in_months = 12
}
}
}

resource "azurerm_key_vault_secret" "vault_secret_contentful_deliveryapikey" {
key_vault_id = azurerm_key_vault.kv[0].id
name = "ContentfulOptions--DeliveryApiKey"
value = "temp value"

lifecycle {
ignore_changes = [
value,
expiration_date
]
}
}

resource "azurerm_key_vault_secret" "vault_secret_contentful_previewapikey" {
key_vault_id = azurerm_key_vault.kv[0].id
name = "ContentfulOptions--PreviewApiKey"
value = "temp value"

lifecycle {
ignore_changes = [
value,
expiration_date
]
}
}

resource "azurerm_key_vault_secret" "vault_secret_contentful_spaceid" {
key_vault_id = azurerm_key_vault.kv[0].id
name = "ContentfulOptions--SpaceId"
value = "temp value"

lifecycle {
ignore_changes = [
value,
expiration_date
]
}
}
39 changes: 39 additions & 0 deletions terraform/azure-network/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
output "vnet_id" {
description = "ID of the Virtual Network"
value = azurerm_virtual_network.vnet.id
}

output "vnet_name" {
description = "Name of the Virtual Network"
value = azurerm_virtual_network.vnet.name
}

output "webapp_subnet_id" {
description = "ID of the delegated Subnet for the Web Application"
value = azurerm_subnet.webapp_snet.id
}

output "agw_subnet_id" {
description = "ID of the Subnet for the App Gateway"
value = var.environment != "development" ? azurerm_subnet.agw_snet[0].id : null
}

output "agw_pip_id" {
description = "ID of the Public IP address for the App Gateway"
value = var.environment != "development" ? azurerm_public_ip.agw_pip[0].id : null
}

output "kv_id" {
description = "ID of the Key Vault"
value = azurerm_key_vault.kv[0].id
}

output "kv_cert_secret_id" {
description = "SSL certificate Secret ID"
value = var.environment != "development" ? azurerm_key_vault_certificate.kv_cert[0].secret_id : null
}

output "kv_mi_id" {
description = "ID of the Managed Identity for the Key Vault"
value = azurerm_user_assigned_identity.kv_mi[0].id
}
19 changes: 19 additions & 0 deletions terraform/azure-network/public-ip.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Create PIP for App Gateway
resource "azurerm_public_ip" "agw_pip" {
# Application Gateway is not deployed to the Development subscription
count = var.environment != "development" ? 1 : 0

name = "${var.resource_name_prefix}-agw-pip"
resource_group_name = var.resource_group
location = var.location
allocation_method = "Static"
ip_version = "IPv4"
sku = "Standard"
sku_tier = "Regional"
zones = []
idle_timeout_in_minutes = 4

lifecycle {
ignore_changes = [tags]
}
}
69 changes: 69 additions & 0 deletions terraform/azure-network/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
variable "environment" {
description = "Environment to deploy resources"
type = string
}

variable "location" {
description = "Name of the Azure region to deploy resources"
type = string
}

variable "resource_group" {
description = "Name of the Azure Resource Group to deploy resources"
type = string
}

variable "resource_name_prefix" {
description = "Prefix for resource names"
type = string
}

variable "kv_certificate_authority_label" {
description = "Label for the Certificate Authority"
type = string
}

variable "kv_certificate_authority_name" {
description = "Name of the Certificate Authority"
type = string
}

variable "kv_certificate_authority_username" {
description = "Username for the Certificate provider"
type = string
}

variable "kv_certificate_authority_password" {
description = "Password the Certificate provider"
type = string
}

variable "kv_certificate_authority_admin_email" {
description = "Email Address of the Certificate Authority Admin"
type = string
}

variable "kv_certificate_authority_admin_first_name" {
description = "First Name of the Certificate Authority Admin"
type = string
}

variable "kv_certificate_authority_admin_last_name" {
description = "Last Name of the Certificate Authority Admin"
type = string
}

variable "kv_certificate_authority_admin_phone_no" {
description = "Phone No. of the Certificate Authority Admin"
type = string
}

variable "kv_certificate_label" {
description = "Label for the Certificate"
type = string
}

variable "kv_certificate_subject" {
description = "Subject of the Certificate"
type = string
}
45 changes: 45 additions & 0 deletions terraform/azure-network/vnet.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Create Virtual Network
resource "azurerm_virtual_network" "vnet" {
name = "${var.resource_name_prefix}-vnet"
location = var.location
resource_group_name = var.resource_group
address_space = ["172.1.0.0/16"]

lifecycle {
ignore_changes = [tags]
}
}

# Create Subnet for Web App
resource "azurerm_subnet" "webapp_snet" {
name = "${var.resource_name_prefix}-webapp-snet"
virtual_network_name = azurerm_virtual_network.vnet.name
resource_group_name = var.resource_group
address_prefixes = ["172.1.1.0/26"]
service_endpoints = ["Microsoft.Storage"]

delegation {
name = "${var.resource_name_prefix}-webapp-dn"

service_delegation {
name = "Microsoft.Web/serverFarms"
actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
}
}

#checkov:skip=CKV2_AZURE_31:NSG not required
}

# Create Subnet for App Gateway
resource "azurerm_subnet" "agw_snet" {
# Subnet only deployed to the Test and Production subscription
count = var.environment != "development" ? 1 : 0

name = "${var.resource_name_prefix}-agw-snet"
virtual_network_name = azurerm_virtual_network.vnet.name
resource_group_name = var.resource_group
address_prefixes = ["172.1.3.0/24"]
service_endpoints = ["Microsoft.Storage", "Microsoft.Web"]

#checkov:skip=CKV2_AZURE_31:NSG not required
}
Loading

0 comments on commit 9a4111d

Please sign in to comment.