+```
+
+##### Initialise Terraform
+
+Install the required terraform version with the Terraform version manager `tfenv`:
+
+```
+$ tfenv install
+```
+
+Initialize Terraform to download the required Terraform modules and configure the remote state backend
+to use the settings you specified in the previous step.
+
+`$ terraform init -backend-config=backend.vars`
+
+##### Create a Terraform variables file
+
+Each environment will need it's own `tfvars` file.
+
+Copy the `terraform.tfvars.example` to `environment-name.tfvars` and modify the contents as required
+
+##### Create the infrastructure
+
+Now Terraform has been initialised you can create a workspace if needed:
+
+`$ terraform workspace new staging`
+
+Or to check what workspaces already exist:
+
+`$ terraform workspace list`
+
+Switch to the new or existing workspace:
+
+`$ terraform workspace select staging`
+
+Plan the changes:
+
+`$ terraform plan -var-file=staging.tfvars`
+
+Terraform will ask you to provide any variables not specified in an `*.auto.tfvars` file.
+Now you can run:
+
+`$ terraform apply -var-file=staging.tfvars`
+
+If everything looks good, answer `yes` and wait for the new infrastructure to be created.
+
+##### Azure resources
+
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | ~> 1.9 |
+| [azapi](#requirement\_azapi) | ~> 1.13 |
+| [azurerm](#requirement\_azurerm) | ~> 4.0 |
+| [statuscake](#requirement\_statuscake) | ~> 2.1 |
+
+## Providers
+
+No providers.
+
+## Modules
+
+| Name | Source | Version |
+|------|--------|---------|
+| [azure\_container\_apps\_hosting](#module\_azure\_container\_apps\_hosting) | github.com/DFE-Digital/terraform-azurerm-container-apps-hosting | v1.16.6 |
+| [azurerm\_key\_vault](#module\_azurerm\_key\_vault) | github.com/DFE-Digital/terraform-azurerm-key-vault-tfvars | v0.5.1 |
+| [statuscake-tls-monitor](#module\_statuscake-tls-monitor) | github.com/dfe-digital/terraform-statuscake-tls-monitor | v0.1.5 |
+
+## Resources
+
+No resources.
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [azure\_client\_id](#input\_azure\_client\_id) | Service Principal Client ID | `string` | n/a | yes |
+| [azure\_client\_secret](#input\_azure\_client\_secret) | Service Principal Client Secret | `string` | n/a | yes |
+| [azure\_location](#input\_azure\_location) | Azure location in which to launch resources. | `string` | n/a | yes |
+| [azure\_subscription\_id](#input\_azure\_subscription\_id) | Service Principal Subscription ID | `string` | n/a | yes |
+| [azure\_tenant\_id](#input\_azure\_tenant\_id) | Service Principal Tenant ID | `string` | n/a | yes |
+| [container\_apps\_allow\_ips\_inbound](#input\_container\_apps\_allow\_ips\_inbound) | Restricts access to the Container Apps by creating a network security group rule that only allow inbound traffic from the provided list of IPs | `list(string)` | `[]` | no |
+| [container\_command](#input\_container\_command) | Container command | `list(any)` | n/a | yes |
+| [container\_health\_probe\_path](#input\_container\_health\_probe\_path) | Specifies the path that is used to determine the liveness of the Container | `string` | n/a | yes |
+| [container\_min\_replicas](#input\_container\_min\_replicas) | Container min replicas | `number` | `1` | no |
+| [container\_port](#input\_container\_port) | Container port | `number` | `8080` | no |
+| [container\_scale\_http\_concurrency](#input\_container\_scale\_http\_concurrency) | When the number of concurrent HTTP requests exceeds this value, then another replica is added. Replicas continue to add to the pool up to the max-replicas amount. | `number` | `10` | no |
+| [container\_secret\_environment\_variables](#input\_container\_secret\_environment\_variables) | Container secret environment variables | `map(string)` | n/a | yes |
+| [dns\_alias\_records](#input\_dns\_alias\_records) | DNS ALIAS records to add to the DNS Zone | map(
object({
ttl : optional(number, 300),
target_resource_id : string
})
)
| `{}` | no |
+| [dns\_mx\_records](#input\_dns\_mx\_records) | DNS MX records to add to the DNS Zone | map(
object({
ttl : optional(number, 300),
records : list(
object({
preference : number,
exchange : string
})
)
})
)
| `{}` | no |
+| [dns\_ns\_records](#input\_dns\_ns\_records) | DNS NS records to add to the DNS Zone | map(
object({
ttl : optional(number, 300),
records : list(string)
})
)
| n/a | yes |
+| [dns\_txt\_records](#input\_dns\_txt\_records) | DNS TXT records to add to the DNS Zone | map(
object({
ttl : optional(number, 300),
records : list(string)
})
)
| n/a | yes |
+| [dns\_zone\_domain\_name](#input\_dns\_zone\_domain\_name) | DNS zone domain name. If created, records will automatically be created to point to the CDN. | `string` | n/a | yes |
+| [enable\_container\_registry](#input\_enable\_container\_registry) | Set to true to create a container registry | `bool` | `false` | no |
+| [enable\_dns\_zone](#input\_enable\_dns\_zone) | Conditionally create a DNS zone | `bool` | n/a | yes |
+| [enable\_health\_insights\_api](#input\_enable\_health\_insights\_api) | Deploys a Function App that exposes the last 3 HTTP Web Tests via an API endpoint. 'enable\_app\_insights\_integration' and 'enable\_monitoring' must be set to 'true'. | `bool` | `false` | no |
+| [enable\_monitoring](#input\_enable\_monitoring) | Create an App Insights instance and notification group for the Container App | `bool` | n/a | yes |
+| [environment](#input\_environment) | Environment name. Will be used along with `project_name` as a prefix for all resources. | `string` | n/a | yes |
+| [existing\_container\_app\_environment](#input\_existing\_container\_app\_environment) | Conditionally launch resources into an existing Container App environment. Specifying this will NOT create an environment. | object({
name = string
resource_group = string
})
| n/a | yes |
+| [existing\_logic\_app\_workflow](#input\_existing\_logic\_app\_workflow) | Name, and Resource Group of an existing Logic App Workflow. Leave empty to create a new Resource | object({
name : string
resource_group_name : string
})
| {
"name": "",
"resource_group_name": ""
}
| no |
+| [existing\_resource\_group](#input\_existing\_resource\_group) | Conditionally launch resources into an existing resource group. Specifying this will NOT create a resource group. | `string` | n/a | yes |
+| [existing\_virtual\_network](#input\_existing\_virtual\_network) | Conditionally use an existing virtual network. The `virtual_network_address_space` must match an existing address space in the VNet. This also requires the resource group name. | `string` | n/a | yes |
+| [health\_insights\_api\_cors\_origins](#input\_health\_insights\_api\_cors\_origins) | List of hostnames that are permitted to contact the Health insights API | `list(string)` | [
"*"
]
| no |
+| [health\_insights\_api\_ipv4\_allow\_list](#input\_health\_insights\_api\_ipv4\_allow\_list) | List of IPv4 addresses that are permitted to contact the Health insights API | `list(string)` | `[]` | no |
+| [image\_name](#input\_image\_name) | Image name | `string` | n/a | yes |
+| [image\_tag](#input\_image\_tag) | Image tag | `string` | n/a | yes |
+| [key\_vault\_access\_ipv4](#input\_key\_vault\_access\_ipv4) | List of IPv4 Addresses that are permitted to access the Key Vault | `list(string)` | n/a | yes |
+| [monitor\_email\_receivers](#input\_monitor\_email\_receivers) | A list of email addresses that should be notified by monitoring alerts | `list(string)` | n/a | yes |
+| [monitor\_endpoint\_healthcheck](#input\_monitor\_endpoint\_healthcheck) | Specify a route that should be monitored for a 200 OK status | `string` | n/a | yes |
+| [monitor\_http\_availability\_fqdn](#input\_monitor\_http\_availability\_fqdn) | Specify a FQDN to monitor for HTTP Availability. Leave unset to dynamically calculate the correct FQDN | `string` | `""` | no |
+| [monitor\_http\_availability\_verb](#input\_monitor\_http\_availability\_verb) | Which HTTP verb to use for the HTTP Availability check | `string` | `"GET"` | no |
+| [project\_name](#input\_project\_name) | Project name. Will be used along with `environment` as a prefix for all resources. | `string` | n/a | yes |
+| [registry\_admin\_enabled](#input\_registry\_admin\_enabled) | Do you want to enable access key based authentication for your Container Registry? | `bool` | `false` | no |
+| [registry\_managed\_identity\_assign\_role](#input\_registry\_managed\_identity\_assign\_role) | Assign the 'AcrPull' Role to the Container App User-Assigned Managed Identity. Note: If you do not have 'Microsoft.Authorization/roleAssignments/write' permission, you will need to manually assign the 'AcrPull' Role to the identity | `bool` | `false` | no |
+| [registry\_server](#input\_registry\_server) | Container registry server (required if `enable_container_registry` is false) | `string` | `""` | no |
+| [registry\_use\_managed\_identity](#input\_registry\_use\_managed\_identity) | Create a User-Assigned Managed Identity for the Container App. Note: If you do not have 'Microsoft.Authorization/roleAssignments/write' permission, you will need to manually assign the 'AcrPull' Role to the identity | `bool` | `true` | no |
+| [statuscake\_api\_token](#input\_statuscake\_api\_token) | API token for StatusCake | `string` | `"00000000000000000000000000000"` | no |
+| [statuscake\_contact\_group\_email\_addresses](#input\_statuscake\_contact\_group\_email\_addresses) | List of email address that should receive notifications from StatusCake | `list(string)` | `[]` | no |
+| [statuscake\_contact\_group\_integrations](#input\_statuscake\_contact\_group\_integrations) | List of Integration IDs to connect to your Contact Group | `list(string)` | `[]` | no |
+| [statuscake\_contact\_group\_name](#input\_statuscake\_contact\_group\_name) | Name of the contact group in StatusCake | `string` | `""` | no |
+| [statuscake\_monitored\_resource\_addresses](#input\_statuscake\_monitored\_resource\_addresses) | The URLs to perform TLS checks on | `list(string)` | `[]` | no |
+| [tags](#input\_tags) | Tags to be applied to all resources | `map(string)` | n/a | yes |
+| [tfvars\_filename](#input\_tfvars\_filename) | tfvars filename. This file is uploaded and stored encrupted within Key Vault, to ensure that the latest tfvars are stored in a shared place. | `string` | n/a | yes |
+
+## Outputs
+
+No outputs.
+
diff --git a/terraform/backend.tf b/terraform/backend.tf
new file mode 100644
index 00000000..40e5c433
--- /dev/null
+++ b/terraform/backend.tf
@@ -0,0 +1,5 @@
+terraform {
+ backend "azurerm" {
+ use_azuread_auth = true
+ }
+}
diff --git a/terraform/backend.vars.example b/terraform/backend.vars.example
new file mode 100644
index 00000000..c6158784
--- /dev/null
+++ b/terraform/backend.vars.example
@@ -0,0 +1,8 @@
+resource_group_name = ""
+storage_account_name = ""
+container_name = ""
+key = ""
+subscription_id = ""
+client_id = ""
+client_secret = ""
+tenant_id = ""
diff --git a/terraform/container-apps-hosting.tf b/terraform/container-apps-hosting.tf
new file mode 100644
index 00000000..d389fd82
--- /dev/null
+++ b/terraform/container-apps-hosting.tf
@@ -0,0 +1,47 @@
+module "azure_container_apps_hosting" {
+ source = "github.com/DFE-Digital/terraform-azurerm-container-apps-hosting?ref=v1.16.6"
+
+ environment = local.environment
+ project_name = local.project_name
+ azure_location = local.azure_location
+ tags = local.tags
+
+ enable_container_registry = local.enable_container_registry
+ registry_admin_enabled = local.registry_admin_enabled
+ registry_use_managed_identity = local.registry_use_managed_identity
+ registry_managed_identity_assign_role = local.registry_managed_identity_assign_role
+ registry_server = local.registry_server
+
+ enable_dns_zone = local.enable_dns_zone
+ dns_zone_domain_name = local.dns_zone_domain_name
+ dns_ns_records = local.dns_ns_records
+ dns_txt_records = local.dns_txt_records
+ dns_mx_records = local.dns_mx_records
+ dns_alias_records = local.dns_alias_records
+
+ image_name = local.image_name
+ image_tag = local.image_tag
+ container_command = local.container_command
+ container_secret_environment_variables = local.container_secret_environment_variables
+ container_scale_http_concurrency = local.container_scale_http_concurrency
+ container_apps_allow_ips_inbound = local.container_apps_allow_ips_inbound
+ container_min_replicas = local.container_min_replicas
+ container_port = local.container_port
+ enable_health_insights_api = local.enable_health_insights_api
+ health_insights_api_cors_origins = local.health_insights_api_cors_origins
+ health_insights_api_ipv4_allow_list = local.health_insights_api_ipv4_allow_list
+
+ existing_container_app_environment = local.existing_container_app_environment
+ existing_virtual_network = local.existing_virtual_network
+ existing_resource_group = local.existing_resource_group
+ launch_in_vnet = false
+ container_app_name_override = "complete-dotnet-app"
+
+ enable_monitoring = local.enable_monitoring
+ monitor_email_receivers = local.monitor_email_receivers
+ container_health_probe_path = local.container_health_probe_path
+ monitor_endpoint_healthcheck = local.monitor_endpoint_healthcheck
+ existing_logic_app_workflow = local.existing_logic_app_workflow
+ monitor_http_availability_verb = local.monitor_http_availability_verb
+ monitor_http_availability_fqdn = local.monitor_http_availability_fqdn
+}
diff --git a/terraform/key-vault-tfvars-secrets.tf b/terraform/key-vault-tfvars-secrets.tf
new file mode 100644
index 00000000..2bac5a34
--- /dev/null
+++ b/terraform/key-vault-tfvars-secrets.tf
@@ -0,0 +1,17 @@
+module "azurerm_key_vault" {
+ source = "github.com/DFE-Digital/terraform-azurerm-key-vault-tfvars?ref=v0.5.1"
+
+ environment = local.environment
+ project_name = "compnet"
+ existing_resource_group = local.existing_resource_group
+ azure_location = local.azure_location
+ key_vault_access_use_rbac_authorization = true
+ key_vault_access_users = []
+ key_vault_access_ipv4 = local.key_vault_access_ipv4
+ tfvars_filename = local.tfvars_filename
+ diagnostic_log_analytics_workspace_id = module.azure_container_apps_hosting.azurerm_log_analytics_workspace_container_app.id
+ diagnostic_eventhub_name = ""
+ tags = local.tags
+
+ depends_on = [module.azure_container_apps_hosting]
+}
diff --git a/terraform/locals.tf b/terraform/locals.tf
new file mode 100644
index 00000000..02dd269d
--- /dev/null
+++ b/terraform/locals.tf
@@ -0,0 +1,44 @@
+locals {
+ environment = var.environment
+ project_name = var.project_name
+ azure_location = var.azure_location
+ tags = var.tags
+ enable_container_registry = var.enable_container_registry
+ registry_admin_enabled = var.registry_admin_enabled
+ registry_use_managed_identity = var.registry_use_managed_identity
+ registry_managed_identity_assign_role = var.registry_managed_identity_assign_role
+ registry_server = var.registry_server
+ image_name = var.image_name
+ image_tag = var.image_tag
+ container_command = var.container_command
+ container_secret_environment_variables = var.container_secret_environment_variables
+ container_scale_http_concurrency = var.container_scale_http_concurrency
+ container_min_replicas = var.container_min_replicas
+ container_port = var.container_port
+ existing_container_app_environment = var.existing_container_app_environment
+ existing_virtual_network = var.existing_virtual_network
+ existing_resource_group = var.existing_resource_group
+ enable_dns_zone = var.enable_dns_zone
+ dns_zone_domain_name = var.dns_zone_domain_name
+ dns_ns_records = var.dns_ns_records
+ dns_txt_records = var.dns_txt_records
+ dns_mx_records = var.dns_mx_records
+ dns_alias_records = var.dns_alias_records
+ key_vault_access_ipv4 = var.key_vault_access_ipv4
+ tfvars_filename = var.tfvars_filename
+ enable_monitoring = var.enable_monitoring
+ monitor_email_receivers = var.monitor_email_receivers
+ container_apps_allow_ips_inbound = var.container_apps_allow_ips_inbound
+ container_health_probe_path = var.container_health_probe_path
+ monitor_endpoint_healthcheck = var.monitor_endpoint_healthcheck
+ existing_logic_app_workflow = var.existing_logic_app_workflow
+ statuscake_monitored_resource_addresses = var.statuscake_monitored_resource_addresses
+ statuscake_contact_group_name = var.statuscake_contact_group_name
+ statuscake_contact_group_integrations = var.statuscake_contact_group_integrations
+ statuscake_contact_group_email_addresses = var.statuscake_contact_group_email_addresses
+ enable_health_insights_api = var.enable_health_insights_api
+ health_insights_api_cors_origins = var.health_insights_api_cors_origins
+ health_insights_api_ipv4_allow_list = var.health_insights_api_ipv4_allow_list
+ monitor_http_availability_verb = var.monitor_http_availability_verb
+ monitor_http_availability_fqdn = var.monitor_http_availability_fqdn
+}
diff --git a/terraform/providers.tf b/terraform/providers.tf
new file mode 100644
index 00000000..1f88c3e5
--- /dev/null
+++ b/terraform/providers.tf
@@ -0,0 +1,17 @@
+provider "azurerm" {
+ features {}
+ skip_provider_registration = true
+ storage_use_azuread = true
+ client_id = var.azure_client_id
+ client_secret = var.azure_client_secret
+ tenant_id = var.azure_tenant_id
+ subscription_id = var.azure_subscription_id
+}
+
+provider "azapi" {
+ enable_hcl_output_for_data_source = true
+}
+
+provider "statuscake" {
+ api_token = var.statuscake_api_token
+}
diff --git a/terraform/statuscake-tls-monitor.tf b/terraform/statuscake-tls-monitor.tf
new file mode 100644
index 00000000..40d836d5
--- /dev/null
+++ b/terraform/statuscake-tls-monitor.tf
@@ -0,0 +1,11 @@
+module "statuscake-tls-monitor" {
+ source = "github.com/dfe-digital/terraform-statuscake-tls-monitor?ref=v0.1.5"
+
+ statuscake_monitored_resource_addresses = local.statuscake_monitored_resource_addresses
+ statuscake_alert_at = [ # days to alert on
+ 40, 20, 5
+ ]
+ statuscake_contact_group_name = local.statuscake_contact_group_name
+ statuscake_contact_group_integrations = local.statuscake_contact_group_integrations
+ statuscake_contact_group_email_addresses = local.statuscake_contact_group_email_addresses
+}
diff --git a/terraform/terraform.tfvars.example b/terraform/terraform.tfvars.example
new file mode 100644
index 00000000..a0c7e660
--- /dev/null
+++ b/terraform/terraform.tfvars.example
@@ -0,0 +1,16 @@
+environment = "development"
+project_name = "myproject"
+azure_location = "uksouth"
+enable_container_registry = true
+image_name = "myimage"
+enable_mssql_database = true
+enable_redis_cache = true
+mssql_server_admin_password = "S3crEt"
+mssql_database_name = "mydatabase"
+container_command = ["/bin/bash", "-c", "echo hello && sleep 86400"]
+container_environment_variables = {
+ "ASPNETCORE_ENVIRONMENT" = "production"
+}
+key_vault_access_users = [
+ "someone_example.com#EXT#@tenantname.onmicrosoft.com",
+]
diff --git a/terraform/variables.tf b/terraform/variables.tf
new file mode 100644
index 00000000..5b44b65a
--- /dev/null
+++ b/terraform/variables.tf
@@ -0,0 +1,293 @@
+variable "azure_client_id" {
+ description = "Service Principal Client ID"
+ type = string
+}
+
+variable "azure_client_secret" {
+ description = "Service Principal Client Secret"
+ type = string
+ sensitive = true
+}
+
+variable "azure_tenant_id" {
+ description = "Service Principal Tenant ID"
+ type = string
+}
+
+variable "azure_subscription_id" {
+ description = "Service Principal Subscription ID"
+ type = string
+}
+
+variable "environment" {
+ description = "Environment name. Will be used along with `project_name` as a prefix for all resources."
+ type = string
+}
+
+variable "key_vault_access_ipv4" {
+ description = "List of IPv4 Addresses that are permitted to access the Key Vault"
+ type = list(string)
+}
+
+variable "tfvars_filename" {
+ description = "tfvars filename. This file is uploaded and stored encrupted within Key Vault, to ensure that the latest tfvars are stored in a shared place."
+ type = string
+}
+
+variable "project_name" {
+ description = "Project name. Will be used along with `environment` as a prefix for all resources."
+ type = string
+}
+
+variable "azure_location" {
+ description = "Azure location in which to launch resources."
+ type = string
+}
+
+variable "tags" {
+ description = "Tags to be applied to all resources"
+ type = map(string)
+}
+
+variable "enable_container_registry" {
+ description = "Set to true to create a container registry"
+ type = bool
+ default = false
+}
+
+variable "registry_admin_enabled" {
+ description = "Do you want to enable access key based authentication for your Container Registry?"
+ type = bool
+ default = false
+}
+
+variable "registry_server" {
+ description = "Container registry server (required if `enable_container_registry` is false)"
+ type = string
+ default = ""
+}
+
+variable "registry_use_managed_identity" {
+ description = "Create a User-Assigned Managed Identity for the Container App. Note: If you do not have 'Microsoft.Authorization/roleAssignments/write' permission, you will need to manually assign the 'AcrPull' Role to the identity"
+ type = bool
+ default = true
+}
+
+variable "registry_managed_identity_assign_role" {
+ description = "Assign the 'AcrPull' Role to the Container App User-Assigned Managed Identity. Note: If you do not have 'Microsoft.Authorization/roleAssignments/write' permission, you will need to manually assign the 'AcrPull' Role to the identity"
+ type = bool
+ default = false
+}
+
+variable "image_name" {
+ description = "Image name"
+ type = string
+}
+
+variable "image_tag" {
+ description = "Image tag"
+ type = string
+}
+
+variable "container_command" {
+ description = "Container command"
+ type = list(any)
+}
+
+variable "container_secret_environment_variables" {
+ description = "Container secret environment variables"
+ type = map(string)
+ sensitive = true
+}
+
+variable "container_scale_http_concurrency" {
+ description = "When the number of concurrent HTTP requests exceeds this value, then another replica is added. Replicas continue to add to the pool up to the max-replicas amount."
+ type = number
+ default = 10
+}
+
+variable "enable_dns_zone" {
+ description = "Conditionally create a DNS zone"
+ type = bool
+}
+
+variable "dns_zone_domain_name" {
+ description = "DNS zone domain name. If created, records will automatically be created to point to the CDN."
+ type = string
+}
+
+variable "dns_ns_records" {
+ description = "DNS NS records to add to the DNS Zone"
+ type = map(
+ object({
+ ttl : optional(number, 300),
+ records : list(string)
+ })
+ )
+}
+
+variable "dns_txt_records" {
+ description = "DNS TXT records to add to the DNS Zone"
+ type = map(
+ object({
+ ttl : optional(number, 300),
+ records : list(string)
+ })
+ )
+}
+
+variable "dns_mx_records" {
+ description = "DNS MX records to add to the DNS Zone"
+ type = map(
+ object({
+ ttl : optional(number, 300),
+ records : list(
+ object({
+ preference : number,
+ exchange : string
+ })
+ )
+ })
+ )
+ default = {}
+}
+
+variable "dns_alias_records" {
+ description = "DNS ALIAS records to add to the DNS Zone"
+ type = map(
+ object({
+ ttl : optional(number, 300),
+ target_resource_id : string
+ })
+ )
+ default = {}
+}
+
+variable "container_apps_allow_ips_inbound" {
+ description = "Restricts access to the Container Apps by creating a network security group rule that only allow inbound traffic from the provided list of IPs"
+ type = list(string)
+ default = []
+}
+
+variable "enable_monitoring" {
+ description = "Create an App Insights instance and notification group for the Container App"
+ type = bool
+}
+
+variable "monitor_email_receivers" {
+ description = "A list of email addresses that should be notified by monitoring alerts"
+ type = list(string)
+}
+
+variable "container_health_probe_path" {
+ description = "Specifies the path that is used to determine the liveness of the Container"
+ type = string
+}
+
+variable "monitor_endpoint_healthcheck" {
+ description = "Specify a route that should be monitored for a 200 OK status"
+ type = string
+}
+
+variable "existing_logic_app_workflow" {
+ description = "Name, and Resource Group of an existing Logic App Workflow. Leave empty to create a new Resource"
+ type = object({
+ name : string
+ resource_group_name : string
+ })
+ default = {
+ name = ""
+ resource_group_name = ""
+ }
+}
+
+variable "statuscake_api_token" {
+ description = "API token for StatusCake"
+ type = string
+ sensitive = true
+ default = "00000000000000000000000000000"
+}
+
+variable "statuscake_contact_group_name" {
+ description = "Name of the contact group in StatusCake"
+ type = string
+ default = ""
+}
+
+variable "statuscake_contact_group_integrations" {
+ description = "List of Integration IDs to connect to your Contact Group"
+ type = list(string)
+ default = []
+}
+
+variable "statuscake_monitored_resource_addresses" {
+ description = "The URLs to perform TLS checks on"
+ type = list(string)
+ default = []
+}
+
+variable "statuscake_contact_group_email_addresses" {
+ description = "List of email address that should receive notifications from StatusCake"
+ type = list(string)
+ default = []
+}
+
+variable "container_min_replicas" {
+ description = "Container min replicas"
+ type = number
+ default = 1
+}
+
+variable "enable_health_insights_api" {
+ description = "Deploys a Function App that exposes the last 3 HTTP Web Tests via an API endpoint. 'enable_app_insights_integration' and 'enable_monitoring' must be set to 'true'."
+ type = bool
+ default = false
+}
+
+variable "health_insights_api_cors_origins" {
+ description = "List of hostnames that are permitted to contact the Health insights API"
+ type = list(string)
+ default = ["*"]
+}
+
+variable "health_insights_api_ipv4_allow_list" {
+ description = "List of IPv4 addresses that are permitted to contact the Health insights API"
+ type = list(string)
+ default = []
+}
+
+variable "container_port" {
+ description = "Container port"
+ type = number
+ default = 8080
+}
+
+variable "existing_container_app_environment" {
+ description = "Conditionally launch resources into an existing Container App environment. Specifying this will NOT create an environment."
+ type = object({
+ name = string
+ resource_group = string
+ })
+}
+
+variable "existing_virtual_network" {
+ description = "Conditionally use an existing virtual network. The `virtual_network_address_space` must match an existing address space in the VNet. This also requires the resource group name."
+ type = string
+}
+
+variable "existing_resource_group" {
+ description = "Conditionally launch resources into an existing resource group. Specifying this will NOT create a resource group."
+ type = string
+}
+
+variable "monitor_http_availability_verb" {
+ description = "Which HTTP verb to use for the HTTP Availability check"
+ type = string
+ default = "GET"
+}
+
+variable "monitor_http_availability_fqdn" {
+ description = "Specify a FQDN to monitor for HTTP Availability. Leave unset to dynamically calculate the correct FQDN"
+ type = string
+ default = ""
+}
diff --git a/terraform/versions.tf b/terraform/versions.tf
new file mode 100644
index 00000000..73673e98
--- /dev/null
+++ b/terraform/versions.tf
@@ -0,0 +1,20 @@
+terraform {
+ required_version = "~> 1.9"
+
+ required_providers {
+ azurerm = {
+ source = "hashicorp/azurerm"
+ version = "~> 4.0"
+ }
+
+ statuscake = {
+ source = "StatusCakeDev/statuscake"
+ version = "~> 2.1"
+ }
+
+ azapi = {
+ source = "Azure/azapi"
+ version = "~> 1.13"
+ }
+ }
+}