Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions infrastructure/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ override.tf.json
# Ignore CLI configuration files
.terraformrc
terraform.rc
.terraform.lock.hcl
2 changes: 1 addition & 1 deletion infrastructure/environments/poc/variables.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ENV_CONFIG=poc
AZURE_SUBSCRIPTION="Lung Cancer Screening - Dev"
HUB_SUBSCRIPTION="Lung Cancer Screening - Dev"
STORAGE_ACCOUNT_RG=rg-tfstate-poc-uks
TERRAFORM_MODULES_REF=main
TERRAFORM_MODULES_REF=feat/public-container-app-env
ENABLE_SOFT_DELETE=false
DOCKER_IMAGE=docker.io/nginxdemos/hello
DOCKER_IMAGE_TAG=latest
4 changes: 2 additions & 2 deletions infrastructure/environments/poc/variables.tfvars
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
features = {
deploy_database_as_container = true
features = {
front_door = false
hub_and_spoke = false
private_networking = false
}
postgres_backup_retention_days = 7
postgres_geo_redundant_backup_enabled = false
private_networking = false
protect_keyvault = false
vnet_address_space = "10.65.0.0/16"
1 change: 1 addition & 0 deletions infrastructure/environments/poc/variables.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
EXAMPLE_KEY: example_value
32 changes: 32 additions & 0 deletions infrastructure/modules/container-apps/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
data "azurerm_client_config" "current" {}

# data "azuread_group" "postgres_sql_admin_group" {
# display_name = var.postgres_sql_admin_group
# }

data "azurerm_private_dns_zone" "storage" {
count = var.features.private_networking ? 1 : 0

provider = azurerm.hub

name = "privatelink.blob.core.windows.net"
resource_group_name = "rg-hub-${var.hub}-uks-private-dns-zones"
}

data "azurerm_private_dns_zone" "storage-account-blob" {
count = var.features.private_networking ? 1 : 0

provider = azurerm.hub

name = "privatelink.blob.core.windows.net"
resource_group_name = "rg-hub-${var.hub}-uks-private-dns-zones"
}

data "azurerm_private_dns_zone" "storage-account-queue" {
count = var.features.private_networking ? 1 : 0

provider = azurerm.hub

name = "privatelink.queue.core.windows.net"
resource_group_name = "rg-hub-${var.hub}-uks-private-dns-zones"
}
45 changes: 45 additions & 0 deletions infrastructure/modules/container-apps/front_door.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
data "azurerm_cdn_frontdoor_profile" "this" {
count = var.features.front_door ? 1 : 0

provider = azurerm.hub

name = var.front_door_profile
resource_group_name = "rg-hub-${var.hub}-uks-${var.app_short_name}"
}

module "frontdoor_endpoint" {
count = var.features.front_door ? 1 : 0

source = "../dtos-devops-templates/infrastructure/modules/cdn-frontdoor-endpoint"

providers = {
azurerm = azurerm.hub # Each project's Front Door profile (with secrets) resides in Hub since it's shared infra with a Non-live/Live deployment pattern
azurerm.dns = azurerm.hub
}

cdn_frontdoor_profile_id = data.azurerm_cdn_frontdoor_profile.this[0].id
custom_domains = {
"${var.environment}-domain" = {
host_name = local.hostname # For prod it must be equal to the dns_zone_name to use apex
dns_zone_name = var.dns_zone_name
dns_zone_rg_name = "rg-hub-${var.hub}-uks-public-dns-zones"
}
}
name = var.environment # environment-specific to avoid naming collisions within a Front Door Profile

origins = {
"${var.environment}-origin" = {
hostname = module.webapp.fqdn
origin_host_header = module.webapp.fqdn
private_link = {
target_type = "managedEnvironments"
location = var.region
private_link_target_id = var.container_app_environment_id
}
}
}
route = {
https_redirect_enabled = true
supported_protocols = ["Http", "Https"]
}
}
34 changes: 34 additions & 0 deletions infrastructure/modules/container-apps/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
resource "azurerm_resource_group" "main" {
name = local.resource_group_name
location = var.region
}

module "webapp" {
source = "../dtos-devops-templates/infrastructure/modules/container-app"

providers = {
azurerm = azurerm
azurerm.hub = azurerm.hub
}

name = "${var.app_short_name}-web-${var.environment}"
container_app_environment_id = var.container_app_environment_id
resource_group_name = azurerm_resource_group.main.name
fetch_secrets_from_app_key_vault = var.fetch_secrets_from_app_key_vault
infra_key_vault_name = "kv-${var.app_short_name}-${var.env_config}-inf"
infra_key_vault_rg = "rg-${var.app_short_name}-${var.env_config}-infra"
enable_auth = var.enable_auth
app_key_vault_id = var.app_key_vault_id
docker_image = var.docker_image
user_assigned_identity_ids = var.deploy_database_as_container ? [] : [module.db_connect_identity[0].id]
environment_variables = merge(
local.common_env,
{
ALLOWED_HOSTS = "${var.app_short_name}-web-${var.environment}.${var.default_domain}"
},
var.deploy_database_as_container ? local.container_db_env : local.azure_db_env
)
secret_variables = var.deploy_database_as_container ? { DATABASE_PASSWORD = resource.random_password.admin_password[0].result } : {}
is_web_app = true
port = 80
}
7 changes: 7 additions & 0 deletions infrastructure/modules/container-apps/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
output "internal_url" {
value = module.webapp.url
}

output "external_url" {
value = var.features.front_door ? "https://${module.frontdoor_endpoint.custom_domains["${var.environment}-domain"].host_name}/" : null
}
100 changes: 100 additions & 0 deletions infrastructure/modules/container-apps/postgres.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
data "azurerm_private_dns_zone" "postgres" {
count = var.features.private_networking ? 1 : 0

provider = azurerm.hub

name = "privatelink.postgres.database.azure.com"
resource_group_name = "rg-hub-${var.hub}-uks-private-dns-zones"
}

# Don't deploy if deploy_database_as_container is true
module "postgres" {
count = var.deploy_database_as_container ? 0 : 1

source = "../dtos-devops-templates/infrastructure/modules/postgresql-flexible"

# postgresql Server
name = "postgres-${var.app_short_name}-${var.environment}-uks"
resource_group_name = azurerm_resource_group.main.name
location = var.region

backup_retention_days = var.postgres_backup_retention_days
geo_redundant_backup_enabled = var.postgres_geo_redundant_backup_enabled
postgresql_admin_object_id = "" #data.azuread_group.postgres_sql_admin_group.object_id
postgresql_admin_principal_name = var.postgres_sql_admin_group
postgresql_admin_principal_type = "Group"
administrator_login = local.database_user
admin_identities = [module.db_connect_identity[0]]

# Diagnostic Settings
log_analytics_workspace_id = var.log_analytics_workspace_audit_id
monitor_diagnostic_setting_postgresql_server_enabled_logs = ["PostgreSQLLogs", "PostgreSQLFlexSessions", "PostgreSQLFlexQueryStoreRuntime", "PostgreSQLFlexQueryStoreWaitStats", "PostgreSQLFlexTableStats", "PostgreSQLFlexDatabaseXacts"]
monitor_diagnostic_setting_postgresql_server_metrics = ["AllMetrics"]

sku_name = var.postgres_sku_name
storage_mb = var.postgres_storage_mb
storage_tier = var.postgres_storage_tier

server_version = "16"
tenant_id = data.azurerm_client_config.current.tenant_id

private_endpoint_properties = var.features.private_networking ? {
private_dns_zone_ids_postgresql = [data.azurerm_private_dns_zone.postgres[0].id]
private_endpoint_enabled = true
private_endpoint_subnet_id = var.postgres_subnet_id
private_endpoint_resource_group_name = azurerm_resource_group.main.name
private_service_connection_is_manual = false
} : null

databases = {
db1 = {
collation = "en_US.utf8"
charset = "UTF8"
max_size_gb = 10
name = local.database_name
}
}

tags = {}
}

module "db_connect_identity" {
count = var.deploy_database_as_container ? 0 : 1

source = "../dtos-devops-templates/infrastructure/modules/managed-identity"
resource_group_name = azurerm_resource_group.main.name
location = var.region
uai_name = "mi-${var.app_short_name}-${var.environment}-db-connect"
}

resource "random_password" "admin_password" {
count = var.deploy_database_as_container ? 1 : 0

length = 30
special = true
override_special = "!@#$%^&*()-_=+"
}

module "database_container" {
count = var.deploy_database_as_container ? 1 : 0

providers = {
azurerm = azurerm
azurerm.hub = azurerm.hub
}

source = "../dtos-devops-templates/infrastructure/modules/container-app"
name = "${var.app_short_name}-db-${var.environment}"
container_app_environment_id = var.container_app_environment_id
docker_image = "postgres:16"
secret_variables = var.deploy_database_as_container ? { POSTGRES_PASSWORD = resource.random_password.admin_password[0].result } : {}
environment_variables = {
POSTGRES_USER = local.database_user
POSTGRES_DB = local.database_name
}
resource_group_name = azurerm_resource_group.main.name
is_tcp_app = true
# postgres has a port of 5432
port = 5432
exposed_port = local.database_port
}
8 changes: 8 additions & 0 deletions infrastructure/modules/container-apps/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
configuration_aliases = [azurerm.hub]
}
}
}
53 changes: 53 additions & 0 deletions infrastructure/modules/container-apps/storage.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module "azure_blob_storage_identity" {
source = "../dtos-devops-templates/infrastructure/modules/managed-identity"
resource_group_name = azurerm_resource_group.main.name
location = var.region
uai_name = "mi-${var.app_short_name}-${var.environment}-blob-storage"
}

