diff --git a/docs/CONFIG-VARS.md b/docs/CONFIG-VARS.md index 45236bd4..e77c4196 100644 --- a/docs/CONFIG-VARS.md +++ b/docs/CONFIG-VARS.md @@ -391,22 +391,7 @@ postgres_servers = { ## Azure Application Gateway with Azure Web Application Firewall (WAF) -Azure Web Application Firewall (WAF) on Azure Application Gateway provides centralized protection of your web applications from common exploits and vulnerabilities. To enable Azure Application Gateway with WAF you need to provide all the required variables as discussed below: - -The variable has the following format: -``` -create_app_gateway = true -app_gateway_config = { - backend_trusted_root_certificate = "" ## .cer format required - ssl_certificate = [{ - data = "" ## .pfx format required - password = "" - }] - backend_address_pool_fqdn = [] -} - -waf_policy = "" ## .json format required -``` +Azure Web Application Firewall (WAF) on Azure Application Gateway provides centralized protection from common exploits and vulnerabilities. Please see the [sample input file](../examples/sample-input-app-gateway.tfvars) for Application Gateway creation example. | Name | Description | Type | Default | Notes | | :--- | :--- | :--- | :--- | :--- | @@ -415,25 +400,27 @@ waf_policy = "" ## .json format required | waf_policy | A JSON file with all the WAF_Policy rules | map | null | The WAF policy has few required components see the details below. | The `app_gateway_config` variable can contain none, some, or all of the parameters listed below: +For the details of all the parameters that can be specified see: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/application_gateway + | Name | Description | Type | Required | Default | Notes | | :--- | :--- | :--- | :--- | :--- | :--- | | sku | The Name of the SKU to use for this Application Gateway. | string | false | "Standard_v2" | If WAF policy is enabled the default is `"WAF_v2"` | | port | The port which should be used for this Application Gateway. | string | false | "443" | | | protocol | The Protocol which should be used. | string | false | "Https" | Possible values are Http and Https.| -| backend_host_name | FQDN for the Gateway | string | False | null |Set this variable when using custom DNS. Not setting this will use Azure Public DNS to set the FQDN for Application Gateway Public IP.| -| backend_trusted_root_certificate | The Trusted Root Certificate to use. | string | True | null | | -| ssl_certificate |The associated SSL Certificate which should be used for this HTTP Listener. | map | True | null |List of data, password or key_vault_secret_id| -| identity_ids | Specifies a list of User Assigned Managed Identity IDs to be assigned to this Application Gateway. | list | False | null | Required when specifying key_vault_secret_id | -| backend_address_pool_fqdn | A list of FQDN's which should be part of the Backend Address Pool. | list | True | null |Add the FQDN of your Ingress-Nginx. Note: You can specify the anticipated FQDN of your ingress without affecting the Gateway creation. This can also be manually updated later in Portal| -| probe | Custom health probes to be created for the Application Gateway. | map | False | "default-probe" || +| backend_host_name | Hostname for the Application Gateway | string | false | null |Set this variable when using custom DNS. Not setting this will use Azure Public DNS to set the FQDN for Application Gateway Public IP.| +| backend_trusted_root_certificate | The Trusted Root Certificate to use. | list(map(string)) | true | null | List of map containing: name, data, or key_vault_secret_id. `key_vault_secret_id` is required if `data` is not set. | +| ssl_certificate |The associated SSL Certificate which should be used for this HTTP Listener. | list(map(string)) | true | null | List of map containing: name, data, password or key_vault_secret_id. `key_vault_secret_id` is required if `data` is not set.| +| identity_ids | Specifies a list of User Assigned Managed Identity IDs to be assigned to this Application Gateway. | list | false | null | Required when specifying key_vault_secret_id | +| backend_address_pool_fqdn | A list of FQDN's which should be part of the Backend Address Pool. | list | true | null | Add the FQDN of your Ingress-Nginx. Note: You can specify the anticipated FQDN of your ingress without affecting the Gateway creation. This can also be manually updated later in Portal| +| probe | Custom health probes to be created for the Application Gateway. | map | false | "default-probe" || The `waf_policy` variable is json file which can contain none, some, or all of the parameters listed below: For the details of all the parameters that can be specified see: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/web_application_firewall_policy | Name | Description | Type | Required | Default | Notes | | :--- | :--- | :--- | :--- | :--- | :--- | -| custom_rules | Specifies one or more custom_rules blocks | list(map) | False | | | -| policy_settings | Specifies A policy_settings block | map | False | | | -| managed_rules | A managed_rules blocks | list(map) | True | | | +| custom_rules | Specifies one or more custom_rules blocks | list(map) | false | | | +| policy_settings | Specifies A policy_settings block | map | false | | | +| managed_rules | A managed_rules blocks | list(map) | true | | | Example WAF Policy: ``` @@ -498,4 +485,4 @@ Example WAF Policy: ] } } -``` \ No newline at end of file +``` diff --git a/examples/sample-input-app-gateway.tfvars b/examples/sample-input-app-gateway.tfvars new file mode 100644 index 00000000..9b74a2c3 --- /dev/null +++ b/examples/sample-input-app-gateway.tfvars @@ -0,0 +1,120 @@ +# !NOTE! - These are only a subset of CONFIG-VARS.md provided as examples. +# Customize this file to add any variables from 'CONFIG-VARS.md' whose default values you +# want to change. + +# **************** REQUIRED VARIABLES **************** +# These required variables' values MUST be provided by the User +prefix = "" # this is a prefix that you assign for the resources to be created +location = "" # e.g., "eastus2" +# **************** REQUIRED VARIABLES **************** + +# !NOTE! - Without specifying your CIDR block access rules, ingress traffic +# to your cluster will be blocked by default. In a SCIM environment, +# the AzureActiveDirectory service tag must be granted access to port +# 443/HTTPS for the ingress IP address. + +# ************** RECOMMENDED VARIABLES *************** +default_public_access_cidrs = [] # e.g., ["123.45.6.89/32"] +ssh_public_key = "~/.ssh/id_rsa.pub" +# ************** RECOMMENDED VARIABLES *************** + +# Tags can be specified matching your tagging strategy. +tags = {} # for example: { "owner|email" = "@.", "key1" = "value1", "key2" = "value2" } + +# Postgres config - By having this entry a database server is created. If you do not +# need an external database server remove the 'postgres_servers' +# block below. +postgres_servers = { + default = {}, +} + +## Azure Application Gateway with Azure Web Application Firewall (WAF) +create_app_gateway = true + +app_gateway_config = { + backend_host_name = "" ## leave empty to use Azure public DNS assigned host name + backend_trusted_root_certificate = [{ + name = "" + data = "" ## Required if key_vault_secret_id not set + key_vault_secret_id = "" ## Required if data not set + }] + ssl_certificate = [{ + name = "" + data = "" ## Required if key_vault_secret_id not set + password = "" ## Required when data is set + key_vault_secret_id = "" ## Required if data not set + }] + identity_ids = [""] ## Required if key_vault_secret_id is set above. + ## Example identity_ids value: `/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/userAssignedIdentityValue` + backend_address_pool_fqdn = [""] ## Required to setup the backend pool. This list only accepts FQDN. +} + +waf_policy = "" ## Required to configure WAF with Application Gateway + +# AKS config +kubernetes_version = "1.26" +default_nodepool_min_nodes = 2 +default_nodepool_vm_type = "Standard_D8s_v4" + +# AKS Node Pools config +node_pools = { + cas = { + "machine_type" = "Standard_E16s_v3" + "os_disk_size" = 200 + "min_nodes" = 1 + "max_nodes" = 1 + "max_pods" = 110 + "node_taints" = ["workload.sas.com/class=cas:NoSchedule"] + "node_labels" = { + "workload.sas.com/class" = "cas" + } + }, + compute = { + "machine_type" = "Standard_E16s_v3" + "os_disk_size" = 200 + "min_nodes" = 1 + "max_nodes" = 1 + "max_pods" = 110 + "node_taints" = ["workload.sas.com/class=compute:NoSchedule"] + "node_labels" = { + "workload.sas.com/class" = "compute" + "launcher.sas.com/prepullImage" = "sas-programming-environment" + } + }, + stateless = { + "machine_type" = "Standard_D16s_v3" + "os_disk_size" = 200 + "min_nodes" = 1 + "max_nodes" = 2 + "max_pods" = 110 + "node_taints" = ["workload.sas.com/class=stateless:NoSchedule"] + "node_labels" = { + "workload.sas.com/class" = "stateless" + } + }, + stateful = { + "machine_type" = "Standard_D8s_v3" + "os_disk_size" = 200 + "min_nodes" = 1 + "max_nodes" = 3 + "max_pods" = 110 + "node_taints" = ["workload.sas.com/class=stateful:NoSchedule"] + "node_labels" = { + "workload.sas.com/class" = "stateful" + } + } +} + +# Jump Server +create_jump_public_ip = true +jump_vm_admin = "jumpuser" +jump_vm_machine_type = "Standard_B2s" + +# Storage for SAS Viya CAS/Compute +storage_type = "standard" +# required ONLY when storage_type is "standard" to create NFS Server VM +create_nfs_public_ip = false +nfs_vm_admin = "nfsuser" +nfs_vm_machine_type = "Standard_D8s_v4" +nfs_raid_disk_size = 128 +nfs_raid_disk_type = "Standard_LRS" diff --git a/modules/azurerm_app_gateway/main.tf b/modules/azurerm_app_gateway/main.tf index ee939e3d..0831e89c 100644 --- a/modules/azurerm_app_gateway/main.tf +++ b/modules/azurerm_app_gateway/main.tf @@ -149,11 +149,12 @@ resource "azurerm_application_gateway" "appgateway" { } dynamic "trusted_root_certificate" { - for_each = var.backend_trusted_root_certificate == null ? [] : [1] + for_each = var.backend_trusted_root_certificate == null ? [] : var.backend_trusted_root_certificate content { - name = "root-cert" - data = filebase64(var.backend_trusted_root_certificate) + name = try(trusted_root_certificate.value.name, null) + data = try(trusted_root_certificate.value.data, null) != null ? filebase64(trusted_root_certificate.value.data) : null + key_vault_secret_id = try(trusted_root_certificate.value.data, null) != null ? null : trusted_root_certificate.value.key_vault_secret_id } } @@ -161,10 +162,19 @@ resource "azurerm_application_gateway" "appgateway" { for_each = var.ssl_certificate == null ? [] : var.ssl_certificate content { - name = "ListenerCert" - data = ssl_certificate.value.data != null ? filebase64(ssl_certificate.value.data) : null - password = ssl_certificate.value.password - key_vault_secret_id = ssl_certificate.value.data != null ? null : ssl_certificate.value.key_vault_secret_id + name = try(ssl_certificate.value.name, null) + data = try(ssl_certificate.value.data, null) != null ? filebase64(ssl_certificate.value.data) : null + password = try(ssl_certificate.value.password, null) + key_vault_secret_id = try(ssl_certificate.value.data, null) != null ? null : ssl_certificate.value.key_vault_secret_id + } + } + + dynamic "identity" { + for_each = var.identity_ids == null ? [] : [1] + + content { + type = "UserAssigned" + identity_ids = var.identity_ids } } @@ -174,9 +184,9 @@ resource "azurerm_application_gateway" "appgateway" { port = var.port protocol = var.protocol request_timeout = 60 - probe_name = var.probe != null ? "default-probe" : null + probe_name = var.probe != null ? try(var.probe[0].name, "default-probe") : null host_name = var.backend_host_name == null ? azurerm_public_ip.gateway_ip.fqdn : var.backend_host_name - trusted_root_certificate_names = var.backend_trusted_root_certificate == null ? null : ["root-cert"] + trusted_root_certificate_names = var.backend_trusted_root_certificate == null ? null : [var.backend_trusted_root_certificate[0].name] } http_listener { @@ -184,7 +194,7 @@ resource "azurerm_application_gateway" "appgateway" { frontend_ip_configuration_name = local.frontend_ip_configuration_name frontend_port_name = local.frontend_port_name protocol = var.protocol - ssl_certificate_name = var.ssl_certificate == null ? null : "ListenerCert" + ssl_certificate_name = var.ssl_certificate == null ? null : var.ssl_certificate[0].name } request_routing_rule { diff --git a/modules/azurerm_app_gateway/variables.tf b/modules/azurerm_app_gateway/variables.tf index 0c03e2c9..0d617ac4 100644 --- a/modules/azurerm_app_gateway/variables.tf +++ b/modules/azurerm_app_gateway/variables.tf @@ -49,7 +49,7 @@ variable "backend_host_name" { variable "backend_trusted_root_certificate" { description = "The Trusted Root Certificate to use." - type = string + type = any default = null } diff --git a/variables.tf b/variables.tf index a597511c..a8142a6f 100644 --- a/variables.tf +++ b/variables.tf @@ -821,13 +821,9 @@ variable "app_gateway_defaults" { protocol = "Https" backend_host_name = null backend_trusted_root_certificate = null - ssl_certificate = [{ - data = null - password = null - key_vault_secret_id = null - }] - identity_ids = [] - backend_address_pool_fqdn = [] + ssl_certificate = null + identity_ids = [] + backend_address_pool_fqdn = [] probe = [{ name = "default-probe" path = "/SASLogon/apiMeta"