From 016872dbddcfd7e3217ee7bfa945a054d8797403 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Mon, 20 Jul 2026 20:31:56 +0100 Subject: [PATCH] Modify terraform * The terraform was copied from external applications, but not all resources are required --- terraform-python-lsrp/.terraform-docs.yml | 26 -- terraform-python-lsrp/.terraform-version | 1 - terraform-python-lsrp/.terraform.lock.hcl | 102 ------ terraform-python-lsrp/README.md | 201 ------------ terraform-python-lsrp/backend.tf | 5 - .../container-apps-hosting.tf | 54 ---- .../key-vault-tfvars-secrets.tf | 17 - terraform-python-lsrp/locals.tf | 45 --- terraform-python-lsrp/providers.tf | 13 - terraform-python-lsrp/variables.tf | 290 ------------------ terraform-python-lsrp/versions.tf | 15 - terraform/.terraform.lock.hcl | 49 +-- terraform/README.md | 47 ++- terraform/backend.vars.example | 8 - terraform/container-apps-hosting.tf | 50 ++- terraform/key-vault-tfvars-secrets.tf | 19 -- terraform/locals.tf | 95 +++--- terraform/providers.tf | 4 - .../scripts/check-tfvars-against-remote.sh | 93 ++++++ terraform/statuscake-tls-monitor.tf | 11 - terraform/tfvars-storage.tf | 47 +++ terraform/variables.tf | 225 ++------------ terraform/versions.tf | 5 + 23 files changed, 273 insertions(+), 1149 deletions(-) delete mode 100644 terraform-python-lsrp/.terraform-docs.yml delete mode 100644 terraform-python-lsrp/.terraform-version delete mode 100644 terraform-python-lsrp/.terraform.lock.hcl delete mode 100644 terraform-python-lsrp/README.md delete mode 100644 terraform-python-lsrp/backend.tf delete mode 100644 terraform-python-lsrp/container-apps-hosting.tf delete mode 100644 terraform-python-lsrp/key-vault-tfvars-secrets.tf delete mode 100644 terraform-python-lsrp/locals.tf delete mode 100644 terraform-python-lsrp/providers.tf delete mode 100644 terraform-python-lsrp/variables.tf delete mode 100644 terraform-python-lsrp/versions.tf delete mode 100644 terraform/backend.vars.example delete mode 100644 terraform/key-vault-tfvars-secrets.tf create mode 100755 terraform/scripts/check-tfvars-against-remote.sh delete mode 100644 terraform/statuscake-tls-monitor.tf create mode 100644 terraform/tfvars-storage.tf diff --git a/terraform-python-lsrp/.terraform-docs.yml b/terraform-python-lsrp/.terraform-docs.yml deleted file mode 100644 index a691780..0000000 --- a/terraform-python-lsrp/.terraform-docs.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -formatter: "markdown table" -version: "~> 0.16" -settings: - anchor: true - default: true - description: false - escape: true - hide-empty: false - html: true - indent: 2 - lockfile: true - read-comments: true - required: true - sensitive: true - type: true -sort: - enabled: true - by: name -output: - file: README.md - mode: inject - template: |- - - {{ .Content }} - diff --git a/terraform-python-lsrp/.terraform-version b/terraform-python-lsrp/.terraform-version deleted file mode 100644 index 4ea8ad8..0000000 --- a/terraform-python-lsrp/.terraform-version +++ /dev/null @@ -1 +0,0 @@ -1.14.3 diff --git a/terraform-python-lsrp/.terraform.lock.hcl b/terraform-python-lsrp/.terraform.lock.hcl deleted file mode 100644 index fcb1dcb..0000000 --- a/terraform-python-lsrp/.terraform.lock.hcl +++ /dev/null @@ -1,102 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/azure/azapi" { - version = "1.15.0" - constraints = "~> 1.13" - hashes = [ - "h1:pO/phGY+TxMEKQ+ffYj+vUIvG5A1tno/sZYDb/yyA/w=", - "zh:0627a8bc77254debc25dc0c7b62e055138217c97b03221e593c3c56dc7550671", - "zh:2fe045f07070ef75d0bec4b0595a74c14394daa838ddb964e2fd23cc98c40c34", - "zh:343009f39c957883b2c06145a5954e524c70f93585f943f1ea3d28ef6995d0d0", - "zh:53fe9ab54485aaebc9b91e27a10bce2729a1c95b1399079e631dc6bb9e3f27dc", - "zh:63c407e7dc04d178d4798c17ad489d9cc92f7d1941d7f4a3f560b95908b6107b", - "zh:7d6fc2b432b264f036bb80ab2b2ba67f80a5d98da8a8c322aa097833dad598c9", - "zh:7ec49c0a8799d469eb6e2a1f856693f9862f1b73f5ed70adc1b346e5a4c6458d", - "zh:889704f10319d301d677539d788fc82a7c73608ab78cb93e1280ac2be39e6e00", - "zh:90b4b07405b7cde9ebae3b034cb5bb5dd18484d1b95bd250f905451f1e86ac3f", - "zh:92aa9c241a8cb2a6d81ad47bc007c119f8b818464a960ebaf39008766c361e6b", - "zh:f28fbd0a2c59e239b53067bc1adc691be444876bcb2d4f78d310f549724da6e0", - "zh:ffb15e0ddfa505d0e9b75341570199076ae574887124f398162b1ead9376b25f", - ] -} - -provider "registry.terraform.io/hashicorp/archive" { - version = "2.7.1" - constraints = "~> 2.6" - hashes = [ - "h1:A7EnRBVm4h9ryO9LwxYnKr4fy7ExPMwD5a1DsY7m1Y0=", - "zh:19881bb356a4a656a865f48aee70c0b8a03c35951b7799b6113883f67f196e8e", - "zh:2fcfbf6318dd514863268b09bbe19bfc958339c636bcbcc3664b45f2b8bf5cc6", - "zh:3323ab9a504ce0a115c28e64d0739369fe85151291a2ce480d51ccbb0c381ac5", - "zh:362674746fb3da3ab9bd4e70c75a3cdd9801a6cf258991102e2c46669cf68e19", - "zh:7140a46d748fdd12212161445c46bbbf30a3f4586c6ac97dd497f0c2565fe949", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:875e6ce78b10f73b1efc849bfcc7af3a28c83a52f878f503bb22776f71d79521", - "zh:b872c6ed24e38428d817ebfb214da69ea7eefc2c38e5a774db2ccd58e54d3a22", - "zh:cd6a44f731c1633ae5d37662af86e7b01ae4c96eb8b04144255824c3f350392d", - "zh:e0600f5e8da12710b0c52d6df0ba147a5486427c1a2cc78f31eea37a47ee1b07", - "zh:f21b2e2563bbb1e44e73557bcd6cdbc1ceb369d471049c40eb56cb84b6317a60", - "zh:f752829eba1cc04a479cf7ae7271526b402e206d5bcf1fcce9f535de5ff9e4e6", - ] -} - -provider "registry.terraform.io/hashicorp/azuread" { - version = "2.53.1" - constraints = "~> 2.37" - hashes = [ - "h1:EZNO8sEtUABuRxujQrDrW1z1QsG0dq6iLbzWtnG7Om4=", - "zh:162916b037e5133f49298b0ffa3e7dcef7d76530a8ca738e7293373980f73c68", - "zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7", - "zh:492931cea4f30887ab5bca36a8556dfcb897288eddd44619c0217fc5da2d57e7", - "zh:4c895e450e18335ad8714cc6d3488fc1a78816ad2851a91b06cb2ef775dd7c66", - "zh:60d92fdaf7235574201f2d8f68f733ee00a822993b3fc95e6952e09e6ec76999", - "zh:67a169119efa41c1fb867ef1a8e79bf03472a2324384c36eb55370c817dcce42", - "zh:9dd4d5ed9233cf9329262200bc5a1aa60942b80dbc611e2ef4b09f47531b39b1", - "zh:a3c160e35b9e40fc1497b83c2f37a8e24565b05a1783c7733609f3695735c2a9", - "zh:a4a221da42b1f46e7c436c7145e5beaadfd9d03f3be6fd526d132c03f18a5979", - "zh:af0d3476a9702d2287e168e3baa670e64daab9c9b01c01e17025a5248f3e28e9", - "zh:e3579bff7894f3d36066b74ec324be6d28f56a42a387a2b8a0eabf33cbff86df", - "zh:f1749ee8ad972ae6424665aa9d2c0ece8c40c51d41ec2f38b863148cb437e865", - ] -} - -provider "registry.terraform.io/hashicorp/azurerm" { - version = "4.58.0" - constraints = "~> 4.0, ~> 4.37" - hashes = [ - "h1:k0a/JkkhIEGrJ/oR7MZWbTZsUXHQ18JIPcVWBdW+V58=", - "zh:041c2a778ab4dd5a9af174b1d6f75409e5aabfc359cb386dfea3fb09e3f32709", - "zh:0a302531a61e7383acf99a6202d7984b2ea559306f45021381665c827a830d46", - "zh:0c69f132c7609683d907e87b89210a298d84c5b0121b62278949931bc54ca952", - "zh:0cadf48e9d2d9daed43212a3c9d886d7faaf68787b6e955456cbe4f43e4a17ec", - "zh:35ef4293d7731f6ff1f8bcba2c4529f987b7fac243c1ac1c154bbc02c9703c25", - "zh:3cb2679e1d56865e0ee0cf4c5d1404dbad0db42d11425e7bf0580a026cc64287", - "zh:4e56411f5119042d4962acff5c6d64224a49a69154ba80e6df63fa57b1e6d284", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:ca4626411a111720c220f9849c7d2e1fcd5d380f56459e096d835a9dbf9e6e13", - "zh:d31c4e65dcb096974479b2d548fffb86fc9a5262aff1b01fe62ef442ce536c6b", - "zh:d9631602999c1853e53ee2c5aef7476e23c7787beddc3599c10dbaa4891ba166", - "zh:f31ba7c9341037ceb7d49467946c01b2b0930404ed1d5643c1451f734a613a03", - ] -} - -provider "registry.terraform.io/hashicorp/null" { - version = "3.2.4" - constraints = "~> 3.2" - hashes = [ - "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", - "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", - "zh:7b9c7b16f118fbc2b05a983817b8ce2f86df125857966ad356353baf4bff5c0a", - "zh:85e33ab43e0e1726e5f97a874b8e24820b6565ff8076523cc2922ba671492991", - "zh:9d32ac3619cfc93eb3c4f423492a8e0f79db05fec58e449dee9b2d5873d5f69f", - "zh:9e15c3c9dd8e0d1e3731841d44c34571b6c97f5b95e8296a45318b94e5287a6e", - "zh:b4c2ab35d1b7696c30b64bf2c0f3a62329107bd1a9121ce70683dec58af19615", - "zh:c43723e8cc65bcdf5e0c92581dcbbdcbdcf18b8d2037406a5f2033b1e22de442", - "zh:ceb5495d9c31bfb299d246ab333f08c7fb0d67a4f82681fbf47f2a21c3e11ab5", - "zh:e171026b3659305c558d9804062762d168f50ba02b88b231d20ec99578a6233f", - "zh:ed0fe2acdb61330b01841fa790be00ec6beaac91d41f311fb8254f74eb6a711f", - ] -} diff --git a/terraform-python-lsrp/README.md b/terraform-python-lsrp/README.md deleted file mode 100644 index 60b8910..0000000 --- a/terraform-python-lsrp/README.md +++ /dev/null @@ -1,201 +0,0 @@ -This documentation covers the deployment of the infrastructure to host the app. - -## Azure infrastructure - -The infrastructure is managed using [Terraform](https://www.terraform.io/).
-The state is stored remotely in encrypted Azure storage.
-[Terraform workspaces](https://www.terraform.io/docs/state/workspaces.html) are used to separate environments. - -#### Configuring the storage backend - -The Terraform state is stored remotely in Azure, this allows multiple team members to -make changes and means the state file is backed up. The state file contains -sensitive information so access to it should be restricted, and it should be stored -encrypted at rest. - -##### Create a new storage backend - -This step only needs to be done once per project (eg. not per environment). -If it has already been created, obtain the storage backend attributes and skip to the next step. - -The [Azure tutorial](https://docs.microsoft.com/en-us/azure/developer/terraform/store-state-in-azure-storage) outlines the steps to create a storage account and container for the state file. You will need: - -- resource_group_name: The name of the resource group used for the Azure Storage account. -- storage_account_name: The name of the Azure Storage account. -- container_name: The name of the blob container. -- key: The name of the state store file to be created. - -##### Create a backend configuration file - -Create a new file named `backend.vars` with the following content: - -``` -resource_group_name = [the name of the Azure resource group] -storage_account_name = [the name of the Azure Storage account] -container_name = [the name of the blob container] -key = "terraform.tstate" -``` - -##### Install dependencies - -We can use [Homebrew](https://brew.sh) to install the dependecies we need to deploy the infrastructure (eg. tfenv, Azure cli). -These are listed in the `Brewfile` - -to install, run: - -``` -$ brew bundle -``` - -##### Log into azure with the Azure CLI - -Log in to your account: - -``` -$ az login -``` - -Confirm which account you are currently using: - -``` -$ az account show -``` - -To list the available subscriptions, run: - -``` -$ az account list -``` - -Then if needed, switch to it using the 'id': - -``` -$ az account set --subscription -``` - -##### 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.14 | -| [azapi](#requirement\_azapi) | ~> 1.13 | -| [azurerm](#requirement\_azurerm) | ~> 4.0 | - -## 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 | v2.6.3 | -| [azurerm\_key\_vault](#module\_azurerm\_key\_vault) | github.com/DFE-Digital/terraform-azurerm-key-vault-tfvars | v0.5.2 | - -## 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\_app\_environment\_internal\_load\_balancer\_enabled](#input\_container\_app\_environment\_internal\_load\_balancer\_enabled) | Should the Container Environment operate in Internal Load Balancing Mode? | `bool` | `false` | no | -| [container\_app\_identities](#input\_container\_app\_identities) | Additional User Assigned Managed Identity Resource IDs to attach to the Container App | `list(string)` | `[]` | no | -| [container\_app\_name\_override](#input\_container\_app\_name\_override) | A custom name for the Container App | `string` | `""` | no | -| [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\_apps\_infra\_subnet\_cidr](#input\_container\_apps\_infra\_subnet\_cidr) | Specify a subnet prefix to use for the container\_apps\_infra subnet | `string` | `"172.16.110.32/28"` | 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` | n/a | yes | -| [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 | -| [enable\_monitoring\_traces](#input\_enable\_monitoring\_traces) | Monitor App Insights traces for error messages | `bool` | `true` | no | -| [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\_network\_watcher\_name](#input\_existing\_network\_watcher\_name) | Use an existing network watcher to add flow logs. | `string` | n/a | yes | -| [existing\_network\_watcher\_resource\_group\_name](#input\_existing\_network\_watcher\_resource\_group\_name) | Existing network watcher resource group. | `string` | n/a | yes | -| [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 | -| [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 | -| [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` | `true` | 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 | -| [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-python-lsrp/backend.tf b/terraform-python-lsrp/backend.tf deleted file mode 100644 index 40e5c43..0000000 --- a/terraform-python-lsrp/backend.tf +++ /dev/null @@ -1,5 +0,0 @@ -terraform { - backend "azurerm" { - use_azuread_auth = true - } -} diff --git a/terraform-python-lsrp/container-apps-hosting.tf b/terraform-python-lsrp/container-apps-hosting.tf deleted file mode 100644 index aa898d1..0000000 --- a/terraform-python-lsrp/container-apps-hosting.tf +++ /dev/null @@ -1,54 +0,0 @@ -module "azure_container_apps_hosting" { - source = "github.com/DFE-Digital/terraform-azurerm-container-apps-hosting?ref=v2.6.3" - - environment = local.environment - project_name = local.project_name - azure_location = local.azure_location - tags = local.tags - - container_app_environment_internal_load_balancer_enabled = local.container_app_environment_internal_load_balancer_enabled - existing_container_app_environment = local.existing_container_app_environment - container_app_name_override = local.container_app_name_override - container_app_identities = local.container_app_identities - existing_virtual_network = local.existing_virtual_network - container_apps_infra_subnet_cidr = local.container_apps_infra_subnet_cidr - existing_resource_group = local.existing_resource_group - container_apps_allow_ips_inbound = local.container_apps_allow_ips_inbound - restrict_container_apps_to_cdn_inbound_only = false - - 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 - - image_name = local.image_name - container_command = local.container_command - container_secret_environment_variables = local.container_secret_environment_variables - container_scale_http_concurrency = local.container_scale_http_concurrency - 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 - - 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 - existing_network_watcher_name = local.existing_network_watcher_name - existing_network_watcher_resource_group_name = local.existing_network_watcher_resource_group_name - - monitor_http_availability_fqdn = local.monitor_http_availability_fqdn - dns_alias_records = local.dns_alias_records - - enable_monitoring_traces = local.enable_monitoring_traces -} diff --git a/terraform-python-lsrp/key-vault-tfvars-secrets.tf b/terraform-python-lsrp/key-vault-tfvars-secrets.tf deleted file mode 100644 index fd59554..0000000 --- a/terraform-python-lsrp/key-vault-tfvars-secrets.tf +++ /dev/null @@ -1,17 +0,0 @@ -module "azurerm_key_vault" { - source = "github.com/DFE-Digital/terraform-azurerm-key-vault-tfvars?ref=v0.5.2" - - environment = local.environment - project_name = local.project_name - 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-python-lsrp/locals.tf b/terraform-python-lsrp/locals.tf deleted file mode 100644 index 838c108..0000000 --- a/terraform-python-lsrp/locals.tf +++ /dev/null @@ -1,45 +0,0 @@ -locals { - environment = var.environment - project_name = var.project_name - azure_location = var.azure_location - tags = var.tags - container_app_environment_internal_load_balancer_enabled = var.container_app_environment_internal_load_balancer_enabled - existing_container_app_environment = var.existing_container_app_environment - container_app_name_override = var.container_app_name_override - container_app_identities = var.container_app_identities - existing_virtual_network = var.existing_virtual_network - existing_resource_group = var.existing_resource_group - container_apps_infra_subnet_cidr = var.container_apps_infra_subnet_cidr - container_apps_allow_ips_inbound = var.container_apps_allow_ips_inbound - 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 - 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 - 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 - 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_health_probe_path = var.container_health_probe_path - monitor_endpoint_healthcheck = var.monitor_endpoint_healthcheck - existing_logic_app_workflow = var.existing_logic_app_workflow - existing_network_watcher_name = var.existing_network_watcher_name - existing_network_watcher_resource_group_name = var.existing_network_watcher_resource_group_name - 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_fqdn = var.monitor_http_availability_fqdn - dns_alias_records = var.dns_alias_records - enable_monitoring_traces = var.enable_monitoring_traces -} diff --git a/terraform-python-lsrp/providers.tf b/terraform-python-lsrp/providers.tf deleted file mode 100644 index 1f0a7ef..0000000 --- a/terraform-python-lsrp/providers.tf +++ /dev/null @@ -1,13 +0,0 @@ -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 -} diff --git a/terraform-python-lsrp/variables.tf b/terraform-python-lsrp/variables.tf deleted file mode 100644 index 522b991..0000000 --- a/terraform-python-lsrp/variables.tf +++ /dev/null @@ -1,290 +0,0 @@ -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 "container_app_environment_internal_load_balancer_enabled" { - description = "Should the Container Environment operate in Internal Load Balancing Mode?" - type = bool - default = false -} - -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 "container_app_name_override" { - type = string - description = "A custom name for the Container App" - default = "" -} - -variable "container_app_identities" { - description = "Additional User Assigned Managed Identity Resource IDs to attach to the Container App" - type = list(string) - default = [] -} - -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 "container_apps_infra_subnet_cidr" { - description = "Specify a subnet prefix to use for the container_apps_infra subnet" - type = string - default = "172.16.110.32/28" -} - -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_container_registry" { - description = "Set to true to create a container registry" - type = bool -} - -variable "registry_admin_enabled" { - description = "Do you want to enable access key based authentication for your Container Registry?" - type = bool - default = true -} - -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 "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 "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 "existing_network_watcher_name" { - description = "Use an existing network watcher to add flow logs." - type = string -} - -variable "existing_network_watcher_resource_group_name" { - description = "Existing network watcher resource group." - type = string -} - -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 "monitor_http_availability_fqdn" { - description = "Specify a FQDN to monitor for HTTP Availability. Leave unset to dynamically calculate the correct FQDN" - type = 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 "enable_monitoring_traces" { - description = "Monitor App Insights traces for error messages" - type = bool - default = true -} diff --git a/terraform-python-lsrp/versions.tf b/terraform-python-lsrp/versions.tf deleted file mode 100644 index 12b064e..0000000 --- a/terraform-python-lsrp/versions.tf +++ /dev/null @@ -1,15 +0,0 @@ -terraform { - required_version = "~> 1.14" - - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 4.0" - } - - azapi = { - source = "Azure/azapi" - version = "~> 1.13" - } - } -} diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl index d80cdcf..e6bb79b 100644 --- a/terraform/.terraform.lock.hcl +++ b/terraform/.terraform.lock.hcl @@ -5,7 +5,6 @@ provider "registry.terraform.io/azure/azapi" { version = "1.15.0" constraints = "~> 1.13" hashes = [ - "h1:Y7ruMuPh8UJRTRl4rm+cdpGtmURx2taqiuqfYaH3o48=", "h1:pO/phGY+TxMEKQ+ffYj+vUIvG5A1tno/sZYDb/yyA/w=", "zh:0627a8bc77254debc25dc0c7b62e055138217c97b03221e593c3c56dc7550671", "zh:2fe045f07070ef75d0bec4b0595a74c14394daa838ddb964e2fd23cc98c40c34", @@ -43,44 +42,23 @@ provider "registry.terraform.io/hashicorp/archive" { ] } -provider "registry.terraform.io/hashicorp/azuread" { - version = "2.53.1" - constraints = "~> 2.37" - hashes = [ - "h1:0z/718jtR2TJHQQMMqi4nvd6XFPV/iA1jb/5fyAcn5o=", - "h1:EZNO8sEtUABuRxujQrDrW1z1QsG0dq6iLbzWtnG7Om4=", - "zh:162916b037e5133f49298b0ffa3e7dcef7d76530a8ca738e7293373980f73c68", - "zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7", - "zh:492931cea4f30887ab5bca36a8556dfcb897288eddd44619c0217fc5da2d57e7", - "zh:4c895e450e18335ad8714cc6d3488fc1a78816ad2851a91b06cb2ef775dd7c66", - "zh:60d92fdaf7235574201f2d8f68f733ee00a822993b3fc95e6952e09e6ec76999", - "zh:67a169119efa41c1fb867ef1a8e79bf03472a2324384c36eb55370c817dcce42", - "zh:9dd4d5ed9233cf9329262200bc5a1aa60942b80dbc611e2ef4b09f47531b39b1", - "zh:a3c160e35b9e40fc1497b83c2f37a8e24565b05a1783c7733609f3695735c2a9", - "zh:a4a221da42b1f46e7c436c7145e5beaadfd9d03f3be6fd526d132c03f18a5979", - "zh:af0d3476a9702d2287e168e3baa670e64daab9c9b01c01e17025a5248f3e28e9", - "zh:e3579bff7894f3d36066b74ec324be6d28f56a42a387a2b8a0eabf33cbff86df", - "zh:f1749ee8ad972ae6424665aa9d2c0ece8c40c51d41ec2f38b863148cb437e865", - ] -} - provider "registry.terraform.io/hashicorp/azurerm" { - version = "4.76.0" + version = "4.81.0" constraints = "~> 4.0, ~> 4.37" hashes = [ - "h1:4VD01UBYjsa3w7zeEBKnDtwClwpsPw6Dk+V9evhiKqU=", - "zh:07bb3a087abca8bd14cc28e3d3d4abb71e0ed711ecec65e7c0a2f1a97b948cf4", - "zh:0fa6640b5d6c0b0fe0b7fa25cebc0091b7dda2efd83ec0347c5a50dfce0957bc", - "zh:3c8618c8a5ab07fadfcb53ecf614f7b99e25bb6c407cf0af703a6b0647d4461d", - "zh:5f23fdda6ff290bc99b25b68f612bf67fbb503b04b1e38664e66d3204a51e99e", - "zh:68e6794cbe5e3b021657035c2465767b8296beed6c9acc8a9e032c4b90ba5746", + "h1:XhToZua4gtih1Kv8RdStcfND83G4Tmb6GZFT4jEUhDU=", + "zh:0732e7b74264ddfa2b90ba69d01c283d3cbae9f72ed3e506c6ac92529fed7fd3", + "zh:12afb524e232fe4e3d6161927724af5dfa4831d71edd9c174917ca9b7377bfae", + "zh:169d619ae202c4145e02fb706fb7c3679445ab3e3ff722edbf89597517a8c92e", + "zh:6beb95a3ef2f2d9c76abaa48e5450e90686a3fb6a47f1cb0ff7c5e94b6960151", + "zh:705e075fb5ffc4bf66fd7cbabf1a65007a41621e80030a2c158a4c83b6046216", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8a51dad112248d3fdfb19cdd65a182bd6a37e7fb7f1af801ab72a962813b5188", - "zh:945ff59c36de8c2128487f4ae0838655feef7c869112430ffa24ea69ff483b76", - "zh:b7306af0ecc8ad78771c17e0e911dd7a561251e4255ffe80516f0654a53f42bb", - "zh:c584de4858fc4ece330f1986f371acd235a5444e9b14ecea177779b1214539e0", - "zh:daa3675af21f8cdf330532af0b420287388f62ac57eaf0bd4c48e732d1052f35", - "zh:e76d972712b48a689f8deae41a3ad796c31d8b3798074d66c6f68e2b3b0aaa1f", + "zh:79a8d17fefe647040fcb9ee8821a4f09f395427c4fd49493489b9a93a9a1038e", + "zh:8cc3f900b3774c0ae37ae42365c4579a199cf9e5edf88e476fdf5ab1048f84ea", + "zh:dec373b9390fa95e257291acd018ed65a7d512b428645d35e22cdbe8b245a08b", + "zh:e60f1e9fb45df6defade2855ed6e68547409ea75d30655c556adb0c08579749b", + "zh:f901d12ec82f3f8b5880a27b5cbcd7bd0d97e60c9367a2d7ed82fdd1157b39ff", + "zh:facf68ea5bf0f2b8ba720e7fba5f86492e1d4c591100460bb91c3f79f391f4b6", ] } @@ -109,7 +87,6 @@ provider "registry.terraform.io/statuscakedev/statuscake" { version = "2.2.2" constraints = "~> 2.1" hashes = [ - "h1:OoqL/K/eNLahbfMwJvYZHo9kacafjtrJKhd6cLrubZ4=", "h1:nVaJkDBk4sv0yWFzg3p+yeJGzE8mB4KJv3Q6/UgU164=", "zh:0916313344c579d6e05d70f88129a10fe48f7dabe0e61cad17874d6c496f288d", "zh:0d491ff72c2eda6482855033ca2146c5ace1663d07cb3da7253b59ed2e2ec6f4", diff --git a/terraform/README.md b/terraform/README.md index 3a54a7d..db58f6c 100644 --- a/terraform/README.md +++ b/terraform/README.md @@ -127,23 +127,31 @@ If everything looks good, answer `yes` and wait for the new infrastructure to be | [terraform](#requirement\_terraform) | ~> 1.9 | | [azapi](#requirement\_azapi) | ~> 1.13 | | [azurerm](#requirement\_azurerm) | ~> 4.0 | +| [null](#requirement\_null) | ~> 3.2 | | [statuscake](#requirement\_statuscake) | ~> 2.1 | ## Providers -No providers. +| Name | Version | +| ---- | ------- | +| [azurerm](#provider\_azurerm) | 4.81.0 | +| [null](#provider\_null) | 3.3.0 | ## Modules | Name | Source | Version | | ---- | ------ | ------- | | [azure\_container\_apps\_hosting](#module\_azure\_container\_apps\_hosting) | github.com/DFE-Digital/terraform-azurerm-container-apps-hosting | v2.8.1 | -| [azurerm\_key\_vault](#module\_azurerm\_key\_vault) | github.com/DFE-Digital/terraform-azurerm-key-vault-tfvars | v0.5.3 | -| [statuscake-tls-monitor](#module\_statuscake-tls-monitor) | github.com/dfe-digital/terraform-statuscake-tls-monitor | v0.1.5 | ## Resources -No resources. +| Name | Type | +| ---- | ---- | +| [azurerm_storage_account.tfvars](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account) | resource | +| [azurerm_storage_account_network_rules.tfvars](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account_network_rules) | resource | +| [azurerm_storage_blob.tfvars](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_blob) | resource | +| [azurerm_storage_container.tfvars](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_container) | resource | +| [null_resource.tfvars](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | ## Inputs @@ -154,57 +162,44 @@ No resources. | [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\_app\_name\_override](#input\_container\_app\_name\_override) | A custom name for the Container App | `string` | `""` | no | | [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\_apps\_infra\_subnet\_service\_endpoints](#input\_container\_apps\_infra\_subnet\_service\_endpoints) | Endpoints to assign to infra subnet | `list(string)` | `[]` | no | +| [container\_apps\_infra\_subnet\_cidr](#input\_container\_apps\_infra\_subnet\_cidr) | Specify a subnet prefix to use for the container\_apps\_infra subnet | `string` | `"172.16.110.64/28"` | 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 | -| [custom\_container\_apps](#input\_custom\_container\_apps) | Custom container apps, by default deployed within the container app environment managed by this module. |
map(object({
container_app_environment_id = optional(string, "")
resource_group_name = optional(string, "")
revision_mode = optional(string, "Single")
container_port = optional(number, 0)
ingress = optional(object({
external_enabled = optional(bool, true)
target_port = optional(number, null)
traffic_weight = object({
percentage = optional(number, 100)
})
cdn_frontdoor_custom_domain = optional(string, "")
cdn_frontdoor_origin_fqdn_override = optional(string, "")
cdn_frontdoor_origin_host_header_override = optional(string, "")
enable_cdn_frontdoor_health_probe = optional(bool, false)
cdn_frontdoor_health_probe_protocol = optional(string, "")
cdn_frontdoor_health_probe_interval = optional(number, 120)
cdn_frontdoor_health_probe_request_type = optional(string, "")
cdn_frontdoor_health_probe_path = optional(string, "")
cdn_frontdoor_forwarding_protocol_override = optional(string, "")
}), null)
identity = optional(list(object({
type = string
identity_ids = list(string)
})), [])
secrets = optional(list(object({
name = string
value = string
})), [])
registry = optional(object({
server = optional(string, "")
username = optional(string, "")
password_secret_name = optional(string, "")
identity = optional(string, "")
}), null),
image = string
cpu = number
memory = number
command = list(string)
liveness_probes = optional(list(object({
interval_seconds = number
transport = string
port = number
path = optional(string, null)
})), [])
env = optional(list(object({
name = string
value = optional(string, null)
secretRef = optional(string, null)
})), [])
min_replicas = number
max_replicas = number
}))
| `{}` | no | -| [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` | n/a | yes | -| [enable\_dns\_zone](#input\_enable\_dns\_zone) | Conditionally create a DNS zone | `bool` | n/a | yes | +| [enable\_container\_registry](#input\_enable\_container\_registry) | Set to true to create a container registry | `bool` | `false` | no | | [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\_init\_container](#input\_enable\_init\_container) | Deploy an Init Container. Init containers run before the primary app container and are used to perform initialization tasks such as downloading data or preparing the environment | `bool` | `false` | no | -| [enable\_keyvault\_private\_endpoint](#input\_enable\_keyvault\_private\_endpoint) | Set to true to create a private endpoint for key vault. | `bool` | n/a | yes | | [enable\_monitoring](#input\_enable\_monitoring) | Create an App Insights instance and notification group for the Container App | `bool` | n/a | yes | | [enable\_monitoring\_traces](#input\_enable\_monitoring\_traces) | Monitor App Insights traces for error messages | `bool` | `true` | no | -| [enable\_redis\_cache](#input\_enable\_redis\_cache) | Set to true to create an Azure Redis Cache, with a private endpoint within the virtual network | `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\_network\_watcher\_name](#input\_existing\_network\_watcher\_name) | Use an existing network watcher to add flow logs. | `string` | n/a | yes | | [existing\_network\_watcher\_resource\_group\_name](#input\_existing\_network\_watcher\_resource\_group\_name) | Existing network watcher resource group. | `string` | n/a | yes | +| [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 | | [init\_container\_command](#input\_init\_container\_command) | Container command for the Init Container | `list(any)` | `[]` | no | | [init\_container\_image](#input\_init\_container\_image) | Image name for the Init Container. Leave blank to use the same Container image from the primary app | `string` | `""` | no | -| [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 | -| [linux\_function\_apps](#input\_linux\_function\_apps) | Linux function apps |
map(object({
runtime = string
runtime_version = string
app_settings = optional(map(string), {})
allowed_origins = optional(list(string), ["*"])
ftp_publish_basic_authentication_enabled = optional(bool, false)
webdeploy_publish_basic_authentication_enabled = optional(bool, false)
ipv4_access = optional(list(string), [])
minimum_tls_version = optional(string, "1.3")
enable_service_bus = optional(bool, false)
service_bus_additional_subscriptions = optional(list(string), [])
connection_strings = optional(map(object({
type = string
value = 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 | | [project\_name](#input\_project\_name) | Project name. Will be used along with `environment` as a prefix for all resources. | `string` | n/a | yes | -| [redis\_cache\_sku](#input\_redis\_cache\_sku) | Redis Cache SKU | `string` | `"Basic"` | no | -| [redis\_cache\_subnet\_cidr](#input\_redis\_cache\_subnet\_cidr) | Redis Cache subnet CIDR | `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` | `true` | no | +| [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 | +| [restrict\_container\_apps\_to\_cdn\_inbound\_only](#input\_restrict\_container\_apps\_to\_cdn\_inbound\_only) | Restricts access to the Container Apps by creating a network security group rule that only allows 'AzureFrontDoor.Backend' inbound, and attaches it to the subnet of the container app environment. | `bool` | `false` | no | | [tags](#input\_tags) | Tags to be applied to all resources | `map(string)` | n/a | yes | +| [tfvars\_access\_ipv4](#input\_tfvars\_access\_ipv4) | List of IPv4 Addresses that are permitted to access the tfvars storage | `list(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 | -| [virtual\_network\_address\_space](#input\_virtual\_network\_address\_space) | Virtual network address space CIDR | `string` | n/a | yes | ## Outputs diff --git a/terraform/backend.vars.example b/terraform/backend.vars.example deleted file mode 100644 index 0e83b76..0000000 --- a/terraform/backend.vars.example +++ /dev/null @@ -1,8 +0,0 @@ -resource_group_name = "s184d01-rsd-tfstate" -storage_account_name = "s184d01rsdstate" -container_name = "s184d01-eatwebtf" -key = "terraform.tstate" -subscription_id = "" -client_id = "" -client_secret = "" -tenant_id = "" diff --git a/terraform/container-apps-hosting.tf b/terraform/container-apps-hosting.tf index 4261baa..22dfe16 100644 --- a/terraform/container-apps-hosting.tf +++ b/terraform/container-apps-hosting.tf @@ -6,20 +6,11 @@ module "azure_container_apps_hosting" { azure_location = local.azure_location tags = local.tags - virtual_network_address_space = local.virtual_network_address_space - container_apps_infra_subnet_service_endpoints = local.container_apps_infra_subnet_service_endpoints - enable_container_registry = local.enable_container_registry - registry_admin_enabled = local.registry_admin_enabled + registry_server = local.registry_server 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 + registry_admin_enabled = local.registry_admin_enabled image_name = local.image_name container_command = local.container_command @@ -28,32 +19,31 @@ module "azure_container_apps_hosting" { 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 - enable_redis_cache = local.enable_redis_cache - redis_cache_sku = local.redis_cache_sku - redis_cache_subnet_cidr = local.redis_cache_subnet_cidr - - linux_function_apps = local.linux_function_apps - - 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 + 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 + container_apps_infra_subnet_cidr = local.container_apps_infra_subnet_cidr + existing_resource_group = local.existing_resource_group + launch_in_vnet = true + container_app_name_override = local.container_app_name_override + + 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 + monitor_http_availability_fqdn = local.monitor_http_availability_fqdn + enable_monitoring_traces = local.enable_monitoring_traces existing_logic_app_workflow = local.existing_logic_app_workflow existing_network_watcher_name = local.existing_network_watcher_name existing_network_watcher_resource_group_name = local.existing_network_watcher_resource_group_name + restrict_container_apps_to_cdn_inbound_only = local.restrict_container_apps_to_cdn_inbound_only - custom_container_apps = local.custom_container_apps enable_init_container = local.enable_init_container init_container_image = local.init_container_image init_container_command = local.init_container_command - - monitor_http_availability_fqdn = local.monitor_http_availability_fqdn - dns_alias_records = local.dns_alias_records - - enable_monitoring_traces = local.enable_monitoring_traces } diff --git a/terraform/key-vault-tfvars-secrets.tf b/terraform/key-vault-tfvars-secrets.tf deleted file mode 100644 index 72d69ba..0000000 --- a/terraform/key-vault-tfvars-secrets.tf +++ /dev/null @@ -1,19 +0,0 @@ -module "azurerm_key_vault" { - source = "github.com/DFE-Digital/terraform-azurerm-key-vault-tfvars?ref=v0.5.3" - - environment = local.environment - project_name = local.project_name - existing_resource_group = module.azure_container_apps_hosting.azurerm_resource_group_default.name - 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 - enable_private_endpoint = local.enable_keyvault_private_endpoint - virtual_network_id = local.enable_keyvault_private_endpoint ? module.azure_container_apps_hosting.azurerm_virtual_network.id : "" - virtual_network_name = local.enable_keyvault_private_endpoint ? module.azure_container_apps_hosting.azurerm_virtual_network.name : "" - key_vault_subnet_cidr = local.enable_keyvault_private_endpoint ? local.key_vault_subnet_cidr : "" - 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 -} diff --git a/terraform/locals.tf b/terraform/locals.tf index 2d0e392..78dbe60 100644 --- a/terraform/locals.tf +++ b/terraform/locals.tf @@ -1,55 +1,44 @@ locals { - environment = var.environment - project_name = var.project_name - azure_location = var.azure_location - tags = var.tags - virtual_network_address_space = var.virtual_network_address_space - virtual_network_address_space_mask = element(split("/", local.virtual_network_address_space), 1) - key_vault_subnet_cidr = cidrsubnet(local.virtual_network_address_space, 21 - local.virtual_network_address_space_mask, 2) - container_apps_infra_subnet_service_endpoints = var.container_apps_infra_subnet_service_endpoints - 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 - 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 - 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 - key_vault_access_ipv4 = var.key_vault_access_ipv4 - enable_keyvault_private_endpoint = var.enable_keyvault_private_endpoint - 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 - enable_redis_cache = var.enable_redis_cache - redis_cache_sku = var.redis_cache_sku - redis_cache_subnet_cidr = var.redis_cache_subnet_cidr - linux_function_apps = var.linux_function_apps - monitor_endpoint_healthcheck = var.monitor_endpoint_healthcheck - existing_logic_app_workflow = var.existing_logic_app_workflow - existing_network_watcher_name = var.existing_network_watcher_name - existing_network_watcher_resource_group_name = var.existing_network_watcher_resource_group_name - 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 - custom_container_apps = var.custom_container_apps - 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 - enable_init_container = var.enable_init_container - init_container_image = var.init_container_image - init_container_command = var.init_container_command - monitor_http_availability_fqdn = var.monitor_http_availability_fqdn - dns_alias_records = var.dns_alias_records - enable_monitoring_traces = var.enable_monitoring_traces + environment = var.environment + project_name = var.project_name + azure_location = var.azure_location + tags = var.tags + enable_container_registry = var.enable_container_registry + registry_server = var.registry_server + registry_use_managed_identity = var.registry_use_managed_identity + registry_managed_identity_assign_role = var.registry_managed_identity_assign_role + registry_admin_enabled = var.registry_admin_enabled + image_name = var.image_name + 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 + tfvars_access_ipv4 = var.tfvars_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 + existing_network_watcher_name = var.existing_network_watcher_name + existing_network_watcher_resource_group_name = var.existing_network_watcher_resource_group_name + 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 + enable_init_container = var.enable_init_container + init_container_image = var.init_container_image + init_container_command = var.init_container_command + monitor_http_availability_fqdn = var.monitor_http_availability_fqdn + enable_monitoring_traces = var.enable_monitoring_traces + existing_container_app_environment = var.existing_container_app_environment + existing_virtual_network = var.existing_virtual_network + existing_resource_group = var.existing_resource_group + container_app_name_override = var.container_app_name_override + restrict_container_apps_to_cdn_inbound_only = var.restrict_container_apps_to_cdn_inbound_only + container_apps_infra_subnet_cidr = var.container_apps_infra_subnet_cidr + + is_windows = can(regex("^[A-Za-z]:", abspath(path.root))) + bash = local.is_windows ? "C:/Program Files/Git/bin/bash.exe" : "/bin/bash" } diff --git a/terraform/providers.tf b/terraform/providers.tf index 1f88c3e..1f0a7ef 100644 --- a/terraform/providers.tf +++ b/terraform/providers.tf @@ -11,7 +11,3 @@ provider "azurerm" { provider "azapi" { enable_hcl_output_for_data_source = true } - -provider "statuscake" { - api_token = var.statuscake_api_token -} diff --git a/terraform/scripts/check-tfvars-against-remote.sh b/terraform/scripts/check-tfvars-against-remote.sh new file mode 100755 index 0000000..76ff68f --- /dev/null +++ b/terraform/scripts/check-tfvars-against-remote.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# exit on failures +set -e +set -o pipefail + +usage() { + echo "Usage: $(basename "$0") [OPTIONS]" 1>&2 + echo " -h - help" + echo " -a - Azure Storage Account name" + echo " -c - Azure Storage Container name" + echo " -f - Name of the tfvars file with file extension" + exit 1 +} + +# if there are not arguments passed exit with usage +if [ $# -eq 0 ] +then + usage +fi + +while getopts "a:c:f:h" opt; do + case $opt in + a) + STORAGE_ACCOUNT_NAME=$OPTARG + ;; + c) + STORAGE_CONTAINER_NAME=$OPTARG + ;; + f) + TFVARS_FILE_NAME=$OPTARG + ;; + h) + usage + ;; + *) + usage + ;; + esac +done + +if [[ + -z "$STORAGE_ACCOUNT_NAME" || + -z "$STORAGE_CONTAINER_NAME" || + -z "$TFVARS_FILE_NAME" +]] +then + usage +fi + +set +e +STORAGE_CHECK=$(az storage blob list --account-name "$STORAGE_ACCOUNT_NAME" --container-name "$STORAGE_CONTAINER_NAME" 2>&1) +set -e + +if ! jq -r >/dev/null 2>&1 <<< "$STORAGE_CHECK" +then + exit 0 +fi + +LAST_UPDATED=$(jq -r \ + --arg name "$TFVARS_FILE_NAME" \ + '.[] | select(.name==$name) | .properties.lastModified' \ + <<< "$STORAGE_CHECK") + +if [ -z "$LAST_UPDATED" ] +then + exit 0 +fi + +LAST_UPDATED=$(echo "$LAST_UPDATED" | cut -d'+' -f1) +LAST_UPDATED_SECONDS=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$LAST_UPDATED" "+%s") + +if [ "$LAST_UPDATED_SECONDS" -gt "$(date -r "$TFVARS_FILE_NAME" +%s)" ] +then + echo "" + echo "" + echo "Error: Your local tfvars file is older than the remote!" + echo "" + echo "Ensure you have the latest tfvars by running:" + echo "" + echo " mv $TFVARS_FILE_NAME $TFVARS_FILE_NAME.old" + echo " az storage blob download \\" + echo " --file $TFVARS_FILE_NAME \\" + echo " --container-name $STORAGE_CONTAINER_NAME \\" + echo " --account-name $STORAGE_ACCOUNT_NAME \\" + echo " --name $TFVARS_FILE_NAME" + echo "" + echo "Or if you are sure your local tfvars are correct, just update the modified time by running:" + echo "" + echo " touch $TFVARS_FILE_NAME" + echo "" + exit 1 +fi diff --git a/terraform/statuscake-tls-monitor.tf b/terraform/statuscake-tls-monitor.tf deleted file mode 100644 index 40d836d..0000000 --- a/terraform/statuscake-tls-monitor.tf +++ /dev/null @@ -1,11 +0,0 @@ -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/tfvars-storage.tf b/terraform/tfvars-storage.tf new file mode 100644 index 0000000..4b9c92a --- /dev/null +++ b/terraform/tfvars-storage.tf @@ -0,0 +1,47 @@ +resource "azurerm_storage_account" "tfvars" { + name = "${replace("${local.environment}${local.project_name}", "-", "")}tfvar" + resource_group_name = local.existing_resource_group + location = local.azure_location + account_tier = "Standard" + account_replication_type = "LRS" + min_tls_version = "TLS1_2" + https_traffic_only_enabled = true + public_network_access_enabled = true + + tags = local.tags +} + +resource "azurerm_storage_container" "tfvars" { + name = "${local.environment}${local.project_name}-tfvar" + storage_account_name = azurerm_storage_account.tfvars.name + container_access_type = "private" +} + +resource "azurerm_storage_blob" "tfvars" { + name = local.tfvars_filename + storage_account_name = azurerm_storage_account.tfvars.name + storage_container_name = azurerm_storage_container.tfvars.name + type = "Block" + source = local.tfvars_filename + content_md5 = filemd5(local.tfvars_filename) + access_tier = "Cool" +} + +resource "azurerm_storage_account_network_rules" "tfvars" { + storage_account_id = azurerm_storage_account.tfvars.id + default_action = length(local.tfvars_access_ipv4) > 0 ? "Deny" : "Allow" + bypass = [] + virtual_network_subnet_ids = [] + ip_rules = local.tfvars_access_ipv4 +} + +resource "null_resource" "tfvars" { + provisioner "local-exec" { + interpreter = [local.bash, "-c"] + command = "./scripts/check-tfvars-against-remote.sh -c \"${azurerm_storage_container.tfvars.name}\" -a \"${azurerm_storage_account.tfvars.name}\" -f \"${local.tfvars_filename}\"" + } + + triggers = { + tfvar_file_md5 = filemd5(local.tfvars_filename) + } +} diff --git a/terraform/variables.tf b/terraform/variables.tf index 8a0eaba..73926a1 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -24,16 +24,11 @@ variable "environment" { type = string } -variable "key_vault_access_ipv4" { - description = "List of IPv4 Addresses that are permitted to access the Key Vault" +variable "tfvars_access_ipv4" { + description = "List of IPv4 Addresses that are permitted to access the tfvars storage" type = list(string) } -variable "enable_keyvault_private_endpoint" { - description = "Set to true to create a private endpoint for key vault." - type = bool -} - 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 @@ -54,26 +49,16 @@ variable "tags" { type = map(string) } -variable "virtual_network_address_space" { - description = "Virtual network address space CIDR" +variable "container_apps_infra_subnet_cidr" { + description = "Specify a subnet prefix to use for the container_apps_infra subnet" type = string -} - -variable "container_apps_infra_subnet_service_endpoints" { - description = "Endpoints to assign to infra subnet" - type = list(string) - default = [] + default = "172.16.110.64/28" } variable "enable_container_registry" { description = "Set to true to create a container registry" type = bool -} - -variable "registry_admin_enabled" { - description = "Do you want to enable access key based authentication for your Container Registry?" - type = bool - default = true + default = false } variable "registry_server" { @@ -94,6 +79,12 @@ variable "registry_managed_identity_assign_role" { 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 "image_name" { description = "Image name" type = string @@ -116,52 +107,6 @@ variable "container_scale_http_concurrency" { 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 "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) @@ -210,95 +155,6 @@ variable "existing_network_watcher_resource_group_name" { type = string } -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 "custom_container_apps" { - description = "Custom container apps, by default deployed within the container app environment managed by this module." - type = map(object({ - container_app_environment_id = optional(string, "") - resource_group_name = optional(string, "") - revision_mode = optional(string, "Single") - container_port = optional(number, 0) - ingress = optional(object({ - external_enabled = optional(bool, true) - target_port = optional(number, null) - traffic_weight = object({ - percentage = optional(number, 100) - }) - cdn_frontdoor_custom_domain = optional(string, "") - cdn_frontdoor_origin_fqdn_override = optional(string, "") - cdn_frontdoor_origin_host_header_override = optional(string, "") - enable_cdn_frontdoor_health_probe = optional(bool, false) - cdn_frontdoor_health_probe_protocol = optional(string, "") - cdn_frontdoor_health_probe_interval = optional(number, 120) - cdn_frontdoor_health_probe_request_type = optional(string, "") - cdn_frontdoor_health_probe_path = optional(string, "") - cdn_frontdoor_forwarding_protocol_override = optional(string, "") - }), null) - identity = optional(list(object({ - type = string - identity_ids = list(string) - })), []) - secrets = optional(list(object({ - name = string - value = string - })), []) - registry = optional(object({ - server = optional(string, "") - username = optional(string, "") - password_secret_name = optional(string, "") - identity = optional(string, "") - }), null), - image = string - cpu = number - memory = number - command = list(string) - liveness_probes = optional(list(object({ - interval_seconds = number - transport = string - port = number - path = optional(string, null) - })), []) - env = optional(list(object({ - name = string - value = optional(string, null) - secretRef = optional(string, null) - })), []) - min_replicas = number - max_replicas = number - })) - default = {} -} - variable "container_min_replicas" { description = "Container min replicas" type = number @@ -353,55 +209,38 @@ variable "monitor_http_availability_fqdn" { 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 "enable_monitoring_traces" { description = "Monitor App Insights traces for error messages" type = bool default = true } -variable "enable_redis_cache" { - description = "Set to true to create an Azure Redis Cache, with a private endpoint within the virtual network" - type = bool +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 "redis_cache_sku" { - description = "Redis Cache SKU" +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 - default = "Basic" } -variable "redis_cache_subnet_cidr" { - description = "Redis Cache subnet CIDR" +variable "existing_resource_group" { + description = "Conditionally launch resources into an existing resource group. Specifying this will NOT create a resource group." type = string } -variable "linux_function_apps" { - description = "Linux function apps" - type = map(object({ - runtime = string - runtime_version = string - app_settings = optional(map(string), {}) - allowed_origins = optional(list(string), ["*"]) - ftp_publish_basic_authentication_enabled = optional(bool, false) - webdeploy_publish_basic_authentication_enabled = optional(bool, false) - ipv4_access = optional(list(string), []) - minimum_tls_version = optional(string, "1.3") - enable_service_bus = optional(bool, false) - service_bus_additional_subscriptions = optional(list(string), []) - connection_strings = optional(map(object({ - type = string - value = string - })), {}) - })) +variable "container_app_name_override" { + type = string + description = "A custom name for the Container App" + default = "" +} + +variable "restrict_container_apps_to_cdn_inbound_only" { + description = "Restricts access to the Container Apps by creating a network security group rule that only allows 'AzureFrontDoor.Backend' inbound, and attaches it to the subnet of the container app environment." + type = bool + default = false } diff --git a/terraform/versions.tf b/terraform/versions.tf index 73673e9..7fb1275 100644 --- a/terraform/versions.tf +++ b/terraform/versions.tf @@ -16,5 +16,10 @@ terraform { source = "Azure/azapi" version = "~> 1.13" } + + null = { + source = "hashicorp/null" + version = "~> 3.2" + } } }