├── README.md ├── infra ├── altinn-digdir-oed-rg │ ├── data.tf │ ├── rg.tf │ ├── alert.tf │ ├── service-plan.tf │ ├── providers.tf │ ├── ai.tf │ ├── servicebus.tf │ ├── kv.tf │ ├── network.tf │ ├── whitelist.tf │ ├── storage.tf │ ├── terraform.tfvars │ ├── variables.tf │ ├── function-feedpoller.tf │ ├── web-app-authz.tf │ ├── entra-id.tf │ ├── database.tf │ ├── frontdoor_waf.tf │ ├── web-app-admin.tf │ └── dashboard.tf ├── altinn-digdir-oed-tt02-rg │ ├── data.tf │ ├── rg.tf │ ├── random.tf │ ├── alert.tf │ ├── providers.tf │ ├── service-plan.tf │ ├── servicebus.tf │ ├── whitelist.tf │ ├── network.tf │ ├── kv.tf │ ├── storage.tf │ ├── terraform.tfvars │ ├── ai.tf │ ├── variables.tf │ ├── function-feedpoller.tf │ ├── frontdoor_waf.tf │ ├── web-app-testapp.tf │ ├── web-app-authz.tf │ ├── entra-id.tf │ ├── database.tf │ ├── web-app-admin.tf │ └── dashboard.tf └── test │ ├── terraform.aztfexport.tf │ ├── provider.aztfexport.tf │ ├── aztfexportResourceMapping.json │ ├── .terraform.lock.hcl │ ├── main.aztfexport.tf │ └── main.tf ├── LICENSE ├── .gitignore └── .github └── workflows ├── altinn-digdir-oed-rg.yml └── altinn-digdir-oed-tt02-rg.yml /README.md: -------------------------------------------------------------------------------- 1 | # dd-infrastructure 2 | Infrastructure repo for digitalt dødsbo 3 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/data.tf: -------------------------------------------------------------------------------- 1 | data "azurerm_client_config" "current" { 2 | } 3 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/data.tf: -------------------------------------------------------------------------------- 1 | data "azurerm_client_config" "current" { 2 | } 3 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/rg.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_resource_group" "rg" { 2 | location = var.rg_location 3 | name = var.rg_name 4 | } 5 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/rg.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_resource_group" "rg" { 2 | location = var.rg_location 3 | name = var.rg_name 4 | } 5 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/random.tf: -------------------------------------------------------------------------------- 1 | # Generate a random integer to create a globally unique name 2 | resource "random_integer" "ri" { 3 | min = 10000 4 | max = 99999 5 | } 6 | -------------------------------------------------------------------------------- /infra/test/terraform.aztfexport.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "local" {} 3 | 4 | required_providers { 5 | azurerm = { 6 | source = "hashicorp/azurerm" 7 | version = "4.16.0" 8 | 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/alert.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_monitor_action_group" "email_ag" { 2 | name = "DD-email-notification-prod-ag" 3 | resource_group_name = azurerm_resource_group.rg.name 4 | short_name = "E-mail DD-p" 5 | email_receiver { 6 | email_address = var.support_email 7 | name = "send-to-EmailAction" 8 | } 9 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/alert.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_monitor_action_group" "email_ag" { 2 | name = "DD-email-notification-test-ag" 3 | resource_group_name = azurerm_resource_group.rg.name 4 | short_name = "E-mail DD-T" 5 | email_receiver { 6 | email_address = var.support_email 7 | name = "send-to-EmailAction" 8 | } 9 | } -------------------------------------------------------------------------------- /infra/test/provider.aztfexport.tf: -------------------------------------------------------------------------------- 1 | provider "azurerm" { 2 | features { 3 | } 4 | subscription_id = "7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103" 5 | environment = "public" 6 | use_msi = false 7 | use_cli = true 8 | use_oidc = false 9 | resource_provider_registrations = "none" 10 | } 11 | -------------------------------------------------------------------------------- /infra/test/aztfexportResourceMapping.json: -------------------------------------------------------------------------------- 1 | { 2 | "/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/Microsoft.Web/sites/dd-test-admin-app": { 3 | "resource_id": "/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/Microsoft.Web/sites/dd-test-admin-app", 4 | "resource_type": "azurerm_linux_web_app", 5 | "resource_name": "res-0" 6 | } 7 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/service-plan.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_service_plan" "feedpoller" { 2 | name = "ASP-altinndigdiroed-feedpoller" 3 | location = azurerm_resource_group.rg.location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | os_type = "Windows" 6 | sku_name = "EP1" 7 | worker_count = 1 8 | } 9 | 10 | resource "azurerm_service_plan" "authz_linux" { 11 | name = "ASP-altinndigdiroed-authz-linux" 12 | location = azurerm_resource_group.rg.location 13 | resource_group_name = azurerm_resource_group.rg.name 14 | os_type = "Linux" 15 | sku_name = "P0v3" 16 | worker_count = 1 17 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = "~> 4.0" 6 | } 7 | azuread = { 8 | source = "hashicorp/azuread" 9 | version = "~> 3.6.0" 10 | } 11 | random = { 12 | source = "hashicorp/random" 13 | version = "~> 3.0" 14 | } 15 | } 16 | backend "azurerm" { 17 | use_azuread_auth = true 18 | } 19 | } 20 | 21 | provider "azurerm" { 22 | subscription_id = var.subscription_id 23 | features {} 24 | resource_providers_to_register = [ 25 | "Microsoft.Monitor", 26 | "Microsoft.AlertsManagement", 27 | "Microsoft.Dashboard", 28 | "Microsoft.KubernetesConfiguration" 29 | ] 30 | } 31 | provider "azuread" { 32 | tenant_id = var.tenant_id 33 | } 34 | provider "random" {} 35 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = "~> 4.0" 6 | } 7 | azuread = { 8 | source = "hashicorp/azuread" 9 | version = "~> 3.6.0" 10 | } 11 | random = { 12 | source = "hashicorp/random" 13 | version = "~> 3.0" 14 | } 15 | } 16 | backend "azurerm" { 17 | use_azuread_auth = true 18 | } 19 | } 20 | 21 | provider "azurerm" { 22 | subscription_id = var.subscription_id 23 | features {} 24 | resource_providers_to_register = [ 25 | "Microsoft.Monitor", 26 | "Microsoft.AlertsManagement", 27 | "Microsoft.Dashboard", 28 | "Microsoft.KubernetesConfiguration" 29 | ] 30 | } 31 | 32 | provider "azuread" { 33 | tenant_id = var.tenant_id 34 | } 35 | 36 | provider "random" {} 37 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/service-plan.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_service_plan" "feedpoller" { 2 | name = "ASP-altinndigdiroedtt02rg-9144" 3 | location = var.alt_location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | os_type = "Windows" 6 | sku_name = "EP1" 7 | worker_count = 1 8 | tags = { 9 | costcenter = "altinn3" 10 | solution = "apps" 11 | } 12 | } 13 | 14 | resource "azurerm_service_plan" "authz_linux" { 15 | name = "ASP-altinndigdiroedtt02rg-${random_integer.ri.result}" 16 | location = var.alt_location 17 | resource_group_name = azurerm_resource_group.rg.name 18 | os_type = "Linux" 19 | sku_name = "B2" 20 | worker_count = 1 21 | tags = { 22 | costcenter = "altinn3" 23 | solution = "apps" 24 | } 25 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Altinn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | crash.*.log 11 | 12 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 13 | # password, private keys, and other secrets. These should not be part of version 14 | # control as they are data points which are potentially sensitive and subject 15 | # to change depending on the environment. 16 | #*.tfvars 17 | #*.tfvars.json 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Ignore transient lock info files created by terraform apply 27 | .terraform.tfstate.lock.info 28 | 29 | # Include override files you do wish to add to version control using negated pattern 30 | # !example_override.tf 31 | 32 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 33 | # example: *tfplan* 34 | 35 | # Ignore CLI configuration files 36 | .terraformrc 37 | terraform.rc 38 | 39 | # Ignore Visual Studio Code files 40 | .vs 41 | -------------------------------------------------------------------------------- /infra/test/.terraform.lock.hcl: -------------------------------------------------------------------------------- 1 | # This file is maintained automatically by "terraform init". 2 | # Manual edits may be lost in future updates. 3 | 4 | provider "registry.terraform.io/hashicorp/azurerm" { 5 | version = "4.16.0" 6 | constraints = "4.16.0" 7 | hashes = [ 8 | "h1:HZdmFPnC/+x6si15pq4rGYv/1TrCcyQXLnDMqq1SONw=", 9 | "zh:2035e461a94bd4180557a06f8e56f228a8a035608d0dac4d08e5870cf9265276", 10 | "zh:3f15778a22ef1b9d0fa28670e5ea6ef1094b0be2533f43f350a2ef15d471b353", 11 | "zh:4f1a4d03b008dd958bcd6bf82cf088fbaa9c121be2fd35e10e6b06c6e8f6aaa1", 12 | "zh:5859f31c342364e849b4f8c437a46f33e927fa820244d0732b8d2ec74a95712d", 13 | "zh:693d0f15512ca8c6b5e999b3a7551503feb06b408b3836bc6a6403e518b9ddab", 14 | "zh:7f4912bec5b04f5156935292377c12484c13582151eb3c2555df409a7e5fb6e0", 15 | "zh:bb9a509497f3a131c52fac32348919bf1b9e06c69a65f24607b03f7b56fb47b6", 16 | "zh:c1b0c64e49ac591fd038ad71e71403ff71c07476e27e8da718c29f0028ea6d0d", 17 | "zh:dd4ca432ee14eb0bb0cdc0bb463c8675b8ef02497be870a20d8dfee3e7fe52b3", 18 | "zh:df58bb7fea984d2b11709567842ca4d55b3f24e187aa6be99e3677f55cbbe7da", 19 | "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", 20 | "zh:f7fb37704da50c096f9c7c25e8a95fe73ce1d3c5aab0d616d506f07bc5cfcdd8", 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/ai.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_log_analytics_workspace" "law" { 2 | name = "altinn-digdir-oed-law" 3 | location = azurerm_resource_group.rg.location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | retention_in_days = 30 6 | } 7 | 8 | resource "azurerm_application_insights" "feedpoller" { 9 | name = "oed-feedpoller-ai" 10 | location = azurerm_resource_group.rg.location 11 | resource_group_name = azurerm_resource_group.rg.name 12 | application_type = "web" 13 | workspace_id = azurerm_log_analytics_workspace.law.id 14 | disable_ip_masking = true 15 | } 16 | 17 | resource "azurerm_application_insights" "authz_ai" { 18 | name = "oed-authz-ai" 19 | location = azurerm_resource_group.rg.location 20 | resource_group_name = azurerm_resource_group.rg.name 21 | application_type = "web" 22 | workspace_id = azurerm_log_analytics_workspace.law.id 23 | disable_ip_masking = true 24 | } 25 | 26 | resource "azurerm_application_insights" "adminapp_ai" { 27 | name = "dd-${var.environment}-adminapp-ai" 28 | location = azurerm_resource_group.rg.location 29 | resource_group_name = azurerm_resource_group.rg.name 30 | application_type = "web" 31 | workspace_id = azurerm_log_analytics_workspace.law.id 32 | disable_ip_masking = true 33 | sampling_percentage = 100 34 | tags = { 35 | "costcenter" = "altinn3" 36 | "solution" = "apps" 37 | } 38 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/servicebus.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_servicebus_namespace" "dd_sb_ns" { 2 | name = "dd-${var.environment}-sbn" 3 | location = azurerm_resource_group.rg.location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | sku = "Standard" 6 | tags = { 7 | costcenter = "altinn3" 8 | solution = "apps" 9 | } 10 | network_rule_set { 11 | default_action = "Deny" 12 | public_network_access_enabled = true 13 | trusted_services_allowed = true 14 | ip_rules = local.whitelist_array 15 | } 16 | } 17 | 18 | # Gi full topic/subscription access til authz 19 | resource "azurerm_role_assignment" "sb_authz_ra" { 20 | scope = azurerm_servicebus_namespace.dd_sb_ns.id 21 | role_definition_name = "Azure Service Bus Data Owner" 22 | principal_id = azurerm_linux_web_app.authz_linux.identity[0].principal_id 23 | } 24 | 25 | # Gi full topic/subscription access til feedpoller function app 26 | resource "azurerm_role_assignment" "sb_feedpoller_ra" { 27 | scope = azurerm_servicebus_namespace.dd_sb_ns.id 28 | role_definition_name = "Azure Service Bus Data Owner" 29 | principal_id = azurerm_windows_function_app.feedpoller.identity[0].principal_id 30 | } 31 | 32 | data "azuread_application" "kv_sp" { 33 | display_name = var.a3_sp_app_name 34 | } 35 | 36 | data "azuread_service_principal" "aks_sp" { 37 | client_id = data.azuread_application.kv_sp.client_id 38 | } 39 | 40 | resource "azurerm_role_assignment" "sb_aks_ra" { 41 | scope = azurerm_servicebus_namespace.dd_sb_ns.id 42 | role_definition_name = "Azure Service Bus Data Owner" 43 | principal_id = data.azuread_service_principal.aks_sp.object_id 44 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/servicebus.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_servicebus_namespace" "dd_sb_ns" { 2 | name = "dd-${var.environment}-sbn" 3 | location = azurerm_resource_group.rg.location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | sku = "Standard" 6 | tags = { 7 | costcenter = "altinn3" 8 | solution = "apps" 9 | } 10 | network_rule_set { 11 | default_action = "Deny" 12 | public_network_access_enabled = true 13 | trusted_services_allowed = true 14 | ip_rules = local.whitelist_array 15 | } 16 | } 17 | 18 | # Gi full topic/subscription access til authz 19 | resource "azurerm_role_assignment" "sb_authz_ra" { 20 | scope = azurerm_servicebus_namespace.dd_sb_ns.id 21 | role_definition_name = "Azure Service Bus Data Owner" 22 | principal_id = azurerm_linux_web_app.authz_linux.identity[0].principal_id 23 | } 24 | 25 | # Gi full topic/subscription access til feedpoller function app 26 | resource "azurerm_role_assignment" "sb_feedpoller_ra" { 27 | scope = azurerm_servicebus_namespace.dd_sb_ns.id 28 | role_definition_name = "Azure Service Bus Data Owner" 29 | principal_id = azurerm_windows_function_app.feedpoller.identity[0].principal_id 30 | } 31 | 32 | data "azuread_application" "kv_sp" { 33 | display_name = var.a3_sp_app_name 34 | } 35 | 36 | data "azuread_service_principal" "aks_sp" { 37 | client_id = data.azuread_application.kv_sp.client_id 38 | } 39 | 40 | resource "azurerm_role_assignment" "sb_aks_ra" { 41 | scope = azurerm_servicebus_namespace.dd_sb_ns.id 42 | role_definition_name = "Azure Service Bus Data Owner" 43 | principal_id = data.azuread_service_principal.aks_sp.object_id 44 | } -------------------------------------------------------------------------------- /infra/test/main.aztfexport.tf: -------------------------------------------------------------------------------- 1 | # Should be deleted? The file is still here because its a resource that was imported into terraform 2 | # Should atleast change the email address to the another one 3 | resource "azurerm_monitor_action_group" "res-0" { 4 | name = "DD-email-notification-ag" 5 | resource_group_name = "altinn-digdir-oed-tt02-rg" 6 | short_name = "E-mail DD" 7 | email_receiver { 8 | email_address = "kurt.monge@digdir.no" 9 | name = "send-to-tl_-EmailAction-" 10 | } 11 | } 12 | resource "azurerm_monitor_scheduled_query_rules_alert_v2" "res-1" { 13 | display_name = "Deceased is alive and instance already exists_v2" 14 | evaluation_frequency = "PT5M" 15 | location = "norwayeast" 16 | name = "Deceased is alive and instance already exists_v2" 17 | resource_group_name = "altinn-digdir-oed-tt02-rg" 18 | scopes = ["/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/monitor-digdir-tt02-rg/providers/Microsoft.OperationalInsights/workspaces/application-digdir-tt02-law"] 19 | severity = 2 20 | target_resource_types = ["Microsoft.OperationalInsights/workspaces"] 21 | window_duration = "PT5M" 22 | action { 23 | action_groups = ["/subscriptions/7B6F8F15-3A3E-43A2-B6AC-8EB6C06AD103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/microsoft.insights/actionGroups/DD-email-notification-ag"] 24 | } 25 | 26 | criteria { 27 | operator = "GreaterThan" 28 | threshold = 0 29 | query = "AppTraces\n| where AppRoleName startswith \"oed\"\n| where SeverityLevel == 3\n| where Properties.EventId == 4003\n\n" 30 | time_aggregation_method = "Count" 31 | failing_periods { 32 | minimum_failing_periods_to_trigger_alert = 1 33 | number_of_evaluation_periods = 1 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/kv.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_key_vault" "kv" { 2 | name = "oed-prod-kv" 3 | location = azurerm_resource_group.rg.location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | sku_name = "standard" 6 | tenant_id = var.tenant_id 7 | } 8 | 9 | # Ingen tilgang til github action bruker 10 | # data "azurerm_key_vault" "a3_kv" { 11 | # name = var.altinn_apps_digdir_kv_name 12 | # resource_group_name = var.altinn_apps_digdir_rg_name 13 | # } 14 | 15 | resource "azurerm_key_vault_access_policy" "digdir_kv_sp" { 16 | depends_on = [azurerm_key_vault.kv] 17 | key_vault_id = azurerm_key_vault.kv.id 18 | tenant_id = data.azurerm_client_config.current.tenant_id 19 | object_id = var.digdir_kv_sp_object_id 20 | key_permissions = ["Get", "List"] 21 | secret_permissions = ["Get", "List"] 22 | certificate_permissions = ["Get", "List"] 23 | } 24 | 25 | resource "azurerm_key_vault_access_policy" "authz_linux" { 26 | depends_on = [azurerm_key_vault.kv] 27 | key_vault_id = azurerm_key_vault.kv.id 28 | tenant_id = data.azurerm_client_config.current.tenant_id 29 | object_id = azurerm_linux_web_app.authz_linux.identity[0].principal_id 30 | secret_permissions = ["Get"] 31 | } 32 | 33 | #access til github action brukeren for dd-infrastructure 34 | resource "azurerm_key_vault_access_policy" "github_access" { 35 | depends_on = [azurerm_key_vault.kv] 36 | key_vault_id = azurerm_key_vault.kv.id 37 | tenant_id = var.tenant_id 38 | object_id = var.github_action_oid 39 | key_permissions = ["Get", "Create", "List", "Delete"] 40 | secret_permissions = ["Get", "Set", "List", "Delete"] 41 | certificate_permissions = ["Get", "Create", "List", "Delete"] 42 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/network.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_public_ip" "pip" { 2 | lifecycle { 3 | ignore_changes = [ 4 | tags["costcenter"], 5 | tags["solution"] 6 | ] 7 | } 8 | name = "oed-feedpoller-ip" 9 | location = azurerm_resource_group.rg.location 10 | resource_group_name = azurerm_resource_group.rg.name 11 | allocation_method = "Static" 12 | ddos_protection_mode = "VirtualNetworkInherited" 13 | domain_name_label = "oed-feedpoller" 14 | ip_version = "IPv4" 15 | zones = ["1", "2", "3"] 16 | } 17 | 18 | resource "azurerm_virtual_network" "vnet" { 19 | name = "oed-feedpoller-vnet" 20 | address_space = ["10.37.167.0/24"] 21 | location = azurerm_resource_group.rg.location 22 | resource_group_name = azurerm_resource_group.rg.name 23 | } 24 | 25 | resource "azurerm_subnet" "default" { 26 | address_prefixes = ["10.37.167.0/27"] 27 | name = "default" 28 | resource_group_name = azurerm_resource_group.rg.name 29 | virtual_network_name = azurerm_virtual_network.vnet.name 30 | delegation { 31 | name = "delegation" 32 | service_delegation { 33 | actions = ["Microsoft.Network/virtualNetworks/subnets/action"] 34 | name = "Microsoft.Web/serverFarms" 35 | } 36 | } 37 | } 38 | 39 | resource "azurerm_nat_gateway" "nat" { 40 | name = "oed-feedpoller-nat" 41 | location = azurerm_resource_group.rg.location 42 | resource_group_name = azurerm_resource_group.rg.name 43 | } 44 | 45 | resource "azurerm_nat_gateway_public_ip_association" "nat_pip" { 46 | nat_gateway_id = azurerm_nat_gateway.nat.id 47 | public_ip_address_id = azurerm_public_ip.pip.id 48 | } 49 | 50 | resource "azurerm_subnet_nat_gateway_association" "nat_subnet" { 51 | subnet_id = azurerm_subnet.default.id 52 | nat_gateway_id = azurerm_nat_gateway.nat.id 53 | } 54 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/whitelist.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | admin_ips = split(",", azurerm_linux_web_app.admin_app.outbound_ip_addresses) 3 | feedpoller_ips = [azurerm_public_ip.pip.ip_address] 4 | 5 | # bygg en liste av objekter med navn og IP 6 | dynamic_non_authz_whitelist = flatten([ 7 | [for ip in local.feedpoller_ips : { 8 | name = "feedpoller-${replace(ip, ".", "-")}" 9 | start_ip = ip 10 | end_ip = ip 11 | }], 12 | [for ip in local.admin_ips : { 13 | name = "admin-${replace(ip, ".", "-")}" 14 | start_ip = ip 15 | end_ip = ip 16 | }] 17 | ]) 18 | 19 | all_non_authz_whitelist = concat(var.static_whitelist, local.dynamic_non_authz_whitelist) 20 | 21 | whitelist_non_authz_array = flatten([ 22 | for rule in local.all_non_authz_whitelist : ( 23 | rule.start_ip != rule.end_ip && rule.end_ip != null ? 24 | [rule.start_ip, rule.end_ip] : 25 | [rule.start_ip] 26 | ) 27 | ]) 28 | 29 | authz_ips = split(",", azurerm_linux_web_app.authz_linux.outbound_ip_addresses) 30 | 31 | dynamic_authz_whitelist = flatten([ 32 | [for ip in local.feedpoller_ips : { 33 | name = "feedpoller-${replace(ip, ".", "-")}" 34 | start_ip = ip 35 | end_ip = ip 36 | }] 37 | ]) 38 | 39 | # kombiner statisk + dynamisk 40 | all_whitelist = distinct(concat(var.static_whitelist, local.dynamic_non_authz_whitelist, local.dynamic_authz_whitelist)) 41 | 42 | # lag map for for_each 43 | whitelist_map_pg = { for rule in local.all_whitelist : rule.name => rule } 44 | 45 | # eks. ["10.0.0.1","10.0.0.1",.....] 46 | whitelist_array = flatten([ 47 | for rule in local.all_whitelist : ( 48 | rule.start_ip != rule.end_ip && rule.end_ip != null ? 49 | [rule.start_ip, rule.end_ip] : 50 | [rule.start_ip] 51 | ) 52 | ]) 53 | } 54 | 55 | output "whitelist_ips" { 56 | description = "Alle IP-adresser som blir whitelistet (inkludert end_ip hvis forskjellig)" 57 | value = local.whitelist_array 58 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/whitelist.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | admin_ips = split(",", azurerm_linux_web_app.admin_app.outbound_ip_addresses) 3 | feedpoller_ips = [azurerm_public_ip.pip.ip_address] 4 | 5 | # bygg en liste av objekter med navn og IP 6 | dynamic_non_authz_whitelist = flatten([ 7 | [for ip in local.feedpoller_ips : { 8 | name = "feedpoller-${replace(ip, ".", "-")}" 9 | start_ip = ip 10 | end_ip = ip 11 | }], 12 | [for ip in local.admin_ips : { 13 | name = "admin-${replace(ip, ".", "-")}" 14 | start_ip = ip 15 | end_ip = ip 16 | }] 17 | ]) 18 | 19 | all_non_authz_whitelist = concat(var.static_whitelist, local.dynamic_non_authz_whitelist) 20 | 21 | whitelist_non_authz_array = flatten([ 22 | for rule in local.all_non_authz_whitelist : ( 23 | rule.start_ip != rule.end_ip && rule.end_ip != null ? 24 | [rule.start_ip, rule.end_ip] : 25 | [rule.start_ip] 26 | ) 27 | ]) 28 | 29 | authz_ips = split(",", azurerm_linux_web_app.authz_linux.outbound_ip_addresses) 30 | 31 | dynamic_authz_whitelist = flatten([ 32 | [for ip in local.feedpoller_ips : { 33 | name = "feedpoller-${replace(ip, ".", "-")}" 34 | start_ip = ip 35 | end_ip = ip 36 | }] 37 | ]) 38 | 39 | # kombiner statisk + dynamisk 40 | all_whitelist = distinct(concat(var.static_whitelist, local.dynamic_non_authz_whitelist, local.dynamic_authz_whitelist)) 41 | 42 | # lag map for for_each 43 | whitelist_map_pg = { for rule in local.all_whitelist : rule.name => rule } 44 | 45 | # eks. ["10.0.0.1","10.0.0.1",.....] 46 | whitelist_array = flatten([ 47 | for rule in local.all_whitelist : ( 48 | rule.start_ip != rule.end_ip && rule.end_ip != null ? 49 | [rule.start_ip, rule.end_ip] : 50 | [rule.start_ip] 51 | ) 52 | ]) 53 | } 54 | 55 | output "whitelist_ips" { 56 | description = "Alle IP-adresser som blir whitelistet (inkludert end_ip hvis forskjellig)" 57 | value = local.whitelist_array 58 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/network.tf: -------------------------------------------------------------------------------- 1 | import { 2 | to = azurerm_public_ip.pip 3 | id = "/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/Microsoft.Network/publicIPAddresses/oed-test-feedpoller-ip" 4 | } 5 | 6 | resource "azurerm_public_ip" "pip" { 7 | lifecycle { 8 | ignore_changes = [ 9 | tags["costcenter"], 10 | tags["solution"] 11 | ] 12 | } 13 | name = "oed-${var.environment}-feedpoller-ip" 14 | location = var.alt_location 15 | resource_group_name = azurerm_resource_group.rg.name 16 | allocation_method = "Static" 17 | ddos_protection_mode = "VirtualNetworkInherited" 18 | domain_name_label = "oed-${var.environment}-feedpoller" 19 | ip_version = "IPv4" 20 | } 21 | 22 | resource "azurerm_virtual_network" "vnet" { 23 | name = "oed-${var.environment}-feedpoller-vnet" 24 | address_space = ["10.37.167.0/24"] 25 | location = var.alt_location 26 | resource_group_name = azurerm_resource_group.rg.name 27 | tags = { 28 | "costcenter" = "altinn3" 29 | "solution" = "apps" 30 | } 31 | } 32 | 33 | resource "azurerm_subnet" "default" { 34 | address_prefixes = ["10.37.167.0/27"] 35 | name = "default" 36 | resource_group_name = azurerm_resource_group.rg.name 37 | virtual_network_name = azurerm_virtual_network.vnet.name 38 | delegation { 39 | name = "delegation" 40 | service_delegation { 41 | actions = ["Microsoft.Network/virtualNetworks/subnets/action"] 42 | name = "Microsoft.Web/serverFarms" 43 | } 44 | } 45 | } 46 | 47 | resource "azurerm_nat_gateway" "nat" { 48 | name = "oed-${var.environment}-feedpoller-nat" 49 | location = var.alt_location 50 | resource_group_name = azurerm_resource_group.rg.name 51 | } 52 | 53 | #import { 54 | # to = azurerm_nat_gateway_public_ip_association.nat_pip 55 | # id = "${azurerm_nat_gateway.nat.id},${azurerm_public_ip.pip.id}" 56 | #} 57 | 58 | #resource "azurerm_nat_gateway_public_ip_association" "nat_pip" { 59 | # nat_gateway_id = azurerm_nat_gateway.nat.id 60 | # public_ip_address_id = azurerm_public_ip.pip.id 61 | #} 62 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/kv.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_key_vault" "kv" { 2 | name = "oed-kv" 3 | location = azurerm_resource_group.rg.location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | sku_name = "standard" 6 | tenant_id = var.tenant_id 7 | purge_protection_enabled = true 8 | tags = { 9 | "costcenter" = "altinn3" 10 | "solution" = "apps" 11 | } 12 | } 13 | 14 | # Ingen tilgang til github action bruker 15 | # data "azurerm_key_vault" "a3_kv" { 16 | # name = var.altinn_apps_digdir_kv_name 17 | # resource_group_name = var.altinn_apps_digdir_rg_name 18 | # } 19 | 20 | resource "azurerm_key_vault_access_policy" "digdir_kv_sp" { 21 | depends_on = [azurerm_key_vault.kv] 22 | key_vault_id = azurerm_key_vault.kv.id 23 | tenant_id = data.azurerm_client_config.current.tenant_id 24 | object_id = var.digdir_kv_sp_object_id 25 | key_permissions = ["Get", "List"] 26 | secret_permissions = ["Get", "List"] 27 | certificate_permissions = ["Get", "List"] 28 | } 29 | 30 | resource "azurerm_key_vault_access_policy" "authz_linux" { 31 | depends_on = [azurerm_key_vault.kv] 32 | key_vault_id = azurerm_key_vault.kv.id 33 | tenant_id = data.azurerm_client_config.current.tenant_id 34 | object_id = azurerm_linux_web_app.authz_linux.identity[0].principal_id 35 | secret_permissions = ["Get"] 36 | } 37 | 38 | resource "azurerm_key_vault_access_policy" "testapp_linux" { 39 | depends_on = [azurerm_key_vault.kv] 40 | key_vault_id = azurerm_key_vault.kv.id 41 | tenant_id = data.azurerm_client_config.current.tenant_id 42 | object_id = azurerm_linux_web_app.testapp-linux.identity[0].principal_id 43 | secret_permissions = ["Get"] 44 | } 45 | 46 | #access til github action brukeren for dd-infrastructure 47 | resource "azurerm_key_vault_access_policy" "github_access" { 48 | key_vault_id = azurerm_key_vault.kv.id 49 | tenant_id = var.tenant_id 50 | object_id = var.github_action_oid 51 | key_permissions = ["Get", "Create", "List", "Delete"] 52 | secret_permissions = ["Get", "Set", "List", "Delete", "Purge"] 53 | certificate_permissions = ["Get", "Create", "List", "Delete"] 54 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/storage.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_storage_account" "sa" { 2 | name = "oedfeedpollerstrg" 3 | location = azurerm_resource_group.rg.location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | account_replication_type = "ZRS" 6 | account_tier = "Standard" 7 | blob_properties { 8 | versioning_enabled = true 9 | } 10 | #network_rules { 11 | #default_action = "Deny" 12 | #virtual_network_subnet_ids = [azurerm_subnet.default.id] 13 | #} 14 | tags = { 15 | costcenter = "altinn3" 16 | service = "oed" 17 | solution = "apps" 18 | } 19 | } 20 | 21 | resource "azurerm_storage_management_policy" "sa_version_cleanup_smp" { 22 | storage_account_id = azurerm_storage_account.sa.id 23 | rule { 24 | name = "delete-old-blob-versions" 25 | enabled = true 26 | 27 | filters { 28 | blob_types = ["blockBlob"] 29 | prefix_match = [""] 30 | } 31 | 32 | actions { 33 | version { 34 | delete_after_days_since_creation = 7 35 | } 36 | } 37 | } 38 | } 39 | 40 | resource "azurerm_storage_account" "sa_admin_app" { 41 | name = "${var.environment}adminapp" 42 | resource_group_name = azurerm_resource_group.rg.name 43 | location = azurerm_resource_group.rg.location 44 | account_tier = "Standard" 45 | account_replication_type = "LRS" 46 | } 47 | 48 | resource "azurerm_storage_table" "st_audit_user" { 49 | name = "audituser" 50 | storage_account_name = azurerm_storage_account.sa_admin_app.name 51 | } 52 | 53 | resource "azurerm_storage_table" "st_audit_estate" { 54 | name = "auditestate" 55 | storage_account_name = azurerm_storage_account.sa_admin_app.name 56 | } 57 | 58 | resource "azurerm_role_assignment" "ra_storage_contributor_admin_app" { 59 | scope = azurerm_storage_account.sa_admin_app.id 60 | role_definition_name = "Storage Table Data Contributor" 61 | principal_id = azurerm_linux_web_app.admin_app.identity[0].principal_id 62 | } 63 | 64 | resource "azurerm_redis_cache" "cache" { 65 | name = "oed-cache" 66 | location = azurerm_resource_group.rg.location 67 | resource_group_name = azurerm_resource_group.rg.name 68 | capacity = 0 69 | family = "C" 70 | sku_name = "Basic" 71 | } 72 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/storage.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_storage_account" "sa" { 2 | name = "oed${var.environment}feedpollerstrg" 3 | location = var.alt_location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | account_replication_type = "LRS" 6 | account_tier = "Standard" 7 | account_kind = "StorageV2" 8 | blob_properties { 9 | versioning_enabled = true 10 | } 11 | #network_rules { 12 | #default_action = "Deny" 13 | #virtual_network_subnet_ids = [azurerm_subnet.default.id] 14 | #} 15 | tags = { 16 | costcenter = "altinn3" 17 | service = "oed" 18 | solution = "apps" 19 | } 20 | } 21 | 22 | resource "azurerm_storage_management_policy" "sa_version_cleanup_smp" { 23 | storage_account_id = azurerm_storage_account.sa.id 24 | rule { 25 | name = "delete-old-blob-versions" 26 | enabled = true 27 | 28 | filters { 29 | blob_types = ["blockBlob"] 30 | prefix_match = [""] 31 | } 32 | 33 | actions { 34 | version { 35 | delete_after_days_since_creation = 1 36 | } 37 | } 38 | } 39 | } 40 | 41 | resource "azurerm_storage_account" "sa_admin_app" { 42 | name = "${var.environment}adminapp" 43 | resource_group_name = azurerm_resource_group.rg.name 44 | location = azurerm_resource_group.rg.location 45 | account_tier = "Standard" 46 | account_replication_type = "LRS" 47 | } 48 | 49 | resource "azurerm_storage_table" "st_audit_user" { 50 | name = "audituser" 51 | storage_account_name = azurerm_storage_account.sa_admin_app.name 52 | } 53 | 54 | resource "azurerm_storage_table" "st_audit_estate" { 55 | name = "auditestate" 56 | storage_account_name = azurerm_storage_account.sa_admin_app.name 57 | } 58 | 59 | resource "azurerm_role_assignment" "ra_storage_contributor_admin_app" { 60 | scope = azurerm_storage_account.sa_admin_app.id 61 | role_definition_name = "Storage Table Data Contributor" 62 | principal_id = azurerm_linux_web_app.admin_app.identity[0].principal_id 63 | } 64 | 65 | resource "azurerm_redis_cache" "cache" { 66 | name = "oed-${var.environment}-cache" 67 | location = var.alt_location 68 | resource_group_name = azurerm_resource_group.rg.name 69 | capacity = 0 70 | family = "C" 71 | sku_name = "Basic" 72 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment = "prod" 2 | rg_name = "altinn-digdir-oed-rg" 3 | rg_location = "norwayeast" 4 | alt_location = "norwayeast" 5 | tenant_id = "cd0026d8-283b-4a55-9bfa-d0ef4a8ba21c" 6 | subscription_id = "0f05e9d4-592b-491a-b9da-49a8b242d0c5" 7 | cluster_fqdn = "digdir.apps.altinn.no" 8 | platform_fqdn = "platform.altinn.no" 9 | maskinporten_fqdn = "maskinporten.no" 10 | domstol_fqdn = "oppgjoer-etter-doedsfall.apps.ocp.prod.domstol.no" 11 | digdir_kv_sp_object_id = "570ae202-0655-482f-8aee-f885aa852685" 12 | digdir_altinn3_law_id = "/subscriptions/0f05e9d4-592b-491a-b9da-49a8b242d0c5/resourceGroups/monitor-digdir-prod-rg/providers/Microsoft.OperationalInsights/workspaces/application-digdir-prod-law" 13 | support_email = "digitalt-dodsbo-prod-aaaapupmzvtgp4ppcx7ggiaou4@digdir.slack.com" 14 | altinn_apps_digdir_kv_name = "digdir-prod-apps-kv" 15 | altinn_apps_digdir_rg_name = "altinnapps-digdir-prod-rg" 16 | github_action_oid = "b59ab7b9-db38-4bd3-8614-e6d10ad70b11" 17 | admin_app_user_group_id = "1d6f4be0-f9fb-4312-a4cb-82d5fdb07dcf" 18 | static_whitelist = [ 19 | { 20 | name = "Oekern_office" 21 | start_ip = "78.41.45.0" 22 | end_ip = "78.41.45.0" 23 | }, 24 | { 25 | name = "aks" 26 | start_ip = "20.100.24.184" 27 | end_ip = "20.100.24.185" 28 | }, 29 | { 30 | name = "A3Auth1" 31 | start_ip = "51.13.20.210" 32 | end_ip = "51.13.20.210" 33 | }, 34 | { 35 | name = "A3Auth2" 36 | start_ip = "51.13.20.208" 37 | end_ip = "51.13.20.208" 38 | }, 39 | { 40 | name = "A3-Eventystem" 41 | start_ip = "20.100.46.139" 42 | end_ip = "20.100.46.139" 43 | } 44 | ] 45 | a3_sp_app_name = "digdir-prod-kv-sp" 46 | fd_sku_name = "Premium_AzureFrontDoor" 47 | authz_custom_domain = "digitaltdodsbo.altinn.no" 48 | 49 | # Entra ID Configuration - Replace with your actual group object IDs 50 | entraid_admin_group_object_id = "c98a0265-fbf9-4890-8a71-50df4623582d" 51 | entraid_read_group_object_id = "87f6e50d-7423-4368-8d24-991146bfdfd6" 52 | entraid_app_name_suffix = "adminapp" 53 | entraid_app_name_prefix = "digdir-dd" 54 | entraid_app_description = "Digital estate management application with Admin and Read roles" 55 | 56 | # SPA Authentication Configuration 57 | entraid_spa_redirect_uri_production = "https://dd-prod-admin-app.azurewebsites.net/redirect" 58 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/terraform.tfvars: -------------------------------------------------------------------------------- 1 | environment = "test" 2 | alt_environment = "tt02" 3 | rg_name = "altinn-digdir-oed-tt02-rg" 4 | rg_location = "norwayeast" 5 | alt_location = "westeurope" 6 | tenant_id = "cd0026d8-283b-4a55-9bfa-d0ef4a8ba21c" 7 | subscription_id = "7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103" 8 | cluster_fqdn = "digdir.apps.tt02.altinn.no" 9 | platform_fqdn = "platform.tt02.altinn.no" 10 | maskinporten_fqdn = "test.maskinporten.no" 11 | domstol_fqdn = "oppgjoer-etter-doedsfall.apps.ocp.test.domstol.no" 12 | digdir_kv_sp_object_id = "c28691c7-9899-4e43-8292-86b99b0ed3d8" 13 | digdir_altinn3_law_id = "/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/monitor-digdir-tt02-rg/providers/Microsoft.OperationalInsights/workspaces/application-digdir-tt02-law" 14 | support_email = "digitalt-dodsbo-test-aaaapwt4zc7waueeb6s5s6j2qi@digdir.slack.com" 15 | altinn_apps_digdir_kv_name = "digdir-tt02-apps-kv" 16 | altinn_apps_digdir_rg_name = "altinnapps-digdir-tt02-rg" 17 | github_action_oid = "b59ab7b9-db38-4bd3-8614-e6d10ad70b11" 18 | admin_app_user_group_id = "717e682e-95a1-4b0e-a120-d47ebbf6109c" 19 | static_whitelist = [ 20 | { 21 | name = "Oekern_office" 22 | start_ip = "78.41.45.0" 23 | end_ip = "78.41.45.0" 24 | }, 25 | { 26 | name = "aks" 27 | start_ip = "51.13.16.142" 28 | end_ip = "51.13.16.143" 29 | }, 30 | { 31 | name = "A3Auth1" 32 | start_ip = "20.100.48.120" 33 | end_ip = "20.100.48.120" 34 | }, 35 | { 36 | name = "A3Auth2" 37 | start_ip = "20.100.48.118" 38 | end_ip = "20.100.48.118" 39 | }, 40 | { 41 | name = "A3-Eventsystem" 42 | start_ip = "20.100.24.41" 43 | end_ip = "20.100.24.41" 44 | } 45 | ] 46 | a3_sp_app_name = "digdir-tt02-kv-sp" 47 | fd_sku_name = "Standard_AzureFrontDoor" 48 | authz_custom_domain = "digitaltdodsbo.tt02.altinn.no" 49 | 50 | # Entra ID Configuration - Replace with your actual group object IDs 51 | entraid_admin_group_object_id = "bca4ee4e-c588-4787-b03b-8f7611d208f1" 52 | entraid_read_group_object_id = "f44bf7de-74fe-4604-ad60-2b5abb55a27a" 53 | entraid_app_name_suffix = "adminapp" 54 | entraid_app_name_prefix = "digdir-dd" 55 | entraid_app_description = "Digital estate management application with Admin and Read roles" 56 | 57 | # SPA Authentication Configuration 58 | entraid_spa_redirect_uri_localhost = "https://localhost:60475/redirect" 59 | entraid_spa_redirect_uri_production = "https://dd-test-admin-app.azurewebsites.net/redirect" 60 | -------------------------------------------------------------------------------- /infra/test/main.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_linux_web_app" "res-0" { 2 | app_settings = { 3 | APPINSIGHTS_INSTRUMENTATIONKEY = "e5b3288e-cff4-4369-addb-4af882bde487" 4 | APPLICATIONINSIGHTS_CONNECTION_STRING = "InstrumentationKey=e5b3288e-cff4-4369-addb-4af882bde487;IngestionEndpoint=https://norwayeast-0.in.applicationinsights.azure.com/;LiveEndpoint=https://norwayeast.livediagnostics.monitor.azure.com/;ApplicationId=c9b785f9-2de7-40c8-b646-14431f194718" 5 | ApplicationInsightsAgent_EXTENSION_VERSION = "~3" 6 | WEBSITE_AUTH_AAD_ALLOWED_TENANTS = "cd0026d8-283b-4a55-9bfa-d0ef4a8ba21c" 7 | } 8 | https_only = true 9 | location = "norwayeast" 10 | name = "dd-test-admin-app" 11 | resource_group_name = "altinn-digdir-oed-tt02-rg" 12 | service_plan_id = "/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/Microsoft.Web/serverFarms/asp-altinndigdir-dd-test-admin" 13 | tags = { 14 | costcenter = "altinn3" 15 | "hidden-link: /app-insights-conn-string" = "InstrumentationKey=e5b3288e-cff4-4369-addb-4af882bde487;IngestionEndpoint=https://norwayeast-0.in.applicationinsights.azure.com/;LiveEndpoint=https://norwayeast.livediagnostics.monitor.azure.com/;ApplicationId=c9b785f9-2de7-40c8-b646-14431f194718" 16 | "hidden-link: /app-insights-instrumentation-key" = "e5b3288e-cff4-4369-addb-4af882bde487" 17 | "hidden-link: /app-insights-resource-id" = "/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/microsoft.insights/components/dd-test-adminapp-ai" 18 | solution = "apps" 19 | } 20 | auth_settings_v2 { 21 | auth_enabled = true 22 | require_authentication = true 23 | unauthenticated_action = "Return403" 24 | active_directory_v2 { 25 | allowed_applications = ["83327527-9010-4c48-84d9-5f1b99bba309"] 26 | allowed_audiences = ["api://83327527-9010-4c48-84d9-5f1b99bba309"] 27 | client_id = "83327527-9010-4c48-84d9-5f1b99bba309" 28 | client_secret_setting_name = "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" 29 | tenant_auth_endpoint = "https://sts.windows.net/cd0026d8-283b-4a55-9bfa-d0ef4a8ba21c/v2.0" 30 | } 31 | login { 32 | token_store_enabled = true 33 | } 34 | } 35 | identity { 36 | type = "SystemAssigned" 37 | } 38 | site_config { 39 | always_on = false 40 | minimum_tls_version = "1.3" 41 | } 42 | sticky_settings { 43 | app_setting_names = ["MICROSOFT_PROVIDER_AUTHENTICATION_SECRET"] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/ai.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_log_analytics_workspace" "law" { 2 | name = "Workspace-altinnapps-digdir-oed-tt02-rg-WEU" 3 | location = var.alt_location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | retention_in_days = 30 6 | tags = { 7 | "costcenter" = "altinn3" 8 | "solution" = "apps" 9 | } 10 | } 11 | 12 | import { 13 | to = azurerm_application_insights.feedpoller 14 | id = "/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/Microsoft.Insights/components/oed-test-feedpoller-ai" 15 | } 16 | 17 | resource "azurerm_application_insights" "feedpoller" { 18 | name = "oed-${var.environment}-feedpoller-ai" 19 | location = var.alt_location 20 | resource_group_name = azurerm_resource_group.rg.name 21 | application_type = "web" 22 | workspace_id = azurerm_log_analytics_workspace.law.id 23 | sampling_percentage = 100 24 | disable_ip_masking = true 25 | tags = { 26 | "costcenter" = "altinn3" 27 | "solution" = "apps" 28 | } 29 | } 30 | 31 | resource "azurerm_application_insights" "authz_ai" { 32 | name = "oed-${var.environment}-authz-ai" 33 | location = var.alt_location 34 | resource_group_name = azurerm_resource_group.rg.name 35 | application_type = "web" 36 | workspace_id = azurerm_log_analytics_workspace.law.id 37 | sampling_percentage = 100 38 | disable_ip_masking = true 39 | tags = { 40 | "costcenter" = "altinn3" 41 | "solution" = "apps" 42 | } 43 | } 44 | 45 | import { 46 | to = azurerm_application_insights.testapp_ai 47 | id = "/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/Microsoft.Insights/components/oed-testapp-ai" 48 | } 49 | 50 | resource "azurerm_application_insights" "testapp_ai" { 51 | name = "oed-testapp-ai" 52 | location = var.alt_location 53 | resource_group_name = azurerm_resource_group.rg.name 54 | application_type = "web" 55 | workspace_id = azurerm_log_analytics_workspace.law.id 56 | sampling_percentage = 100 57 | disable_ip_masking = true 58 | tags = { 59 | "costcenter" = "altinn3" 60 | "solution" = "apps" 61 | } 62 | } 63 | 64 | resource "azurerm_application_insights" "adminapp_ai" { 65 | name = "dd-${var.environment}-adminapp-ai" 66 | location = azurerm_resource_group.rg.location 67 | resource_group_name = azurerm_resource_group.rg.name 68 | application_type = "web" 69 | workspace_id = azurerm_log_analytics_workspace.law.id 70 | sampling_percentage = 100 71 | disable_ip_masking = true 72 | tags = { 73 | "costcenter" = "altinn3" 74 | "solution" = "apps" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/variables.tf: -------------------------------------------------------------------------------- 1 | variable "environment" { 2 | type = string 3 | } 4 | variable "rg_location" { 5 | type = string 6 | } 7 | variable "rg_name" { 8 | type = string 9 | } 10 | variable "alt_location" { 11 | type = string 12 | } 13 | variable "tenant_id" { 14 | type = string 15 | } 16 | variable "subscription_id" { 17 | type = string 18 | } 19 | variable "cluster_fqdn" { 20 | type = string 21 | } 22 | variable "platform_fqdn" { 23 | type = string 24 | } 25 | variable "maskinporten_fqdn" { 26 | type = string 27 | } 28 | variable "domstol_fqdn" { 29 | type = string 30 | } 31 | variable "digdir_kv_sp_object_id" { 32 | type = string 33 | } 34 | variable "digdir_altinn3_law_id" { 35 | type = string 36 | } 37 | variable "support_email" { 38 | type = string 39 | } 40 | variable "altinn_apps_digdir_kv_name" { 41 | type = string 42 | } 43 | variable "altinn_apps_digdir_rg_name" { 44 | type = string 45 | } 46 | variable "github_action_oid" { 47 | type = string 48 | } 49 | variable "admin_app_user_group_id" { 50 | type = string 51 | } 52 | variable "static_whitelist" { 53 | description = "Liste med hardkodede IP-regler" 54 | type = list(object({ 55 | name = string 56 | start_ip = string 57 | end_ip = string 58 | })) 59 | } 60 | variable "a3_sp_app_name" { 61 | description = "Digdir A3 app principal object name" 62 | type = string 63 | } 64 | variable "fd_sku_name" { 65 | description = "Front door and WAF sku level" 66 | type = string 67 | } 68 | variable "authz_custom_domain" { 69 | description = "custom domene for authz" 70 | type = string 71 | } 72 | variable "entraid_admin_group_object_id" { 73 | description = "Object ID of the existing admin group in Entra ID" 74 | type = string 75 | } 76 | variable "entraid_read_group_object_id" { 77 | description = "Object ID of the existing read group in Entra ID" 78 | type = string 79 | } 80 | variable "entraid_app_name_suffix" { 81 | description = "Suffix for the Entra ID app name (will be prefixed with prefix-dd-{environment}-)" 82 | type = string 83 | default = "entraid-app" 84 | } 85 | variable "entraid_app_name_prefix" { 86 | description = "Prefix for the Entra ID app name" 87 | type = string 88 | default = "digdir-dd" 89 | } 90 | variable "entraid_app_description" { 91 | description = "Description for the Entra ID application" 92 | type = string 93 | default = "Application with Admin and Read roles for digital estate management" 94 | } 95 | variable "entraid_spa_redirect_uri_localhost" { 96 | description = "Localhost redirect URI for SPA authentication (development)" 97 | type = string 98 | default = "http://localhost:3000/redirect" 99 | } 100 | variable "entraid_spa_redirect_uri_production" { 101 | description = "Production redirect URI for SPA authentication" 102 | type = string 103 | default = "https://your-app-domain.com/redirect" 104 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/variables.tf: -------------------------------------------------------------------------------- 1 | variable "environment" { 2 | type = string 3 | } 4 | variable "alt_environment" { 5 | type = string 6 | } 7 | variable "rg_location" { 8 | type = string 9 | } 10 | variable "rg_name" { 11 | type = string 12 | } 13 | variable "alt_location" { 14 | type = string 15 | } 16 | variable "tenant_id" { 17 | type = string 18 | } 19 | variable "subscription_id" { 20 | type = string 21 | } 22 | variable "cluster_fqdn" { 23 | type = string 24 | } 25 | variable "platform_fqdn" { 26 | type = string 27 | } 28 | variable "maskinporten_fqdn" { 29 | type = string 30 | } 31 | variable "domstol_fqdn" { 32 | type = string 33 | } 34 | variable "digdir_kv_sp_object_id" { 35 | type = string 36 | } 37 | variable "digdir_altinn3_law_id" { 38 | type = string 39 | } 40 | variable "support_email" { 41 | type = string 42 | } 43 | variable "altinn_apps_digdir_kv_name" { 44 | type = string 45 | } 46 | variable "altinn_apps_digdir_rg_name" { 47 | type = string 48 | } 49 | variable "github_action_oid" { 50 | type = string 51 | } 52 | variable "admin_app_user_group_id" { 53 | type = string 54 | } 55 | variable "static_whitelist" { 56 | description = "Liste med hardkodede IP-regler" 57 | type = list(object({ 58 | name = string 59 | start_ip = string 60 | end_ip = string 61 | })) 62 | } 63 | variable "a3_sp_app_name" { 64 | description = "Digdir A3 app principal object name" 65 | type = string 66 | } 67 | variable "fd_sku_name" { 68 | description = "Front door and WAF sku level" 69 | type = string 70 | } 71 | variable "authz_custom_domain" { 72 | description = "custom domene for authz" 73 | type = string 74 | } 75 | variable "entraid_admin_group_object_id" { 76 | description = "Object ID of the existing admin group in Entra ID" 77 | type = string 78 | } 79 | variable "entraid_read_group_object_id" { 80 | description = "Object ID of the existing read group in Entra ID" 81 | type = string 82 | } 83 | variable "entraid_app_name_suffix" { 84 | description = "Suffix for the Entra ID app name (will be prefixed with prefix-dd-{environment}-)" 85 | type = string 86 | default = "entraid-app" 87 | } 88 | variable "entraid_app_name_prefix" { 89 | description = "Prefix for the Entra ID app name" 90 | type = string 91 | default = "digdir-dd" 92 | } 93 | variable "entraid_app_description" { 94 | description = "Description for the Entra ID application" 95 | type = string 96 | default = "Application with Admin and Read roles for digital estate management" 97 | } 98 | variable "entraid_spa_redirect_uri_localhost" { 99 | description = "Localhost redirect URI for SPA authentication (development)" 100 | type = string 101 | default = "http://localhost:3000/redirect" 102 | } 103 | variable "entraid_spa_redirect_uri_production" { 104 | description = "Production redirect URI for SPA authentication" 105 | type = string 106 | default = "https://your-app-domain.com/redirect" 107 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/function-feedpoller.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_windows_function_app" "feedpoller" { 2 | lifecycle { 3 | ignore_changes = [ 4 | app_settings["FUNCTIONS_EXTENSION_VERSION"] # Setting som tf ikke fanger opp er lik 5 | ] 6 | } 7 | app_settings = { 8 | "AzureWebJobs.FeedPoller.Disabled" = "0" 9 | "ConnectionStrings:Redis" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=ConnectionStrings--Redis)" 10 | "DaSettings:ProxyHostEndpointMatch" = "domstol.no$|brreg.no$|pipedream.net$" 11 | "MaskinportenSettings:ClientId" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedEventsConfig--MaskinportenSettings--ClientId)" 12 | "MaskinportenSettings:EncodedJwk" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedEventsConfig--MaskinportenSettings--EncodedJwk)" 13 | "MaskinportenSettings:Environment" = "${var.environment}" 14 | "MaskinportenSettings:Scope" = "domstol:forvaltningssaker:doedsfall.read altinn:serviceowner/events altinn:dd:internalevents" 15 | "MaskinportenSettings:DaResource" = "https://${var.domstol_fqdn}/api" 16 | "MaskinportenSettings:OedEventsResource" = "https://digdir.apps.altinn.no/digdir/oed-events/da-events/api/v1" 17 | "OedSettings:DaProxyHostEndpointMatch" = "domstol.no$|brreg.no$|pipedream.net$|${var.cluster_fqdn}$" 18 | "OedSettings:OedEventsBaseUrl" = "https://${var.cluster_fqdn}/digdir/oed-events/da-events/api/v1/" 19 | "FUNCTIONS_WORKER_RUNTIME" = "dotnet-isolated" 20 | "FUNCTIONS_EXTENSION_VERSION" = "~4" 21 | } 22 | https_only = true 23 | builtin_logging_enabled = false 24 | client_certificate_mode = "Required" 25 | location = azurerm_resource_group.rg.location 26 | name = "oed-feedpoller-func" 27 | resource_group_name = azurerm_resource_group.rg.name 28 | service_plan_id = azurerm_service_plan.feedpoller.id 29 | storage_account_access_key = azurerm_storage_account.sa.primary_access_key 30 | storage_account_name = azurerm_storage_account.sa.name 31 | tags = { 32 | costcenter = "altinn3" 33 | "hidden-link: /app-insights-conn-string" = azurerm_application_insights.feedpoller.connection_string 34 | "hidden-link: /app-insights-instrumentation-key" = azurerm_application_insights.feedpoller.instrumentation_key 35 | solution = "apps" 36 | } 37 | virtual_network_subnet_id = azurerm_subnet.default.id 38 | identity { 39 | type = "SystemAssigned" 40 | } 41 | site_config { 42 | application_insights_connection_string = azurerm_application_insights.feedpoller.connection_string 43 | application_insights_key = azurerm_application_insights.feedpoller.instrumentation_key 44 | ftps_state = "FtpsOnly" 45 | remote_debugging_enabled = false 46 | vnet_route_all_enabled = true 47 | use_32_bit_worker = false 48 | application_stack { 49 | dotnet_version = "v8.0" 50 | } 51 | cors { 52 | allowed_origins = ["https://portal.azure.com"] 53 | support_credentials = false 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /.github/workflows/altinn-digdir-oed-rg.yml: -------------------------------------------------------------------------------- 1 | name: altinn-digdir-oed-rg 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - .github/workflows/altinn-digdir-oed-rg.yml 9 | - infra/altinn-digdir-oed-rg/** 10 | pull_request: 11 | branches: 12 | - main 13 | paths: 14 | - .github/workflows/altinn-digdir-oed-rg.yml 15 | - infra/altinn-digdir-oed-rg/** 16 | workflow_dispatch: 17 | inputs: 18 | log_level: 19 | required: true 20 | description: Terraform Log Level 21 | default: WARN 22 | type: choice 23 | options: 24 | - TRACE 25 | - DEBUG 26 | - INFO 27 | - WARN 28 | - ERROR 29 | 30 | env: 31 | ENVIRONMENT: prod 32 | TF_STATE_NAME: altinn-digdir-oed-rg.tfstate 33 | TF_PROJECT: ./infra/altinn-digdir-oed-rg 34 | ARM_CLIENT_ID: ${{ vars.TF_AZURE_CLIENT_ID }} 35 | ARM_SUBSCRIPTION_ID: 0f05e9d4-592b-491a-b9da-49a8b242d0c5 36 | TF_LOG: ${{ github.event.inputs.log_level || 'INFO' }} 37 | 38 | permissions: 39 | id-token: write 40 | contents: write 41 | pull-requests: write 42 | 43 | jobs: 44 | plan: 45 | name: Plan 46 | environment: prod 47 | runs-on: ubuntu-latest 48 | steps: 49 | - name: Checkout Repository 50 | uses: actions/checkout@v4 51 | 52 | - name: Setup Terraform 53 | uses: hashicorp/setup-terraform@v3 54 | with: 55 | terraform_wrapper: false 56 | terraform_version: latest 57 | 58 | - name: Terraform Format 59 | run: terraform fmt -recursive 60 | working-directory: ${{ env.TF_PROJECT }} 61 | 62 | - name: Terraform Plan 63 | uses: altinn/altinn-platform/actions/terraform/plan@main 64 | with: 65 | working_directory: ${{ env.TF_PROJECT }} 66 | oidc_type: environment 67 | oidc_value: ${{ env.ENVIRONMENT }} 68 | arm_client_id: ${{ env.ARM_CLIENT_ID }} 69 | arm_subscription_id: ${{ env.ARM_SUBSCRIPTION_ID }} 70 | tf_state_name: ${{ env.TF_STATE_NAME }} 71 | gh_token: ${{ secrets.GITHUB_TOKEN }} 72 | tf_log_level: ${{ github.event.inputs.log_level || 'INFO' }} 73 | tf_version: latest 74 | 75 | deploy: 76 | name: Deploy 77 | environment: prod 78 | if: github.ref == 'refs/heads/main' 79 | needs: plan 80 | runs-on: ubuntu-latest 81 | steps: 82 | - name: Checkout Repository 83 | uses: actions/checkout@v4 84 | 85 | - name: Setup Terraform 86 | uses: hashicorp/setup-terraform@v3 87 | with: 88 | terraform_wrapper: false 89 | terraform_version: latest 90 | 91 | - name: Terraform Format 92 | run: terraform fmt -recursive 93 | working-directory: ${{ env.TF_PROJECT }} 94 | 95 | - name: Terraform Apply 96 | uses: altinn/altinn-platform/actions/terraform/apply@main 97 | with: 98 | working_directory: ${{ env.TF_PROJECT }} 99 | oidc_type: environment 100 | oidc_value: ${{ env.ENVIRONMENT }} 101 | arm_client_id: ${{ env.ARM_CLIENT_ID }} 102 | arm_subscription_id: ${{ env.ARM_SUBSCRIPTION_ID }} 103 | tf_state_name: ${{ env.TF_STATE_NAME }} 104 | tf_log_level: ${{ github.event.inputs.log_level || 'INFO' }} 105 | tf_version: latest 106 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/function-feedpoller.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_windows_function_app" "feedpoller" { 2 | lifecycle { 3 | ignore_changes = [ 4 | app_settings["FUNCTIONS_EXTENSION_VERSION"] # Setting som tf ikke fanger opp er lik 5 | ] 6 | } 7 | app_settings = { 8 | "AzureWebJobs.FeedPoller.Disabled" = "0" 9 | "ConnectionStrings:Redis" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=ConnectionStrings--Redis)" 10 | "DaSettings:ProxyHostEndpointMatch" = "domstol.no$|brreg.no$|pipedream.net$" 11 | "MaskinportenSettings:ClientId" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedEventsConfig--MaskinportenSettings--ClientId)" 12 | "MaskinportenSettings:EncodedJwk" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedEventsConfig--MaskinportenSettings--EncodedJwk)" 13 | "MaskinportenSettings:Environment" = "${var.environment}" 14 | "MaskinportenSettings:DaResource" = "https://${var.domstol_fqdn}/api" 15 | "MaskinportenSettings:OedEventsResource" = "https://digdir.apps.altinn.no/digdir/oed-events/da-events/api/v1" 16 | "MaskinportenSettings:Scope" = "domstol:forvaltningssaker:doedsfall.read altinn:serviceowner/events altinn:dd:internal" 17 | "OedSettings:DaProxyHostEndpointMatch" = "domstol.no$|brreg.no$|pipedream.net$|${var.cluster_fqdn}$" 18 | "OedSettings:OedEventsBaseUrl" = "https://${var.cluster_fqdn}/digdir/oed-events/da-events/api/v1/" 19 | "FUNCTIONS_WORKER_RUNTIME" = "dotnet-isolated" 20 | "FUNCTIONS_EXTENSION_VERSION" = "~4" 21 | } 22 | https_only = true 23 | builtin_logging_enabled = false 24 | client_certificate_mode = "Required" 25 | location = var.alt_location 26 | name = "oed-${var.environment}-feedpoller-func" 27 | resource_group_name = azurerm_resource_group.rg.name 28 | service_plan_id = azurerm_service_plan.feedpoller.id 29 | storage_account_access_key = azurerm_storage_account.sa.primary_access_key 30 | storage_account_name = azurerm_storage_account.sa.name 31 | tags = { 32 | costcenter = "altinn3" 33 | "hidden-link: /app-insights-conn-string" = azurerm_application_insights.feedpoller.connection_string 34 | "hidden-link: /app-insights-instrumentation-key" = azurerm_application_insights.feedpoller.instrumentation_key 35 | "hidden-link: /app-insights-resource-id" = azurerm_application_insights.feedpoller.id 36 | solution = "apps" 37 | } 38 | virtual_network_subnet_id = azurerm_subnet.default.id 39 | identity { 40 | type = "SystemAssigned" 41 | } 42 | site_config { 43 | application_insights_connection_string = azurerm_application_insights.feedpoller.connection_string 44 | application_insights_key = azurerm_application_insights.feedpoller.instrumentation_key 45 | ftps_state = "FtpsOnly" 46 | remote_debugging_enabled = false 47 | vnet_route_all_enabled = true 48 | use_32_bit_worker = false 49 | application_stack { 50 | dotnet_version = "v8.0" 51 | } 52 | cors { 53 | allowed_origins = ["https://portal.azure.com"] 54 | support_credentials = false 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /.github/workflows/altinn-digdir-oed-tt02-rg.yml: -------------------------------------------------------------------------------- 1 | name: altinn-digdir-oed-tt02-rg 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - .github/workflows/altinn-digdir-oed-tt02-rg.yml 9 | - infra/altinn-digdir-oed-tt02-rg/** 10 | pull_request: 11 | branches: 12 | - main 13 | paths: 14 | - .github/workflows/altinn-digdir-oed-tt02-rg.yml 15 | - infra/altinn-digdir-oed-tt02-rg/** 16 | workflow_dispatch: 17 | inputs: 18 | log_level: 19 | required: true 20 | description: Terraform Log Level 21 | default: WARN 22 | type: choice 23 | options: 24 | - TRACE 25 | - DEBUG 26 | - INFO 27 | - WARN 28 | - ERROR 29 | 30 | env: 31 | ENVIRONMENT: test 32 | TF_STATE_NAME: altinn-digdir-oed-tt02-rg.tfstate 33 | TF_PROJECT: ./infra/altinn-digdir-oed-tt02-rg 34 | ARM_CLIENT_ID: ${{ vars.TF_AZURE_CLIENT_ID }} 35 | ARM_SUBSCRIPTION_ID: 7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103 36 | TF_LOG: ${{ github.event.inputs.log_level || 'INFO' }} 37 | 38 | permissions: 39 | id-token: write 40 | contents: write 41 | pull-requests: write 42 | 43 | jobs: 44 | plan: 45 | name: Plan 46 | environment: test 47 | runs-on: ubuntu-latest 48 | steps: 49 | - name: Checkout Repository 50 | uses: actions/checkout@v4 51 | 52 | - name: Setup Terraform 53 | uses: hashicorp/setup-terraform@v3 54 | with: 55 | terraform_wrapper: false 56 | terraform_version: latest 57 | 58 | - name: Terraform Format 59 | run: terraform fmt -recursive 60 | working-directory: ${{ env.TF_PROJECT }} 61 | 62 | - name: Terraform Plan 63 | uses: altinn/altinn-platform/actions/terraform/plan@main 64 | with: 65 | working_directory: ${{ env.TF_PROJECT }} 66 | oidc_type: environment 67 | oidc_value: ${{ env.ENVIRONMENT }} 68 | arm_client_id: ${{ env.ARM_CLIENT_ID }} 69 | arm_subscription_id: ${{ env.ARM_SUBSCRIPTION_ID }} 70 | tf_state_name: ${{ env.TF_STATE_NAME }} 71 | gh_token: ${{ secrets.GITHUB_TOKEN }} 72 | tf_log_level: ${{ github.event.inputs.log_level || 'INFO' }} 73 | tf_version: latest 74 | 75 | deploy: 76 | name: Deploy 77 | environment: test 78 | if: github.ref == 'refs/heads/main' 79 | needs: plan 80 | runs-on: ubuntu-latest 81 | steps: 82 | - name: Checkout Repository 83 | uses: actions/checkout@v4 84 | 85 | - name: Setup Terraform 86 | uses: hashicorp/setup-terraform@v3 87 | with: 88 | terraform_wrapper: false 89 | terraform_version: latest 90 | 91 | - name: Terraform Format 92 | run: terraform fmt -recursive 93 | working-directory: ${{ env.TF_PROJECT }} 94 | 95 | - name: Terraform Apply 96 | uses: altinn/altinn-platform/actions/terraform/apply@main 97 | with: 98 | working_directory: ${{ env.TF_PROJECT }} 99 | oidc_type: environment 100 | oidc_value: ${{ env.ENVIRONMENT }} 101 | arm_client_id: ${{ env.ARM_CLIENT_ID }} 102 | arm_subscription_id: ${{ env.ARM_SUBSCRIPTION_ID }} 103 | tf_state_name: ${{ env.TF_STATE_NAME }} 104 | tf_log_level: ${{ github.event.inputs.log_level || 'INFO' }} 105 | tf_version: latest 106 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/frontdoor_waf.tf: -------------------------------------------------------------------------------- 1 | # 1. Front Door (STANDARD) 2 | resource "azurerm_cdn_frontdoor_profile" "fd_profile" { 3 | name = "oed-fd-profile-${var.environment}" 4 | resource_group_name = azurerm_resource_group.rg.name 5 | sku_name = var.fd_sku_name 6 | } 7 | 8 | # 2. Logging 9 | resource "azurerm_monitor_diagnostic_setting" "fd_logs" { 10 | name = "frontdoor-logs" 11 | target_resource_id = azurerm_cdn_frontdoor_profile.fd_profile.id 12 | log_analytics_workspace_id = azurerm_log_analytics_workspace.law.id 13 | 14 | enabled_log { 15 | category = "FrontdoorAccessLog" 16 | } 17 | 18 | enabled_metric { 19 | category = "AllMetrics" 20 | } 21 | } 22 | 23 | # 3. Origin group (App Service backend) 24 | resource "azurerm_cdn_frontdoor_origin_group" "origin_group" { 25 | name = "oed-origin-group-${var.environment}" 26 | cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fd_profile.id 27 | 28 | load_balancing {} 29 | } 30 | 31 | resource "azurerm_cdn_frontdoor_origin" "app_origin" { 32 | name = "oed-appservice-origin-${var.environment}" 33 | certificate_name_check_enabled = true 34 | cdn_frontdoor_origin_group_id = azurerm_cdn_frontdoor_origin_group.origin_group.id 35 | host_name = azurerm_linux_web_app.authz_linux.default_hostname 36 | http_port = 80 37 | https_port = 443 38 | enabled = true 39 | origin_host_header = azurerm_linux_web_app.authz_linux.default_hostname 40 | } 41 | 42 | # 4. Endpoint 43 | resource "azurerm_cdn_frontdoor_endpoint" "endpoint" { 44 | name = "digdir-dd-${var.environment}-authz" 45 | cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fd_profile.id 46 | } 47 | 48 | # 5. Custom domain (managed TLS støttes også på Standard) 49 | resource "azurerm_cdn_frontdoor_custom_domain" "authz_domain" { 50 | name = "authzdigitaltdodsbo${var.environment}" 51 | cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fd_profile.id 52 | host_name = var.authz_custom_domain 53 | 54 | tls { 55 | certificate_type = "ManagedCertificate" 56 | } 57 | } 58 | 59 | output "frontdoor_dns_validation_txt_name" { 60 | value = "_dnsauth.${var.authz_custom_domain}" 61 | } 62 | 63 | output "frontdoor_dns_validation_txt_value" { 64 | value = azurerm_cdn_frontdoor_custom_domain.authz_domain.validation_token 65 | description = "Opprett TXT-record på _dnsauth.digitaltdodsbo.tt02.altinn.no med denne verdien for å validere domene hos Front Door." 66 | } 67 | 68 | output "frontdoor_cname_target" { 69 | value = azurerm_cdn_frontdoor_endpoint.endpoint.host_name 70 | description = "Sett CNAME for digitaltdodsbo.tt02.altinn.no til denne verdien for cutover." 71 | } 72 | 73 | # 6. Route 74 | resource "azurerm_cdn_frontdoor_route" "route" { 75 | name = "default-route-${var.environment}" 76 | cdn_frontdoor_endpoint_id = azurerm_cdn_frontdoor_endpoint.endpoint.id 77 | cdn_frontdoor_origin_group_id = azurerm_cdn_frontdoor_origin_group.origin_group.id 78 | cdn_frontdoor_origin_ids = [azurerm_cdn_frontdoor_origin.app_origin.id] 79 | 80 | cdn_frontdoor_custom_domain_ids = [ 81 | azurerm_cdn_frontdoor_custom_domain.authz_domain.id 82 | ] 83 | 84 | supported_protocols = ["Https", "Http"] 85 | https_redirect_enabled = true 86 | forwarding_protocol = "HttpsOnly" 87 | patterns_to_match = ["/*"] 88 | link_to_default_domain = true 89 | } 90 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/web-app-authz.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_linux_web_app" "authz_linux" { 2 | name = "oed-${var.environment}-authz-app-linux" 3 | location = var.alt_location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | service_plan_id = azurerm_service_plan.authz_linux.id 6 | depends_on = [azurerm_service_plan.authz_linux] 7 | https_only = true 8 | 9 | app_settings = { 10 | APPINSIGHTS_INSTRUMENTATIONKEY = azurerm_application_insights.authz_ai.instrumentation_key 11 | APPINSIGHTS_PROFILERFEATURE_VERSION = "1.0.0" 12 | APPINSIGHTS_SNAPSHOTFEATURE_VERSION = "1.0.0" 13 | APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.authz_ai.connection_string 14 | ApplicationInsightsAgent_EXTENSION_VERSION = "~2" 15 | DiagnosticServices_EXTENSION_VERSION = "~3" 16 | "GeneralSettings__MaskinportenAuxillaryOauth2WellKnownEndpoint" = "https://${var.maskinporten_fqdn}/.well-known/oauth-authorization-server/" 17 | "GeneralSettings__MaskinportenOauth2WellKnownEndpoint" = "https://${var.platform_fqdn}/authentication/api/v1/openid/.well-known/openid-configuration/" 18 | "GeneralSettings__OedEventAuthQueryParameter" = "auth" 19 | InstrumentationEngine_EXTENSION_VERSION = "disabled" 20 | "Secrets__OedEventAuthKey" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--OedEventAuthKey)" 21 | "Secrets__PostgreSqlAdminConnectionString" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--PostgreSqlAdminConnectionString)" 22 | "Secrets__PostgreSqlUserConnectionString" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--PostgreSqlUserConnectionString)" 23 | SnapshotDebugger_EXTENSION_VERSION = "disabled" 24 | XDT_MicrosoftApplicationInsights_BaseExtensions = "disabled" 25 | XDT_MicrosoftApplicationInsights_Java = "1" 26 | XDT_MicrosoftApplicationInsights_Mode = "recommended" 27 | XDT_MicrosoftApplicationInsights_NodeJS = "1" 28 | XDT_MicrosoftApplicationInsights_PreemptSdk = "disabled" 29 | } 30 | tags = { 31 | "hidden-link: /app-insights-conn-string" = azurerm_application_insights.authz_ai.connection_string 32 | "hidden-link: /app-insights-instrumentation-key" = azurerm_application_insights.authz_ai.instrumentation_key 33 | "hidden-link: /app-insights-resource-id" = azurerm_application_insights.authz_ai.id 34 | } 35 | 36 | identity { 37 | type = "SystemAssigned" 38 | } 39 | 40 | logs { 41 | detailed_error_messages = true 42 | failed_request_tracing = false 43 | http_logs { 44 | file_system { 45 | retention_in_days = 5 46 | retention_in_mb = 35 47 | } 48 | } 49 | } 50 | 51 | site_config { 52 | always_on = true 53 | minimum_tls_version = "1.2" 54 | health_check_eviction_time_in_min = 10 55 | health_check_path = "/health" 56 | http2_enabled = true 57 | ip_restriction_default_action = "Deny" 58 | 59 | application_stack { 60 | dotnet_version = "10.0" 61 | } 62 | 63 | ip_restriction { 64 | name = "Allow-FrontDoor" 65 | description = "Allow-FrontDoor" 66 | service_tag = "AzureFrontDoor.Backend" 67 | action = "Allow" 68 | headers { 69 | x_azure_fdid = ["${azurerm_cdn_frontdoor_profile.fd_profile.resource_guid}"] 70 | } 71 | priority = 10 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/web-app-testapp.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_linux_web_app" "testapp-linux" { 2 | name = "oed-testapp-app-linux" 3 | location = var.alt_location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | service_plan_id = azurerm_service_plan.authz_linux.id 6 | depends_on = [azurerm_service_plan.authz_linux] 7 | https_only = true 8 | 9 | lifecycle { 10 | ignore_changes = [ 11 | app_settings["AuthSettings__CloudEventSecret"], 12 | ] 13 | } 14 | 15 | app_settings = { 16 | APPINSIGHTS_INSTRUMENTATIONKEY = azurerm_application_insights.testapp_ai.instrumentation_key 17 | APPINSIGHTS_PROFILERFEATURE_VERSION = "1.0.0" 18 | APPINSIGHTS_SNAPSHOTFEATURE_VERSION = "1.0.0" 19 | APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.testapp_ai.connection_string 20 | "AltinnSettings__Password" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--TestTokenGenerator--Password)" 21 | "AltinnSettings__PlatformUrl" = "https://platform.tt02.altinn.no" 22 | "AltinnSettings__TokenGeneratorUrl" = "https://altinn-testtools-token-generator.azurewebsites.net" 23 | "AltinnSettings__Username" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--TestTokenGenerator--Username)" 24 | ApplicationInsightsAgent_EXTENSION_VERSION = "~2" 25 | "AuthSettings__CloudEventQueryParamName" = "code" 26 | "AuthSettings__Password" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--oed-testapp-password)" 27 | "AuthSettings__Username" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--oed-testapp-username)" 28 | DiagnosticServices_EXTENSION_VERSION = "~3" 29 | InstrumentationEngine_EXTENSION_VERSION = "disabled" 30 | "MaskinportenSettings__ClientId" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedConfig--MaskinportenSettings--ClientId)" 31 | "MaskinportenSettings__EncodedJwk" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedConfig--MaskinportenSettings--EncodedJwk)" 32 | "MaskinportenSettings__Environment" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedConfig--MaskinportenSettings--Environment)" 33 | "MaskinportenSettings__TokenExchangeEnvironment" = "tt02" 34 | "OedEventsSettings__BaseAddress" = "https://digdir.apps.tt02.altinn.no" 35 | SnapshotDebugger_EXTENSION_VERSION = "disabled" 36 | XDT_MicrosoftApplicationInsights_BaseExtensions = "disabled" 37 | XDT_MicrosoftApplicationInsights_Java = "1" 38 | XDT_MicrosoftApplicationInsights_Mode = "recommended" 39 | XDT_MicrosoftApplicationInsights_NodeJS = "1" 40 | XDT_MicrosoftApplicationInsights_PreemptSdk = "disabled" 41 | } 42 | 43 | tags = { 44 | "hidden-link: /app-insights-conn-string" = azurerm_application_insights.testapp_ai.connection_string 45 | "hidden-link: /app-insights-instrumentation-key" = azurerm_application_insights.testapp_ai.instrumentation_key 46 | "hidden-link: /app-insights-resource-id" = azurerm_application_insights.testapp_ai.id 47 | } 48 | 49 | identity { 50 | type = "SystemAssigned, UserAssigned" 51 | identity_ids = ["/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/oed-kv-principal"] 52 | } 53 | 54 | site_config { 55 | always_on = false 56 | minimum_tls_version = "1.2" 57 | health_check_eviction_time_in_min = 10 58 | health_check_path = "/health" 59 | http2_enabled = true 60 | 61 | application_stack { 62 | dotnet_version = "10.0" 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/web-app-authz.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_linux_web_app" "authz_linux" { 2 | name = "oed-${var.environment}-authz-app-${random_integer.ri.result}" 3 | location = var.alt_location 4 | resource_group_name = azurerm_resource_group.rg.name 5 | service_plan_id = azurerm_service_plan.authz_linux.id 6 | depends_on = [azurerm_service_plan.authz_linux] 7 | https_only = true 8 | app_settings = { 9 | //WEBSITE_DAAS_STORAGE_CONNECTIONSTRING = "DefaultEndpointsProtocol=https;AccountName=oedteson39ei;EndpointSuffix=core.windows.net" 10 | APPINSIGHTS_INSTRUMENTATIONKEY = azurerm_application_insights.authz_ai.instrumentation_key 11 | APPINSIGHTS_PROFILERFEATURE_VERSION = "1.0.0" 12 | APPINSIGHTS_SNAPSHOTFEATURE_VERSION = "1.0.0" 13 | APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.authz_ai.connection_string 14 | ApplicationInsightsAgent_EXTENSION_VERSION = "~2" 15 | DiagnosticServices_EXTENSION_VERSION = "~3" 16 | InstrumentationEngine_EXTENSION_VERSION = "disabled" 17 | "GeneralSettings__MaskinportenAuxillaryOauth2WellKnownEndpoint" = "https://${var.maskinporten_fqdn}/.well-known/oauth-authorization-server/" 18 | "GeneralSettings__MaskinportenOauth2WellKnownEndpoint" = "https://${var.platform_fqdn}/authentication/api/v1/openid/.well-known/openid-configuration/" 19 | "GeneralSettings__OedEventAuthQueryParameter" = "auth" 20 | "Secrets__OedEventAuthKey" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--OedEventAuthKey)" 21 | "Secrets__PostgreSqlAdminConnectionString" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--PostgreSqlAdminConnectionString)" 22 | "Secrets__PostgreSqlUserConnectionString" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--PostgreSqlUserConnectionString)" 23 | SnapshotDebugger_EXTENSION_VERSION = "disabled" 24 | XDT_MicrosoftApplicationInsights_BaseExtensions = "disabled" 25 | XDT_MicrosoftApplicationInsights_Java = "1" 26 | XDT_MicrosoftApplicationInsights_Mode = "recommended" 27 | XDT_MicrosoftApplicationInsights_NodeJS = "1" 28 | XDT_MicrosoftApplicationInsights_PreemptSdk = "disabled" 29 | } 30 | tags = { 31 | "costcenter" = "altinn3" 32 | "hidden-link: /app-insights-conn-string" = azurerm_application_insights.authz_ai.connection_string 33 | "hidden-link: /app-insights-instrumentation-key" = azurerm_application_insights.authz_ai.instrumentation_key 34 | "hidden-link: /app-insights-resource-id" = azurerm_application_insights.authz_ai.id 35 | "solution" = "apps" 36 | } 37 | 38 | identity { 39 | type = "SystemAssigned, UserAssigned" 40 | identity_ids = ["/subscriptions/7b6f8f15-3a3e-43a2-b6ac-8eb6c06ad103/resourceGroups/altinn-digdir-oed-tt02-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/oed-kv-principal"] 41 | } 42 | 43 | site_config { 44 | always_on = false 45 | minimum_tls_version = "1.2" 46 | health_check_eviction_time_in_min = 10 47 | health_check_path = "/health" 48 | http2_enabled = true 49 | ip_restriction_default_action = "Deny" 50 | 51 | application_stack { 52 | dotnet_version = "10.0" 53 | } 54 | 55 | ip_restriction { 56 | name = "Allow-FrontDoor" 57 | description = "Allow-FrontDoor" 58 | service_tag = "AzureFrontDoor.Backend" 59 | action = "Allow" 60 | headers { 61 | x_azure_fdid = ["${azurerm_cdn_frontdoor_profile.fd_profile.resource_guid}"] 62 | } 63 | priority = 10 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/entra-id.tf: -------------------------------------------------------------------------------- 1 | # Data sources for existing Entra ID groups 2 | data "azuread_group" "admin_group" { 3 | object_id = var.entraid_admin_group_object_id 4 | } 5 | 6 | data "azuread_group" "read_group" { 7 | object_id = var.entraid_read_group_object_id 8 | } 9 | 10 | # Generate unique IDs for app roles and API scope 11 | resource "random_uuid" "admin_role_id" {} 12 | resource "random_uuid" "read_role_id" {} 13 | resource "random_uuid" "access_token_scope_id" {} 14 | 15 | # Entra ID Application with App Roles and API Scope 16 | resource "azuread_application" "admin_ad_app" { 17 | display_name = "${var.entraid_app_name_prefix}-${var.environment}-${var.entraid_app_name_suffix}" 18 | description = var.entraid_app_description 19 | owners = [data.azurerm_client_config.current.object_id] 20 | group_membership_claims = ["None"] 21 | sign_in_audience = "AzureADMyOrg" 22 | 23 | # Ignore changes to identifier_uris to prevent recreation 24 | lifecycle { 25 | ignore_changes = [ 26 | identifier_uris, 27 | ] 28 | } 29 | 30 | # App Roles 31 | app_role { 32 | allowed_member_types = ["User"] 33 | description = "Admin role for ${var.entraid_app_name_prefix}-${var.environment}-${var.entraid_app_name_suffix}" 34 | display_name = "Admin" 35 | enabled = true 36 | id = random_uuid.admin_role_id.result 37 | value = "Admin" 38 | } 39 | 40 | app_role { 41 | allowed_member_types = ["User"] 42 | description = "Read role for ${var.entraid_app_name_prefix}-${var.environment}-${var.entraid_app_name_suffix}" 43 | display_name = "Read" 44 | enabled = true 45 | id = random_uuid.read_role_id.result 46 | value = "Read" 47 | } 48 | 49 | # SPA (Single Page Application) configuration 50 | single_page_application { 51 | redirect_uris = [ 52 | var.entraid_spa_redirect_uri_production 53 | ] 54 | } 55 | 56 | # Enable access tokens and ID tokens for authentication 57 | # This is equivalent to checking "Access tokens" and "ID tokens" in Azure portal 58 | required_resource_access { 59 | resource_app_id = "00000003-0000-0000-c000-000000000000" # Microsoft Graph 60 | 61 | resource_access { 62 | id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d" # User.Read 63 | type = "Scope" 64 | } 65 | } 66 | 67 | # API configuration with exposed scope 68 | api { 69 | mapped_claims_enabled = false 70 | requested_access_token_version = 2 71 | 72 | oauth2_permission_scope { 73 | admin_consent_description = "Allow the application to read access tokens" 74 | admin_consent_display_name = "Read access tokens" 75 | enabled = true 76 | id = random_uuid.access_token_scope_id.result 77 | type = "User" 78 | user_consent_description = "Allow the application to read access tokens on your behalf" 79 | user_consent_display_name = "Read access tokens" 80 | value = "AccessToken.Read" 81 | } 82 | } 83 | } 84 | 85 | # Service Principal (Enterprise App) 86 | resource "azuread_service_principal" "admin_ad_app_sp" { 87 | client_id = azuread_application.admin_ad_app.client_id 88 | app_role_assignment_required = true 89 | owners = [data.azurerm_client_config.current.object_id] 90 | 91 | tags = ["terraform", "${var.entraid_app_name_prefix}-${var.environment}"] 92 | } 93 | 94 | # App Role Assignments - Admin Group to Admin Role 95 | resource "azuread_app_role_assignment" "admin_group_to_admin_role" { 96 | app_role_id = random_uuid.admin_role_id.result 97 | principal_object_id = data.azuread_group.admin_group.object_id 98 | resource_object_id = azuread_service_principal.admin_ad_app_sp.object_id 99 | } 100 | 101 | # App Role Assignments - Read Group to Read Role 102 | resource "azuread_app_role_assignment" "read_group_to_read_role" { 103 | app_role_id = random_uuid.read_role_id.result 104 | principal_object_id = data.azuread_group.read_group.object_id 105 | resource_object_id = azuread_service_principal.admin_ad_app_sp.object_id 106 | } 107 | 108 | resource "azuread_application_identifier_uri" "admin_ad_app_identifier_uri" { 109 | application_id = azuread_application.admin_ad_app.id 110 | identifier_uri = "api://${azuread_application.admin_ad_app.client_id}" 111 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/entra-id.tf: -------------------------------------------------------------------------------- 1 | # Data sources for existing Entra ID groups 2 | data "azuread_group" "admin_group" { 3 | object_id = var.entraid_admin_group_object_id 4 | } 5 | 6 | data "azuread_group" "read_group" { 7 | object_id = var.entraid_read_group_object_id 8 | } 9 | 10 | # Generate unique IDs for app roles and API scope 11 | resource "random_uuid" "admin_role_id" {} 12 | resource "random_uuid" "read_role_id" {} 13 | resource "random_uuid" "access_token_scope_id" {} 14 | 15 | # Entra ID Application with App Roles and API Scope 16 | resource "azuread_application" "admin_ad_app" { 17 | display_name = "${var.entraid_app_name_prefix}-${var.environment}-${var.entraid_app_name_suffix}" 18 | description = var.entraid_app_description 19 | owners = [data.azurerm_client_config.current.object_id] 20 | group_membership_claims = ["None"] 21 | sign_in_audience = "AzureADMyOrg" 22 | 23 | # Ignore changes to identifier_uris to prevent recreation 24 | lifecycle { 25 | ignore_changes = [ 26 | identifier_uris, 27 | ] 28 | } 29 | 30 | # App Roles 31 | app_role { 32 | allowed_member_types = ["User"] 33 | description = "Admin role for ${var.entraid_app_name_prefix}-${var.environment}-${var.entraid_app_name_suffix}" 34 | display_name = "Admin" 35 | enabled = true 36 | id = random_uuid.admin_role_id.result 37 | value = "Admin" 38 | } 39 | 40 | app_role { 41 | allowed_member_types = ["User"] 42 | description = "Read role for ${var.entraid_app_name_prefix}-${var.environment}-${var.entraid_app_name_suffix}" 43 | display_name = "Read" 44 | enabled = true 45 | id = random_uuid.read_role_id.result 46 | value = "Read" 47 | } 48 | 49 | # SPA (Single Page Application) configuration 50 | single_page_application { 51 | redirect_uris = [ 52 | var.entraid_spa_redirect_uri_localhost, 53 | var.entraid_spa_redirect_uri_production 54 | ] 55 | } 56 | 57 | # Enable access tokens and ID tokens for authentication 58 | # This is equivalent to checking "Access tokens" and "ID tokens" in Azure portal 59 | required_resource_access { 60 | resource_app_id = "00000003-0000-0000-c000-000000000000" # Microsoft Graph 61 | 62 | resource_access { 63 | id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d" # User.Read 64 | type = "Scope" 65 | } 66 | } 67 | 68 | # API configuration with exposed scope 69 | api { 70 | mapped_claims_enabled = false 71 | requested_access_token_version = 2 72 | 73 | oauth2_permission_scope { 74 | admin_consent_description = "Allow the application to read access tokens" 75 | admin_consent_display_name = "Read access tokens" 76 | enabled = true 77 | id = random_uuid.access_token_scope_id.result 78 | type = "User" 79 | user_consent_description = "Allow the application to read access tokens on your behalf" 80 | user_consent_display_name = "Read access tokens" 81 | value = "AccessToken.Read" 82 | } 83 | } 84 | } 85 | 86 | # Service Principal (Enterprise App) 87 | resource "azuread_service_principal" "admin_ad_app_sp" { 88 | client_id = azuread_application.admin_ad_app.client_id 89 | app_role_assignment_required = true 90 | owners = [data.azurerm_client_config.current.object_id] 91 | 92 | tags = ["terraform", "${var.entraid_app_name_prefix}-${var.environment}"] 93 | } 94 | 95 | # App Role Assignments - Admin Group to Admin Role 96 | resource "azuread_app_role_assignment" "admin_group_to_admin_role" { 97 | app_role_id = random_uuid.admin_role_id.result 98 | principal_object_id = data.azuread_group.admin_group.object_id 99 | resource_object_id = azuread_service_principal.admin_ad_app_sp.object_id 100 | } 101 | 102 | # App Role Assignments - Read Group to Read Role 103 | resource "azuread_app_role_assignment" "read_group_to_read_role" { 104 | app_role_id = random_uuid.read_role_id.result 105 | principal_object_id = data.azuread_group.read_group.object_id 106 | resource_object_id = azuread_service_principal.admin_ad_app_sp.object_id 107 | } 108 | 109 | resource "azuread_application_identifier_uri" "admin_ad_app_identifier_uri" { 110 | application_id = azuread_application.admin_ad_app.id 111 | identifier_uri = "api://${azuread_application.admin_ad_app.client_id}" 112 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/database.tf: -------------------------------------------------------------------------------- 1 | # PostgreSQL for OED 2 | resource "random_password" "dd_admin_password" { 3 | length = 16 4 | special = true 5 | } 6 | 7 | resource "random_password" "dd_user_password" { 8 | length = 16 9 | special = true 10 | } 11 | 12 | resource "azurerm_postgresql_flexible_server" "pg" { 13 | name = "dd-${var.environment}-pg" 14 | location = azurerm_resource_group.rg.location 15 | resource_group_name = azurerm_resource_group.rg.name 16 | administrator_login = "pgadmin" 17 | administrator_password = random_password.dd_admin_password.result 18 | version = "16" 19 | sku_name = "B_Standard_B2ms" 20 | storage_mb = 32768 21 | backup_retention_days = 7 22 | auto_grow_enabled = false 23 | public_network_access_enabled = true 24 | zone = "1" 25 | 26 | authentication { 27 | active_directory_auth_enabled = true 28 | password_auth_enabled = true 29 | tenant_id = var.tenant_id 30 | } 31 | tags = { 32 | "costcenter" = "altinn3" 33 | "solution" = "apps" 34 | } 35 | } 36 | 37 | resource "azurerm_postgresql_flexible_server_database" "oed_db" { 38 | name = "dd-oed-${var.environment}-pg-db" 39 | server_id = azurerm_postgresql_flexible_server.pg.id 40 | charset = "UTF8" 41 | collation = "en_US.utf8" 42 | } 43 | 44 | locals { 45 | app_user = { 46 | name = "appuser" 47 | password = random_password.dd_user_password.result 48 | } 49 | } 50 | 51 | #Har ikke tilgang til a3 aps kv, så connstringen legges i oed-kv og må flyttes manuelt 52 | resource "azurerm_key_vault_secret" "admin_conn_string" { 53 | name = "dd-pgadmin-connection-string" 54 | value = "Server=${azurerm_postgresql_flexible_server.pg.fqdn};Username=${azurerm_postgresql_flexible_server.pg.administrator_login};Database=${azurerm_postgresql_flexible_server_database.oed_db.name};Port=5432;Password='${random_password.dd_admin_password.result}';SSLMode=Prefer" 55 | key_vault_id = azurerm_key_vault.kv.id 56 | } 57 | 58 | resource "azurerm_key_vault_secret" "user_conn_string" { 59 | name = "OedConfig--Postgres--ConnectionString" 60 | value = "Server=${azurerm_postgresql_flexible_server.pg.fqdn};Username=${local.app_user.name};Database=${azurerm_postgresql_flexible_server_database.oed_db.name};Port=5432;Password='${local.app_user.password}';SSLMode=Prefer" 61 | key_vault_id = azurerm_key_vault.kv.id 62 | } 63 | 64 | resource "azurerm_postgresql_flexible_server_firewall_rule" "whitelist" { 65 | depends_on = [local.whitelist_map_pg] 66 | for_each = local.whitelist_map_pg 67 | 68 | name = each.key 69 | server_id = azurerm_postgresql_flexible_server.pg.id 70 | start_ip_address = each.value.start_ip 71 | end_ip_address = each.value.end_ip 72 | } 73 | 74 | # Authz db 75 | # Hent connection string fra Key Vault 76 | # For å feks. oppgrade db versjon, så må en ha admin rettigheter på serveren 77 | data "azurerm_key_vault_secret" "pg_connstr" { 78 | name = "Secrets--PostgreSqlAdminConnectionString" 79 | key_vault_id = azurerm_key_vault.kv.id 80 | } 81 | 82 | locals { 83 | pg_password = regex("Password=([^;]+);", data.azurerm_key_vault_secret.pg_connstr.value)[0] 84 | } 85 | 86 | 87 | resource "azurerm_postgresql_flexible_server" "psql" { 88 | lifecycle { 89 | prevent_destroy = true 90 | } 91 | administrator_login = "oed${var.environment}pgadmin" 92 | administrator_password = local.pg_password 93 | auto_grow_enabled = false 94 | backup_retention_days = 7 95 | location = var.alt_location 96 | name = "oed-${var.environment}-authz-pg" 97 | public_network_access_enabled = true 98 | resource_group_name = azurerm_resource_group.rg.name 99 | sku_name = "B_Standard_B4ms" 100 | version = "16" 101 | zone = "1" 102 | 103 | authentication { 104 | active_directory_auth_enabled = true 105 | password_auth_enabled = true 106 | tenant_id = "cd0026d8-283b-4a55-9bfa-d0ef4a8ba21c" 107 | } 108 | tags = { 109 | "costcenter" = "altinn3" 110 | "solution" = "apps" 111 | } 112 | } 113 | 114 | resource "azurerm_postgresql_flexible_server_database" "oedauthz" { 115 | lifecycle { 116 | prevent_destroy = true 117 | } 118 | name = "oedauthz" 119 | server_id = azurerm_postgresql_flexible_server.psql.id 120 | collation = "en_US.utf8" 121 | charset = "utf8" 122 | } 123 | 124 | resource "azurerm_postgresql_flexible_server_firewall_rule" "authz_whitelist" { 125 | depends_on = [local.whitelist_map_pg] 126 | for_each = local.whitelist_map_pg 127 | 128 | name = each.key 129 | server_id = azurerm_postgresql_flexible_server.psql.id 130 | start_ip_address = each.value.start_ip 131 | end_ip_address = each.value.end_ip 132 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/database.tf: -------------------------------------------------------------------------------- 1 | # PostgreSQL for OED 2 | resource "random_password" "dd_admin_password" { 3 | length = 16 4 | special = true 5 | } 6 | 7 | resource "random_password" "dd_user_password" { 8 | length = 16 9 | special = true 10 | } 11 | 12 | resource "azurerm_postgresql_flexible_server" "pg" { 13 | lifecycle { 14 | ignore_changes = [ 15 | zone 16 | ] 17 | prevent_destroy = true 18 | } 19 | name = "dd-${var.environment}-pg" 20 | location = azurerm_resource_group.rg.location 21 | resource_group_name = azurerm_resource_group.rg.name 22 | administrator_login = "pgadmin" 23 | administrator_password = random_password.dd_admin_password.result 24 | version = "16" 25 | sku_name = "GP_Standard_D2s_v3" 26 | storage_mb = 32768 27 | backup_retention_days = 35 28 | auto_grow_enabled = true 29 | public_network_access_enabled = true 30 | 31 | authentication { 32 | active_directory_auth_enabled = true 33 | password_auth_enabled = true 34 | tenant_id = var.tenant_id 35 | } 36 | maintenance_window { 37 | day_of_week = "2" 38 | start_hour = "1" 39 | start_minute = "4" 40 | } 41 | tags = { 42 | "costcenter" = "altinn3" 43 | "solution" = "apps" 44 | } 45 | } 46 | 47 | resource "azurerm_postgresql_flexible_server_database" "oed_db" { 48 | name = "dd-oed-${var.environment}-pg-db" 49 | server_id = azurerm_postgresql_flexible_server.pg.id 50 | charset = "UTF8" 51 | collation = "en_US.utf8" 52 | } 53 | 54 | locals { 55 | app_user = { 56 | name = "appuser" 57 | password = random_password.dd_user_password.result 58 | } 59 | } 60 | 61 | #Har ikke tilgang til a3 aps kv, så connstringen legges i oed-kv og må flyttes manuelt 62 | resource "azurerm_key_vault_secret" "admin_conn_string" { 63 | name = "dd-pgadmin-connection-string" 64 | value = "Server=${azurerm_postgresql_flexible_server.pg.fqdn};Username=${azurerm_postgresql_flexible_server.pg.administrator_login};Database=${azurerm_postgresql_flexible_server_database.oed_db.name};Port=5432;Password='${random_password.dd_admin_password.result}';SSLMode=Prefer" 65 | key_vault_id = azurerm_key_vault.kv.id 66 | } 67 | 68 | resource "azurerm_key_vault_secret" "user_conn_string" { 69 | name = "OedConfig--Postgres--ConnectionString" 70 | value = "Server=${azurerm_postgresql_flexible_server.pg.fqdn};Username=${local.app_user.name};Database=${azurerm_postgresql_flexible_server_database.oed_db.name};Port=5432;Password='${local.app_user.password}';SSLMode=Prefer" 71 | key_vault_id = azurerm_key_vault.kv.id 72 | } 73 | 74 | resource "azurerm_postgresql_flexible_server_firewall_rule" "whitelist" { 75 | depends_on = [local.whitelist_map_pg] 76 | for_each = local.whitelist_map_pg 77 | 78 | name = each.key 79 | server_id = azurerm_postgresql_flexible_server.pg.id 80 | start_ip_address = each.value.start_ip 81 | end_ip_address = each.value.end_ip 82 | } 83 | 84 | # PostgreSQL for OED Authz 85 | resource "random_password" "psql_oedpgadmin" { 86 | length = 32 87 | special = true 88 | override_special = "!@#$%&*" 89 | } 90 | 91 | resource "azurerm_postgresql_flexible_server" "psql" { 92 | lifecycle { 93 | ignore_changes = [ 94 | zone, 95 | high_availability[0].standby_availability_zone 96 | ] 97 | prevent_destroy = true 98 | } 99 | administrator_login = "oedpgadmin" 100 | administrator_password = random_password.psql_oedpgadmin.result 101 | auto_grow_enabled = true 102 | backup_retention_days = 35 103 | location = azurerm_resource_group.rg.location 104 | name = "oed-authz-pg" 105 | public_network_access_enabled = true 106 | resource_group_name = azurerm_resource_group.rg.name 107 | sku_name = "GP_Standard_D2s_v3" 108 | version = "16" 109 | 110 | authentication { 111 | active_directory_auth_enabled = true 112 | password_auth_enabled = true 113 | tenant_id = "cd0026d8-283b-4a55-9bfa-d0ef4a8ba21c" 114 | } 115 | 116 | maintenance_window { 117 | day_of_week = "2" 118 | start_hour = "1" 119 | start_minute = "4" 120 | } 121 | } 122 | 123 | resource "azurerm_postgresql_flexible_server_database" "oedauthz" { 124 | name = "oedauthz" 125 | server_id = azurerm_postgresql_flexible_server.psql.id 126 | collation = "en_US.utf8" 127 | charset = "utf8" 128 | } 129 | 130 | resource "azurerm_postgresql_flexible_server_firewall_rule" "authz_whitelist" { 131 | depends_on = [local.whitelist_map_pg] 132 | for_each = local.whitelist_map_pg 133 | 134 | name = each.key 135 | server_id = azurerm_postgresql_flexible_server.psql.id 136 | start_ip_address = each.value.start_ip 137 | end_ip_address = each.value.end_ip 138 | } 139 | 140 | resource "azurerm_key_vault_secret" "psql_connect" { 141 | for_each = toset(["Secrets--PostgreSqlAdminConnectionString", "Secrets--PostgreSqlUserConnectionString"]) 142 | name = each.key 143 | value = "Server=${azurerm_postgresql_flexible_server.psql.fqdn};Username=${azurerm_postgresql_flexible_server.psql.administrator_login};Database=oedauthz;Port=5432;Password=${random_password.psql_oedpgadmin.result};SSLMode=Prefer" 144 | key_vault_id = azurerm_key_vault.kv.id 145 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/frontdoor_waf.tf: -------------------------------------------------------------------------------- 1 | # 1. Front Door 2 | resource "azurerm_cdn_frontdoor_profile" "fd_profile" { 3 | name = "oed-fd-profile-${var.environment}" 4 | resource_group_name = azurerm_resource_group.rg.name 5 | sku_name = var.fd_sku_name 6 | } 7 | 8 | resource "azurerm_monitor_diagnostic_setting" "fd_logs" { 9 | name = "frontdoor-logs" 10 | target_resource_id = azurerm_cdn_frontdoor_profile.fd_profile.id 11 | log_analytics_workspace_id = azurerm_log_analytics_workspace.law.id 12 | 13 | enabled_log { 14 | category = "FrontdoorAccessLog" 15 | } 16 | enabled_log { 17 | category = "FrontdoorWebApplicationFirewallLog" 18 | } 19 | enabled_metric { 20 | category = "AllMetrics" 21 | } 22 | } 23 | 24 | # 2. WAF-policy med Geomatch 25 | resource "azurerm_cdn_frontdoor_firewall_policy" "waf_policy" { 26 | name = "oedwafpolicy${var.environment}" 27 | resource_group_name = azurerm_resource_group.rg.name 28 | sku_name = azurerm_cdn_frontdoor_profile.fd_profile.sku_name 29 | enabled = true 30 | mode = "Prevention" 31 | 32 | managed_rule { 33 | action = "Block" 34 | type = "Microsoft_DefaultRuleSet" 35 | version = "2.1" 36 | } 37 | managed_rule { 38 | action = "Block" 39 | type = "Microsoft_BotManagerRuleSet" 40 | version = "1.1" 41 | } 42 | 43 | #Spesifikk blokking fra EU/EUS må ligge først 44 | custom_rule { 45 | name = "BlockTestIP" 46 | priority = 10 47 | type = "MatchRule" 48 | action = "Block" 49 | enabled = false 50 | 51 | match_condition { 52 | match_variable = "RemoteAddr" 53 | operator = "IPMatch" 54 | match_values = ["82.164.55.142"] # ← erstatt med IP-adressen du vil blokkere 55 | } 56 | } 57 | 58 | #GEO open 59 | custom_rule { 60 | name = "AllowEUEOS1" 61 | priority = 21 62 | type = "MatchRule" 63 | action = "Allow" 64 | enabled = true 65 | 66 | match_condition { 67 | match_variable = "RemoteAddr" 68 | operator = "GeoMatch" 69 | match_values = [ 70 | # EØS-land (3) 71 | "IS", "LI", "NO", 72 | #Andre 73 | "CH", 74 | #EU-Land 75 | "SE", "DK", "FI", "EE", "LV" 76 | ] 77 | } 78 | } 79 | 80 | custom_rule { 81 | name = "AllowEUEOS2" 82 | priority = 22 83 | type = "MatchRule" 84 | action = "Allow" 85 | enabled = true 86 | 87 | match_condition { 88 | match_variable = "RemoteAddr" 89 | operator = "GeoMatch" 90 | match_values = [ 91 | # EU-land (27) 92 | "HU", "IE", "IT", "LU", "MT", "NL", "PL", "PT", "RO", "SK" 93 | ] 94 | } 95 | } 96 | 97 | custom_rule { 98 | name = "AllowEUEOS3" 99 | priority = 23 100 | type = "MatchRule" 101 | action = "Allow" 102 | enabled = true 103 | 104 | match_condition { 105 | match_variable = "RemoteAddr" 106 | operator = "GeoMatch" 107 | match_values = [ 108 | # EU-land (27) 109 | "SI", "ES" 110 | ] 111 | } 112 | } 113 | 114 | custom_rule { 115 | name = "DenyAllOthers" 116 | priority = 100 117 | type = "MatchRule" 118 | action = "Block" 119 | enabled = false 120 | 121 | match_condition { 122 | match_variable = "RemoteAddr" 123 | operator = "IPMatch" 124 | match_values = ["0.0.0.0/0"] 125 | } 126 | } 127 | } 128 | 129 | resource "azurerm_cdn_frontdoor_security_policy" "waf_security_policy" { 130 | name = "oed-fd-security-policy-${var.environment}" 131 | cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fd_profile.id 132 | 133 | security_policies { 134 | firewall { 135 | cdn_frontdoor_firewall_policy_id = azurerm_cdn_frontdoor_firewall_policy.waf_policy.id 136 | 137 | association { 138 | domain { 139 | cdn_frontdoor_domain_id = azurerm_cdn_frontdoor_custom_domain.authz_domain.id 140 | } 141 | domain { 142 | cdn_frontdoor_domain_id = azurerm_cdn_frontdoor_endpoint.endpoint.id 143 | } 144 | patterns_to_match = ["/*"] 145 | } 146 | } 147 | } 148 | } 149 | 150 | # 3. Origin group (App Service backend) 151 | resource "azurerm_cdn_frontdoor_origin_group" "origin_group" { 152 | name = "oed-origin-group-${var.environment}" 153 | cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fd_profile.id 154 | 155 | load_balancing {} 156 | } 157 | 158 | resource "azurerm_cdn_frontdoor_origin" "app_origin" { 159 | name = "oed-appservice-origin-${var.environment}" 160 | certificate_name_check_enabled = true 161 | cdn_frontdoor_origin_group_id = azurerm_cdn_frontdoor_origin_group.origin_group.id 162 | host_name = azurerm_linux_web_app.authz_linux.default_hostname 163 | http_port = 80 164 | https_port = 443 165 | enabled = true 166 | origin_host_header = azurerm_linux_web_app.authz_linux.default_hostname 167 | } 168 | 169 | # 4. Front Door Endpoint 170 | resource "azurerm_cdn_frontdoor_endpoint" "endpoint" { 171 | name = "digdir-dd-${var.environment}-authz" #første del av url med fdurl : med "azurefd.net" som postfix 172 | cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fd_profile.id 173 | } 174 | 175 | # 5. Custom domain 176 | resource "azurerm_cdn_frontdoor_custom_domain" "authz_domain" { 177 | name = "authzdigitaltdodsbo${var.environment}" 178 | cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.fd_profile.id 179 | host_name = var.authz_custom_domain 180 | 181 | tls { 182 | certificate_type = "ManagedCertificate" 183 | } 184 | } 185 | 186 | output "frontdoor_dns_validation_txt_name" { 187 | value = "_dnsauth.${var.authz_custom_domain}" 188 | } 189 | 190 | output "frontdoor_dns_validation_txt_value" { 191 | value = azurerm_cdn_frontdoor_custom_domain.authz_domain.validation_token 192 | description = "Opprett TXT-record på _dnsauth.var.authz_custom_domain med denne verdien for å validere domene hos Front Door." 193 | } 194 | 195 | # digitaltdodsbo.altinn.no CNAME -> ${azurerm_cdn_frontdoor_endpoint.endpoint.host_name} 196 | output "frontdoor_cname_target" { 197 | value = azurerm_cdn_frontdoor_endpoint.endpoint.host_name 198 | description = "Sett CNAME for digitaltdodsbo.altinn.no til denne verdien for cutover." 199 | } 200 | 201 | # 6. Route + WAF-link 202 | resource "azurerm_cdn_frontdoor_route" "route" { 203 | name = "default-route-${var.environment}" 204 | cdn_frontdoor_endpoint_id = azurerm_cdn_frontdoor_endpoint.endpoint.id 205 | cdn_frontdoor_origin_group_id = azurerm_cdn_frontdoor_origin_group.origin_group.id 206 | cdn_frontdoor_origin_ids = [azurerm_cdn_frontdoor_origin.app_origin.id] 207 | 208 | cdn_frontdoor_custom_domain_ids = [ 209 | azurerm_cdn_frontdoor_custom_domain.authz_domain.id 210 | ] 211 | supported_protocols = ["Https", "Http"] 212 | patterns_to_match = ["/*"] 213 | forwarding_protocol = "HttpsOnly" 214 | link_to_default_domain = true 215 | https_redirect_enabled = true 216 | } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/web-app-admin.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | app_hostname = "dd-${var.environment}-admin-app.azurewebsites.net" 3 | } 4 | 5 | resource "azuread_application" "admin_app_reg" { 6 | display_name = "dd-${var.environment}-admin-app" 7 | owners = [data.azurerm_client_config.current.object_id] 8 | group_membership_claims = ["All"] # Include group membership claims in the token 9 | # This is required to allow the app to read group memberships of users 10 | required_resource_access { 11 | resource_app_id = "00000003-0000-0000-c000-000000000000" # Microsoft Graph 12 | resource_access { 13 | id = "5b567255-7703-4780-807c-7be8301ae99b" # GroupMember.Read.All 14 | type = "Scope" 15 | } 16 | } 17 | web { 18 | redirect_uris = [ 19 | "https://${local.app_hostname}/.auth/login/aad/callback" 20 | ] 21 | implicit_grant { 22 | access_token_issuance_enabled = true 23 | id_token_issuance_enabled = true 24 | } 25 | } 26 | } 27 | 28 | resource "azuread_service_principal" "admin_app_sp" { 29 | client_id = azuread_application.admin_app_reg.client_id 30 | owners = [data.azurerm_client_config.current.object_id] 31 | } 32 | 33 | resource "azuread_application_password" "admin_app_secret_V2" { 34 | application_id = azuread_application.admin_app_reg.id 35 | display_name = azuread_application.admin_app_reg.display_name 36 | } 37 | 38 | resource "azurerm_key_vault_secret" "aad_secret" { 39 | name = "OedAdmin--MicrosoftProviderAuthSecret" 40 | value = azuread_application_password.admin_app_secret_V2.value 41 | key_vault_id = azurerm_key_vault.kv.id 42 | } 43 | 44 | resource "azurerm_service_plan" "admin_asp" { 45 | name = "asp-altinndigdir-dd-${var.environment}-admin" 46 | location = azurerm_resource_group.rg.location 47 | resource_group_name = azurerm_resource_group.rg.name 48 | os_type = "Linux" 49 | sku_name = "B1" 50 | } 51 | 52 | resource "azurerm_linux_web_app" "admin_app" { 53 | depends_on = [azurerm_service_plan.admin_asp] 54 | lifecycle { 55 | ignore_changes = [ 56 | tags["hidden-link: /app-insights-resource-id"] 57 | ] 58 | } 59 | name = "dd-${var.environment}-admin-app" 60 | location = azurerm_resource_group.rg.location 61 | resource_group_name = azurerm_resource_group.rg.name 62 | service_plan_id = azurerm_service_plan.admin_asp.id 63 | https_only = true 64 | 65 | app_settings = { 66 | "DOTNET_ENVIRONMENT" = "Production" 67 | "ASPNETCORE_ENVIRONMENT" = "Production" 68 | "ConnectionStrings__OedDb" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedConfig--Postgres--ConnectionString)" 69 | "ConnectionStrings__OedAuthzDb" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--PostgreSqlUserConnectionString)" 70 | "APPINSIGHTS_INSTRUMENTATIONKEY" = azurerm_application_insights.adminapp_ai.instrumentation_key 71 | "APPLICATIONINSIGHTS_CONNECTION_STRING" = azurerm_application_insights.adminapp_ai.connection_string 72 | "ApplicationInsightsAgent_EXTENSION_VERSION" = "~3" 73 | "WEBSITE_AUTH_AAD_ALLOWED_TENANTS" = var.tenant_id 74 | "AzureEntraId__ClientId" = azuread_application.admin_ad_app.client_id 75 | "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=${azurerm_key_vault_secret.aad_secret.name})" 76 | "MaskinportenSettings__ClientId" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedAdmin--MaskinportenSettings--ClientId)" 77 | "MaskinportenSettings__Environment" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedAdmin--MaskinportenSettings--Environment)" 78 | "MaskinportenSettings__EncodedJwk" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedAdmin--MaskinportenSettings--EncodedJwk)" 79 | "AltinnSettings__PlatformUrl" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedAdmin--AltinnSettings--PlatformUrl)" 80 | } 81 | 82 | tags = { 83 | "costcenter" = "altinn3" 84 | "solution" = "apps" 85 | "hidden-link: /app-insights-conn-string" = azurerm_application_insights.adminapp_ai.connection_string 86 | "hidden-link: /app-insights-instrumentation-key" = azurerm_application_insights.adminapp_ai.instrumentation_key 87 | "hidden-link: /app-insights-resource-id" = azurerm_application_insights.adminapp_ai.id 88 | } 89 | 90 | site_config { 91 | minimum_tls_version = "1.3" 92 | application_stack { 93 | dotnet_version = "10.0" 94 | } 95 | always_on = true 96 | } 97 | 98 | identity { 99 | type = "SystemAssigned" 100 | } 101 | 102 | auth_settings_v2 { 103 | auth_enabled = true 104 | require_authentication = true 105 | default_provider = "azureactivedirectory" 106 | unauthenticated_action = "RedirectToLoginPage" 107 | excluded_paths = ["/health", "/scalar"] 108 | 109 | active_directory_v2 { 110 | client_id = azuread_application.admin_app_reg.client_id 111 | tenant_auth_endpoint = "https://login.microsoftonline.com/${var.tenant_id}/v2.0/" 112 | client_secret_setting_name = "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" 113 | #allowed_groups = [var.admin_app_user_group_id] 114 | } 115 | 116 | login { 117 | token_store_enabled = true 118 | } 119 | } 120 | } 121 | 122 | resource "azurerm_key_vault_access_policy" "dd_admin_read_secrets" { 123 | depends_on = [azurerm_linux_web_app.admin_app] 124 | key_vault_id = azurerm_key_vault.kv.id 125 | tenant_id = azurerm_linux_web_app.admin_app.identity[0].tenant_id 126 | object_id = azurerm_linux_web_app.admin_app.identity[0].principal_id 127 | 128 | secret_permissions = [ 129 | "Get", 130 | "List" 131 | ] 132 | } 133 | 134 | # Legger client secret som har utløpsdato i keyvault slik at vi kan følge opp. 135 | resource "azurerm_key_vault_secret" "admin_app_client_secret" { 136 | depends_on = [azuread_application_password.admin_app_secret_V2] 137 | name = "dd-admin-app-client-secret" 138 | value = azuread_application_password.admin_app_secret_V2.value 139 | expiration_date = formatdate("YYYY-MM-DD'T'hh:mm:ss'Z'", azuread_application_password.admin_app_secret_V2.end_date) 140 | not_before_date = formatdate("YYYY-MM-DD'T'hh:mm:ss'Z'", azuread_application_password.admin_app_secret_V2.start_date) 141 | key_vault_id = azurerm_key_vault.kv.id 142 | } 143 | 144 | # Ingen tilgang til github action bruker 145 | # Access til systembruker for å lese secrets direkte fra a3 keyvault 146 | # resource "azurerm_key_vault_access_policy" "admin_app_system_user_a3_kvap" { 147 | # depends_on = [data.azurerm_key_vault.a3_kv] 148 | # key_vault_id = data.azurerm_key_vault.a3_kv.id 149 | # tenant_id = data.azurerm_client_config.current.tenant_id 150 | # object_id = azurerm_linux_web_app.admin_app.identity[0].principal_id 151 | # key_permissions = ["Get", "List"] 152 | # secret_permissions = ["Get", "List"] 153 | # certificate_permissions = ["Get", "List"] 154 | # } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/web-app-admin.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | app_hostname = "dd-${var.environment}-admin-app.azurewebsites.net" 3 | } 4 | 5 | resource "azuread_application" "admin_app_reg" { 6 | display_name = "dd-${var.environment}-admin-app" 7 | owners = [data.azurerm_client_config.current.object_id] 8 | group_membership_claims = ["SecurityGroup"] # Include group membership claims in the token 9 | # This is required to allow the app to read group memberships of users 10 | required_resource_access { 11 | resource_app_id = "00000003-0000-0000-c000-000000000000" # Microsoft Graph 12 | resource_access { 13 | id = "5b567255-7703-4780-807c-7be8301ae99b" # GroupMember.Read.All 14 | type = "Scope" 15 | } 16 | } 17 | web { 18 | redirect_uris = [ 19 | "https://${local.app_hostname}/.auth/login/aad/callback" 20 | ] 21 | implicit_grant { 22 | access_token_issuance_enabled = true 23 | id_token_issuance_enabled = true 24 | } 25 | } 26 | } 27 | 28 | resource "azuread_service_principal" "admin_app_sp" { 29 | client_id = azuread_application.admin_app_reg.client_id 30 | owners = [data.azurerm_client_config.current.object_id] 31 | } 32 | 33 | resource "azuread_application_password" "admin_app_secret_V2" { 34 | application_id = azuread_application.admin_app_reg.id 35 | display_name = azuread_application.admin_app_reg.display_name 36 | } 37 | 38 | resource "azurerm_key_vault_secret" "aad_secret" { 39 | name = "OedAdmin--MicrosoftProviderAuthSecret" 40 | value = azuread_application_password.admin_app_secret_V2.value 41 | key_vault_id = azurerm_key_vault.kv.id 42 | } 43 | 44 | resource "azurerm_service_plan" "admin_asp" { 45 | name = "asp-altinndigdir-dd-${var.environment}-admin" 46 | location = azurerm_resource_group.rg.location 47 | resource_group_name = azurerm_resource_group.rg.name 48 | os_type = "Linux" 49 | sku_name = "B1" 50 | } 51 | 52 | resource "azurerm_linux_web_app" "admin_app" { 53 | depends_on = [azurerm_service_plan.admin_asp] 54 | lifecycle { 55 | ignore_changes = [ 56 | tags["hidden-link: /app-insights-resource-id"] 57 | ] 58 | } 59 | name = "dd-${var.environment}-admin-app" 60 | location = azurerm_resource_group.rg.location 61 | resource_group_name = azurerm_resource_group.rg.name 62 | service_plan_id = azurerm_service_plan.admin_asp.id 63 | https_only = true 64 | 65 | app_settings = { 66 | "DOTNET_ENVIRONMENT" = "Staging" 67 | "ASPNETCORE_ENVIRONMENT" = "Staging" 68 | "ConnectionStrings__OedDb" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedConfig--Postgres--ConnectionString)" 69 | "ConnectionStrings__OedAuthzDb" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=Secrets--PostgreSqlUserConnectionString)" 70 | "APPINSIGHTS_INSTRUMENTATIONKEY" = azurerm_application_insights.adminapp_ai.instrumentation_key 71 | "APPLICATIONINSIGHTS_CONNECTION_STRING" = azurerm_application_insights.adminapp_ai.connection_string 72 | "ApplicationInsightsAgent_EXTENSION_VERSION" = "~3" 73 | "WEBSITE_AUTH_AAD_ALLOWED_TENANTS" = var.tenant_id 74 | "AzureEntraId__ClientId" = azuread_application.admin_ad_app.client_id 75 | "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=${azurerm_key_vault_secret.aad_secret.name})" 76 | "MaskinportenSettings__ClientId" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedAdmin--MaskinportenSettings--ClientId)" 77 | "MaskinportenSettings__Environment" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedAdmin--MaskinportenSettings--Environment)" 78 | "MaskinportenSettings__EncodedJwk" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedAdmin--MaskinportenSettings--EncodedJwk)" 79 | "AltinnSettings__PlatformUrl" = "@Microsoft.KeyVault(VaultName=${azurerm_key_vault.kv.name};SecretName=OedAdmin--AltinnSettings--PlatformUrl)" 80 | } 81 | 82 | tags = { 83 | "costcenter" = "altinn3" 84 | "solution" = "apps" 85 | "hidden-link: /app-insights-conn-string" = azurerm_application_insights.adminapp_ai.connection_string 86 | "hidden-link: /app-insights-instrumentation-key" = azurerm_application_insights.adminapp_ai.instrumentation_key 87 | "hidden-link: /app-insights-resource-id" = azurerm_application_insights.adminapp_ai.id 88 | } 89 | 90 | site_config { 91 | minimum_tls_version = "1.3" 92 | application_stack { 93 | dotnet_version = "10.0" 94 | } 95 | always_on = true 96 | } 97 | 98 | identity { 99 | type = "SystemAssigned" 100 | } 101 | 102 | auth_settings_v2 { 103 | auth_enabled = true 104 | require_authentication = true 105 | default_provider = "azureactivedirectory" 106 | unauthenticated_action = "RedirectToLoginPage" 107 | excluded_paths = ["/health", "/scalar"] 108 | 109 | active_directory_v2 { 110 | client_id = azuread_application.admin_app_reg.client_id 111 | tenant_auth_endpoint = "https://login.microsoftonline.com/${var.tenant_id}/v2.0/" 112 | client_secret_setting_name = "MICROSOFT_PROVIDER_AUTHENTICATION_SECRET" 113 | #allowed_groups = [var.admin_app_user_group_id] 114 | } 115 | 116 | login { 117 | token_store_enabled = true 118 | } 119 | } 120 | } 121 | 122 | #Access til systembruker for å lese secrets direkte fra oed keyvault 123 | resource "azurerm_key_vault_access_policy" "dd_admin_read_secrets" { 124 | depends_on = [azurerm_linux_web_app.admin_app] 125 | key_vault_id = azurerm_key_vault.kv.id 126 | tenant_id = azurerm_linux_web_app.admin_app.identity[0].tenant_id 127 | object_id = azurerm_linux_web_app.admin_app.identity[0].principal_id 128 | 129 | key_permissions = ["Get", "List"] 130 | secret_permissions = ["Get", "List"] 131 | certificate_permissions = ["Get", "List"] 132 | } 133 | 134 | # Legger client secret som har utløpsdato i keyvault slik at vi kan følge opp. 135 | resource "azurerm_key_vault_secret" "admin_app_client_secret" { 136 | depends_on = [azuread_application_password.admin_app_secret_V2] 137 | name = "dd-admin-app-client-secret" 138 | value = azuread_application_password.admin_app_secret_V2.value 139 | expiration_date = formatdate("YYYY-MM-DD'T'hh:mm:ss'Z'", azuread_application_password.admin_app_secret_V2.end_date) 140 | not_before_date = formatdate("YYYY-MM-DD'T'hh:mm:ss'Z'", azuread_application_password.admin_app_secret_V2.start_date) 141 | key_vault_id = azurerm_key_vault.kv.id 142 | } 143 | 144 | # Ingen tilgang til github action bruker 145 | # Access til systembruker for å lese secrets direkte fra a3 keyvault 146 | # resource "azurerm_key_vault_access_policy" "admin_app_system_user_a3_kvap" { 147 | # depends_on = [data.azurerm_key_vault.a3_kv] 148 | # key_vault_id = data.azurerm_key_vault.a3_kv.id 149 | # tenant_id = data.azurerm_client_config.current.tenant_id 150 | # object_id = azurerm_linux_web_app.admin_app.identity[0].principal_id 151 | # key_permissions = ["Get", "List"] 152 | # secret_permissions = ["Get", "List"] 153 | # certificate_permissions = ["Get", "List"] 154 | # } -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-tt02-rg/dashboard.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_portal_dashboard" "dashboards" { 2 | dashboard_properties = jsonencode({ 3 | lenses = { 4 | "0" = { 5 | order = 0 6 | parts = { 7 | "0" = { 8 | metadata = { 9 | asset = { 10 | idInputName = "id" 11 | type = "ApplicationInsights" 12 | } 13 | defaultMenuItemId = "overview" 14 | inputs = [{ 15 | name = "id" 16 | value = azurerm_application_insights.authz_ai.id 17 | }, { 18 | name = "Version" 19 | value = "1.0" 20 | }] 21 | type = "Extension/AppInsightsExtension/PartType/AspNetOverviewPinnedPart" 22 | } 23 | position = { 24 | colSpan = 2 25 | rowSpan = 1 26 | x = 0 27 | y = 0 28 | } 29 | } 30 | "1" = { 31 | metadata = { 32 | asset = { 33 | idInputName = "ComponentId" 34 | type = "ApplicationInsights" 35 | } 36 | defaultMenuItemId = "ProactiveDetection" 37 | inputs = [{ 38 | name = "ComponentId" 39 | value = { 40 | Name = azurerm_application_insights.authz_ai.name 41 | ResourceGroup = azurerm_resource_group.rg.name 42 | SubscriptionId = var.subscription_id 43 | } 44 | }, { 45 | name = "Version" 46 | value = "1.0" 47 | }] 48 | type = "Extension/AppInsightsExtension/PartType/ProactiveDetectionAsyncPart" 49 | } 50 | position = { 51 | colSpan = 1 52 | rowSpan = 1 53 | x = 2 54 | y = 0 55 | } 56 | } 57 | "10" = { 58 | metadata = { 59 | asset = { 60 | idInputName = "ResourceId" 61 | type = "ApplicationInsights" 62 | } 63 | defaultMenuItemId = "performance" 64 | inputs = [{ 65 | name = "ResourceId" 66 | value = azurerm_application_insights.authz_ai.id 67 | }, { 68 | isOptional = true 69 | name = "DataModel" 70 | value = { 71 | timeContext = { 72 | createdTime = "2018-05-04T23:43:37.804Z" 73 | durationMs = 86400000 74 | grain = 1 75 | isInitialTime = false 76 | useDashboardTimeRange = false 77 | } 78 | version = "1.0.0" 79 | } 80 | }, { 81 | isOptional = true 82 | name = "ConfigurationId" 83 | value = "2a8ede4f-2bee-4b9c-aed9-2db0e8a01865" 84 | }] 85 | isAdapter = true 86 | type = "Extension/AppInsightsExtension/PartType/CuratedBladePerformancePinnedPart" 87 | } 88 | position = { 89 | colSpan = 1 90 | rowSpan = 1 91 | x = 11 92 | y = 1 93 | } 94 | } 95 | "11" = { 96 | metadata = { 97 | inputs = [] 98 | settings = { 99 | content = { 100 | settings = { 101 | content = "# Browser" 102 | subtitle = "" 103 | title = "" 104 | } 105 | } 106 | } 107 | type = "Extension[azure]/HubsExtension/PartType/MarkdownPart" 108 | } 109 | position = { 110 | colSpan = 3 111 | rowSpan = 1 112 | x = 12 113 | y = 1 114 | } 115 | } 116 | "12" = { 117 | metadata = { 118 | asset = { 119 | idInputName = "ComponentId" 120 | type = "ApplicationInsights" 121 | } 122 | defaultMenuItemId = "browser" 123 | inputs = [{ 124 | name = "ComponentId" 125 | value = { 126 | Name = azurerm_application_insights.authz_ai.name 127 | ResourceGroup = azurerm_resource_group.rg.name 128 | SubscriptionId = var.subscription_id 129 | } 130 | }, { 131 | name = "MetricsExplorerJsonDefinitionId" 132 | value = "BrowserPerformanceTimelineMetrics" 133 | }, { 134 | name = "TimeContext" 135 | value = { 136 | createdTime = "2018-05-08T12:16:27.534Z" 137 | durationMs = 86400000 138 | grain = 1 139 | isInitialTime = false 140 | useDashboardTimeRange = false 141 | } 142 | }, { 143 | name = "CurrentFilter" 144 | value = { 145 | eventTypes = [4, 1, 3, 5, 2, 6, 13] 146 | isPermissive = false 147 | typeFacets = {} 148 | } 149 | }, { 150 | name = "id" 151 | value = { 152 | Name = azurerm_application_insights.authz_ai.name 153 | ResourceGroup = azurerm_resource_group.rg.name 154 | SubscriptionId = var.subscription_id 155 | } 156 | }, { 157 | name = "Version" 158 | value = "1.0" 159 | }] 160 | type = "Extension/AppInsightsExtension/PartType/MetricsExplorerBladePinnedPart" 161 | } 162 | position = { 163 | colSpan = 1 164 | rowSpan = 1 165 | x = 15 166 | y = 1 167 | } 168 | } 169 | "13" = { 170 | metadata = { 171 | inputs = [{ 172 | name = "options" 173 | value = { 174 | chart = { 175 | metrics = [{ 176 | aggregationType = 5 177 | metricVisualization = { 178 | color = "#47BDF5" 179 | displayName = "Sessions" 180 | } 181 | name = "sessions/count" 182 | namespace = "microsoft.insights/components/kusto" 183 | resourceMetadata = { 184 | id = azurerm_application_insights.authz_ai.id 185 | } 186 | }, { 187 | aggregationType = 5 188 | metricVisualization = { 189 | color = "#7E58FF" 190 | displayName = "Users" 191 | } 192 | name = "users/count" 193 | namespace = "microsoft.insights/components/kusto" 194 | resourceMetadata = { 195 | id = azurerm_application_insights.authz_ai.id 196 | } 197 | }] 198 | openBladeOnClick = { 199 | destinationBlade = { 200 | bladeName = "ResourceMenuBlade" 201 | extensionName = "HubsExtension" 202 | parameters = { 203 | id = azurerm_application_insights.authz_ai.id 204 | menuid = "segmentationUsers" 205 | } 206 | } 207 | openBlade = true 208 | } 209 | title = "Unique sessions and users" 210 | visualization = { 211 | axisVisualization = { 212 | x = { 213 | axisType = 2 214 | isVisible = true 215 | } 216 | y = { 217 | axisType = 1 218 | isVisible = true 219 | } 220 | } 221 | chartType = 2 222 | legendVisualization = { 223 | hideSubtitle = false 224 | isVisible = true 225 | position = 2 226 | } 227 | } 228 | } 229 | } 230 | }, { 231 | isOptional = true 232 | name = "sharedTimeRange" 233 | }] 234 | settings = {} 235 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 236 | } 237 | position = { 238 | colSpan = 4 239 | rowSpan = 3 240 | x = 0 241 | y = 2 242 | } 243 | } 244 | "14" = { 245 | metadata = { 246 | inputs = [{ 247 | name = "options" 248 | value = { 249 | chart = { 250 | metrics = [{ 251 | aggregationType = 7 252 | metricVisualization = { 253 | color = "#EC008C" 254 | displayName = "Failed requests" 255 | } 256 | name = "requests/failed" 257 | namespace = "microsoft.insights/components" 258 | resourceMetadata = { 259 | id = azurerm_application_insights.authz_ai.id 260 | } 261 | }] 262 | openBladeOnClick = { 263 | destinationBlade = { 264 | bladeName = "ResourceMenuBlade" 265 | extensionName = "HubsExtension" 266 | parameters = { 267 | id = azurerm_application_insights.authz_ai.id 268 | menuid = "failures" 269 | } 270 | } 271 | openBlade = true 272 | } 273 | title = "Failed requests" 274 | visualization = { 275 | axisVisualization = { 276 | x = { 277 | axisType = 2 278 | isVisible = true 279 | } 280 | y = { 281 | axisType = 1 282 | isVisible = true 283 | } 284 | } 285 | chartType = 3 286 | legendVisualization = { 287 | hideSubtitle = false 288 | isVisible = true 289 | position = 2 290 | } 291 | } 292 | } 293 | } 294 | }, { 295 | isOptional = true 296 | name = "sharedTimeRange" 297 | }] 298 | settings = {} 299 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 300 | } 301 | position = { 302 | colSpan = 4 303 | rowSpan = 3 304 | x = 4 305 | y = 2 306 | } 307 | } 308 | "15" = { 309 | metadata = { 310 | inputs = [{ 311 | name = "options" 312 | value = { 313 | chart = { 314 | metrics = [{ 315 | aggregationType = 4 316 | metricVisualization = { 317 | color = "#00BCF2" 318 | displayName = "Server response time" 319 | } 320 | name = "requests/duration" 321 | namespace = "microsoft.insights/components" 322 | resourceMetadata = { 323 | id = azurerm_application_insights.authz_ai.id 324 | } 325 | }] 326 | openBladeOnClick = { 327 | destinationBlade = { 328 | bladeName = "ResourceMenuBlade" 329 | extensionName = "HubsExtension" 330 | parameters = { 331 | id = azurerm_application_insights.authz_ai.id 332 | menuid = "performance" 333 | } 334 | } 335 | openBlade = true 336 | } 337 | title = "Server response time" 338 | visualization = { 339 | axisVisualization = { 340 | x = { 341 | axisType = 2 342 | isVisible = true 343 | } 344 | y = { 345 | axisType = 1 346 | isVisible = true 347 | } 348 | } 349 | chartType = 2 350 | legendVisualization = { 351 | hideSubtitle = false 352 | isVisible = true 353 | position = 2 354 | } 355 | } 356 | } 357 | } 358 | }, { 359 | isOptional = true 360 | name = "sharedTimeRange" 361 | }] 362 | settings = {} 363 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 364 | } 365 | position = { 366 | colSpan = 4 367 | rowSpan = 3 368 | x = 8 369 | y = 2 370 | } 371 | } 372 | "16" = { 373 | metadata = { 374 | inputs = [{ 375 | name = "options" 376 | value = { 377 | chart = { 378 | metrics = [{ 379 | aggregationType = 4 380 | metricVisualization = { 381 | color = "#7E58FF" 382 | displayName = "Page load network connect time" 383 | } 384 | name = "browserTimings/networkDuration" 385 | namespace = "microsoft.insights/components" 386 | resourceMetadata = { 387 | id = azurerm_application_insights.authz_ai.id 388 | } 389 | }, { 390 | aggregationType = 4 391 | metricVisualization = { 392 | color = "#44F1C8" 393 | displayName = "Client processing time" 394 | } 395 | name = "browserTimings/processingDuration" 396 | namespace = "microsoft.insights/components" 397 | resourceMetadata = { 398 | id = azurerm_application_insights.authz_ai.id 399 | } 400 | }, { 401 | aggregationType = 4 402 | metricVisualization = { 403 | color = "#EB9371" 404 | displayName = "Send request time" 405 | } 406 | name = "browserTimings/sendDuration" 407 | namespace = "microsoft.insights/components" 408 | resourceMetadata = { 409 | id = azurerm_application_insights.authz_ai.id 410 | } 411 | }, { 412 | aggregationType = 4 413 | metricVisualization = { 414 | color = "#0672F1" 415 | displayName = "Receiving response time" 416 | } 417 | name = "browserTimings/receiveDuration" 418 | namespace = "microsoft.insights/components" 419 | resourceMetadata = { 420 | id = azurerm_application_insights.authz_ai.id 421 | } 422 | }] 423 | title = "Average page load time breakdown" 424 | visualization = { 425 | axisVisualization = { 426 | x = { 427 | axisType = 2 428 | isVisible = true 429 | } 430 | y = { 431 | axisType = 1 432 | isVisible = true 433 | } 434 | } 435 | chartType = 3 436 | legendVisualization = { 437 | hideSubtitle = false 438 | isVisible = true 439 | position = 2 440 | } 441 | } 442 | } 443 | } 444 | }, { 445 | isOptional = true 446 | name = "sharedTimeRange" 447 | }] 448 | settings = {} 449 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 450 | } 451 | position = { 452 | colSpan = 4 453 | rowSpan = 3 454 | x = 12 455 | y = 2 456 | } 457 | } 458 | "17" = { 459 | metadata = { 460 | inputs = [{ 461 | name = "options" 462 | value = { 463 | chart = { 464 | metrics = [{ 465 | aggregationType = 4 466 | metricVisualization = { 467 | color = "#47BDF5" 468 | displayName = "Availability" 469 | } 470 | name = "availabilityResults/availabilityPercentage" 471 | namespace = "microsoft.insights/components" 472 | resourceMetadata = { 473 | id = azurerm_application_insights.authz_ai.id 474 | } 475 | }] 476 | openBladeOnClick = { 477 | destinationBlade = { 478 | bladeName = "ResourceMenuBlade" 479 | extensionName = "HubsExtension" 480 | parameters = { 481 | id = azurerm_application_insights.authz_ai.id 482 | menuid = "availability" 483 | } 484 | } 485 | openBlade = true 486 | } 487 | title = "Average availability" 488 | visualization = { 489 | axisVisualization = { 490 | x = { 491 | axisType = 2 492 | isVisible = true 493 | } 494 | y = { 495 | axisType = 1 496 | isVisible = true 497 | } 498 | } 499 | chartType = 3 500 | legendVisualization = { 501 | hideSubtitle = false 502 | isVisible = true 503 | position = 2 504 | } 505 | } 506 | } 507 | } 508 | }, { 509 | isOptional = true 510 | name = "sharedTimeRange" 511 | }] 512 | settings = {} 513 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 514 | } 515 | position = { 516 | colSpan = 4 517 | rowSpan = 3 518 | x = 0 519 | y = 5 520 | } 521 | } 522 | "18" = { 523 | metadata = { 524 | inputs = [{ 525 | name = "options" 526 | value = { 527 | chart = { 528 | metrics = [{ 529 | aggregationType = 7 530 | metricVisualization = { 531 | color = "#47BDF5" 532 | displayName = "Server exceptions" 533 | } 534 | name = "exceptions/server" 535 | namespace = "microsoft.insights/components" 536 | resourceMetadata = { 537 | id = azurerm_application_insights.authz_ai.id 538 | } 539 | }, { 540 | aggregationType = 7 541 | metricVisualization = { 542 | color = "#7E58FF" 543 | displayName = "Dependency failures" 544 | } 545 | name = "dependencies/failed" 546 | namespace = "microsoft.insights/components" 547 | resourceMetadata = { 548 | id = azurerm_application_insights.authz_ai.id 549 | } 550 | }] 551 | title = "Server exceptions and Dependency failures" 552 | visualization = { 553 | axisVisualization = { 554 | x = { 555 | axisType = 2 556 | isVisible = true 557 | } 558 | y = { 559 | axisType = 1 560 | isVisible = true 561 | } 562 | } 563 | chartType = 2 564 | legendVisualization = { 565 | hideSubtitle = false 566 | isVisible = true 567 | position = 2 568 | } 569 | } 570 | } 571 | } 572 | }, { 573 | isOptional = true 574 | name = "sharedTimeRange" 575 | }] 576 | settings = {} 577 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 578 | } 579 | position = { 580 | colSpan = 4 581 | rowSpan = 3 582 | x = 4 583 | y = 5 584 | } 585 | } 586 | "19" = { 587 | metadata = { 588 | inputs = [{ 589 | name = "options" 590 | value = { 591 | chart = { 592 | metrics = [{ 593 | aggregationType = 4 594 | metricVisualization = { 595 | color = "#47BDF5" 596 | displayName = "Processor time" 597 | } 598 | name = "performanceCounters/processorCpuPercentage" 599 | namespace = "microsoft.insights/components" 600 | resourceMetadata = { 601 | id = azurerm_application_insights.authz_ai.id 602 | } 603 | }, { 604 | aggregationType = 4 605 | metricVisualization = { 606 | color = "#7E58FF" 607 | displayName = "Process CPU" 608 | } 609 | name = "performanceCounters/processCpuPercentage" 610 | namespace = "microsoft.insights/components" 611 | resourceMetadata = { 612 | id = azurerm_application_insights.authz_ai.id 613 | } 614 | }] 615 | title = "Average processor and process CPU utilization" 616 | visualization = { 617 | axisVisualization = { 618 | x = { 619 | axisType = 2 620 | isVisible = true 621 | } 622 | y = { 623 | axisType = 1 624 | isVisible = true 625 | } 626 | } 627 | chartType = 2 628 | legendVisualization = { 629 | hideSubtitle = false 630 | isVisible = true 631 | position = 2 632 | } 633 | } 634 | } 635 | } 636 | }, { 637 | isOptional = true 638 | name = "sharedTimeRange" 639 | }] 640 | settings = {} 641 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 642 | } 643 | position = { 644 | colSpan = 4 645 | rowSpan = 3 646 | x = 8 647 | y = 5 648 | } 649 | } 650 | "2" = { 651 | metadata = { 652 | asset = { 653 | idInputName = "ComponentId" 654 | type = "ApplicationInsights" 655 | } 656 | inputs = [{ 657 | name = "ComponentId" 658 | value = { 659 | Name = azurerm_application_insights.authz_ai.name 660 | ResourceGroup = azurerm_resource_group.rg.name 661 | SubscriptionId = var.subscription_id 662 | } 663 | }, { 664 | name = "ResourceId" 665 | value = azurerm_application_insights.authz_ai.id 666 | }] 667 | type = "Extension/AppInsightsExtension/PartType/QuickPulseButtonSmallPart" 668 | } 669 | position = { 670 | colSpan = 1 671 | rowSpan = 1 672 | x = 3 673 | y = 0 674 | } 675 | } 676 | "20" = { 677 | metadata = { 678 | inputs = [{ 679 | name = "options" 680 | value = { 681 | chart = { 682 | metrics = [{ 683 | aggregationType = 7 684 | metricVisualization = { 685 | color = "#47BDF5" 686 | displayName = "Browser exceptions" 687 | } 688 | name = "exceptions/browser" 689 | namespace = "microsoft.insights/components" 690 | resourceMetadata = { 691 | id = azurerm_application_insights.authz_ai.id 692 | } 693 | }] 694 | title = "Browser exceptions" 695 | visualization = { 696 | axisVisualization = { 697 | x = { 698 | axisType = 2 699 | isVisible = true 700 | } 701 | y = { 702 | axisType = 1 703 | isVisible = true 704 | } 705 | } 706 | chartType = 2 707 | legendVisualization = { 708 | hideSubtitle = false 709 | isVisible = true 710 | position = 2 711 | } 712 | } 713 | } 714 | } 715 | }, { 716 | isOptional = true 717 | name = "sharedTimeRange" 718 | }] 719 | settings = {} 720 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 721 | } 722 | position = { 723 | colSpan = 4 724 | rowSpan = 3 725 | x = 12 726 | y = 5 727 | } 728 | } 729 | "21" = { 730 | metadata = { 731 | inputs = [{ 732 | name = "options" 733 | value = { 734 | chart = { 735 | metrics = [{ 736 | aggregationType = 7 737 | metricVisualization = { 738 | color = "#47BDF5" 739 | displayName = "Availability ${var.environment} results count" 740 | } 741 | name = "availabilityResults/count" 742 | namespace = "microsoft.insights/components" 743 | resourceMetadata = { 744 | id = azurerm_application_insights.authz_ai.id 745 | } 746 | }] 747 | title = "Availability ${var.environment} results count" 748 | visualization = { 749 | axisVisualization = { 750 | x = { 751 | axisType = 2 752 | isVisible = true 753 | } 754 | y = { 755 | axisType = 1 756 | isVisible = true 757 | } 758 | } 759 | chartType = 2 760 | legendVisualization = { 761 | hideSubtitle = false 762 | isVisible = true 763 | position = 2 764 | } 765 | } 766 | } 767 | } 768 | }, { 769 | isOptional = true 770 | name = "sharedTimeRange" 771 | }] 772 | settings = {} 773 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 774 | } 775 | position = { 776 | colSpan = 4 777 | rowSpan = 3 778 | x = 0 779 | y = 8 780 | } 781 | } 782 | "22" = { 783 | metadata = { 784 | inputs = [{ 785 | name = "options" 786 | value = { 787 | chart = { 788 | metrics = [{ 789 | aggregationType = 4 790 | metricVisualization = { 791 | color = "#47BDF5" 792 | displayName = "Process IO rate" 793 | } 794 | name = "performanceCounters/processIOBytesPerSecond" 795 | namespace = "microsoft.insights/components" 796 | resourceMetadata = { 797 | id = azurerm_application_insights.authz_ai.id 798 | } 799 | }] 800 | title = "Average process I/O rate" 801 | visualization = { 802 | axisVisualization = { 803 | x = { 804 | axisType = 2 805 | isVisible = true 806 | } 807 | y = { 808 | axisType = 1 809 | isVisible = true 810 | } 811 | } 812 | chartType = 2 813 | legendVisualization = { 814 | hideSubtitle = false 815 | isVisible = true 816 | position = 2 817 | } 818 | } 819 | } 820 | } 821 | }, { 822 | isOptional = true 823 | name = "sharedTimeRange" 824 | }] 825 | settings = {} 826 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 827 | } 828 | position = { 829 | colSpan = 4 830 | rowSpan = 3 831 | x = 4 832 | y = 8 833 | } 834 | } 835 | "23" = { 836 | metadata = { 837 | inputs = [{ 838 | name = "options" 839 | value = { 840 | chart = { 841 | metrics = [{ 842 | aggregationType = 4 843 | metricVisualization = { 844 | color = "#47BDF5" 845 | displayName = "Available memory" 846 | } 847 | name = "performanceCounters/memoryAvailableBytes" 848 | namespace = "microsoft.insights/components" 849 | resourceMetadata = { 850 | id = azurerm_application_insights.authz_ai.id 851 | } 852 | }] 853 | title = "Average available memory" 854 | visualization = { 855 | axisVisualization = { 856 | x = { 857 | axisType = 2 858 | isVisible = true 859 | } 860 | y = { 861 | axisType = 1 862 | isVisible = true 863 | } 864 | } 865 | chartType = 2 866 | legendVisualization = { 867 | hideSubtitle = false 868 | isVisible = true 869 | position = 2 870 | } 871 | } 872 | } 873 | } 874 | }, { 875 | isOptional = true 876 | name = "sharedTimeRange" 877 | }] 878 | settings = {} 879 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 880 | } 881 | position = { 882 | colSpan = 4 883 | rowSpan = 3 884 | x = 8 885 | y = 8 886 | } 887 | } 888 | "3" = { 889 | metadata = { 890 | asset = { 891 | idInputName = "ComponentId" 892 | type = "ApplicationInsights" 893 | } 894 | inputs = [{ 895 | name = "ComponentId" 896 | value = { 897 | Name = azurerm_application_insights.authz_ai.name 898 | ResourceGroup = azurerm_resource_group.rg.name 899 | SubscriptionId = var.subscription_id 900 | } 901 | }, { 902 | name = "TimeContext" 903 | value = { 904 | createdTime = "2018-05-04T01:20:33.345Z" 905 | durationMs = 86400000 906 | endTime = null 907 | grain = 1 908 | isInitialTime = true 909 | useDashboardTimeRange = false 910 | } 911 | }, { 912 | name = "Version" 913 | value = "1.0" 914 | }] 915 | type = "Extension/AppInsightsExtension/PartType/AvailabilityNavButtonPart" 916 | } 917 | position = { 918 | colSpan = 1 919 | rowSpan = 1 920 | x = 4 921 | y = 0 922 | } 923 | } 924 | "4" = { 925 | metadata = { 926 | asset = { 927 | idInputName = "ComponentId" 928 | type = "ApplicationInsights" 929 | } 930 | inputs = [{ 931 | name = "ComponentId" 932 | value = { 933 | Name = azurerm_application_insights.authz_ai.name 934 | ResourceGroup = azurerm_resource_group.rg.name 935 | SubscriptionId = var.subscription_id 936 | } 937 | }, { 938 | name = "TimeContext" 939 | value = { 940 | createdTime = "2018-05-08T18:47:35.237Z" 941 | durationMs = 86400000 942 | endTime = null 943 | grain = 1 944 | isInitialTime = true 945 | useDashboardTimeRange = false 946 | } 947 | }, { 948 | name = "ConfigurationId" 949 | value = "78ce933e-e864-4b05-a27b-71fd55a6afad" 950 | }] 951 | type = "Extension/AppInsightsExtension/PartType/AppMapButtonPart" 952 | } 953 | position = { 954 | colSpan = 1 955 | rowSpan = 1 956 | x = 5 957 | y = 0 958 | } 959 | } 960 | "5" = { 961 | metadata = { 962 | inputs = [] 963 | settings = { 964 | content = { 965 | settings = { 966 | content = "# Usage" 967 | subtitle = "" 968 | title = "" 969 | } 970 | } 971 | } 972 | type = "Extension[azure]/HubsExtension/PartType/MarkdownPart" 973 | } 974 | position = { 975 | colSpan = 3 976 | rowSpan = 1 977 | x = 0 978 | y = 1 979 | } 980 | } 981 | "6" = { 982 | metadata = { 983 | asset = { 984 | idInputName = "ComponentId" 985 | type = "ApplicationInsights" 986 | } 987 | inputs = [{ 988 | name = "ComponentId" 989 | value = { 990 | Name = azurerm_application_insights.authz_ai.name 991 | ResourceGroup = azurerm_resource_group.rg.name 992 | SubscriptionId = var.subscription_id 993 | } 994 | }, { 995 | name = "TimeContext" 996 | value = { 997 | createdTime = "2018-05-04T01:22:35.782Z" 998 | durationMs = 86400000 999 | endTime = null 1000 | grain = 1 1001 | isInitialTime = true 1002 | useDashboardTimeRange = false 1003 | } 1004 | }] 1005 | type = "Extension/AppInsightsExtension/PartType/UsageUsersOverviewPart" 1006 | } 1007 | position = { 1008 | colSpan = 1 1009 | rowSpan = 1 1010 | x = 3 1011 | y = 1 1012 | } 1013 | } 1014 | "7" = { 1015 | metadata = { 1016 | inputs = [] 1017 | settings = { 1018 | content = { 1019 | settings = { 1020 | content = "# Reliability" 1021 | subtitle = "" 1022 | title = "" 1023 | } 1024 | } 1025 | } 1026 | type = "Extension[azure]/HubsExtension/PartType/MarkdownPart" 1027 | } 1028 | position = { 1029 | colSpan = 3 1030 | rowSpan = 1 1031 | x = 4 1032 | y = 1 1033 | } 1034 | } 1035 | "8" = { 1036 | metadata = { 1037 | asset = { 1038 | idInputName = "ResourceId" 1039 | type = "ApplicationInsights" 1040 | } 1041 | defaultMenuItemId = "failures" 1042 | inputs = [{ 1043 | name = "ResourceId" 1044 | value = azurerm_application_insights.authz_ai.id 1045 | }, { 1046 | isOptional = true 1047 | name = "DataModel" 1048 | value = { 1049 | timeContext = { 1050 | createdTime = "2018-05-04T23:42:40.072Z" 1051 | durationMs = 86400000 1052 | grain = 1 1053 | isInitialTime = false 1054 | useDashboardTimeRange = false 1055 | } 1056 | version = "1.0.0" 1057 | } 1058 | }, { 1059 | isOptional = true 1060 | name = "ConfigurationId" 1061 | value = "8a02f7bf-ac0f-40e1-afe9-f0e72cfee77f" 1062 | }] 1063 | isAdapter = true 1064 | type = "Extension/AppInsightsExtension/PartType/CuratedBladeFailuresPinnedPart" 1065 | } 1066 | position = { 1067 | colSpan = 1 1068 | rowSpan = 1 1069 | x = 7 1070 | y = 1 1071 | } 1072 | } 1073 | "9" = { 1074 | metadata = { 1075 | inputs = [] 1076 | settings = { 1077 | content = { 1078 | settings = { 1079 | content = "# Responsiveness\r\n" 1080 | subtitle = "" 1081 | title = "" 1082 | } 1083 | } 1084 | } 1085 | type = "Extension[azure]/HubsExtension/PartType/MarkdownPart" 1086 | } 1087 | position = { 1088 | colSpan = 3 1089 | rowSpan = 1 1090 | x = 8 1091 | y = 1 1092 | } 1093 | } 1094 | } 1095 | } 1096 | } 1097 | }) 1098 | location = var.alt_location 1099 | name = "b50fb231-6a4d-414d-be5b-1a043d1ddf59-dashboard" 1100 | resource_group_name = azurerm_resource_group.rg.name 1101 | tags = { 1102 | costcenter = "altinn3" 1103 | hidden-title = "${azurerm_application_insights.authz_ai.name} Dashboard" 1104 | solution = "apps" 1105 | } 1106 | } 1107 | -------------------------------------------------------------------------------- /infra/altinn-digdir-oed-rg/dashboard.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_portal_dashboard" "dashboards" { 2 | dashboard_properties = jsonencode({ 3 | lenses = { 4 | "0" = { 5 | order = 0 6 | parts = { 7 | "0" = { 8 | metadata = { 9 | asset = { 10 | idInputName = "id" 11 | type = "ApplicationInsights" 12 | } 13 | defaultMenuItemId = "overview" 14 | inputs = [{ 15 | name = "id" 16 | value = azurerm_application_insights.authz_ai.id 17 | }, { 18 | name = "Version" 19 | value = "1.0" 20 | }] 21 | type = "Extension/AppInsightsExtension/PartType/AspNetOverviewPinnedPart" 22 | } 23 | position = { 24 | colSpan = 2 25 | rowSpan = 1 26 | x = 0 27 | y = 0 28 | } 29 | } 30 | "1" = { 31 | metadata = { 32 | asset = { 33 | idInputName = "ComponentId" 34 | type = "ApplicationInsights" 35 | } 36 | defaultMenuItemId = "ProactiveDetection" 37 | inputs = [{ 38 | name = "ComponentId" 39 | value = { 40 | Name = azurerm_application_insights.authz_ai.name 41 | ResourceGroup = azurerm_resource_group.rg.name 42 | SubscriptionId = var.subscription_id 43 | } 44 | }, { 45 | name = "Version" 46 | value = "1.0" 47 | }] 48 | type = "Extension/AppInsightsExtension/PartType/ProactiveDetectionAsyncPart" 49 | } 50 | position = { 51 | colSpan = 1 52 | rowSpan = 1 53 | x = 2 54 | y = 0 55 | } 56 | } 57 | "10" = { 58 | metadata = { 59 | asset = { 60 | idInputName = "ResourceId" 61 | type = "ApplicationInsights" 62 | } 63 | defaultMenuItemId = "performance" 64 | inputs = [{ 65 | name = "ResourceId" 66 | value = azurerm_application_insights.authz_ai.id 67 | }, { 68 | isOptional = true 69 | name = "DataModel" 70 | value = { 71 | timeContext = { 72 | createdTime = "2018-05-04T23:43:37.804Z" 73 | durationMs = 86400000 74 | grain = 1 75 | isInitialTime = false 76 | useDashboardTimeRange = false 77 | } 78 | version = "1.0.0" 79 | } 80 | }, { 81 | isOptional = true 82 | name = "ConfigurationId" 83 | value = "2a8ede4f-2bee-4b9c-aed9-2db0e8a01865" 84 | }] 85 | isAdapter = true 86 | type = "Extension/AppInsightsExtension/PartType/CuratedBladePerformancePinnedPart" 87 | } 88 | position = { 89 | colSpan = 1 90 | rowSpan = 1 91 | x = 11 92 | y = 1 93 | } 94 | } 95 | "11" = { 96 | metadata = { 97 | inputs = [] 98 | settings = { 99 | content = { 100 | settings = { 101 | content = "# Browser" 102 | subtitle = "" 103 | title = "" 104 | } 105 | } 106 | } 107 | type = "Extension[azure]/HubsExtension/PartType/MarkdownPart" 108 | } 109 | position = { 110 | colSpan = 3 111 | rowSpan = 1 112 | x = 12 113 | y = 1 114 | } 115 | } 116 | "12" = { 117 | metadata = { 118 | asset = { 119 | idInputName = "ComponentId" 120 | type = "ApplicationInsights" 121 | } 122 | defaultMenuItemId = "browser" 123 | inputs = [{ 124 | name = "ComponentId" 125 | value = { 126 | Name = azurerm_application_insights.authz_ai.name 127 | ResourceGroup = azurerm_resource_group.rg.name 128 | SubscriptionId = var.subscription_id 129 | } 130 | }, { 131 | name = "MetricsExplorerJsonDefinitionId" 132 | value = "BrowserPerformanceTimelineMetrics" 133 | }, { 134 | name = "TimeContext" 135 | value = { 136 | createdTime = "2018-05-08T12:16:27.534Z" 137 | durationMs = 86400000 138 | grain = 1 139 | isInitialTime = false 140 | useDashboardTimeRange = false 141 | } 142 | }, { 143 | name = "CurrentFilter" 144 | value = { 145 | eventTypes = [4, 1, 3, 5, 2, 6, 13] 146 | isPermissive = false 147 | typeFacets = {} 148 | } 149 | }, { 150 | name = "id" 151 | value = { 152 | Name = azurerm_application_insights.authz_ai.name 153 | ResourceGroup = azurerm_resource_group.rg.name 154 | SubscriptionId = var.subscription_id 155 | } 156 | }, { 157 | name = "Version" 158 | value = "1.0" 159 | }] 160 | type = "Extension/AppInsightsExtension/PartType/MetricsExplorerBladePinnedPart" 161 | } 162 | position = { 163 | colSpan = 1 164 | rowSpan = 1 165 | x = 15 166 | y = 1 167 | } 168 | } 169 | "13" = { 170 | metadata = { 171 | inputs = [{ 172 | name = "options" 173 | value = { 174 | chart = { 175 | metrics = [{ 176 | aggregationType = 5 177 | metricVisualization = { 178 | color = "#47BDF5" 179 | displayName = "Sessions" 180 | } 181 | name = "sessions/count" 182 | namespace = "microsoft.insights/components/kusto" 183 | resourceMetadata = { 184 | id = azurerm_application_insights.authz_ai.id 185 | } 186 | }, { 187 | aggregationType = 5 188 | metricVisualization = { 189 | color = "#7E58FF" 190 | displayName = "Users" 191 | } 192 | name = "users/count" 193 | namespace = "microsoft.insights/components/kusto" 194 | resourceMetadata = { 195 | id = azurerm_application_insights.authz_ai.id 196 | } 197 | }] 198 | openBladeOnClick = { 199 | destinationBlade = { 200 | bladeName = "ResourceMenuBlade" 201 | extensionName = "HubsExtension" 202 | parameters = { 203 | id = azurerm_application_insights.authz_ai.id 204 | menuid = "segmentationUsers" 205 | } 206 | } 207 | openBlade = true 208 | } 209 | title = "Unique sessions and users" 210 | visualization = { 211 | axisVisualization = { 212 | x = { 213 | axisType = 2 214 | isVisible = true 215 | } 216 | y = { 217 | axisType = 1 218 | isVisible = true 219 | } 220 | } 221 | chartType = 2 222 | legendVisualization = { 223 | hideSubtitle = false 224 | isVisible = true 225 | position = 2 226 | } 227 | } 228 | } 229 | } 230 | }, { 231 | isOptional = true 232 | name = "sharedTimeRange" 233 | }] 234 | settings = {} 235 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 236 | } 237 | position = { 238 | colSpan = 4 239 | rowSpan = 3 240 | x = 0 241 | y = 2 242 | } 243 | } 244 | "14" = { 245 | metadata = { 246 | inputs = [{ 247 | name = "options" 248 | value = { 249 | chart = { 250 | metrics = [{ 251 | aggregationType = 7 252 | metricVisualization = { 253 | color = "#EC008C" 254 | displayName = "Failed requests" 255 | } 256 | name = "requests/failed" 257 | namespace = "microsoft.insights/components" 258 | resourceMetadata = { 259 | id = azurerm_application_insights.authz_ai.id 260 | } 261 | }] 262 | openBladeOnClick = { 263 | destinationBlade = { 264 | bladeName = "ResourceMenuBlade" 265 | extensionName = "HubsExtension" 266 | parameters = { 267 | id = azurerm_application_insights.authz_ai.id 268 | menuid = "failures" 269 | } 270 | } 271 | openBlade = true 272 | } 273 | title = "Failed requests" 274 | visualization = { 275 | axisVisualization = { 276 | x = { 277 | axisType = 2 278 | isVisible = true 279 | } 280 | y = { 281 | axisType = 1 282 | isVisible = true 283 | } 284 | } 285 | chartType = 3 286 | legendVisualization = { 287 | hideSubtitle = false 288 | isVisible = true 289 | position = 2 290 | } 291 | } 292 | } 293 | } 294 | }, { 295 | isOptional = true 296 | name = "sharedTimeRange" 297 | }] 298 | settings = {} 299 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 300 | } 301 | position = { 302 | colSpan = 4 303 | rowSpan = 3 304 | x = 4 305 | y = 2 306 | } 307 | } 308 | "15" = { 309 | metadata = { 310 | inputs = [{ 311 | name = "options" 312 | value = { 313 | chart = { 314 | metrics = [{ 315 | aggregationType = 4 316 | metricVisualization = { 317 | color = "#00BCF2" 318 | displayName = "Server response time" 319 | } 320 | name = "requests/duration" 321 | namespace = "microsoft.insights/components" 322 | resourceMetadata = { 323 | id = azurerm_application_insights.authz_ai.id 324 | } 325 | }] 326 | openBladeOnClick = { 327 | destinationBlade = { 328 | bladeName = "ResourceMenuBlade" 329 | extensionName = "HubsExtension" 330 | parameters = { 331 | id = azurerm_application_insights.authz_ai.id 332 | menuid = "performance" 333 | } 334 | } 335 | openBlade = true 336 | } 337 | title = "Server response time" 338 | visualization = { 339 | axisVisualization = { 340 | x = { 341 | axisType = 2 342 | isVisible = true 343 | } 344 | y = { 345 | axisType = 1 346 | isVisible = true 347 | } 348 | } 349 | chartType = 2 350 | legendVisualization = { 351 | hideSubtitle = false 352 | isVisible = true 353 | position = 2 354 | } 355 | } 356 | } 357 | } 358 | }, { 359 | isOptional = true 360 | name = "sharedTimeRange" 361 | }] 362 | settings = {} 363 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 364 | } 365 | position = { 366 | colSpan = 4 367 | rowSpan = 3 368 | x = 8 369 | y = 2 370 | } 371 | } 372 | "16" = { 373 | metadata = { 374 | inputs = [{ 375 | name = "options" 376 | value = { 377 | chart = { 378 | metrics = [{ 379 | aggregationType = 4 380 | metricVisualization = { 381 | color = "#7E58FF" 382 | displayName = "Page load network connect time" 383 | } 384 | name = "browserTimings/networkDuration" 385 | namespace = "microsoft.insights/components" 386 | resourceMetadata = { 387 | id = azurerm_application_insights.authz_ai.id 388 | } 389 | }, { 390 | aggregationType = 4 391 | metricVisualization = { 392 | color = "#44F1C8" 393 | displayName = "Client processing time" 394 | } 395 | name = "browserTimings/processingDuration" 396 | namespace = "microsoft.insights/components" 397 | resourceMetadata = { 398 | id = azurerm_application_insights.authz_ai.id 399 | } 400 | }, { 401 | aggregationType = 4 402 | metricVisualization = { 403 | color = "#EB9371" 404 | displayName = "Send request time" 405 | } 406 | name = "browserTimings/sendDuration" 407 | namespace = "microsoft.insights/components" 408 | resourceMetadata = { 409 | id = azurerm_application_insights.authz_ai.id 410 | } 411 | }, { 412 | aggregationType = 4 413 | metricVisualization = { 414 | color = "#0672F1" 415 | displayName = "Receiving response time" 416 | } 417 | name = "browserTimings/receiveDuration" 418 | namespace = "microsoft.insights/components" 419 | resourceMetadata = { 420 | id = azurerm_application_insights.authz_ai.id 421 | } 422 | }] 423 | title = "Average page load time breakdown" 424 | visualization = { 425 | axisVisualization = { 426 | x = { 427 | axisType = 2 428 | isVisible = true 429 | } 430 | y = { 431 | axisType = 1 432 | isVisible = true 433 | } 434 | } 435 | chartType = 3 436 | legendVisualization = { 437 | hideSubtitle = false 438 | isVisible = true 439 | position = 2 440 | } 441 | } 442 | } 443 | } 444 | }, { 445 | isOptional = true 446 | name = "sharedTimeRange" 447 | }] 448 | settings = {} 449 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 450 | } 451 | position = { 452 | colSpan = 4 453 | rowSpan = 3 454 | x = 12 455 | y = 2 456 | } 457 | } 458 | "17" = { 459 | metadata = { 460 | inputs = [{ 461 | name = "options" 462 | value = { 463 | chart = { 464 | metrics = [{ 465 | aggregationType = 4 466 | metricVisualization = { 467 | color = "#47BDF5" 468 | displayName = "Availability" 469 | } 470 | name = "availabilityResults/availabilityPercentage" 471 | namespace = "microsoft.insights/components" 472 | resourceMetadata = { 473 | id = azurerm_application_insights.authz_ai.id 474 | } 475 | }] 476 | openBladeOnClick = { 477 | destinationBlade = { 478 | bladeName = "ResourceMenuBlade" 479 | extensionName = "HubsExtension" 480 | parameters = { 481 | id = azurerm_application_insights.authz_ai.id 482 | menuid = "availability" 483 | } 484 | } 485 | openBlade = true 486 | } 487 | title = "Average availability" 488 | visualization = { 489 | axisVisualization = { 490 | x = { 491 | axisType = 2 492 | isVisible = true 493 | } 494 | y = { 495 | axisType = 1 496 | isVisible = true 497 | } 498 | } 499 | chartType = 3 500 | legendVisualization = { 501 | hideSubtitle = false 502 | isVisible = true 503 | position = 2 504 | } 505 | } 506 | } 507 | } 508 | }, { 509 | isOptional = true 510 | name = "sharedTimeRange" 511 | }] 512 | settings = {} 513 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 514 | } 515 | position = { 516 | colSpan = 4 517 | rowSpan = 3 518 | x = 0 519 | y = 5 520 | } 521 | } 522 | "18" = { 523 | metadata = { 524 | inputs = [{ 525 | name = "options" 526 | value = { 527 | chart = { 528 | metrics = [{ 529 | aggregationType = 7 530 | metricVisualization = { 531 | color = "#47BDF5" 532 | displayName = "Server exceptions" 533 | } 534 | name = "exceptions/server" 535 | namespace = "microsoft.insights/components" 536 | resourceMetadata = { 537 | id = azurerm_application_insights.authz_ai.id 538 | } 539 | }, { 540 | aggregationType = 7 541 | metricVisualization = { 542 | color = "#7E58FF" 543 | displayName = "Dependency failures" 544 | } 545 | name = "dependencies/failed" 546 | namespace = "microsoft.insights/components" 547 | resourceMetadata = { 548 | id = azurerm_application_insights.authz_ai.id 549 | } 550 | }] 551 | title = "Server exceptions and Dependency failures" 552 | visualization = { 553 | axisVisualization = { 554 | x = { 555 | axisType = 2 556 | isVisible = true 557 | } 558 | y = { 559 | axisType = 1 560 | isVisible = true 561 | } 562 | } 563 | chartType = 2 564 | legendVisualization = { 565 | hideSubtitle = false 566 | isVisible = true 567 | position = 2 568 | } 569 | } 570 | } 571 | } 572 | }, { 573 | isOptional = true 574 | name = "sharedTimeRange" 575 | }] 576 | settings = {} 577 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 578 | } 579 | position = { 580 | colSpan = 4 581 | rowSpan = 3 582 | x = 4 583 | y = 5 584 | } 585 | } 586 | "19" = { 587 | metadata = { 588 | inputs = [{ 589 | name = "options" 590 | value = { 591 | chart = { 592 | metrics = [{ 593 | aggregationType = 4 594 | metricVisualization = { 595 | color = "#47BDF5" 596 | displayName = "Processor time" 597 | } 598 | name = "performanceCounters/processorCpuPercentage" 599 | namespace = "microsoft.insights/components" 600 | resourceMetadata = { 601 | id = azurerm_application_insights.authz_ai.id 602 | } 603 | }, { 604 | aggregationType = 4 605 | metricVisualization = { 606 | color = "#7E58FF" 607 | displayName = "Process CPU" 608 | } 609 | name = "performanceCounters/processCpuPercentage" 610 | namespace = "microsoft.insights/components" 611 | resourceMetadata = { 612 | id = azurerm_application_insights.authz_ai.id 613 | } 614 | }] 615 | title = "Average processor and process CPU utilization" 616 | visualization = { 617 | axisVisualization = { 618 | x = { 619 | axisType = 2 620 | isVisible = true 621 | } 622 | y = { 623 | axisType = 1 624 | isVisible = true 625 | } 626 | } 627 | chartType = 2 628 | legendVisualization = { 629 | hideSubtitle = false 630 | isVisible = true 631 | position = 2 632 | } 633 | } 634 | } 635 | } 636 | }, { 637 | isOptional = true 638 | name = "sharedTimeRange" 639 | }] 640 | settings = {} 641 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 642 | } 643 | position = { 644 | colSpan = 4 645 | rowSpan = 3 646 | x = 8 647 | y = 5 648 | } 649 | } 650 | "2" = { 651 | metadata = { 652 | asset = { 653 | idInputName = "ComponentId" 654 | type = "ApplicationInsights" 655 | } 656 | inputs = [{ 657 | name = "ComponentId" 658 | value = { 659 | Name = azurerm_application_insights.authz_ai.name 660 | ResourceGroup = azurerm_resource_group.rg.name 661 | SubscriptionId = var.subscription_id 662 | } 663 | }, { 664 | name = "ResourceId" 665 | value = azurerm_application_insights.authz_ai.id 666 | }] 667 | type = "Extension/AppInsightsExtension/PartType/QuickPulseButtonSmallPart" 668 | } 669 | position = { 670 | colSpan = 1 671 | rowSpan = 1 672 | x = 3 673 | y = 0 674 | } 675 | } 676 | "20" = { 677 | metadata = { 678 | inputs = [{ 679 | name = "options" 680 | value = { 681 | chart = { 682 | metrics = [{ 683 | aggregationType = 7 684 | metricVisualization = { 685 | color = "#47BDF5" 686 | displayName = "Browser exceptions" 687 | } 688 | name = "exceptions/browser" 689 | namespace = "microsoft.insights/components" 690 | resourceMetadata = { 691 | id = azurerm_application_insights.authz_ai.id 692 | } 693 | }] 694 | title = "Browser exceptions" 695 | visualization = { 696 | axisVisualization = { 697 | x = { 698 | axisType = 2 699 | isVisible = true 700 | } 701 | y = { 702 | axisType = 1 703 | isVisible = true 704 | } 705 | } 706 | chartType = 2 707 | legendVisualization = { 708 | hideSubtitle = false 709 | isVisible = true 710 | position = 2 711 | } 712 | } 713 | } 714 | } 715 | }, { 716 | isOptional = true 717 | name = "sharedTimeRange" 718 | }] 719 | settings = {} 720 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 721 | } 722 | position = { 723 | colSpan = 4 724 | rowSpan = 3 725 | x = 12 726 | y = 5 727 | } 728 | } 729 | "21" = { 730 | metadata = { 731 | inputs = [{ 732 | name = "options" 733 | value = { 734 | chart = { 735 | metrics = [{ 736 | aggregationType = 7 737 | metricVisualization = { 738 | color = "#47BDF5" 739 | displayName = "Availability ${var.environment} results count" 740 | } 741 | name = "availabilityResults/count" 742 | namespace = "microsoft.insights/components" 743 | resourceMetadata = { 744 | id = azurerm_application_insights.authz_ai.id 745 | } 746 | }] 747 | title = "Availability ${var.environment} results count" 748 | visualization = { 749 | axisVisualization = { 750 | x = { 751 | axisType = 2 752 | isVisible = true 753 | } 754 | y = { 755 | axisType = 1 756 | isVisible = true 757 | } 758 | } 759 | chartType = 2 760 | legendVisualization = { 761 | hideSubtitle = false 762 | isVisible = true 763 | position = 2 764 | } 765 | } 766 | } 767 | } 768 | }, { 769 | isOptional = true 770 | name = "sharedTimeRange" 771 | }] 772 | settings = {} 773 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 774 | } 775 | position = { 776 | colSpan = 4 777 | rowSpan = 3 778 | x = 0 779 | y = 8 780 | } 781 | } 782 | "22" = { 783 | metadata = { 784 | inputs = [{ 785 | name = "options" 786 | value = { 787 | chart = { 788 | metrics = [{ 789 | aggregationType = 4 790 | metricVisualization = { 791 | color = "#47BDF5" 792 | displayName = "Process IO rate" 793 | } 794 | name = "performanceCounters/processIOBytesPerSecond" 795 | namespace = "microsoft.insights/components" 796 | resourceMetadata = { 797 | id = azurerm_application_insights.authz_ai.id 798 | } 799 | }] 800 | title = "Average process I/O rate" 801 | visualization = { 802 | axisVisualization = { 803 | x = { 804 | axisType = 2 805 | isVisible = true 806 | } 807 | y = { 808 | axisType = 1 809 | isVisible = true 810 | } 811 | } 812 | chartType = 2 813 | legendVisualization = { 814 | hideSubtitle = false 815 | isVisible = true 816 | position = 2 817 | } 818 | } 819 | } 820 | } 821 | }, { 822 | isOptional = true 823 | name = "sharedTimeRange" 824 | }] 825 | settings = {} 826 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 827 | } 828 | position = { 829 | colSpan = 4 830 | rowSpan = 3 831 | x = 4 832 | y = 8 833 | } 834 | } 835 | "23" = { 836 | metadata = { 837 | inputs = [{ 838 | name = "options" 839 | value = { 840 | chart = { 841 | metrics = [{ 842 | aggregationType = 4 843 | metricVisualization = { 844 | color = "#47BDF5" 845 | displayName = "Available memory" 846 | } 847 | name = "performanceCounters/memoryAvailableBytes" 848 | namespace = "microsoft.insights/components" 849 | resourceMetadata = { 850 | id = azurerm_application_insights.authz_ai.id 851 | } 852 | }] 853 | title = "Average available memory" 854 | visualization = { 855 | axisVisualization = { 856 | x = { 857 | axisType = 2 858 | isVisible = true 859 | } 860 | y = { 861 | axisType = 1 862 | isVisible = true 863 | } 864 | } 865 | chartType = 2 866 | legendVisualization = { 867 | hideSubtitle = false 868 | isVisible = true 869 | position = 2 870 | } 871 | } 872 | } 873 | } 874 | }, { 875 | isOptional = true 876 | name = "sharedTimeRange" 877 | }] 878 | settings = {} 879 | type = "Extension/HubsExtension/PartType/MonitorChartPart" 880 | } 881 | position = { 882 | colSpan = 4 883 | rowSpan = 3 884 | x = 8 885 | y = 8 886 | } 887 | } 888 | "3" = { 889 | metadata = { 890 | asset = { 891 | idInputName = "ComponentId" 892 | type = "ApplicationInsights" 893 | } 894 | inputs = [{ 895 | name = "ComponentId" 896 | value = { 897 | Name = azurerm_application_insights.authz_ai.name 898 | ResourceGroup = azurerm_resource_group.rg.name 899 | SubscriptionId = var.subscription_id 900 | } 901 | }, { 902 | name = "TimeContext" 903 | value = { 904 | createdTime = "2018-05-04T01:20:33.345Z" 905 | durationMs = 86400000 906 | endTime = null 907 | grain = 1 908 | isInitialTime = true 909 | useDashboardTimeRange = false 910 | } 911 | }, { 912 | name = "Version" 913 | value = "1.0" 914 | }] 915 | type = "Extension/AppInsightsExtension/PartType/AvailabilityNavButtonPart" 916 | } 917 | position = { 918 | colSpan = 1 919 | rowSpan = 1 920 | x = 4 921 | y = 0 922 | } 923 | } 924 | "4" = { 925 | metadata = { 926 | asset = { 927 | idInputName = "ComponentId" 928 | type = "ApplicationInsights" 929 | } 930 | inputs = [{ 931 | name = "ComponentId" 932 | value = { 933 | Name = azurerm_application_insights.authz_ai.name 934 | ResourceGroup = azurerm_resource_group.rg.name 935 | SubscriptionId = var.subscription_id 936 | } 937 | }, { 938 | name = "TimeContext" 939 | value = { 940 | createdTime = "2018-05-08T18:47:35.237Z" 941 | durationMs = 86400000 942 | endTime = null 943 | grain = 1 944 | isInitialTime = true 945 | useDashboardTimeRange = false 946 | } 947 | }, { 948 | name = "ConfigurationId" 949 | value = "78ce933e-e864-4b05-a27b-71fd55a6afad" 950 | }] 951 | type = "Extension/AppInsightsExtension/PartType/AppMapButtonPart" 952 | } 953 | position = { 954 | colSpan = 1 955 | rowSpan = 1 956 | x = 5 957 | y = 0 958 | } 959 | } 960 | "5" = { 961 | metadata = { 962 | inputs = [] 963 | settings = { 964 | content = { 965 | settings = { 966 | content = "# Usage" 967 | subtitle = "" 968 | title = "" 969 | } 970 | } 971 | } 972 | type = "Extension[azure]/HubsExtension/PartType/MarkdownPart" 973 | } 974 | position = { 975 | colSpan = 3 976 | rowSpan = 1 977 | x = 0 978 | y = 1 979 | } 980 | } 981 | "6" = { 982 | metadata = { 983 | asset = { 984 | idInputName = "ComponentId" 985 | type = "ApplicationInsights" 986 | } 987 | inputs = [{ 988 | name = "ComponentId" 989 | value = { 990 | Name = azurerm_application_insights.authz_ai.name 991 | ResourceGroup = azurerm_resource_group.rg.name 992 | SubscriptionId = var.subscription_id 993 | } 994 | }, { 995 | name = "TimeContext" 996 | value = { 997 | createdTime = "2018-05-04T01:22:35.782Z" 998 | durationMs = 86400000 999 | endTime = null 1000 | grain = 1 1001 | isInitialTime = true 1002 | useDashboardTimeRange = false 1003 | } 1004 | }] 1005 | type = "Extension/AppInsightsExtension/PartType/UsageUsersOverviewPart" 1006 | } 1007 | position = { 1008 | colSpan = 1 1009 | rowSpan = 1 1010 | x = 3 1011 | y = 1 1012 | } 1013 | } 1014 | "7" = { 1015 | metadata = { 1016 | inputs = [] 1017 | settings = { 1018 | content = { 1019 | settings = { 1020 | content = "# Reliability" 1021 | subtitle = "" 1022 | title = "" 1023 | } 1024 | } 1025 | } 1026 | type = "Extension[azure]/HubsExtension/PartType/MarkdownPart" 1027 | } 1028 | position = { 1029 | colSpan = 3 1030 | rowSpan = 1 1031 | x = 4 1032 | y = 1 1033 | } 1034 | } 1035 | "8" = { 1036 | metadata = { 1037 | asset = { 1038 | idInputName = "ResourceId" 1039 | type = "ApplicationInsights" 1040 | } 1041 | defaultMenuItemId = "failures" 1042 | inputs = [{ 1043 | name = "ResourceId" 1044 | value = azurerm_application_insights.authz_ai.id 1045 | }, { 1046 | isOptional = true 1047 | name = "DataModel" 1048 | value = { 1049 | timeContext = { 1050 | createdTime = "2018-05-04T23:42:40.072Z" 1051 | durationMs = 86400000 1052 | grain = 1 1053 | isInitialTime = false 1054 | useDashboardTimeRange = false 1055 | } 1056 | version = "1.0.0" 1057 | } 1058 | }, { 1059 | isOptional = true 1060 | name = "ConfigurationId" 1061 | value = "8a02f7bf-ac0f-40e1-afe9-f0e72cfee77f" 1062 | }] 1063 | isAdapter = true 1064 | type = "Extension/AppInsightsExtension/PartType/CuratedBladeFailuresPinnedPart" 1065 | } 1066 | position = { 1067 | colSpan = 1 1068 | rowSpan = 1 1069 | x = 7 1070 | y = 1 1071 | } 1072 | } 1073 | "9" = { 1074 | metadata = { 1075 | inputs = [] 1076 | settings = { 1077 | content = { 1078 | settings = { 1079 | content = "# Responsiveness\r\n" 1080 | subtitle = "" 1081 | title = "" 1082 | } 1083 | } 1084 | } 1085 | type = "Extension[azure]/HubsExtension/PartType/MarkdownPart" 1086 | } 1087 | position = { 1088 | colSpan = 3 1089 | rowSpan = 1 1090 | x = 8 1091 | y = 1 1092 | } 1093 | } 1094 | } 1095 | } 1096 | } 1097 | }) 1098 | location = azurerm_resource_group.rg.location 1099 | name = "${azurerm_application_insights.authz_ai.name}-dashboard" 1100 | resource_group_name = azurerm_resource_group.rg.name 1101 | tags = { 1102 | costcenter = "altinn3" 1103 | hidden-title = "${azurerm_application_insights.authz_ai.name} Dashboard" 1104 | solution = "apps" 1105 | } 1106 | } 1107 | --------------------------------------------------------------------------------