diff --git a/.deepsource.toml b/.deepsource.toml new file mode 100644 index 0000000..18b001a --- /dev/null +++ b/.deepsource.toml @@ -0,0 +1,4 @@ +version = 1 + +[[analyzers]] +name = "terraform" \ No newline at end of file diff --git a/.github/workflows/auto_assignee.yml b/.github/workflows/auto_assignee.yml new file mode 100644 index 0000000..2e6fff2 --- /dev/null +++ b/.github/workflows/auto_assignee.yml @@ -0,0 +1,14 @@ +name: Auto Assign PRs + +on: + pull_request: + types: [opened, reopened] + + workflow_dispatch: +jobs: + assignee: + uses: clouddrove/github-shared-workflows/.github/workflows/auto_assignee.yml@1.2.8 + secrets: + GITHUB: ${{ secrets.GITHUB }} + with: + assignees: 'clouddrove-ci' \ No newline at end of file diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 0000000..fc495a0 --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,12 @@ +--- +name: Auto merge +on: + pull_request: +jobs: + auto-merge: + uses: clouddrove/github-shared-workflows/.github/workflows/auto_merge.yml@1.2.8 + secrets: + GITHUB: ${{ secrets.GITHUB }} + with: + tfcheck: 'basic-example / Check code format' +... \ No newline at end of file diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 8d61c56..4a58255 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -6,7 +6,8 @@ on: - "*" workflow_dispatch: jobs: - call-workflow-changelog: - uses: clouddrove/github-shared-workflows/.github/workflows/changelog.yml@master + changelog: + uses: clouddrove/github-shared-workflows/.github/workflows/changelog.yml@1.2.8 + secrets: inherit with: branch: 'master' diff --git a/.github/workflows/readme.yml b/.github/workflows/readme.yml index 8b60bee..c4a5793 100644 --- a/.github/workflows/readme.yml +++ b/.github/workflows/readme.yml @@ -1,54 +1,15 @@ -name: 'Create README.md file' +name: Readme Workflow on: push: branches: - master - + paths-ignore: + - 'README.md' + - 'docs/**' + workflow_dispatch: jobs: - readme-create: - name: 'readme-create' - runs-on: ubuntu-latest - steps: - - name: 'Checkout' - uses: actions/checkout@master - - - name: 'Set up Python 3.7' - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - - name: 'create readme' - uses: 'clouddrove/github-actions@v9.0.2' - with: - actions_subcommand: 'readme' - github_token: '${{ secrets.GITHUB }}' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - - name: 'pre-commit check errors' - uses: pre-commit/action@v2.0.0 - continue-on-error: true - - - name: 'pre-commit fix erros' - uses: pre-commit/action@v2.0.0 - continue-on-error: true - - - name: 'push readme' - uses: 'clouddrove/github-actions@v9.0.2' - continue-on-error: true - with: - actions_subcommand: 'push' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: 'Slack Notification' - uses: clouddrove/action-slack@v2 - with: - status: ${{ job.status }} - fields: repo,author - author_name: 'CloudDrove' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # required - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_TERRAFORM }} # required - if: always() + README: + uses: clouddrove/github-shared-workflows/.github/workflows/readme.yml@master + secrets: + TOKEN : ${{ secrets.GITHUB }} + SLACK_WEBHOOK_TERRAFORM: ${{ secrets.SLACK_WEBHOOK_TERRAFORM }} diff --git a/.github/workflows/semantic-releaser.yml b/.github/workflows/semantic-releaser.yml deleted file mode 100644 index 6e685a0..0000000 --- a/.github/workflows/semantic-releaser.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Release - -on: - push: - branches: - - main - paths: - - '**.tf' - - '!examples/**.tf' - -jobs: - release: - name: Release - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - persist-credentials: false - - - name: Setup Node.js - uses: actions/setup-node@v1 - with: - node-version: 14 - - - name: Release - env: - GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} - run: npx semantic-release diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml deleted file mode 100644 index 08638e3..0000000 --- a/.github/workflows/static-checks.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: static-checks - -on: - pull_request: - -jobs: - versionExtract: - name: Get min/max versions - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Terraform min/max versions - id: minMax - uses: clowdhaus/terraform-min-max@main - outputs: - minVersion: ${{ steps.minMax.outputs.minVersion }} - maxVersion: ${{ steps.minMax.outputs.maxVersion }} - - versionEvaluate: - name: Evaluate Terraform versions - runs-on: ubuntu-latest - needs: versionExtract - strategy: - fail-fast: false - matrix: - version: - - ${{ needs.versionExtract.outputs.minVersion }} - - ${{ needs.versionExtract.outputs.maxVersion }} - directory: - - _example/complete - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install Terraform v${{ matrix.version }} - uses: hashicorp/setup-terraform@v1 - with: - terraform_version: ${{ matrix.version }} - - - name: Init & validate v${{ matrix.version }} - run: | - cd ${{ matrix.directory }} - terraform init - terraform validate - - name: tflint - uses: reviewdog/action-tflint@master - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - working_directory: ${{ matrix.directory }} - fail_on_error: 'true' - filter_mode: 'nofilter' - flags: '--module' - - format: - name: Check code format - runs-on: ubuntu-latest - needs: versionExtract - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install Terraform v${{ needs.versionExtract.outputs.maxVersion }} - uses: hashicorp/setup-terraform@v1 - with: - terraform_version: ${{ needs.versionExtract.outputs.maxVersion }} - - - name: Check Terraform format changes - run: terraform fmt --recursive -check=true diff --git a/.github/workflows/tf-checks.yml b/.github/workflows/tf-checks.yml new file mode 100644 index 0000000..a6bebe7 --- /dev/null +++ b/.github/workflows/tf-checks.yml @@ -0,0 +1,15 @@ +name: tf-checks +on: + push: + branches: [ master ] + pull_request: + workflow_dispatch: + complete-linux-example: + uses: clouddrove/github-shared-workflows/.github/workflows/tf-checks.yml@1.2.8 + with: + working_directory: './_example/complete/linux_web_app/' + + complete-windows-example: + uses: clouddrove/github-shared-workflows/.github/workflows/tf-checks.yml@1.2.8 + with: + working_directory: './_example/complete/windows_web_app/' \ No newline at end of file diff --git a/.github/workflows/tflint.yml b/.github/workflows/tflint.yml new file mode 100644 index 0000000..0badffd --- /dev/null +++ b/.github/workflows/tflint.yml @@ -0,0 +1,11 @@ +name: tf-lint +on: + push: + branches: [ master ] + pull_request: + workflow_dispatch: +jobs: + tf-lint: + uses: clouddrove/github-shared-workflows/.github/workflows/tf-lint.yml@1.2.8 + secrets: + GITHUB: ${{ secrets.GITHUB }} \ No newline at end of file diff --git a/.github/workflows/tfsec.yml b/.github/workflows/tfsec.yml index 9aaf588..fab3153 100644 --- a/.github/workflows/tfsec.yml +++ b/.github/workflows/tfsec.yml @@ -5,7 +5,7 @@ on: workflow_dispatch: jobs: tfsec: - uses: clouddrove/github-shared-workflows/.github/workflows/tfsec.yml@master + uses: clouddrove/github-shared-workflows/.github/workflows/tfsec.yml@1.2.8 secrets: inherit with: working_directory: '.' \ No newline at end of file diff --git a/_example/complete/linux_web_app/main.tf b/_example/complete/linux_web_app/main.tf new file mode 100644 index 0000000..d298284 --- /dev/null +++ b/_example/complete/linux_web_app/main.tf @@ -0,0 +1,127 @@ +provider "azurerm" { + features {} + subscription_id = "068245d4-3c94-42fe-9c4d-9e5e1cabc60c" +} + +##----------------------------------------------------------------------------- +## Resource group +##----------------------------------------------------------------------------- +module "resource_group" { + source = "clouddrove/resource-group/azure" + version = "1.0.2" + + label_order = ["name", "environment"] + name = "rg-example" + environment = "test" + location = "Canada Central" +} + +##----------------------------------------------------------------------------- +## Log Analytics +##----------------------------------------------------------------------------- +module "log-analytics" { + source = "clouddrove/log-analytics/azure" + version = "1.1.0" + name = "app" + environment = "test" + label_order = ["name", "environment"] + create_log_analytics_workspace = true + log_analytics_workspace_sku = "PerGB2018" + resource_group_name = module.resource_group.resource_group_name + log_analytics_workspace_location = module.resource_group.resource_group_location + log_analytics_workspace_id = module.log-analytics.workspace_id +} + +##----------------------------------------------------------------------------- +## Linux web app +##----------------------------------------------------------------------------- +module "linux-web-app" { + source = "../../.." + enable = true + name = "app" + environment = "testing" + label_order = ["name", "environment", ] + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + + os_type = var.os_type + sku_name = var.linux_sku_name + + + + ##----------------------------------------------------------------------------- + ## To Deploy Container + ##----------------------------------------------------------------------------- + use_docker = false + docker_image_name = var.docker_image_name + docker_registry_url = ".azurecr.io" + docker_registry_username = "" + docker_registry_password = "" + acr_id = "" + + ##----------------------------------------------------------------------------- + ## Node application + ##----------------------------------------------------------------------------- + use_node = true + node_version = var.node_version + + ##----------------------------------------------------------------------------- + ## Dot net application + ##----------------------------------------------------------------------------- + use_dotnet = false + dotnet_version = var.dotnet_version + + ##----------------------------------------------------------------------------- + ## Java application + ##----------------------------------------------------------------------------- + use_java = false + java_version = var.java_version + java_server = var.java_server + java_server_version = var.java_server_version + + + ##----------------------------------------------------------------------------- + ## python application + ##----------------------------------------------------------------------------- + + use_python = false + python_version = var.python_version + + ##----------------------------------------------------------------------------- + ## php application + ##----------------------------------------------------------------------------- + + use_php = false + php_version = var.php_version + + ##----------------------------------------------------------------------------- + ## Ruby application + ##----------------------------------------------------------------------------- + + use_ruby = false + ruby_version = var.ruby_version + + ##----------------------------------------------------------------------------- + ## Go application + ##----------------------------------------------------------------------------- + + use_go = false + go_version = var.go_version + + site_config = var.site_config + app_settings = var.app_settings + + ##----------------------------------------------------------------------------- + ## App service logs + ##----------------------------------------------------------------------------- + + app_service_logs = var.app_service_logs + + + ##----------------------------------------------------------------------------- + ## log analytics + ##----------------------------------------------------------------------------- + log_analytics_workspace_id = module.log-analytics.workspace_id + app_insights_workspace_id = module.log-analytics.workspace_id # log analytics workspace id in app insights +} + diff --git a/_example/complete/outputs.tf b/_example/complete/linux_web_app/outputs.tf similarity index 100% rename from _example/complete/outputs.tf rename to _example/complete/linux_web_app/outputs.tf diff --git a/_example/complete/linux_web_app/variables.tf b/_example/complete/linux_web_app/variables.tf new file mode 100644 index 0000000..f69aaef --- /dev/null +++ b/_example/complete/linux_web_app/variables.tf @@ -0,0 +1,98 @@ +##----------------------------------------------------------------------------- +## App Service +##----------------------------------------------------------------------------- + +variable "linux_sku_name" { + default = "B1" + +} + +variable "os_type" { + default = "Linux" +} + +variable "enable" { + default = true +} + +variable "is_linux_webapp" { + default = true +} + +variable "dotnet_version" { + default = "8.0" +} + +variable "node_version" { + default = "20-lts" +} + +variable "site_config" { + default = { + container_registry_use_managed_identity = true # Set to true + } +} + +variable "app_settings" { + type = map(string) + description = "A map of settings for the application" + default = { + foo = "bar" + } +} + +variable "php_version" { + type = string + default = "8.2" +} + +variable "python_version" { + type = string + default = "3.12" +} + +variable "go_version" { + type = string + default = "1.19" +} + +variable "ruby_version" { + type = string + default = "2.7" +} + +variable "java_version" { + type = string + default = "17" +} + +variable "java_server" { + type = string + default = "JAVA" + # Possible values include JAVA, TOMCAT, and JBOSSEAP ( Its in premium sku ). +} + +variable "java_server_version" { + type = string + default = "17" +} + +variable "docker_image_name" { + default = "nginx:latest" +} + +variable "app_service_logs" { + default = { + detailed_error_messages = false + failed_request_tracing = false + application_logs = { + file_system_level = "Information" + } + http_logs = { + file_system = { + retention_in_days = 7 + retention_in_mb = 35 + } + } + } +} diff --git a/_example/complete/versions.tf b/_example/complete/linux_web_app/versions.tf similarity index 65% rename from _example/complete/versions.tf rename to _example/complete/linux_web_app/versions.tf index 3a62915..c3d7de8 100644 --- a/_example/complete/versions.tf +++ b/_example/complete/linux_web_app/versions.tf @@ -1,12 +1,12 @@ terraform { - required_version = ">= 1.3.6" + required_version = ">= 1.9.0" } terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = ">=3.0.0" + version = ">=3.109.0" } } } \ No newline at end of file diff --git a/_example/complete/main.tf b/_example/complete/main.tf deleted file mode 100644 index 979a4e7..0000000 --- a/_example/complete/main.tf +++ /dev/null @@ -1,44 +0,0 @@ -provider "azurerm" { - features {} -} - -# Resource Group -module "resource_group" { - source = "clouddrove/resource-group/azure" - version = "1.0.2" - - label_order = ["name", "environment"] - name = "rg-example" - environment = "test" - location = "Canada Central" -} - -# APP Service -module "app-service" { - source = "../../" - enabled = true - name = "app" - environment = "teting" - label_order = ["name", "environment", ] - resource_group_name = module.resource_group.resource_group_name - location = module.resource_group.resource_group_location - - service_plan = { - kind = "Windows" - size = "S1" - tier = "Free" - } - - app_service_name = "test-app-service" - enable_client_affinity = true - enable_https = true - - site_config = { - use_32_bit_worker_process = true - windows_fx_version = "node|18-lts" - } - - app_settings = { - WEBSITE_NODE_DEFAULT_VERSION = "~16" - } -} \ No newline at end of file diff --git a/_example/complete/variables.tf b/_example/complete/variables.tf deleted file mode 100644 index e69de29..0000000 diff --git a/_example/complete/windows_web_app/main.tf b/_example/complete/windows_web_app/main.tf new file mode 100644 index 0000000..c85eace --- /dev/null +++ b/_example/complete/windows_web_app/main.tf @@ -0,0 +1,112 @@ +provider "azurerm" { + features {} + subscription_id = "068245d4-3c94-42fe-9c4d-9e5e1cabc60c" +} + +##----------------------------------------------------------------------------- +## Resource group +##----------------------------------------------------------------------------- +module "resource_group" { + source = "clouddrove/resource-group/azure" + version = "1.0.2" + + label_order = ["name", "environment"] + name = "rg-example" + environment = "test" + location = "Canada Central" +} + +module "log-analytics" { + source = "clouddrove/log-analytics/azure" + version = "1.1.0" + name = "app" + environment = "test" + label_order = ["name", "environment"] + create_log_analytics_workspace = true + log_analytics_workspace_sku = "PerGB2018" + resource_group_name = module.resource_group.resource_group_name + log_analytics_workspace_location = module.resource_group.resource_group_location + log_analytics_workspace_id = module.log-analytics.workspace_id +} + +##----------------------------------------------------------------------------- +## Windows web app +##----------------------------------------------------------------------------- +module "windows-web-app" { + source = "../../.." + enable = true + name = "app" + environment = "testing" + label_order = ["name", "environment", ] + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + + os_type = var.os_type + sku_name = var.windows_sku_name + + ##----------------------------------------------------------------------------- + ## log analytics + ##----------------------------------------------------------------------------- + log_analytics_workspace_id = module.log-analytics.workspace_id + app_insights_workspace_id = module.log-analytics.workspace_id + + ##----------------------------------------------------------------------------- + ## app service logs + ##----------------------------------------------------------------------------- + app_service_logs = var.app_service_logs + + + site_config = var.site_config + app_settings = var.app_settings + + ##----------------------------------------------------------------------------- + ## Current stack ( Possible values -> dotnet, dotnetcore, node, python, php, and java ) + ##----------------------------------------------------------------------------- + + current_stack = "dotnet" # Specify runtime stack here + + ##----------------------------------------------------------------------------- + ## Dot net + ##----------------------------------------------------------------------------- + use_dotnet = true # Make it true if want to use it + dotnet_version = var.dotnet_version # For dotnet + dotnet_core_version = var.dotnet_core_version # For dotnetcore + + ##----------------------------------------------------------------------------- + ## Node application + ##----------------------------------------------------------------------------- + use_node = false + node_version = var.node_version + + ##----------------------------------------------------------------------------- + ## python application + ##----------------------------------------------------------------------------- + + use_python = false # Can only be a bool (true to use it) + + ##----------------------------------------------------------------------------- + ## php application + ##----------------------------------------------------------------------------- + + use_php = false + php_version = var.php_version + + ##----------------------------------------------------------------------------- + ## java application + ##----------------------------------------------------------------------------- + + use_java = false + java_version = var.java_version + + ##----------------------------------------------------------------------------- + ## To Deploy Docker Container + ##----------------------------------------------------------------------------- + + use_docker = false # Make it true if want to use it + docker_image_name = var.docker_image_name + docker_registry_url = ".azurecr.io" + docker_registry_username = "" + docker_registry_password = "" + acr_id = "" + +} \ No newline at end of file diff --git a/_example/complete/variables.auto.tfvars b/_example/complete/windows_web_app/outputs.tf similarity index 100% rename from _example/complete/variables.auto.tfvars rename to _example/complete/windows_web_app/outputs.tf diff --git a/_example/complete/windows_web_app/variables.tf b/_example/complete/windows_web_app/variables.tf new file mode 100644 index 0000000..f8a5887 --- /dev/null +++ b/_example/complete/windows_web_app/variables.tf @@ -0,0 +1,73 @@ +variable "windows_sku_name" { + default = "S1" +} + +variable "os_type" { + default = "Windows" +} + +variable "enable" { + default = true +} + +variable "is_linux_webapp" { + default = false +} + +variable "dotnet_version" { + default = "v8.0" +} + +variable "dotnet_core_version" { + default = "v4.0" +} + +variable "node_version" { + default = "~20" +} + +variable "python_version" { + default = "1.8.0" +} + +variable "php_version" { + default = "8.3" +} + +variable "java_version" { + default = "17" +} + +variable "site_config" { + default = { + container_registry_use_managed_identity = true # Set to true + } +} + +variable "app_settings" { + type = map(string) + description = "A map of settings for the application" + default = { + foo = "bar" + } +} + +variable "docker_image_name" { + default = "nginx-test:latest" # Windows-based Docker image should be used here +} + +variable "app_service_logs" { + default = { + detailed_error_messages = false + failed_request_tracing = false + application_logs = { + file_system_level = "Information" + } + http_logs = { + file_system = { + retention_in_days = 7 + retention_in_mb = 35 + } + } + } +} diff --git a/_example/complete/windows_web_app/versions.tf b/_example/complete/windows_web_app/versions.tf new file mode 100644 index 0000000..c3d7de8 --- /dev/null +++ b/_example/complete/windows_web_app/versions.tf @@ -0,0 +1,12 @@ +terraform { + required_version = ">= 1.9.0" +} + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">=3.109.0" + } + } +} \ No newline at end of file diff --git a/main.tf b/main.tf index ab16b76..45881cf 100644 --- a/main.tf +++ b/main.tf @@ -1,8 +1,14 @@ ## Managed By : CloudDrove ## Copyright @ CloudDrove. All Right Reserved. +##----------------------------------------------------------------------------- +## DATA +##----------------------------------------------------------------------------- +data "azurerm_client_config" "main" {} - +##----------------------------------------------------------------------------- +## Labels module called that will be used for naming and tags. +##----------------------------------------------------------------------------- module "labels" { source = "clouddrove/labels/azure" @@ -15,128 +21,594 @@ module "labels" { repository = var.repository } +##----------------------------------------------------------------------------- +## Locals +##----------------------------------------------------------------------------- locals { + default_site_config = { + always_on = "true" + scm_minimum_tls_version = "1.2" + } - # app insights - app_insights = try(data.azurerm_application_insights.main.0, try(azurerm_application_insights.main.0, {})) + site_config = merge(local.default_site_config, var.site_config) - default_app_settings = var.application_insights_enabled ? { - APPLICATION_INSIGHTS_IKEY = try(local.app_insights.instrumentation_key, "") - APPINSIGHTS_INSTRUMENTATIONKEY = try(local.app_insights.instrumentation_key, "") - APPLICATIONINSIGHTS_CONNECTION_STRING = try(local.app_insights.connection_string, "") - ApplicationInsightsAgent_EXTENSION_VERSION = "~2" - } : {} + subnets = [for subnet in var.authorized_subnet_ids : { + name = "ip_restriction_subnet_${join("", [1, index(var.authorized_subnet_ids, subnet)])}" + ip_address = null + virtual_network_subnet_id = subnet + service_tag = null + subnet_id = subnet + priority = join("", [1, index(var.authorized_subnet_ids, subnet)]) + action = "Allow" + headers = local.ip_restriction_headers + }] - # Default configuration for Site config block - default_site_config = { - always_on = "true" - } + ip_restriction_headers = var.ip_restriction_headers != null ? [merge(local.default_ip_restrictions_headers, var.ip_restriction_headers)] : [] - ip_address = [for ip_address in var.ips_allowed : { - name = "ip_restriction_cidr_${join("", [1, index(var.ips_allowed, ip_address)])}" - ip_address = ip_address + cidrs = [for cidr in var.authorized_ips : { + name = "ip_restriction_cidr_${join("", [1, index(var.authorized_ips, cidr)])}" + ip_address = cidr virtual_network_subnet_id = null service_tag = null subnet_id = null - priority = join("", [1, index(var.ips_allowed, ip_address)]) + priority = join("", [1, index(var.authorized_ips, cidr)]) action = "Allow" + headers = local.ip_restriction_headers }] - subnets = [for subnet in var.subnet_ids_allowed : { - name = "ip_restriction_subnet_${join("", [1, index(var.subnet_ids_allowed, subnet)])}" + default_ip_restrictions_headers = { + x_azure_fdid = null + x_fd_health_probe = null + x_forwarded_for = null + x_forwarded_host = null + } + + scm_subnets = [for subnet in var.scm_authorized_subnet_ids : { + name = "scm_ip_restriction_subnet_${join("", [1, index(var.scm_authorized_subnet_ids, subnet)])}" ip_address = null virtual_network_subnet_id = subnet service_tag = null subnet_id = subnet - priority = join("", [1, index(var.subnet_ids_allowed, subnet)]) + priority = join("", [1, index(var.scm_authorized_subnet_ids, subnet)]) + action = "Allow" + headers = local.scm_ip_restriction_headers + }] + + scm_ip_restriction_headers = var.scm_ip_restriction_headers != null ? [merge(local.default_ip_restrictions_headers, var.scm_ip_restriction_headers)] : [] + + service_tags = [for service_tag in var.authorized_service_tags : { + name = "service_tag_restriction_${join("", [1, index(var.authorized_service_tags, service_tag)])}" + ip_address = null + virtual_network_subnet_id = null + service_tag = service_tag + subnet_id = null + priority = join("", [1, index(var.authorized_service_tags, service_tag)]) action = "Allow" + headers = local.ip_restriction_headers }] + + scm_cidrs = [for cidr in var.scm_authorized_ips : { + name = "scm_ip_restriction_cidr_${join("", [1, index(var.scm_authorized_ips, cidr)])}" + ip_address = cidr + virtual_network_subnet_id = null + service_tag = null + subnet_id = null + priority = join("", [1, index(var.scm_authorized_ips, cidr)]) + action = "Allow" + headers = local.scm_ip_restriction_headers + }] + + scm_service_tags = [for service_tag in var.scm_authorized_service_tags : { + name = "scm_service_tag_restriction_${join("", [1, index(var.scm_authorized_service_tags, service_tag)])}" + ip_address = null + virtual_network_subnet_id = null + service_tag = service_tag + subnet_id = null + priority = join("", [1, index(var.scm_authorized_service_tags, service_tag)]) + action = "Allow" + headers = local.scm_ip_restriction_headers + }] + + app_insights = try(data.azurerm_application_insights.app_insights[0], try(azurerm_application_insights.app_insights[0], {})) + + + app_settings = merge(local.default_app_settings, var.app_settings) + default_app_settings = var.application_insights_enabled ? { + APPLICATION_INSIGHTS_IKEY = try(local.app_insights.instrumentation_key, "") + APPINSIGHTS_INSTRUMENTATIONKEY = try(local.app_insights.instrumentation_key, "") + APPLICATIONINSIGHTS_CONNECTION_STRING = try(local.app_insights.connection_string, "") + } : {} + + auth_settings_active_directory = merge( + { + client_id = null + client_secret = null + allowed_audiences = [] + }, + local.auth_settings.active_directory == null ? local.auth_settings_ad_default : var.auth_settings.active_directory) + auth_settings_ad_default = { + client_id = null + client_secret = null + allowed_audiences = [] + } + + auth_settings = merge( + { + enabled = false + issuer = format("https://sts.windows.net/%s/", data.azurerm_client_config.main.tenant_id) + token_store_enabled = false + unauthenticated_client_action = "RedirectToLoginPage" + default_provider = "AzureActiveDirectory" + allowed_external_redirect_urls = [] + active_directory = null + }, + var.auth_settings) + + + auth_settings_v2_login_default = { + token_store_enabled = false + token_refresh_extension_time = 72 + preserve_url_fragments_for_logins = false + cookie_expiration_convention = "FixedTime" + cookie_expiration_time = "08:00:00" + validate_nonce = true + nonce_expiration_time = "00:05:00" + } + + auth_settings_v2_login = try(var.auth_settings_v2.login, null) == null ? local.auth_settings_v2_login_default : var.auth_settings_v2.login + resource_group_name = var.resource_group_name + location = var.location + valid_rg_name = var.existing_private_dns_zone == null ? local.resource_group_name : (var.existing_private_dns_zone_resource_group_name == "" ? local.resource_group_name : var.existing_private_dns_zone_resource_group_name) + private_dns_zone_name = var.existing_private_dns_zone == null ? join("", azurerm_private_dns_zone.dnszone.*.name) : var.existing_private_dns_zone } -data "azurerm_client_config" "main" {} +##----------------------------------------------------------------------------- +## App service plan +##----------------------------------------------------------------------------- +resource "azurerm_service_plan" "main" { + count = var.enable ? 1 : 0 + name = format("%s-asp", module.labels.id) + resource_group_name = var.resource_group_name + location = var.location -## APP SERVICE PLAN + os_type = var.os_type + sku_name = var.sku_name + worker_count = var.sku_name == "B1" ? null : var.worker_count + maximum_elastic_worker_count = var.maximum_elastic_worker_count + app_service_environment_id = var.app_service_environment_id + per_site_scaling_enabled = var.per_site_scaling_enabled + tags = module.labels.tags +} -resource "azurerm_app_service_plan" "main" { - name = format("app-service-plan-%s", lower(replace(module.labels.id, "/[[:^alnum:]]/", ""))) +##----------------------------------------------------------------------------- +## Linux web app +##----------------------------------------------------------------------------- + +resource "azurerm_linux_web_app" "main" { + count = var.enable && var.os_type == "Linux" ? 1 : 0 + name = format("%s-linux-app", module.labels.id) resource_group_name = var.resource_group_name location = var.location - kind = var.service_plan.kind - reserved = var.service_plan.kind == "Linux" ? true : false - is_xenon = var.service_plan.kind == "xenon" ? true : false - per_site_scaling = var.service_plan.per_site_scaling - tags = module.labels.tags + service_plan_id = azurerm_service_plan.main[0].id + + public_network_access_enabled = var.public_network_access_enabled + virtual_network_subnet_id = var.app_service_vnet_integration_subnet_id + + + dynamic "site_config" { + for_each = [local.site_config] - sku { - tier = var.service_plan.tier - size = var.service_plan.size - capacity = var.service_plan.capacity + content { + linux_fx_version = lookup(site_config.value, "linux_fx_version", null) + container_registry_managed_identity_client_id = lookup(site_config.value, "container_registry_managed_identity_client_id", null) + container_registry_use_managed_identity = lookup(site_config.value, "container_registry_use_managed_identity", null) + + always_on = lookup(site_config.value, "always_on", null) + app_command_line = lookup(site_config.value, "app_command_line", null) + default_documents = lookup(site_config.value, "default_documents", null) + ftps_state = lookup(site_config.value, "ftps_state", "FtpsOnly") + health_check_path = lookup(site_config.value, "health_check_path", null) + http2_enabled = lookup(site_config.value, "http2_enabled", null) + local_mysql_enabled = lookup(site_config.value, "local_mysql_enabled", false) + managed_pipeline_mode = lookup(site_config.value, "managed_pipeline_mode", null) + minimum_tls_version = lookup(site_config.value, "minimum_tls_version", lookup(site_config.value, "min_tls_version", "1.2")) + remote_debugging_enabled = lookup(site_config.value, "remote_debugging_enabled", false) + remote_debugging_version = lookup(site_config.value, "remote_debugging_version", null) + use_32_bit_worker = lookup(site_config.value, "use_32_bit_worker", false) + websockets_enabled = lookup(site_config.value, "websockets_enabled", false) + + dynamic "ip_restriction" { + for_each = concat(local.subnets, local.cidrs, local.service_tags) + content { + name = ip_restriction.value.name + ip_address = ip_restriction.value.ip_address + virtual_network_subnet_id = ip_restriction.value.virtual_network_subnet_id + service_tag = ip_restriction.value.service_tag + priority = ip_restriction.value.priority + action = ip_restriction.value.action + headers = ip_restriction.value.headers + } + } + + dynamic "scm_ip_restriction" { + for_each = concat(local.scm_subnets, local.scm_cidrs, local.scm_service_tags) + content { + name = scm_ip_restriction.value.name + ip_address = scm_ip_restriction.value.ip_address + virtual_network_subnet_id = scm_ip_restriction.value.virtual_network_subnet_id + service_tag = scm_ip_restriction.value.service_tag + priority = scm_ip_restriction.value.priority + action = scm_ip_restriction.value.action + headers = scm_ip_restriction.value.headers + } + } + scm_minimum_tls_version = lookup(site_config.value, "scm_minimum_tls_version", "1.2") + scm_use_main_ip_restriction = length(var.scm_authorized_ips) > 0 || var.scm_authorized_subnet_ids != null ? false : true + + vnet_route_all_enabled = var.app_service_vnet_integration_subnet_id != null + + application_stack { + docker_image_name = var.use_docker ? var.docker_image_name : null + docker_registry_url = var.use_docker ? format("https://%s", var.docker_registry_url) : null + docker_registry_username = var.use_docker ? var.docker_registry_username : null + docker_registry_password = var.use_docker ? var.docker_registry_password : null + dotnet_version = var.use_dotnet ? var.dotnet_version : null + node_version = var.use_node ? var.node_version : null + java_version = var.use_java ? var.java_version : null + java_server = var.use_java ? var.java_server : null + java_server_version = var.use_java ? var.java_server_version : null + php_version = var.use_php ? var.php_version : null + python_version = var.use_python ? var.python_version : null + ruby_version = var.use_ruby ? var.ruby_version : null + go_version = var.use_go ? var.go_version : null + } + + dynamic "cors" { + for_each = lookup(site_config.value, "cors", []) + content { + allowed_origins = cors.value.allowed_origins + support_credentials = lookup(cors.value, "support_credentials", null) + } + } + } + } + + app_settings = var.staging_slot_custom_app_settings == null ? local.app_settings : merge(local.default_app_settings, var.staging_slot_custom_app_settings) + + dynamic "connection_string" { + for_each = var.connection_strings + content { + name = lookup(connection_string.value, "name", null) + type = lookup(connection_string.value, "type", null) + value = lookup(connection_string.value, "value", null) + } + } + + + dynamic "auth_settings" { + for_each = local.auth_settings.enabled ? ["enabled"] : [] + content { + enabled = local.auth_settings.enabled + issuer = local.auth_settings.issuer + token_store_enabled = local.auth_settings.token_store_enabled + unauthenticated_client_action = local.auth_settings.unauthenticated_client_action + default_provider = local.auth_settings.default_provider + allowed_external_redirect_urls = local.auth_settings.allowed_external_redirect_urls + + dynamic "active_directory" { + for_each = local.auth_settings_active_directory.client_id == null ? [] : [local.auth_settings_active_directory] + content { + client_id = local.auth_settings_active_directory.client_id + client_secret = local.auth_settings_active_directory.client_secret + allowed_audiences = concat(formatlist("https://%s", [format("%s.azurewebsites.net", format("%s-app", module.labels.id))]), local.auth_settings_active_directory.allowed_audiences) + } + } + } + } + + dynamic "auth_settings_v2" { + for_each = lookup(var.auth_settings_v2, "auth_enabled", false) ? [var.auth_settings_v2] : [] + content { + auth_enabled = lookup(auth_settings_v2.value, "auth_enabled", false) + runtime_version = lookup(auth_settings_v2.value, "runtime_version", "~1") + config_file_path = lookup(auth_settings_v2.value, "config_file_path", null) + require_authentication = lookup(auth_settings_v2.value, "require_authentication", null) + unauthenticated_action = lookup(auth_settings_v2.value, "unauthenticated_action", "RedirectToLoginPage") + default_provider = lookup(auth_settings_v2.value, "default_provider", "azureactivedirectory") + excluded_paths = lookup(auth_settings_v2.value, "excluded_paths", null) + require_https = lookup(auth_settings_v2.value, "require_https", true) + http_route_api_prefix = lookup(auth_settings_v2.value, "http_route_api_prefix", "/.auth") + forward_proxy_convention = lookup(auth_settings_v2.value, "forward_proxy_convention", "ForwardProxyConventionNoProxy") + forward_proxy_custom_host_header_name = lookup(auth_settings_v2.value, "forward_proxy_custom_host_header_name", null) + forward_proxy_custom_scheme_header_name = lookup(auth_settings_v2.value, "forward_proxy_custom_scheme_header_name", null) + + dynamic "apple_v2" { + for_each = try(var.auth_settings_v2.apple_v2[*], []) + content { + client_id = lookup(apple_v2.value, "client_id", null) + client_secret_setting_name = lookup(apple_v2.value, "client_secret_setting_name", null) + } + } + + dynamic "active_directory_v2" { + for_each = try(var.auth_settings_v2.active_directory_v2[*], []) + + content { + client_id = lookup(active_directory_v2.value, "client_id", null) + tenant_auth_endpoint = lookup(active_directory_v2.value, "tenant_auth_endpoint", null) + client_secret_setting_name = lookup(active_directory_v2.value, "client_secret_setting_name", null) + client_secret_certificate_thumbprint = lookup(active_directory_v2.value, "client_secret_certificate_thumbprint", null) + jwt_allowed_groups = lookup(active_directory_v2.value, "jwt_allowed_groups", null) + jwt_allowed_client_applications = lookup(active_directory_v2.value, "jwt_allowed_client_applications", null) + www_authentication_disabled = lookup(active_directory_v2.value, "www_authentication_disabled", false) + allowed_groups = lookup(active_directory_v2.value, "allowed_groups", null) + allowed_identities = lookup(active_directory_v2.value, "allowed_identities", null) + allowed_applications = lookup(active_directory_v2.value, "allowed_applications", null) + login_parameters = lookup(active_directory_v2.value, "login_parameters", null) + } + } + + dynamic "azure_static_web_app_v2" { + for_each = try(var.auth_settings_v2.azure_static_web_app_v2[*], []) + content { + client_id = lookup(azure_static_web_app_v2.value, "client_id", null) + } + } + + dynamic "custom_oidc_v2" { + for_each = try(var.auth_settings_v2.custom_oidc_v2[*], []) + content { + name = lookup(custom_oidc_v2.value, "name", null) + client_id = lookup(custom_oidc_v2.value, "client_id", null) + openid_configuration_endpoint = lookup(custom_oidc_v2.value, "openid_configuration_endpoint", null) + name_claim_type = lookup(custom_oidc_v2.value, "name_claim_type", null) + scopes = lookup(custom_oidc_v2.value, "scopes", null) + client_credential_method = lookup(custom_oidc_v2.value, "client_credential_method", null) + client_secret_setting_name = lookup(custom_oidc_v2.value, "client_secret_setting_name", null) + authorisation_endpoint = lookup(custom_oidc_v2.value, "authorisation_endpoint", null) + token_endpoint = lookup(custom_oidc_v2.value, "token_endpoint", null) + issuer_endpoint = lookup(custom_oidc_v2.value, "issuer_endpoint", null) + certification_uri = lookup(custom_oidc_v2.value, "certification_uri", null) + } + } + + dynamic "facebook_v2" { + for_each = try(var.auth_settings_v2.facebook_v2[*], []) + content { + app_id = lookup(facebook_v2.value, "app_id", null) + app_secret_setting_name = lookup(facebook_v2.value, "app_secret_setting_name", null) + graph_api_version = lookup(facebook_v2.value, "graph_api_version", null) + login_scopes = lookup(facebook_v2.value, "login_scopes", null) + } + } + + dynamic "github_v2" { + for_each = try(var.auth_settings_v2.github_v2[*], []) + content { + client_id = lookup(github_v2.value, "client_id", null) + client_secret_setting_name = lookup(github_v2.value, "client_secret_setting_name", null) + login_scopes = lookup(github_v2.value, "login_scopes", null) + } + } + + dynamic "google_v2" { + for_each = try(var.auth_settings_v2.google_v2[*], []) + content { + client_id = lookup(google_v2.value, "client_id", null) + client_secret_setting_name = lookup(google_v2.value, "client_secret_setting_name", null) + allowed_audiences = lookup(google_v2.value, "allowed_audiences", null) + login_scopes = lookup(google_v2.value, "login_scopes", null) + } + } + + dynamic "microsoft_v2" { + for_each = try(var.auth_settings_v2.microsoft_v2[*], []) + content { + client_id = lookup(microsoft_v2.value, "client_id", null) + client_secret_setting_name = lookup(microsoft_v2.value, "client_secret_setting_name", null) + allowed_audiences = lookup(microsoft_v2.value, "allowed_audiences", null) + login_scopes = lookup(microsoft_v2.value, "login_scopes", null) + } + } + + dynamic "twitter_v2" { + for_each = try(var.auth_settings_v2.twitter_v2[*], []) + content { + consumer_key = lookup(twitter_v2.value, "consumer_key", null) + consumer_secret_setting_name = lookup(twitter_v2.value, "consumer_secret_setting_name", null) + } + } + + login { + logout_endpoint = lookup(local.auth_settings_v2_login, "logout_endpoint", null) + cookie_expiration_convention = lookup(local.auth_settings_v2_login, "cookie_expiration_convention", "FixedTime") + cookie_expiration_time = lookup(local.auth_settings_v2_login, "cookie_expiration_time", "08:00:00") + preserve_url_fragments_for_logins = lookup(local.auth_settings_v2_login, "preserve_url_fragments_for_logins", false) + token_refresh_extension_time = lookup(local.auth_settings_v2_login, "token_refresh_extension_time", 72) + token_store_enabled = lookup(local.auth_settings_v2_login, "token_store_enabled", false) + token_store_path = lookup(local.auth_settings_v2_login, "token_store_path", null) + token_store_sas_setting_name = lookup(local.auth_settings_v2_login, "token_store_sas_setting_name", null) + validate_nonce = lookup(local.auth_settings_v2_login, "validate_nonce", true) + nonce_expiration_time = lookup(local.auth_settings_v2_login, "nonce_expiration_time", "00:05:00") + } + } + } + + client_affinity_enabled = var.client_affinity_enabled + https_only = var.https_only + + dynamic "identity" { + for_each = var.identity[*] + content { + type = var.identity.type + identity_ids = var.identity.identity_ids + } + } + + dynamic "storage_account" { + for_each = var.mount_points + content { + name = lookup(storage_account.value, "name", format("%s-%s", storage_account.value["account_name"], storage_account.value["share_name"])) + type = lookup(storage_account.value, "type", "AzureFiles") + account_name = lookup(storage_account.value, "account_name", null) + share_name = lookup(storage_account.value, "share_name", null) + access_key = lookup(storage_account.value, "access_key", null) + mount_path = lookup(storage_account.value, "mount_path", null) + } + } + + dynamic "logs" { + for_each = var.app_service_logs == null ? [] : [var.app_service_logs] + content { + detailed_error_messages = lookup(logs.value, "detailed_error_messages", null) + failed_request_tracing = lookup(logs.value, "failed_request_tracing", null) + + dynamic "application_logs" { + for_each = lookup(logs.value, "application_logs", null) == null ? [] : ["application_logs"] + + content { + dynamic "azure_blob_storage" { + for_each = lookup(logs.value["application_logs"], "azure_blob_storage", null) == null ? [] : ["azure_blob_storage"] + content { + level = lookup(logs.value["application_logs"]["azure_blob_storage"], "level", null) + retention_in_days = lookup(logs.value["application_logs"]["azure_blob_storage"], "retention_in_days", null) + sas_url = lookup(logs.value["application_logs"]["azure_blob_storage"], "sas_url", null) + } + } + file_system_level = lookup(logs.value["application_logs"], "file_system_level", null) + } + } + + dynamic "http_logs" { + for_each = lookup(logs.value, "http_logs", null) == null ? [] : ["http_logs"] + content { + dynamic "azure_blob_storage" { + for_each = lookup(logs.value["http_logs"], "azure_blob_storage", null) == null ? [] : ["azure_blob_storage"] + content { + retention_in_days = lookup(logs.value["http_logs"]["azure_blob_storage"], "retention_in_days", null) + sas_url = lookup(logs.value["http_logs"]["azure_blob_storage"], "sas_url", null) + } + } + dynamic "file_system" { + for_each = lookup(logs.value["http_logs"], "file_system", null) == null ? [] : ["file_system"] + content { + retention_in_days = lookup(logs.value["http_logs"]["file_system"], "retention_in_days", null) + retention_in_mb = lookup(logs.value["http_logs"]["file_system"], "retention_in_mb", null) + } + } + } + } + } + } + + tags = module.labels.tags + + lifecycle { + ignore_changes = [ + app_settings, + # site_config.0.application_stack, + site_config.0.cors, + site_config.0.ip_restriction_default_action, + site_config.0.scm_ip_restriction_default_action, + site_config.0.ftps_state + ] } } -## APP SERVICE +##----------------------------------------------------------------------------- +## Windows web app +##----------------------------------------------------------------------------- -resource "azurerm_app_service" "main" { - count = var.enabled ? 1 : 0 - name = lower(format("%s-app-service", module.labels.id)) - resource_group_name = var.resource_group_name - location = var.location - app_service_plan_id = azurerm_app_service_plan.main.id - client_affinity_enabled = var.enable_client_affinity - https_only = var.enable_https - client_cert_enabled = var.enable_client_certificate - tags = module.labels.tags - app_settings = merge(local.default_app_settings, var.app_settings) +resource "azurerm_windows_web_app" "main" { + count = var.enable && var.os_type == "Windows" ? 1 : 0 + name = format("%s-windows-app", module.labels.id) + resource_group_name = var.resource_group_name + location = var.location + service_plan_id = azurerm_service_plan.main[0].id + + public_network_access_enabled = var.public_network_access_enabled + virtual_network_subnet_id = var.app_service_vnet_integration_subnet_id dynamic "site_config" { - for_each = [merge(local.default_site_config, var.site_config)] - - content { - always_on = lookup(site_config.value, "always_on", false) - app_command_line = lookup(site_config.value, "app_command_line", null) - default_documents = lookup(site_config.value, "default_documents", null) - dotnet_framework_version = lookup(site_config.value, "dotnet_framework_version", "v2.0") - ftps_state = lookup(site_config.value, "ftps_state", "FtpsOnly") - health_check_path = lookup(site_config.value, "health_check_path", null) - ip_restriction = concat(local.subnets, local.ip_address) - number_of_workers = var.service_plan.per_site_scaling == true ? lookup(site_config.value, "number_of_workers") : null - http2_enabled = lookup(site_config.value, "http2_enabled", false) - java_container = lookup(site_config.value, "java_container", null) - java_container_version = lookup(site_config.value, "java_container_version", null) - java_version = lookup(site_config.value, "java_version", null) - local_mysql_enabled = lookup(site_config.value, "local_mysql_enabled", null) - linux_fx_version = lookup(site_config.value, "linux_fx_version", null) - windows_fx_version = lookup(site_config.value, "windows_fx_version", null) - managed_pipeline_mode = lookup(site_config.value, "managed_pipeline_mode", "Integrated") - min_tls_version = lookup(site_config.value, "min_tls_version", "1.2") - php_version = lookup(site_config.value, "php_version", null) - python_version = lookup(site_config.value, "python_version", null) - remote_debugging_enabled = lookup(site_config.value, "remote_debugging_enabled", null) - remote_debugging_version = lookup(site_config.value, "remote_debugging_version", null) - scm_type = lookup(site_config.value, "scm_type", null) - use_32_bit_worker_process = lookup(site_config.value, "use_32_bit_worker_process", true) - websockets_enabled = lookup(site_config.value, "websockets_enabled", null) - } - } - - auth_settings { - enabled = var.enable_auth_settings - default_provider = var.default_auth_provider - allowed_external_redirect_urls = [] - issuer = format("https://sts.windows.net/%s/", data.azurerm_client_config.main.tenant_id) - unauthenticated_client_action = var.unauthenticated_client_action - token_store_enabled = var.token_store_enabled - - dynamic "active_directory" { - for_each = var.active_directory_auth_setttings - content { - client_id = lookup(active_directory_auth_setttings.value, "client_id", null) - client_secret = lookup(active_directory_auth_setttings.value, "client_secret", null) - allowed_audiences = concat(formatlist("https://%s", [format("%s.azurewebsites.net", var.app_service_name)]), []) + for_each = [local.site_config] + + content { + windows_fx_version = lookup(site_config.value, "windows_fx_version", null) + container_registry_managed_identity_client_id = lookup(site_config.value, "container_registry_managed_identity_client_id", null) + container_registry_use_managed_identity = lookup(site_config.value, "container_registry_use_managed_identity", null) + + always_on = lookup(site_config.value, "always_on", null) + app_command_line = lookup(site_config.value, "app_command_line", null) + default_documents = lookup(site_config.value, "default_documents", null) + ftps_state = lookup(site_config.value, "ftps_state", "FtpsOnly") + health_check_path = lookup(site_config.value, "health_check_path", null) + http2_enabled = lookup(site_config.value, "http2_enabled", null) + local_mysql_enabled = lookup(site_config.value, "local_mysql_enabled", false) + managed_pipeline_mode = lookup(site_config.value, "managed_pipeline_mode", null) + minimum_tls_version = lookup(site_config.value, "minimum_tls_version", lookup(site_config.value, "min_tls_version", "1.2")) + remote_debugging_enabled = lookup(site_config.value, "remote_debugging_enabled", false) + remote_debugging_version = lookup(site_config.value, "remote_debugging_version", null) + use_32_bit_worker = lookup(site_config.value, "use_32_bit_worker", false) + websockets_enabled = lookup(site_config.value, "websockets_enabled", false) + + dynamic "ip_restriction" { + for_each = concat(local.subnets, local.cidrs, local.service_tags) + content { + name = ip_restriction.value.name + ip_address = ip_restriction.value.ip_address + virtual_network_subnet_id = ip_restriction.value.virtual_network_subnet_id + service_tag = ip_restriction.value.service_tag + priority = ip_restriction.value.priority + action = ip_restriction.value.action + headers = ip_restriction.value.headers + } + } + + dynamic "scm_ip_restriction" { + for_each = concat(local.scm_subnets, local.scm_cidrs, local.scm_service_tags) + content { + name = scm_ip_restriction.value.name + ip_address = scm_ip_restriction.value.ip_address + virtual_network_subnet_id = scm_ip_restriction.value.virtual_network_subnet_id + service_tag = scm_ip_restriction.value.service_tag + priority = scm_ip_restriction.value.priority + action = scm_ip_restriction.value.action + headers = scm_ip_restriction.value.headers + } + } + scm_minimum_tls_version = lookup(site_config.value, "scm_minimum_tls_version", "1.2") + scm_use_main_ip_restriction = length(var.scm_authorized_ips) > 0 || var.scm_authorized_subnet_ids != null ? false : true + + vnet_route_all_enabled = var.app_service_vnet_integration_subnet_id != null + + application_stack { + docker_image_name = var.use_docker ? var.docker_image_name : null + docker_registry_url = var.use_docker ? format("https://%s", var.docker_registry_url) : null + docker_registry_username = var.use_docker ? var.docker_registry_username : null + docker_registry_password = var.use_docker ? var.docker_registry_password : null + current_stack = var.use_current_stack ? var.current_stack : null + python = var.use_python && var.current_stack == "python" ? var.use_python : null # Can only be true or false + php_version = var.use_php && var.current_stack == "php" ? var.php_version : null + node_version = var.use_node && var.current_stack == "node" ? var.node_version : null + java_version = var.use_java && var.current_stack == "java" ? var.java_version : null + java_embedded_server_enabled = var.use_java && var.current_stack == "java" ? var.java_embedded_server_enabled : null + tomcat_version = var.use_tomcat ? var.tomcat_version : null + dotnet_version = var.use_dotnet && var.current_stack == "dotnet" ? var.dotnet_version : null + dotnet_core_version = var.use_dotnet && var.current_stack == "dotnetcore" ? var.dotnet_core_version : null + } + + dynamic "cors" { + for_each = lookup(site_config.value, "cors", []) + content { + allowed_origins = cors.value.allowed_origins + support_credentials = lookup(cors.value, "support_credentials", null) + } } } } + app_settings = var.staging_slot_custom_app_settings == null ? local.app_settings : merge(local.default_app_settings, var.staging_slot_custom_app_settings) + dynamic "connection_string" { for_each = var.connection_strings content { @@ -146,15 +618,171 @@ resource "azurerm_app_service" "main" { } } - identity { - type = var.identity_ids != null ? "SystemAssigned, UserAssigned" : "SystemAssigned" - identity_ids = var.identity_ids + + dynamic "auth_settings" { + for_each = local.auth_settings.enabled ? ["enabled"] : [] + content { + enabled = local.auth_settings.enabled + issuer = local.auth_settings.issuer + token_store_enabled = local.auth_settings.token_store_enabled + unauthenticated_client_action = local.auth_settings.unauthenticated_client_action + default_provider = local.auth_settings.default_provider + allowed_external_redirect_urls = local.auth_settings.allowed_external_redirect_urls + + dynamic "active_directory" { + for_each = local.auth_settings_active_directory.client_id == null ? [] : [local.auth_settings_active_directory] + content { + client_id = local.auth_settings_active_directory.client_id + client_secret = local.auth_settings_active_directory.client_secret + allowed_audiences = concat(formatlist("https://%s", [format("%s.azurewebsites.net", format("%s-app", module.labels.id))]), local.auth_settings_active_directory.allowed_audiences) + } + } + } + } + + dynamic "auth_settings_v2" { + for_each = lookup(var.auth_settings_v2, "auth_enabled", false) ? [var.auth_settings_v2] : [] + content { + auth_enabled = lookup(auth_settings_v2.value, "auth_enabled", false) + runtime_version = lookup(auth_settings_v2.value, "runtime_version", "~1") + config_file_path = lookup(auth_settings_v2.value, "config_file_path", null) + require_authentication = lookup(auth_settings_v2.value, "require_authentication", null) + unauthenticated_action = lookup(auth_settings_v2.value, "unauthenticated_action", "RedirectToLoginPage") + default_provider = lookup(auth_settings_v2.value, "default_provider", "azureactivedirectory") + excluded_paths = lookup(auth_settings_v2.value, "excluded_paths", null) + require_https = lookup(auth_settings_v2.value, "require_https", true) + http_route_api_prefix = lookup(auth_settings_v2.value, "http_route_api_prefix", "/.auth") + forward_proxy_convention = lookup(auth_settings_v2.value, "forward_proxy_convention", "ForwardProxyConventionNoProxy") + forward_proxy_custom_host_header_name = lookup(auth_settings_v2.value, "forward_proxy_custom_host_header_name", null) + forward_proxy_custom_scheme_header_name = lookup(auth_settings_v2.value, "forward_proxy_custom_scheme_header_name", null) + + dynamic "apple_v2" { + for_each = try(var.auth_settings_v2.apple_v2[*], []) + content { + client_id = lookup(apple_v2.value, "client_id", null) + client_secret_setting_name = lookup(apple_v2.value, "client_secret_setting_name", null) + } + } + + dynamic "active_directory_v2" { + for_each = try(var.auth_settings_v2.active_directory_v2[*], []) + + content { + client_id = lookup(active_directory_v2.value, "client_id", null) + tenant_auth_endpoint = lookup(active_directory_v2.value, "tenant_auth_endpoint", null) + client_secret_setting_name = lookup(active_directory_v2.value, "client_secret_setting_name", null) + client_secret_certificate_thumbprint = lookup(active_directory_v2.value, "client_secret_certificate_thumbprint", null) + jwt_allowed_groups = lookup(active_directory_v2.value, "jwt_allowed_groups", null) + jwt_allowed_client_applications = lookup(active_directory_v2.value, "jwt_allowed_client_applications", null) + www_authentication_disabled = lookup(active_directory_v2.value, "www_authentication_disabled", false) + allowed_groups = lookup(active_directory_v2.value, "allowed_groups", null) + allowed_identities = lookup(active_directory_v2.value, "allowed_identities", null) + allowed_applications = lookup(active_directory_v2.value, "allowed_applications", null) + login_parameters = lookup(active_directory_v2.value, "login_parameters", null) + } + } + + dynamic "azure_static_web_app_v2" { + for_each = try(var.auth_settings_v2.azure_static_web_app_v2[*], []) + content { + client_id = lookup(azure_static_web_app_v2.value, "client_id", null) + } + } + + dynamic "custom_oidc_v2" { + for_each = try(var.auth_settings_v2.custom_oidc_v2[*], []) + content { + name = lookup(custom_oidc_v2.value, "name", null) + client_id = lookup(custom_oidc_v2.value, "client_id", null) + openid_configuration_endpoint = lookup(custom_oidc_v2.value, "openid_configuration_endpoint", null) + name_claim_type = lookup(custom_oidc_v2.value, "name_claim_type", null) + scopes = lookup(custom_oidc_v2.value, "scopes", null) + client_credential_method = lookup(custom_oidc_v2.value, "client_credential_method", null) + client_secret_setting_name = lookup(custom_oidc_v2.value, "client_secret_setting_name", null) + authorisation_endpoint = lookup(custom_oidc_v2.value, "authorisation_endpoint", null) + token_endpoint = lookup(custom_oidc_v2.value, "token_endpoint", null) + issuer_endpoint = lookup(custom_oidc_v2.value, "issuer_endpoint", null) + certification_uri = lookup(custom_oidc_v2.value, "certification_uri", null) + } + } + + dynamic "facebook_v2" { + for_each = try(var.auth_settings_v2.facebook_v2[*], []) + content { + app_id = lookup(facebook_v2.value, "app_id", null) + app_secret_setting_name = lookup(facebook_v2.value, "app_secret_setting_name", null) + graph_api_version = lookup(facebook_v2.value, "graph_api_version", null) + login_scopes = lookup(facebook_v2.value, "login_scopes", null) + } + } + + dynamic "github_v2" { + for_each = try(var.auth_settings_v2.github_v2[*], []) + content { + client_id = lookup(github_v2.value, "client_id", null) + client_secret_setting_name = lookup(github_v2.value, "client_secret_setting_name", null) + login_scopes = lookup(github_v2.value, "login_scopes", null) + } + } + + dynamic "google_v2" { + for_each = try(var.auth_settings_v2.google_v2[*], []) + content { + client_id = lookup(google_v2.value, "client_id", null) + client_secret_setting_name = lookup(google_v2.value, "client_secret_setting_name", null) + allowed_audiences = lookup(google_v2.value, "allowed_audiences", null) + login_scopes = lookup(google_v2.value, "login_scopes", null) + } + } + + dynamic "microsoft_v2" { + for_each = try(var.auth_settings_v2.microsoft_v2[*], []) + content { + client_id = lookup(microsoft_v2.value, "client_id", null) + client_secret_setting_name = lookup(microsoft_v2.value, "client_secret_setting_name", null) + allowed_audiences = lookup(microsoft_v2.value, "allowed_audiences", null) + login_scopes = lookup(microsoft_v2.value, "login_scopes", null) + } + } + + dynamic "twitter_v2" { + for_each = try(var.auth_settings_v2.twitter_v2[*], []) + content { + consumer_key = lookup(twitter_v2.value, "consumer_key", null) + consumer_secret_setting_name = lookup(twitter_v2.value, "consumer_secret_setting_name", null) + } + } + + login { + logout_endpoint = lookup(local.auth_settings_v2_login, "logout_endpoint", null) + cookie_expiration_convention = lookup(local.auth_settings_v2_login, "cookie_expiration_convention", "FixedTime") + cookie_expiration_time = lookup(local.auth_settings_v2_login, "cookie_expiration_time", "08:00:00") + preserve_url_fragments_for_logins = lookup(local.auth_settings_v2_login, "preserve_url_fragments_for_logins", false) + token_refresh_extension_time = lookup(local.auth_settings_v2_login, "token_refresh_extension_time", 72) + token_store_enabled = lookup(local.auth_settings_v2_login, "token_store_enabled", false) + token_store_path = lookup(local.auth_settings_v2_login, "token_store_path", null) + token_store_sas_setting_name = lookup(local.auth_settings_v2_login, "token_store_sas_setting_name", null) + validate_nonce = lookup(local.auth_settings_v2_login, "validate_nonce", true) + nonce_expiration_time = lookup(local.auth_settings_v2_login, "nonce_expiration_time", "00:05:00") + } + } + } + + client_affinity_enabled = var.client_affinity_enabled + https_only = var.https_only + + dynamic "identity" { + for_each = var.identity[*] + content { + type = var.identity.type + identity_ids = var.identity.identity_ids + } } dynamic "storage_account" { - for_each = var.storage_mounts + for_each = var.mount_points content { - name = lookup(storage_account.value, "name") + name = lookup(storage_account.value, "name", format("%s-%s", storage_account.value["account_name"], storage_account.value["share_name"])) type = lookup(storage_account.value, "type", "AzureFiles") account_name = lookup(storage_account.value, "account_name", null) share_name = lookup(storage_account.value, "share_name", null) @@ -163,27 +791,94 @@ resource "azurerm_app_service" "main" { } } + dynamic "logs" { + for_each = var.app_service_logs == null ? [] : [var.app_service_logs] + content { + detailed_error_messages = lookup(logs.value, "detailed_error_messages", null) + failed_request_tracing = lookup(logs.value, "failed_request_tracing", null) + + dynamic "application_logs" { + for_each = lookup(logs.value, "application_logs", null) == null ? [] : ["application_logs"] + + content { + dynamic "azure_blob_storage" { + for_each = lookup(logs.value["application_logs"], "azure_blob_storage", null) == null ? [] : ["azure_blob_storage"] + content { + level = lookup(logs.value["application_logs"]["azure_blob_storage"], "level", null) + retention_in_days = lookup(logs.value["application_logs"]["azure_blob_storage"], "retention_in_days", null) + sas_url = lookup(logs.value["application_logs"]["azure_blob_storage"], "sas_url", null) + } + } + file_system_level = lookup(logs.value["application_logs"], "file_system_level", null) + } + } + + dynamic "http_logs" { + for_each = lookup(logs.value, "http_logs", null) == null ? [] : ["http_logs"] + content { + dynamic "azure_blob_storage" { + for_each = lookup(logs.value["http_logs"], "azure_blob_storage", null) == null ? [] : ["azure_blob_storage"] + content { + retention_in_days = lookup(logs.value["http_logs"]["azure_blob_storage"], "retention_in_days", null) + sas_url = lookup(logs.value["http_logs"]["azure_blob_storage"], "sas_url", null) + } + } + dynamic "file_system" { + for_each = lookup(logs.value["http_logs"], "file_system", null) == null ? [] : ["file_system"] + content { + retention_in_days = lookup(logs.value["http_logs"]["file_system"], "retention_in_days", null) + retention_in_mb = lookup(logs.value["http_logs"]["file_system"], "retention_in_mb", null) + } + } + } + } + } + } + + tags = module.labels.tags + lifecycle { ignore_changes = [ - tags, - site_config, - auth_settings, - storage_account, - identity, - connection_string, + app_settings, + site_config.0.cors, + site_config.0.ip_restriction_default_action, + site_config.0.scm_ip_restriction_default_action, + site_config.0.ftps_state ] } } -locals { - resource_group_name = var.resource_group_name - location = var.location - valid_rg_name = var.existing_private_dns_zone == null ? local.resource_group_name : (var.existing_private_dns_zone_resource_group_name == "" ? local.resource_group_name : var.existing_private_dns_zone_resource_group_name) - private_dns_zone_name = var.existing_private_dns_zone == null ? join("", azurerm_private_dns_zone.dnszone.*.name) : var.existing_private_dns_zone +##----------------------------------------------------------------------------- +## Application Insights +##----------------------------------------------------------------------------- + +data "azurerm_application_insights" "app_insights" { + count = var.application_insights_enabled && var.application_insights_id != null ? 1 : 0 + + name = split("/", var.application_insights_id)[8] + resource_group_name = split("/", var.application_insights_id)[4] +} + +resource "azurerm_application_insights" "app_insights" { + count = var.enable && var.application_insights_enabled && var.application_insights_id == null ? 1 : 0 + + name = format("%s-app-insights", module.labels.id) + location = var.location + resource_group_name = var.resource_group_name + application_type = var.application_insights_type + sampling_percentage = var.application_insights_sampling_percentage + retention_in_days = var.retention_in_days + disable_ip_masking = var.disable_ip_masking + tags = module.labels.tags + workspace_id = var.app_insights_workspace_id # Added log analytics workspace id from module in main using this variable app_insights_workspace_id } +##----------------------------------------------------------------------------- +## End Point +##----------------------------------------------------------------------------- + resource "azurerm_private_endpoint" "pep" { - count = var.enabled && var.enable_private_endpoint ? 1 : 0 + count = var.enable && var.enable_private_endpoint ? 1 : 0 name = format("%s-pe-app-service", module.labels.id) location = local.location resource_group_name = local.resource_group_name @@ -192,7 +887,7 @@ resource "azurerm_private_endpoint" "pep" { private_service_connection { name = format("%s-psc-app-service", module.labels.id) is_manual_connection = false - private_connection_resource_id = azurerm_app_service.main[0].id + private_connection_resource_id = azurerm_linux_web_app.main[0].id subresource_names = ["sites"] } @@ -204,21 +899,25 @@ resource "azurerm_private_endpoint" "pep" { } data "azurerm_private_endpoint_connection" "private-ip-0" { - count = var.enabled && var.enable_private_endpoint ? 1 : 0 + count = var.enable && var.enable_private_endpoint ? 1 : 0 name = join("", azurerm_private_endpoint.pep.*.name) resource_group_name = local.resource_group_name - depends_on = [azurerm_app_service.main] + depends_on = [azurerm_linux_web_app.main] } +##----------------------------------------------------------------------------- +## Dns Zone +##----------------------------------------------------------------------------- + resource "azurerm_private_dns_zone" "dnszone" { - count = var.enabled && var.existing_private_dns_zone == null && var.enable_private_endpoint ? 1 : 0 + count = var.enable && var.existing_private_dns_zone == null && var.enable_private_endpoint ? 1 : 0 name = "privatelink.azurewebsites.net" resource_group_name = local.resource_group_name tags = module.labels.tags } resource "azurerm_private_dns_zone_virtual_network_link" "vent-link" { - count = var.enabled && var.enable_private_endpoint && (var.existing_private_dns_zone != null ? (var.existing_private_dns_zone_resource_group_name == "" ? false : true) : true) ? 1 : 0 + count = var.enable && var.enable_private_endpoint && (var.existing_private_dns_zone != null ? (var.existing_private_dns_zone_resource_group_name == "" ? false : true) : true) ? 1 : 0 name = var.existing_private_dns_zone == null ? format("%s-pdz-vnet-link-app-service", module.labels.id) : format("%s-pdz-vnet-link-app-service-1", module.labels.id) resource_group_name = local.valid_rg_name private_dns_zone_name = local.private_dns_zone_name @@ -226,29 +925,62 @@ resource "azurerm_private_dns_zone_virtual_network_link" "vent-link" { tags = module.labels.tags } -# App Insights +##----------------------------------------------------------------------------- +## Telemetry +##----------------------------------------------------------------------------- -data "azurerm_application_insights" "main" { - count = var.application_insights_enabled && var.application_insights_id != null ? 1 : 0 - name = split("/", var.application_insights_id)[8] - resource_group_name = split("/", var.application_insights_id)[4] +resource "azurerm_application_insights_api_key" "read_telemetry" { + name = format("%s-app-insights-api-key", module.labels.id) + application_insights_id = azurerm_application_insights.app_insights[0].id + read_permissions = var.read_permissions } -resource "azurerm_application_insights" "main" { - count = var.application_insights_enabled && var.application_insights_id == null ? 1 : 0 - name = lower(format("app-insights-%s", var.app_insights_name)) - location = var.location - resource_group_name = var.resource_group_name - application_type = var.application_insights_type - retention_in_days = var.retention_in_days - disable_ip_masking = var.disable_ip_masking - tags = merge({ "ResourceName" = "${var.app_insights_name}" }, module.labels.tags, ) -} - -# VNET integration +##----------------------------------------------------------------------------- +## Vnet Integration +##----------------------------------------------------------------------------- resource "azurerm_app_service_virtual_network_swift_connection" "main" { count = var.enable_vnet_integration == true ? 1 : 0 - app_service_id = azurerm_app_service.main[0].id + app_service_id = azurerm_linux_web_app.main[0].id subnet_id = var.integration_subnet_id } + +##----------------------------------------------------------------------------- +## Diagnostic settings +##----------------------------------------------------------------------------- + +resource "azurerm_monitor_diagnostic_setting" "diagnostic" { + count = var.enable && var.enable_diagnostic ? 1 : 0 + name = format("%s-diagnostic-log", module.labels.id) + target_resource_id = var.enable && var.os_type == "Linux" ? azurerm_linux_web_app.main[0].id : azurerm_windows_web_app.main[0].id # Added condition for both linux and windows + log_analytics_workspace_id = var.log_analytics_workspace_id + storage_account_id = var.storage_account_id + eventhub_name = var.eventhub_name + eventhub_authorization_rule_id = var.eventhub_authorization_rule_id + log_analytics_destination_type = var.log_analytics_destination_type + dynamic "enabled_log" { + for_each = var.log_category + content { + category = enabled_log.value + } + } + + dynamic "metric" { + for_each = var.metric_enabled ? ["AllMetrics"] : [] + content { + category = metric.value + enabled = true + } + } +} + +##----------------------------------------------------------------------------- +## Acr Role assignment +##----------------------------------------------------------------------------- +resource "azurerm_role_assignment" "acr_pull" { + count = var.enable && var.use_docker && var.site_config.container_registry_use_managed_identity == true ? 1 : 0 + principal_id = var.enable && var.os_type == "Linux" ? azurerm_linux_web_app.main[0].identity.0.principal_id : azurerm_windows_web_app.main[0].identity.0.principal_id # Updated Condition + role_definition_name = "AcrPull" + scope = var.acr_id + skip_service_principal_aad_check = true +} \ No newline at end of file diff --git a/outputs.tf b/outputs.tf index ec2c94c..bdc8d20 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,54 +1,44 @@ output "service_plan_id" { - value = azurerm_app_service_plan.main.id description = "The ID of the App Service Plan component." + value = azurerm_service_plan.main[*].id } -output "maximum_number_of_workers" { - value = azurerm_app_service_plan.main.maximum_number_of_workers - description = "The maximum number of workers supported with the App Service Plan's sku." +output "service_plan_name" { + description = "The Name of the App Service Plan component." + value = azurerm_service_plan.main[*].name } -output "id" { - value = azurerm_app_service.main[0].id - description = "The ID of the App Service." +output "service_plan_location" { + description = "Azure location of the created Service Plan" + value = azurerm_service_plan.main[*].location } -output "custom_domain_verification_id" { - value = azurerm_app_service.main[0].custom_domain_verification_id - description = "An identifier used by App Service to perform domain ownership verification via DNS TXT record." +output "app_service_id" { + description = "Id of the App Service" + value = azurerm_linux_web_app.main[*].id } -output "default_site_hostname" { - value = azurerm_app_service.main[0].default_site_hostname - description = "The Default Hostname associated with the App Service - such as mysite.azurewebsites.net" +output "app_service_name" { + description = "Name of the App Service" + value = azurerm_linux_web_app.main[*].name } -output "outbound_ip_addresses" { - value = azurerm_app_service.main[0].outbound_ip_addresses - description = "A comma separated list of outbound IP addresses - such as 52.23.25.3,52.143.43.12" +output "app_service_default_site_hostname" { + description = "The Default Hostname associated with the App Service" + value = azurerm_linux_web_app.main[*].default_hostname } -output "outbound_ip_address_list" { - value = join("", azurerm_app_service.main[0].outbound_ip_address_list) - description = "A list of outbound IP addresses - such as ['52.23.25.3', '52.143.43.12']" +output "app_service_outbound_ip_addresses" { + description = "Outbound IP adresses of the App Service" + value = join("", azurerm_linux_web_app.main[*].outbound_ip_addresses) } -output "possible_outbound_ip_addresses" { - value = azurerm_app_service.main[0].possible_outbound_ip_addresses - description = "A comma separated list of outbound IP addresses - such as 52.23.25.3,52.143.43.12,52.143.43.17 - not all of which are necessarily in use. Superset of outbound_ip_addresses" +output "app_service_possible_outbound_ip_addresses" { + description = "Possible outbound IP adresses of the App Service" + value = join("", azurerm_linux_web_app.main[*].possible_outbound_ip_addresses) } -output "possible_outbound_ip_address_list" { - value = join("", azurerm_app_service.main[0].possible_outbound_ip_address_list) - description = "A list of outbound IP addresses - such as ['52.23.25.3', '52.143.43.12', '52.143.43.17'] - not all of which are necessarily in use. Superset of outbound_ip_address_list" +output "app_service_site_credential" { + description = "Site credential block of the App Service" + value = azurerm_linux_web_app.main[*].site_credential } - -output "source_control" { - value = azurerm_app_service.main[0].source_control - description = "A source_control block as defined below, which contains the Source Control information when scm_type is set to LocalGit." -} - -output "site_credential" { - value = azurerm_app_service.main[0].site_credential - description = "A site_credential block as defined below, which contains the site-level credentials used to publish to this App Service." -} \ No newline at end of file diff --git a/variables.tf b/variables.tf index 330c461..6baba91 100644 --- a/variables.tf +++ b/variables.tf @@ -20,7 +20,7 @@ variable "repository" { variable "label_order" { type = list(any) - default = [] + default = ["name", "environment", ] description = "Label order, e.g. sequence of application name and environment `name`,`environment`,'attribute' [`webserver`,`qa`,`devops`,`public`,] ." } @@ -30,12 +30,24 @@ variable "managedby" { description = "ManagedBy, eg ''." } -variable "enabled" { +variable "enable" { type = bool description = "Set to false to prevent the module from creating any resources." default = true } +variable "app_service_linux" { + type = bool + description = "Set to false to prevent the module from creating any linux web app resources." + default = false +} + +variable "app_service_linux_container" { + type = bool + description = "Set to false to prevent the module from creating any linux web app resources." + default = false +} + variable "resource_group_name" { type = string default = "" @@ -58,107 +70,360 @@ variable "tags" { # APP SERVICE PLAN -variable "service_plan" { - description = "Definition of the dedicated plan to use" - type = object({ - kind = string - size = string - capacity = optional(number) - tier = string - per_site_scaling = optional(bool) - }) +variable "os_type" { + description = "The O/S type for the App Services to be hosted in this plan. Possible values include `Windows`, `Linux`, and `WindowsContainer`." + type = string + + validation { + condition = try(contains(["Windows", "Linux", "WindowsContainer"], var.os_type), true) + error_message = "The `os_type` value must be valid. Possible values are `Windows`, `Linux`, and `WindowsContainer`." + } +} + +variable "sku_name" { + description = "The SKU for the plan. Possible values include B1, B2, B3, D1, F1, FREE, I1, I2, I3, I1v2, I2v2, I3v2, P1v2, P2v2, P3v2, P1v3, P2v3, P3v3, S1, S2, S3, SHARED, Y1, EP1, EP2, EP3, WS1, WS2, and WS3." + type = string + + validation { + condition = try(contains(["B1", "B2", "B3", "D1", "F1", "FREE", "I1", "I2", "I3", "I1v2", "I2v2", "I3v2", "P1v2", "P2v2", "P3v2", "P1v3", "P2v3", "P3v3", "S1", "S2", "S3", "SHARED", "Y1", "EP1", "EP2", "EP3", "WS1", "WS2", "WS3"], var.sku_name), true) + error_message = "The `sku_name` value must be valid. Possible values include B1, B2, B3, D1, F1, FREE, I1, I2, I3, I1v2, I2v2, I3v2, P1v2, P2v2, P3v2, P1v3, P2v3, P3v3, S1, S2, S3, SHARED, Y1, EP1, EP2, EP3, WS1, WS2, and WS3." + } +} + +variable "app_service_environment_id" { + description = "The ID of the App Service Environment to create this Service Plan in. Requires an Isolated SKU. Use one of I1, I2, I3 for azurerm_app_service_environment, or I1v2, I2v2, I3v2 for azurerm_app_service_environment_v3" + type = string + default = null +} + +variable "worker_count" { + description = "The number of Workers (instances) to be allocated." + type = number + default = 1 +} + +variable "maximum_elastic_worker_count" { + description = "The maximum number of workers to use in an Elastic SKU Plan. Cannot be set unless using an Elastic SKU." + type = number + default = null +} + +variable "per_site_scaling_enabled" { + description = "Should Per Site Scaling be enabled." + type = bool + default = false } -variable "ips_allowed" { - description = "IPs restriction for App Service to allow specific IP addresses or ranges" +variable "public_network_access_enabled" { + description = "Whether enable public access for the App Service." + type = bool + default = true +} + +variable "app_service_vnet_integration_subnet_id" { + description = "Id of the subnet to associate with the app service" + type = string + default = null +} + +variable "site_config" { + description = "Site config for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#site_config. IP restriction attribute is no more managed in this block." + type = any + default = {} +} + +variable "authorized_subnet_ids" { + description = "Subnets restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#ip_restriction" + type = list(string) + default = [] +} + +variable "ip_restriction_headers" { + description = "IPs restriction headers for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#headers" + type = map(list(string)) + default = null +} + +variable "authorized_ips" { + description = "IPs restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#ip_restriction" type = list(string) default = [] } -variable "subnet_ids_allowed" { - description = "Allow Specific Subnets for App Service" +variable "authorized_service_tags" { + description = "Service Tags restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#ip_restriction" type = list(string) default = [] } -# APP SERVICE +variable "scm_authorized_subnet_ids" { + description = "SCM subnets restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#scm_ip_restriction" + type = list(string) + default = [] +} -variable "app_service_name" { - description = "Specifies the name of the App Service." - default = "" +variable "scm_ip_restriction_headers" { + description = "IPs restriction headers for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#headers" + type = map(list(string)) + default = null } -variable "app_settings" { - description = "A key-value pair of App Settings." +variable "scm_authorized_ips" { + description = "SCM IPs restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#scm_ip_restriction" + type = list(string) + default = [] +} + +variable "scm_authorized_service_tags" { + description = "SCM Service Tags restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#scm_ip_restriction" + type = list(string) + default = [] +} + +variable "staging_slot_custom_app_settings" { type = map(string) - default = {} + description = "Override staging slot with custom app settings" + default = null } -variable "enable_client_affinity" { - description = "Should the App Service send session affinity cookies, which route client requests in the same session to the same instance?" - default = false +variable "docker_image_name" { + type = string + default = "" + description = "The docker image, including tag, to be used. e.g. appsvc/staticsite:latest." } -variable "enable_https" { - description = "Can the App Service only be accessed via HTTPS?" - default = false +variable "docker_registry_url" { + type = string + default = "" + description = "The URL of the container registry where the docker_image_name is located. e.g. https://index.docker.io or https://mcr.microsoft.com. This value is required with docker_image_name" } -variable "enable_client_certificate" { - description = "Does the App Service require client certificates for incoming requests" - default = false +variable "docker_registry_username" { + type = string + default = null + description = "The User Name to use for authentication against the registry to pull the image." } -variable "site_config" { - description = "Site configuration for Application Service" - type = any - default = {} +variable "docker_registry_password" { + type = string + default = null + description = "The User Name to use for authentication against the registry to pull the image." } -variable "enable_auth_settings" { - description = "Specifies the Authenication enabled or not" - default = false +variable "dotnet_version" { + type = string + default = null + description = "dotnet version" } -variable "default_auth_provider" { - description = "The default provider to use when multiple providers have been set up. Possible values are `AzureActiveDirectory`, `Facebook`, `Google`, `MicrosoftAccount` and `Twitter`" - default = "AzureActiveDirectory" +variable "java_server" { + type = string + default = null + description = "Java server" } -variable "unauthenticated_client_action" { - description = "The action to take when an unauthenticated client attempts to access the app. Possible values are `AllowAnonymous` and `RedirectToLoginPage`" - default = "RedirectToLoginPage" +variable "java_server_version" { + type = string + default = null + description = "Java server version" } -variable "token_store_enabled" { - description = "If enabled the module will durably store platform-specific security tokens that are obtained during login flows" - default = false +variable "java_version" { + type = string + default = null + description = "Java version" } -variable "active_directory_auth_setttings" { - description = "Acitve directory authentication provider settings for app service" - type = any +variable "node_version" { + type = string + default = null + description = "Node version" +} + +variable "php_version" { + type = string + default = null + description = "php version" +} + +variable "python_version" { + type = string + default = null + description = "Python version" +} + +variable "ruby_version" { + type = string + default = null + description = "Ruby version" +} + +variable "application_insights_enabled" { + description = "Use Application Insights for this App Service" + type = bool + default = true +} + +variable "app_settings" { + description = "Application settings for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#app_settings" + type = map(string) default = {} } variable "connection_strings" { - description = "Connection strings for App Service" + description = "Connection strings for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#connection_string" type = list(map(string)) default = [] } -variable "identity_ids" { - description = "Specifies a list of user managed identity ids to be assigned" - default = null +variable "auth_settings" { + description = "Authentication settings. Issuer URL is generated thanks to the tenant ID. For active_directory block, the allowed_audiences list is filled with a value generated with the name of the App Service. See https://www.terraform.io/docs/providers/azurerm/r/app_service.html#auth_settings" + type = any + default = {} } -variable "storage_mounts" { - description = "Storage account mount points for App Service" +variable "auth_settings_v2" { + description = "Authentication settings V2. See https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_web_app#auth_settings_v2" + type = any + default = {} +} + +variable "client_affinity_enabled" { + description = "Client affinity activation for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#client_affinity_enabled" + type = bool + default = false +} + +variable "https_only" { + description = "HTTPS restriction for App Service. See documentation https://www.terraform.io/docs/providers/azurerm/r/app_service.html#https_only" + type = bool + default = false +} + +variable "mount_points" { + description = "Storage Account mount points. Name is generated if not set and default type is AzureFiles. See https://www.terraform.io/docs/providers/azurerm/r/app_service.html#storage_account" type = list(map(string)) default = [] } -# Private Endpoint +variable "app_service_logs" { + description = "Configuration of the App Service and App Service Slot logs. Documentation [here](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_web_app#logs)" + type = object({ + detailed_error_messages = optional(bool) + failed_request_tracing = optional(bool) + application_logs = optional(object({ + file_system_level = string + azure_blob_storage = optional(object({ + level = string + retention_in_days = number + sas_url = string + })) + })) + http_logs = optional(object({ + azure_blob_storage = optional(object({ + retention_in_days = number + sas_url = string + })) + file_system = optional(object({ + retention_in_days = number + retention_in_mb = number + })) + })) + }) + default = null +} + +variable "identity" { + description = "Map with identity block information." + type = object({ + type = string + identity_ids = list(string) + }) + default = { + type = "SystemAssigned" + identity_ids = [] + } +} + +variable "application_insights_id" { + description = "ID of the existing Application Insights to use instead of deploying a new one." + type = string + default = null +} + +variable "application_insights_type" { + description = "Application type for Application Insights resource" + type = string + default = "web" +} + +variable "application_insights_sampling_percentage" { + description = "Specifies the percentage of sampled datas for Application Insights. Documentation [here](https://docs.microsoft.com/en-us/azure/azure-monitor/app/sampling#ingestion-sampling)" + type = number + default = null +} + +variable "acr_id" { + type = string + default = null + description = "Container registry id to give access to pull images" +} + +variable "enable_diagnostic" { + type = bool + default = true + description = "Set to false to prevent the module from creating any resources." +} + +variable "log_analytics_workspace_id" { + type = string + default = null + description = "Log Analytics workspace id in which logs should be retained." +} + +variable "metric_enabled" { + type = bool + default = true + description = "Whether metric diagnonsis should be enable in diagnostic settings for flexible Mysql." +} + +variable "log_category" { + type = list(string) + default = ["AppServiceHTTPLogs", "AppServiceConsoleLogs", "AppServiceAuditLogs", "AppServiceAppLogs", "AppServicePlatformLogs"] + description = "Categories of logs to be recorded in diagnostic setting." +} + +variable "log_analytics_destination_type" { + type = string + default = null + description = "Possible values are AzureDiagnostics and Dedicated, default to AzureDiagnostics. When set to Dedicated, logs sent to a Log Analytics workspace will go into resource specific tables, instead of the legacy AzureDiagnostics table." +} + +variable "storage_account_id" { + type = string + default = null + description = "Storage account id to pass it to destination details of diagnosys setting of NSG." +} + +variable "eventhub_name" { + type = string + default = null + description = "Eventhub Name to pass it to destination details of diagnosys setting of NSG." +} + +variable "eventhub_authorization_rule_id" { + type = string + default = null + description = "Eventhub authorization rule id to pass it to destination details of diagnosys setting of NSG." +} + +variable "is_linux_webapp" { + description = "Enable linux web app" + type = bool + default = true +} + +# # Private Endpoint variable "virtual_network_id" { type = string @@ -190,7 +455,7 @@ variable "existing_private_dns_zone_resource_group_name" { description = "The name of the existing resource group" } -## Addon vritual link +# ## Addon vritual link variable "addon_vent_link" { type = bool default = false @@ -209,27 +474,6 @@ variable "addon_virtual_network_id" { description = "The name of the addon vnet link vnet id" } -# app insights -variable "application_insights_enabled" { - description = "Specify the Application Insights use for this App Service" - default = true -} - -variable "application_insights_id" { - description = "Resource ID of the existing Application Insights" - default = null -} - -variable "app_insights_name" { - description = "The Name of the application insights" - default = "" -} - -variable "application_insights_type" { - description = "Specifies the type of Application Insights to create. Valid values are `ios` for iOS, `java` for Java web, `MobileCenter` for App Center, `Node.JS` for Node.js, `other` for General, `phone` for Windows Phone, `store` for Windows Store and `web` for ASP.NET." - default = "web" -} - variable "retention_in_days" { description = "Specifies the retention period in days. Possible values are `30`, `60`, `90`, `120`, `180`, `270`, `365`, `550` or `730`" default = 90 @@ -249,4 +493,90 @@ variable "integration_subnet_id" { type = string default = null description = "The resource ID of the subnet" +} + +variable "app_insights_workspace_id" { + type = string + default = null +} + +variable "read_permissions" { + type = list(string) + default = ["aggregate", "api", "draft", "extendqueries", "search"] +} + +variable "use_docker" { + type = bool + default = false +} + +variable "use_dotnet" { + type = bool + default = false +} + +variable "use_php" { + type = bool + default = false +} + +variable "use_python" { + type = bool + default = false +} + +variable "use_node" { + type = bool + default = false +} + +variable "use_java" { + type = bool + default = false +} + +variable "use_ruby" { + type = bool + default = false +} + +variable "use_current_stack" { + type = bool + default = true +} + +variable "current_stack" { + type = string + default = null + # Possible values -> dotnet, dotnetcore, node, python, php, and java +} + +variable "java_embedded_server_enabled" { + type = string + default = null +} + +variable "use_tomcat" { + type = bool + default = false +} + +variable "tomcat_version" { + type = string + default = null +} + +variable "dotnet_core_version" { + type = string + default = null +} + +variable "use_go" { + type = bool + default = false +} + +variable "go_version" { + type = string + default = null } \ No newline at end of file diff --git a/versions.tf b/versions.tf index 3a62915..c3d7de8 100644 --- a/versions.tf +++ b/versions.tf @@ -1,12 +1,12 @@ terraform { - required_version = ">= 1.3.6" + required_version = ">= 1.9.0" } terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = ">=3.0.0" + version = ">=3.109.0" } } } \ No newline at end of file