module "azure_queue_storage_identity" {
source = "../dtos-devops-templates/infrastructure/modules/managed-identity"
resource_group_name = azurerm_resource_group.main.name
location = var.region
uai_name = "mi-${var.app_short_name}-${var.environment}-queue-storage"
}

module "storage" {
source = "../dtos-devops-templates/infrastructure/modules/storage"

containers = local.storage_containers
location = var.region
log_analytics_workspace_id = var.log_analytics_workspace_audit_id

monitor_diagnostic_setting_storage_account_enabled_logs = ["StorageWrite", "StorageRead", "StorageDelete"]
monitor_diagnostic_setting_storage_account_metrics = ["AllMetrics"]

name = replace(lower(local.storage_account_name), "-", "")

private_endpoint_properties = var.features.private_networking ? {
private_dns_zone_ids_blob = [data.azurerm_private_dns_zone.storage-account-blob[0].id]
private_dns_zone_ids_queue = [data.azurerm_private_dns_zone.storage-account-queue[0].id]
private_endpoint_enabled = true
private_endpoint_subnet_id = var.main_subnet_id
private_endpoint_resource_group_name = azurerm_resource_group.main.name
private_service_connection_is_manual = false
} : null
queues = local.storage_queues
resource_group_name = azurerm_resource_group.main.name
}

module "blob_storage_role_assignment" {
source = "../dtos-devops-templates/infrastructure/modules/rbac-assignment"
principal_id = module.azure_blob_storage_identity.principal_id
role_definition_name = "Storage Blob Data Contributor"
scope = module.storage.storage_account_id
depends_on = [module.storage, module.azure_blob_storage_identity]
}

module "queue_storage_role_assignment" {
source = "../dtos-devops-templates/infrastructure/modules/rbac-assignment"
principal_id = module.azure_queue_storage_identity.principal_id
role_definition_name = "Storage Queue Data Contributor"
scope = module.storage.storage_account_id
depends_on = [module.storage, module.azure_queue_storage_identity]
}
Loading
Loading