From 8d4c64112893783216be2c5d16d9c4cfad4ceca7 Mon Sep 17 00:00:00 2001 From: lolorol Date: Fri, 26 Mar 2021 11:28:59 +0000 Subject: [PATCH 01/38] Initial 5.3.0 --- .devcontainer/docker-compose.yml | 2 +- .../caf_eslz/README.md | 0 .../caf_eslz/backend.azurerm | 0 .../caf_eslz/es_main.tf | 0 .../caf_eslz/landingzone.tf | 0 .../caf_eslz/locals.remote_tfstates.tf | 0 .../caf_eslz/main.tf | 0 .../caf_eslz/output.tf | 0 .../100/enterprise_scale_contoso_com.tfvars | 0 .../200/enterprise_scale_contoso_com.tfvars | 0 ...chetype_definition_es_management.tmpl.json | 0 .../200/lib/archetype_definition_es_root.json | 0 ...nt_es_allowed_resource-locations.tmpl.json | 0 ..._allowed_resourcegroup-locations.tmpl.json | 0 ...licy_assignment_es_deploy_asc_ce.tmpl.json | 0 ...ignment_es_deploy_asc_monitoring.tmpl.json | 0 ...ssignment_es_deploy_asc_standard.tmpl.json | 0 ...nment_es_deploy_diag_activitylog.tmpl.json | 0 ...ment_es_deploy_diag_loganalytics.tmpl.json | 0 ...icy_definition_es_deploy_asc_standard.json | 0 .../caf_eslz/variables.tf | 0 .../caf_foundations/README.md | 0 .../caf_foundations/backend.azurerm | 0 .../caf_foundations/dynamic_secrets.tf | 0 .../caf_foundations/landingzone.tf | 0 .../caf_foundations/locals.remote_tfstates.tf | 0 .../caf_foundations/main.tf | 0 .../caf_foundations/output.tf | 0 .../caf_foundations/variables.tf | 0 .../add-ons/azure_devops/azdo.tf | 0 .../add-ons/azure_devops/azdo_agent_pools.tf | 0 .../add-ons/azure_devops/azdo_pipelines.tf | 0 .../azure_devops/azdo_service_endpoint.tf | 0 .../azure_devops/azdo_variable_groups.tf | 0 .../add-ons/azure_devops/backend.azurerm | 0 .../documentation/images/pat_token.png | Bin .../azure_devops/locals.remote_tfstates.tf | 0 .../add-ons/azure_devops/main.tf | 0 .../add-ons/azure_devops/output.tf | 0 .../add-ons/azure_devops/readme.md | 0 .../200-contoso_demo/azure_devops.tfvars | 0 .../200-contoso_demo/configurations.tfvars | 0 .../200-contoso_demo/pipeline/rover.yaml | 0 .../add-ons/azure_devops/solution.tf | 0 .../add-ons/azure_devops/variables.tf | 0 .../azure_devops_agent/backend.azurerm | 0 .../azure_devops_agent/dynamic_secrets.tf | 0 .../extensions/devops_selfhosted_agent.tf | 0 .../extensions/variables.tf | 0 .../locals.current_tfstates.tf | 0 .../add-ons/azure_devops_agent/main.tf | 0 .../add-ons/azure_devops_agent/output.tf | 0 .../add-ons/azure_devops_agent/readme.md | 0 .../level0/configuration.tfvars | 0 .../200-contoso_demo/level0/keyvaults.tfvars | 0 .../level0/storage_accounts.tfvars | 0 .../level0/virtual_machines.tfvars | 0 .../level1/configuration.tfvars | 0 .../200-contoso_demo/level1/keyvaults.tfvars | 0 .../level1/storage_accounts.tfvars | 0 .../level1/virtual_machines.tfvars | 0 .../cloud-init-install-rover-tools.config | 0 .../scripts/devops_runtime_baremetal.sh | 0 .../scripts/devops_runtime_docker.sh | 0 .../add-ons/azure_devops_agent/solution.tf | 0 .../add-ons/azure_devops_agent/variables.tf | 0 .../vm_extention_devops_agent.tf | 0 .../terraform_cloud/example/tfc.tfvars | 0 .../add-ons/terraform_cloud/main.tf | 0 .../add-ons/terraform_cloud/readme.md | 0 .../terraform_cloud/terraform_cloud.tf | 0 .../add-ons/terraform_cloud/variables.tf | 0 .../caf_launchpad}/backend.azurerm | 0 .../documentation/img/launchpad-100.PNG | Bin 0 -> 143702 bytes .../documentation/img/launchpad-200.png | Bin 0 -> 232335 bytes .../documentation/img/launchpad_workflow.png | Bin 0 -> 40149 bytes .../caf_launchpad/documentation/variables.md | 41 + .../caf_launchpad/dynamic_secrets.tf | 11 + landingzones.old/caf_launchpad/landingzone.tf | 48 ++ landingzones.old/caf_launchpad/main.tf | 99 +++ landingzones.old/caf_launchpad/output.tf | 66 ++ landingzones.old/caf_launchpad/readme.md | 206 +++++ .../caf_launchpad/scenario/100/README.md | 44 + .../scenario/100/configuration.tfvars | 68 ++ .../scenario/100/dynamic_secrets.tfvars | 114 +++ .../scenario/100/iam_role_mapping.tfvars | 47 ++ .../scenario/100/keyvaults.tfvars | 99 +++ .../scenario/100/storage_accounts.tfvars | 102 +++ .../caf_launchpad/scenario/200/compute.tfvars | 100 +++ .../scenario/200/configuration.tfvars | 100 +++ .../diagnostic_event_hub_namespaces.tfvars | 20 + .../200/diagnostic_log_analytics.tfvars | 48 ++ .../200/diagnostic_storage_accounts.tfvars | 64 ++ .../200/diagnostics_definition.tfvars | 274 +++++++ .../200/diagnostics_destinations.tfvars | 31 + .../scenario/200/dynamic_secrets.tfvars | 152 ++++ .../scenario/200/iam_azuread.tfvars | 184 +++++ .../200/iam_azuread_api_permissions.tfvars | 43 + .../scenario/200/iam_custom_roles.tfvars | 76 ++ .../scenario/200/iam_keyvault_policies.tfvars | 114 +++ .../200/iam_managed_identities.tfvars | 32 + .../scenario/200/iam_role_mapping.tfvars | 154 ++++ .../scenario/200/keyvaults.tfvars | 204 +++++ .../scenario/200/networking.tfvars | 110 +++ .../200/networking_nsg_definition.tfvars | 141 ++++ .../caf_launchpad/scenario/200/readme.md | 56 ++ .../scenario/200/storage_accounts.tfvars | 101 +++ .../scenario/200/subscriptions.tfvars | 20 + .../cloud-init-install-rover-tools.config | 49 ++ .../caf_launchpad/scripts/grant_consent.sh | 0 landingzones.old/caf_launchpad/variables.tf | 191 +++++ .../caf_networking}/backend.azurerm | 0 .../img/100-single-region-hub.png | Bin .../img/101-multi-region-hub.png | Bin .../documentation/img/105-hub-and-spoke.png | Bin .../img/106-hub-virtual-wan-firewall.png | Bin .../caf_networking/landingzone.tf | 0 .../caf_networking/locals.remote_tfstates.tf | 0 .../caf_networking/main.tf | 0 .../caf_networking/output.tf | 0 .../caf_networking/readme.md | 0 .../configuration.tfvars | 0 .../network_security_group_definition.tfvars | 0 .../scenario/100-single-region-hub/readme.md | 0 .../101-multi-region-hub/configuration.tfvars | 0 .../network_security_group_definition.tfvars | 0 .../101-multi-region-hub/peering.tfvars | 0 .../scenario/101-multi-region-hub/readme.md | 0 .../virtual_networks.tfvars | 0 .../105-hub-and-spoke/configuration.tfvars | 0 .../network_security_group_definition.tfvars | 0 .../scenario/105-hub-and-spoke/readme.md | 0 .../configuration.tfvars | 0 .../network_security_group_definition.tfvars | 0 .../106-hub-virtual-wan-firewall/readme.md | 0 .../virtual_wan.tfvars | 0 .../configuration.tfvars | 0 .../201-multi-region-hub/configuration.tfvars | 0 .../210-aks-private/configuration.tfvars | 0 .../peerings/launchpad/configuration.tfvars | 0 .../caf_networking/variables.tf | 0 .../caf_shared_services}/backend.azurerm | 0 .../caf_shared_services/landingzone.tf | 0 .../locals.remote_tfstates.tf | 0 .../caf_shared_services/main.tf | 0 .../caf_shared_services/output.tf | 0 .../caf_shared_services/readme.md | 0 .../scenario/100/configuration.tfvars | 0 .../scenario/200/configuration.tfvars | 0 .../caf_shared_services/variables.tf | 0 .../caf_shared_services/vm_extensions.tf | 0 .../add-ons/aks_applications/app/main.tf | 0 .../add-ons/aks_applications/app/module.tf | 0 .../add-ons/aks_applications/app/output.tf | 0 .../add-ons/aks_applications/app/variables.tf | 0 .../add-ons/aks_applications/applications.tf | 0 .../add-ons/aks_applications}/backend.azurerm | 0 .../locals.remote_tfstates.tf | 0 .../add-ons/aks_applications/main.tf | 0 .../add-ons/aks_applications/output.tf | 0 .../add-ons/aks_applications/variables.tf | 0 .../add-ons/databricks}/backend.azurerm | 0 .../add-ons/databricks/databricks.tf | 0 .../databricks/locals.remote_tfstates.tf | 0 .../caf_solutions/add-ons/databricks/main.tf | 0 .../add-ons/databricks/variables.tf | 0 .../caf_solutions/backend.azurerm | 4 + .../caf_solutions/dynamic_secrets.tf | 0 .../caf_solutions/landingzone.tf | 0 .../caf_solutions/locals.remote_tfstates.tf | 0 .../caf_solutions/main.tf | 0 .../modules/databricks/cluster.tf | 0 .../modules/databricks/instance_pool.tf | 0 .../caf_solutions/modules/databricks/main.tf | 0 .../modules/databricks/output.tf | 0 .../modules/databricks/variables.tf | 0 .../caf_solutions/output.tf | 0 .../caf_solutions/readme.md | 0 .../cloud-init-install-rover-tools.config | 0 .../caf_solutions/variables.tf | 0 .../caf_launchpad/.terraform.lock.hcl | 72 ++ landingzones/caf_launchpad/dynamic_secrets.tf | 4 +- landingzones/caf_launchpad/landingzone.tf | 78 +- landingzones/caf_launchpad/main.tf | 25 +- landingzones/caf_launchpad/output.tf | 68 +- landingzones/caf_launchpad/variables.tf | 142 ++-- .../aad-pod-identity/aad-msi-binding.yaml | 16 + .../aad-pod-identity/aad_pod_identity.tf | 120 +++ .../add-ons/aad-pod-identity/backend.azurerm | 4 + .../build/kustomization_build.tf | 16 + .../add-ons/aad-pod-identity/build/main.tf | 7 + .../aad-pod-identity/build/variables.tf | 2 + .../aad-pod-identity/local.remote_tfstates.tf | 54 ++ .../add-ons/aad-pod-identity/main.tf | 17 + .../add-ons/aad-pod-identity/providers.tf | 32 + .../add-ons/aad-pod-identity/variables.tf | 36 + .../aks-pod-identity-assignment.tf | 58 ++ .../aks-secure-baseline/backend.azurerm | 4 + .../aks-secure-baseline/kustomization.yaml | 5 + .../local.remote_tfstates.tf | 54 ++ .../add-ons/aks-secure-baseline/main.tf | 17 + .../add-ons/aks-secure-baseline/providers.tf | 32 + .../aks-secure-baseline/secure-baseline.tf | 22 + .../add-ons/aks-secure-baseline/variables.tf | 36 + .../add-ons/aks_applications/app/main.tf | 7 + .../add-ons/aks_applications/app/module.tf | 48 ++ .../add-ons/aks_applications/app/output.tf | 0 .../add-ons/aks_applications/app/variables.tf | 5 + .../add-ons/aks_applications/applications.tf | 27 + .../add-ons/aks_applications/backend.azurerm | 4 + .../locals.remote_tfstates.tf | 54 ++ .../add-ons/aks_applications/main.tf | 75 ++ .../add-ons/aks_applications/output.tf | 0 .../add-ons/aks_applications/variables.tf | 36 + .../caf_solution/add-ons/azure_devops/azdo.tf | 15 + .../add-ons/azure_devops/azdo_agent_pools.tf | 52 ++ .../add-ons/azure_devops/azdo_pipelines.tf | 43 + .../azure_devops/azdo_service_endpoint.tf | 36 + .../azure_devops/azdo_variable_groups.tf | 39 + .../add-ons/azure_devops/backend.azurerm | 4 + .../documentation/images/pat_token.png | Bin 0 -> 78143 bytes .../azure_devops/locals.remote_tfstates.tf | 76 ++ .../caf_solution/add-ons/azure_devops/main.tf | 69 ++ .../add-ons/azure_devops/output.tf | 6 + .../add-ons/azure_devops/readme.md | 60 ++ .../200-contoso_demo/azure_devops.tfvars | 232 ++++++ .../200-contoso_demo/configurations.tfvars | 123 +++ .../200-contoso_demo/pipeline/rover.yaml | 70 ++ .../add-ons/azure_devops/solution.tf | 36 + .../add-ons/azure_devops/variables.tf | 102 +++ .../azure_devops_agent/backend.azurerm | 4 + .../azure_devops_agent/dynamic_secrets.tf | 11 + .../extensions/devops_selfhosted_agent.tf | 44 + .../extensions/variables.tf | 3 + .../locals.current_tfstates.tf | 74 ++ .../add-ons/azure_devops_agent/main.tf | 69 ++ .../add-ons/azure_devops_agent/output.tf | 34 + .../add-ons/azure_devops_agent/readme.md | 54 ++ .../level0/configuration.tfvars | 64 ++ .../200-contoso_demo/level0/keyvaults.tfvars | 28 + .../level0/storage_accounts.tfvars | 42 + .../level0/virtual_machines.tfvars | 79 ++ .../level1/configuration.tfvars | 68 ++ .../200-contoso_demo/level1/keyvaults.tfvars | 32 + .../level1/storage_accounts.tfvars | 42 + .../level1/virtual_machines.tfvars | 77 ++ .../cloud-init-install-rover-tools.config | 117 +++ .../scripts/devops_runtime_baremetal.sh | 109 +++ .../scripts/devops_runtime_docker.sh | 29 + .../add-ons/azure_devops_agent/solution.tf | 37 + .../add-ons/azure_devops_agent/variables.tf | 102 +++ .../vm_extention_devops_agent.tf | 37 + .../caf_solution/add-ons/caf_eslz/README.md | 44 + .../add-ons/caf_eslz/backend.azurerm | 4 + .../caf_solution/add-ons/caf_eslz/es_main.tf | 25 + .../caf_eslz/locals.remote_tfstates.tf | 46 ++ .../caf_solution/add-ons/caf_eslz/main.tf | 18 + .../caf_solution/add-ons/caf_eslz/output.tf | 0 .../100/enterprise_scale_contoso_com.tfvars | 25 + .../200/enterprise_scale_contoso_com.tfvars | 45 + ...chetype_definition_es_management.tmpl.json | 12 + .../200/lib/archetype_definition_es_root.json | 13 + ...nt_es_allowed_resource-locations.tmpl.json | 28 + ..._allowed_resourcegroup-locations.tmpl.json | 28 + ...licy_assignment_es_deploy_asc_ce.tmpl.json | 28 + ...ignment_es_deploy_asc_monitoring.tmpl.json | 88 ++ ...ssignment_es_deploy_asc_standard.tmpl.json | 21 + ...nment_es_deploy_diag_activitylog.tmpl.json | 25 + ...ment_es_deploy_diag_loganalytics.tmpl.json | 25 + ...icy_definition_es_deploy_asc_standard.json | 284 +++++++ .../add-ons/caf_eslz/variables.tf | 135 +++ .../add-ons/databricks/backend.azurerm | 4 + .../add-ons/databricks/databricks.tf | 21 + .../databricks/locals.remote_tfstates.tf | 43 + .../caf_solution/add-ons/databricks/main.tf | 63 ++ .../add-ons/databricks/variables.tf | 154 ++++ .../add-ons/helm-charts/backend.azurerm | 4 + .../add-ons/helm-charts/charts.tf | 21 + .../helm-charts/local.remote_tfstates.tf | 49 ++ .../caf_solution/add-ons/helm-charts/main.tf | 17 + .../add-ons/helm-charts/providers.tf | 39 + .../add-ons/helm-charts/variables.tf | 32 + .../terraform_cloud/example/tfc.tfvars | 25 + .../add-ons/terraform_cloud/main.tf | 51 ++ .../add-ons/terraform_cloud/readme.md | 44 + .../terraform_cloud/terraform_cloud.tf | 83 ++ .../add-ons/terraform_cloud/variables.tf | 85 ++ landingzones/caf_solution/backend.azurerm | 4 + landingzones/caf_solution/dynamic_secrets.tf | 10 + landingzones/caf_solution/landingzone.tf | 44 + landingzones/caf_solution/local.remote.tf | 100 +++ .../caf_solution/local.remote_objects.tf | 36 + .../caf_solution/locals.remote_tfstates.tf | 45 + landingzones/caf_solution/main.tf | 66 ++ .../modules/databricks/cluster.tf | 17 + .../modules/databricks/instance_pool.tf | 0 .../caf_solution/modules/databricks/main.tf | 9 + .../caf_solution/modules/databricks/output.tf | 7 + .../modules/databricks/variables.tf | 4 + landingzones/caf_solution/output.tf | 16 + landingzones/caf_solution/readme.md | 22 + .../100-passthrough/landingzone.tfvars | 12 + .../configuration.tfvars | 62 ++ .../network_security_group_definition.tfvars | 327 ++++++++ .../100-single-region-hub/readme.md | 45 + .../101-multi-region-hub/configuration.tfvars | 27 + .../network_security_group_definition.tfvars | 344 ++++++++ .../101-multi-region-hub/peering.tfvars | 31 + .../networking/101-multi-region-hub/readme.md | 50 ++ .../virtual_networks.tfvars | 78 ++ .../105-hub-and-spoke/configuration.tfvars | 155 ++++ .../network_security_group_definition.tfvars | 122 +++ .../networking/105-hub-and-spoke/readme.md | 52 ++ .../configuration.tfvars | 71 ++ .../network_security_group_definition.tfvars | 104 +++ .../106-hub-virtual-wan-firewall/readme.md | 47 ++ .../virtual_wan.tfvars | 84 ++ .../configuration.tfvars | 612 ++++++++++++++ .../201-multi-region-hub/configuration.tfvars | 767 +++++++++++++++++ .../210-aks-private/configuration.tfvars | 772 ++++++++++++++++++ .../peerings/launchpad/configuration.tfvars | 41 + .../shared_services/100/configuration.tfvars | 140 ++++ .../shared_services/200/configuration.tfvars | 156 ++++ .../cloud-init-install-rover-tools.config | 119 +++ .../caf_solution/scripts/grant_consent.sh | 28 + landingzones/caf_solution/variables.tf | 303 +++++++ 326 files changed, 12892 insertions(+), 177 deletions(-) rename {landingzones => landingzones.old}/caf_eslz/README.md (100%) rename {landingzones => landingzones.old}/caf_eslz/backend.azurerm (100%) rename {landingzones => landingzones.old}/caf_eslz/es_main.tf (100%) rename {landingzones => landingzones.old}/caf_eslz/landingzone.tf (100%) rename {landingzones => landingzones.old}/caf_eslz/locals.remote_tfstates.tf (100%) rename {landingzones => landingzones.old}/caf_eslz/main.tf (100%) rename {landingzones => landingzones.old}/caf_eslz/output.tf (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/archetype_definition_es_root.json (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json (100%) rename {landingzones => landingzones.old}/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json (100%) rename {landingzones => landingzones.old}/caf_eslz/variables.tf (100%) rename {landingzones => landingzones.old}/caf_foundations/README.md (100%) rename {landingzones => landingzones.old}/caf_foundations/backend.azurerm (100%) rename {landingzones => landingzones.old}/caf_foundations/dynamic_secrets.tf (100%) rename {landingzones => landingzones.old}/caf_foundations/landingzone.tf (100%) rename {landingzones => landingzones.old}/caf_foundations/locals.remote_tfstates.tf (100%) rename {landingzones => landingzones.old}/caf_foundations/main.tf (100%) rename {landingzones => landingzones.old}/caf_foundations/output.tf (100%) rename {landingzones => landingzones.old}/caf_foundations/variables.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/azdo.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/azdo_agent_pools.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/azdo_pipelines.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/azdo_service_endpoint.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/azdo_variable_groups.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/backend.azurerm (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/documentation/images/pat_token.png (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/locals.remote_tfstates.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/main.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/output.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/readme.md (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/solution.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops/variables.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/backend.azurerm (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/locals.current_tfstates.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/main.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/output.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/readme.md (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/solution.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/variables.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/terraform_cloud/main.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/terraform_cloud/readme.md (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/terraform_cloud/terraform_cloud.tf (100%) rename {landingzones => landingzones.old}/caf_launchpad/add-ons/terraform_cloud/variables.tf (100%) rename {landingzones/caf_networking => landingzones.old/caf_launchpad}/backend.azurerm (100%) create mode 100644 landingzones.old/caf_launchpad/documentation/img/launchpad-100.PNG create mode 100644 landingzones.old/caf_launchpad/documentation/img/launchpad-200.png create mode 100644 landingzones.old/caf_launchpad/documentation/img/launchpad_workflow.png create mode 100644 landingzones.old/caf_launchpad/documentation/variables.md create mode 100644 landingzones.old/caf_launchpad/dynamic_secrets.tf create mode 100644 landingzones.old/caf_launchpad/landingzone.tf create mode 100644 landingzones.old/caf_launchpad/main.tf create mode 100644 landingzones.old/caf_launchpad/output.tf create mode 100644 landingzones.old/caf_launchpad/readme.md create mode 100644 landingzones.old/caf_launchpad/scenario/100/README.md create mode 100644 landingzones.old/caf_launchpad/scenario/100/configuration.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/100/dynamic_secrets.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/100/iam_role_mapping.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/100/keyvaults.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/100/storage_accounts.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/compute.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/configuration.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostics_definition.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostics_destinations.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/dynamic_secrets.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_azuread.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_custom_roles.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_managed_identities.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_role_mapping.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/keyvaults.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/networking.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/networking_nsg_definition.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/readme.md create mode 100644 landingzones.old/caf_launchpad/scenario/200/storage_accounts.tfvars create mode 100644 landingzones.old/caf_launchpad/scenario/200/subscriptions.tfvars create mode 100644 landingzones.old/caf_launchpad/scripts/cloud-init-install-rover-tools.config rename {landingzones => landingzones.old}/caf_launchpad/scripts/grant_consent.sh (100%) create mode 100644 landingzones.old/caf_launchpad/variables.tf rename {landingzones/caf_shared_services => landingzones.old/caf_networking}/backend.azurerm (100%) rename {landingzones => landingzones.old}/caf_networking/documentation/img/100-single-region-hub.png (100%) rename {landingzones => landingzones.old}/caf_networking/documentation/img/101-multi-region-hub.png (100%) rename {landingzones => landingzones.old}/caf_networking/documentation/img/105-hub-and-spoke.png (100%) rename {landingzones => landingzones.old}/caf_networking/documentation/img/106-hub-virtual-wan-firewall.png (100%) rename {landingzones => landingzones.old}/caf_networking/landingzone.tf (100%) rename {landingzones => landingzones.old}/caf_networking/locals.remote_tfstates.tf (100%) rename {landingzones => landingzones.old}/caf_networking/main.tf (100%) rename {landingzones => landingzones.old}/caf_networking/output.tf (100%) rename {landingzones => landingzones.old}/caf_networking/readme.md (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/100-single-region-hub/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/100-single-region-hub/network_security_group_definition.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/100-single-region-hub/readme.md (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/101-multi-region-hub/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/101-multi-region-hub/network_security_group_definition.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/101-multi-region-hub/peering.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/101-multi-region-hub/readme.md (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/101-multi-region-hub/virtual_networks.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/105-hub-and-spoke/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/105-hub-and-spoke/network_security_group_definition.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/105-hub-and-spoke/readme.md (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/106-hub-virtual-wan-firewall/readme.md (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/106-hub-virtual-wan-firewall/virtual_wan.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/200-single-region-hub/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/201-multi-region-hub/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/210-aks-private/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/scenario/210-aks-private/peerings/launchpad/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_networking/variables.tf (100%) rename {landingzones/caf_solutions/add-ons/aks_applications => landingzones.old/caf_shared_services}/backend.azurerm (100%) rename {landingzones => landingzones.old}/caf_shared_services/landingzone.tf (100%) rename {landingzones => landingzones.old}/caf_shared_services/locals.remote_tfstates.tf (100%) rename {landingzones => landingzones.old}/caf_shared_services/main.tf (100%) rename {landingzones => landingzones.old}/caf_shared_services/output.tf (100%) rename {landingzones => landingzones.old}/caf_shared_services/readme.md (100%) rename {landingzones => landingzones.old}/caf_shared_services/scenario/100/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_shared_services/scenario/200/configuration.tfvars (100%) rename {landingzones => landingzones.old}/caf_shared_services/variables.tf (100%) rename {landingzones => landingzones.old}/caf_shared_services/vm_extensions.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/aks_applications/app/main.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/aks_applications/app/module.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/aks_applications/app/output.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/aks_applications/app/variables.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/aks_applications/applications.tf (100%) rename {landingzones/caf_solutions/add-ons/databricks => landingzones.old/caf_solutions/add-ons/aks_applications}/backend.azurerm (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/aks_applications/locals.remote_tfstates.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/aks_applications/main.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/aks_applications/output.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/aks_applications/variables.tf (100%) rename {landingzones/caf_solutions => landingzones.old/caf_solutions/add-ons/databricks}/backend.azurerm (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/databricks/databricks.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/databricks/locals.remote_tfstates.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/databricks/main.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/add-ons/databricks/variables.tf (100%) create mode 100644 landingzones.old/caf_solutions/backend.azurerm rename {landingzones => landingzones.old}/caf_solutions/dynamic_secrets.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/landingzone.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/locals.remote_tfstates.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/main.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/modules/databricks/cluster.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/modules/databricks/instance_pool.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/modules/databricks/main.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/modules/databricks/output.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/modules/databricks/variables.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/output.tf (100%) rename {landingzones => landingzones.old}/caf_solutions/readme.md (100%) rename {landingzones => landingzones.old}/caf_solutions/scripts/cloud-init-install-rover-tools.config (100%) rename {landingzones => landingzones.old}/caf_solutions/variables.tf (100%) create mode 100644 landingzones/caf_launchpad/.terraform.lock.hcl create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/backend.azurerm create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/build/main.tf create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/build/variables.tf create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/main.tf create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/providers.tf create mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/variables.tf create mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf create mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/backend.azurerm create mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml create mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf create mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/main.tf create mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/providers.tf create mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf create mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/variables.tf create mode 100644 landingzones/caf_solution/add-ons/aks_applications/app/main.tf create mode 100644 landingzones/caf_solution/add-ons/aks_applications/app/module.tf create mode 100644 landingzones/caf_solution/add-ons/aks_applications/app/output.tf create mode 100644 landingzones/caf_solution/add-ons/aks_applications/app/variables.tf create mode 100644 landingzones/caf_solution/add-ons/aks_applications/applications.tf create mode 100644 landingzones/caf_solution/add-ons/aks_applications/backend.azurerm create mode 100644 landingzones/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf create mode 100644 landingzones/caf_solution/add-ons/aks_applications/main.tf create mode 100644 landingzones/caf_solution/add-ons/aks_applications/output.tf create mode 100644 landingzones/caf_solution/add-ons/aks_applications/variables.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo_pipelines.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/backend.azurerm create mode 100644 landingzones/caf_solution/add-ons/azure_devops/documentation/images/pat_token.png create mode 100644 landingzones/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/main.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/output.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/readme.md create mode 100644 landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml create mode 100644 landingzones/caf_solution/add-ons/azure_devops/solution.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops/variables.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/backend.azurerm create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/main.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/output.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/readme.md create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/solution.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/variables.tf create mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/README.md create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/backend.azurerm create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/es_main.tf create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/main.tf create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/output.tf create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json create mode 100644 landingzones/caf_solution/add-ons/caf_eslz/variables.tf create mode 100644 landingzones/caf_solution/add-ons/databricks/backend.azurerm create mode 100644 landingzones/caf_solution/add-ons/databricks/databricks.tf create mode 100644 landingzones/caf_solution/add-ons/databricks/locals.remote_tfstates.tf create mode 100644 landingzones/caf_solution/add-ons/databricks/main.tf create mode 100644 landingzones/caf_solution/add-ons/databricks/variables.tf create mode 100644 landingzones/caf_solution/add-ons/helm-charts/backend.azurerm create mode 100644 landingzones/caf_solution/add-ons/helm-charts/charts.tf create mode 100644 landingzones/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf create mode 100644 landingzones/caf_solution/add-ons/helm-charts/main.tf create mode 100644 landingzones/caf_solution/add-ons/helm-charts/providers.tf create mode 100644 landingzones/caf_solution/add-ons/helm-charts/variables.tf create mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars create mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/main.tf create mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/readme.md create mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf create mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/variables.tf create mode 100644 landingzones/caf_solution/backend.azurerm create mode 100644 landingzones/caf_solution/dynamic_secrets.tf create mode 100644 landingzones/caf_solution/landingzone.tf create mode 100644 landingzones/caf_solution/local.remote.tf create mode 100644 landingzones/caf_solution/local.remote_objects.tf create mode 100644 landingzones/caf_solution/locals.remote_tfstates.tf create mode 100644 landingzones/caf_solution/main.tf create mode 100644 landingzones/caf_solution/modules/databricks/cluster.tf create mode 100644 landingzones/caf_solution/modules/databricks/instance_pool.tf create mode 100644 landingzones/caf_solution/modules/databricks/main.tf create mode 100644 landingzones/caf_solution/modules/databricks/output.tf create mode 100644 landingzones/caf_solution/modules/databricks/variables.tf create mode 100644 landingzones/caf_solution/output.tf create mode 100644 landingzones/caf_solution/readme.md create mode 100644 landingzones/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/100-single-region-hub/readme.md create mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/readme.md create mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/105-hub-and-spoke/readme.md create mode 100644 landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md create mode 100644 landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/210-aks-private/configuration.tfvars create mode 100644 landingzones/caf_solution/scenario/networking/210-aks-private/peerings/launchpad/configuration.tfvars create mode 100644 landingzones/caf_solution/scenario/shared_services/100/configuration.tfvars create mode 100644 landingzones/caf_solution/scenario/shared_services/200/configuration.tfvars create mode 100644 landingzones/caf_solution/scripts/cloud-init-install-rover-tools.config create mode 100644 landingzones/caf_solution/scripts/grant_consent.sh create mode 100644 landingzones/caf_solution/variables.tf diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 00195b17f..95d2821c0 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -6,7 +6,7 @@ version: '3.7' services: rover: - image: aztfmod/rover:0.13.6-2103.0304 + image: aztfmod/rover-preview:0.14.8-2103.181107 user: vscode labels: diff --git a/landingzones/caf_eslz/README.md b/landingzones.old/caf_eslz/README.md similarity index 100% rename from landingzones/caf_eslz/README.md rename to landingzones.old/caf_eslz/README.md diff --git a/landingzones/caf_eslz/backend.azurerm b/landingzones.old/caf_eslz/backend.azurerm similarity index 100% rename from landingzones/caf_eslz/backend.azurerm rename to landingzones.old/caf_eslz/backend.azurerm diff --git a/landingzones/caf_eslz/es_main.tf b/landingzones.old/caf_eslz/es_main.tf similarity index 100% rename from landingzones/caf_eslz/es_main.tf rename to landingzones.old/caf_eslz/es_main.tf diff --git a/landingzones/caf_eslz/landingzone.tf b/landingzones.old/caf_eslz/landingzone.tf similarity index 100% rename from landingzones/caf_eslz/landingzone.tf rename to landingzones.old/caf_eslz/landingzone.tf diff --git a/landingzones/caf_eslz/locals.remote_tfstates.tf b/landingzones.old/caf_eslz/locals.remote_tfstates.tf similarity index 100% rename from landingzones/caf_eslz/locals.remote_tfstates.tf rename to landingzones.old/caf_eslz/locals.remote_tfstates.tf diff --git a/landingzones/caf_eslz/main.tf b/landingzones.old/caf_eslz/main.tf similarity index 100% rename from landingzones/caf_eslz/main.tf rename to landingzones.old/caf_eslz/main.tf diff --git a/landingzones/caf_eslz/output.tf b/landingzones.old/caf_eslz/output.tf similarity index 100% rename from landingzones/caf_eslz/output.tf rename to landingzones.old/caf_eslz/output.tf diff --git a/landingzones/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars b/landingzones.old/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars similarity index 100% rename from landingzones/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars rename to landingzones.old/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars diff --git a/landingzones/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars b/landingzones.old/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars similarity index 100% rename from landingzones/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars rename to landingzones.old/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars diff --git a/landingzones/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json rename to landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json diff --git a/landingzones/caf_eslz/scenario/200/lib/archetype_definition_es_root.json b/landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_root.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/archetype_definition_es_root.json rename to landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_root.json diff --git a/landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json rename to landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json diff --git a/landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json rename to landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json diff --git a/landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json rename to landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json diff --git a/landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json rename to landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json diff --git a/landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json rename to landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json diff --git a/landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json rename to landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json diff --git a/landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json rename to landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json diff --git a/landingzones/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json similarity index 100% rename from landingzones/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json rename to landingzones.old/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json diff --git a/landingzones/caf_eslz/variables.tf b/landingzones.old/caf_eslz/variables.tf similarity index 100% rename from landingzones/caf_eslz/variables.tf rename to landingzones.old/caf_eslz/variables.tf diff --git a/landingzones/caf_foundations/README.md b/landingzones.old/caf_foundations/README.md similarity index 100% rename from landingzones/caf_foundations/README.md rename to landingzones.old/caf_foundations/README.md diff --git a/landingzones/caf_foundations/backend.azurerm b/landingzones.old/caf_foundations/backend.azurerm similarity index 100% rename from landingzones/caf_foundations/backend.azurerm rename to landingzones.old/caf_foundations/backend.azurerm diff --git a/landingzones/caf_foundations/dynamic_secrets.tf b/landingzones.old/caf_foundations/dynamic_secrets.tf similarity index 100% rename from landingzones/caf_foundations/dynamic_secrets.tf rename to landingzones.old/caf_foundations/dynamic_secrets.tf diff --git a/landingzones/caf_foundations/landingzone.tf b/landingzones.old/caf_foundations/landingzone.tf similarity index 100% rename from landingzones/caf_foundations/landingzone.tf rename to landingzones.old/caf_foundations/landingzone.tf diff --git a/landingzones/caf_foundations/locals.remote_tfstates.tf b/landingzones.old/caf_foundations/locals.remote_tfstates.tf similarity index 100% rename from landingzones/caf_foundations/locals.remote_tfstates.tf rename to landingzones.old/caf_foundations/locals.remote_tfstates.tf diff --git a/landingzones/caf_foundations/main.tf b/landingzones.old/caf_foundations/main.tf similarity index 100% rename from landingzones/caf_foundations/main.tf rename to landingzones.old/caf_foundations/main.tf diff --git a/landingzones/caf_foundations/output.tf b/landingzones.old/caf_foundations/output.tf similarity index 100% rename from landingzones/caf_foundations/output.tf rename to landingzones.old/caf_foundations/output.tf diff --git a/landingzones/caf_foundations/variables.tf b/landingzones.old/caf_foundations/variables.tf similarity index 100% rename from landingzones/caf_foundations/variables.tf rename to landingzones.old/caf_foundations/variables.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/azdo.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/azdo.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/azdo.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/azdo_agent_pools.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_agent_pools.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/azdo_agent_pools.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_agent_pools.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/azdo_pipelines.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_pipelines.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/azdo_pipelines.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_pipelines.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/azdo_service_endpoint.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_service_endpoint.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/azdo_service_endpoint.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_service_endpoint.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/azdo_variable_groups.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_variable_groups.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/azdo_variable_groups.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_variable_groups.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/backend.azurerm b/landingzones.old/caf_launchpad/add-ons/azure_devops/backend.azurerm similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/backend.azurerm rename to landingzones.old/caf_launchpad/add-ons/azure_devops/backend.azurerm diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/documentation/images/pat_token.png b/landingzones.old/caf_launchpad/add-ons/azure_devops/documentation/images/pat_token.png similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/documentation/images/pat_token.png rename to landingzones.old/caf_launchpad/add-ons/azure_devops/documentation/images/pat_token.png diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/locals.remote_tfstates.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/locals.remote_tfstates.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/locals.remote_tfstates.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/locals.remote_tfstates.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/main.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/main.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/output.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/output.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/readme.md b/landingzones.old/caf_launchpad/add-ons/azure_devops/readme.md similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/readme.md rename to landingzones.old/caf_launchpad/add-ons/azure_devops/readme.md diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml b/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml rename to landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/solution.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/solution.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/solution.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/solution.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops/variables.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops/variables.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/backend.azurerm b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/backend.azurerm similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/backend.azurerm rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/backend.azurerm diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/locals.current_tfstates.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/locals.current_tfstates.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/locals.current_tfstates.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/locals.current_tfstates.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/main.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/main.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/output.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/output.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/readme.md b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/readme.md similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/readme.md rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/readme.md diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/solution.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/solution.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/solution.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/solution.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/variables.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/variables.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf diff --git a/landingzones/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf rename to landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf diff --git a/landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars similarity index 100% rename from landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars rename to landingzones.old/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars diff --git a/landingzones/caf_launchpad/add-ons/terraform_cloud/main.tf b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/main.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/terraform_cloud/main.tf rename to landingzones.old/caf_launchpad/add-ons/terraform_cloud/main.tf diff --git a/landingzones/caf_launchpad/add-ons/terraform_cloud/readme.md b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/readme.md similarity index 100% rename from landingzones/caf_launchpad/add-ons/terraform_cloud/readme.md rename to landingzones.old/caf_launchpad/add-ons/terraform_cloud/readme.md diff --git a/landingzones/caf_launchpad/add-ons/terraform_cloud/terraform_cloud.tf b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/terraform_cloud.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/terraform_cloud/terraform_cloud.tf rename to landingzones.old/caf_launchpad/add-ons/terraform_cloud/terraform_cloud.tf diff --git a/landingzones/caf_launchpad/add-ons/terraform_cloud/variables.tf b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf similarity index 100% rename from landingzones/caf_launchpad/add-ons/terraform_cloud/variables.tf rename to landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf diff --git a/landingzones/caf_networking/backend.azurerm b/landingzones.old/caf_launchpad/backend.azurerm similarity index 100% rename from landingzones/caf_networking/backend.azurerm rename to landingzones.old/caf_launchpad/backend.azurerm diff --git a/landingzones.old/caf_launchpad/documentation/img/launchpad-100.PNG b/landingzones.old/caf_launchpad/documentation/img/launchpad-100.PNG new file mode 100644 index 0000000000000000000000000000000000000000..c93a36c46bafe2b787394e8729e469a1c98bc6db GIT binary patch literal 143702 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%0A}!)1#qO;^}XKhld?yny=?0OQ;f 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ȿ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

8x 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⪙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 z%0D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

eWxqjS32AL3iKBq8=c>e-zj+ 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 HA13EtOFTXU literal 0 HcmV?d00001 diff --git a/landingzones.old/caf_launchpad/documentation/variables.md b/landingzones.old/caf_launchpad/documentation/variables.md new file mode 100644 index 000000000..ce3e5b190 --- /dev/null +++ b/landingzones.old/caf_launchpad/documentation/variables.md @@ -0,0 +1,41 @@ +# Variables of the landing zone launchpad + +The launchpad landing zone leverage object variables to provide better understanding of the variables to set in the configuration files. + +## launchpad_mode + +There are two launchpad versions that can be deployed in an Azure subscription. When set to launchpad_light it not impersonating the rover to the launchpad aad application and keep the execution under the logged-in user. It is designed to provide a way to experience the landing zone when the logged-in user has limited privileges in the Azure AD tenant. + +| Variable | Default | Allowed value | Type | Example | +|---|---|---|---|---| +| launchpad_mode | "launchpad_light" | ["launchpad_light", "launchpad"] | string | | + +## level + +| Variable | Description | +|---|---| +| level | The Cloud Adoption Framework for the Terraform Edition proposes to group landing zones into different levels to group per function and more importantly to secure the levels and prevent a level to access to an un-authorized level. More details on this link | + + +"level0" | ["level0", "level1", "level2", "level3", "level4"] | string | | + +## global_settings + +| Variable | Description | +|---|---| +| global_settings | The global_settings is an object containing the default settings the landing zones from a higher level can hinerit. | + +| Default | +|---| +```hcl +default = { + default_location = "southeastasia" + prefix = null +} +``` +### Attributes + +| Attribute | Allowed values +|---| +* prefix is not set or null it generates a random 4 alpha char +* prefix = "" disable the prefix in the naming conventions diff --git a/landingzones.old/caf_launchpad/dynamic_secrets.tf b/landingzones.old/caf_launchpad/dynamic_secrets.tf new file mode 100644 index 000000000..5dd97a475 --- /dev/null +++ b/landingzones.old/caf_launchpad/dynamic_secrets.tf @@ -0,0 +1,11 @@ + +module dynamic_keyvault_secrets { + source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" + version = "~>5.2.0" + + for_each = try(var.dynamic_keyvault_secrets, {}) + + settings = each.value + keyvault = module.launchpad.keyvaults[each.key] + objects = module.launchpad +} diff --git a/landingzones.old/caf_launchpad/landingzone.tf b/landingzones.old/caf_launchpad/landingzone.tf new file mode 100644 index 000000000..762a46947 --- /dev/null +++ b/landingzones.old/caf_launchpad/landingzone.tf @@ -0,0 +1,48 @@ +module "launchpad" { + source = "aztfmod/caf/azurerm" + version = "~>5.2.0" + + current_landingzone_key = var.landingzone.key + tenant_id = var.tenant_id + tags = local.tags + global_settings = local.global_settings + enable = var.enable + logged_user_objectId = var.logged_user_objectId + logged_aad_app_objectId = var.logged_aad_app_objectId + user_type = var.user_type + log_analytics = var.log_analytics + diagnostics = { + diagnostics_definition = var.diagnostics_definition + diagnostics_destinations = var.diagnostics_destinations + diagnostic_event_hub_namespaces = var.diagnostic_event_hub_namespaces + diagnostic_log_analytics = var.diagnostic_log_analytics + diagnostic_storage_accounts = var.diagnostic_storage_accounts + } + event_hub_namespaces = var.event_hub_namespaces + resource_groups = var.resource_groups + keyvaults = var.keyvaults + keyvault_access_policies = var.keyvault_access_policies + keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps + subscriptions = var.subscriptions + compute = { + virtual_machines = var.virtual_machines + bastion_hosts = var.bastion_hosts + } + networking = { + vnets = var.vnets + network_security_group_definition = var.network_security_group_definition + public_ip_addresses = var.public_ip_addresses + azurerm_routes = var.azurerm_routes + route_tables = var.route_tables + } + storage_accounts = var.storage_accounts + # diagnostic_storage_accounts = var.diagnostic_storage_accounts + azuread_apps = var.azuread_apps + azuread_api_permissions = var.azuread_api_permissions + azuread_groups = var.azuread_groups + azuread_roles = var.azuread_roles + azuread_users = var.azuread_users + managed_identities = var.managed_identities + custom_role_definitions = var.custom_role_definitions + role_mapping = var.role_mapping +} diff --git a/landingzones.old/caf_launchpad/main.tf b/landingzones.old/caf_launchpad/main.tf new file mode 100644 index 000000000..7064f4f8f --- /dev/null +++ b/landingzones.old/caf_launchpad/main.tf @@ -0,0 +1,99 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.43" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.4.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + tls = { + source = "hashicorp/tls" + version = "~> 2.2.0" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "~> 1.2.0" + } + } + required_version = ">= 0.13" +} + + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +resource "random_string" "prefix" { + count = var.prefix == null ? 1 : 0 + length = 4 + special = false + upper = false + number = false +} + +resource "random_string" "alpha1" { + count = var.prefix == null ? 1 : 0 + length = 1 + special = false + upper = false + number = false +} + +locals { + landingzone_tag = { + landingzone = var.landingzone.key + } + tags = merge(local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = var.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = { + default_region = var.default_region + environment = var.environment + inherit_tags = var.inherit_tags + passthrough = var.passthrough + prefix = var.prefix + prefixes = var.prefix == "" ? null : [try(var.prefix, random_string.prefix.0.result)] + prefix_with_hyphen = var.prefix == "" ? "" : try(format("%s-", var.prefix) , format("%s-", random_string.prefix.0.result)) + random_length = var.random_length + regions = var.regions + tags = var.tags + use_slug = var.use_slug + } + + tfstates = map( + var.landingzone.key, + local.backend[var.landingzone.backend_type] + ) + + backend = { + azurerm = { + storage_account_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].name + container_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].containers["tfstate"].name + resource_group_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].resource_group_name + key = var.tf_name + level = var.landingzone.level + tenant_id = data.azurerm_client_config.current.tenant_id + subscription_id = data.azurerm_client_config.current.subscription_id + } + } + +} + +data "azurerm_client_config" "current" {} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/output.tf b/landingzones.old/caf_launchpad/output.tf new file mode 100644 index 000000000..cd0c82677 --- /dev/null +++ b/landingzones.old/caf_launchpad/output.tf @@ -0,0 +1,66 @@ +output global_settings { + value = local.global_settings + sensitive = true +} + +output diagnostics { + value = module.launchpad.diagnostics + sensitive = true +} + +# TODO: candidate to deprecation in 2101 +# output networking { +# value = map( +# var.landingzone.key, +# map( +# "vnets", module.launchpad.vnets +# ) +# ) +# sensitive = true +# description = "[WARNING] deprecated. Use vnets from 0.4" +# } + +output vnets { + value = tomap({ + (var.landingzone.key) = module.launchpad.vnets + }) + sensitive = true +} + +output tfstates { + value = local.tfstates + sensitive = true +} + +output backend_type { + value = var.landingzone.backend_type + sensitive = true +} + +output keyvaults { + value = tomap({ + (var.landingzone.key) = module.launchpad.keyvaults + }) + sensitive = true +} + +output managed_identities { + value = tomap({ + (var.landingzone.key) = module.launchpad.managed_identities + }) + sensitive = true +} + +output aad_apps { + value = tomap({ + (var.landingzone.key) = module.launchpad.aad_apps + }) + sensitive = true +} + +output azuread_groups { + value = tomap({ + (var.landingzone.key) = module.launchpad.azuread_groups + }) + sensitive = true +} diff --git a/landingzones.old/caf_launchpad/readme.md b/landingzones.old/caf_launchpad/readme.md new file mode 100644 index 000000000..9bc5aa947 --- /dev/null +++ b/landingzones.old/caf_launchpad/readme.md @@ -0,0 +1,206 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Launchpad + +The launchpad allows you to manage the foundations of landing zone environments by: + +* Securing remote Terraform state storage for multiple subscriptions. +* Managing the transition from manual to automated environments. +* Bring up the DevOps foundations using Azure DevOps, Terraform Cloud and GitHub actions (more to come). + +Launchpad operates at **level 0**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +
+ +## Getting started with launchpad + +Depending on what you are trying to achieve, we provide you with different levels of launchpads to cover different scenario: + +| level | scenario | supported environments | +|-----------------------|------------------------------------------------------------------------------------------------------------------|--------------------------------------------| +| [100](./scenario/100) | Start with this one! basic functionalities and features, no RBAC or security hardening - for demo and simple POC | working on AIRS subscriptions | +| [200](./scenario/200) | intermediate functionalities includes diagnostics features | may not work in AIRS, need AAD permissions | +| [300](./scenario/300) | advanced functionalities, includes RBAC features | not working in AIRS, need AAD permissions | +| [400](./scenario/400) | advanced functionalities, includes RBAC features and security hardening | not working in AIRS, need AAD permissions | + +You can pick your scenario and use one of the following commands: + +```bash +# Simple scenario for learning and demonstration +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \ + -parallelism=30 \ + -a apply + +# Advanced scenario - Requires Azure AD privileges +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ + -parallelism=30 \ + -a apply + +# If the tfstates are stored in a different subscription you need to execute the following command +rover -lz /tf/caf/landingzones/caf_launchpad \ + -tfstate_subscription_id \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ + -parallelism=30 \ + -a apply +``` + +
+ +## Overview of launchpad initialization + +![Launchpad Worklow](./documentation/img/launchpad_workflow.png) + +The rover executed in launchpad mode performs the following option to bootstrap your environment: + +1. **Initialize a terraform state**: + * The launchpad tries to retrieve an existing terraform state on Azure using the name of the tfstate file and the name of the workspace (level0 by default) + * Creates a tfstates folder if no remote state have been retrieved, this happens when your environment does not contain a storage account containing a tfstate matching the input parameters + + The Launchpad deployment relies on the following providers: + + * hashicorp/azurerm + * hashicorp/azuread + * hashicorp/random + * aztfmod/azurecaf + * hashicorp/null + + The latest version of the Launchpad relies on the new capabilities of **Terraform 0.13** + +2. **Call Terraform init**: + + * The launchpad then call terraform init to retrieve the provides and modules associated with the deployment + +3. **Call terraform apply**: + * deploy the resources as specified in the launchpad configuration files (see description below) + +```bash +Outputs: + +aad_apps = +azure_subscriptions = +diagnostics_map = +github_token_keyvault = +global_settings = +keyvaults = +log_analytics = +networking = +resource_groups = +``` + +4. **Create a workspace to host the local tfsate** - the launchpad will create two containers in the newly created storage account (in step 3): + * "sandpit" workspace + * "level0" (by default) workspace + +5. **Upload the launchpad state (tfstate) to the storage level0 workspace** - the state contains the default settings, keyvault id, and service principal id created during the launchpad deployment + +```bash +Moving launchpad to the cloud + - storage_account_name: storageaccname + - resource_group: hrjx-rg-launchpad-tfstates-rVb7GtKPXxHMa + - storage_key: retrieved +{ + "etag": "\"0x8D833A974C32C5F\"", + "lastModified": "2020-07-29T10:23:37+00:00" +} +``` + +
+ +## Launchpad architecture + +Each resource deployed with the launchpad is leveraging the [azurecaf provider](https://github.com/aztfmod/terraform-provider-azurecaf) to enforce naming convention. + +The launchpad deploys the following Azure components: + +1. Resource groups - By default the launchpad light auto variables will create three resources groups : launchpad-tfstates to host a the tfstate storage account, launchpad-security to host a keyvault, launchpad-devops-agents to host deployment agents should you choose to deploy VMs to automate subsequent deployment using Azure DevOps or GitHub + +2. Storage Accounts - a storage account in the launchpad-tfstates reosource group. The storage account contains the tfstate of the launchpad deployment and will be automatically configured as the Terraform remote backend when deploying landing zones with the rover + +3. KeyVaults - a keyvault resource to store with Get,List,Set,Delete access to for the logged in user (using the Azure CLI) - the keyvault will contain secrets of service principal accounts and managed identities + +4. A Log Analytics workspace and a KeyVault analytics solution deployed in the launchpad-devops-agent resource group. The Log Analytics workspace will gather the monitoring information and logs of both the DevOps agents and of the Keyvault + +5. Diagnostic settings - Creates Storage Account and Event Hubs (optional) to be used for diagnostics and operations logs. The resources are created in the launchpad-devops-agent resource group + +6. Virtual Network: The Launchpad can create Virtual Networks and subnets to deploy additional workloads during the bootstrap process - typically CI/CD agents + +7. Azure Active Directory Applications and role assignment + + This a critical aspect of the launchpad bootstrap process. The deployment creates an Azure AD Application named "caf_launchpad_level0" by default. The launchpad can be configured to create additional Azure AD Applications + + * The user deploying the launchpad is set to be the application owner + * A Service Principal + random password is created for each Application - the data is then stored in the referenced keyvault as multiple secrets + * Resource Access is assigned based on the aad_api_permissions object + * Each application can be assigned one or multiple Azure AD roles through the aad_roles object - empty by default + + By default the underlying service principal will be granted **owner** access to the subscription targeted by the launchpad deployment. This Azure AD Application + Service Principal will be used in subsequent deployments using the Rover. + + API permissions and admin consent are also granted during the bootstrap process. The grant_consent.sh scripts is called for to enable API access for a given Application + * The variable `aad_api_permissions` object can contains multiple entries + * each key references one of the Application defined in the `aad_apps` variable. The content of each entry is an api permission definition. + + The objectId, ApplicationId, ServicePrincipalID, client_secret are each stored in a keyvault using the secret_prefix value as defined in the code example + + The example below shows an App Definition, a role assignment and an API permission assignment. using three terraform variables with define an app called "caf_launchpad_github_terraformdev_github-integration-landingzones", we assign the Application Developer role to this application, finally we grand admin consent to the Active Directory Graph APIs. + + ```terraform + aad_apps = { + azure_caf-terraform-landingzones = { + application_name = "caf_launchpad_github_terraformdev_github-integration-landingzones" + password_expire_in_days = 60 + tenant_name = "terraformdev.onmicrosoft.com" + keyvault = { + keyvault_key = "launchpad" + secret_prefix = "caf-launchpad-github-terraformdev-github-integration-landingzones" + } + } + } + aad_roles = { + azure_caf-terraform-landingzones = { + roles = [ + "Application Developer" + ] + } + } + + aad_api_permissions = { + azure_caf-terraform-landingzones = { + active_directory_graph = { + resource_app_id = "00000002-0000-0000-c000-000000000000" + resource_access = { + active_directory_graph_resource_access_id_Application_ReadWrite_OwnedBy = { + id = "824c81eb-e3f8-4ee6-8f6d-de7f50d565b7" + type = "Role" + } + active_directory_graph_resource_access_id_Directory_ReadWrite_All = { + id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175" + type = "Role" + } + } + } + } + } + ``` + + The Azure Active Directory Application creation, Role assignment and Admin Consent delegation plays a critical role in the launchpad bootstrapping process. Make sure to work with your Tenant administrators to define the scope and the roles assigned the Application created by the launchpad. + +8. Release Agents (Optional): + * Deploys Virtual machines in the targeted Virtual Network. You may choose to leverage an existing Azure DevOps organization and deploy CI/CD agents and pipelines. The Agents will then be in charge of subsequent rover deployments to automate the IaC provisioning with Terraform + +## Launchpad add-ons + +Add-ons are additional capabilities to enhance the launchpad, that are deployed separately and managed by a different state. + +Current add-ons: + +* Azure DevOps Self Hosted Agents and Pipeline + +In-development add-ons: + +* Terrform Cloud Enterprise +* GitHub Actions diff --git a/landingzones.old/caf_launchpad/scenario/100/README.md b/landingzones.old/caf_launchpad/scenario/100/README.md new file mode 100644 index 000000000..dfa8197a7 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/100/README.md @@ -0,0 +1,44 @@ +# Launchpad - scenario 100 + +The 100 scenario is designed to demonstrate a basic functional foundations to store Terraform state on Azure storage and use it centrally. +The focus of this scenario is to be able to deploy a basic launchpad from a remote machine and use the portal to review the settings in a non-constrained environment. +For example in this scenario you can go to the Key Vaults and view the secrets from the portal, a feature that is disabled in the 300+ scenarios. +We recommend using the 100 scenario for demonstration purposes. + +An estimated time of 5 minutes is required to deploy this scenario. + +## Pre-requisites + +This scenario require the following privileges: + +| Component | Privileges | +|--------------------|--------------------| +| Active Directory | None | +| Azure subscription | Subscription owner | + +## Deployment + +```bash +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad -var-folder \ + /tf/caf/landingzones/caf_launchpad/scenario/100 \ + -a apply + +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \ + -a destroy +``` + +## Architecture diagram +![Launchpad 100](../../documentation/img/launchpad-100.PNG) + +## Services deployed in this scenario + +| Component | Purpose | +|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Resource group | Multiple resource groups are created to isolate the services. | +| Storage account | A storage account for remote tfstate management is provided for each level of the framework. Additional storage accounts are created for diagnostic logs. | +| Key Vault | The launchpad Key Vault hosts all secrets required by the rover to access the remote states, the Key Vault policies are created allowing the logged-in user to see secrets created and stored. | +| Virtual network | To secure the communication between the services a dedicated virtual network is deployed with a gateway subnet, bastion service, jumpbox and azure devops release agents. Service endpoints is enabled but not configured. | +| Azure AD Applications | An Azure AD application is created. This account is mainly use to bootstrap the services during the initialization. It is also considered as a breakglass account for the launchpad landing zones | diff --git a/landingzones.old/caf_launchpad/scenario/100/configuration.tfvars b/landingzones.old/caf_launchpad/scenario/100/configuration.tfvars new file mode 100644 index 000000000..ad53a6ba0 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/100/configuration.tfvars @@ -0,0 +1,68 @@ +landingzone = { + backend_type = "azurerm" + level = "level0" + key = "launchpad" +} + + +# Default region. When not set to a resource it will use that value +default_region = "region1" + +# naming convention settings +# for more settings on naming convention, please refer to the provider documentation: https://github.com/aztfmod/terraform-provider-azurecaf +# +# passthrough means the default CAF naming convention is not applied and you are responsible +# of the unicity of the names you are giving. the CAF provider will clear out +# passthrough = false +# adds random chars at the end of the names produced by the provider +# random_length = 3 + +# Inherit_tags defines if a resource will inherit it's resource group tags +inherit_tags = true + +regions = { + region1 = "southeastasia" + region2 = "eastasia" +} + +launchpad_key_names = { + azuread_app = "caf_launchpad_level0" + keyvault_client_secret = "aadapp-caf-launchpad-level0" + tfstates = [ + "level0", + ] +} + +resource_groups = { + level0 = { + name = "launchpad-level0" + tags = { + level = "level0" + } + } + level1 = { + name = "launchpad-level1" + tags = { + level = "level1" + } + } + level2 = { + name = "launchpad-level2" + tags = { + level = "level2" + } + } + level3 = { + name = "launchpad-level3" + tags = { + level = "level3" + } + } + level4 = { + name = "launchpad-level4" + tags = { + level = "level4" + } + } +} + diff --git a/landingzones.old/caf_launchpad/scenario/100/dynamic_secrets.tfvars b/landingzones.old/caf_launchpad/scenario/100/dynamic_secrets.tfvars new file mode 100644 index 000000000..23a0258d4 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/100/dynamic_secrets.tfvars @@ -0,0 +1,114 @@ + +# Store output attributes into keyvault secret +# Those values are used by the rover to connect the current remote state and +# identity the lower level +dynamic_keyvault_secrets = { + level0 = { + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level1 = { + lower_stg = { + output_key = "storage_accounts" + resource_key = "level0" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level0" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level2 = { + lower_stg = { + output_key = "storage_accounts" + resource_key = "level1" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level1" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level3 = { + lower_stg = { + output_key = "storage_accounts" + resource_key = "level2" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level2" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level4 = { + lower_stg = { + output_key = "storage_accounts" + resource_key = "level3" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level3" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } +} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/100/iam_role_mapping.tfvars b/landingzones.old/caf_launchpad/scenario/100/iam_role_mapping.tfvars new file mode 100644 index 000000000..87a218b80 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/100/iam_role_mapping.tfvars @@ -0,0 +1,47 @@ + +# +# Services supported: subscriptions, storage accounts and resource groups +# Can assign roles to: AD groups, AD object ID, AD applications, Managed identities +# +role_mapping = { + built_in_role_mapping = { + storage_accounts = { + level0 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + level1 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + level2 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + level3 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + level4 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + } + } + +} diff --git a/landingzones.old/caf_launchpad/scenario/100/keyvaults.tfvars b/landingzones.old/caf_launchpad/scenario/100/keyvaults.tfvars new file mode 100644 index 000000000..00de22b41 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/100/keyvaults.tfvars @@ -0,0 +1,99 @@ + +keyvaults = { + level0 = { + name = "level0" + resource_group_key = "level0" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level0" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + } + + level1 = { + name = "level1" + resource_group_key = "level1" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level1" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } + + level2 = { + name = "level2" + resource_group_key = "level2" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level2" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + } + + level3 = { + name = "level3" + resource_group_key = "level3" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level3" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } + + level4 = { + name = "level4" + resource_group_key = "level4" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level4" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} diff --git a/landingzones.old/caf_launchpad/scenario/100/storage_accounts.tfvars b/landingzones.old/caf_launchpad/scenario/100/storage_accounts.tfvars new file mode 100644 index 000000000..bb2834b9c --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/100/storage_accounts.tfvars @@ -0,0 +1,102 @@ + +storage_accounts = { + level0 = { + name = "level0" + resource_group_key = "level0" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + ## Those tags must never be changed after being set as they are used by the rover to locate the launchpad and the tfstates. + # Only adjust the environment value at creation time + tfstate = "level0" + environment = "sandpit" + launchpad = "launchpad" + ## + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + + level1 = { + name = "level1" + resource_group_key = "level1" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level1" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level2 = { + name = "level2" + resource_group_key = "level2" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level2" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level3 = { + name = "level3" + resource_group_key = "level3" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level3" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level4 = { + name = "level4" + resource_group_key = "level4" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level4" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + + } + +} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/compute.tfvars b/landingzones.old/caf_launchpad/scenario/200/compute.tfvars new file mode 100644 index 000000000..88164c5a4 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/compute.tfvars @@ -0,0 +1,100 @@ +################################################## +# +# Compute resources +# +################################################## + +bastion_hosts = { + launchpad_host = { + name = "bastion" + resource_group_key = "bastion_launchpad" + vnet_key = "devops_region1" + subnet_key = "AzureBastionSubnet" + public_ip_key = "bastion_host_rg1" + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "bastion_host" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + } +} + +# Virtual machines +virtual_machines = { + + # Configuration to deploy a bastion host linux virtual machine + bastion_host = { + resource_group_key = "bastion_launchpad" + region = "region1" + boot_diagnostics_storage_account_key = "bootdiag_region1" + provision_vm_agent = true + + os_type = "linux" + + # the auto-generated ssh key in keyvault secret. Secret name being {VM name}-ssh-public and {VM name}-ssh-private + keyvault_key = "secrets" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + vnet_key = "devops_region1" + subnet_key = "jumpbox" + name = "0" + enable_ip_forwarding = false + internal_dns_name_label = "nic0" + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "network_interface_card" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + } + + virtual_machine_settings = { + linux = { + name = "bastion" + size = "Standard_F2" + admin_username = "adminuser" + disable_password_authentication = true + custom_data = "scripts/cloud-init-install-rover-tools.config" + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "bastion-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference = { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "18.04-LTS" + version = "latest" + } + + identity = { + type = "UserAssigned" + managed_identity_keys = [ + "level0", "level1", "level2", "level3", "level4" + ] + } + + } + } + + } +} + diff --git a/landingzones.old/caf_launchpad/scenario/200/configuration.tfvars b/landingzones.old/caf_launchpad/scenario/200/configuration.tfvars new file mode 100644 index 000000000..36645019e --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/configuration.tfvars @@ -0,0 +1,100 @@ +landingzone = { + backend_type = "azurerm" + level = "level0" + key = "launchpad" +} + +enable = { + bastion_hosts = false + virtual_machines = false +} + +# Default region. When not set to a resource it will use that value +default_region = "region1" + +regions = { + region1 = "southeastasia" + region2 = "eastasia" +} + +# core tags to be applied accross this landing zone +tags = { + owner = "CAF" + deploymentType = "Terraform" + costCenter = "0" + BusinessUnit = "SHARED" + DR = "NON-DR-ENABLED" +} + +# naming convention settings +# for more settings on naming convention, please refer to the provider documentation: https://github.com/aztfmod/terraform-provider-azurecaf +# +# passthrough means the default CAF naming convention is not applied and you are responsible +# of the unicity of the names you are giving. the CAF provider will clear out +# passthrough = false +# adds random chars at the end of the names produced by the provider +# random_length = 3 + +# all resources deployed will inherit tags from the parent resource group +inherit_tags = true + +launchpad_key_names = { + azuread_app = "caf_launchpad_level0" + keyvault_client_secret = "aadapp-caf-launchpad-level0" + tfstates = [ + "level0", + "level1", + "level2", + "level3", + "level4" + ] +} + +resource_groups = { + level0 = { + name = "launchpad-level0" + tags = { + level = "level0" + } + } + level1 = { + name = "launchpad-level1" + tags = { + level = "level1" + } + } + level2 = { + name = "launchpad-level2" + tags = { + level = "level2" + } + } + level3 = { + name = "launchpad-level3" + tags = { + level = "level3" + } + } + level4 = { + name = "launchpad-level4" + tags = { + level = "level4" + } + } + security = { + name = "launchpad-security" + } + networking = { + name = "launchpad-networking" + } + ops = { + name = "operations" + } + siem = { + name = "siem-logs" + } + bastion_launchpad = { + name = "launchpad-bastion" + } +} + diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars new file mode 100644 index 000000000..75c3e3e90 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars @@ -0,0 +1,20 @@ + +# Event hub diagnostics +diagnostic_event_hub_namespaces = { + central_logs_region1 = { + name = "logs" + resource_group_key = "ops" + sku = "Standard" + region = "region1" + + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "event_hub_namespace" + destination_type = "storage" + destination_key = "all_regions" + } + } + } +} + + diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars new file mode 100644 index 000000000..fd2cb048f --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars @@ -0,0 +1,48 @@ +# +# Define the settings for log analytics workspace and solution map +# +diagnostic_log_analytics = { + central_logs_region1 = { + region = "region1" + name = "logs" + resource_group_key = "ops" + # you can setup up to 5 key + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "log_analytics" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + solutions_maps = { + NetworkMonitoring = { + "publisher" = "Microsoft" + "product" = "OMSGallery/NetworkMonitoring" + }, + ADAssessment = { + "publisher" = "Microsoft" + "product" = "OMSGallery/ADAssessment" + }, + ADReplication = { + "publisher" = "Microsoft" + "product" = "OMSGallery/ADReplication" + }, + AgentHealthAssessment = { + "publisher" = "Microsoft" + "product" = "OMSGallery/AgentHealthAssessment" + }, + DnsAnalytics = { + "publisher" = "Microsoft" + "product" = "OMSGallery/DnsAnalytics" + }, + ContainerInsights = { + "publisher" = "Microsoft" + "product" = "OMSGallery/ContainerInsights" + }, + KeyVaultAnalytics = { + "publisher" = "Microsoft" + "product" = "OMSGallery/KeyVaultAnalytics" + } + } + } +} diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars new file mode 100644 index 000000000..a58c5eee8 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars @@ -0,0 +1,64 @@ +# Defines different repositories for the diagnostics logs +# Storage accounts, log analytics, event hubs + +diagnostic_storage_accounts = { + # Stores diagnostic logging for region1 + diaglogs_region1 = { + name = "diaglogsrg1" + region = "region1" + resource_group_key = "ops" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores diagnostic logging for region2 + diaglogs_region2 = { + name = "diaglogrg2" + region = "region2" + resource_group_key = "ops" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores security logs for siem default region" + diagsiem_region1 = { + name = "siemsg1" + resource_group_key = "siem" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores diagnostic logging for region2 + diagsiem_region2 = { + name = "siemrg2" + region = "region2" + resource_group_key = "siem" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores boot diagnostic for region1 + bootdiag_region1 = { + name = "bootrg1" + region = "region1" + resource_group_key = "ops" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores boot diagnostic for region2 + bootdiag_region2 = { + name = "bootrg2" + region = "region2" + resource_group_key = "ops" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } +} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostics_definition.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostics_definition.tfvars new file mode 100644 index 000000000..10a20c4dd --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/diagnostics_definition.tfvars @@ -0,0 +1,274 @@ + +# +# Define a set of settings for the various type of Azure resources +# + +diagnostics_definition = { + log_analytics = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["Audit", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + default_all = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AuditEvent", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + bastion_host = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["BastionAuditLogs", true, false, 7], + ] + } + + } + + networking_all = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["VMProtectionAlerts", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + public_ip_address = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["DDoSProtectionNotifications", true, false, 7], + ["DDoSMitigationFlowLogs", true, false, 7], + ["DDoSMitigationReports", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + network_security_group = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["NetworkSecurityGroupEvent", true, false, 7], + ["NetworkSecurityGroupRuleCounter", true, false, 7], + ] + } + + } + + network_interface_card = { + name = "operational_logs_and_metrics" + categories = { + # log = [ + # # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + # ["AuditEvent", true, false, 7], + # ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + azure_container_registry = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["ContainerRegistryRepositoryEvents", true, false, 7], + ["ContainerRegistryLoginEvents", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + } + + azure_kubernetes_cluster = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["kube-apiserver", true, false, 7], + ["kube-audit", true, false, 7], + ["kube-audit-admin", true, false, 7], + ["kube-controller-manager", true, false, 7], + ["kube-scheduler", true, false, 7], + ["cluster-autoscaler", true, false, 7], + ["guard", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + } + + azure_site_recovery = { + name = "operational_logs_and_metrics" + log_analytics_destination_type = "Dedicated" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AzureBackupReport", true, true, 7], + ["CoreAzureBackup", true, true, 7], + ["AddonAzureBackupAlerts", true, true, 7], + ["AddonAzureBackupJobs", true, true, 7], + ["AddonAzureBackupPolicy", true, true, 7], + ["AddonAzureBackupProtectedInstance", true, true, 7], + ["AddonAzureBackupStorage", true, true, 7], + ["AzureSiteRecoveryJobs", true, true, 7], + ["AzureSiteRecoveryEvents", true, true, 7], + ["AzureSiteRecoveryReplicatedItems", true, true, 7], + ["AzureSiteRecoveryReplicationStats", true, true, 7], + ["AzureSiteRecoveryRecoveryPoints", true, true, 7], + ["AzureSiteRecoveryReplicationDataUploadRate", true, true, 7], + ["AzureSiteRecoveryProtectedDiskDataChurn", true, true, 30], + ] + metric = [ + #["AllMetrics", 60, True], + ] + } + + } + + azure_automation = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["JobLogs", true, true, 30], + ["JobStreams", true, true, 30], + ["DscNodeStatus", true, true, 30], + ] + metric = [ + # ["Category name", "Metric Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, true, 30], + ] + } + + } + + event_hub_namespace = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["ArchiveLogs", true, false, 7], + ["OperationalLogs", true, false, 7], + ["AutoScaleLogs", true, false, 7], + ["KafkaCoordinatorLogs", true, false, 7], + ["KafkaUserErrorLogs", true, false, 7], + ["EventHubVNetConnectionEvent", true, false, 7], + ["CustomerManagedKeyUserLogs", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + compliance_all = { + name = "compliance_logs" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AuditEvent", true, true, 365], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", false, false, 7], + ] + } + + } + + siem_all = { + name = "siem" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AuditEvent", true, true, 0], + ] + + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", false, false, 0], + ] + } + + } + + subscription_operations = { + name = "subscription_operations" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)"] + ["Administrative", true], + ["Security", true], + ["ServiceHealth", true], + ["Alert", true], + ["Policy", true], + ["Autoscale", true], + ["ResourceHealth", true], + ["Recommendation", true], + ] + } + } + + subscription_siem = { + name = "activity_logs_for_siem" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)"] + ["Administrative", false], + ["Security", true], + ["ServiceHealth", false], + ["Alert", false], + ["Policy", true], + ["Autoscale", false], + ["ResourceHealth", false], + ["Recommendation", false], + ] + } + + } + +} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostics_destinations.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostics_destinations.tfvars new file mode 100644 index 000000000..95ede1c24 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/diagnostics_destinations.tfvars @@ -0,0 +1,31 @@ +# Defines the different destination for the different log profiles +# Different profiles to target different operational teams + +diagnostics_destinations = { + # Storage keys must reference the azure region name + # For storage, reference "all_regions" and we will send the logs to the storage account + # in the region of the deployment + storage = { + all_regions = { + southeastasia = { + storage_account_key = "diagsiem_region1" + } + eastasia = { + storage_account_key = "diagsiem_region2" + } + } + } + + log_analytics = { + central_logs = { + log_analytics_key = "central_logs_region1" + log_analytics_destination_type = "Dedicated" + } + } + + event_hub_namespaces = { + central_logs = { + event_hub_namespace_key = "central_logs_region1" + } + } +} diff --git a/landingzones.old/caf_launchpad/scenario/200/dynamic_secrets.tfvars b/landingzones.old/caf_launchpad/scenario/200/dynamic_secrets.tfvars new file mode 100644 index 000000000..94042fd05 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/dynamic_secrets.tfvars @@ -0,0 +1,152 @@ + +# Store output attributes into keyvault secret +# Those values are used by the rover to connect the current remote state and +# identity the lower level +dynamic_keyvault_secrets = { + level0 = { + msi = { + output_key = "managed_identities" + resource_key = "level0" + attribute_key = "id" + secret_name = "msi-resource-id" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + admin = { + secret_name = "azdo-pat-admin" + value = "" + } + agent = { + secret_name = "azdo-pat-agent" + value = "" + } + } + level1 = { + msi = { + output_key = "managed_identities" + resource_key = "level1" + attribute_key = "id" + secret_name = "msi-resource-id" + } + lower_stg = { + output_key = "storage_accounts" + resource_key = "level0" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level0" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level2 = { + msi = { + output_key = "managed_identities" + resource_key = "level2" + attribute_key = "id" + secret_name = "msi-resource-id" + } + lower_stg = { + output_key = "storage_accounts" + resource_key = "level1" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level1" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level3 = { + msi = { + output_key = "managed_identities" + resource_key = "level3" + attribute_key = "id" + secret_name = "msi-resource-id" + } + lower_stg = { + output_key = "storage_accounts" + resource_key = "level2" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level2" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level4 = { + msi = { + output_key = "managed_identities" + resource_key = "level4" + attribute_key = "id" + secret_name = "msi-resource-id" + } + lower_stg = { + output_key = "storage_accounts" + resource_key = "level3" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level3" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } +} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_azuread.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_azuread.tfvars new file mode 100644 index 000000000..4a4856f72 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/iam_azuread.tfvars @@ -0,0 +1,184 @@ + +azuread_groups = { + keyvault_level0_rw = { + name = "caf-level0-keyvault-rw" + description = "Provide read and write access to the keyvault secrets / level0." + members = { + user_principal_names = [ + ] + group_names = [] + object_ids = [] + group_keys = [] + + service_principal_keys = [ + "caf_launchpad_level0" + ] + + } + owners = { + user_principal_names = [ + ] + service_principal_keys = [ + "caf_launchpad_level0" + ] + } + prevent_duplicate_name = false + } + + keyvault_level1_rw = { + name = "caf-level1-landingzones-rw" + description = "Provide read and write access to manage landingzones / level1." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + keyvault_level2_rw = { + name = "caf-level2-landingzones-rw" + description = "Provide read and write access to manage landingzones / level2." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + keyvault_level3_rw = { + name = "caf-level3-landingzones-rw" + description = "Provide read and write access to manage landingzones / level3." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + keyvault_level4_rw = { + name = "caf-level4-applications" + description = "Provide read access to the applications who need to deploy on the level4." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + caf_launchpad_Reader = { + name = "caf-launchpad-Reader" + description = "Provide Reader role to the caf launchpad landing zone resource groups." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + keyvault_password_rotation = { + name = "caf-level0-password-rotation-rw" + description = "Provide read and write access to the keyvault secrets / level0." + members = { + user_principal_names = [ + ] + group_names = [] + object_ids = [] + group_keys = [] + + service_principal_keys = [ + "caf_launchpad_level0" + ] + + } + owners = { + user_principal_names = [ + ] + service_principal_keys = [ + "caf_launchpad_level0" + ] + } + prevent_duplicate_name = false + } +} + +azuread_users = { + + # don't change that key + aad-user-devops-user-admin = { + useprefix = true + user_name = "caf-level0-security-devops-pat-rotation" + password_expire_in_days = 180 + + # Value must match with var.keyvaults[keyname] to store username and password for password rotation + keyvault_key = "secrets" + } + +} + +azuread_apps = { + # Do not rename the key "launchpad" to be able to upgrade to the standard launchpad + caf_launchpad_level0 = { + useprefix = true + application_name = "caf_launchpad_level0" + password_expire_in_days = 180 + + # Store the ${secret_prefix}-client-id, ${secret_prefix}-client-secret... + # Set the policy during the creation process of the launchpad + keyvaults = { + level0 = { + secret_prefix = "aadapp-caf-launchpad-level0" + } + } + } + +} + +# +# Available roles: +# az rest --method Get --uri https://graph.microsoft.com/v1.0/directoryRoleTemplates -o json | jq -r .value[].displayName +# +azuread_roles = { + azuread_apps = { + caf_launchpad_level0 = { + roles = [ + "Application Administrator", + "Application Developer", + "User Administrator" + ] + } + } + managed_identities = { + level0 = { + roles = [ + "Directory Readers", + "Application Developer", + "User Administrator" + ] + } + level1 = { + roles = [ + "Directory Readers" + ] + } + level2 = { + roles = [ + "Directory Readers" + ] + } + level3 = { + roles = [ + "Directory Readers" + ] + } + level4 = { + roles = [ + "Directory Readers" + ] + } + } +} diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars new file mode 100644 index 000000000..f73f3b73d --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars @@ -0,0 +1,43 @@ + + +azuread_api_permissions = { + + caf_launchpad_level0 = { + active_directory_graph = { + resource_app_id = "00000002-0000-0000-c000-000000000000" + resource_access = { + Application_ReadWrite_OwnedBy = { + id = "824c81eb-e3f8-4ee6-8f6d-de7f50d565b7" + type = "Role" + } + Directory_ReadWrite_All = { + id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175" + type = "Role" + } + } + } + + microsoft_graph = { + resource_app_id = "00000003-0000-0000-c000-000000000000" + resource_access = { + AppRoleAssignment_ReadWrite_All = { + id = "06b708a9-e830-4db3-a914-8e69da51d44f" + type = "Role" + } + DelegatedPermissionGrant_ReadWrite_All = { + id = "8e8e4742-1d95-4f68-9d56-6ee75648c72a" + type = "Role" + } + GroupReadWriteAll = { + id = "62a82d76-70ea-41e2-9197-370581804d09" + type = "Role" + } + RoleManagement_ReadWrite_Directory = { + id = "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8" + type = "Role" + } + } + } + } + +} diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_custom_roles.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_custom_roles.tfvars new file mode 100644 index 000000000..f314abf3a --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/iam_custom_roles.tfvars @@ -0,0 +1,76 @@ + +custom_role_definitions = { + caf-launchpad = { + name = "caf-launchpad" + useprefix = true + description = "Provide addition permissions on top of built-in Contributor role to manage landing zones deployment" + permissions = { + actions = [ + "Microsoft.Authorization/roleAssignments/delete", + "Microsoft.Authorization/roleAssignments/read", + "Microsoft.Authorization/roleAssignments/write", + "Microsoft.Authorization/roleDefinitions/delete", + "Microsoft.Authorization/roleDefinitions/read", + "Microsoft.Authorization/roleDefinitions/write", + "microsoft.insights/diagnosticSettings/delete", + "microsoft.insights/diagnosticSettings/read", + "microsoft.insights/diagnosticSettings/write", + "Microsoft.KeyVault/vaults/delete", + "Microsoft.KeyVault/vaults/read", + "Microsoft.KeyVault/vaults/write", + "Microsoft.KeyVault/vaults/accessPolicies/write", + "Microsoft.Network/networkSecurityGroups/delete", + "Microsoft.Network/networkSecurityGroups/read", + "Microsoft.Network/networkSecurityGroups/write", + "Microsoft.Network/networkSecurityGroups/join/action", + "Microsoft.Network/virtualNetworks/subnets/delete", + "Microsoft.Network/virtualNetworks/subnets/read", + "Microsoft.Network/virtualNetworks/subnets/write", + "Microsoft.OperationalInsights/workspaces/delete", + "Microsoft.OperationalInsights/workspaces/read", + "Microsoft.OperationalInsights/workspaces/write", + "Microsoft.OperationalInsights/workspaces/sharedKeys/action", + "Microsoft.OperationsManagement/solutions/delete", + "Microsoft.OperationsManagement/solutions/read", + "Microsoft.OperationsManagement/solutions/write", + "Microsoft.Storage/storageAccounts/delete", + "Microsoft.Storage/storageAccounts/read", + "Microsoft.Storage/storageAccounts/write", + "Microsoft.Storage/storageAccounts/blobServices/containers/delete", + "Microsoft.Storage/storageAccounts/blobServices/containers/read", + "Microsoft.Storage/storageAccounts/blobServices/containers/write", + "Microsoft.Storage/storageAccounts/blobServices/containers/lease/action", + "Microsoft.Storage/storageAccounts/blobServices/read", + "Microsoft.Storage/storageAccounts/listKeys/action", + "Microsoft.Resources/subscriptions/providers/read", + "Microsoft.Resources/subscriptions/read", + "Microsoft.Resources/subscriptions/resourcegroups/delete", + "Microsoft.Resources/subscriptions/resourcegroups/read", + "Microsoft.Resources/subscriptions/resourcegroups/write", + "Microsoft.Network/virtualNetworks/delete", + "Microsoft.Network/virtualNetworks/read", + "Microsoft.Network/virtualNetworks/write", + ] + } + + } + + caf-launchpad-contributor = { + name = "caf-launchpad-contributor" + useprefix = true + description = "Provide addition permissions on top of built-in Contributor role to manage landing zones deployment" + permissions = { + actions = [ + "Microsoft.Authorization/roleAssignments/delete", + "Microsoft.Authorization/roleAssignments/read", + "Microsoft.Authorization/roleAssignments/write", + "Microsoft.Authorization/roleDefinitions/delete", + "Microsoft.Authorization/roleDefinitions/read", + "Microsoft.Authorization/roleDefinitions/write", + "Microsoft.Resources/subscriptions/providers/read" + ] + } + } + +} + diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars new file mode 100644 index 000000000..e755b1ebd --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars @@ -0,0 +1,114 @@ +keyvault_access_policies_azuread_apps = { + level0 = { + caf_launchpad_level0 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + # A maximum of 16 access policies per keyvault + level1 = { + caf_launchpad_level0 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # A maximum of 16 access policies per keyvault + level2 = { + caf_launchpad_level0 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + + # A maximum of 16 access policies per keyvault + level3 = { + caf_launchpad_level0 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + + # A maximum of 16 access policies per keyvault + level4 = { + caf_launchpad_level1 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + + secrets = { + caf_launchpad_level0 = { + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } +} + +keyvault_access_policies = { + # A maximum of 16 access policies per keyvault + level0 = { + keyvault_level0_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + # A maximum of 16 access policies per keyvault + level1 = { + keyvault_level1_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level1_rw" + secret_permissions = ["Get", "List"] + } + } + + # A maximum of 16 access policies per keyvault + level2 = { + keyvault_level2_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level2_rw" + secret_permissions = ["Get", "List"] + } + } + + + # A maximum of 16 access policies per keyvault + level3 = { + keyvault_level3_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level3_rw" + secret_permissions = ["Get", "List"] + } + } + + + # A maximum of 16 access policies per keyvault + level4 = { + keyvault_level4_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level4_rw" + secret_permissions = ["Get", "List"] + } + } + + + secrets = { + keyvault_level0_rw = { + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + keyvault_password_rotation = { + azuread_group_key = "keyvault_password_rotation" + secret_permissions = ["Set", "Get", "List", "Delete", ] + } + } +} diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_managed_identities.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_managed_identities.tfvars new file mode 100644 index 000000000..a5e76137c --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/iam_managed_identities.tfvars @@ -0,0 +1,32 @@ + +managed_identities = { + level0 = { + # Used by the release agent to access the level0 keyvault and storage account with the tfstates in read / write + name = "landingzone-level0-msi" + resource_group_key = "security" + } + level1 = { + # Used by the release agent to access the level1 keyvault and storage account with the tfstates in read / write + # Has read access to level0 + name = "landingzone-level1-msi" + resource_group_key = "security" + } + level2 = { + # Used by the release agent to access the level2 keyvault and storage account with the tfstates in read / write + # Has read access to level1 + name = "landingzone-level2-msi" + resource_group_key = "security" + } + level3 = { + # Used by the release agent to access the level3 keyvault and storage account with the tfstates in read / write + # Has read access to level2 + name = "landingzone-level3-msi" + resource_group_key = "security" + } + level4 = { + # Used by the release agent to access the level4 keyvault and storage account with the tfstates in read / write + # Has read access to level3 + name = "landingzone-level4-msi" + resource_group_key = "security" + } +} diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_role_mapping.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_role_mapping.tfvars new file mode 100644 index 000000000..23a919f2a --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/iam_role_mapping.tfvars @@ -0,0 +1,154 @@ + +# +# Services supported: subscriptions, storage accounts and resource groups +# Can assign roles to: AD groups, AD object ID, AD applications, Managed identities +# +role_mapping = { + custom_role_mapping = { + subscriptions = { + logged_in_subscription = { + "caf-launchpad-contributor" = { + azuread_groups = { + keys = ["keyvault_level0_rw", "keyvault_level1_rw", "keyvault_level2_rw", "keyvault_level3_rw", "keyvault_level4_rw", ] + } + managed_identities = { + keys = ["level0", "level1", "level2", "level3", "level4"] + } + azuread_apps = { + keys = ["caf_launchpad_level0"] + } + } + } + } + } + + built_in_role_mapping = { + subscriptions = { + logged_in_subscription = { + "Contributor" = { + azuread_apps = { + keys = ["caf_launchpad_level0"] + } + managed_identities = { + keys = ["level0", "level1", "level2", "level3", "level4"] + } + } + } + } + resource_groups = { + level0 = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + security = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + networking = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + ops = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + siem = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + } + storage_accounts = { + level0 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + azuread_groups = { + keys = ["keyvault_level0_rw"] + } + azuread_apps = { + keys = ["caf_launchpad_level0"] + } + managed_identities = { + keys = ["level0"] + } + } + "Storage Blob Data Reader" = { + azuread_groups = { + keys = ["keyvault_level1_rw"] + } + } + } + level1 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + azuread_groups = { + keys = ["keyvault_level1_rw"] + } + managed_identities = { + keys = ["level1"] + } + } + "Storage Blob Data Reader" = { + azuread_groups = { + keys = ["keyvault_level2_rw"] + } + } + } + level2 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + azuread_groups = { + keys = ["keyvault_level2_rw"] + } + managed_identities = { + keys = ["level2"] + } + } + "Storage Blob Data Reader" = { + azuread_groups = { + keys = ["keyvault_level3_rw"] + } + } + } + level3 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + azuread_groups = { + keys = ["keyvault_level3_rw"] + } + managed_identities = { + keys = ["level3"] + } + } + "Storage Blob Data Reader" = { + azuread_groups = { + keys = ["keyvault_level4_rw"] + } + } + } + } + } + +} diff --git a/landingzones.old/caf_launchpad/scenario/200/keyvaults.tfvars b/landingzones.old/caf_launchpad/scenario/200/keyvaults.tfvars new file mode 100644 index 000000000..9b407a31d --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/keyvaults.tfvars @@ -0,0 +1,204 @@ + +keyvaults = { + level0 = { + name = "level0" + resource_group_key = "level0" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level0" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + level1 = { + name = "level1" + resource_group_key = "level1" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level1" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + level2 = { + name = "level2" + resource_group_key = "level2" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level2" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + level3 = { + name = "level3" + resource_group_key = "level3" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level3" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + level4 = { + name = "level4" + resource_group_key = "level4" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level4" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + secrets = { + name = "secrets" + resource_group_key = "security" + region = "region1" + sku_name = "premium" + soft_delete_enabled = true + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + + } +} diff --git a/landingzones.old/caf_launchpad/scenario/200/networking.tfvars b/landingzones.old/caf_launchpad/scenario/200/networking.tfvars new file mode 100644 index 000000000..e21c316fe --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/networking.tfvars @@ -0,0 +1,110 @@ + +################################################## +# +# Networking resources +# +################################################## + + +public_ip_addresses = { + bastion_host_rg1 = { + name = "pip1" + resource_group_key = "networking" + sku = "Standard" + allocation_method = "Static" + ip_version = "IPv4" + idle_timeout_in_minutes = "4" + + # you can setup up to 5 key + diagnostic_profiles = { + bastion_host_rg1 = { + definition_key = "public_ip_address" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + } +} + +vnets = { + devops_region1 = { + resource_group_key = "networking" + region = "region1" + vnet = { + name = "devops" + address_space = ["10.100.100.0/24"] + } + specialsubnets = {} + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["10.100.100.24/29"] + nsg_key = "azure_bastion_nsg" + } + jumpbox = { + name = "jumpbox" + cidr = ["10.100.100.32/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level0 = { + name = "level0" + cidr = ["10.100.100.40/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level1 = { + name = "level1" + cidr = ["10.100.100.48/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level2 = { + name = "level2" + cidr = ["10.100.100.56/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level3 = { + name = "level3" + cidr = ["10.100.100.64/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level4 = { + name = "level4" + cidr = ["10.100.100.72/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + private_endpoints = { + name = "private_endpoints" + cidr = ["10.100.100.128/25"] + enforce_private_link_endpoint_network_policies = true + } + } + + # you can setup up to 5 keys - vnet diganostic + diagnostic_profiles = { + vnet = { + definition_key = "networking_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + } +} + + +route_tables = { + default_no_internet = { + name = "default_no_internet" + resource_group_key = "networking" + } +} + +azurerm_routes = { + no_internet = { + name = "no_internet" + resource_group_key = "networking" + route_table_key = "default_no_internet" + address_prefix = "0.0.0.0/0" + next_hop_type = "None" + } +} diff --git a/landingzones.old/caf_launchpad/scenario/200/networking_nsg_definition.tfvars b/landingzones.old/caf_launchpad/scenario/200/networking_nsg_definition.tfvars new file mode 100644 index 000000000..8b558b104 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/networking_nsg_definition.tfvars @@ -0,0 +1,141 @@ + +# +# Definition of the networking security groups +# +network_security_group_definition = { + # This entry is applied to all subnets with no NSG defined + empty_nsg = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } + + azure_bastion_nsg = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } + + jumphost = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "ssh-inbound-22", + priority = "200" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + +} diff --git a/landingzones.old/caf_launchpad/scenario/200/readme.md b/landingzones.old/caf_launchpad/scenario/200/readme.md new file mode 100644 index 000000000..82f7b4440 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/readme.md @@ -0,0 +1,56 @@ +# Launchpad - scenario 200 + +The 200 scenario is an extension of the 100 scenario, meaning you can upgrade a 100 scenario to a 200. +The 200 scenario is designed to demonstrate a more secure environment but is not recommended for production use. +The focus of this scenario is to be able to deploy a more advanced launchpad from a remote machine and use the portal to review the settings in a non-constrained environment. +For example in this scenario you can go to the Key Vaults and view the secrets from the portal. A feature that is disabled in the 300+ scenarios. We recommend using the 200 scenario for demonstration or building new capabilities. + +An estimated time of 20 minutes is required to deploy this scenario. + +## Pre-requisites + +This scenario require the following privileges: + +| Component | Privileges | +|--------------------|--------------------------------| +| Active Directory | Application Administrator role | +| Azure subscription | Subscription owner | + +## Deployment + +```bash +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ + -level level0 \ + -a apply + +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ + -level level0 \ + -a destroy +``` + +## Architecture diagram + +![Launchpad 200](../../documentation/img/launchpad-200.png) + +## Services deployed in this scenario + +| Component | Purpose | +|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Resource group | Multiple resource groups are created to isolate the services | +| Storage account | A storage account for remote tfstate management is provided for each level of the framework. Additional storage accounts are created for diagnostic logs. | +| Keyvault | The launchpad keyvault hosts all secrets required by the rover to access the remote states. The secret keyvault is used to host all Azure AD users, applications and virtual machines's ssh key. | +| Virtual network | To secure the communication between the services a dedicated virtual network is deployed with a gateway subnet, bastion service, jumpbox and azure DevOps release agents. Service endpoints is enabled but not configured. | +| Bastion host service | Is use to support the access to the rover in scenario 300 and 400. | +| Jumpbox | A Linux server with the docker engine to run the rover and perform the deployment of the scenario 300 and 400. | +| Log analytics | A central log analytics workspace is created to collect all diagnostics and metrics information. Solutions are also deployed. | +| Diagnostic profiles | Default settings with 7 days retention of diagnostic profile is provided for all services. | +| Diagnostic destination | Operation sends the logs to a log analytics workspace and SIEM send all security logs to a storage account. | +| Diagnostic | Is enabled by default on all services. | +| Azure AD Users | An Azure AD user is created. This user is used in scenario 300 and 400 to own the Azure DevOps Personal Access Token (PAT) rotation. | +| Azure AD Applications | An Azure AD application is created. This account is mainly use to bootstrap the services during the initialization. It is also considered as a breakglass account for the launchpad landing zones. | +| Azure AD API permissions | A set of API permissions assigned to the Azure AD application to support management of the landing zones in a pipeline. | +| Managed Identities | A user managed Identity account is created for each Azure DevOps agent. This account is configured to get access to the keyvaults and Azure storage accounts | \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/storage_accounts.tfvars b/landingzones.old/caf_launchpad/scenario/200/storage_accounts.tfvars new file mode 100644 index 000000000..bd60a50f5 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/storage_accounts.tfvars @@ -0,0 +1,101 @@ + +storage_accounts = { + level0 = { + name = "level0" + resource_group_key = "level0" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + ## Those tags must never be changed after being set as they are used by the rover to locate the launchpad and the tfstates. + # Only adjust the environment value at creation time + tfstate = "level0" + environment = "sandpit" + launchpad = "launchpad" + ## + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level1 = { + name = "level1" + resource_group_key = "level1" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level1" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level2 = { + name = "level2" + resource_group_key = "level2" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level2" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level3 = { + name = "level3" + resource_group_key = "level3" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level3" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level4 = { + name = "level4" + resource_group_key = "level4" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level4" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + + } + +} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/subscriptions.tfvars b/landingzones.old/caf_launchpad/scenario/200/subscriptions.tfvars new file mode 100644 index 000000000..9e98ae770 --- /dev/null +++ b/landingzones.old/caf_launchpad/scenario/200/subscriptions.tfvars @@ -0,0 +1,20 @@ + +subscriptions = { + logged_in_subscription = { + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "subscription_operations" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "subscription_siem" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } +} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scripts/cloud-init-install-rover-tools.config b/landingzones.old/caf_launchpad/scripts/cloud-init-install-rover-tools.config new file mode 100644 index 000000000..53cd432e8 --- /dev/null +++ b/landingzones.old/caf_launchpad/scripts/cloud-init-install-rover-tools.config @@ -0,0 +1,49 @@ +#cloud-config + +apt: + preserve_sources_list: true + sources: + azure-cli.list: + source: "deb https://packages.microsoft.com/repos/azure-cli/ bionic main" + key: | + -----BEGIN PGP PUBLIC KEY BLOCK----- + Version: GnuPG v1.4.7 (GNU/Linux) + + mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT + LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV + 7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag + OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j + H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr + M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs + ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC + AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH + /32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe + MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy + 7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV + KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ + XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+ + NdCFTW7wY0Fb1fWJ+/KTsC4= + =J6gs + -----END PGP PUBLIC KEY BLOCK----- +package_update: true + +packages: + - ca-certificates + - curl + - apt-transport-https + - lsb-release + - azure-cli + +snap: + commands: + - snap install kubectl --classic +# Install docker and docker-compose +runcmd: + - [ sh, -c, 'curl -sSL https://get.docker.com/ | sh' ] + - [ sh, -c, 'curl -L https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep "tag_name" | cut -d \" -f4)/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose' ] + - [ sh, -c, 'sudo chmod +x /usr/local/bin/docker-compose' ] + +# Add default auto created user to docker group +system_info: + default_user: + groups: [docker] \ No newline at end of file diff --git a/landingzones/caf_launchpad/scripts/grant_consent.sh b/landingzones.old/caf_launchpad/scripts/grant_consent.sh similarity index 100% rename from landingzones/caf_launchpad/scripts/grant_consent.sh rename to landingzones.old/caf_launchpad/scripts/grant_consent.sh diff --git a/landingzones.old/caf_launchpad/variables.tf b/landingzones.old/caf_launchpad/variables.tf new file mode 100644 index 000000000..acf69cd2f --- /dev/null +++ b/landingzones.old/caf_launchpad/variables.tf @@ -0,0 +1,191 @@ +# Map of the current tfstate +variable tfstate_storage_account_name { + default = null +} +variable tfstate_container_name { + default = null +} +variable tfstate_key { + default = null +} +variable tfstate_resource_group_name { + default = null +} + +variable tenant_id {} +variable landingzone { + description = "The landing zone name is used to reference the tfstate in configuration files. Therefore while set it is recommended not to change" +} + +variable passthrough { + default = false +} +variable random_length { + default = null +} + +variable inherit_tags { + default = false +} + +variable default_region { + description = "Define the default region where services are deployed if the location is not set at the resource level" + default = "region1" +} + +variable regions { + type = map + description = "List of the regions where services can be deployed. This impact the diagnostics logs settings" + default = { + region1 = "southeastasia" + } +} + +variable enable { + description = "Map of services defined in the configuration file you want to disable during a deployment" + default = {} +} + +variable prefix { + default = null +} + +variable use_slug { + default = true +} + +variable log_analytics { + default = {} +} + +variable event_hub_namespaces { + default = {} +} + +# Do not change the default value to be able to upgrade to the standard launchpad +variable tf_name { + description = "Name of the terraform state in the blob storage (Does not include the extension .tfstate). Setup by the rover. Leave empty in the configuration file" + default = "" +} + +variable resource_groups {} + +variable storage_accounts {} +variable diagnostic_storage_accounts { + default = {} +} +variable diagnostic_event_hub_namespaces { + default = {} +} +variable diagnostic_log_analytics { + default = {} +} +variable keyvaults {} +variable keyvault_access_policies { + default = {} +} +variable dynamic_keyvault_secrets {} + +variable subscriptions { + default = {} +} + +## Azure Active Directory +variable azuread_apps { + default = {} +} +variable azuread_groups { + default = {} +} +variable azuread_users { + default = {} +} +variable azuread_roles { + default = {} +} +variable managed_identities { + default = {} +} + +variable virtual_machines { + description = "Virtual machine object" + default = {} +} + +variable bastion_hosts { + default = {} +} + +variable launchpad_key_names {} + +variable custom_role_definitions { + default = {} +} +variable role_mapping { + default = { + built_in_role_mapping = {} + custom_role_mapping = {} + } +} + +variable tags { + type = map + default = {} +} + +variable rover_version {} + +variable user_type {} + +variable logged_user_objectId { + default = null +} +variable logged_aad_app_objectId { + default = null +} + +variable aad_users { + default = {} +} + +variable aad_roles { + default = {} +} + +variable azuread_api_permissions { + default = {} +} + +variable environment { + type = string + description = "This variable is set by the rover during the deployment based on the -env or -environment flags. Default to sandpit" +} + +variable diagnostics_definition { + default = {} +} +variable diagnostics_destinations { + default = {} +} + +variable vnets { + default = {} +} + +variable network_security_group_definition { + default = {} +} + +variable public_ip_addresses { + default = {} +} +variable route_tables { + default = {} +} +variable azurerm_routes { + default = {} +} + +variable keyvault_access_policies_azuread_apps { + default = {} +} diff --git a/landingzones/caf_shared_services/backend.azurerm b/landingzones.old/caf_networking/backend.azurerm similarity index 100% rename from landingzones/caf_shared_services/backend.azurerm rename to landingzones.old/caf_networking/backend.azurerm diff --git a/landingzones/caf_networking/documentation/img/100-single-region-hub.png b/landingzones.old/caf_networking/documentation/img/100-single-region-hub.png similarity index 100% rename from landingzones/caf_networking/documentation/img/100-single-region-hub.png rename to landingzones.old/caf_networking/documentation/img/100-single-region-hub.png diff --git a/landingzones/caf_networking/documentation/img/101-multi-region-hub.png b/landingzones.old/caf_networking/documentation/img/101-multi-region-hub.png similarity index 100% rename from landingzones/caf_networking/documentation/img/101-multi-region-hub.png rename to landingzones.old/caf_networking/documentation/img/101-multi-region-hub.png diff --git a/landingzones/caf_networking/documentation/img/105-hub-and-spoke.png b/landingzones.old/caf_networking/documentation/img/105-hub-and-spoke.png similarity index 100% rename from landingzones/caf_networking/documentation/img/105-hub-and-spoke.png rename to landingzones.old/caf_networking/documentation/img/105-hub-and-spoke.png diff --git a/landingzones/caf_networking/documentation/img/106-hub-virtual-wan-firewall.png b/landingzones.old/caf_networking/documentation/img/106-hub-virtual-wan-firewall.png similarity index 100% rename from landingzones/caf_networking/documentation/img/106-hub-virtual-wan-firewall.png rename to landingzones.old/caf_networking/documentation/img/106-hub-virtual-wan-firewall.png diff --git a/landingzones/caf_networking/landingzone.tf b/landingzones.old/caf_networking/landingzone.tf similarity index 100% rename from landingzones/caf_networking/landingzone.tf rename to landingzones.old/caf_networking/landingzone.tf diff --git a/landingzones/caf_networking/locals.remote_tfstates.tf b/landingzones.old/caf_networking/locals.remote_tfstates.tf similarity index 100% rename from landingzones/caf_networking/locals.remote_tfstates.tf rename to landingzones.old/caf_networking/locals.remote_tfstates.tf diff --git a/landingzones/caf_networking/main.tf b/landingzones.old/caf_networking/main.tf similarity index 100% rename from landingzones/caf_networking/main.tf rename to landingzones.old/caf_networking/main.tf diff --git a/landingzones/caf_networking/output.tf b/landingzones.old/caf_networking/output.tf similarity index 100% rename from landingzones/caf_networking/output.tf rename to landingzones.old/caf_networking/output.tf diff --git a/landingzones/caf_networking/readme.md b/landingzones.old/caf_networking/readme.md similarity index 100% rename from landingzones/caf_networking/readme.md rename to landingzones.old/caf_networking/readme.md diff --git a/landingzones/caf_networking/scenario/100-single-region-hub/configuration.tfvars b/landingzones.old/caf_networking/scenario/100-single-region-hub/configuration.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/100-single-region-hub/configuration.tfvars rename to landingzones.old/caf_networking/scenario/100-single-region-hub/configuration.tfvars diff --git a/landingzones/caf_networking/scenario/100-single-region-hub/network_security_group_definition.tfvars b/landingzones.old/caf_networking/scenario/100-single-region-hub/network_security_group_definition.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/100-single-region-hub/network_security_group_definition.tfvars rename to landingzones.old/caf_networking/scenario/100-single-region-hub/network_security_group_definition.tfvars diff --git a/landingzones/caf_networking/scenario/100-single-region-hub/readme.md b/landingzones.old/caf_networking/scenario/100-single-region-hub/readme.md similarity index 100% rename from landingzones/caf_networking/scenario/100-single-region-hub/readme.md rename to landingzones.old/caf_networking/scenario/100-single-region-hub/readme.md diff --git a/landingzones/caf_networking/scenario/101-multi-region-hub/configuration.tfvars b/landingzones.old/caf_networking/scenario/101-multi-region-hub/configuration.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/101-multi-region-hub/configuration.tfvars rename to landingzones.old/caf_networking/scenario/101-multi-region-hub/configuration.tfvars diff --git a/landingzones/caf_networking/scenario/101-multi-region-hub/network_security_group_definition.tfvars b/landingzones.old/caf_networking/scenario/101-multi-region-hub/network_security_group_definition.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/101-multi-region-hub/network_security_group_definition.tfvars rename to landingzones.old/caf_networking/scenario/101-multi-region-hub/network_security_group_definition.tfvars diff --git a/landingzones/caf_networking/scenario/101-multi-region-hub/peering.tfvars b/landingzones.old/caf_networking/scenario/101-multi-region-hub/peering.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/101-multi-region-hub/peering.tfvars rename to landingzones.old/caf_networking/scenario/101-multi-region-hub/peering.tfvars diff --git a/landingzones/caf_networking/scenario/101-multi-region-hub/readme.md b/landingzones.old/caf_networking/scenario/101-multi-region-hub/readme.md similarity index 100% rename from landingzones/caf_networking/scenario/101-multi-region-hub/readme.md rename to landingzones.old/caf_networking/scenario/101-multi-region-hub/readme.md diff --git a/landingzones/caf_networking/scenario/101-multi-region-hub/virtual_networks.tfvars b/landingzones.old/caf_networking/scenario/101-multi-region-hub/virtual_networks.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/101-multi-region-hub/virtual_networks.tfvars rename to landingzones.old/caf_networking/scenario/101-multi-region-hub/virtual_networks.tfvars diff --git a/landingzones/caf_networking/scenario/105-hub-and-spoke/configuration.tfvars b/landingzones.old/caf_networking/scenario/105-hub-and-spoke/configuration.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/105-hub-and-spoke/configuration.tfvars rename to landingzones.old/caf_networking/scenario/105-hub-and-spoke/configuration.tfvars diff --git a/landingzones/caf_networking/scenario/105-hub-and-spoke/network_security_group_definition.tfvars b/landingzones.old/caf_networking/scenario/105-hub-and-spoke/network_security_group_definition.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/105-hub-and-spoke/network_security_group_definition.tfvars rename to landingzones.old/caf_networking/scenario/105-hub-and-spoke/network_security_group_definition.tfvars diff --git a/landingzones/caf_networking/scenario/105-hub-and-spoke/readme.md b/landingzones.old/caf_networking/scenario/105-hub-and-spoke/readme.md similarity index 100% rename from landingzones/caf_networking/scenario/105-hub-and-spoke/readme.md rename to landingzones.old/caf_networking/scenario/105-hub-and-spoke/readme.md diff --git a/landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars rename to landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars diff --git a/landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars rename to landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars diff --git a/landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall/readme.md b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/readme.md similarity index 100% rename from landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall/readme.md rename to landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/readme.md diff --git a/landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall/virtual_wan.tfvars b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/virtual_wan.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall/virtual_wan.tfvars rename to landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/virtual_wan.tfvars diff --git a/landingzones/caf_networking/scenario/200-single-region-hub/configuration.tfvars b/landingzones.old/caf_networking/scenario/200-single-region-hub/configuration.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/200-single-region-hub/configuration.tfvars rename to landingzones.old/caf_networking/scenario/200-single-region-hub/configuration.tfvars diff --git a/landingzones/caf_networking/scenario/201-multi-region-hub/configuration.tfvars b/landingzones.old/caf_networking/scenario/201-multi-region-hub/configuration.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/201-multi-region-hub/configuration.tfvars rename to landingzones.old/caf_networking/scenario/201-multi-region-hub/configuration.tfvars diff --git a/landingzones/caf_networking/scenario/210-aks-private/configuration.tfvars b/landingzones.old/caf_networking/scenario/210-aks-private/configuration.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/210-aks-private/configuration.tfvars rename to landingzones.old/caf_networking/scenario/210-aks-private/configuration.tfvars diff --git a/landingzones/caf_networking/scenario/210-aks-private/peerings/launchpad/configuration.tfvars b/landingzones.old/caf_networking/scenario/210-aks-private/peerings/launchpad/configuration.tfvars similarity index 100% rename from landingzones/caf_networking/scenario/210-aks-private/peerings/launchpad/configuration.tfvars rename to landingzones.old/caf_networking/scenario/210-aks-private/peerings/launchpad/configuration.tfvars diff --git a/landingzones/caf_networking/variables.tf b/landingzones.old/caf_networking/variables.tf similarity index 100% rename from landingzones/caf_networking/variables.tf rename to landingzones.old/caf_networking/variables.tf diff --git a/landingzones/caf_solutions/add-ons/aks_applications/backend.azurerm b/landingzones.old/caf_shared_services/backend.azurerm similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/backend.azurerm rename to landingzones.old/caf_shared_services/backend.azurerm diff --git a/landingzones/caf_shared_services/landingzone.tf b/landingzones.old/caf_shared_services/landingzone.tf similarity index 100% rename from landingzones/caf_shared_services/landingzone.tf rename to landingzones.old/caf_shared_services/landingzone.tf diff --git a/landingzones/caf_shared_services/locals.remote_tfstates.tf b/landingzones.old/caf_shared_services/locals.remote_tfstates.tf similarity index 100% rename from landingzones/caf_shared_services/locals.remote_tfstates.tf rename to landingzones.old/caf_shared_services/locals.remote_tfstates.tf diff --git a/landingzones/caf_shared_services/main.tf b/landingzones.old/caf_shared_services/main.tf similarity index 100% rename from landingzones/caf_shared_services/main.tf rename to landingzones.old/caf_shared_services/main.tf diff --git a/landingzones/caf_shared_services/output.tf b/landingzones.old/caf_shared_services/output.tf similarity index 100% rename from landingzones/caf_shared_services/output.tf rename to landingzones.old/caf_shared_services/output.tf diff --git a/landingzones/caf_shared_services/readme.md b/landingzones.old/caf_shared_services/readme.md similarity index 100% rename from landingzones/caf_shared_services/readme.md rename to landingzones.old/caf_shared_services/readme.md diff --git a/landingzones/caf_shared_services/scenario/100/configuration.tfvars b/landingzones.old/caf_shared_services/scenario/100/configuration.tfvars similarity index 100% rename from landingzones/caf_shared_services/scenario/100/configuration.tfvars rename to landingzones.old/caf_shared_services/scenario/100/configuration.tfvars diff --git a/landingzones/caf_shared_services/scenario/200/configuration.tfvars b/landingzones.old/caf_shared_services/scenario/200/configuration.tfvars similarity index 100% rename from landingzones/caf_shared_services/scenario/200/configuration.tfvars rename to landingzones.old/caf_shared_services/scenario/200/configuration.tfvars diff --git a/landingzones/caf_shared_services/variables.tf b/landingzones.old/caf_shared_services/variables.tf similarity index 100% rename from landingzones/caf_shared_services/variables.tf rename to landingzones.old/caf_shared_services/variables.tf diff --git a/landingzones/caf_shared_services/vm_extensions.tf b/landingzones.old/caf_shared_services/vm_extensions.tf similarity index 100% rename from landingzones/caf_shared_services/vm_extensions.tf rename to landingzones.old/caf_shared_services/vm_extensions.tf diff --git a/landingzones/caf_solutions/add-ons/aks_applications/app/main.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/app/main.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/app/main.tf rename to landingzones.old/caf_solutions/add-ons/aks_applications/app/main.tf diff --git a/landingzones/caf_solutions/add-ons/aks_applications/app/module.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/app/module.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/app/module.tf rename to landingzones.old/caf_solutions/add-ons/aks_applications/app/module.tf diff --git a/landingzones/caf_solutions/add-ons/aks_applications/app/output.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/app/output.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/app/output.tf rename to landingzones.old/caf_solutions/add-ons/aks_applications/app/output.tf diff --git a/landingzones/caf_solutions/add-ons/aks_applications/app/variables.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/app/variables.tf rename to landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf diff --git a/landingzones/caf_solutions/add-ons/aks_applications/applications.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/applications.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/applications.tf rename to landingzones.old/caf_solutions/add-ons/aks_applications/applications.tf diff --git a/landingzones/caf_solutions/add-ons/databricks/backend.azurerm b/landingzones.old/caf_solutions/add-ons/aks_applications/backend.azurerm similarity index 100% rename from landingzones/caf_solutions/add-ons/databricks/backend.azurerm rename to landingzones.old/caf_solutions/add-ons/aks_applications/backend.azurerm diff --git a/landingzones/caf_solutions/add-ons/aks_applications/locals.remote_tfstates.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/locals.remote_tfstates.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/locals.remote_tfstates.tf rename to landingzones.old/caf_solutions/add-ons/aks_applications/locals.remote_tfstates.tf diff --git a/landingzones/caf_solutions/add-ons/aks_applications/main.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/main.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/main.tf rename to landingzones.old/caf_solutions/add-ons/aks_applications/main.tf diff --git a/landingzones/caf_solutions/add-ons/aks_applications/output.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/output.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/output.tf rename to landingzones.old/caf_solutions/add-ons/aks_applications/output.tf diff --git a/landingzones/caf_solutions/add-ons/aks_applications/variables.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/aks_applications/variables.tf rename to landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf diff --git a/landingzones/caf_solutions/backend.azurerm b/landingzones.old/caf_solutions/add-ons/databricks/backend.azurerm similarity index 100% rename from landingzones/caf_solutions/backend.azurerm rename to landingzones.old/caf_solutions/add-ons/databricks/backend.azurerm diff --git a/landingzones/caf_solutions/add-ons/databricks/databricks.tf b/landingzones.old/caf_solutions/add-ons/databricks/databricks.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/databricks/databricks.tf rename to landingzones.old/caf_solutions/add-ons/databricks/databricks.tf diff --git a/landingzones/caf_solutions/add-ons/databricks/locals.remote_tfstates.tf b/landingzones.old/caf_solutions/add-ons/databricks/locals.remote_tfstates.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/databricks/locals.remote_tfstates.tf rename to landingzones.old/caf_solutions/add-ons/databricks/locals.remote_tfstates.tf diff --git a/landingzones/caf_solutions/add-ons/databricks/main.tf b/landingzones.old/caf_solutions/add-ons/databricks/main.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/databricks/main.tf rename to landingzones.old/caf_solutions/add-ons/databricks/main.tf diff --git a/landingzones/caf_solutions/add-ons/databricks/variables.tf b/landingzones.old/caf_solutions/add-ons/databricks/variables.tf similarity index 100% rename from landingzones/caf_solutions/add-ons/databricks/variables.tf rename to landingzones.old/caf_solutions/add-ons/databricks/variables.tf diff --git a/landingzones.old/caf_solutions/backend.azurerm b/landingzones.old/caf_solutions/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones.old/caf_solutions/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solutions/dynamic_secrets.tf b/landingzones.old/caf_solutions/dynamic_secrets.tf similarity index 100% rename from landingzones/caf_solutions/dynamic_secrets.tf rename to landingzones.old/caf_solutions/dynamic_secrets.tf diff --git a/landingzones/caf_solutions/landingzone.tf b/landingzones.old/caf_solutions/landingzone.tf similarity index 100% rename from landingzones/caf_solutions/landingzone.tf rename to landingzones.old/caf_solutions/landingzone.tf diff --git a/landingzones/caf_solutions/locals.remote_tfstates.tf b/landingzones.old/caf_solutions/locals.remote_tfstates.tf similarity index 100% rename from landingzones/caf_solutions/locals.remote_tfstates.tf rename to landingzones.old/caf_solutions/locals.remote_tfstates.tf diff --git a/landingzones/caf_solutions/main.tf b/landingzones.old/caf_solutions/main.tf similarity index 100% rename from landingzones/caf_solutions/main.tf rename to landingzones.old/caf_solutions/main.tf diff --git a/landingzones/caf_solutions/modules/databricks/cluster.tf b/landingzones.old/caf_solutions/modules/databricks/cluster.tf similarity index 100% rename from landingzones/caf_solutions/modules/databricks/cluster.tf rename to landingzones.old/caf_solutions/modules/databricks/cluster.tf diff --git a/landingzones/caf_solutions/modules/databricks/instance_pool.tf b/landingzones.old/caf_solutions/modules/databricks/instance_pool.tf similarity index 100% rename from landingzones/caf_solutions/modules/databricks/instance_pool.tf rename to landingzones.old/caf_solutions/modules/databricks/instance_pool.tf diff --git a/landingzones/caf_solutions/modules/databricks/main.tf b/landingzones.old/caf_solutions/modules/databricks/main.tf similarity index 100% rename from landingzones/caf_solutions/modules/databricks/main.tf rename to landingzones.old/caf_solutions/modules/databricks/main.tf diff --git a/landingzones/caf_solutions/modules/databricks/output.tf b/landingzones.old/caf_solutions/modules/databricks/output.tf similarity index 100% rename from landingzones/caf_solutions/modules/databricks/output.tf rename to landingzones.old/caf_solutions/modules/databricks/output.tf diff --git a/landingzones/caf_solutions/modules/databricks/variables.tf b/landingzones.old/caf_solutions/modules/databricks/variables.tf similarity index 100% rename from landingzones/caf_solutions/modules/databricks/variables.tf rename to landingzones.old/caf_solutions/modules/databricks/variables.tf diff --git a/landingzones/caf_solutions/output.tf b/landingzones.old/caf_solutions/output.tf similarity index 100% rename from landingzones/caf_solutions/output.tf rename to landingzones.old/caf_solutions/output.tf diff --git a/landingzones/caf_solutions/readme.md b/landingzones.old/caf_solutions/readme.md similarity index 100% rename from landingzones/caf_solutions/readme.md rename to landingzones.old/caf_solutions/readme.md diff --git a/landingzones/caf_solutions/scripts/cloud-init-install-rover-tools.config b/landingzones.old/caf_solutions/scripts/cloud-init-install-rover-tools.config similarity index 100% rename from landingzones/caf_solutions/scripts/cloud-init-install-rover-tools.config rename to landingzones.old/caf_solutions/scripts/cloud-init-install-rover-tools.config diff --git a/landingzones/caf_solutions/variables.tf b/landingzones.old/caf_solutions/variables.tf similarity index 100% rename from landingzones/caf_solutions/variables.tf rename to landingzones.old/caf_solutions/variables.tf diff --git a/landingzones/caf_launchpad/.terraform.lock.hcl b/landingzones/caf_launchpad/.terraform.lock.hcl new file mode 100644 index 000000000..f8ae181d8 --- /dev/null +++ b/landingzones/caf_launchpad/.terraform.lock.hcl @@ -0,0 +1,72 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/aztfmod/azurecaf" { + version = "1.2.2" + constraints = "~> 1.2.0" + hashes = [ + "h1:5GMOMtQg1/i6yigQ++Nol/lno2D67D5LhO3/VLPMq9A=", + ] +} + +provider "registry.terraform.io/hashicorp/azuread" { + version = "1.4.0" + constraints = "~> 1.4.0" + hashes = [ + "h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=", + ] +} + +provider "registry.terraform.io/hashicorp/azurerm" { + version = "2.50.0" + constraints = "~> 2.50.0, ~> 2.50" + hashes = [ + "h1:Vr6WUm88s9hXGkyVjHtHsP2Jmc2ypQXn6ww7dXtvk1M=", + ] +} + +provider "registry.terraform.io/hashicorp/external" { + version = "1.2.0" + constraints = "~> 1.2.0" + hashes = [ + "h1:wDfbBn+171g9/+aWqkicrN5l1S3kuqEX4J1zyPCDsoY=", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "2.1.2" + constraints = "~> 2.1.0" + hashes = [ + "h1:CFnENdqQu4g3LJNevA32aDxcUz2qGkRGQpFfkI8TCdE=", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "2.2.1" + constraints = "~> 2.2.1" + hashes = [ + "h1:Zg1Bpi6vr7b0H6no8kVDfEucn5pvNALivdrVKVHarGs=", + ] +} + +provider "registry.terraform.io/hashicorp/template" { + version = "2.2.0" + hashes = [ + "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", + ] +} + +provider "registry.terraform.io/hashicorp/time" { + version = "0.7.0" + hashes = [ + "h1:1VPBq+jeoCf0wVCxnzK6BNnOmNbXf3fRnDmS43Jw7Oo=", + ] +} + +provider "registry.terraform.io/hashicorp/tls" { + version = "2.2.0" + constraints = "~> 2.2.0" + hashes = [ + "h1:BRvNNW/32RAFXRcEAovtJWVbFt8zesIKkQm2N0GBCn8=", + ] +} diff --git a/landingzones/caf_launchpad/dynamic_secrets.tf b/landingzones/caf_launchpad/dynamic_secrets.tf index 5dd97a475..c288df262 100644 --- a/landingzones/caf_launchpad/dynamic_secrets.tf +++ b/landingzones/caf_launchpad/dynamic_secrets.tf @@ -1,7 +1,7 @@ -module dynamic_keyvault_secrets { +module "dynamic_keyvault_secrets" { source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" - version = "~>5.2.0" + version = "5.3.0-preview2" for_each = try(var.dynamic_keyvault_secrets, {}) diff --git a/landingzones/caf_launchpad/landingzone.tf b/landingzones/caf_launchpad/landingzone.tf index 762a46947..c2657d989 100644 --- a/landingzones/caf_launchpad/landingzone.tf +++ b/landingzones/caf_launchpad/landingzone.tf @@ -1,48 +1,54 @@ module "launchpad" { source = "aztfmod/caf/azurerm" - version = "~>5.2.0" + version = "5.3.0-preview2" - current_landingzone_key = var.landingzone.key - tenant_id = var.tenant_id - tags = local.tags - global_settings = local.global_settings - enable = var.enable - logged_user_objectId = var.logged_user_objectId - logged_aad_app_objectId = var.logged_aad_app_objectId - user_type = var.user_type - log_analytics = var.log_analytics - diagnostics = { - diagnostics_definition = var.diagnostics_definition - diagnostics_destinations = var.diagnostics_destinations - diagnostic_event_hub_namespaces = var.diagnostic_event_hub_namespaces - diagnostic_log_analytics = var.diagnostic_log_analytics - diagnostic_storage_accounts = var.diagnostic_storage_accounts - } + azuread_api_permissions = var.azuread_api_permissions + azuread_apps = var.azuread_apps + azuread_groups = var.azuread_groups + azuread_roles = var.azuread_roles + azuread_users = var.azuread_users + current_landingzone_key = var.landingzone.key + custom_role_definitions = var.custom_role_definitions + enable = var.enable event_hub_namespaces = var.event_hub_namespaces - resource_groups = var.resource_groups - keyvaults = var.keyvaults + global_settings = local.global_settings keyvault_access_policies = var.keyvault_access_policies keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps + keyvaults = var.keyvaults + log_analytics = var.log_analytics + logged_aad_app_objectId = var.logged_aad_app_objectId + logged_user_objectId = var.logged_user_objectId + managed_identities = var.managed_identities + resource_groups = var.resource_groups + role_mapping = var.role_mapping + storage_accounts = var.storage_accounts subscriptions = var.subscriptions + tags = local.tags + tenant_id = var.tenant_id + user_type = var.user_type + + diagnostics = { + diagnostics_definition = try(var.diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = try(var.diagnostics.diagnostics_destinations, var.diagnostics_destinations) + diagnostic_event_hub_namespaces = try(var.diagnostics.diagnostic_event_hub_namespaces, var.diagnostic_event_hub_namespaces) + diagnostic_log_analytics = try(var.diagnostics.diagnostic_log_analytics, var.diagnostic_log_analytics) + diagnostic_storage_accounts = try(var.diagnostics.diagnostic_storage_accounts, var.diagnostic_storage_accounts) + } + compute = { - virtual_machines = var.virtual_machines - bastion_hosts = var.bastion_hosts + virtual_machines = try(var.compute.virtual_machines, var.virtual_machines) + bastion_hosts = try(var.compute.bastion_hosts, var.bastion_hosts) } + networking = { - vnets = var.vnets - network_security_group_definition = var.network_security_group_definition - public_ip_addresses = var.public_ip_addresses - azurerm_routes = var.azurerm_routes - route_tables = var.route_tables + vnets = try(var.networking.vnets, var.vnets) + network_security_group_definition = try(var.networking.network_security_group_definition, var.network_security_group_definition) + public_ip_addresses = try(var.networking.public_ip_addresses, var.public_ip_addresses) + azurerm_routes = try(var.networking.azurerm_routes, var.azurerm_routes) + route_tables = try(var.networking.route_tables, var.route_tables) + } + + security = { + keyvault_keys = var.keyvault_keys } - storage_accounts = var.storage_accounts - # diagnostic_storage_accounts = var.diagnostic_storage_accounts - azuread_apps = var.azuread_apps - azuread_api_permissions = var.azuread_api_permissions - azuread_groups = var.azuread_groups - azuread_roles = var.azuread_roles - azuread_users = var.azuread_users - managed_identities = var.managed_identities - custom_role_definitions = var.custom_role_definitions - role_mapping = var.role_mapping } diff --git a/landingzones/caf_launchpad/main.tf b/landingzones/caf_launchpad/main.tf index 7064f4f8f..2c52ea02b 100644 --- a/landingzones/caf_launchpad/main.tf +++ b/landingzones/caf_launchpad/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "~> 2.43" + version = "~> 2.50" } azuread = { source = "hashicorp/azuread" @@ -34,11 +34,7 @@ terraform { provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } + features {} } resource "random_string" "prefix" { @@ -49,19 +45,12 @@ resource "random_string" "prefix" { number = false } -resource "random_string" "alpha1" { - count = var.prefix == null ? 1 : 0 - length = 1 - special = false - upper = false - number = false -} - locals { landingzone_tag = { - landingzone = var.landingzone.key + "landingzone" = var.landingzone.key } - tags = merge(local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = var.environment }, { "rover_version" = var.rover_version }, var.tags) + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) global_settings = { default_region = var.default_region @@ -69,8 +58,8 @@ locals { inherit_tags = var.inherit_tags passthrough = var.passthrough prefix = var.prefix - prefixes = var.prefix == "" ? null : [try(var.prefix, random_string.prefix.0.result)] - prefix_with_hyphen = var.prefix == "" ? "" : try(format("%s-", var.prefix) , format("%s-", random_string.prefix.0.result)) + prefixes = var.prefix == "" ? null : [try(random_string.prefix.0.result, var.prefix)] + prefix_with_hyphen = var.prefix == "" ? null : format("%s", try(random_string.prefix.0.result, var.prefix)) random_length = var.random_length regions = var.regions tags = var.tags diff --git a/landingzones/caf_launchpad/output.tf b/landingzones/caf_launchpad/output.tf index cd0c82677..313425b12 100644 --- a/landingzones/caf_launchpad/output.tf +++ b/landingzones/caf_launchpad/output.tf @@ -1,66 +1,16 @@ -output global_settings { - value = local.global_settings - sensitive = true -} - -output diagnostics { - value = module.launchpad.diagnostics - sensitive = true -} - -# TODO: candidate to deprecation in 2101 -# output networking { -# value = map( -# var.landingzone.key, -# map( -# "vnets", module.launchpad.vnets -# ) -# ) -# sensitive = true -# description = "[WARNING] deprecated. Use vnets from 0.4" -# } -output vnets { - value = tomap({ - (var.landingzone.key) = module.launchpad.vnets - }) +output "objects" { + value = tomap( + { (var.landingzone.key) = { + for key, value in module.launchpad : key => value + if try(value, {}) != {} + } + } + ) sensitive = true } -output tfstates { +output "tfstates" { value = local.tfstates sensitive = true } - -output backend_type { - value = var.landingzone.backend_type - sensitive = true -} - -output keyvaults { - value = tomap({ - (var.landingzone.key) = module.launchpad.keyvaults - }) - sensitive = true -} - -output managed_identities { - value = tomap({ - (var.landingzone.key) = module.launchpad.managed_identities - }) - sensitive = true -} - -output aad_apps { - value = tomap({ - (var.landingzone.key) = module.launchpad.aad_apps - }) - sensitive = true -} - -output azuread_groups { - value = tomap({ - (var.landingzone.key) = module.launchpad.azuread_groups - }) - sensitive = true -} diff --git a/landingzones/caf_launchpad/variables.tf b/landingzones/caf_launchpad/variables.tf index acf69cd2f..6ff3d9dd7 100644 --- a/landingzones/caf_launchpad/variables.tf +++ b/landingzones/caf_launchpad/variables.tf @@ -1,191 +1,211 @@ # Map of the current tfstate -variable tfstate_storage_account_name { +variable "tfstate_storage_account_name" { default = null } -variable tfstate_container_name { +variable "tfstate_container_name" { default = null } -variable tfstate_key { +variable "tfstate_key" { default = null } -variable tfstate_resource_group_name { +variable "tfstate_resource_group_name" { default = null } -variable tenant_id {} -variable landingzone { +variable "tenant_id" {} +variable "landingzone" { description = "The landing zone name is used to reference the tfstate in configuration files. Therefore while set it is recommended not to change" } -variable passthrough { +variable "passthrough" { default = false } -variable random_length { +variable "random_length" { default = null } -variable inherit_tags { +variable "inherit_tags" { default = false } -variable default_region { +variable "default_region" { description = "Define the default region where services are deployed if the location is not set at the resource level" default = "region1" } -variable regions { - type = map +variable "regions" { + type = map(any) description = "List of the regions where services can be deployed. This impact the diagnostics logs settings" default = { region1 = "southeastasia" } } -variable enable { +variable "enable" { description = "Map of services defined in the configuration file you want to disable during a deployment" default = {} } -variable prefix { +variable "prefix" { default = null } -variable use_slug { +variable "use_slug" { default = true } -variable log_analytics { +variable "log_analytics" { default = {} } -variable event_hub_namespaces { +variable "event_hub_namespaces" { default = {} } # Do not change the default value to be able to upgrade to the standard launchpad -variable tf_name { +variable "tf_name" { description = "Name of the terraform state in the blob storage (Does not include the extension .tfstate). Setup by the rover. Leave empty in the configuration file" default = "" } -variable resource_groups {} +variable "resource_groups" {} -variable storage_accounts {} -variable diagnostic_storage_accounts { +variable "storage_accounts" {} +variable "keyvaults" {} +variable "keyvault_access_policies" { default = {} } -variable diagnostic_event_hub_namespaces { +variable "keyvault_keys" { default = {} } -variable diagnostic_log_analytics { - default = {} -} -variable keyvaults {} -variable keyvault_access_policies { - default = {} -} -variable dynamic_keyvault_secrets {} +variable "dynamic_keyvault_secrets" {} -variable subscriptions { +variable "subscriptions" { default = {} } ## Azure Active Directory -variable azuread_apps { +variable "azuread_apps" { default = {} } -variable azuread_groups { +variable "azuread_groups" { default = {} } -variable azuread_users { +variable "azuread_users" { default = {} } -variable azuread_roles { +variable "azuread_roles" { default = {} } -variable managed_identities { +variable "managed_identities" { default = {} } -variable virtual_machines { - description = "Virtual machine object" - default = {} +variable "networking" { + default = {} } -variable bastion_hosts { +variable "compute" { default = {} } -variable launchpad_key_names {} +variable "launchpad_key_names" {} -variable custom_role_definitions { +variable "custom_role_definitions" { default = {} } -variable role_mapping { +variable "role_mapping" { default = { built_in_role_mapping = {} custom_role_mapping = {} } } -variable tags { - type = map +variable "tags" { + type = map(any) default = {} } -variable rover_version {} +variable "rover_version" {} -variable user_type {} +variable "user_type" {} -variable logged_user_objectId { +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable aad_users { +variable "aad_users" { default = {} } -variable aad_roles { +variable "aad_roles" { default = {} } -variable azuread_api_permissions { +variable "azuread_api_permissions" { default = {} } -variable environment { +variable "environment" { type = string description = "This variable is set by the rover during the deployment based on the -env or -environment flags. Default to sandpit" } -variable diagnostics_definition { +variable "diagnostics" { + default = {} +} + +variable "diagnostics_definition" { + default = {} +} + +variable "diagnostics_destinations" { + default = {} +} + +variable "diagnostic_event_hub_namespaces" { default = {} } -variable diagnostics_destinations { + +variable "diagnostic_log_analytics" { default = {} } -variable vnets { +variable "diagnostic_storage_accounts" { default = {} } -variable network_security_group_definition { +variable "keyvault_access_policies_azuread_apps" { default = {} } -variable public_ip_addresses { +variable "virtual_machines" { default = {} } -variable route_tables { + +variable "bastion_hosts" { default = {} } -variable azurerm_routes { + +variable "vnets" { default = {} } -variable keyvault_access_policies_azuread_apps { +variable "network_security_group_definition" { default = {} } + +variable "public_ip_addresses" { + default = {} +} + +variable "azurerm_routes" { + default = {} +} + +variable "route_tables" { + default = {} +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml b/landingzones/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml new file mode 100644 index 000000000..c430b2385 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml @@ -0,0 +1,16 @@ +apiVersion: aadpodidentity.k8s.io/v1 +kind: AzureIdentity +metadata: + name: podmi-caf-rover-platform-level0 +spec: + type: 0 + resourceID: ${resource_id} + clientID: ${client_id} +--- +apiVersion: aadpodidentity.k8s.io/v1 +kind: AzureIdentityBinding +metadata: + name: podmi-gitlab-runner-binding +spec: + azureIdentity: podmi-caf-rover-platform-level0 + selector: podmi-caf-rover-platform-level0 \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf new file mode 100644 index 000000000..05f60b4d1 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf @@ -0,0 +1,120 @@ +resource "kubernetes_namespace" "ns" { + metadata { + name = var.aad_pod_identity.namespace + } +} + +module "build" { + depends_on = [kubernetes_namespace.ns] + source = "./build" + for_each = try(data.kustomization_overlay.aad_pod_identity, {}) + + settings = each.value +} + + + +data "kustomization_overlay" "aad_pod_identity" { + for_each = local.msi + + resources = [ + "aad-msi-binding.yaml", + ] + + namespace = var.aad_pod_identity.namespace + + patches { + patch = <<-EOF + - op: replace + path: /spec/resourceID + value: ${each.value.id} + EOF + + target = { + kind = "AzureIdentity" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /spec/clientID + value: ${each.value.client_id} + EOF + + target = { + kind = "AzureIdentity" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /metadata/name + value: ${each.value.azureIdentity} + EOF + + target = { + kind = "AzureIdentity" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /metadata/name + value: ${each.value.azureIdentity}-binding + EOF + + target = { + kind = "AzureIdentityBinding" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /spec/azureIdentity + value: ${each.value.azureIdentity} + EOF + + target = { + kind = "AzureIdentityBinding" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /spec/selector + value: ${each.value.selector} + EOF + + target = { + kind = "AzureIdentityBinding" + } + } +} + +output "manifests" { + value = data.kustomization_overlay.aad_pod_identity +} + +locals { + msi = { + for msi in flatten( + [ + for key, value in var.managed_identities : [ + for msi_key in value.msi_keys : { + key = key + msi_key = msi_key + client_id = local.remote.managed_identities[value.lz_key][msi_key].client_id + id = local.remote.managed_identities[value.lz_key][msi_key].id + azureIdentity = value["aad_msi_bindings"][msi_key].azureIdentity + selector = value["aad_msi_bindings"][msi_key].selector + } + ] + ] + ) : format("%s-%s", msi.key, msi.msi_key) => msi + } +} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/backend.azurerm b/landingzones/caf_solution/add-ons/aad-pod-identity/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf new file mode 100644 index 000000000..985bd96f5 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf @@ -0,0 +1,16 @@ +resource "kustomization_resource" "p0" { + for_each = var.settings.ids_prio[0] + manifest = var.settings.manifests[each.value] +} + +resource "kustomization_resource" "p1" { + depends_on = [kustomization_resource.p0] + for_each = var.settings.ids_prio[1] + manifest = var.settings.manifests[each.value] +} + +resource "kustomization_resource" "p2" { + depends_on = [kustomization_resource.p1] + for_each = var.settings.ids_prio[2] + manifest = var.settings.manifests[each.value] +} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/build/main.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/build/main.tf new file mode 100644 index 000000000..e65c6fa22 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/build/main.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + kustomization = { + source = "kbst/kustomization" + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/build/variables.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/build/variables.tf new file mode 100644 index 000000000..f5c321890 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/build/variables.tf @@ -0,0 +1,2 @@ +variable "settings" { +} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf new file mode 100644 index 000000000..d458c18a1 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf @@ -0,0 +1,54 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = try(each.value.container, local.landingzone[try(each.value.level, "current")].container_name) + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics + + remote = { + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + global_settings = local.global_settings + diagnostics = local.diagnostics + + + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) + } + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) + } + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) + } + } + +} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/main.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/main.tf new file mode 100644 index 000000000..f0cc7ddbe --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/main.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.51.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.0.2" + } + kustomization = { + source = "kbst/kustomization" + version = "~> 0.4.0" + } + } + required_version = ">= 0.13" +} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/providers.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/providers.tf new file mode 100644 index 000000000..be2b3abb1 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/providers.tf @@ -0,0 +1,32 @@ + +provider "azurerm" { + features { + } +} + +provider "kubernetes" { + host = local.k8sconfigs[var.aks_cluster_key].host + username = local.k8sconfigs[var.aks_cluster_key].username + password = local.k8sconfigs[var.aks_cluster_key].password + client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate + client_key = local.k8sconfigs[var.aks_cluster_key].client_key + cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate +} + +provider "kustomization" { + kubeconfig_raw = local.k8sconfigs[var.aks_cluster_key].kube_admin_config_raw +} + +locals { + k8sconfigs = { + for key, value in var.aks_clusters : key => { + kube_admin_config_raw = local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config_raw + host = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.host : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.host + username = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.username : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.username + password = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.password : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.password + client_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_certificate) + client_key = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_key) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_key) + cluster_ca_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.cluster_ca_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.cluster_ca_certificate) + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/variables.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/variables.tf new file mode 100644 index 000000000..971033737 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aad-pod-identity/variables.tf @@ -0,0 +1,36 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "landingzone" {} +variable "rover_version" { + default = null +} +variable "tags" { + default = {} +} + +###### + +variable "aks_cluster_key" { + description = "AKS cluster key to deploy the Gitlab Helm charts. The key must be defined in the variable aks_clusters" +} +variable "aks_cluster_vnet_key" { + +} +variable "aks_clusters" {} +variable "vnets" {} +variable "managed_identities" { + description = "Map of the user managed identities." +} + +variable "aad_pod_identity" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf new file mode 100644 index 000000000..96c672df0 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf @@ -0,0 +1,58 @@ + +# Get the details of the node pool's resource group created by AKS +data "azurerm_resource_group" "noderg" { + for_each = var.aks_clusters + name = local.remote.aks_clusters[each.value.lz_key][each.value.key].node_resource_group +} + +# +# Set permissions to the kubelet and cluster identity +# +resource "azurerm_role_assignment" "kubelet_noderg_miop" { + for_each = var.aks_clusters + + scope = data.azurerm_resource_group.noderg[each.key].id + role_definition_name = "Managed Identity Operator" + principal_id = local.remote.aks_clusters[each.value.lz_key][each.value.key].kubelet_identity[0].object_id +} + +resource "azurerm_role_assignment" "kubelet_noderg_vmcontrib" { + for_each = var.aks_clusters + + scope = data.azurerm_resource_group.noderg[each.key].id + role_definition_name = "Virtual Machine Contributor" + principal_id = local.remote.aks_clusters[each.value.lz_key][each.value.key].kubelet_identity[0].object_id +} + + +resource "azurerm_role_assignment" "kubelet_vnet_networkcontrib" { + for_each = toset(var.vnets[var.aks_cluster_vnet_key].subnet_keys) + + scope = local.remote.vnets[var.vnets[var.aks_cluster_vnet_key].lz_key][var.vnets[var.aks_cluster_vnet_key].key].subnets[each.value].id + role_definition_name = "Network Contributor" + principal_id = local.remote.aks_clusters[var.aks_clusters[var.aks_cluster_key].lz_key][var.aks_cluster_key].identity[0].principal_id +} + +resource "azurerm_role_assignment" "kubelet_user_msi" { + for_each = local.msi_to_grant_permissions + + scope = each.value.id + role_definition_name = "Managed Identity Operator" + principal_id = local.remote.aks_clusters[var.aks_clusters[var.aks_cluster_key].lz_key][var.aks_cluster_key].kubelet_identity[0].object_id +} + +locals { + msi_to_grant_permissions = { + for msi in flatten( + [ + for key, value in var.managed_identities : [ + for msi_key in value.msi_keys : { + key = key + msi_key = msi_key + id = local.remote.managed_identities[value.lz_key][msi_key].id + } + ] + ] + ) : format("%s-%s", msi.key, msi.msi_key) => msi + } +} diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/backend.azurerm b/landingzones/caf_solution/add-ons/aks-secure-baseline/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks-secure-baseline/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml b/landingzones/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml new file mode 100644 index 000000000..373d8b437 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - https://raw.githubusercontent.com/Azure/caf-terraform-landingzones-starter/starter/enterprise_scale/construction_sets/aks/online/aks_secure_baseline/cluster-baseline-settings/flux.yaml \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf new file mode 100644 index 000000000..d458c18a1 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf @@ -0,0 +1,54 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = try(each.value.container, local.landingzone[try(each.value.level, "current")].container_name) + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics + + remote = { + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + global_settings = local.global_settings + diagnostics = local.diagnostics + + + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) + } + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) + } + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) + } + } + +} diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/main.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/main.tf new file mode 100644 index 000000000..ac7602c81 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks-secure-baseline/main.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.51.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.0.2" + } + kustomization = { + source = "kbst/kustomization" + version = ">= 0.4.0" + } + } + required_version = ">= 0.13" +} diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/providers.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/providers.tf new file mode 100644 index 000000000..be2b3abb1 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks-secure-baseline/providers.tf @@ -0,0 +1,32 @@ + +provider "azurerm" { + features { + } +} + +provider "kubernetes" { + host = local.k8sconfigs[var.aks_cluster_key].host + username = local.k8sconfigs[var.aks_cluster_key].username + password = local.k8sconfigs[var.aks_cluster_key].password + client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate + client_key = local.k8sconfigs[var.aks_cluster_key].client_key + cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate +} + +provider "kustomization" { + kubeconfig_raw = local.k8sconfigs[var.aks_cluster_key].kube_admin_config_raw +} + +locals { + k8sconfigs = { + for key, value in var.aks_clusters : key => { + kube_admin_config_raw = local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config_raw + host = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.host : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.host + username = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.username : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.username + password = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.password : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.password + client_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_certificate) + client_key = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_key) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_key) + cluster_ca_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.cluster_ca_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.cluster_ca_certificate) + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf new file mode 100644 index 000000000..f2208c9bd --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf @@ -0,0 +1,22 @@ +# Process the Kustomization in the current folder +data "kustomization_build" "flux" { + path = "." +} + +resource "kustomization_resource" "cluster_secure_baseline_p0" { + # depends_on = [kubernetes_namespace.cluster_secure_baseline] + for_each = data.kustomization_build.flux.ids_prio[0] + manifest = data.kustomization_build.flux.manifests[each.value] +} + +resource "kustomization_resource" "cluster_secure_baseline_p1" { + depends_on = [kustomization_resource.cluster_secure_baseline_p0] + for_each = data.kustomization_build.flux.ids_prio[1] + manifest = data.kustomization_build.flux.manifests[each.value] +} + +resource "kustomization_resource" "cluster_secure_baseline_p2" { + depends_on = [kustomization_resource.cluster_secure_baseline_p1] + for_each = data.kustomization_build.flux.ids_prio[2] + manifest = data.kustomization_build.flux.manifests[each.value] +} diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/variables.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/variables.tf new file mode 100644 index 000000000..971033737 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks-secure-baseline/variables.tf @@ -0,0 +1,36 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "landingzone" {} +variable "rover_version" { + default = null +} +variable "tags" { + default = {} +} + +###### + +variable "aks_cluster_key" { + description = "AKS cluster key to deploy the Gitlab Helm charts. The key must be defined in the variable aks_clusters" +} +variable "aks_cluster_vnet_key" { + +} +variable "aks_clusters" {} +variable "vnets" {} +variable "managed_identities" { + description = "Map of the user managed identities." +} + +variable "aad_pod_identity" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/app/main.tf b/landingzones/caf_solution/add-ons/aks_applications/app/main.tf new file mode 100644 index 000000000..1191eedce --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks_applications/app/main.tf @@ -0,0 +1,7 @@ +provider "kubernetes" { + alias = "k8s" +} + +provider "helm" { + alias = "helm" +} diff --git a/landingzones/caf_solution/add-ons/aks_applications/app/module.tf b/landingzones/caf_solution/add-ons/aks_applications/app/module.tf new file mode 100644 index 000000000..2d4288893 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks_applications/app/module.tf @@ -0,0 +1,48 @@ +resource "kubernetes_namespace" "namespaces" { + for_each = var.namespaces + metadata { + annotations = try(each.value.annotations, null) + labels = try(each.value.labels, null) + name = each.value.name + } + + provider = kubernetes.k8s +} + +# https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release +resource "helm_release" "charts" { + for_each = var.helm_charts + + name = each.value.name + repository = each.value.repository + chart = each.value.chart + + namespace = each.value.namespace + wait = try(each.value.wait, true) + timeout = try(each.value.timeout, 900) + skip_crds = try(each.value.skip_crds, false) + create_namespace = try(each.value.create_namespace, false) + + dynamic "set" { + for_each = try(each.value.sets, {}) + content { + name = set.key + value = set.value + } + } + + dynamic "set_sensitive" { + for_each = try(each.value.sets_sensitive, {}) + content { + name = set_sensitive.key + value = set_sensitive.value + } + } + + provider = helm.helm + + depends_on = [kubernetes_namespace.namespaces] + # values = [ + # "${file("values.yaml")}" + # ] +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/app/output.tf b/landingzones/caf_solution/add-ons/aks_applications/app/output.tf new file mode 100644 index 000000000..e69de29bb diff --git a/landingzones/caf_solution/add-ons/aks_applications/app/variables.tf b/landingzones/caf_solution/add-ons/aks_applications/app/variables.tf new file mode 100644 index 000000000..4a0225192 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks_applications/app/variables.tf @@ -0,0 +1,5 @@ +variable "cluster" {} + +variable "namespaces" {} + +variable "helm_charts" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/applications.tf b/landingzones/caf_solution/add-ons/aks_applications/applications.tf new file mode 100644 index 000000000..b1f674491 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks_applications/applications.tf @@ -0,0 +1,27 @@ +module "app1" { + source = "./app" + for_each = try(local.clusters[var.cluster_re1_key], null) != null ? { (var.cluster_re1_key) = local.clusters[var.cluster_re1_key] } : {} + + cluster = each.value + namespaces = var.namespaces + helm_charts = var.helm_charts + + providers = { + kubernetes.k8s = kubernetes.k8s1 + helm.helm = helm.helm1 + } +} + +module "app2" { + source = "./app" + for_each = try(local.clusters[var.cluster_re2_key], null) != null ? { (var.cluster_re2_key) = local.clusters[var.cluster_re2_key] } : {} + + cluster = each.value + namespaces = var.namespaces + helm_charts = var.helm_charts + + providers = { + kubernetes.k8s = kubernetes.k8s2 + helm.helm = helm.helm2 + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/backend.azurerm b/landingzones/caf_solution/add-ons/aks_applications/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks_applications/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf b/landingzones/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf new file mode 100644 index 000000000..cf16e86c6 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf @@ -0,0 +1,54 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + remote = { + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aks_clusters[key], {})) + } + } + + clusters = local.remote.aks_clusters[var.landingzone.global_settings_key] + k8sconfigs = { for key, value in values(local.clusters) : key => { + host = value.enable_rbac ? value.kube_admin_config.0.host : value.kube_config.0.host + username = value.enable_rbac ? value.kube_admin_config.0.username : value.kube_config.0.username + password = value.enable_rbac ? value.kube_admin_config.0.password : value.kube_config.0.password + client_certificate = value.enable_rbac ? base64decode(value.kube_admin_config.0.client_certificate) : base64decode(value.kube_config.0.client_certificate) + client_key = value.enable_rbac ? base64decode(value.kube_admin_config.0.client_key) : base64decode(value.kube_config.0.client_key) + cluster_ca_certificate = value.enable_rbac ? base64decode(value.kube_admin_config.0.cluster_ca_certificate) : base64decode(value.kube_config.0.cluster_ca_certificate) + } + } + +} diff --git a/landingzones/caf_solution/add-ons/aks_applications/main.tf b/landingzones/caf_solution/add-ons/aks_applications/main.tf new file mode 100644 index 000000000..2222bc4d2 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks_applications/main.tf @@ -0,0 +1,75 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.43" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 1.13.2" + } + helm = { + source = "hashicorp/helm" + version = "~> 1.3.0" + } + } + required_version = ">= 0.13" +} + + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + + +provider "kubernetes" { + load_config_file = false + host = try(local.k8sconfigs[0].host, null) + username = try(local.k8sconfigs[0].username, null) + password = try(local.k8sconfigs[0].password, null) + client_certificate = try(local.k8sconfigs[0].client_certificate, null) + client_key = try(local.k8sconfigs[0].client_key, null) + cluster_ca_certificate = try(local.k8sconfigs[0].cluster_ca_certificate, null) + alias = "k8s1" +} + +provider "helm" { + kubernetes { + load_config_file = false + host = try(local.k8sconfigs[0].host, null) + username = try(local.k8sconfigs[0].username, null) + password = try(local.k8sconfigs[0].password, null) + client_certificate = try(local.k8sconfigs[0].client_certificate, null) + client_key = try(local.k8sconfigs[0].client_key, null) + cluster_ca_certificate = try(local.k8sconfigs[0].cluster_ca_certificate, null) + } + alias = "helm1" +} + +provider "kubernetes" { + load_config_file = false + host = try(local.k8sconfigs[1].host, null) + username = try(local.k8sconfigs[1].username, null) + password = try(local.k8sconfigs[1].password, null) + client_certificate = try(local.k8sconfigs[1].client_certificate, null) + client_key = try(local.k8sconfigs[1].client_key, null) + cluster_ca_certificate = try(local.k8sconfigs[1].cluster_ca_certificate, null) + alias = "k8s2" +} + +provider "helm" { + kubernetes { + load_config_file = false + host = try(local.k8sconfigs[1].host, null) + username = try(local.k8sconfigs[1].username, null) + password = try(local.k8sconfigs[1].password, null) + client_certificate = try(local.k8sconfigs[1].client_certificate, null) + client_key = try(local.k8sconfigs[1].client_key, null) + cluster_ca_certificate = try(local.k8sconfigs[1].cluster_ca_certificate, null) + } + alias = "helm2" +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/output.tf b/landingzones/caf_solution/add-ons/aks_applications/output.tf new file mode 100644 index 000000000..e69de29bb diff --git a/landingzones/caf_solution/add-ons/aks_applications/variables.tf b/landingzones/caf_solution/add-ons/aks_applications/variables.tf new file mode 100644 index 000000000..7ad77ea93 --- /dev/null +++ b/landingzones/caf_solution/add-ons/aks_applications/variables.tf @@ -0,0 +1,36 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_resource_group_name" {} +# variable tfstate_key {} + +variable "global_settings" { + default = {} +} + +# variable tenant_id {} +variable "landingzone" {} + +variable "namespaces" {} + +variable "tags" { + default = null + type = map(any) +} + +variable "helm_charts" {} + +variable "rover_version" { + default = null +} + +variable "cluster_re1_key" { + default = null +} +variable "cluster_re2_key" { + default = null +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo.tf new file mode 100644 index 000000000..9d2b42c02 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/azdo.tf @@ -0,0 +1,15 @@ +# The PAT token must be provisioned in a different deployment +provider "azuredevops" { + org_service_url = var.azure_devops.url + personal_access_token = data.azurerm_key_vault_secret.pat.value +} + +data "azurerm_key_vault_secret" "pat" { + name = var.azure_devops.pats["admin"].secret_name + key_vault_id = local.remote.keyvaults[var.azure_devops.pats["admin"].lz_key][var.azure_devops.pats["admin"].keyvault_key].id + +} + +data "azuredevops_project" "project" { + name = var.azure_devops.project +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf new file mode 100644 index 000000000..7832ba6e9 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf @@ -0,0 +1,52 @@ + +locals { + organization_agent_pools = try(var.azure_devops.organization_agent_pools, {}) + project_agent_pools = try(var.azure_devops.project_agent_pools, {}) +} + + +## Agent pools +## Those pools are created in the organization, not the project +resource "azuredevops_agent_pool" "pool" { + for_each = try(var.azure_devops.organization_agent_pools, {}) + + name = each.value.name + auto_provision = lookup(each.value, "auto_provision", false) +} + +# +# add the agent pools into the project +# + +data "azuredevops_agent_pool" "pool" { + depends_on = [azuredevops_agent_pool.pool] + for_each = try(var.azure_devops.project_agent_pools, {}) + + name = each.value.name +} + +resource "azuredevops_agent_queue" "agent_queue" { + for_each = data.azuredevops_agent_pool.pool + + project_id = data.azuredevops_project.project.id + agent_pool_id = each.value.id + + lifecycle { + ignore_changes = [ + agent_pool_id + ] + } +} + +# +# Grant acccess to queue to all pipelines in the project +# + +resource "azuredevops_resource_authorization" "queue" { + for_each = data.azuredevops_agent_pool.pool + + project_id = data.azuredevops_project.project.id + resource_id = azuredevops_agent_queue.agent_queue[each.key].id + type = "queue" + authorized = true +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo_pipelines.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo_pipelines.tf new file mode 100644 index 000000000..6fe4fdcbb --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/azdo_pipelines.tf @@ -0,0 +1,43 @@ +data "azuredevops_git_repositories" "repos" { + project_id = data.azuredevops_project.project.id +} + + +locals { + repositories = zipmap(tolist(data.azuredevops_git_repositories.repos.repositories.*.name), tolist(data.azuredevops_git_repositories.repos.repositories)) +} + +resource "azuredevops_build_definition" "build_definition" { + + for_each = try(var.azure_devops.pipelines, {}) + project_id = data.azuredevops_project.project.id + name = each.value.name + path = each.value.folder + + variable_groups = lookup(each.value, "variable_group_keys", null) == null ? null : [ + for key in each.value.variable_group_keys : + azuredevops_variable_group.variable_group[key].id + ] + + repository { + repo_id = local.repositories[each.value.git_repo_name].id + repo_type = each.value.repo_type + yml_path = each.value.yaml + branch_name = lookup(each.value, "branch_name", null) + # service_connection_id = lookup(each.value, "repo_type", null) == "github" ? null : azuredevops_serviceendpoint_azurerm.github[each.value.service_connection_key].id + } + + ci_trigger { + use_yaml = true + } + + dynamic "variable" { + for_each = try(each.value.variables, {}) + + content { + name = variable.key + value = variable.value + } + } + +} diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf new file mode 100644 index 000000000..760919a25 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf @@ -0,0 +1,36 @@ + +data "azurerm_key_vault_secret" "client_secret" { + depends_on = [module.caf] + for_each = try(var.azure_devops.service_endpoints, {}) + + name = format("%s-client-secret", local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].secret_name_client_secret) + key_vault_id = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].id +} + +resource "azuredevops_serviceendpoint_azurerm" "azure" { + depends_on = [module.caf] + for_each = try(var.azure_devops.service_endpoints, {}) + + project_id = data.azuredevops_project.project.id + service_endpoint_name = each.value.endpoint_name + credentials { + serviceprincipalid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].azuread_application.application_id + serviceprincipalkey = data.azurerm_key_vault_secret.client_secret[each.key].value + } + azurerm_spn_tenantid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].tenant_id + azurerm_subscription_id = each.value.subscription_id + azurerm_subscription_name = each.value.subscription_name +} + +# +# Grant acccess to service endpoint to all pipelines in the project +# + +resource "azuredevops_resource_authorization" "endpoint" { + for_each = azuredevops_serviceendpoint_azurerm.azure + + project_id = data.azuredevops_project.project.id + resource_id = each.value.id + type = "endpoint" + authorized = true +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf new file mode 100644 index 000000000..7cd1ed1c2 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf @@ -0,0 +1,39 @@ +# +# permissions required: +# - vso.variablegroups_manage (create) +# + vso.buid (update) +# + vso.build_execute (destroy) +# +resource "azuredevops_variable_group" "variable_group" { + for_each = try(var.azure_devops.variable_groups, {}) + + project_id = data.azuredevops_project.project.id + name = each.value.name + description = try(each.value.description, null) + allow_access = try(each.value.allow_access, false) + + dynamic "key_vault" { + for_each = lookup(each.value, "keyvault", null) == null ? [] : [1] + + content { + name = try(each.value.keyvault.lz_key, null) == null ? local.combined.keyvaults[var.landingzone.key][each.value.keyvault.keyvault_key].name : local.combined.keyvaults[each.value.keyvault.lz_key][each.value.keyvault.keyvault_key].name + service_endpoint_id = azuredevops_serviceendpoint_azurerm.azure[each.value.keyvault.serviceendpoint_key].id + } + } + + dynamic "variable" { + for_each = { + for key, variable in each.value.variables : key => { + name = key == "name" ? variable : key + value = key == "name" ? null : variable + } + } + + content { + # When used with Keyvault, the name must be the keyvault secret name and value must not be set + name = variable.value.name + value = variable.value.value + } + } + +} diff --git a/landingzones/caf_solution/add-ons/azure_devops/backend.azurerm b/landingzones/caf_solution/add-ons/azure_devops/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/documentation/images/pat_token.png b/landingzones/caf_solution/add-ons/azure_devops/documentation/images/pat_token.png new file mode 100644 index 0000000000000000000000000000000000000000..84fc549c5baa26167b2a975c5ae917e5a46b162e GIT binary patch literal 78143 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 literal 0 HcmV?d00001 diff --git a/landingzones/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf b/landingzones/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf new file mode 100644 index 000000000..4295ebf43 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf @@ -0,0 +1,76 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + diagnostics = { + diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics + } + + + combined = { + aad_apps = merge(local.remote.aad_apps, map(var.landingzone.key, module.caf.aad_apps)) + azuread_groups = merge(local.remote.azuread_groups, map(var.landingzone.key, module.caf.azuread_groups)) + keyvaults = merge(local.remote.keyvaults, map(var.landingzone.key, module.caf.keyvaults)) + managed_identities = merge(local.remote.managed_identities, map(var.landingzone.key, module.caf.managed_identities)) + } + + remote = { + aad_apps = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {})) + } + + azuread_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) + } + + keyvaults = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) + } + + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) + } + + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) + } + } + + +} diff --git a/landingzones/caf_solution/add-ons/azure_devops/main.tf b/landingzones/caf_solution/add-ons/azure_devops/main.tf new file mode 100644 index 000000000..3cf3eb96f --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/main.tf @@ -0,0 +1,69 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.43" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.0.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + azuredevops = { + source = "microsoft/azuredevops" + version = "~> 0.1.0" + } + tls = { + source = "hashicorp/tls" + version = "~> 2.2.0" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "~>1.1.0" + } + } + required_version = ">= 0.13" +} + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + + +locals { + + + tfstates = merge( + map(var.landingzone.backend_type, + map( + "storage_account_name", var.tfstate_storage_account_name, + "container_name", var.tfstate_container_name, + "resource_group_name", var.tfstate_resource_group_name, + "key", var.tfstate_key, + "level", var.landingzone.level, + "tenant_id", var.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + , + data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates + ) + +} diff --git a/landingzones/caf_solution/add-ons/azure_devops/output.tf b/landingzones/caf_solution/add-ons/azure_devops/output.tf new file mode 100644 index 000000000..a46105168 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/output.tf @@ -0,0 +1,6 @@ +output "keyvaults" { + value = map( + var.landingzone.key, module.caf.keyvaults + ) + sensitive = true +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/readme.md b/landingzones/caf_solution/add-ons/azure_devops/readme.md new file mode 100644 index 000000000..1ebbb675f --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/readme.md @@ -0,0 +1,60 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Azure Devops add-on + +The Azure Devops add-ons allow you to setup you Azure Devops environment as a platform to automate all your subsequent landing zone deployment from level 0 until level 4 through Azure pipelines with self hosted agents. + +* Azure Devops: + - Agent Pools (Organization and Project Level) + - Service Endpoint + - Variables and Variable Groups + - Pipelines + +* Azure (Connection with Azure Devops): + - Azure AD Application + - Custom Role + - Keyvault and access policies for Azure AD App + +Azure Devops add-on landing zone operates at **level 0** + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +## Dependencies + +Landing zone: +* CAF Launchpad (Scenario 200 or above) + +Azure Devops (example): +* Organization: https://dev.azure.com/azure-terraform +* Project : contoso_demo (https://dev.azure.com/azure-terraform/contoso_demo) +* Repo : caf-configuration (https://dev.azure.com/azure-terraform/contoso_demo/_git/caf-configuration) + - In order for pipeline to work properly, YAML file should be in this repo and referred accordingly under pipeline section in azure_devops.tfvars + - sample yaml attached [here](./scenario/200-contoso_demo/pipeline/rover.yaml). + +Azure: +* PAT Token : PAT Token should be updated in keyvault secret that deployed by launchpad LZ as below + +![](./documentation/images/pat_token.png) + +## Deployment + +```bash +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops \ + -tfstate azure_devops-contoso_demo.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo \ + -parallelism 30 \ + -level level0 \ + -env sandpit \ + -a apply + + +# If the tfstates are stored in a different subscription you need to execute the following command +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops \ + -tfstate_subscription_id \ + -tfstate azure_devops-contoso_demo.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo \ + -parallelism 30 \ + -level level0 \ + -env sandpit \ + -a apply +``` + +We are planning to release more examples on how to deploy the Azure Devops Agents. diff --git a/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars b/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars new file mode 100644 index 000000000..bf0bd6c1f --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars @@ -0,0 +1,232 @@ + + +azure_devops = { + + url = "https://dev.azure.com/azure-terraform/" + project = "contoso_demo" + + # PAT Token should be updated manually to the keyvault after running launchpad + pats = { + admin = { + secret_name = "azdo-pat-admin" + lz_key = "launchpad" + keyvault_key = "secrets" + } + } + + organization_agent_pools = { + level0 = { + name = "caf-sandpit-level0" + auto_provision = false # When set to false the agent pool is not populated automatically into the devops projects (recommended) + } + level1 = { + name = "caf-sandpit-level1" + auto_provision = false + } + level2 = { + name = "caf-sandpit-level2" + auto_provision = false + } + level3 = { + name = "caf-sandpit-level3" + auto_provision = false + } + level4 = { + name = "caf-sandpit-level4" + auto_provision = false + } + } + + project_agent_pools = { + level0 = { + name = "caf-sandpit-level0" + } + level1 = { + name = "caf-sandpit-level1" + } + level2 = { + name = "caf-sandpit-level2" + } + level3 = { + name = "caf-sandpit-level3" + } + level4 = { + name = "caf-sandpit-level4" + } + } + + service_endpoints = { + contoso_demo = { + endpoint_name = "terraformdev (terraformdev.onmicrosoft.com) - contoso_demo" + subscription_name = "ase-landingzone" + subscription_id = "1d53e782-9f46-4720-b6b3-cff29106e9f6" + aad_app_key = "contoso_demo" + secret_keyvault_key = "devops" + } + } + + variable_groups = { + global = { + name = "release-global" # changing that name requires to change it in the devops agents yaml variables group + allow_access = true + variables = { + HOME_FOLDER_USER = "vsts_azpcontainer" + ROVER_IMAGE = "aztfmod/rover:2010.2808" + TF_CLI_ARGS = "'-no-color'" + TF_CLI_ARGS_init = "" + TF_CLI_ARGS_plan = "'-input=false'" + TF_VAR_ARGS_destroy = "'-auto-approve -refresh=false'" + ENVIRONMENT = "sandpit" + LANDINGZONE_BRANCH = "2010.0.0" + } + } + + level0 = { + name = "release-level0" + allow_access = true + variables = { + TF_VAR_pipeline_level = "level0" + ARM_USE_MSI = "true" + AGENT_POOL = "caf-sandpit-level0" + } + } + + level0_kv = { + name = "release-level0-msi" + allow_access = true + keyvault = { + lz_key = "launchpad" + keyvault_key = "level0" + serviceendpoint_key = "contoso_demo" + } + variables = { + name = "msi-resource-id" + } + } + + level1 = { + name = "release-level1" + allow_access = true + variables = { + TF_VAR_pipeline_level = "level1" + ARM_USE_MSI = "true" + AGENT_POOL = "caf-sandpit-level1" + } + } + + level1_kv = { + name = "release-level1-msi" + allow_access = true + keyvault = { + lz_key = "launchpad" + keyvault_key = "level1" + serviceendpoint_key = "contoso_demo" + } + variables = { + name = "msi-resource-id" + } + } + + level2 = { + name = "release-level2" + allow_access = true + variables = { + TF_VAR_pipeline_level = "level2" + ARM_USE_MSI = "true" + AGENT_POOL = "caf-sandpit-level2" + } + } + + level2_kv = { + name = "release-level2-msi" + allow_access = true + keyvault = { + lz_key = "launchpad" + keyvault_key = "level2" + serviceendpoint_key = "contoso_demo" + } + variables = { + name = "msi-resource-id" + } + } + + level3 = { + name = "release-level3" + allow_access = true + variables = { + TF_VAR_pipeline_level = "level3" + ARM_USE_MSI = "true" + AGENT_POOL = "caf-sandpit-level3" + } + } + + level3_kv = { + name = "release-level3-msi" + allow_access = true + keyvault = { + lz_key = "launchpad" + keyvault_key = "level3" + serviceendpoint_key = "contoso_demo" + } + variables = { + name = "msi-resource-id" + } + } + } + + pipelines = { + + # + # Agent pools + # + + devops_agent_level1_plan = { + name = "devops_agent_level1_plan" + folder = "\\configuration\\level1" + yaml = "configuration/pipeline/rover.yaml" + repo_type = "TfsGit" + git_repo_name = "caf-configuration" + variables = { + landingZoneName = "azdo-agent-level1", + terraformAction = "plan", + tfstateName = "azdo-agent-level1.tfstate" + configPath = "/configuration/level1/azuredevops/agent" + landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" + level = "level1" + } + variable_group_keys = ["global", "level0", "level0_kv"] + } + devops_agent_level1_apply = { + name = "devops_agent_level1_apply" + folder = "\\configuration\\level1" + yaml = "configuration/pipeline/rover.yaml" + repo_type = "TfsGit" + git_repo_name = "caf-configuration" + variables = { + landingZoneName = "azdo-agent-level1", + terraformAction = "apply", + tfstateName = "azdo-agent-level1.tfstate" + configPath = "/configuration/level1/azuredevops/agent" + landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" + level = "level1" + } + variable_group_keys = ["global", "level0", "level0_kv"] + } + devops_agent_level1_destroy = { + name = "devops_agent_level1_destroy" + folder = "\\configuration\\level1" + yaml = "configuration/pipeline/rover.yaml" + repo_type = "TfsGit" + git_repo_name = "caf-configuration" + variables = { + landingZoneName = "azdo-agent-level1", + terraformAction = "destroy", + tfstateName = "azdo-agent-level1.tfstate" + configPath = "/configuration/level1/azuredevops/agent" + landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" + level = "level1" + } + variable_group_keys = ["global", "level0", "level0_kv"] + } + } +} diff --git a/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars b/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars new file mode 100644 index 000000000..e4d8208f3 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars @@ -0,0 +1,123 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level0" + key = "azdo-contoso_demo" + tfstates = { + launchpad = { + level = "current" + tfstate = "caf_launchpad.tfstate" + } + } +} + +resource_groups = { + rg1 = { + name = "devops-agents-security" + } +} + + +keyvaults = { + devops = { + name = "devops" + resource_group_key = "rg1" + sku_name = "standard" + + creation_policies = { + keyvault_level0_rw = { + # Reference a key to an azure ad group + lz_key = "launchpad" + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} + +keyvault_access_policies_azuread_apps = { + level0 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } + level1 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } + level2 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } + level3 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } + level4 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } +} + + +azuread_apps = { + + contoso_demo = { + useprefix = true + application_name = "caf-level4-contoso_demo" + password_expire_in_days = 60 + tenant_name = "terraformdev.onmicrosoft.com" + reply_urls = ["https://localhost"] + keyvaults = { + devops = { + secret_prefix = "aadapp-caf-level4-azdo-contoso_demo" + } + } + } + +} + +custom_role_definitions = { + + caf-azdo-to-azure-subscription = { + name = "caf-azure-devops-azure-app-service-improvement-program-TO-azure-subscription" + useprefix = true + description = "CAF Custom role for service principal in Azure Devops to access resources" + permissions = { + actions = [ + "Microsoft.Resources/subscriptions/read", + "Microsoft.KeyVault/vaults/read" + ] + } + } + +} + + +role_mapping = { + custom_role_mapping = { + subscriptions = { + logged_in_subscription = { + "caf-azdo-to-azure-subscription" = { + azuread_apps = { + keys = ["contoso_demo"] + } + } + } + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml b/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml new file mode 100644 index 000000000..156fb9983 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml @@ -0,0 +1,70 @@ +parameters: + - name: timeoutInMinutes + displayName: 'Timeout in minutes' + type: number + default: 60 + + variables: + - group: release-global + + resources: + containers: + - container: rover + image: $(ROVER_IMAGE) + options: --user 0:0 -e TF_PLUGIN_CACHE_DIR="/home/$(HOME_FOLDER_USER)/plugin-cache" -e TF_DATA_DIR="/home/$(HOME_FOLDER_USER)" + + trigger: none + + jobs: + - job: CAF_Rover + + displayName: Azure Landing Zone + + pool: $(AGENT_POOL) + + continueOnError: false + + workspace: + clean: all + + container: rover + + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + + steps: + - checkout: self + + - bash: | + git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null + + az login --identity -u $(msi-resource-id) + + /tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \ + -tfstate $(tfstateName) \ + -var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \ + -parallelism=30 \ + -level $(level) \ + -a $(terraformAction) \ + -env $(ENVIRONMENT) + + condition: ne(variables['terraformAction'], 'destroy') + failOnStderr: true + displayName: 'Terraform $(terraformAction)' + + - bash: | + git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null + + az login --identity -u $(msi-resource-id) + + /tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \ + -tfstate $(tfstateName) \ + -var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \ + -parallelism=30 \ + -level $(level) \ + -a $(terraformAction) \ + -auto-approve \ + -env $(ENVIRONMENT) + + condition: eq(variables['terraformAction'], 'destroy') + failOnStderr: true + displayName: 'Terraform destroy' diff --git a/landingzones/caf_solution/add-ons/azure_devops/solution.tf b/landingzones/caf_solution/add-ons/azure_devops/solution.tf new file mode 100644 index 000000000..718e923ba --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/solution.tf @@ -0,0 +1,36 @@ +module "caf" { + source = "aztfmod/caf/azurerm" + version = "~>5.1.0" + + current_landingzone_key = var.landingzone.key + tenant_id = var.tenant_id + tfstates = local.tfstates + tags = local.tags + global_settings = local.global_settings + diagnostics = local.diagnostics + diagnostic_storage_accounts = var.diagnostic_storage_accounts + logged_user_objectId = var.logged_user_objectId + logged_aad_app_objectId = var.logged_aad_app_objectId + resource_groups = var.resource_groups + storage_accounts = var.storage_accounts + azuread_groups = var.azuread_groups + keyvaults = var.keyvaults + keyvault_access_policies = var.keyvault_access_policies + keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps + role_mapping = var.role_mapping + custom_role_definitions = var.custom_role_definitions + azuread_apps = var.azuread_apps + compute = { + virtual_machines = var.virtual_machines + } + storage = { + storage_account_blobs = var.storage_account_blobs + } + + remote_objects = { + keyvaults = local.remote.keyvaults + vnets = local.remote.vnets + managed_identities = local.remote.managed_identities + azuread_groups = local.remote.azuread_groups + } +} diff --git a/landingzones/caf_solution/add-ons/azure_devops/variables.tf b/landingzones/caf_solution/add-ons/azure_devops/variables.tf new file mode 100644 index 000000000..87dcc831a --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops/variables.tf @@ -0,0 +1,102 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} + +variable "global_settings" { + default = {} +} +variable "tenant_id" {} +variable "landingzone" { +} +variable "rover_version" { + default = null +} + +variable "logged_user_objectId" { + default = null +} +variable "logged_aad_app_objectId" { + default = null +} +variable "tags" { + default = null +} +variable "app_service_environments" { + default = {} +} +variable "app_service_plans" { + default = {} +} +variable "app_services" { + default = {} +} +variable "diagnostics_definition" { + default = {} +} +variable "resource_groups" { + default = {} +} +variable "network_security_group_definition" { + default = {} +} +variable "vnets" { + default = {} +} +variable "azurerm_redis_caches" { + default = {} +} +variable "mssql_servers" { + default = {} +} +variable "storage_accounts" { + default = {} +} +variable "storage_account_blobs" { + default = {} +} +variable "azuread_groups" { + default = {} +} +variable "keyvaults" { + default = {} +} +variable "keyvault_access_policies" { + default = {} +} +variable "keyvault_access_policies_azuread_apps" { + default = {} +} +variable "virtual_machines" { + default = {} +} +variable "diagnostic_storage_accounts" { + default = {} +} +variable "virtual_machine_extension_scripts" { + default = {} +} +variable "azure_devops" { + default = {} +} +variable "role_mapping" { + default = {} +} +variable "custom_role_definitions" { + default = {} +} +variable "azuread_apps" { + default = {} +} +variable "dynamic_keyvault_secrets" { + default = {} +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/backend.azurerm b/landingzones/caf_solution/add-ons/azure_devops_agent/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf new file mode 100644 index 000000000..63f0367a4 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf @@ -0,0 +1,11 @@ + +module "dynamic_keyvault_secrets" { + source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" + version = "~>5.1.0" + + for_each = try(var.dynamic_keyvault_secrets, {}) + + settings = each.value + keyvault = module.caf.keyvaults[each.key] + objects = module.caf +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf new file mode 100644 index 000000000..5372db558 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf @@ -0,0 +1,44 @@ + +resource "azurerm_virtual_machine_extension" "devops_selfhosted_agent" { + for_each = { + for key, value in var.extensions : key => value + if key == "devops_selfhosted_agent" + } + + name = "install_azure_devops_agent" + + virtual_machine_id = var.virtual_machine_id + publisher = "Microsoft.Azure.Extensions" + type = "CustomScript" + type_handler_version = "2.1" + + #timestamp: use this field only to trigger a re-run of the script by changing value of this field. + # Any integer value is acceptable; it must only be different than the previous value. + settings = jsonencode( + { + "timestamp" : each.value.version, + "fileUris" : concat(local.devops_selfhosted_agent.file_uris, local.devops_selfhosted_agent.storage_account_blobs_urls), + + } + ) + protected_settings = jsonencode( + { + "commandToExecute" : format("bash %s '%s' '%s' '%s' '%s' '%s' '%s' '%s'", var.extensions[each.key].agent_init_script, var.settings[each.key].azure_devops.url, var.settings[each.key].agent_pat, var.settings[each.key].azure_devops.agent_pool.name, var.settings[each.key].azure_devops.agent_pool.agent_name_prefix, var.settings[each.key].azure_devops.agent_pool.num_agents, var.settings[each.key].admin_username, var.settings[each.key].azure_devops.rover_version) + } + ) + +} + +locals { + devops_selfhosted_agent = { + file_uris = flatten( + [ + for file_uris_key, file in try(var.extensions.devops_selfhosted_agent.fileUris, {}) : [ + for file_uri_key in file.storage_blob_keys : var.settings.devops_selfhosted_agent.storage_accounts[file.storage_account_key].containers[file.container_key].blobs[file_uri_key].url + ] + ] + ) + + storage_account_blobs_urls = try(var.settings.devops_selfhosted_agent.storage_account_blobs_urls, []) + } +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf new file mode 100644 index 000000000..9b8d2f8c3 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf @@ -0,0 +1,3 @@ +variable "virtual_machine_id" {} +variable "extensions" {} +variable "settings" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf new file mode 100644 index 000000000..fcc2fc189 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf @@ -0,0 +1,74 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + diagnostics = { + diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics + } + + + combined = { + aad_apps = merge(local.remote.aad_apps, map(var.landingzone.key, module.caf.aad_apps)) + azuread_groups = merge(local.remote.azuread_groups, map(var.landingzone.key, module.caf.azuread_groups)) + keyvaults = merge(local.remote.keyvaults, map(var.landingzone.key, module.caf.keyvaults)) + managed_identities = merge(local.remote.managed_identities, map(var.landingzone.key, module.caf.managed_identities)) + } + + remote = { + aad_apps = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {})) + } + + azuread_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) + } + + keyvaults = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) + } + + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) + } + + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) + } + } +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/main.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/main.tf new file mode 100644 index 000000000..67d570897 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/main.tf @@ -0,0 +1,69 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.43" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.0.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + azuredevops = { + source = "microsoft/azuredevops" + version = "~> 0.1.1" + } + tls = { + source = "hashicorp/tls" + version = "~> 2.2.0" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "~>1.1.0" + } + } + required_version = ">= 0.13" +} + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + + +locals { + + + tfstates = merge( + map(var.landingzone.key, + map( + "storage_account_name", var.tfstate_storage_account_name, + "container_name", var.tfstate_container_name, + "resource_group_name", var.tfstate_resource_group_name, + "key", var.tfstate_key, + "level", var.landingzone.level, + "tenant_id", var.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + , + data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates + ) + +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/output.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/output.tf new file mode 100644 index 000000000..e19cb88aa --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/output.tf @@ -0,0 +1,34 @@ +output "managed_identities" { + value = local.combined.managed_identities + sensitive = false +} + +output "azuread_groups" { + value = local.combined.azuread_groups + sensitive = true +} + +output "keyvaults" { + value = local.combined.keyvaults + sensitive = false +} + +output "vnets" { + value = local.remote.vnets + sensitive = false +} + +output "global_settings" { + value = local.global_settings + sensitive = true +} + +output "diagnostics" { + value = local.diagnostics + sensitive = true +} + +output "tfstates" { + value = local.tfstates + sensitive = true +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/readme.md b/landingzones/caf_solution/add-ons/azure_devops_agent/readme.md new file mode 100644 index 000000000..dd7b29571 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/readme.md @@ -0,0 +1,54 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Azure Devops Agent add-on + +The Azure Devops Agent add-ons is the continuation of Self Hosted Agent implementation for Azure Devops environment that deployed in Azure Devops add on LZ. This will set up the underlying resources required for Agent in Azure. + +* Azure Virtual Machine to host the Agent +* Azure VM Extension to connect the VM to Azure Devops self hosted agent +* Storage account to put the script for VM Extension +* Key Vault to store the SSH key of the VM + +Azure Devops (Self Hosted Agent) add-on landing zone operates base on agent level for example for agent level0 will operates at **level 0** and agent level1 will operates at **level 1** + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +## Dependencies + +Landing zone: +* CAF Launchpad +* Azure DevOps add on (example: scenario 200-contoso_demo) + +## Deployment + +### Deploy the Azure Devops agent for level0 +```bash +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ + -tfstate level0_azure_devops_agents.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0 \ + -parallelism 30 \ + -level level0 \ + -env sandpit \ + -a apply +``` + +### Deploy the Azure Devops agent for level1 +```bash +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ + -tfstate azdo-agent-level1.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1 \ + -parallelism 30 \ + -level level1 \ + -env sandpit \ + -a apply + + +# If the tfstates are stored in a different subscription you need to execute the following command + +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ + -tfstate_subscription_id \ + -tfstate azdo-agent-level1.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1 \ + -parallelism 30 \ + -level level1 \ + -env sandpit \ + -a apply +``` \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars new file mode 100644 index 000000000..0141decf0 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars @@ -0,0 +1,64 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level0" + key = "azdo-agent-level0" + tfstates = { + launchpad = { + level = "current" + tfstate = "caf_launchpad.tfstate" + } + azdo-contoso_demo = { + level = "current" + tfstate = "azure_devops-contoso_demo" + } + } +} + +resource_groups = { + rg1 = { + name = "devops-agents-level0" + } +} + +azure_devops = { + + # Rover version to apply to the devops self-hosted agents during the setup. + rover_version = "aztfmod/rover:2010.2808" + url = "https://dev.azure.com/azure-terraform/" + + pats = { + agent = { + secret_name = "azdo-pat-agent" + keyvault_key = "secrets" + lz_key = "launchpad" + } + } + + agent_pool = { + name = "caf-sandpit-level0" + auto_provision = true + num_agents = 4 + agent_name_prefix = "agent" + } + +} + +role_mapping = { + built_in_role_mapping = { + storage_accounts = { + scripts_region1 = { + "Storage Blob Data Contributor" = { + azuread_groups = { + lz_key = "launchpad" + keys = ["keyvault_level0_rw"] + } + managed_identities = { + lz_key = "launchpad" + keys = ["level0"] + } + } + } + } + } +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars new file mode 100644 index 000000000..35f188ba7 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars @@ -0,0 +1,28 @@ + +keyvaults = { + ssh = { + name = "sshl0" + resource_group_key = "rg1" + sku_name = "premium" + soft_delete_enabled = true + + creation_policies = { + keyvault_level0_rw = { + # Reference a key to an azure ad group + lz_key = "launchpad" + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } + +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars new file mode 100644 index 000000000..0af2a98f2 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars @@ -0,0 +1,42 @@ + +storage_accounts = { + # Is used to store the azure devops deployment script to setup the Azure Devops Selfhosted agents + scripts_region1 = { + name = "scriptsl0" + resource_group_key = "rg1" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + allow_blob_public_access = true + + containers = { + scripts = { + name = "deployment-scripts" + container_access_type = "blob" + } + } + } +} + +# Attributes available https://www.terraform.io/docs/providers/azurerm/r/storage_blob.html +storage_account_blobs = { + devops_runtime_baremetal = { + storage_account_key = "scripts_region1" + storage_container_name = "deployment-scripts" + name = "devops_runtime_baremetal.sh" + source = "scripts/devops_runtime_baremetal.sh" + } +} + +diagnostic_storage_accounts = { + # Stores boot diagnostic for region1 + bootdiag_region1 = { + name = "bootl4" + resource_group_key = "rg1" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } +} + diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars new file mode 100644 index 000000000..3140b94e1 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars @@ -0,0 +1,79 @@ + +# Virtual machines +virtual_machines = { + + # Configuration to deploy a bastion host linux virtual machine + level0 = { + resource_group_key = "rg1" + provision_vm_agent = true + boot_diagnostics_storage_account_key = "bootdiag_region1" + + os_type = "linux" + + keyvault_key = "ssh" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + lz_key = "launchpad" + vnet_key = "devops_region1" + subnet_key = "release_agent_level0" + name = "0-release-agent-level0" + enable_ip_forwarding = false + internal_dns_name_label = "release-agent-level0" + } + } + + virtual_machine_settings = { + linux = { + name = "release-agent-level0" + size = "Standard_F2s_v2" + admin_username = "adminuser" + disable_password_authentication = true + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "release-agent-level0-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference = { + publisher = "canonical" + offer = "0001-com-ubuntu-server-focal" + sku = "20_04-lts" + version = "latest" + } + + identity = { + type = "UserAssigned" + + remote = { + launchpad = { + managed_identity_keys = [ + "level0", + ] + } + } + } + + + } + } + + virtual_machine_extensions = { + devops_selfhosted_agent = { + version = 1 + virtual_machine_key = "vm_devops_level0" + agent_init_script = "devops_runtime_baremetal.sh" + storage_account_blobs = [ + "devops_runtime_baremetal" + ] + } + } + + } +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars new file mode 100644 index 000000000..7197d9c73 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars @@ -0,0 +1,68 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "azdo-agent-level0" + level = "level1" + key = "azdo-agent-level1" + tfstates = { + azdo-agent-level0 = { + level = "lower" + tfstate = "level0_azure_devops_agents.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + azdo-contoso_demo = { + level = "lower" + tfstate = "azure_devops-contoso_demo" + } + } +} + +resource_groups = { + rg1 = { + name = "devops-agents-level0" + } +} + +azure_devops = { + + # Rover version to apply to the devops self-hosted agents during the setup. + rover_version = "aztfmod/rover:2010.2808" + url = "https://dev.azure.com/azure-terraform/" + + pats = { + agent = { + secret_name = "azdo-pat-agent" + keyvault_key = "secrets" + lz_key = "launchpad" + } + } + + agent_pool = { + name = "caf-sandpit-level1" + auto_provision = true + num_agents = 4 + agent_name_prefix = "agent" + } + +} + +role_mapping = { + built_in_role_mapping = { + storage_accounts = { + scripts_region1 = { + "Storage Blob Data Contributor" = { + azuread_groups = { + lz_key = "launchpad" + keys = ["keyvault_level0_rw"] + } + managed_identities = { + lz_key = "launchpad" + keys = ["level0", "level1"] + } + } + } + } + } +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars new file mode 100644 index 000000000..f25881503 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars @@ -0,0 +1,32 @@ + +keyvaults = { + ssh = { + name = "sshl1" + resource_group_key = "rg1" + sku_name = "premium" + soft_delete_enabled = true + + creation_policies = { + keyvault_level0_rw = { + # Reference a key to an azure ad group + lz_key = "launchpad" + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + msi_level0 = { + lz_key = "launchpad" + managed_identity_key = "level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars new file mode 100644 index 000000000..5ee9634cf --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars @@ -0,0 +1,42 @@ + +storage_accounts = { + # Is used to store the azure devops deployment script to setup the Azure Devops Selfhosted agents + scripts_region1 = { + name = "scriptsl1" + resource_group_key = "rg1" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + allow_blob_public_access = true + + containers = { + scripts = { + name = "deployment-scripts" + container_access_type = "blob" + } + } + } +} + +# Attributes available https://www.terraform.io/docs/providers/azurerm/r/storage_blob.html +storage_account_blobs = { + devops_runtime_baremetal = { + storage_account_key = "scripts_region1" + storage_container_name = "deployment-scripts" + name = "devops_runtime_baremetal.sh" + source = "scripts/devops_runtime_baremetal.sh" + } +} + +diagnostic_storage_accounts = { + # Stores boot diagnostic for region1 + bootdiag_region1 = { + name = "bootl1" + resource_group_key = "rg1" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } +} + diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars new file mode 100644 index 000000000..41a40da84 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars @@ -0,0 +1,77 @@ + +# Virtual machines +virtual_machines = { + + # Configuration to deploy a bastion host linux virtual machine + level1 = { + resource_group_key = "rg1" + provision_vm_agent = true + boot_diagnostics_storage_account_key = "bootdiag_region1" + + os_type = "linux" + + keyvault_key = "ssh" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + lz_key = "launchpad" + vnet_key = "devops_region1" + subnet_key = "release_agent_level1" + name = "0-release-agent-level1" + enable_ip_forwarding = false + internal_dns_name_label = "release-agent-level1" + } + } + + virtual_machine_settings = { + linux = { + name = "release-agent-level1" + size = "Standard_F2s_v2" + admin_username = "adminuser" + disable_password_authentication = true + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "release-agent-level1-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference = { + publisher = "canonical" + offer = "0001-com-ubuntu-server-focal" + sku = "20_04-lts" + version = "latest" + } + + identity = { + type = "UserAssigned" + + remote = { + lz_key = "launchpad" + managed_identity_keys = [ + "level1", + ] + } + } + + + } + } + + virtual_machine_extensions = { + devops_selfhosted_agent = { + version = 1 + agent_init_script = "devops_runtime_baremetal.sh" + storage_account_blobs = [ + "devops_runtime_baremetal" + ] + } + } + + } +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config b/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config new file mode 100644 index 000000000..5bed7c472 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config @@ -0,0 +1,117 @@ +#cloud-config +apt: + preserve_sources_list: true + sources: + azure-cli.list: + source: "deb https://packages.microsoft.com/repos/azure-cli/ bionic main" + key: | + -----BEGIN PGP PUBLIC KEY BLOCK----- + Version: GnuPG v1.4.7 (GNU/Linux) + + mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT + LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV + 7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag + OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j + H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr + M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs + ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC + AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH + /32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe + MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy + 7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV + KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ + XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+ + NdCFTW7wY0Fb1fWJ+/KTsC4= + =J6gs + -----END PGP PUBLIC KEY BLOCK----- + docker.list: + source: "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" + key: | + -----BEGIN PGP PUBLIC KEY BLOCK----- + + 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 + YT90qFF93M3v01BbxP+EIY2/9tiIPbrd + =0YYh + -----END PGP PUBLIC KEY BLOCK----- +package_update: true + +packages: + - docker-ce + - azure-cli + - ca-certificates + - curl + - apt-transport-https + - lsb-release + - jq + +snap: + commands: + - snap install kubectl --classic + +apt_upgrade: true + + # Install docker-compose +runcmd: + - [ sh, -c, 'curl -L https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep "tag_name" | cut -d \" -f4)/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose' ] + - [ sh, -c, 'sudo chmod +x /usr/local/bin/docker-compose' ] + +# Add default auto created user to docker group +system_info: + default_user: + groups: [docker] \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh b/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh new file mode 100644 index 000000000..7abc06a08 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh @@ -0,0 +1,109 @@ +#!/bin/sh + +url=${1} +pat_token=${2} +agent_pool=${3} +agent_prefix=${4} +num_agent=${5} +admin_user=${6} +rover_version="${7}" + +error() { + local parent_lineno="$1" + local message="$2" + local code="${3:-1}" + if [[ -n "$message" ]] ; then + >&2 echo -e "\e[41mError on or near line ${parent_lineno}: ${message}; exiting with status ${code}\e[0m" + else + >&2 echo -e "\e[41mError on or near line ${parent_lineno}; exiting with status ${code}\e[0m" + fi + echo "" + exit "${code}" +} + +function cleanup { + echo "calling cleanup" + + echo "stopping the service" + sudo ./svc.sh stop || true + echo "uninstall the service" + sudo ./svc.sh uninstall || true + echo "un-register from AZDO" + sudo -u ${admin_user} ./config.sh remove --unattended --auth pat --token ${pat_token} || true +} + +set -ETe +trap 'error ${LINENO}' ERR 1 2 3 6 + +#strict mode, fail on error +# set -euo pipefail + +echo "start" + +echo "install Ubuntu packages" + +# To make it easier for build and release pipelines to run apt-get, +# configure apt to not require confirmation (assume the -y argument by default) +export DEBIAN_FRONTEND=noninteractive +echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes + +apt-get update +apt-get install -y --no-install-recommends \ + ca-certificates \ + jq \ + apt-transport-https \ + docker.io \ + sudo + +echo "Allowing agent to run docker" + +usermod -aG docker ${admin_user} +systemctl daemon-reload +systemctl enable docker +service docker start +docker --version + +# Pull rover base image +echo "Rover docker image ${rover_version}" +docker pull "${rover_version}" 2>/dev/null + +echo "Installing Azure CLI" + +curl -sL https://aka.ms/InstallAzureCLIDeb | bash + +echo "install VSTS Agent" + +cd /home/${admin_user} +mkdir -p agent +cd agent + +AGENTRELEASE="$(curl -s https://api.github.com/repos/Microsoft/azure-pipelines-agent/releases/latest | grep -oP '"tag_name": "v\K(.*)(?=")')" +AGENTURL="https://vstsagentpackage.azureedge.net/agent/${AGENTRELEASE}/vsts-agent-linux-x64-${AGENTRELEASE}.tar.gz" +echo "Release "${AGENTRELEASE}" appears to be latest" +echo "Downloading..." +curl -s ${AGENTURL} -o agent_package.tar.gz + +for agent_num in $(seq 1 ${num_agent}); do + agent_dir="agent-$agent_num" + mkdir -p "$agent_dir" + cd "$agent_dir" + echo "moving to $agent_dir" + + cleanup + + name="${agent_prefix}-${agent_num}" + echo "installing agent $name" + tar zxvf ../agent_package.tar.gz + chmod -R 777 . + echo "extracted" + ./bin/installdependencies.sh || true + echo "dependencies installed" + sudo -u ${admin_user} ./config.sh --unattended --url "${url}" --auth pat --token "${pat_token}" --pool "${agent_pool}" --agent "${name}" --acceptTeeEula --replace --work ./_work --runAsService + echo "configuration done" + ./svc.sh install + echo "service installed" + ./svc.sh start + echo "service started" + echo "config done" + cd .. +done diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh b/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh new file mode 100644 index 000000000..eb0b8cc2a --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc +sudo sh -c 'echo -e "[azure-cli] +name=Azure CLI +baseurl=https://packages.microsoft.com/yumrepos/azure-cli +enabled=1 +gpgcheck=1 +gpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/azure-cli.repo' +sudo yum -y install azure-cli + +sudo yum install -y yum-utils device-mapper-persistent-data lvm2 +sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo +sudo yum makecache fast +sudo yum install -y docker-ce +sudo systemctl daemon-reload +sudo systemctl enable docker +sudo service docker start +sudo docker --version + +sudo az login --identity + +az acr login --name ${7} +sudo docker pull "${7}/${5}" + +for agent_num in $(seq 1 ${6}); do + name="${4}-${agent_num}" + sudo docker run -d -v /var/run/docker.sock:/var/run/docker.sock --name ${name} -e AZP_URL=${1} -e AZP_TOKEN=${2} -e AZP_POOL="${3}" -e AZP_AGENT_NAME="${name}" "${7}/${5}" +done \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/solution.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/solution.tf new file mode 100644 index 000000000..3316f9894 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/solution.tf @@ -0,0 +1,37 @@ +module "caf" { + source = "aztfmod/caf/azurerm" + version = "~>5.1.0" + + current_landingzone_key = var.landingzone.key + tenant_id = var.tenant_id + tfstates = local.tfstates + tags = local.tags + global_settings = local.global_settings + diagnostics = local.diagnostics + diagnostic_storage_accounts = var.diagnostic_storage_accounts + logged_user_objectId = var.logged_user_objectId + logged_aad_app_objectId = var.logged_aad_app_objectId + resource_groups = var.resource_groups + storage_accounts = var.storage_accounts + azuread_groups = var.azuread_groups + keyvaults = var.keyvaults + keyvault_access_policies = var.keyvault_access_policies + managed_identities = var.managed_identities + role_mapping = var.role_mapping + custom_role_definitions = var.custom_role_definitions + azuread_apps = var.azuread_apps + compute = { + virtual_machines = var.virtual_machines + } + storage = { + storage_account_blobs = var.storage_account_blobs + } + + # Pass the remote objects you need to connect to. + remote_objects = { + keyvaults = local.remote.keyvaults + vnets = local.remote.vnets + managed_identities = local.remote.managed_identities + azuread_groups = local.remote.azuread_groups + } +} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/variables.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/variables.tf new file mode 100644 index 000000000..45c344a59 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/variables.tf @@ -0,0 +1,102 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} + +variable "global_settings" { + default = {} +} +variable "tenant_id" {} +variable "landingzone" { +} +variable "rover_version" { + default = null +} + +variable "logged_user_objectId" { + default = null +} +variable "logged_aad_app_objectId" { + default = null +} +variable "tags" { + default = null +} +variable "app_service_environments" { + default = {} +} +variable "app_service_plans" { + default = {} +} +variable "app_services" { + default = {} +} +variable "diagnostics_definition" { + default = {} +} +variable "resource_groups" { + default = {} +} +variable "network_security_group_definition" { + default = {} +} +variable "vnets" { + default = {} +} +variable "azurerm_redis_caches" { + default = {} +} +variable "mssql_servers" { + default = {} +} +variable "storage_accounts" { + default = {} +} +variable "storage_account_blobs" { + default = {} +} +variable "azuread_groups" { + default = {} +} +variable "keyvaults" { + default = {} +} +variable "keyvault_access_policies" { + default = {} +} +variable "virtual_machines" { + default = {} +} +variable "diagnostic_storage_accounts" { + default = {} +} +variable "virtual_machine_extension_scripts" { + default = {} +} +variable "azure_devops" { + default = {} +} +variable "role_mapping" { + default = {} +} +variable "custom_role_definitions" { + default = {} +} +variable "azuread_apps" { + default = {} +} +variable "dynamic_keyvault_secrets" { + default = {} +} +variable "managed_identities" { + default = {} +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf new file mode 100644 index 000000000..898d03288 --- /dev/null +++ b/landingzones/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf @@ -0,0 +1,37 @@ + + +# Get PAT token from keyvault +data "azurerm_key_vault_secret" "agent_pat" { + depends_on = [module.caf] + for_each = { + for key, value in try(var.virtual_machines, {}) : key => value + if try(value.virtual_machine_extensions, null) != null + } + + name = var.azure_devops.pats.agent.secret_name + key_vault_id = try(var.azure_devops.pats["agent"].lz_key, null) == null ? local.combined.keyvaults[var.landingzone.key][var.azure_devops.pats["agent"].keyvault_key].id : local.combined.keyvaults[var.azure_devops.pats["agent"].lz_key][var.azure_devops.pats["agent"].keyvault_key].id +} + + +module "vm_extensions" { + source = "./extensions" + depends_on = [module.caf] + for_each = { + for key, value in try(var.virtual_machines, {}) : key => value + if try(value.virtual_machine_extensions, null) != null + } + + virtual_machine_id = module.caf.virtual_machines[each.key].id + extensions = each.value.virtual_machine_extensions + settings = { + devops_selfhosted_agent = { + storage_accounts = module.caf.storage_accounts + agent_pat = data.azurerm_key_vault_secret.agent_pat[each.key].value + admin_username = each.value.virtual_machine_settings[each.value.os_type].admin_username + azure_devops = var.azure_devops + storage_account_blobs_urls = [ + for key, value in try(var.storage_account_blobs, []) : module.caf.storage_account_blobs[key].url + ] + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/README.md b/landingzones/caf_solution/add-ons/caf_eslz/README.md new file mode 100644 index 000000000..afef4f046 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/README.md @@ -0,0 +1,44 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Enterprise-Scale + +The foundations landing zone allows you to manage the core components of an environment: + +* Management groups +* Policies + +Foundations landing zone operates at **level 1**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +
+ +## Components + +CAF eslz leverages the enterprise-scale module in order to deploy its core components. + +For full description on enterprise_scale module usage, please [refer to the repository](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale) + +This is currently work in progress. +Use the following configuration file in order to get started with the enterprise-scale module integration: + +```bash +# This example will setup the complete enterprise-scale fundamentals management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription + +rover -lz /tf/caf/public/landingzones/caf_eslz \ + -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/100 \ + -level level1 \ + -a [plan|apply|destroy] + +# This example will setup custom enterprise-scale management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription + +rover -lz /tf/caf/public/landingzones/caf_eslz \ + -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/200 \ + -level level1 \ + -a [plan|apply|destroy] + +# If the tfstates are stored in a different subscription you need to execute the following command +rover -lz /tf/caf/public/landingzones/caf_eslz \ + -tfstate_subscription_id \ + -var-folder /tf/caf/public/landingzones/caf_foundations/scenario/200 \ + -level level1 \ + -a apply +``` diff --git a/landingzones/caf_solution/add-ons/caf_eslz/backend.azurerm b/landingzones/caf_solution/add-ons/caf_eslz/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/es_main.tf b/landingzones/caf_solution/add-ons/caf_eslz/es_main.tf new file mode 100644 index 000000000..a2dff70a0 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/es_main.tf @@ -0,0 +1,25 @@ +# For full description on enterprise_scale module usage, please refer to https://github.com/Azure/terraform-azurerm-caf-enterprise-scale + +module "enterprise_scale" { + source = "Azure/caf-enterprise-scale/azurerm" + version = "0.0.8" + + root_parent_id = data.azurerm_client_config.current.tenant_id + + root_id = var.root_id + root_name = var.root_name + deploy_core_landing_zones = var.deploy_core_landing_zones + + # Control whether to deploy the demo landing zones // default = false + deploy_demo_landing_zones = var.deploy_demo_landing_zones + + # Set a path for the custom archetype library path + library_path = try(format("%s", var.library_path), "") + + # Deploys the custom landing zone configuration as defined in config file + custom_landing_zones = var.custom_landing_zones + subscription_id_overrides = var.subscription_id_overrides + archetype_config_overrides = var.archetype_config_overrides + + default_location = local.global_settings.regions[local.global_settings.default_region] +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf b/landingzones/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf new file mode 100644 index 000000000..ee887a2d1 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf @@ -0,0 +1,46 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + diagnostics = { + diagnostics_definition = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition + diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics + event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.event_hub_namespaces + } + +} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/main.tf b/landingzones/caf_solution/add-ons/caf_eslz/main.tf new file mode 100644 index 000000000..9dbcda3db --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/main.tf @@ -0,0 +1,18 @@ +terraform { + + required_version = ">= 0.13" +} + + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} +data "azurerm_subscription" "current" {} + + diff --git a/landingzones/caf_solution/add-ons/caf_eslz/output.tf b/landingzones/caf_solution/add-ons/caf_eslz/output.tf new file mode 100644 index 000000000..e69de29bb diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars b/landingzones/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars new file mode 100644 index 000000000..89e2ea1fd --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars @@ -0,0 +1,25 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "caf_eslz" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } +} + +enterprise_scale = { + # Define a custom ID to use for the root Management Group + # Also used as a prefix for all core Management Group IDs + # root_id = "caf" + # root_name = "CAF-RootManagementGroup" + + # Control whether to deploy the default core landing zones // default = true + deploy_core_landing_zones = true + + # Control whether to deploy the demo landing zones // default = false + deploy_demo_landing_zones = false +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars new file mode 100644 index 000000000..73c92cb7f --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars @@ -0,0 +1,45 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "caf_foundations" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } +} + +enterprise_scale = { + #path to the policies definition and assignment repo + library_path = "/tf/caf/public/landingzones/caf_eslz/scenario/200/lib" + + #management groups hierarchy configuration + custom_landing_zones = { + caf = { + display_name = "CAF-RootManagementGroup" + parent_management_group_id = "" + subscription_ids = [] + archetype_config = { + archetype_id = "es_root" + parameters = {} + access_control = {} + } + } + child-caf = { + display_name = "CAF-ChildManagementGroup" + parent_management_group_id = "caf" + subscription_ids = [] + archetype_config = { + archetype_id = "es_management" + parameters = { + ES-Deploy-ForwardDiagLog = { + logAnalytics = "central_logs_region1" + } + } + access_control = {} + } + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json new file mode 100644 index 000000000..e6d18b5db --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json @@ -0,0 +1,12 @@ +{ + "es_management": { + "policy_assignments": [ + "ES-Deploy-ASC-Standard" + ], + "policy_definitions": [ + ], + "policy_set_definitions": [], + "role_assignments": [], + "role_definitions": [] + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json new file mode 100644 index 000000000..e41b04f6f --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json @@ -0,0 +1,13 @@ +{ + "es_root": { + "policy_assignments": [ + "ES-Deploy-ASC-Standard" + ], + "policy_definitions": [ + "ES-Deploy-ASC-Standard" + ], + "policy_set_definitions": [], + "role_assignments": [], + "role_definitions": [] + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json new file mode 100644 index 000000000..ae28ea455 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json @@ -0,0 +1,28 @@ +{ + "name": "ES-Allowed-Locations", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Specifies the allowed locations (regions) where resources can be deployed", + "displayName": "ES-Allowed-Resource-Locations", + "notScopes": [], + "parameters": { + "listOfAllowedLocations": { + "value": [ + "uksouth", + "ukwest" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "None" + } +} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json new file mode 100644 index 000000000..b00174588 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json @@ -0,0 +1,28 @@ +{ + "name": "ES-Allowed-RSG-Locations", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Specifies the allowed locations (regions) where Resource Groups can be deployed", + "displayName": "ES-Allowed-ResourceGroup-Locations", + "notScopes": [], + "parameters": { + "listOfAllowedLocations": { + "value": [ + "uksouth", + "ukwest" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "None" + } +} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json new file mode 100644 index 000000000..4417b6a01 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json @@ -0,0 +1,28 @@ +{ + "name": "ES-Deploy-ASC-ContExport", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Deploy ASC Continuous Export To Log Analytics Workspace.", + "displayName": "ES-Deploy-ASC-ContinuousExportToWorkspace", + "notScopes": [], + "parameters": { + "resourceGroupLocation": { + "value": null + }, + "workspaceResourceId": { + "value": null + } + }, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-ContinuousExportToWorkspace", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json new file mode 100644 index 000000000..ba6d2186f --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json @@ -0,0 +1,88 @@ +{ + "name": "ES-Deploy-ASC-Monitoring", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Enable Monitoring in Azure Security Center.", + "displayName": "ES-Deploy-ASC-Monitoring", + "notScopes": [], + "parameters": { + "aadAuthenticationInSqlServerMonitoringEffect": { + "value": "Disabled" + }, + "diskEncryptionMonitoringEffect": { + "value": "Disabled" + }, + "encryptionOfAutomationAccountMonitoringEffect": { + "value": "Disabled" + }, + "identityDesignateLessThanOwnersMonitoringEffect": { + "value": "Disabled" + }, + "identityDesignateMoreThanOneOwnerMonitoringEffect": { + "value": "Disabled" + }, + "identityEnableMFAForWritePermissionsMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveDeprecatedAccountMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveDeprecatedAccountWithOwnerPermissionsMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveExternalAccountWithOwnerPermissionsMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveExternalAccountWithReadPermissionsMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveExternalAccountWithWritePermissionsMonitoringEffect": { + "value": "Disabled" + }, + "jitNetworkAccessMonitoringEffect": { + "value": "Disabled" + }, + "networkSecurityGroupsOnSubnetsMonitoringEffect": { + "value": "AuditIfNotExists" + }, + "sqlDbEncryptionMonitoringEffect": { + "value": "Disabled" + }, + "sqlManagedInstanceAdvancedDataSecurityEmailAdminsMonitoringEffect": { + "value": "Disabled" + }, + "sqlManagedInstanceAdvancedDataSecurityEmailsMonitoringEffect": { + "value": "Disabled" + }, + "sqlServerAdvancedDataSecurityEmailAdminsMonitoringEffect": { + "value": "Disabled" + }, + "sqlServerAdvancedDataSecurityMonitoringEffect": { + "value": "Disabled" + }, + "systemUpdatesMonitoringEffect": { + "value": "Disabled" + }, + "useRbacRulesMonitoringEffect": { + "value": "Disabled" + }, + "vmssSystemUpdatesMonitoringEffect": { + "value": "Disabled" + }, + "windowsDefenderExploitGuardMonitoringEffect": { + "value": "Disabled" + } + }, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json new file mode 100644 index 000000000..1786a9c39 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json @@ -0,0 +1,21 @@ +{ + "name": "ES-Deploy-ASC-Standard", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Deploy Azure Security Center Standard Tier.", + "displayName": "ES-Deploy-ASC-Standard", + "notScopes": [], + "parameters": {}, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-Standard", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json new file mode 100644 index 000000000..7bf367af8 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json @@ -0,0 +1,25 @@ +{ + "name": "ES-Deploy-ForwardActLogs", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Ensures that Activity Log Diagnostics settings are set to push logs into Log Analytics workspace.", + "displayName": "ES-Deploy-Diagnostics-ForwardActivityLogs", + "notScopes": [], + "parameters": { + "logAnalytics": { + "value": null + } + }, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-Diagnostics-LogAnalytics", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json new file mode 100644 index 000000000..6cae95354 --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json @@ -0,0 +1,25 @@ +{ + "name": "ES-Deploy-ForwardDiagLog", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Ensures that Azure resources are configured to forward diagnostic logs and metrics to an Azure Log Analytics workspace.", + "displayName": "ES-Deploy-Diagnostics-ForwardDiagnosticLogs", + "notScopes": [], + "parameters": { + "logAnalytics": { + "value": null + } + }, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/ES-Deploy-Diagnostics-LogAnalytics", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json new file mode 100644 index 000000000..d75c1298a --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json @@ -0,0 +1,284 @@ +{ + "name": "ES-Deploy-ASC-Standard", + "type": "Microsoft.Authorization/policyDefinitions", + "apiVersion": "2019-09-01", + "properties": { + "description": "Ensures that subscriptions have Security Center Standard enabled.", + "displayName": "ES-Deploy-ASC-Standard", + "mode": "All", + "parameters": { + "pricingTierVMs": { + "type": "String", + "metadata": { + "displayName": "pricingTierVMs", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierSqlServers": { + "type": "String", + "metadata": { + "displayName": "pricingTierSqlServers", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierAppServices": { + "type": "String", + "metadata": { + "displayName": "pricingTierAppServices", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierStorageAccounts": { + "type": "String", + "metadata": { + "displayName": "pricingTierStorageAccounts", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierContainerRegistry": { + "type": "String", + "metadata": { + "displayName": "pricingTierContainerRegistry", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierKeyVaults": { + "type": "String", + "metadata": { + "displayName": "pricingTierKeyVaults", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierKubernetesService": { + "type": "String", + "metadata": { + "displayName": "pricingTierKubernetesService", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.Resources/subscriptions" + } + ] + }, + "then": { + "effect": "deployIfNotExists", + "details": { + "type": "Microsoft.Security/pricings", + "deploymentScope": "subscription", + "existenceScope": "subscription", + "roleDefinitionIds": [ + "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635" + ], + "existenceCondition": { + "allOf": [ + { + "field": "Microsoft.Security/pricings/pricingTier", + "equals": "Standard" + }, + { + "field": "type", + "equals": "Microsoft.Security/pricings" + } + ] + }, + "deployment": { + "location": "northeurope", + "properties": { + "mode": "incremental", + "parameters": { + "pricingTierVMs": { + "value": "[parameters('pricingTierVMs')]" + }, + "pricingTierSqlServers": { + "value": "[parameters('pricingTierSqlServers')]" + }, + "pricingTierAppServices": { + "value": "[parameters('pricingTierAppServices')]" + }, + "pricingTierStorageAccounts": { + "value": "[parameters('pricingTierStorageAccounts')]" + }, + "pricingTierContainerRegistry": { + "value": "[parameters('pricingTierContainerRegistry')]" + }, + "pricingTierKeyVaults": { + "value": "[parameters('pricingTierKeyVaults')]" + }, + "pricingTierKubernetesService": { + "value": "[parameters('pricingTierKubernetesService')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "pricingTierVMs": { + "type": "string", + "metadata": { + "description": "pricingTierVMs" + } + }, + "pricingTierSqlServers": { + "type": "string", + "metadata": { + "description": "pricingTierSqlServers" + } + }, + "pricingTierAppServices": { + "type": "string", + "metadata": { + "description": "pricingTierAppServices" + } + }, + "pricingTierStorageAccounts": { + "type": "string", + "metadata": { + "description": "pricingTierStorageAccounts" + } + }, + "pricingTierContainerRegistry": { + "type": "string", + "metadata": { + "description": "ContainerRegistry" + } + }, + "pricingTierKeyVaults": { + "type": "string", + "metadata": { + "description": "KeyVaults" + } + }, + "pricingTierKubernetesService": { + "type": "string", + "metadata": { + "description": "KubernetesService" + } + } + }, + "variables": {}, + "resources": [ + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "VirtualMachines", + "properties": { + "pricingTier": "[parameters('pricingTierVMs')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "StorageAccounts", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/VirtualMachines')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierStorageAccounts')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "AppServices", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/StorageAccounts')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierAppServices')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "SqlServers", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/AppServices')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierSqlServers')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "KeyVaults", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/SqlServers')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierKeyVaults')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "KubernetesService", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/KeyVaults')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierKubernetesService')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "ContainerRegistry", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/KubernetesService')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierContainerRegistry')]" + } + } + ], + "outputs": {} + } + } + } + } + } + } + } +} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/variables.tf b/landingzones/caf_solution/add-ons/caf_eslz/variables.tf new file mode 100644 index 000000000..2d9c23fac --- /dev/null +++ b/landingzones/caf_solution/add-ons/caf_eslz/variables.tf @@ -0,0 +1,135 @@ +# Map of the remote data state +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} +variable "tfstate_storage_account_name" { + description = "This value is propulated by the rover" +} +variable "tfstate_container_name" { + description = "This value is propulated by the rover" +} +variable "tfstate_key" { + description = "This value is propulated by the rover" +} +variable "tfstate_resource_group_name" { + description = "This value is propulated by the rover" +} + +variable "landingzone" { + default = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "enterprise_scale" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } + } +} + +variable "user_type" {} +variable "tenant_id" {} +variable "rover_version" {} +variable "logged_user_objectId" { + default = null +} +variable "tags" { + type = map(any) + default = {} +} + + +variable "root_id" { + type = string + description = "If specified, will set a custom Name (ID) value for the Enterprise-scale \"root\" Management Group, and append this to the ID for all core Enterprise-scale Management Groups." + default = "es" + + validation { + condition = can(regex("^[a-zA-Z0-9-]{2,10}$", var.root_id)) + error_message = "The root_id value must be between 2 to 10 characters long and can only contain alphanumeric characters and hyphens." + } +} + +variable "root_name" { + type = string + description = "If specified, will set a custom Display Name value for the Enterprise-scale \"root\" Management Group." + default = "Enterprise-Scale" + + validation { + condition = can(regex("^[A-Za-z][A-Za-z0-9- ._]{1,22}[A-Za-z0-9]?$", var.root_name)) + error_message = "The root_name value must be between 2 to 24 characters long, start with a letter, end with a letter or number, and can only contain space, hyphen, underscore or period characters." + } +} + +variable "deploy_core_landing_zones" { + type = bool + description = "If set to true, will include the core Enterprise-scale Management Group hierarchy." + default = false +} + +variable "archetype_config_overrides" { + type = map(any) + description = "If specified, will set custom Archetype configurations to the default Enterprise-scale Management Groups." + default = {} +} + +variable "subscription_id_overrides" { + type = map(list(string)) + description = "If specified, will be used to assign subscription_ids to the default Enterprise-scale Management Groups." + default = {} +} + +variable "deploy_demo_landing_zones" { + type = bool + description = "If set to true, will include the demo \"Landing Zone\" Management Groups." + default = false +} + +variable "custom_landing_zones" { + type = map( + object({ + display_name = string + parent_management_group_id = string + subscription_ids = list(string) + archetype_config = object({ + archetype_id = string + parameters = any + access_control = any + }) + }) + ) + description = "If specified, will deploy additional Management Groups alongside Enterprise-scale core Management Groups." + default = {} + + validation { + condition = can(regex("^[a-z0-9-]{2,36}$", keys(var.custom_landing_zones)[0])) || length(keys(var.custom_landing_zones)) == 0 + error_message = "The custom_landing_zones keys must be between 2 to 36 characters long and can only contain lowercase letters, numbers and hyphens." + } +} + +variable "library_path" { + type = string + description = "If specified, sets the path to a custom library folder for archetype artefacts." + default = "" +} + +variable "template_file_variables" { + type = map(any) + description = "If specified, provides the ability to define custom template variables used when reading in template files from the built-in and custom library_path." + default = {} +} + +variable "default_location" { + type = string + description = "If specified, will use set the default location used for resource deployments where needed." + default = "eastus" + + # Need to add validation covering all Azure locations +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/databricks/backend.azurerm b/landingzones/caf_solution/add-ons/databricks/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones/caf_solution/add-ons/databricks/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/databricks/databricks.tf b/landingzones/caf_solution/add-ons/databricks/databricks.tf new file mode 100644 index 000000000..1c81174b7 --- /dev/null +++ b/landingzones/caf_solution/add-ons/databricks/databricks.tf @@ -0,0 +1,21 @@ +locals { + azure_workspace_resource_id = local.remote.databricks_workspaces[var.databricks.lz_key][var.databricks.workspace_key].id +} + +provider "databricks" { + azure_workspace_resource_id = local.azure_workspace_resource_id + # azure_client_id = var.client_id + # azure_client_secret = var.client_secret + # azure_tenant_id = var.tenant_id +} + +module "databricks" { + source = "../../modules/databricks" + + settings = var.databricks +} + +output "databricks" { + value = module.databricks + sensitive = false +} diff --git a/landingzones/caf_solution/add-ons/databricks/locals.remote_tfstates.tf b/landingzones/caf_solution/add-ons/databricks/locals.remote_tfstates.tf new file mode 100644 index 000000000..b813756c5 --- /dev/null +++ b/landingzones/caf_solution/add-ons/databricks/locals.remote_tfstates.tf @@ -0,0 +1,43 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + remote = { + databricks_workspaces = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.databricks_workspaces[key], {})) + } + } + +} diff --git a/landingzones/caf_solution/add-ons/databricks/main.tf b/landingzones/caf_solution/add-ons/databricks/main.tf new file mode 100644 index 000000000..1325d0f88 --- /dev/null +++ b/landingzones/caf_solution/add-ons/databricks/main.tf @@ -0,0 +1,63 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.43" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "1.0.0" + } + databricks = { + source = "databrickslabs/databricks" + version = "~> 0.2.5" + } + } + required_version = ">= 0.13" +} + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + +data "terraform_remote_state" "landingzone" { + backend = "azurerm" + config = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + key = var.tfstate_key + resource_group_name = var.tfstate_resource_group_name + } +} + +locals { + diagnostics = { + diagnostics_definition = merge(data.terraform_remote_state.landingzone.outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = data.terraform_remote_state.landingzone.outputs.diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.landingzone.outputs.diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.landingzone.outputs.diagnostics.log_analytics + } + + tfstates = merge( + map(var.landingzone.key, + map( + "storage_account_name", var.tfstate_storage_account_name, + "container_name", var.tfstate_container_name, + "resource_group_name", var.tfstate_resource_group_name, + "key", var.tfstate_key, + "level", var.landingzone.level, + "tenant_id", data.azurerm_client_config.current.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + , + data.terraform_remote_state.landingzone.outputs.tfstates + ) + +} diff --git a/landingzones/caf_solution/add-ons/databricks/variables.tf b/landingzones/caf_solution/add-ons/databricks/variables.tf new file mode 100644 index 000000000..6c3a9e993 --- /dev/null +++ b/landingzones/caf_solution/add-ons/databricks/variables.tf @@ -0,0 +1,154 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "global_settings" { + default = {} +} + +variable "landingzone" { + default = "" +} + +variable "environment" { + default = "sandpit" +} +variable "rover_version" { + default = null +} +variable "max_length" { + default = 40 +} +variable "logged_user_objectId" { + default = null +} +variable "logged_aad_app_objectId" { + default = null +} +variable "tags" { + default = null + type = map(any) +} +variable "diagnostic_log_analytics" { + default = {} +} +variable "app_service_environments" { + default = {} +} +variable "app_service_plans" { + default = {} +} +variable "app_services" { + default = {} +} +variable "diagnostics_definition" { + default = null +} +variable "resource_groups" { + default = null +} +variable "network_security_group_definition" { + default = {} +} +variable "vnets" { + default = {} +} +variable "azurerm_redis_caches" { + default = {} +} +variable "mssql_servers" { + default = {} +} +variable "mssql_databases" { + default = {} +} +variable "mssql_elastic_pools" { + default = {} +} +variable "storage_accounts" { + default = {} +} +variable "azuread_groups" { + default = {} +} +variable "keyvaults" { + default = {} +} +variable "keyvault_access_policies" { + default = {} +} +variable "virtual_machines" { + default = {} +} +variable "azure_container_registries" { + default = {} +} +variable "bastion_hosts" { + default = {} +} +variable "public_ip_addresses" { + default = {} +} +variable "diagnostic_storage_accounts" { + default = {} +} +variable "managed_identities" { + default = {} +} +variable "private_dns" { + default = {} +} +variable "synapse_workspaces" { + default = {} +} +variable "azurerm_application_insights" { + default = {} +} +variable "role_mapping" { + default = {} +} +variable "aks_clusters" { + default = {} +} +variable "databricks_workspaces" { + default = {} +} +variable "machine_learning_workspaces" { + default = {} +} +variable "monitoring" { + default = {} +} +variable "virtual_wans" { + default = {} +} +variable "event_hub_namespaces" { + default = {} +} +variable "application_gateways" { + default = {} +} +variable "application_gateway_applications" { + default = {} +} +variable "dynamic_keyvault_secrets" { + default = {} +} +variable "disk_encryption_sets" { + default = {} +} +variable "keyvault_keys" { + default = {} +} +variable "databricks" { + default = {} +} +variable "var_folder_path" { + default = {} +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/helm-charts/backend.azurerm b/landingzones/caf_solution/add-ons/helm-charts/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones/caf_solution/add-ons/helm-charts/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/helm-charts/charts.tf b/landingzones/caf_solution/add-ons/helm-charts/charts.tf new file mode 100644 index 000000000..74b16be73 --- /dev/null +++ b/landingzones/caf_solution/add-ons/helm-charts/charts.tf @@ -0,0 +1,21 @@ + +resource "kubernetes_namespace" "gitlab_runners" { + for_each = var.aks_namespaces + + metadata { + name = each.value + } +} + +resource "helm_release" "chart" { + depends_on = [kubernetes_namespace.gitlab_runners] + for_each = var.helm_charts + + chart = each.value.chart + name = each.value.name + namespace = each.value.namespace + repository = try(each.value.repository, null) + timeout = try(each.value.timeout, 4000) + values = [file(each.value.value_file)] + wait = try(each.value.wait, true) +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf b/landingzones/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf new file mode 100644 index 000000000..c87b31046 --- /dev/null +++ b/landingzones/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf @@ -0,0 +1,49 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics + + remote = { + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + global_settings = local.global_settings + diagnostics = local.diagnostics + + + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) + } + + } + +} diff --git a/landingzones/caf_solution/add-ons/helm-charts/main.tf b/landingzones/caf_solution/add-ons/helm-charts/main.tf new file mode 100644 index 000000000..263eade2a --- /dev/null +++ b/landingzones/caf_solution/add-ons/helm-charts/main.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.51.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.0.2" + } + helm = { + source = "hashicorp/helm" + version = "~> 2.0.3" + } + } + required_version = ">= 0.13" +} diff --git a/landingzones/caf_solution/add-ons/helm-charts/providers.tf b/landingzones/caf_solution/add-ons/helm-charts/providers.tf new file mode 100644 index 000000000..3beaf3ead --- /dev/null +++ b/landingzones/caf_solution/add-ons/helm-charts/providers.tf @@ -0,0 +1,39 @@ + +provider "azurerm" { + features { + } +} + +provider "kubernetes" { + host = local.k8sconfigs[var.aks_cluster_key].host + username = local.k8sconfigs[var.aks_cluster_key].username + password = local.k8sconfigs[var.aks_cluster_key].password + client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate + client_key = local.k8sconfigs[var.aks_cluster_key].client_key + cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate +} + +provider "helm" { + kubernetes { + host = local.k8sconfigs[var.aks_cluster_key].host + username = local.k8sconfigs[var.aks_cluster_key].username + password = local.k8sconfigs[var.aks_cluster_key].password + client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate + client_key = local.k8sconfigs[var.aks_cluster_key].client_key + cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate + } +} + +locals { + k8sconfigs = { + for key, value in var.aks_clusters : key => { + kube_admin_config_raw = local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config_raw + host = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.host : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.host + username = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.username : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.username + password = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.password : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.password + client_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_certificate) + client_key = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_key) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_key) + cluster_ca_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.cluster_ca_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.cluster_ca_certificate) + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/helm-charts/variables.tf b/landingzones/caf_solution/add-ons/helm-charts/variables.tf new file mode 100644 index 000000000..2c4c62f35 --- /dev/null +++ b/landingzones/caf_solution/add-ons/helm-charts/variables.tf @@ -0,0 +1,32 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "landingzone" {} +variable "rover_version" { + default = null +} +variable "tags" { + default = null +} + +variable "helm_charts" {} +variable "aks_namespaces" { + default = {} +} +variable "aks_cluster_key" { + description = "AKS cluster key to deploy the Gitlab Helm charts. The key must be defined in the variable aks_clusters" +} +variable "aks_cluster_vnet_key" { + +} +variable "aks_clusters" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars b/landingzones/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars new file mode 100644 index 000000000..1ce04bf0f --- /dev/null +++ b/landingzones/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars @@ -0,0 +1,25 @@ +landingzone = { + backend_type = "remote" + level = "level0" + key = "launchpad" +} + +# Create the TFC organization +tfe_organizations = { + caf_lz = { + name = "caf-landingzones-test3" + email = "admin@your-company.com" + + } +} + +# Create the required TFE workspaces +tfe_workspaces = { + caf_launchpad = { + # specifies the object key for the organization where to create the workspace + organization_key = "caf_lz" + name = "caf_launchpad" + # path to place the backend file for the corresponding landing zone + backend_file = "/backend.hcl" + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/main.tf b/landingzones/caf_solution/add-ons/terraform_cloud/main.tf new file mode 100644 index 000000000..413e570f5 --- /dev/null +++ b/landingzones/caf_solution/add-ons/terraform_cloud/main.tf @@ -0,0 +1,51 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.40" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.0.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + tfe = { + source = "hashicorp/tfe" + version = "~> 0.22.0" + } + } + required_version = ">= 0.13" +} + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + +locals { + tfstates = merge( + map(var.landingzone.backend_type, + map( + "level", var.landingzone.level, + "tenant_id", data.azurerm_client_config.current.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + ) +} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/readme.md b/landingzones/caf_solution/add-ons/terraform_cloud/readme.md new file mode 100644 index 000000000..7bfe4e7a6 --- /dev/null +++ b/landingzones/caf_solution/add-ons/terraform_cloud/readme.md @@ -0,0 +1,44 @@ +# Add-on to deploy a Terraform Cloud / Terraform Enterprise configuration for Azure CAF landing zones + +Supported scenario in this release: + +1. Create the TFE/TFC environment (organization, variables, workspaces) + +Future scenarios: + +1. Use TFE/TFC as remote backend (local execution, backend in TFC) +2. Deploy Terraform Enterprise Server and remote agents +3. Use TFE/TFC in online mode (execution in TFE with remote agents) + +## Authenticating to Terraform Cloud + +First step is to authenticate to TFC using the following commands: + +```bash +terraform login +export TERRAFORM_CONFIG="$HOME/.terraform.d/credentials.tfrc.json" +``` + +## Creating the TFC environment + +This will setup TFC organization, workspaces and variables to host landing zones. + +```bash +# Deploy +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/ \ +-var-folder /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/ \ +-a plan -launchpad + +or +cd /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/ +terraform init +terraform plan \ +-var-file /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars +``` + +Once ready, you can create your configuration: + +```bash +terraform apply \ +-var-file /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars +``` \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf b/landingzones/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf new file mode 100644 index 000000000..db9218fc0 --- /dev/null +++ b/landingzones/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf @@ -0,0 +1,83 @@ + +resource "tfe_organization" "tfe_org" { + for_each = try(var.tfe_organizations, {}) + + name = each.value.name + email = each.value.email + session_timeout_minutes = try(each.value.session_timeout_minutes, 20160) + session_remember_minutes = try(each.value.session_remember_minutes, 20160) + collaborator_auth_policy = try(each.value.collaborator_auth_policy, "password") + owners_team_saml_role_id = try(each.value.owners_team_saml_role_id, null) +} + +resource "tfe_workspace" "tfe_wks" { + for_each = try(var.tfe_workspaces, {}) + + name = each.value.name + organization = tfe_organization.tfe_org[each.value.organization_key].name + auto_apply = try(each.value.auto_apply, false) + file_triggers_enabled = try(each.value.file_triggers_enabled, true) + operations = try(each.value.operations, true) + queue_all_runs = try(each.value.queue_all_runs, true) + speculative_enabled = try(each.value.speculative_enabled, true) + ssh_key_id = try(each.value.ssh_key_id, null) + terraform_version = try(each.value.terraform_version, null) + trigger_prefixes = try(each.value.trigger_prefixes, null) + working_directory = try(each.value.working_directory, null) + + dynamic "vcs_repo" { + for_each = lookup(each.value, "vcs_repo", null) == null ? [] : [1] + + content { + identifier = each.value.vcs_repo.identifier + branch = try(each.value.vcs_repo.branch, null) + ingress_submodules = try(each.value.vcs_repo.ingress_submodules, false) + oauth_token_id = each.value.vcs_repo.oauth_token_id + } + } +} + +resource "tfe_variable" "variable" { + for_each = try(var.tfe_variables, {}) + + key = each.value.key_name + value = each.value.value + category = each.value.category + workspace_id = tfe_workspace.tfe_wks[each.value.workspace_key].id + description = each.value.description + hcl = try(each.value.hcl, false) + sensitive = try(each.value.sensitive, false) +} + +resource "null_resource" "backend_file" { + depends_on = [tfe_workspace.tfe_wks] + for_each = try(var.tfe_workspaces, {}) + + provisioner "local-exec" { + working_dir = "./" + command = "echo workspaces '{' name = \\\"${each.value.name}\\\" '}' >> ${path.cwd}${each.value.backend_file}" + } + provisioner "local-exec" { + working_dir = "./" + command = "echo hostname = \\\"app.terraform.io\\\" >> ${path.cwd}${each.value.backend_file}" + } + provisioner "local-exec" { + working_dir = "./" + command = "echo organization = \\\"${tfe_organization.tfe_org[each.value.organization_key].name}\\\" >> ${path.cwd}${each.value.backend_file}" + } +} + +resource "null_resource" "backend_file_destroy" { + depends_on = [tfe_workspace.tfe_wks] + for_each = try(var.tfe_workspaces, {}) + + triggers = { + backend_file = lookup(each.value, "backend_file") + } + + provisioner "local-exec" { + command = format("rm %s%s", path.cwd, self.triggers.backend_file) + when = destroy + on_failure = fail + } +} diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/variables.tf b/landingzones/caf_solution/add-ons/terraform_cloud/variables.tf new file mode 100644 index 000000000..499b0aba5 --- /dev/null +++ b/landingzones/caf_solution/add-ons/terraform_cloud/variables.tf @@ -0,0 +1,85 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" { + default = {} +} +variable "lower_container_name" { + default = {} +} +variable "lower_resource_group_name" { + default = {} +} + +variable "tfstate_storage_account_name" { + default = {} +} +variable "tfstate_container_name" { + default = {} +} +variable "tfstate_key" { + default = {} +} +variable "tfstate_resource_group_name" { + default = {} +} + +variable "global_settings" { + default = {} +} +variable "tenant_id" { + default = {} +} +variable "landingzone" { + default = {} +} + +variable "rover_version" { + default = null +} + +variable "logged_user_objectId" { + default = null +} +variable "logged_aad_app_objectId" { + default = null +} +variable "tags" { + default = null +} +variable "keyvaults" { + default = {} +} +variable "keyvault_access_policies" { + default = {} +} +variable "role_mapping" { + default = {} +} +variable "secrets_from_keys" { + default = {} +} +variable "custom_role_definitions" { + default = {} +} +variable "azuread_apps" { + default = {} +} + +variable "tfe_organizations" { + default = {} +} + +variable "tfe_workspaces" { + default = {} +} + +variable "tfe_variables" { + default = {} +} + +variable "tfe_servers" { + default = {} +} + +variable "tfe_agents" { + default = {} +} \ No newline at end of file diff --git a/landingzones/caf_solution/backend.azurerm b/landingzones/caf_solution/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/landingzones/caf_solution/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/dynamic_secrets.tf b/landingzones/caf_solution/dynamic_secrets.tf new file mode 100644 index 000000000..a822cb004 --- /dev/null +++ b/landingzones/caf_solution/dynamic_secrets.tf @@ -0,0 +1,10 @@ +module "dynamic_keyvault_secrets" { + source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" + version = "5.3.0-preview2" + + for_each = try(var.dynamic_keyvault_secrets, {}) + + settings = each.value + keyvault = module.solution.keyvaults[each.key] + objects = module.solution +} \ No newline at end of file diff --git a/landingzones/caf_solution/landingzone.tf b/landingzones/caf_solution/landingzone.tf new file mode 100644 index 000000000..521155de7 --- /dev/null +++ b/landingzones/caf_solution/landingzone.tf @@ -0,0 +1,44 @@ +module "solution" { + source = "aztfmod/caf/azurerm" + version = "5.3.0-preview2" + + azuread_api_permissions = var.azuread_api_permissions + azuread_apps = var.azuread_apps + azuread_groups = var.azuread_groups + azuread_roles = var.azuread_roles + azuread_users = var.azuread_users + compute = var.compute + current_landingzone_key = var.landingzone.key + custom_role_definitions = var.custom_role_definitions + database = var.database + event_hub_namespaces = var.event_hub_namespaces + global_settings = local.global_settings + keyvault_access_policies = var.keyvault_access_policies + keyvault_certificate_issuers = var.keyvault_certificate_issuers + keyvaults = var.keyvaults + log_analytics = var.log_analytics + logged_aad_app_objectId = var.logged_aad_app_objectId + logged_user_objectId = var.logged_user_objectId + managed_identities = var.managed_identities + networking = var.networking + remote_objects = local.remote_objects + resource_groups = var.resource_groups + role_mapping = var.role_mapping + security = var.security + shared_services = var.shared_services + storage_accounts = var.storage_accounts + subscription_billing_role_assignments = var.subscription_billing_role_assignments + subscriptions = var.subscriptions + tags = var.tags + tenant_id = var.tenant_id + tfstates = var.tfstates + user_type = var.user_type + webapp = var.webapp + + diagnostics = { + diagnostic_event_hub_namespaces = try(local.diagnostics.diagnostic_event_hub_namespaces, var.diagnostic_event_hub_namespaces) + diagnostic_log_analytics = try(local.diagnostics.diagnostic_log_analytics, var.diagnostic_log_analytics) + diagnostic_storage_accounts = try(local.diagnostics.diagnostic_storage_accounts, var.diagnostic_storage_accounts) + } + +} diff --git a/landingzones/caf_solution/local.remote.tf b/landingzones/caf_solution/local.remote.tf new file mode 100644 index 000000000..6d76fb1ff --- /dev/null +++ b/landingzones/caf_solution/local.remote.tf @@ -0,0 +1,100 @@ +locals { + remote = { + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) + } + app_service_environments = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_service_environments, {})) + } + app_service_plans = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_service_plans, {})) + } + app_services = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_services, {})) + } + application_gateway_applications = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].application_gateway_applications, {})) + } + application_gateways = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].application_gateways, {})) + } + availability_sets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].availability_sets, {})) + } + azuread_applications = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azuread_applications, {})) + } + azuread_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azuread_groups, {})) + } + azuread_users = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azuread_users, {})) + } + azurerm_firewalls = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azurerm_firewalls, {})) + } + container_registry = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].container_registry, {})) + } + event_hub_namespaces = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].event_hub_namespaces, {})) + } + front_door_waf_policies = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].front_door_waf_policies, {})) + } + keyvaults = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].keyvaults, {})) + } + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) + } + mssql_databases = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_databases, {})) + } + mssql_elastic_pools = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_elastic_pools, {})) + } + mssql_managed_databases = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_managed_databases, {})) + } + mssql_managed_instances = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_managed_instances, {})) + } + mssql_servers = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_servers, {})) + } + mysql_servers = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mysql_servers, {})) + } + network_watchers = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].network_watchers, {})) + } + postgresql_servers = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].postgresql_servers, {})) + } + private_dns = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].private_dns, {})) + } + proximity_placement_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].proximity_placement_groups, {})) + } + public_ip_addresses = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].public_ip_addresses, {})) + } + recovery_vaults = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].recovery_vaults, {})) + } + resource_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].resource_groups, {})) + } + storage_accounts = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].storage_accounts, {})) + } + synapse_workspaces = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].synapse_workspaces, {})) + } + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/local.remote_objects.tf b/landingzones/caf_solution/local.remote_objects.tf new file mode 100644 index 000000000..8863c7ff0 --- /dev/null +++ b/landingzones/caf_solution/local.remote_objects.tf @@ -0,0 +1,36 @@ +locals { + remote_objects = { + aks_clusters = local.remote.aks_clusters + app_service_environments = local.remote.app_service_environments + app_service_plans = local.remote.app_service_plans + app_services = local.remote.app_services + application_gateway_applications = local.remote.application_gateway_applications + application_gateways = local.remote.application_gateways + availability_sets = local.remote.availability_sets + azuread_applications = local.remote.azuread_applications + azuread_groups = local.remote.azuread_groups + azuread_users = local.remote.azuread_users + azurerm_firewalls = local.remote.azurerm_firewalls + container_registry = local.remote.container_registry + event_hub_namespaces = local.remote.event_hub_namespaces + front_door_waf_policies = local.remote.front_door_waf_policies + keyvaults = local.remote.keyvaults + managed_identities = local.remote.managed_identities + mssql_databases = local.remote.mssql_databases + mssql_elastic_pools = local.remote.mssql_elastic_pools + mssql_managed_databases = local.remote.mssql_managed_databases + mssql_managed_instances = local.remote.mssql_managed_instances + mssql_servers = local.remote.mssql_servers + mysql_servers = local.remote.mysql_servers + network_watchers = local.remote.network_watchers + postgresql_servers = local.remote.postgresql_servers + private_dns = local.remote.private_dns + proximity_placement_groups = local.remote.proximity_placement_groups + public_ip_addresses = local.remote.public_ip_addresses + recovery_vaults = local.remote.recovery_vaults + resource_groups = local.remote.resource_groups + storage_accounts = local.remote.storage_accounts + synapse_workspaces = local.remote.synapse_workspaces + vnets = local.remote.vnets + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/locals.remote_tfstates.tf b/landingzones/caf_solution/locals.remote_tfstates.tf new file mode 100644 index 000000000..e05465330 --- /dev/null +++ b/landingzones/caf_solution/locals.remote_tfstates.tf @@ -0,0 +1,45 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = try(each.value.workspace, local.landingzone[try(each.value.level, "current")].container_name) + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + + diagnostics = { + diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.log_analytics + event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.event_hub_namespaces + } + +} diff --git a/landingzones/caf_solution/main.tf b/landingzones/caf_solution/main.tf new file mode 100644 index 000000000..909659c2d --- /dev/null +++ b/landingzones/caf_solution/main.tf @@ -0,0 +1,66 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.50" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.4.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + tls = { + source = "hashicorp/tls" + version = "~> 2.2.0" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "~>1.2.0" + } + } + required_version = ">= 0.13" +} + + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + + +locals { + + # Update the tfstates map + tfstates = merge( + map(var.landingzone.key, + map( + "storage_account_name", var.tfstate_storage_account_name, + "container_name", var.tfstate_container_name, + "resource_group_name", var.tfstate_resource_group_name, + "key", var.tfstate_key, + "level", var.landingzone.level, + "tenant_id", var.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + , + data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates + ) + +} \ No newline at end of file diff --git a/landingzones/caf_solution/modules/databricks/cluster.tf b/landingzones/caf_solution/modules/databricks/cluster.tf new file mode 100644 index 000000000..25310d783 --- /dev/null +++ b/landingzones/caf_solution/modules/databricks/cluster.tf @@ -0,0 +1,17 @@ +resource "databricks_cluster" "cluster" { + cluster_name = var.settings.name + spark_version = var.settings.spark_version + node_type_id = var.settings.node_type_id + autotermination_minutes = var.settings.autotermination_minutes + + dynamic "autoscale" { + for_each = try(var.settings.autoscale, null) == null ? [] : [1] + + content { + min_workers = try(var.settings.autoscale.min_workers, null) + max_workers = try(var.settings.autoscale.max_workers, null) + } + } + + +} \ No newline at end of file diff --git a/landingzones/caf_solution/modules/databricks/instance_pool.tf b/landingzones/caf_solution/modules/databricks/instance_pool.tf new file mode 100644 index 000000000..e69de29bb diff --git a/landingzones/caf_solution/modules/databricks/main.tf b/landingzones/caf_solution/modules/databricks/main.tf new file mode 100644 index 000000000..8993136bd --- /dev/null +++ b/landingzones/caf_solution/modules/databricks/main.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + databricks = { + source = "databrickslabs/databricks" + } + } + required_version = ">= 0.13" +} + diff --git a/landingzones/caf_solution/modules/databricks/output.tf b/landingzones/caf_solution/modules/databricks/output.tf new file mode 100644 index 000000000..d6bc7bc48 --- /dev/null +++ b/landingzones/caf_solution/modules/databricks/output.tf @@ -0,0 +1,7 @@ +output "cluster" { + value = { + id = databricks_cluster.cluster.id + default_tags = databricks_cluster.cluster.default_tags + state = databricks_cluster.cluster.state + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/modules/databricks/variables.tf b/landingzones/caf_solution/modules/databricks/variables.tf new file mode 100644 index 000000000..719f36726 --- /dev/null +++ b/landingzones/caf_solution/modules/databricks/variables.tf @@ -0,0 +1,4 @@ +variable "azure_workspace_resource_id" { + default = {} +} +variable "settings" {} \ No newline at end of file diff --git a/landingzones/caf_solution/output.tf b/landingzones/caf_solution/output.tf new file mode 100644 index 000000000..6c2f8c16d --- /dev/null +++ b/landingzones/caf_solution/output.tf @@ -0,0 +1,16 @@ +output "objects" { + value = tomap( + { + (var.landingzone.key) = { + for key, value in module.solution : key => value + if try(value, {}) != {} + } + } + ) + sensitive = true +} + +output "tfstates" { + value = local.tfstates + sensitive = true +} diff --git a/landingzones/caf_solution/readme.md b/landingzones/caf_solution/readme.md new file mode 100644 index 000000000..48f6c0333 --- /dev/null +++ b/landingzones/caf_solution/readme.md @@ -0,0 +1,22 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Solutions + +The landing zones solutions provide the underlying infrastructure to support your applications. The following are solutions accelerator ready to be deployed into your environment. They would require some review to match your operating model. + +* App Services (including App Service Environment) +* Azure Kubernetes Service (AKS) +* Azure Databricks +* Azure SQL Database +* Azure Application Gateway +* Azure Redis Cache +* Azure Keyvault +* Azure Virtual Machine +* Azure Machine Learning +* Azure Synapse + +Solutions landing zone operates at **level 3**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +## Deploying solutions + +Solution examples are available in the CAF Landing zones Starter repo: https://github.com/Azure/caf-terraform-landingzones-starter diff --git a/landingzones/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars b/landingzones/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars new file mode 100644 index 000000000..9340de718 --- /dev/null +++ b/landingzones/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars @@ -0,0 +1,12 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "caf_foundations" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars b/landingzones/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars new file mode 100644 index 000000000..7269553e2 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars @@ -0,0 +1,62 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "foundations" + level = "level2" + key = "networking_hub" + tfstates = { + foundations = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + } +} + +resource_groups = { + vnet_hub_re1 = { + name = "vnet-hub-re1" + region = "region1" + } +} + +vnets = { + hub_re1 = { + resource_group_key = "vnet_hub_re1" + region = "region1" + vnet = { + name = "hub-re1" + address_space = ["100.64.100.0/22"] + } + specialsubnets = { + GatewaySubnet = { + name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway + cidr = ["100.64.100.0/27"] + } + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["100.64.101.0/26"] + } + } + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["100.64.101.64/26"] + nsg_key = "azure_bastion_nsg" + } + jumpbox = { + name = "jumpbox" + cidr = ["100.64.102.0/27"] + nsg_key = "jumpbox" + } + private_endpoints = { + name = "private_endpoints" + cidr = ["100.64.103.128/25"] + enforce_private_link_endpoint_network_policies = true + } + } + } + +} diff --git a/landingzones/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars b/landingzones/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars new file mode 100644 index 000000000..232a5432d --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars @@ -0,0 +1,327 @@ +# +# Definition of the networking security groups +# +network_security_group_definition = { + # This entry is applied to all subnets with no NSG defined + empty_nsg = { + } + + azure_bastion_nsg = { + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } + + application_gateway = { + nsg = [ + { + name = "Inbound-HTTP", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "80-82" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "Inbound-HTTPs", + priority = "130" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "Inbound-AGW", + priority = "140" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "65200-65535" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + ] + } + + api_management = { + nsg = [ + { + name = "Inbound-APIM", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3443" + source_address_prefix = "ApiManagement" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Inbound-Redis", + priority = "110" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "6381-6383" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Inbound-LoadBalancer", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "*" + source_address_prefix = "AzureLoadBalancer" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Outbound-StorageHttp", + priority = "100" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "80" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-StorageHttps", + priority = "110" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-AADHttp", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "80" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureActiveDirectory" + }, + { + name = "Outbound-AADHttps", + priority = "130" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureActiveDirectory" + }, + { + name = "Outbound-SQL", + priority = "140" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "1433" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "SQL" + }, + { + name = "Outbound-EventHub", + priority = "150" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "5671-5672" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "EventHub" + }, + { + name = "Outbound-EventHubHttps", + priority = "160" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "EventHub" + }, + { + name = "Outbound-FileShareGit", + priority = "170" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "445" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-Health", + priority = "180" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "1886" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-Monitor", + priority = "190" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureMonitor" + }, + { + name = "Outbound-MoSMTP1itor", + priority = "200" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "25" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-SMTP2", + priority = "210" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "587" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-SMTP3", + priority = "220" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "25028" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-Redis", + priority = "230" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "6381-6383" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + + jumpbox = { + nsg = [ + { + name = "ssh-inbound-22", + priority = "200" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + +} + diff --git a/landingzones/caf_solution/scenario/networking/100-single-region-hub/readme.md b/landingzones/caf_solution/scenario/networking/100-single-region-hub/readme.md new file mode 100644 index 000000000..624dfff6b --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/100-single-region-hub/readme.md @@ -0,0 +1,45 @@ +# CAF landing zones for Terraform - Single region hub virtual network + +The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. + +* Hub and spoke +* Virtual WAN +* Application DMZ scenario +* Any custom network topology based on virtual networks or virtual WAN +* Library of network security groups definition + +Networking landing zone operates at **level 2**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). + +## Architecture diagram + +This example allows you to deploy the following topology: + +![100-example](../../documentation/img/100-single-region-hub.png) + + +## Components deployed by this example + +| Component | Type of resource | Purpose | +|----------------------------------------------------------------------------------|-------------------------|------------------------------------------------------------------| +| vnet-hub-re1 | Resource group | resource group to host the virtual network | +| vnet_hub_re1 | Virtual network | virtual network used as a hub | +| GatewaySubnet,AzureFirewallSubnet,AzureBastionSubnet, jumpbox, private_endpoints | Virtual Subnets | virtual subnets | +| azure_bastion_nsg, empty_nsg, application_gateway, api_management, jumpbox | Network security groups | network security groups that can be attached to virtual subnets. | + + +## Customizing this example + +Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. + +## Deploying this example + +Once you have picked a scenario for test, you can deploy it using: + +```bash +rover -lz /tf/caf/landingzones/caf_networking \ +-level level2 \ +-var-folder /tf/caf/landingzones/caf_networking/scenario/100-single-region-hub \ +-a apply +``` diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars new file mode 100644 index 000000000..26f860340 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars @@ -0,0 +1,27 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "foundations" + level = "level2" + key = "networking_hub" + tfstates = { + foundations = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + } +} + +resource_groups = { + vnet_hub_re1 = { + name = "vnet-hub-re1" + region = "region1" + } + vnet_hub_re2 = { + name = "vnet-hub-re2" + region = "region2" + } +} diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars new file mode 100644 index 000000000..6352fec33 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars @@ -0,0 +1,344 @@ +# +# Definition of the networking security groups +# +network_security_group_definition = { + # This entry is applied to all subnets with no NSG defined + empty_nsg = { + } + + azure_bastion_nsg = { + + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } + + application_gateway = { + + nsg = [ + { + name = "Inbound-HTTP", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "80-82" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "Inbound-HTTPs", + priority = "130" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "Inbound-AGW", + priority = "140" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "65200-65535" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + ] + } + + api_management = { + + nsg = [ + { + name = "Inbound-APIM", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3443" + source_address_prefix = "ApiManagement" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Inbound-Redis", + priority = "110" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "6381-6383" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Inbound-LoadBalancer", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "*" + source_address_prefix = "AzureLoadBalancer" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Outbound-StorageHttp", + priority = "100" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "80" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-StorageHttps", + priority = "110" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-AADHttp", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "80" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureActiveDirectory" + }, + { + name = "Outbound-AADHttps", + priority = "130" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureActiveDirectory" + }, + { + name = "Outbound-SQL", + priority = "140" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "1433" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "SQL" + }, + { + name = "Outbound-EventHub", + priority = "150" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "5671-5672" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "EventHub" + }, + { + name = "Outbound-EventHubHttps", + priority = "160" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "EventHub" + }, + { + name = "Outbound-FileShareGit", + priority = "170" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "445" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-Health", + priority = "180" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "1886" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-Monitor", + priority = "190" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureMonitor" + }, + { + name = "Outbound-MoSMTP1itor", + priority = "200" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "25" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-SMTP2", + priority = "210" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "587" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-SMTP3", + priority = "220" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "25028" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-Redis", + priority = "230" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "6381-6383" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + + jumpbox = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "ssh-inbound-22", + priority = "200" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + +} diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars new file mode 100644 index 000000000..40a1eb491 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars @@ -0,0 +1,31 @@ + +vnet_peerings = { + hub_re1_TO_hub_re2 = { + name = "hub_re1_TO_hub_re2" + from = { + vnet_key = "hub_re1" + } + to = { + vnet_key = "hub_re2" + } + allow_virtual_network_access = true + allow_forwarded_traffic = false + allow_gateway_transit = false + use_remote_gateways = false + } + + hub_re2_TO_hub_re1 = { + name = "hub_re2_TO_hub_re1" + from = { + vnet_key = "hub_re2" + } + to = { + vnet_key = "hub_re1" + } + allow_virtual_network_access = true + allow_forwarded_traffic = false + allow_gateway_transit = false + use_remote_gateways = false + } + +} diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/readme.md b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/readme.md new file mode 100644 index 000000000..8d7ad2ac7 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/readme.md @@ -0,0 +1,50 @@ +# CAF landing zones for Terraform - Multi-region hub with global peering + +This scenario deploys the networking hub across multiple regions + +The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. + +* Hub and spoke +* Virtual WAN +* Application DMZ scenario +* Any custom network topology based on virtual networks or virtual WAN +* Library of network security groups definition + +Networking landing zone operates at **level 2**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). + +## Architecture diagram + +This example allows you to deploy the following topology: + +![101-example](../../documentation/img/101-multi-region-hub.png) + + +## Components deployed by this example + +| Component | Type of resource | Purpose | +|----------------------------------------------------------------------------------|-------------------------|--------------------------------------------------------------------------------------------| +| vnet-hub-re1, vnet-hub-re2 | Resource group | resource group to host the virtual network | +| vnet_hub_re1, vnet-hub-re2 | Virtual network | virtual network used as a hub | +| GatewaySubnet,AzureFirewallSubnet,AzureBastionSubnet, jumpbox, private_endpoints | Virtual Subnets | virtual subnets | +| azure_bastion_nsg, empty_nsg, application_gateway, api_management, jumpbox | Network security groups | network security groups that can be attached to virtual subnets. | +| hub_re1_TO_hub_re2, and hub_re2_TO_hub_re1 | Virtual network peering | Peering between vnet_hub_re1 and vnet-hub-re2 | +| bastion-re1-pip1, bastion-re2-pip1 | Public IP address | Public IP address to be used in vnet_hub_re1 and vnet-hub-re2, to be used by Azure Bastion | +| bastion-re1, bastion-re2 | Azure Bastion | Azure Bastion host in order to access the virtual network. | + + +## Customizing this example + +Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. + +## Deploying this example + +Once you have picked a scenario for test, you can deploy it using: + +```bash +rover -lz /tf/caf/landingzones/caf_networking \ +-level level2 \ +-var-folder /tf/caf/landingzones/caf_networking/scenario/101-multi-region-hub \ +-a apply +``` diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars new file mode 100644 index 000000000..67af89832 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars @@ -0,0 +1,78 @@ + +vnets = { + hub_re1 = { + resource_group_key = "vnet_hub_re1" + region = "region1" + vnet = { + name = "hub-re1" + address_space = ["100.64.100.0/22"] + } + specialsubnets = { + GatewaySubnet = { + name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway + cidr = ["100.64.100.0/27"] + } + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["100.64.101.0/26"] + } + } + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["100.64.101.64/26"] + nsg_key = "azure_bastion_nsg" + } + jumpbox = { + name = "jumpbox" + cidr = ["100.64.102.0/27"] + nsg_key = "jumpbox" + } + private_endpoints = { + name = "private_endpoints" + cidr = ["100.64.103.128/25"] + enforce_private_link_endpoint_network_policies = true + } + } + + } + + hub_re2 = { + resource_group_key = "vnet_hub_re2" + region = "region2" + vnet = { + name = "hub-re2" + address_space = ["100.65.100.0/22"] + } + specialsubnets = { + GatewaySubnet = { + name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway + cidr = ["100.65.100.0/27"] + } + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["100.65.101.0/26"] + } + } + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["100.65.101.64/26"] + nsg_key = "azure_bastion_nsg" + } + jumpbox = { + name = "jumpbox" + cidr = ["100.65.102.0/27"] + nsg_key = "jumpbox" + } + private_endpoints = { + name = "private_endpoints" + cidr = ["100.65.103.128/25"] + enforce_private_link_endpoint_network_policies = true + } + } + + } + + +} diff --git a/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars b/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars new file mode 100644 index 000000000..b32be7ef7 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars @@ -0,0 +1,155 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "foundations" + level = "level2" + key = "networking_hub" + tfstates = { + foundations = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + } +} + +resource_groups = { + vnet_hub_region1 = { + name = "vnet-hub-re1" + } + vnet_spoke_region1 = { + name = "vnet-spoke-re1" + } +} + +vnets = { + hub_re1 = { + resource_group_key = "vnet_hub_region1" + vnet = { + name = "hub-re1" + address_space = ["10.10.100.0/24"] + } + specialsubnets = { + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["10.10.100.192/26"] + } + } + subnets = { + jumphost = { + name = "jumphost" + cidr = ["10.10.100.0/25"] + nsg_key = "jumphost" + } + } + } + + spoke_re1 = { + resource_group_key = "vnet_spoke_region1" + vnet = { + name = "spoke-re1" + address_space = ["10.11.100.0/24"] + } + specialsubnets = {} + subnets = { + jumphost = { + name = "jumphost" + cidr = ["10.11.100.0/25"] + nsg_key = "jumphost" + } + webapp1 = { + name = "webapp-presentation-tier" + cidr = ["10.11.100.128/25"] + } + } + } +} + +azurerm_firewalls = { + # Southeastasia firewall (do not change the key when created) + fw_re1 = { + region = "region1" + name = "azfwre1" + resource_group_key = "vnet_hub_region1" + vnet_key = "hub_re1" + public_ip_key = "az_fw_pip" + + } + +} + +public_ip_addresses = { + + az_fw_pip = { + name = "az_fw_re1_pip1" + region = "region1" + resource_group_key = "vnet_hub_region1" + sku = "Standard" + allocation_method = "Static" + ip_version = "IPv4" + idle_timeout_in_minutes = "4" + + } +} + +route_tables = { + default_to_firewall_re1 = { + name = "default_to_firewall_re1" + resource_group_key = "vnet_spoke_region1" + } +} + +azurerm_routes = { + default_to_firewall_rg1 = { + name = "0-0-0-0-through-firewall-re1" + resource_group_key = "vnet_spoke_region1" + route_table_key = "default_to_firewall_re1" + address_prefix = "0.0.0.0/0" + next_hop_type = "VirtualAppliance" + + # To be set when next_hop_type = "VirtualAppliance" + private_ip_keys = { + azurerm_firewall = { + key = "fw_re1" + interface_index = 0 + } + # virtual_machine = { + # key = "" + # nic_key = "" + # } + } + } +} + +vnet_peerings = { + hub-re1_TO_spoke-re1 = { + name = "hub-re1_TO_spoke-re1" + from = { + vnet_key = "hub_re1" + } + to = { + vnet_key = "spoke_re1" + } + allow_virtual_network_access = true + allow_forwarded_traffic = true + allow_gateway_transit = false + use_remote_gateways = false + } + + spoke-re1_TO_hub-re1 = { + name = "hub_re2_TO_hub_re1" + from = { + vnet_key = "spoke_re1" + } + to = { + vnet_key = "hub_re1" + } + allow_virtual_network_access = true + allow_forwarded_traffic = false + allow_gateway_transit = false + use_remote_gateways = false + } + +} diff --git a/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars b/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars new file mode 100644 index 000000000..40dfc522a --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars @@ -0,0 +1,122 @@ +# +# Definition of the networking security groups +# +network_security_group_definition = { + azure_bastion_nsg = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } + + jumphost = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "ssh-inbound-22", + priority = "200" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + +} diff --git a/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/readme.md b/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/readme.md new file mode 100644 index 000000000..b2820fb78 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/readme.md @@ -0,0 +1,52 @@ +# CAF landing zones for Terraform - Secure Hub and Spoke with Azure Firewall + +This scenario deploys the networking hub across multiple regions + +The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. + +* Hub and spoke +* Virtual WAN +* Application DMZ scenario +* Any custom network topology based on virtual networks or virtual WAN +* Library of network security groups definition + +Networking landing zone operates at **level 2**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). + +## Architecture diagram + +This example allows you to deploy the following topology: + +![101-example](../../documentation/img/105-hub-and-spoke.png) + + +## Components deployed by this example + +| Component | Type of resource | Purpose | +|--|--|--| +| vnet-hub-re1, vnet-spoke-re2 | Resource group | resource group to host the virtual network | +| hub-re1, spoke-re1 | Virtual network | virtual networks for hub and spokeshub | +| AzureFirewallSubnet,jumphost, webapp-presentation-tier | Virtual Subnets | virtual subnets | +| azure_bastion_nsg, , jumphost_nsg | Network security groups | network security groups that can be attached to virtual subnets. | +| hub_re1_TO_spoke_re1, and spoke_re1_TO_hub_re1 | Virtual network peering | Peering between hub-re1 and spoke-re1 | +| azfwre1 | Azure Firewall | Azure Firewall in Hub network | +| az_fw_re1_pip1 | Public IP address | Public IP address used by Azure Firewall | +| default_to_firewall_re1 | Route table | Route table to host route entries | +| 0-0-0-0-through-firewall-re1 | Route table entry | Route all traffic to Azure Firewall in hub | + + +## Customizing this example + +Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. + +## Deploying this example + +Once you have picked a scenario for test, you can deploy it using: + +```bash +rover -lz /tf/caf/landingzones/caf_networking \ +-level level2 \ +-var-folder /tf/caf/landingzones/caf_networking/scenario/105-hub-and-spoke \ +-a apply +``` diff --git a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars new file mode 100644 index 000000000..ea7eb6d12 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars @@ -0,0 +1,71 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "foundations" + level = "level2" + key = "networking_hub" + tfstates = { + foundations = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + } +} + +resource_groups = { + vnet_re1 = { + name = "vnet-spoke-re1" + region = "region1" + } + hub_re1 = { + name = "vnet-hub-re1" + region = "region1" + } +} + +vnets = { + vnet_re1 = { + resource_group_key = "vnet_re1" + region = "region1" + vnet = { + name = "hub-re1" + address_space = ["10.10.100.0/24"] + } + specialsubnets = { + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["10.10.100.192/26"] + } + } + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["10.10.100.160/27"] + nsg_key = "azure_bastion_nsg" + } + } + } +} + +vhub_peerings = { + # Establish the peering with Virtual Hubs + hub_rg1-TO-vnet_rg1 = { + vhub = { + virtual_wan_key = "vwan_re1" + virtual_hub_key = "hub_re1" + } + vnet = { + # If the virtual network is stored in another another landing zone, use the following attributes to refer the state file: + # lz_key = "networking" + # output_key = "vnets" + vnet_key = "vnet_re1" + } + name = "vhub_peering_hub_sg" + hub_to_virtual_network_traffic_allowed = true + virtual_network_to_hub_gateways_traffic_allowed = true + internet_security_enabled = true + } +} diff --git a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars new file mode 100644 index 000000000..3d3d06e3a --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars @@ -0,0 +1,104 @@ +network_security_group_definition = { + empty_nsg = { + + nsg = [] + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } + + azure_bastion_nsg = { + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } +} \ No newline at end of file diff --git a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md new file mode 100644 index 000000000..eb0b2487b --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md @@ -0,0 +1,47 @@ +# CAF landing zones for Terraform - Azure Virtual WAN with Firewall manager + +The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. + +* Hub and spoke +* Virtual WAN +* Application DMZ scenario +* Any custom network topology based on virtual networks or virtual WAN +* Library of network security groups definition + +Networking landing zone operates at **level 2**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). + +## Architecture diagram + +This example allows you to deploy the following topology: + +![virtual_wan_lz](../../documentation/img/106-hub-virtual-wan-firewall.png) + + +## Components deployed by this example + +| Component | Type of resource | Purpose | +|------------------------------|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| vnet-spoke-re1, vnet-hub-re1 | Resource group | resource group to host the virtual network and virtual WAN | +| vnet_re1 | Virtual network with subnets, network security groups | virtual network used as a spoke, attached to the virtual hub from Azure Virtual WAN | +| contosovWAN-re1 | Virtual WAN | virtual WAN infrastructure | +| hub-re1, hub-re2 | Virtual Hubs | virtual hubs to be deployed in region, the hubs can be configured to deploy point-to-site connectivity, site-to-site connectivity or Express Route connectivity. | +| hub_fw_re1, hub_fw_re2 | Azure Firewall | traffic filtering between hubs and outside | +| hub_rg1-TO-vnet_rg1 | Virtual network and Virtual Hubs peering objects | network peering between virtual hubs and virtual network | + + +## Customizing this example + +Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. + +## Deploying this example + +Once you have picked a scenario for test, you can deploy it using: + +```bash +rover -lz /tf/caf/landingzones/caf_networking \ +-level level2 \ +-var-folder /tf/caf/landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall \ +-a apply +``` diff --git a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars new file mode 100644 index 000000000..547e62450 --- /dev/null +++ b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars @@ -0,0 +1,84 @@ +virtual_wans = { + vwan_re1 = { + resource_group_key = "hub_re1" + name = "contosovWAN-re1" + region = "region1" + + hubs = { + hub_re1 = { + hub_name = "hub-re1" + region = "region1" + hub_address_prefix = "10.0.3.0/24" + deploy_firewall = true + firewall_name = "hub-fw-re1" + firewall_resource_group_key = "hub_re1" + deploy_p2s = false + p2s_config = { + name = "caf-sea-vpn-p2s" + scale_unit = 2 + connection_configuration = { + name = "client-connections" + vpn_client_address_pool = { + address_prefixes = ["192.168.0.0/24"] + } + } + server_config = { + vpn_authentication_types = ["Certificate"] + client_root_certificate = { + name = "DigiCert-Federated-ID-Root-CA" + public_cert_data = < Date: Fri, 26 Mar 2021 11:34:17 +0000 Subject: [PATCH 02/38] Update to preview3 branch --- landingzones/caf_launchpad/dynamic_secrets.tf | 3 +-- landingzones/caf_launchpad/landingzone.tf | 3 +-- landingzones/caf_solution/dynamic_secrets.tf | 3 +-- landingzones/caf_solution/landingzone.tf | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/landingzones/caf_launchpad/dynamic_secrets.tf b/landingzones/caf_launchpad/dynamic_secrets.tf index c288df262..3b78eb1c8 100644 --- a/landingzones/caf_launchpad/dynamic_secrets.tf +++ b/landingzones/caf_launchpad/dynamic_secrets.tf @@ -1,7 +1,6 @@ module "dynamic_keyvault_secrets" { - source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" - version = "5.3.0-preview2" + source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=5.3.0_preview" for_each = try(var.dynamic_keyvault_secrets, {}) diff --git a/landingzones/caf_launchpad/landingzone.tf b/landingzones/caf_launchpad/landingzone.tf index c2657d989..fe36988d8 100644 --- a/landingzones/caf_launchpad/landingzone.tf +++ b/landingzones/caf_launchpad/landingzone.tf @@ -1,6 +1,5 @@ module "launchpad" { - source = "aztfmod/caf/azurerm" - version = "5.3.0-preview2" + source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git?ref=5.3.0_preview" azuread_api_permissions = var.azuread_api_permissions azuread_apps = var.azuread_apps diff --git a/landingzones/caf_solution/dynamic_secrets.tf b/landingzones/caf_solution/dynamic_secrets.tf index a822cb004..fde3df0e0 100644 --- a/landingzones/caf_solution/dynamic_secrets.tf +++ b/landingzones/caf_solution/dynamic_secrets.tf @@ -1,6 +1,5 @@ module "dynamic_keyvault_secrets" { - source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" - version = "5.3.0-preview2" + source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=5.3.0_preview" for_each = try(var.dynamic_keyvault_secrets, {}) diff --git a/landingzones/caf_solution/landingzone.tf b/landingzones/caf_solution/landingzone.tf index 521155de7..bfa7422a6 100644 --- a/landingzones/caf_solution/landingzone.tf +++ b/landingzones/caf_solution/landingzone.tf @@ -1,6 +1,5 @@ module "solution" { - source = "aztfmod/caf/azurerm" - version = "5.3.0-preview2" + source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git?ref=5.3.0_preview" azuread_api_permissions = var.azuread_api_permissions azuread_apps = var.azuread_apps From 4b96b88b5299b5aab4ad9f394c141fb53e72c769 Mon Sep 17 00:00:00 2001 From: lolorol Date: Fri, 26 Mar 2021 11:44:23 +0000 Subject: [PATCH 03/38] Fix duplicate variable --- landingzones/caf_solution/variables.tf | 4 ---- 1 file changed, 4 deletions(-) diff --git a/landingzones/caf_solution/variables.tf b/landingzones/caf_solution/variables.tf index 0c22d9563..b92fb1ac4 100644 --- a/landingzones/caf_solution/variables.tf +++ b/landingzones/caf_solution/variables.tf @@ -279,10 +279,6 @@ variable "event_hubs" { default = {} } -variable "automations" { - default = {} -} - variable "event_hub_auth_rules" { default = {} } From 436c34154536a04f84fb48bb58e953fa359b8167 Mon Sep 17 00:00:00 2001 From: lolorol Date: Sat, 27 Mar 2021 06:53:20 +0000 Subject: [PATCH 04/38] Move to root folder --- .../caf_launchpad/.terraform.lock.hcl | 72 -- landingzones/caf_launchpad/backend.azurerm | 4 - .../documentation/img/launchpad-100.PNG | Bin 143702 -> 0 bytes .../documentation/img/launchpad-200.png | Bin 232335 -> 0 bytes .../documentation/img/launchpad_workflow.png | Bin 40149 -> 0 bytes .../caf_launchpad/documentation/variables.md | 41 - landingzones/caf_launchpad/dynamic_secrets.tf | 10 - landingzones/caf_launchpad/landingzone.tf | 53 -- landingzones/caf_launchpad/main.tf | 88 -- landingzones/caf_launchpad/output.tf | 16 - landingzones/caf_launchpad/readme.md | 206 ----- .../caf_launchpad/scenario/100/README.md | 44 - .../scenario/100/configuration.tfvars | 68 -- .../scenario/100/dynamic_secrets.tfvars | 114 --- .../scenario/100/iam_role_mapping.tfvars | 47 -- .../scenario/100/keyvaults.tfvars | 99 --- .../scenario/100/storage_accounts.tfvars | 102 --- .../caf_launchpad/scenario/200/compute.tfvars | 100 --- .../scenario/200/configuration.tfvars | 100 --- .../diagnostic_event_hub_namespaces.tfvars | 20 - .../200/diagnostic_log_analytics.tfvars | 48 -- .../200/diagnostic_storage_accounts.tfvars | 64 -- .../200/diagnostics_definition.tfvars | 274 ------- .../200/diagnostics_destinations.tfvars | 31 - .../scenario/200/dynamic_secrets.tfvars | 152 ---- .../scenario/200/iam_azuread.tfvars | 184 ----- .../200/iam_azuread_api_permissions.tfvars | 43 - .../scenario/200/iam_custom_roles.tfvars | 76 -- .../scenario/200/iam_keyvault_policies.tfvars | 114 --- .../200/iam_managed_identities.tfvars | 32 - .../scenario/200/iam_role_mapping.tfvars | 154 ---- .../scenario/200/keyvaults.tfvars | 204 ----- .../scenario/200/networking.tfvars | 110 --- .../200/networking_nsg_definition.tfvars | 141 ---- .../caf_launchpad/scenario/200/readme.md | 56 -- .../scenario/200/storage_accounts.tfvars | 101 --- .../scenario/200/subscriptions.tfvars | 20 - .../cloud-init-install-rover-tools.config | 49 -- landingzones/caf_launchpad/variables.tf | 211 ----- .../aad-pod-identity/aad-msi-binding.yaml | 16 - .../aad-pod-identity/aad_pod_identity.tf | 120 --- .../add-ons/aad-pod-identity/backend.azurerm | 4 - .../build/kustomization_build.tf | 16 - .../add-ons/aad-pod-identity/build/main.tf | 7 - .../aad-pod-identity/build/variables.tf | 2 - .../aad-pod-identity/local.remote_tfstates.tf | 54 -- .../add-ons/aad-pod-identity/main.tf | 17 - .../add-ons/aad-pod-identity/providers.tf | 32 - .../add-ons/aad-pod-identity/variables.tf | 36 - .../aks-pod-identity-assignment.tf | 58 -- .../aks-secure-baseline/backend.azurerm | 4 - .../aks-secure-baseline/kustomization.yaml | 5 - .../local.remote_tfstates.tf | 54 -- .../add-ons/aks-secure-baseline/main.tf | 17 - .../add-ons/aks-secure-baseline/providers.tf | 32 - .../aks-secure-baseline/secure-baseline.tf | 22 - .../add-ons/aks-secure-baseline/variables.tf | 36 - .../add-ons/aks_applications/app/main.tf | 7 - .../add-ons/aks_applications/app/module.tf | 48 -- .../add-ons/aks_applications/app/output.tf | 0 .../add-ons/aks_applications/app/variables.tf | 5 - .../add-ons/aks_applications/applications.tf | 27 - .../add-ons/aks_applications/backend.azurerm | 4 - .../locals.remote_tfstates.tf | 54 -- .../add-ons/aks_applications/main.tf | 75 -- .../add-ons/aks_applications/output.tf | 0 .../add-ons/aks_applications/variables.tf | 36 - .../caf_solution/add-ons/azure_devops/azdo.tf | 15 - .../add-ons/azure_devops/azdo_agent_pools.tf | 52 -- .../add-ons/azure_devops/azdo_pipelines.tf | 43 - .../azure_devops/azdo_service_endpoint.tf | 36 - .../azure_devops/azdo_variable_groups.tf | 39 - .../add-ons/azure_devops/backend.azurerm | 4 - .../documentation/images/pat_token.png | Bin 78143 -> 0 bytes .../azure_devops/locals.remote_tfstates.tf | 76 -- .../caf_solution/add-ons/azure_devops/main.tf | 69 -- .../add-ons/azure_devops/output.tf | 6 - .../add-ons/azure_devops/readme.md | 60 -- .../200-contoso_demo/azure_devops.tfvars | 232 ------ .../200-contoso_demo/configurations.tfvars | 123 --- .../200-contoso_demo/pipeline/rover.yaml | 70 -- .../add-ons/azure_devops/solution.tf | 36 - .../add-ons/azure_devops/variables.tf | 102 --- .../azure_devops_agent/backend.azurerm | 4 - .../azure_devops_agent/dynamic_secrets.tf | 11 - .../extensions/devops_selfhosted_agent.tf | 44 - .../extensions/variables.tf | 3 - .../locals.current_tfstates.tf | 74 -- .../add-ons/azure_devops_agent/main.tf | 69 -- .../add-ons/azure_devops_agent/output.tf | 34 - .../add-ons/azure_devops_agent/readme.md | 54 -- .../level0/configuration.tfvars | 64 -- .../200-contoso_demo/level0/keyvaults.tfvars | 28 - .../level0/storage_accounts.tfvars | 42 - .../level0/virtual_machines.tfvars | 79 -- .../level1/configuration.tfvars | 68 -- .../200-contoso_demo/level1/keyvaults.tfvars | 32 - .../level1/storage_accounts.tfvars | 42 - .../level1/virtual_machines.tfvars | 77 -- .../cloud-init-install-rover-tools.config | 117 --- .../scripts/devops_runtime_baremetal.sh | 109 --- .../scripts/devops_runtime_docker.sh | 29 - .../add-ons/azure_devops_agent/solution.tf | 37 - .../add-ons/azure_devops_agent/variables.tf | 102 --- .../vm_extention_devops_agent.tf | 37 - .../caf_solution/add-ons/caf_eslz/README.md | 44 - .../add-ons/caf_eslz/backend.azurerm | 4 - .../caf_solution/add-ons/caf_eslz/es_main.tf | 25 - .../caf_eslz/locals.remote_tfstates.tf | 46 -- .../caf_solution/add-ons/caf_eslz/main.tf | 18 - .../caf_solution/add-ons/caf_eslz/output.tf | 0 .../100/enterprise_scale_contoso_com.tfvars | 25 - .../200/enterprise_scale_contoso_com.tfvars | 45 - ...chetype_definition_es_management.tmpl.json | 12 - .../200/lib/archetype_definition_es_root.json | 13 - ...nt_es_allowed_resource-locations.tmpl.json | 28 - ..._allowed_resourcegroup-locations.tmpl.json | 28 - ...licy_assignment_es_deploy_asc_ce.tmpl.json | 28 - ...ignment_es_deploy_asc_monitoring.tmpl.json | 88 -- ...ssignment_es_deploy_asc_standard.tmpl.json | 21 - ...nment_es_deploy_diag_activitylog.tmpl.json | 25 - ...ment_es_deploy_diag_loganalytics.tmpl.json | 25 - ...icy_definition_es_deploy_asc_standard.json | 284 ------- .../add-ons/caf_eslz/variables.tf | 135 --- .../add-ons/databricks/backend.azurerm | 4 - .../add-ons/databricks/databricks.tf | 21 - .../databricks/locals.remote_tfstates.tf | 43 - .../caf_solution/add-ons/databricks/main.tf | 63 -- .../add-ons/databricks/variables.tf | 154 ---- .../add-ons/helm-charts/backend.azurerm | 4 - .../add-ons/helm-charts/charts.tf | 21 - .../helm-charts/local.remote_tfstates.tf | 49 -- .../caf_solution/add-ons/helm-charts/main.tf | 17 - .../add-ons/helm-charts/providers.tf | 39 - .../add-ons/helm-charts/variables.tf | 32 - .../terraform_cloud/example/tfc.tfvars | 25 - .../add-ons/terraform_cloud/main.tf | 51 -- .../add-ons/terraform_cloud/readme.md | 44 - .../terraform_cloud/terraform_cloud.tf | 83 -- .../add-ons/terraform_cloud/variables.tf | 85 -- landingzones/caf_solution/backend.azurerm | 4 - landingzones/caf_solution/dynamic_secrets.tf | 9 - landingzones/caf_solution/landingzone.tf | 43 - landingzones/caf_solution/local.remote.tf | 100 --- .../caf_solution/local.remote_objects.tf | 36 - .../caf_solution/locals.remote_tfstates.tf | 45 - landingzones/caf_solution/main.tf | 66 -- .../modules/databricks/cluster.tf | 17 - .../modules/databricks/instance_pool.tf | 0 .../caf_solution/modules/databricks/main.tf | 9 - .../caf_solution/modules/databricks/output.tf | 7 - .../modules/databricks/variables.tf | 4 - landingzones/caf_solution/output.tf | 16 - landingzones/caf_solution/readme.md | 22 - .../100-passthrough/landingzone.tfvars | 12 - .../configuration.tfvars | 62 -- .../network_security_group_definition.tfvars | 327 -------- .../100-single-region-hub/readme.md | 45 - .../101-multi-region-hub/configuration.tfvars | 27 - .../network_security_group_definition.tfvars | 344 -------- .../101-multi-region-hub/peering.tfvars | 31 - .../networking/101-multi-region-hub/readme.md | 50 -- .../virtual_networks.tfvars | 78 -- .../105-hub-and-spoke/configuration.tfvars | 155 ---- .../network_security_group_definition.tfvars | 122 --- .../networking/105-hub-and-spoke/readme.md | 52 -- .../configuration.tfvars | 71 -- .../network_security_group_definition.tfvars | 104 --- .../106-hub-virtual-wan-firewall/readme.md | 47 -- .../virtual_wan.tfvars | 84 -- .../configuration.tfvars | 612 -------------- .../201-multi-region-hub/configuration.tfvars | 767 ----------------- .../210-aks-private/configuration.tfvars | 772 ------------------ .../peerings/launchpad/configuration.tfvars | 41 - .../shared_services/100/configuration.tfvars | 140 ---- .../shared_services/200/configuration.tfvars | 156 ---- .../cloud-init-install-rover-tools.config | 119 --- .../caf_solution/scripts/grant_consent.sh | 28 - landingzones/caf_solution/variables.tf | 299 ------- 179 files changed, 12707 deletions(-) delete mode 100644 landingzones/caf_launchpad/.terraform.lock.hcl delete mode 100644 landingzones/caf_launchpad/backend.azurerm delete mode 100644 landingzones/caf_launchpad/documentation/img/launchpad-100.PNG delete mode 100644 landingzones/caf_launchpad/documentation/img/launchpad-200.png delete mode 100644 landingzones/caf_launchpad/documentation/img/launchpad_workflow.png delete mode 100644 landingzones/caf_launchpad/documentation/variables.md delete mode 100644 landingzones/caf_launchpad/dynamic_secrets.tf delete mode 100644 landingzones/caf_launchpad/landingzone.tf delete mode 100644 landingzones/caf_launchpad/main.tf delete mode 100644 landingzones/caf_launchpad/output.tf delete mode 100644 landingzones/caf_launchpad/readme.md delete mode 100644 landingzones/caf_launchpad/scenario/100/README.md delete mode 100644 landingzones/caf_launchpad/scenario/100/configuration.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/100/dynamic_secrets.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/100/iam_role_mapping.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/100/keyvaults.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/100/storage_accounts.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/compute.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/configuration.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/diagnostics_definition.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/diagnostics_destinations.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/dynamic_secrets.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/iam_azuread.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/iam_custom_roles.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/iam_managed_identities.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/iam_role_mapping.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/keyvaults.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/networking.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/networking_nsg_definition.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/readme.md delete mode 100644 landingzones/caf_launchpad/scenario/200/storage_accounts.tfvars delete mode 100644 landingzones/caf_launchpad/scenario/200/subscriptions.tfvars delete mode 100644 landingzones/caf_launchpad/scripts/cloud-init-install-rover-tools.config delete mode 100644 landingzones/caf_launchpad/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/backend.azurerm delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/build/main.tf delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/build/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/main.tf delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/providers.tf delete mode 100644 landingzones/caf_solution/add-ons/aad-pod-identity/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf delete mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/backend.azurerm delete mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml delete mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf delete mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/main.tf delete mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/providers.tf delete mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf delete mode 100644 landingzones/caf_solution/add-ons/aks-secure-baseline/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/app/main.tf delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/app/module.tf delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/app/output.tf delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/app/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/applications.tf delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/backend.azurerm delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/main.tf delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/output.tf delete mode 100644 landingzones/caf_solution/add-ons/aks_applications/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo_pipelines.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/backend.azurerm delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/documentation/images/pat_token.png delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/main.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/output.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/readme.md delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/solution.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/backend.azurerm delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/main.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/output.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/readme.md delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/solution.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/README.md delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/backend.azurerm delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/es_main.tf delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/main.tf delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/output.tf delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json delete mode 100644 landingzones/caf_solution/add-ons/caf_eslz/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/databricks/backend.azurerm delete mode 100644 landingzones/caf_solution/add-ons/databricks/databricks.tf delete mode 100644 landingzones/caf_solution/add-ons/databricks/locals.remote_tfstates.tf delete mode 100644 landingzones/caf_solution/add-ons/databricks/main.tf delete mode 100644 landingzones/caf_solution/add-ons/databricks/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/helm-charts/backend.azurerm delete mode 100644 landingzones/caf_solution/add-ons/helm-charts/charts.tf delete mode 100644 landingzones/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf delete mode 100644 landingzones/caf_solution/add-ons/helm-charts/main.tf delete mode 100644 landingzones/caf_solution/add-ons/helm-charts/providers.tf delete mode 100644 landingzones/caf_solution/add-ons/helm-charts/variables.tf delete mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars delete mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/main.tf delete mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/readme.md delete mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf delete mode 100644 landingzones/caf_solution/add-ons/terraform_cloud/variables.tf delete mode 100644 landingzones/caf_solution/backend.azurerm delete mode 100644 landingzones/caf_solution/dynamic_secrets.tf delete mode 100644 landingzones/caf_solution/landingzone.tf delete mode 100644 landingzones/caf_solution/local.remote.tf delete mode 100644 landingzones/caf_solution/local.remote_objects.tf delete mode 100644 landingzones/caf_solution/locals.remote_tfstates.tf delete mode 100644 landingzones/caf_solution/main.tf delete mode 100644 landingzones/caf_solution/modules/databricks/cluster.tf delete mode 100644 landingzones/caf_solution/modules/databricks/instance_pool.tf delete mode 100644 landingzones/caf_solution/modules/databricks/main.tf delete mode 100644 landingzones/caf_solution/modules/databricks/output.tf delete mode 100644 landingzones/caf_solution/modules/databricks/variables.tf delete mode 100644 landingzones/caf_solution/output.tf delete mode 100644 landingzones/caf_solution/readme.md delete mode 100644 landingzones/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/100-single-region-hub/readme.md delete mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/readme.md delete mode 100644 landingzones/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/105-hub-and-spoke/readme.md delete mode 100644 landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md delete mode 100644 landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/210-aks-private/configuration.tfvars delete mode 100644 landingzones/caf_solution/scenario/networking/210-aks-private/peerings/launchpad/configuration.tfvars delete mode 100644 landingzones/caf_solution/scenario/shared_services/100/configuration.tfvars delete mode 100644 landingzones/caf_solution/scenario/shared_services/200/configuration.tfvars delete mode 100644 landingzones/caf_solution/scripts/cloud-init-install-rover-tools.config delete mode 100644 landingzones/caf_solution/scripts/grant_consent.sh delete mode 100644 landingzones/caf_solution/variables.tf diff --git a/landingzones/caf_launchpad/.terraform.lock.hcl b/landingzones/caf_launchpad/.terraform.lock.hcl deleted file mode 100644 index f8ae181d8..000000000 --- a/landingzones/caf_launchpad/.terraform.lock.hcl +++ /dev/null @@ -1,72 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/aztfmod/azurecaf" { - version = "1.2.2" - constraints = "~> 1.2.0" - hashes = [ - "h1:5GMOMtQg1/i6yigQ++Nol/lno2D67D5LhO3/VLPMq9A=", - ] -} - -provider "registry.terraform.io/hashicorp/azuread" { - version = "1.4.0" - constraints = "~> 1.4.0" - hashes = [ - "h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=", - ] -} - -provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.50.0" - constraints = "~> 2.50.0, ~> 2.50" - hashes = [ - "h1:Vr6WUm88s9hXGkyVjHtHsP2Jmc2ypQXn6ww7dXtvk1M=", - ] -} - -provider "registry.terraform.io/hashicorp/external" { - version = "1.2.0" - constraints = "~> 1.2.0" - hashes = [ - "h1:wDfbBn+171g9/+aWqkicrN5l1S3kuqEX4J1zyPCDsoY=", - ] -} - -provider "registry.terraform.io/hashicorp/null" { - version = "2.1.2" - constraints = "~> 2.1.0" - hashes = [ - "h1:CFnENdqQu4g3LJNevA32aDxcUz2qGkRGQpFfkI8TCdE=", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "2.2.1" - constraints = "~> 2.2.1" - hashes = [ - "h1:Zg1Bpi6vr7b0H6no8kVDfEucn5pvNALivdrVKVHarGs=", - ] -} - -provider "registry.terraform.io/hashicorp/template" { - version = "2.2.0" - hashes = [ - "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", - ] -} - -provider "registry.terraform.io/hashicorp/time" { - version = "0.7.0" - hashes = [ - "h1:1VPBq+jeoCf0wVCxnzK6BNnOmNbXf3fRnDmS43Jw7Oo=", - ] -} - -provider "registry.terraform.io/hashicorp/tls" { - version = "2.2.0" - constraints = "~> 2.2.0" - hashes = [ - "h1:BRvNNW/32RAFXRcEAovtJWVbFt8zesIKkQm2N0GBCn8=", - ] -} diff --git a/landingzones/caf_launchpad/backend.azurerm b/landingzones/caf_launchpad/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_launchpad/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_launchpad/documentation/img/launchpad-100.PNG b/landingzones/caf_launchpad/documentation/img/launchpad-100.PNG deleted file mode 100644 index c93a36c46bafe2b787394e8729e469a1c98bc6db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143702 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%0A}!)1#qO;^}XKhld?yny=?0OQ;f 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ȿ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
fW#D|re`0@a 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

8x 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⪙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 z%0D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

eWxqjS32AL3iKBq8=c>e-zj+ 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 HA13EtOFTXU diff --git a/landingzones/caf_launchpad/documentation/variables.md b/landingzones/caf_launchpad/documentation/variables.md deleted file mode 100644 index ce3e5b190..000000000 --- a/landingzones/caf_launchpad/documentation/variables.md +++ /dev/null @@ -1,41 +0,0 @@ -# Variables of the landing zone launchpad - -The launchpad landing zone leverage object variables to provide better understanding of the variables to set in the configuration files. - -## launchpad_mode - -There are two launchpad versions that can be deployed in an Azure subscription. When set to launchpad_light it not impersonating the rover to the launchpad aad application and keep the execution under the logged-in user. It is designed to provide a way to experience the landing zone when the logged-in user has limited privileges in the Azure AD tenant. - -| Variable | Default | Allowed value | Type | Example | -|---|---|---|---|---| -| launchpad_mode | "launchpad_light" | ["launchpad_light", "launchpad"] | string | | - -## level - -| Variable | Description | -|---|---| -| level | The Cloud Adoption Framework for the Terraform Edition proposes to group landing zones into different levels to group per function and more importantly to secure the levels and prevent a level to access to an un-authorized level. More details on this link | - - -"level0" | ["level0", "level1", "level2", "level3", "level4"] | string | | - -## global_settings - -| Variable | Description | -|---|---| -| global_settings | The global_settings is an object containing the default settings the landing zones from a higher level can hinerit. | - -| Default | -|---| -```hcl -default = { - default_location = "southeastasia" - prefix = null -} -``` -### Attributes - -| Attribute | Allowed values -|---| -* prefix is not set or null it generates a random 4 alpha char -* prefix = "" disable the prefix in the naming conventions diff --git a/landingzones/caf_launchpad/dynamic_secrets.tf b/landingzones/caf_launchpad/dynamic_secrets.tf deleted file mode 100644 index 3b78eb1c8..000000000 --- a/landingzones/caf_launchpad/dynamic_secrets.tf +++ /dev/null @@ -1,10 +0,0 @@ - -module "dynamic_keyvault_secrets" { - source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=5.3.0_preview" - - for_each = try(var.dynamic_keyvault_secrets, {}) - - settings = each.value - keyvault = module.launchpad.keyvaults[each.key] - objects = module.launchpad -} diff --git a/landingzones/caf_launchpad/landingzone.tf b/landingzones/caf_launchpad/landingzone.tf deleted file mode 100644 index fe36988d8..000000000 --- a/landingzones/caf_launchpad/landingzone.tf +++ /dev/null @@ -1,53 +0,0 @@ -module "launchpad" { - source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git?ref=5.3.0_preview" - - azuread_api_permissions = var.azuread_api_permissions - azuread_apps = var.azuread_apps - azuread_groups = var.azuread_groups - azuread_roles = var.azuread_roles - azuread_users = var.azuread_users - current_landingzone_key = var.landingzone.key - custom_role_definitions = var.custom_role_definitions - enable = var.enable - event_hub_namespaces = var.event_hub_namespaces - global_settings = local.global_settings - keyvault_access_policies = var.keyvault_access_policies - keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps - keyvaults = var.keyvaults - log_analytics = var.log_analytics - logged_aad_app_objectId = var.logged_aad_app_objectId - logged_user_objectId = var.logged_user_objectId - managed_identities = var.managed_identities - resource_groups = var.resource_groups - role_mapping = var.role_mapping - storage_accounts = var.storage_accounts - subscriptions = var.subscriptions - tags = local.tags - tenant_id = var.tenant_id - user_type = var.user_type - - diagnostics = { - diagnostics_definition = try(var.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = try(var.diagnostics.diagnostics_destinations, var.diagnostics_destinations) - diagnostic_event_hub_namespaces = try(var.diagnostics.diagnostic_event_hub_namespaces, var.diagnostic_event_hub_namespaces) - diagnostic_log_analytics = try(var.diagnostics.diagnostic_log_analytics, var.diagnostic_log_analytics) - diagnostic_storage_accounts = try(var.diagnostics.diagnostic_storage_accounts, var.diagnostic_storage_accounts) - } - - compute = { - virtual_machines = try(var.compute.virtual_machines, var.virtual_machines) - bastion_hosts = try(var.compute.bastion_hosts, var.bastion_hosts) - } - - networking = { - vnets = try(var.networking.vnets, var.vnets) - network_security_group_definition = try(var.networking.network_security_group_definition, var.network_security_group_definition) - public_ip_addresses = try(var.networking.public_ip_addresses, var.public_ip_addresses) - azurerm_routes = try(var.networking.azurerm_routes, var.azurerm_routes) - route_tables = try(var.networking.route_tables, var.route_tables) - } - - security = { - keyvault_keys = var.keyvault_keys - } -} diff --git a/landingzones/caf_launchpad/main.tf b/landingzones/caf_launchpad/main.tf deleted file mode 100644 index 2c52ea02b..000000000 --- a/landingzones/caf_launchpad/main.tf +++ /dev/null @@ -1,88 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.50" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.4.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features {} -} - -resource "random_string" "prefix" { - count = var.prefix == null ? 1 : 0 - length = 4 - special = false - upper = false - number = false -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = { - default_region = var.default_region - environment = var.environment - inherit_tags = var.inherit_tags - passthrough = var.passthrough - prefix = var.prefix - prefixes = var.prefix == "" ? null : [try(random_string.prefix.0.result, var.prefix)] - prefix_with_hyphen = var.prefix == "" ? null : format("%s", try(random_string.prefix.0.result, var.prefix)) - random_length = var.random_length - regions = var.regions - tags = var.tags - use_slug = var.use_slug - } - - tfstates = map( - var.landingzone.key, - local.backend[var.landingzone.backend_type] - ) - - backend = { - azurerm = { - storage_account_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].name - container_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].containers["tfstate"].name - resource_group_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].resource_group_name - key = var.tf_name - level = var.landingzone.level - tenant_id = data.azurerm_client_config.current.tenant_id - subscription_id = data.azurerm_client_config.current.subscription_id - } - } - -} - -data "azurerm_client_config" "current" {} \ No newline at end of file diff --git a/landingzones/caf_launchpad/output.tf b/landingzones/caf_launchpad/output.tf deleted file mode 100644 index 313425b12..000000000 --- a/landingzones/caf_launchpad/output.tf +++ /dev/null @@ -1,16 +0,0 @@ - -output "objects" { - value = tomap( - { (var.landingzone.key) = { - for key, value in module.launchpad : key => value - if try(value, {}) != {} - } - } - ) - sensitive = true -} - -output "tfstates" { - value = local.tfstates - sensitive = true -} diff --git a/landingzones/caf_launchpad/readme.md b/landingzones/caf_launchpad/readme.md deleted file mode 100644 index 9bc5aa947..000000000 --- a/landingzones/caf_launchpad/readme.md +++ /dev/null @@ -1,206 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Launchpad - -The launchpad allows you to manage the foundations of landing zone environments by: - -* Securing remote Terraform state storage for multiple subscriptions. -* Managing the transition from manual to automated environments. -* Bring up the DevOps foundations using Azure DevOps, Terraform Cloud and GitHub actions (more to come). - -Launchpad operates at **level 0**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -
- -## Getting started with launchpad - -Depending on what you are trying to achieve, we provide you with different levels of launchpads to cover different scenario: - -| level | scenario | supported environments | -|-----------------------|------------------------------------------------------------------------------------------------------------------|--------------------------------------------| -| [100](./scenario/100) | Start with this one! basic functionalities and features, no RBAC or security hardening - for demo and simple POC | working on AIRS subscriptions | -| [200](./scenario/200) | intermediate functionalities includes diagnostics features | may not work in AIRS, need AAD permissions | -| [300](./scenario/300) | advanced functionalities, includes RBAC features | not working in AIRS, need AAD permissions | -| [400](./scenario/400) | advanced functionalities, includes RBAC features and security hardening | not working in AIRS, need AAD permissions | - -You can pick your scenario and use one of the following commands: - -```bash -# Simple scenario for learning and demonstration -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \ - -parallelism=30 \ - -a apply - -# Advanced scenario - Requires Azure AD privileges -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ - -parallelism=30 \ - -a apply - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/landingzones/caf_launchpad \ - -tfstate_subscription_id \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ - -parallelism=30 \ - -a apply -``` - -
- -## Overview of launchpad initialization - -![Launchpad Worklow](./documentation/img/launchpad_workflow.png) - -The rover executed in launchpad mode performs the following option to bootstrap your environment: - -1. **Initialize a terraform state**: - * The launchpad tries to retrieve an existing terraform state on Azure using the name of the tfstate file and the name of the workspace (level0 by default) - * Creates a tfstates folder if no remote state have been retrieved, this happens when your environment does not contain a storage account containing a tfstate matching the input parameters - - The Launchpad deployment relies on the following providers: - - * hashicorp/azurerm - * hashicorp/azuread - * hashicorp/random - * aztfmod/azurecaf - * hashicorp/null - - The latest version of the Launchpad relies on the new capabilities of **Terraform 0.13** - -2. **Call Terraform init**: - - * The launchpad then call terraform init to retrieve the provides and modules associated with the deployment - -3. **Call terraform apply**: - * deploy the resources as specified in the launchpad configuration files (see description below) - -```bash -Outputs: - -aad_apps = -azure_subscriptions = -diagnostics_map = -github_token_keyvault = -global_settings = -keyvaults = -log_analytics = -networking = -resource_groups = -``` - -4. **Create a workspace to host the local tfsate** - the launchpad will create two containers in the newly created storage account (in step 3): - * "sandpit" workspace - * "level0" (by default) workspace - -5. **Upload the launchpad state (tfstate) to the storage level0 workspace** - the state contains the default settings, keyvault id, and service principal id created during the launchpad deployment - -```bash -Moving launchpad to the cloud - - storage_account_name: storageaccname - - resource_group: hrjx-rg-launchpad-tfstates-rVb7GtKPXxHMa - - storage_key: retrieved -{ - "etag": "\"0x8D833A974C32C5F\"", - "lastModified": "2020-07-29T10:23:37+00:00" -} -``` - -
- -## Launchpad architecture - -Each resource deployed with the launchpad is leveraging the [azurecaf provider](https://github.com/aztfmod/terraform-provider-azurecaf) to enforce naming convention. - -The launchpad deploys the following Azure components: - -1. Resource groups - By default the launchpad light auto variables will create three resources groups : launchpad-tfstates to host a the tfstate storage account, launchpad-security to host a keyvault, launchpad-devops-agents to host deployment agents should you choose to deploy VMs to automate subsequent deployment using Azure DevOps or GitHub - -2. Storage Accounts - a storage account in the launchpad-tfstates reosource group. The storage account contains the tfstate of the launchpad deployment and will be automatically configured as the Terraform remote backend when deploying landing zones with the rover - -3. KeyVaults - a keyvault resource to store with Get,List,Set,Delete access to for the logged in user (using the Azure CLI) - the keyvault will contain secrets of service principal accounts and managed identities - -4. A Log Analytics workspace and a KeyVault analytics solution deployed in the launchpad-devops-agent resource group. The Log Analytics workspace will gather the monitoring information and logs of both the DevOps agents and of the Keyvault - -5. Diagnostic settings - Creates Storage Account and Event Hubs (optional) to be used for diagnostics and operations logs. The resources are created in the launchpad-devops-agent resource group - -6. Virtual Network: The Launchpad can create Virtual Networks and subnets to deploy additional workloads during the bootstrap process - typically CI/CD agents - -7. Azure Active Directory Applications and role assignment - - This a critical aspect of the launchpad bootstrap process. The deployment creates an Azure AD Application named "caf_launchpad_level0" by default. The launchpad can be configured to create additional Azure AD Applications - - * The user deploying the launchpad is set to be the application owner - * A Service Principal + random password is created for each Application - the data is then stored in the referenced keyvault as multiple secrets - * Resource Access is assigned based on the aad_api_permissions object - * Each application can be assigned one or multiple Azure AD roles through the aad_roles object - empty by default - - By default the underlying service principal will be granted **owner** access to the subscription targeted by the launchpad deployment. This Azure AD Application + Service Principal will be used in subsequent deployments using the Rover. - - API permissions and admin consent are also granted during the bootstrap process. The grant_consent.sh scripts is called for to enable API access for a given Application - * The variable `aad_api_permissions` object can contains multiple entries - * each key references one of the Application defined in the `aad_apps` variable. The content of each entry is an api permission definition. - - The objectId, ApplicationId, ServicePrincipalID, client_secret are each stored in a keyvault using the secret_prefix value as defined in the code example - - The example below shows an App Definition, a role assignment and an API permission assignment. using three terraform variables with define an app called "caf_launchpad_github_terraformdev_github-integration-landingzones", we assign the Application Developer role to this application, finally we grand admin consent to the Active Directory Graph APIs. - - ```terraform - aad_apps = { - azure_caf-terraform-landingzones = { - application_name = "caf_launchpad_github_terraformdev_github-integration-landingzones" - password_expire_in_days = 60 - tenant_name = "terraformdev.onmicrosoft.com" - keyvault = { - keyvault_key = "launchpad" - secret_prefix = "caf-launchpad-github-terraformdev-github-integration-landingzones" - } - } - } - aad_roles = { - azure_caf-terraform-landingzones = { - roles = [ - "Application Developer" - ] - } - } - - aad_api_permissions = { - azure_caf-terraform-landingzones = { - active_directory_graph = { - resource_app_id = "00000002-0000-0000-c000-000000000000" - resource_access = { - active_directory_graph_resource_access_id_Application_ReadWrite_OwnedBy = { - id = "824c81eb-e3f8-4ee6-8f6d-de7f50d565b7" - type = "Role" - } - active_directory_graph_resource_access_id_Directory_ReadWrite_All = { - id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175" - type = "Role" - } - } - } - } - } - ``` - - The Azure Active Directory Application creation, Role assignment and Admin Consent delegation plays a critical role in the launchpad bootstrapping process. Make sure to work with your Tenant administrators to define the scope and the roles assigned the Application created by the launchpad. - -8. Release Agents (Optional): - * Deploys Virtual machines in the targeted Virtual Network. You may choose to leverage an existing Azure DevOps organization and deploy CI/CD agents and pipelines. The Agents will then be in charge of subsequent rover deployments to automate the IaC provisioning with Terraform - -## Launchpad add-ons - -Add-ons are additional capabilities to enhance the launchpad, that are deployed separately and managed by a different state. - -Current add-ons: - -* Azure DevOps Self Hosted Agents and Pipeline - -In-development add-ons: - -* Terrform Cloud Enterprise -* GitHub Actions diff --git a/landingzones/caf_launchpad/scenario/100/README.md b/landingzones/caf_launchpad/scenario/100/README.md deleted file mode 100644 index dfa8197a7..000000000 --- a/landingzones/caf_launchpad/scenario/100/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Launchpad - scenario 100 - -The 100 scenario is designed to demonstrate a basic functional foundations to store Terraform state on Azure storage and use it centrally. -The focus of this scenario is to be able to deploy a basic launchpad from a remote machine and use the portal to review the settings in a non-constrained environment. -For example in this scenario you can go to the Key Vaults and view the secrets from the portal, a feature that is disabled in the 300+ scenarios. -We recommend using the 100 scenario for demonstration purposes. - -An estimated time of 5 minutes is required to deploy this scenario. - -## Pre-requisites - -This scenario require the following privileges: - -| Component | Privileges | -|--------------------|--------------------| -| Active Directory | None | -| Azure subscription | Subscription owner | - -## Deployment - -```bash -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad -var-folder \ - /tf/caf/landingzones/caf_launchpad/scenario/100 \ - -a apply - -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \ - -a destroy -``` - -## Architecture diagram -![Launchpad 100](../../documentation/img/launchpad-100.PNG) - -## Services deployed in this scenario - -| Component | Purpose | -|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Resource group | Multiple resource groups are created to isolate the services. | -| Storage account | A storage account for remote tfstate management is provided for each level of the framework. Additional storage accounts are created for diagnostic logs. | -| Key Vault | The launchpad Key Vault hosts all secrets required by the rover to access the remote states, the Key Vault policies are created allowing the logged-in user to see secrets created and stored. | -| Virtual network | To secure the communication between the services a dedicated virtual network is deployed with a gateway subnet, bastion service, jumpbox and azure devops release agents. Service endpoints is enabled but not configured. | -| Azure AD Applications | An Azure AD application is created. This account is mainly use to bootstrap the services during the initialization. It is also considered as a breakglass account for the launchpad landing zones | diff --git a/landingzones/caf_launchpad/scenario/100/configuration.tfvars b/landingzones/caf_launchpad/scenario/100/configuration.tfvars deleted file mode 100644 index ad53a6ba0..000000000 --- a/landingzones/caf_launchpad/scenario/100/configuration.tfvars +++ /dev/null @@ -1,68 +0,0 @@ -landingzone = { - backend_type = "azurerm" - level = "level0" - key = "launchpad" -} - - -# Default region. When not set to a resource it will use that value -default_region = "region1" - -# naming convention settings -# for more settings on naming convention, please refer to the provider documentation: https://github.com/aztfmod/terraform-provider-azurecaf -# -# passthrough means the default CAF naming convention is not applied and you are responsible -# of the unicity of the names you are giving. the CAF provider will clear out -# passthrough = false -# adds random chars at the end of the names produced by the provider -# random_length = 3 - -# Inherit_tags defines if a resource will inherit it's resource group tags -inherit_tags = true - -regions = { - region1 = "southeastasia" - region2 = "eastasia" -} - -launchpad_key_names = { - azuread_app = "caf_launchpad_level0" - keyvault_client_secret = "aadapp-caf-launchpad-level0" - tfstates = [ - "level0", - ] -} - -resource_groups = { - level0 = { - name = "launchpad-level0" - tags = { - level = "level0" - } - } - level1 = { - name = "launchpad-level1" - tags = { - level = "level1" - } - } - level2 = { - name = "launchpad-level2" - tags = { - level = "level2" - } - } - level3 = { - name = "launchpad-level3" - tags = { - level = "level3" - } - } - level4 = { - name = "launchpad-level4" - tags = { - level = "level4" - } - } -} - diff --git a/landingzones/caf_launchpad/scenario/100/dynamic_secrets.tfvars b/landingzones/caf_launchpad/scenario/100/dynamic_secrets.tfvars deleted file mode 100644 index 23a0258d4..000000000 --- a/landingzones/caf_launchpad/scenario/100/dynamic_secrets.tfvars +++ /dev/null @@ -1,114 +0,0 @@ - -# Store output attributes into keyvault secret -# Those values are used by the rover to connect the current remote state and -# identity the lower level -dynamic_keyvault_secrets = { - level0 = { - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level1 = { - lower_stg = { - output_key = "storage_accounts" - resource_key = "level0" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level0" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level2 = { - lower_stg = { - output_key = "storage_accounts" - resource_key = "level1" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level1" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level3 = { - lower_stg = { - output_key = "storage_accounts" - resource_key = "level2" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level2" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level4 = { - lower_stg = { - output_key = "storage_accounts" - resource_key = "level3" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level3" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } -} \ No newline at end of file diff --git a/landingzones/caf_launchpad/scenario/100/iam_role_mapping.tfvars b/landingzones/caf_launchpad/scenario/100/iam_role_mapping.tfvars deleted file mode 100644 index 87a218b80..000000000 --- a/landingzones/caf_launchpad/scenario/100/iam_role_mapping.tfvars +++ /dev/null @@ -1,47 +0,0 @@ - -# -# Services supported: subscriptions, storage accounts and resource groups -# Can assign roles to: AD groups, AD object ID, AD applications, Managed identities -# -role_mapping = { - built_in_role_mapping = { - storage_accounts = { - level0 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - level1 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - level2 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - level3 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - level4 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - } - } - -} diff --git a/landingzones/caf_launchpad/scenario/100/keyvaults.tfvars b/landingzones/caf_launchpad/scenario/100/keyvaults.tfvars deleted file mode 100644 index 00de22b41..000000000 --- a/landingzones/caf_launchpad/scenario/100/keyvaults.tfvars +++ /dev/null @@ -1,99 +0,0 @@ - -keyvaults = { - level0 = { - name = "level0" - resource_group_key = "level0" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level0" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - } - - level1 = { - name = "level1" - resource_group_key = "level1" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level1" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - } - - level2 = { - name = "level2" - resource_group_key = "level2" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level2" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - } - - level3 = { - name = "level3" - resource_group_key = "level3" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level3" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - } - - level4 = { - name = "level4" - resource_group_key = "level4" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level4" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - } -} diff --git a/landingzones/caf_launchpad/scenario/100/storage_accounts.tfvars b/landingzones/caf_launchpad/scenario/100/storage_accounts.tfvars deleted file mode 100644 index bb2834b9c..000000000 --- a/landingzones/caf_launchpad/scenario/100/storage_accounts.tfvars +++ /dev/null @@ -1,102 +0,0 @@ - -storage_accounts = { - level0 = { - name = "level0" - resource_group_key = "level0" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - ## Those tags must never be changed after being set as they are used by the rover to locate the launchpad and the tfstates. - # Only adjust the environment value at creation time - tfstate = "level0" - environment = "sandpit" - launchpad = "launchpad" - ## - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - - level1 = { - name = "level1" - resource_group_key = "level1" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level1" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level2 = { - name = "level2" - resource_group_key = "level2" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level2" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level3 = { - name = "level3" - resource_group_key = "level3" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level3" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level4 = { - name = "level4" - resource_group_key = "level4" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level4" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - - } - -} \ No newline at end of file diff --git a/landingzones/caf_launchpad/scenario/200/compute.tfvars b/landingzones/caf_launchpad/scenario/200/compute.tfvars deleted file mode 100644 index 88164c5a4..000000000 --- a/landingzones/caf_launchpad/scenario/200/compute.tfvars +++ /dev/null @@ -1,100 +0,0 @@ -################################################## -# -# Compute resources -# -################################################## - -bastion_hosts = { - launchpad_host = { - name = "bastion" - resource_group_key = "bastion_launchpad" - vnet_key = "devops_region1" - subnet_key = "AzureBastionSubnet" - public_ip_key = "bastion_host_rg1" - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "bastion_host" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - } -} - -# Virtual machines -virtual_machines = { - - # Configuration to deploy a bastion host linux virtual machine - bastion_host = { - resource_group_key = "bastion_launchpad" - region = "region1" - boot_diagnostics_storage_account_key = "bootdiag_region1" - provision_vm_agent = true - - os_type = "linux" - - # the auto-generated ssh key in keyvault secret. Secret name being {VM name}-ssh-public and {VM name}-ssh-private - keyvault_key = "secrets" - - # Define the number of networking cards to attach the virtual machine - networking_interfaces = { - nic0 = { - # Value of the keys from networking.tfvars - vnet_key = "devops_region1" - subnet_key = "jumpbox" - name = "0" - enable_ip_forwarding = false - internal_dns_name_label = "nic0" - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "network_interface_card" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - } - - virtual_machine_settings = { - linux = { - name = "bastion" - size = "Standard_F2" - admin_username = "adminuser" - disable_password_authentication = true - custom_data = "scripts/cloud-init-install-rover-tools.config" - - # Value of the nic keys to attach the VM. The first one in the list is the default nic - network_interface_keys = ["nic0"] - - os_disk = { - name = "bastion-os" - caching = "ReadWrite" - storage_account_type = "Standard_LRS" - } - - source_image_reference = { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "18.04-LTS" - version = "latest" - } - - identity = { - type = "UserAssigned" - managed_identity_keys = [ - "level0", "level1", "level2", "level3", "level4" - ] - } - - } - } - - } -} - diff --git a/landingzones/caf_launchpad/scenario/200/configuration.tfvars b/landingzones/caf_launchpad/scenario/200/configuration.tfvars deleted file mode 100644 index 36645019e..000000000 --- a/landingzones/caf_launchpad/scenario/200/configuration.tfvars +++ /dev/null @@ -1,100 +0,0 @@ -landingzone = { - backend_type = "azurerm" - level = "level0" - key = "launchpad" -} - -enable = { - bastion_hosts = false - virtual_machines = false -} - -# Default region. When not set to a resource it will use that value -default_region = "region1" - -regions = { - region1 = "southeastasia" - region2 = "eastasia" -} - -# core tags to be applied accross this landing zone -tags = { - owner = "CAF" - deploymentType = "Terraform" - costCenter = "0" - BusinessUnit = "SHARED" - DR = "NON-DR-ENABLED" -} - -# naming convention settings -# for more settings on naming convention, please refer to the provider documentation: https://github.com/aztfmod/terraform-provider-azurecaf -# -# passthrough means the default CAF naming convention is not applied and you are responsible -# of the unicity of the names you are giving. the CAF provider will clear out -# passthrough = false -# adds random chars at the end of the names produced by the provider -# random_length = 3 - -# all resources deployed will inherit tags from the parent resource group -inherit_tags = true - -launchpad_key_names = { - azuread_app = "caf_launchpad_level0" - keyvault_client_secret = "aadapp-caf-launchpad-level0" - tfstates = [ - "level0", - "level1", - "level2", - "level3", - "level4" - ] -} - -resource_groups = { - level0 = { - name = "launchpad-level0" - tags = { - level = "level0" - } - } - level1 = { - name = "launchpad-level1" - tags = { - level = "level1" - } - } - level2 = { - name = "launchpad-level2" - tags = { - level = "level2" - } - } - level3 = { - name = "launchpad-level3" - tags = { - level = "level3" - } - } - level4 = { - name = "launchpad-level4" - tags = { - level = "level4" - } - } - security = { - name = "launchpad-security" - } - networking = { - name = "launchpad-networking" - } - ops = { - name = "operations" - } - siem = { - name = "siem-logs" - } - bastion_launchpad = { - name = "launchpad-bastion" - } -} - diff --git a/landingzones/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars b/landingzones/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars deleted file mode 100644 index 75c3e3e90..000000000 --- a/landingzones/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars +++ /dev/null @@ -1,20 +0,0 @@ - -# Event hub diagnostics -diagnostic_event_hub_namespaces = { - central_logs_region1 = { - name = "logs" - resource_group_key = "ops" - sku = "Standard" - region = "region1" - - diagnostic_profiles = { - central_logs_region1 = { - definition_key = "event_hub_namespace" - destination_type = "storage" - destination_key = "all_regions" - } - } - } -} - - diff --git a/landingzones/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars b/landingzones/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars deleted file mode 100644 index fd2cb048f..000000000 --- a/landingzones/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars +++ /dev/null @@ -1,48 +0,0 @@ -# -# Define the settings for log analytics workspace and solution map -# -diagnostic_log_analytics = { - central_logs_region1 = { - region = "region1" - name = "logs" - resource_group_key = "ops" - # you can setup up to 5 key - diagnostic_profiles = { - central_logs_region1 = { - definition_key = "log_analytics" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - solutions_maps = { - NetworkMonitoring = { - "publisher" = "Microsoft" - "product" = "OMSGallery/NetworkMonitoring" - }, - ADAssessment = { - "publisher" = "Microsoft" - "product" = "OMSGallery/ADAssessment" - }, - ADReplication = { - "publisher" = "Microsoft" - "product" = "OMSGallery/ADReplication" - }, - AgentHealthAssessment = { - "publisher" = "Microsoft" - "product" = "OMSGallery/AgentHealthAssessment" - }, - DnsAnalytics = { - "publisher" = "Microsoft" - "product" = "OMSGallery/DnsAnalytics" - }, - ContainerInsights = { - "publisher" = "Microsoft" - "product" = "OMSGallery/ContainerInsights" - }, - KeyVaultAnalytics = { - "publisher" = "Microsoft" - "product" = "OMSGallery/KeyVaultAnalytics" - } - } - } -} diff --git a/landingzones/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars b/landingzones/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars deleted file mode 100644 index a58c5eee8..000000000 --- a/landingzones/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars +++ /dev/null @@ -1,64 +0,0 @@ -# Defines different repositories for the diagnostics logs -# Storage accounts, log analytics, event hubs - -diagnostic_storage_accounts = { - # Stores diagnostic logging for region1 - diaglogs_region1 = { - name = "diaglogsrg1" - region = "region1" - resource_group_key = "ops" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores diagnostic logging for region2 - diaglogs_region2 = { - name = "diaglogrg2" - region = "region2" - resource_group_key = "ops" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores security logs for siem default region" - diagsiem_region1 = { - name = "siemsg1" - resource_group_key = "siem" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores diagnostic logging for region2 - diagsiem_region2 = { - name = "siemrg2" - region = "region2" - resource_group_key = "siem" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores boot diagnostic for region1 - bootdiag_region1 = { - name = "bootrg1" - region = "region1" - resource_group_key = "ops" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores boot diagnostic for region2 - bootdiag_region2 = { - name = "bootrg2" - region = "region2" - resource_group_key = "ops" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } -} \ No newline at end of file diff --git a/landingzones/caf_launchpad/scenario/200/diagnostics_definition.tfvars b/landingzones/caf_launchpad/scenario/200/diagnostics_definition.tfvars deleted file mode 100644 index 10a20c4dd..000000000 --- a/landingzones/caf_launchpad/scenario/200/diagnostics_definition.tfvars +++ /dev/null @@ -1,274 +0,0 @@ - -# -# Define a set of settings for the various type of Azure resources -# - -diagnostics_definition = { - log_analytics = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["Audit", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - default_all = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AuditEvent", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - bastion_host = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["BastionAuditLogs", true, false, 7], - ] - } - - } - - networking_all = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["VMProtectionAlerts", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - public_ip_address = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["DDoSProtectionNotifications", true, false, 7], - ["DDoSMitigationFlowLogs", true, false, 7], - ["DDoSMitigationReports", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - network_security_group = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["NetworkSecurityGroupEvent", true, false, 7], - ["NetworkSecurityGroupRuleCounter", true, false, 7], - ] - } - - } - - network_interface_card = { - name = "operational_logs_and_metrics" - categories = { - # log = [ - # # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - # ["AuditEvent", true, false, 7], - # ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - azure_container_registry = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["ContainerRegistryRepositoryEvents", true, false, 7], - ["ContainerRegistryLoginEvents", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - } - - azure_kubernetes_cluster = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["kube-apiserver", true, false, 7], - ["kube-audit", true, false, 7], - ["kube-audit-admin", true, false, 7], - ["kube-controller-manager", true, false, 7], - ["kube-scheduler", true, false, 7], - ["cluster-autoscaler", true, false, 7], - ["guard", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - } - - azure_site_recovery = { - name = "operational_logs_and_metrics" - log_analytics_destination_type = "Dedicated" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AzureBackupReport", true, true, 7], - ["CoreAzureBackup", true, true, 7], - ["AddonAzureBackupAlerts", true, true, 7], - ["AddonAzureBackupJobs", true, true, 7], - ["AddonAzureBackupPolicy", true, true, 7], - ["AddonAzureBackupProtectedInstance", true, true, 7], - ["AddonAzureBackupStorage", true, true, 7], - ["AzureSiteRecoveryJobs", true, true, 7], - ["AzureSiteRecoveryEvents", true, true, 7], - ["AzureSiteRecoveryReplicatedItems", true, true, 7], - ["AzureSiteRecoveryReplicationStats", true, true, 7], - ["AzureSiteRecoveryRecoveryPoints", true, true, 7], - ["AzureSiteRecoveryReplicationDataUploadRate", true, true, 7], - ["AzureSiteRecoveryProtectedDiskDataChurn", true, true, 30], - ] - metric = [ - #["AllMetrics", 60, True], - ] - } - - } - - azure_automation = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["JobLogs", true, true, 30], - ["JobStreams", true, true, 30], - ["DscNodeStatus", true, true, 30], - ] - metric = [ - # ["Category name", "Metric Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, true, 30], - ] - } - - } - - event_hub_namespace = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["ArchiveLogs", true, false, 7], - ["OperationalLogs", true, false, 7], - ["AutoScaleLogs", true, false, 7], - ["KafkaCoordinatorLogs", true, false, 7], - ["KafkaUserErrorLogs", true, false, 7], - ["EventHubVNetConnectionEvent", true, false, 7], - ["CustomerManagedKeyUserLogs", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - compliance_all = { - name = "compliance_logs" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AuditEvent", true, true, 365], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", false, false, 7], - ] - } - - } - - siem_all = { - name = "siem" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AuditEvent", true, true, 0], - ] - - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", false, false, 0], - ] - } - - } - - subscription_operations = { - name = "subscription_operations" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)"] - ["Administrative", true], - ["Security", true], - ["ServiceHealth", true], - ["Alert", true], - ["Policy", true], - ["Autoscale", true], - ["ResourceHealth", true], - ["Recommendation", true], - ] - } - } - - subscription_siem = { - name = "activity_logs_for_siem" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)"] - ["Administrative", false], - ["Security", true], - ["ServiceHealth", false], - ["Alert", false], - ["Policy", true], - ["Autoscale", false], - ["ResourceHealth", false], - ["Recommendation", false], - ] - } - - } - -} \ No newline at end of file diff --git a/landingzones/caf_launchpad/scenario/200/diagnostics_destinations.tfvars b/landingzones/caf_launchpad/scenario/200/diagnostics_destinations.tfvars deleted file mode 100644 index 95ede1c24..000000000 --- a/landingzones/caf_launchpad/scenario/200/diagnostics_destinations.tfvars +++ /dev/null @@ -1,31 +0,0 @@ -# Defines the different destination for the different log profiles -# Different profiles to target different operational teams - -diagnostics_destinations = { - # Storage keys must reference the azure region name - # For storage, reference "all_regions" and we will send the logs to the storage account - # in the region of the deployment - storage = { - all_regions = { - southeastasia = { - storage_account_key = "diagsiem_region1" - } - eastasia = { - storage_account_key = "diagsiem_region2" - } - } - } - - log_analytics = { - central_logs = { - log_analytics_key = "central_logs_region1" - log_analytics_destination_type = "Dedicated" - } - } - - event_hub_namespaces = { - central_logs = { - event_hub_namespace_key = "central_logs_region1" - } - } -} diff --git a/landingzones/caf_launchpad/scenario/200/dynamic_secrets.tfvars b/landingzones/caf_launchpad/scenario/200/dynamic_secrets.tfvars deleted file mode 100644 index 94042fd05..000000000 --- a/landingzones/caf_launchpad/scenario/200/dynamic_secrets.tfvars +++ /dev/null @@ -1,152 +0,0 @@ - -# Store output attributes into keyvault secret -# Those values are used by the rover to connect the current remote state and -# identity the lower level -dynamic_keyvault_secrets = { - level0 = { - msi = { - output_key = "managed_identities" - resource_key = "level0" - attribute_key = "id" - secret_name = "msi-resource-id" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - admin = { - secret_name = "azdo-pat-admin" - value = "" - } - agent = { - secret_name = "azdo-pat-agent" - value = "" - } - } - level1 = { - msi = { - output_key = "managed_identities" - resource_key = "level1" - attribute_key = "id" - secret_name = "msi-resource-id" - } - lower_stg = { - output_key = "storage_accounts" - resource_key = "level0" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level0" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level2 = { - msi = { - output_key = "managed_identities" - resource_key = "level2" - attribute_key = "id" - secret_name = "msi-resource-id" - } - lower_stg = { - output_key = "storage_accounts" - resource_key = "level1" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level1" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level3 = { - msi = { - output_key = "managed_identities" - resource_key = "level3" - attribute_key = "id" - secret_name = "msi-resource-id" - } - lower_stg = { - output_key = "storage_accounts" - resource_key = "level2" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level2" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level4 = { - msi = { - output_key = "managed_identities" - resource_key = "level4" - attribute_key = "id" - secret_name = "msi-resource-id" - } - lower_stg = { - output_key = "storage_accounts" - resource_key = "level3" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level3" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } -} \ No newline at end of file diff --git a/landingzones/caf_launchpad/scenario/200/iam_azuread.tfvars b/landingzones/caf_launchpad/scenario/200/iam_azuread.tfvars deleted file mode 100644 index 4a4856f72..000000000 --- a/landingzones/caf_launchpad/scenario/200/iam_azuread.tfvars +++ /dev/null @@ -1,184 +0,0 @@ - -azuread_groups = { - keyvault_level0_rw = { - name = "caf-level0-keyvault-rw" - description = "Provide read and write access to the keyvault secrets / level0." - members = { - user_principal_names = [ - ] - group_names = [] - object_ids = [] - group_keys = [] - - service_principal_keys = [ - "caf_launchpad_level0" - ] - - } - owners = { - user_principal_names = [ - ] - service_principal_keys = [ - "caf_launchpad_level0" - ] - } - prevent_duplicate_name = false - } - - keyvault_level1_rw = { - name = "caf-level1-landingzones-rw" - description = "Provide read and write access to manage landingzones / level1." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - keyvault_level2_rw = { - name = "caf-level2-landingzones-rw" - description = "Provide read and write access to manage landingzones / level2." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - keyvault_level3_rw = { - name = "caf-level3-landingzones-rw" - description = "Provide read and write access to manage landingzones / level3." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - keyvault_level4_rw = { - name = "caf-level4-applications" - description = "Provide read access to the applications who need to deploy on the level4." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - caf_launchpad_Reader = { - name = "caf-launchpad-Reader" - description = "Provide Reader role to the caf launchpad landing zone resource groups." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - keyvault_password_rotation = { - name = "caf-level0-password-rotation-rw" - description = "Provide read and write access to the keyvault secrets / level0." - members = { - user_principal_names = [ - ] - group_names = [] - object_ids = [] - group_keys = [] - - service_principal_keys = [ - "caf_launchpad_level0" - ] - - } - owners = { - user_principal_names = [ - ] - service_principal_keys = [ - "caf_launchpad_level0" - ] - } - prevent_duplicate_name = false - } -} - -azuread_users = { - - # don't change that key - aad-user-devops-user-admin = { - useprefix = true - user_name = "caf-level0-security-devops-pat-rotation" - password_expire_in_days = 180 - - # Value must match with var.keyvaults[keyname] to store username and password for password rotation - keyvault_key = "secrets" - } - -} - -azuread_apps = { - # Do not rename the key "launchpad" to be able to upgrade to the standard launchpad - caf_launchpad_level0 = { - useprefix = true - application_name = "caf_launchpad_level0" - password_expire_in_days = 180 - - # Store the ${secret_prefix}-client-id, ${secret_prefix}-client-secret... - # Set the policy during the creation process of the launchpad - keyvaults = { - level0 = { - secret_prefix = "aadapp-caf-launchpad-level0" - } - } - } - -} - -# -# Available roles: -# az rest --method Get --uri https://graph.microsoft.com/v1.0/directoryRoleTemplates -o json | jq -r .value[].displayName -# -azuread_roles = { - azuread_apps = { - caf_launchpad_level0 = { - roles = [ - "Application Administrator", - "Application Developer", - "User Administrator" - ] - } - } - managed_identities = { - level0 = { - roles = [ - "Directory Readers", - "Application Developer", - "User Administrator" - ] - } - level1 = { - roles = [ - "Directory Readers" - ] - } - level2 = { - roles = [ - "Directory Readers" - ] - } - level3 = { - roles = [ - "Directory Readers" - ] - } - level4 = { - roles = [ - "Directory Readers" - ] - } - } -} diff --git a/landingzones/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars b/landingzones/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars deleted file mode 100644 index f73f3b73d..000000000 --- a/landingzones/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars +++ /dev/null @@ -1,43 +0,0 @@ - - -azuread_api_permissions = { - - caf_launchpad_level0 = { - active_directory_graph = { - resource_app_id = "00000002-0000-0000-c000-000000000000" - resource_access = { - Application_ReadWrite_OwnedBy = { - id = "824c81eb-e3f8-4ee6-8f6d-de7f50d565b7" - type = "Role" - } - Directory_ReadWrite_All = { - id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175" - type = "Role" - } - } - } - - microsoft_graph = { - resource_app_id = "00000003-0000-0000-c000-000000000000" - resource_access = { - AppRoleAssignment_ReadWrite_All = { - id = "06b708a9-e830-4db3-a914-8e69da51d44f" - type = "Role" - } - DelegatedPermissionGrant_ReadWrite_All = { - id = "8e8e4742-1d95-4f68-9d56-6ee75648c72a" - type = "Role" - } - GroupReadWriteAll = { - id = "62a82d76-70ea-41e2-9197-370581804d09" - type = "Role" - } - RoleManagement_ReadWrite_Directory = { - id = "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8" - type = "Role" - } - } - } - } - -} diff --git a/landingzones/caf_launchpad/scenario/200/iam_custom_roles.tfvars b/landingzones/caf_launchpad/scenario/200/iam_custom_roles.tfvars deleted file mode 100644 index f314abf3a..000000000 --- a/landingzones/caf_launchpad/scenario/200/iam_custom_roles.tfvars +++ /dev/null @@ -1,76 +0,0 @@ - -custom_role_definitions = { - caf-launchpad = { - name = "caf-launchpad" - useprefix = true - description = "Provide addition permissions on top of built-in Contributor role to manage landing zones deployment" - permissions = { - actions = [ - "Microsoft.Authorization/roleAssignments/delete", - "Microsoft.Authorization/roleAssignments/read", - "Microsoft.Authorization/roleAssignments/write", - "Microsoft.Authorization/roleDefinitions/delete", - "Microsoft.Authorization/roleDefinitions/read", - "Microsoft.Authorization/roleDefinitions/write", - "microsoft.insights/diagnosticSettings/delete", - "microsoft.insights/diagnosticSettings/read", - "microsoft.insights/diagnosticSettings/write", - "Microsoft.KeyVault/vaults/delete", - "Microsoft.KeyVault/vaults/read", - "Microsoft.KeyVault/vaults/write", - "Microsoft.KeyVault/vaults/accessPolicies/write", - "Microsoft.Network/networkSecurityGroups/delete", - "Microsoft.Network/networkSecurityGroups/read", - "Microsoft.Network/networkSecurityGroups/write", - "Microsoft.Network/networkSecurityGroups/join/action", - "Microsoft.Network/virtualNetworks/subnets/delete", - "Microsoft.Network/virtualNetworks/subnets/read", - "Microsoft.Network/virtualNetworks/subnets/write", - "Microsoft.OperationalInsights/workspaces/delete", - "Microsoft.OperationalInsights/workspaces/read", - "Microsoft.OperationalInsights/workspaces/write", - "Microsoft.OperationalInsights/workspaces/sharedKeys/action", - "Microsoft.OperationsManagement/solutions/delete", - "Microsoft.OperationsManagement/solutions/read", - "Microsoft.OperationsManagement/solutions/write", - "Microsoft.Storage/storageAccounts/delete", - "Microsoft.Storage/storageAccounts/read", - "Microsoft.Storage/storageAccounts/write", - "Microsoft.Storage/storageAccounts/blobServices/containers/delete", - "Microsoft.Storage/storageAccounts/blobServices/containers/read", - "Microsoft.Storage/storageAccounts/blobServices/containers/write", - "Microsoft.Storage/storageAccounts/blobServices/containers/lease/action", - "Microsoft.Storage/storageAccounts/blobServices/read", - "Microsoft.Storage/storageAccounts/listKeys/action", - "Microsoft.Resources/subscriptions/providers/read", - "Microsoft.Resources/subscriptions/read", - "Microsoft.Resources/subscriptions/resourcegroups/delete", - "Microsoft.Resources/subscriptions/resourcegroups/read", - "Microsoft.Resources/subscriptions/resourcegroups/write", - "Microsoft.Network/virtualNetworks/delete", - "Microsoft.Network/virtualNetworks/read", - "Microsoft.Network/virtualNetworks/write", - ] - } - - } - - caf-launchpad-contributor = { - name = "caf-launchpad-contributor" - useprefix = true - description = "Provide addition permissions on top of built-in Contributor role to manage landing zones deployment" - permissions = { - actions = [ - "Microsoft.Authorization/roleAssignments/delete", - "Microsoft.Authorization/roleAssignments/read", - "Microsoft.Authorization/roleAssignments/write", - "Microsoft.Authorization/roleDefinitions/delete", - "Microsoft.Authorization/roleDefinitions/read", - "Microsoft.Authorization/roleDefinitions/write", - "Microsoft.Resources/subscriptions/providers/read" - ] - } - } - -} - diff --git a/landingzones/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars b/landingzones/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars deleted file mode 100644 index e755b1ebd..000000000 --- a/landingzones/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars +++ /dev/null @@ -1,114 +0,0 @@ -keyvault_access_policies_azuread_apps = { - level0 = { - caf_launchpad_level0 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - # A maximum of 16 access policies per keyvault - level1 = { - caf_launchpad_level0 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # A maximum of 16 access policies per keyvault - level2 = { - caf_launchpad_level0 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - - # A maximum of 16 access policies per keyvault - level3 = { - caf_launchpad_level0 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - - # A maximum of 16 access policies per keyvault - level4 = { - caf_launchpad_level1 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - - secrets = { - caf_launchpad_level0 = { - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } -} - -keyvault_access_policies = { - # A maximum of 16 access policies per keyvault - level0 = { - keyvault_level0_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - # A maximum of 16 access policies per keyvault - level1 = { - keyvault_level1_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level1_rw" - secret_permissions = ["Get", "List"] - } - } - - # A maximum of 16 access policies per keyvault - level2 = { - keyvault_level2_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level2_rw" - secret_permissions = ["Get", "List"] - } - } - - - # A maximum of 16 access policies per keyvault - level3 = { - keyvault_level3_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level3_rw" - secret_permissions = ["Get", "List"] - } - } - - - # A maximum of 16 access policies per keyvault - level4 = { - keyvault_level4_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level4_rw" - secret_permissions = ["Get", "List"] - } - } - - - secrets = { - keyvault_level0_rw = { - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - keyvault_password_rotation = { - azuread_group_key = "keyvault_password_rotation" - secret_permissions = ["Set", "Get", "List", "Delete", ] - } - } -} diff --git a/landingzones/caf_launchpad/scenario/200/iam_managed_identities.tfvars b/landingzones/caf_launchpad/scenario/200/iam_managed_identities.tfvars deleted file mode 100644 index a5e76137c..000000000 --- a/landingzones/caf_launchpad/scenario/200/iam_managed_identities.tfvars +++ /dev/null @@ -1,32 +0,0 @@ - -managed_identities = { - level0 = { - # Used by the release agent to access the level0 keyvault and storage account with the tfstates in read / write - name = "landingzone-level0-msi" - resource_group_key = "security" - } - level1 = { - # Used by the release agent to access the level1 keyvault and storage account with the tfstates in read / write - # Has read access to level0 - name = "landingzone-level1-msi" - resource_group_key = "security" - } - level2 = { - # Used by the release agent to access the level2 keyvault and storage account with the tfstates in read / write - # Has read access to level1 - name = "landingzone-level2-msi" - resource_group_key = "security" - } - level3 = { - # Used by the release agent to access the level3 keyvault and storage account with the tfstates in read / write - # Has read access to level2 - name = "landingzone-level3-msi" - resource_group_key = "security" - } - level4 = { - # Used by the release agent to access the level4 keyvault and storage account with the tfstates in read / write - # Has read access to level3 - name = "landingzone-level4-msi" - resource_group_key = "security" - } -} diff --git a/landingzones/caf_launchpad/scenario/200/iam_role_mapping.tfvars b/landingzones/caf_launchpad/scenario/200/iam_role_mapping.tfvars deleted file mode 100644 index 23a919f2a..000000000 --- a/landingzones/caf_launchpad/scenario/200/iam_role_mapping.tfvars +++ /dev/null @@ -1,154 +0,0 @@ - -# -# Services supported: subscriptions, storage accounts and resource groups -# Can assign roles to: AD groups, AD object ID, AD applications, Managed identities -# -role_mapping = { - custom_role_mapping = { - subscriptions = { - logged_in_subscription = { - "caf-launchpad-contributor" = { - azuread_groups = { - keys = ["keyvault_level0_rw", "keyvault_level1_rw", "keyvault_level2_rw", "keyvault_level3_rw", "keyvault_level4_rw", ] - } - managed_identities = { - keys = ["level0", "level1", "level2", "level3", "level4"] - } - azuread_apps = { - keys = ["caf_launchpad_level0"] - } - } - } - } - } - - built_in_role_mapping = { - subscriptions = { - logged_in_subscription = { - "Contributor" = { - azuread_apps = { - keys = ["caf_launchpad_level0"] - } - managed_identities = { - keys = ["level0", "level1", "level2", "level3", "level4"] - } - } - } - } - resource_groups = { - level0 = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - security = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - networking = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - ops = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - siem = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - } - storage_accounts = { - level0 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - azuread_groups = { - keys = ["keyvault_level0_rw"] - } - azuread_apps = { - keys = ["caf_launchpad_level0"] - } - managed_identities = { - keys = ["level0"] - } - } - "Storage Blob Data Reader" = { - azuread_groups = { - keys = ["keyvault_level1_rw"] - } - } - } - level1 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - azuread_groups = { - keys = ["keyvault_level1_rw"] - } - managed_identities = { - keys = ["level1"] - } - } - "Storage Blob Data Reader" = { - azuread_groups = { - keys = ["keyvault_level2_rw"] - } - } - } - level2 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - azuread_groups = { - keys = ["keyvault_level2_rw"] - } - managed_identities = { - keys = ["level2"] - } - } - "Storage Blob Data Reader" = { - azuread_groups = { - keys = ["keyvault_level3_rw"] - } - } - } - level3 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - azuread_groups = { - keys = ["keyvault_level3_rw"] - } - managed_identities = { - keys = ["level3"] - } - } - "Storage Blob Data Reader" = { - azuread_groups = { - keys = ["keyvault_level4_rw"] - } - } - } - } - } - -} diff --git a/landingzones/caf_launchpad/scenario/200/keyvaults.tfvars b/landingzones/caf_launchpad/scenario/200/keyvaults.tfvars deleted file mode 100644 index 9b407a31d..000000000 --- a/landingzones/caf_launchpad/scenario/200/keyvaults.tfvars +++ /dev/null @@ -1,204 +0,0 @@ - -keyvaults = { - level0 = { - name = "level0" - resource_group_key = "level0" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level0" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - level1 = { - name = "level1" - resource_group_key = "level1" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level1" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - level2 = { - name = "level2" - resource_group_key = "level2" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level2" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - level3 = { - name = "level3" - resource_group_key = "level3" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level3" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - level4 = { - name = "level4" - resource_group_key = "level4" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level4" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - secrets = { - name = "secrets" - resource_group_key = "security" - region = "region1" - sku_name = "premium" - soft_delete_enabled = true - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - - } -} diff --git a/landingzones/caf_launchpad/scenario/200/networking.tfvars b/landingzones/caf_launchpad/scenario/200/networking.tfvars deleted file mode 100644 index e21c316fe..000000000 --- a/landingzones/caf_launchpad/scenario/200/networking.tfvars +++ /dev/null @@ -1,110 +0,0 @@ - -################################################## -# -# Networking resources -# -################################################## - - -public_ip_addresses = { - bastion_host_rg1 = { - name = "pip1" - resource_group_key = "networking" - sku = "Standard" - allocation_method = "Static" - ip_version = "IPv4" - idle_timeout_in_minutes = "4" - - # you can setup up to 5 key - diagnostic_profiles = { - bastion_host_rg1 = { - definition_key = "public_ip_address" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - } -} - -vnets = { - devops_region1 = { - resource_group_key = "networking" - region = "region1" - vnet = { - name = "devops" - address_space = ["10.100.100.0/24"] - } - specialsubnets = {} - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["10.100.100.24/29"] - nsg_key = "azure_bastion_nsg" - } - jumpbox = { - name = "jumpbox" - cidr = ["10.100.100.32/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level0 = { - name = "level0" - cidr = ["10.100.100.40/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level1 = { - name = "level1" - cidr = ["10.100.100.48/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level2 = { - name = "level2" - cidr = ["10.100.100.56/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level3 = { - name = "level3" - cidr = ["10.100.100.64/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level4 = { - name = "level4" - cidr = ["10.100.100.72/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - private_endpoints = { - name = "private_endpoints" - cidr = ["10.100.100.128/25"] - enforce_private_link_endpoint_network_policies = true - } - } - - # you can setup up to 5 keys - vnet diganostic - diagnostic_profiles = { - vnet = { - definition_key = "networking_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - } -} - - -route_tables = { - default_no_internet = { - name = "default_no_internet" - resource_group_key = "networking" - } -} - -azurerm_routes = { - no_internet = { - name = "no_internet" - resource_group_key = "networking" - route_table_key = "default_no_internet" - address_prefix = "0.0.0.0/0" - next_hop_type = "None" - } -} diff --git a/landingzones/caf_launchpad/scenario/200/networking_nsg_definition.tfvars b/landingzones/caf_launchpad/scenario/200/networking_nsg_definition.tfvars deleted file mode 100644 index 8b558b104..000000000 --- a/landingzones/caf_launchpad/scenario/200/networking_nsg_definition.tfvars +++ /dev/null @@ -1,141 +0,0 @@ - -# -# Definition of the networking security groups -# -network_security_group_definition = { - # This entry is applied to all subnets with no NSG defined - empty_nsg = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } - - azure_bastion_nsg = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } - - jumphost = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "ssh-inbound-22", - priority = "200" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - -} diff --git a/landingzones/caf_launchpad/scenario/200/readme.md b/landingzones/caf_launchpad/scenario/200/readme.md deleted file mode 100644 index 82f7b4440..000000000 --- a/landingzones/caf_launchpad/scenario/200/readme.md +++ /dev/null @@ -1,56 +0,0 @@ -# Launchpad - scenario 200 - -The 200 scenario is an extension of the 100 scenario, meaning you can upgrade a 100 scenario to a 200. -The 200 scenario is designed to demonstrate a more secure environment but is not recommended for production use. -The focus of this scenario is to be able to deploy a more advanced launchpad from a remote machine and use the portal to review the settings in a non-constrained environment. -For example in this scenario you can go to the Key Vaults and view the secrets from the portal. A feature that is disabled in the 300+ scenarios. We recommend using the 200 scenario for demonstration or building new capabilities. - -An estimated time of 20 minutes is required to deploy this scenario. - -## Pre-requisites - -This scenario require the following privileges: - -| Component | Privileges | -|--------------------|--------------------------------| -| Active Directory | Application Administrator role | -| Azure subscription | Subscription owner | - -## Deployment - -```bash -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ - -level level0 \ - -a apply - -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ - -level level0 \ - -a destroy -``` - -## Architecture diagram - -![Launchpad 200](../../documentation/img/launchpad-200.png) - -## Services deployed in this scenario - -| Component | Purpose | -|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Resource group | Multiple resource groups are created to isolate the services | -| Storage account | A storage account for remote tfstate management is provided for each level of the framework. Additional storage accounts are created for diagnostic logs. | -| Keyvault | The launchpad keyvault hosts all secrets required by the rover to access the remote states. The secret keyvault is used to host all Azure AD users, applications and virtual machines's ssh key. | -| Virtual network | To secure the communication between the services a dedicated virtual network is deployed with a gateway subnet, bastion service, jumpbox and azure DevOps release agents. Service endpoints is enabled but not configured. | -| Bastion host service | Is use to support the access to the rover in scenario 300 and 400. | -| Jumpbox | A Linux server with the docker engine to run the rover and perform the deployment of the scenario 300 and 400. | -| Log analytics | A central log analytics workspace is created to collect all diagnostics and metrics information. Solutions are also deployed. | -| Diagnostic profiles | Default settings with 7 days retention of diagnostic profile is provided for all services. | -| Diagnostic destination | Operation sends the logs to a log analytics workspace and SIEM send all security logs to a storage account. | -| Diagnostic | Is enabled by default on all services. | -| Azure AD Users | An Azure AD user is created. This user is used in scenario 300 and 400 to own the Azure DevOps Personal Access Token (PAT) rotation. | -| Azure AD Applications | An Azure AD application is created. This account is mainly use to bootstrap the services during the initialization. It is also considered as a breakglass account for the launchpad landing zones. | -| Azure AD API permissions | A set of API permissions assigned to the Azure AD application to support management of the landing zones in a pipeline. | -| Managed Identities | A user managed Identity account is created for each Azure DevOps agent. This account is configured to get access to the keyvaults and Azure storage accounts | \ No newline at end of file diff --git a/landingzones/caf_launchpad/scenario/200/storage_accounts.tfvars b/landingzones/caf_launchpad/scenario/200/storage_accounts.tfvars deleted file mode 100644 index bd60a50f5..000000000 --- a/landingzones/caf_launchpad/scenario/200/storage_accounts.tfvars +++ /dev/null @@ -1,101 +0,0 @@ - -storage_accounts = { - level0 = { - name = "level0" - resource_group_key = "level0" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - ## Those tags must never be changed after being set as they are used by the rover to locate the launchpad and the tfstates. - # Only adjust the environment value at creation time - tfstate = "level0" - environment = "sandpit" - launchpad = "launchpad" - ## - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level1 = { - name = "level1" - resource_group_key = "level1" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level1" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level2 = { - name = "level2" - resource_group_key = "level2" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level2" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level3 = { - name = "level3" - resource_group_key = "level3" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level3" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level4 = { - name = "level4" - resource_group_key = "level4" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level4" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - - } - -} \ No newline at end of file diff --git a/landingzones/caf_launchpad/scenario/200/subscriptions.tfvars b/landingzones/caf_launchpad/scenario/200/subscriptions.tfvars deleted file mode 100644 index 9e98ae770..000000000 --- a/landingzones/caf_launchpad/scenario/200/subscriptions.tfvars +++ /dev/null @@ -1,20 +0,0 @@ - -subscriptions = { - logged_in_subscription = { - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "subscription_operations" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "subscription_siem" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } -} \ No newline at end of file diff --git a/landingzones/caf_launchpad/scripts/cloud-init-install-rover-tools.config b/landingzones/caf_launchpad/scripts/cloud-init-install-rover-tools.config deleted file mode 100644 index 53cd432e8..000000000 --- a/landingzones/caf_launchpad/scripts/cloud-init-install-rover-tools.config +++ /dev/null @@ -1,49 +0,0 @@ -#cloud-config - -apt: - preserve_sources_list: true - sources: - azure-cli.list: - source: "deb https://packages.microsoft.com/repos/azure-cli/ bionic main" - key: | - -----BEGIN PGP PUBLIC KEY BLOCK----- - Version: GnuPG v1.4.7 (GNU/Linux) - - mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT - LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV - 7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag - OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j - H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr - M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs - ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC - AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH - /32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe - MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy - 7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV - KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ - XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+ - NdCFTW7wY0Fb1fWJ+/KTsC4= - =J6gs - -----END PGP PUBLIC KEY BLOCK----- -package_update: true - -packages: - - ca-certificates - - curl - - apt-transport-https - - lsb-release - - azure-cli - -snap: - commands: - - snap install kubectl --classic -# Install docker and docker-compose -runcmd: - - [ sh, -c, 'curl -sSL https://get.docker.com/ | sh' ] - - [ sh, -c, 'curl -L https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep "tag_name" | cut -d \" -f4)/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose' ] - - [ sh, -c, 'sudo chmod +x /usr/local/bin/docker-compose' ] - -# Add default auto created user to docker group -system_info: - default_user: - groups: [docker] \ No newline at end of file diff --git a/landingzones/caf_launchpad/variables.tf b/landingzones/caf_launchpad/variables.tf deleted file mode 100644 index 6ff3d9dd7..000000000 --- a/landingzones/caf_launchpad/variables.tf +++ /dev/null @@ -1,211 +0,0 @@ -# Map of the current tfstate -variable "tfstate_storage_account_name" { - default = null -} -variable "tfstate_container_name" { - default = null -} -variable "tfstate_key" { - default = null -} -variable "tfstate_resource_group_name" { - default = null -} - -variable "tenant_id" {} -variable "landingzone" { - description = "The landing zone name is used to reference the tfstate in configuration files. Therefore while set it is recommended not to change" -} - -variable "passthrough" { - default = false -} -variable "random_length" { - default = null -} - -variable "inherit_tags" { - default = false -} - -variable "default_region" { - description = "Define the default region where services are deployed if the location is not set at the resource level" - default = "region1" -} - -variable "regions" { - type = map(any) - description = "List of the regions where services can be deployed. This impact the diagnostics logs settings" - default = { - region1 = "southeastasia" - } -} - -variable "enable" { - description = "Map of services defined in the configuration file you want to disable during a deployment" - default = {} -} - -variable "prefix" { - default = null -} - -variable "use_slug" { - default = true -} - -variable "log_analytics" { - default = {} -} - -variable "event_hub_namespaces" { - default = {} -} - -# Do not change the default value to be able to upgrade to the standard launchpad -variable "tf_name" { - description = "Name of the terraform state in the blob storage (Does not include the extension .tfstate). Setup by the rover. Leave empty in the configuration file" - default = "" -} - -variable "resource_groups" {} - -variable "storage_accounts" {} -variable "keyvaults" {} -variable "keyvault_access_policies" { - default = {} -} -variable "keyvault_keys" { - default = {} -} -variable "dynamic_keyvault_secrets" {} - -variable "subscriptions" { - default = {} -} - -## Azure Active Directory -variable "azuread_apps" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "azuread_users" { - default = {} -} -variable "azuread_roles" { - default = {} -} -variable "managed_identities" { - default = {} -} - -variable "networking" { - default = {} -} - -variable "compute" { - default = {} -} - -variable "launchpad_key_names" {} - -variable "custom_role_definitions" { - default = {} -} -variable "role_mapping" { - default = { - built_in_role_mapping = {} - custom_role_mapping = {} - } -} - -variable "tags" { - type = map(any) - default = {} -} - -variable "rover_version" {} - -variable "user_type" {} - -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} - -variable "aad_users" { - default = {} -} - -variable "aad_roles" { - default = {} -} - -variable "azuread_api_permissions" { - default = {} -} - -variable "environment" { - type = string - description = "This variable is set by the rover during the deployment based on the -env or -environment flags. Default to sandpit" -} - -variable "diagnostics" { - default = {} -} - -variable "diagnostics_definition" { - default = {} -} - -variable "diagnostics_destinations" { - default = {} -} - -variable "diagnostic_event_hub_namespaces" { - default = {} -} - -variable "diagnostic_log_analytics" { - default = {} -} - -variable "diagnostic_storage_accounts" { - default = {} -} - -variable "keyvault_access_policies_azuread_apps" { - default = {} -} - -variable "virtual_machines" { - default = {} -} - -variable "bastion_hosts" { - default = {} -} - -variable "vnets" { - default = {} -} - -variable "network_security_group_definition" { - default = {} -} - -variable "public_ip_addresses" { - default = {} -} - -variable "azurerm_routes" { - default = {} -} - -variable "route_tables" { - default = {} -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml b/landingzones/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml deleted file mode 100644 index c430b2385..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: aadpodidentity.k8s.io/v1 -kind: AzureIdentity -metadata: - name: podmi-caf-rover-platform-level0 -spec: - type: 0 - resourceID: ${resource_id} - clientID: ${client_id} ---- -apiVersion: aadpodidentity.k8s.io/v1 -kind: AzureIdentityBinding -metadata: - name: podmi-gitlab-runner-binding -spec: - azureIdentity: podmi-caf-rover-platform-level0 - selector: podmi-caf-rover-platform-level0 \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf deleted file mode 100644 index 05f60b4d1..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf +++ /dev/null @@ -1,120 +0,0 @@ -resource "kubernetes_namespace" "ns" { - metadata { - name = var.aad_pod_identity.namespace - } -} - -module "build" { - depends_on = [kubernetes_namespace.ns] - source = "./build" - for_each = try(data.kustomization_overlay.aad_pod_identity, {}) - - settings = each.value -} - - - -data "kustomization_overlay" "aad_pod_identity" { - for_each = local.msi - - resources = [ - "aad-msi-binding.yaml", - ] - - namespace = var.aad_pod_identity.namespace - - patches { - patch = <<-EOF - - op: replace - path: /spec/resourceID - value: ${each.value.id} - EOF - - target = { - kind = "AzureIdentity" - } - } - - patches { - patch = <<-EOF - - op: replace - path: /spec/clientID - value: ${each.value.client_id} - EOF - - target = { - kind = "AzureIdentity" - } - } - - patches { - patch = <<-EOF - - op: replace - path: /metadata/name - value: ${each.value.azureIdentity} - EOF - - target = { - kind = "AzureIdentity" - } - } - - patches { - patch = <<-EOF - - op: replace - path: /metadata/name - value: ${each.value.azureIdentity}-binding - EOF - - target = { - kind = "AzureIdentityBinding" - } - } - - patches { - patch = <<-EOF - - op: replace - path: /spec/azureIdentity - value: ${each.value.azureIdentity} - EOF - - target = { - kind = "AzureIdentityBinding" - } - } - - patches { - patch = <<-EOF - - op: replace - path: /spec/selector - value: ${each.value.selector} - EOF - - target = { - kind = "AzureIdentityBinding" - } - } -} - -output "manifests" { - value = data.kustomization_overlay.aad_pod_identity -} - -locals { - msi = { - for msi in flatten( - [ - for key, value in var.managed_identities : [ - for msi_key in value.msi_keys : { - key = key - msi_key = msi_key - client_id = local.remote.managed_identities[value.lz_key][msi_key].client_id - id = local.remote.managed_identities[value.lz_key][msi_key].id - azureIdentity = value["aad_msi_bindings"][msi_key].azureIdentity - selector = value["aad_msi_bindings"][msi_key].selector - } - ] - ] - ) : format("%s-%s", msi.key, msi.msi_key) => msi - } -} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/backend.azurerm b/landingzones/caf_solution/add-ons/aad-pod-identity/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf deleted file mode 100644 index 985bd96f5..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf +++ /dev/null @@ -1,16 +0,0 @@ -resource "kustomization_resource" "p0" { - for_each = var.settings.ids_prio[0] - manifest = var.settings.manifests[each.value] -} - -resource "kustomization_resource" "p1" { - depends_on = [kustomization_resource.p0] - for_each = var.settings.ids_prio[1] - manifest = var.settings.manifests[each.value] -} - -resource "kustomization_resource" "p2" { - depends_on = [kustomization_resource.p1] - for_each = var.settings.ids_prio[2] - manifest = var.settings.manifests[each.value] -} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/build/main.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/build/main.tf deleted file mode 100644 index e65c6fa22..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/build/main.tf +++ /dev/null @@ -1,7 +0,0 @@ -terraform { - required_providers { - kustomization = { - source = "kbst/kustomization" - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/build/variables.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/build/variables.tf deleted file mode 100644 index f5c321890..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/build/variables.tf +++ /dev/null @@ -1,2 +0,0 @@ -variable "settings" { -} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf deleted file mode 100644 index d458c18a1..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf +++ /dev/null @@ -1,54 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = try(each.value.container, local.landingzone[try(each.value.level, "current")].container_name) - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings - diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics - - remote = { - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - global_settings = local.global_settings - diagnostics = local.diagnostics - - - aks_clusters = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) - } - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) - } - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) - } - } - -} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/main.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/main.tf deleted file mode 100644 index f0cc7ddbe..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/main.tf +++ /dev/null @@ -1,17 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.51.0" - } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 2.0.2" - } - kustomization = { - source = "kbst/kustomization" - version = "~> 0.4.0" - } - } - required_version = ">= 0.13" -} diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/providers.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/providers.tf deleted file mode 100644 index be2b3abb1..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/providers.tf +++ /dev/null @@ -1,32 +0,0 @@ - -provider "azurerm" { - features { - } -} - -provider "kubernetes" { - host = local.k8sconfigs[var.aks_cluster_key].host - username = local.k8sconfigs[var.aks_cluster_key].username - password = local.k8sconfigs[var.aks_cluster_key].password - client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate - client_key = local.k8sconfigs[var.aks_cluster_key].client_key - cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate -} - -provider "kustomization" { - kubeconfig_raw = local.k8sconfigs[var.aks_cluster_key].kube_admin_config_raw -} - -locals { - k8sconfigs = { - for key, value in var.aks_clusters : key => { - kube_admin_config_raw = local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config_raw - host = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.host : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.host - username = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.username : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.username - password = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.password : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.password - client_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_certificate) - client_key = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_key) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_key) - cluster_ca_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.cluster_ca_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.cluster_ca_certificate) - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aad-pod-identity/variables.tf b/landingzones/caf_solution/add-ons/aad-pod-identity/variables.tf deleted file mode 100644 index 971033737..000000000 --- a/landingzones/caf_solution/add-ons/aad-pod-identity/variables.tf +++ /dev/null @@ -1,36 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "landingzone" {} -variable "rover_version" { - default = null -} -variable "tags" { - default = {} -} - -###### - -variable "aks_cluster_key" { - description = "AKS cluster key to deploy the Gitlab Helm charts. The key must be defined in the variable aks_clusters" -} -variable "aks_cluster_vnet_key" { - -} -variable "aks_clusters" {} -variable "vnets" {} -variable "managed_identities" { - description = "Map of the user managed identities." -} - -variable "aad_pod_identity" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf deleted file mode 100644 index 96c672df0..000000000 --- a/landingzones/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf +++ /dev/null @@ -1,58 +0,0 @@ - -# Get the details of the node pool's resource group created by AKS -data "azurerm_resource_group" "noderg" { - for_each = var.aks_clusters - name = local.remote.aks_clusters[each.value.lz_key][each.value.key].node_resource_group -} - -# -# Set permissions to the kubelet and cluster identity -# -resource "azurerm_role_assignment" "kubelet_noderg_miop" { - for_each = var.aks_clusters - - scope = data.azurerm_resource_group.noderg[each.key].id - role_definition_name = "Managed Identity Operator" - principal_id = local.remote.aks_clusters[each.value.lz_key][each.value.key].kubelet_identity[0].object_id -} - -resource "azurerm_role_assignment" "kubelet_noderg_vmcontrib" { - for_each = var.aks_clusters - - scope = data.azurerm_resource_group.noderg[each.key].id - role_definition_name = "Virtual Machine Contributor" - principal_id = local.remote.aks_clusters[each.value.lz_key][each.value.key].kubelet_identity[0].object_id -} - - -resource "azurerm_role_assignment" "kubelet_vnet_networkcontrib" { - for_each = toset(var.vnets[var.aks_cluster_vnet_key].subnet_keys) - - scope = local.remote.vnets[var.vnets[var.aks_cluster_vnet_key].lz_key][var.vnets[var.aks_cluster_vnet_key].key].subnets[each.value].id - role_definition_name = "Network Contributor" - principal_id = local.remote.aks_clusters[var.aks_clusters[var.aks_cluster_key].lz_key][var.aks_cluster_key].identity[0].principal_id -} - -resource "azurerm_role_assignment" "kubelet_user_msi" { - for_each = local.msi_to_grant_permissions - - scope = each.value.id - role_definition_name = "Managed Identity Operator" - principal_id = local.remote.aks_clusters[var.aks_clusters[var.aks_cluster_key].lz_key][var.aks_cluster_key].kubelet_identity[0].object_id -} - -locals { - msi_to_grant_permissions = { - for msi in flatten( - [ - for key, value in var.managed_identities : [ - for msi_key in value.msi_keys : { - key = key - msi_key = msi_key - id = local.remote.managed_identities[value.lz_key][msi_key].id - } - ] - ] - ) : format("%s-%s", msi.key, msi.msi_key) => msi - } -} diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/backend.azurerm b/landingzones/caf_solution/add-ons/aks-secure-baseline/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_solution/add-ons/aks-secure-baseline/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml b/landingzones/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml deleted file mode 100644 index 373d8b437..000000000 --- a/landingzones/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - https://raw.githubusercontent.com/Azure/caf-terraform-landingzones-starter/starter/enterprise_scale/construction_sets/aks/online/aks_secure_baseline/cluster-baseline-settings/flux.yaml \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf deleted file mode 100644 index d458c18a1..000000000 --- a/landingzones/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf +++ /dev/null @@ -1,54 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = try(each.value.container, local.landingzone[try(each.value.level, "current")].container_name) - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings - diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics - - remote = { - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - global_settings = local.global_settings - diagnostics = local.diagnostics - - - aks_clusters = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) - } - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) - } - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) - } - } - -} diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/main.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/main.tf deleted file mode 100644 index ac7602c81..000000000 --- a/landingzones/caf_solution/add-ons/aks-secure-baseline/main.tf +++ /dev/null @@ -1,17 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.51.0" - } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 2.0.2" - } - kustomization = { - source = "kbst/kustomization" - version = ">= 0.4.0" - } - } - required_version = ">= 0.13" -} diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/providers.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/providers.tf deleted file mode 100644 index be2b3abb1..000000000 --- a/landingzones/caf_solution/add-ons/aks-secure-baseline/providers.tf +++ /dev/null @@ -1,32 +0,0 @@ - -provider "azurerm" { - features { - } -} - -provider "kubernetes" { - host = local.k8sconfigs[var.aks_cluster_key].host - username = local.k8sconfigs[var.aks_cluster_key].username - password = local.k8sconfigs[var.aks_cluster_key].password - client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate - client_key = local.k8sconfigs[var.aks_cluster_key].client_key - cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate -} - -provider "kustomization" { - kubeconfig_raw = local.k8sconfigs[var.aks_cluster_key].kube_admin_config_raw -} - -locals { - k8sconfigs = { - for key, value in var.aks_clusters : key => { - kube_admin_config_raw = local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config_raw - host = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.host : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.host - username = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.username : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.username - password = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.password : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.password - client_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_certificate) - client_key = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_key) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_key) - cluster_ca_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.cluster_ca_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.cluster_ca_certificate) - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf deleted file mode 100644 index f2208c9bd..000000000 --- a/landingzones/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf +++ /dev/null @@ -1,22 +0,0 @@ -# Process the Kustomization in the current folder -data "kustomization_build" "flux" { - path = "." -} - -resource "kustomization_resource" "cluster_secure_baseline_p0" { - # depends_on = [kubernetes_namespace.cluster_secure_baseline] - for_each = data.kustomization_build.flux.ids_prio[0] - manifest = data.kustomization_build.flux.manifests[each.value] -} - -resource "kustomization_resource" "cluster_secure_baseline_p1" { - depends_on = [kustomization_resource.cluster_secure_baseline_p0] - for_each = data.kustomization_build.flux.ids_prio[1] - manifest = data.kustomization_build.flux.manifests[each.value] -} - -resource "kustomization_resource" "cluster_secure_baseline_p2" { - depends_on = [kustomization_resource.cluster_secure_baseline_p1] - for_each = data.kustomization_build.flux.ids_prio[2] - manifest = data.kustomization_build.flux.manifests[each.value] -} diff --git a/landingzones/caf_solution/add-ons/aks-secure-baseline/variables.tf b/landingzones/caf_solution/add-ons/aks-secure-baseline/variables.tf deleted file mode 100644 index 971033737..000000000 --- a/landingzones/caf_solution/add-ons/aks-secure-baseline/variables.tf +++ /dev/null @@ -1,36 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "landingzone" {} -variable "rover_version" { - default = null -} -variable "tags" { - default = {} -} - -###### - -variable "aks_cluster_key" { - description = "AKS cluster key to deploy the Gitlab Helm charts. The key must be defined in the variable aks_clusters" -} -variable "aks_cluster_vnet_key" { - -} -variable "aks_clusters" {} -variable "vnets" {} -variable "managed_identities" { - description = "Map of the user managed identities." -} - -variable "aad_pod_identity" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/app/main.tf b/landingzones/caf_solution/add-ons/aks_applications/app/main.tf deleted file mode 100644 index 1191eedce..000000000 --- a/landingzones/caf_solution/add-ons/aks_applications/app/main.tf +++ /dev/null @@ -1,7 +0,0 @@ -provider "kubernetes" { - alias = "k8s" -} - -provider "helm" { - alias = "helm" -} diff --git a/landingzones/caf_solution/add-ons/aks_applications/app/module.tf b/landingzones/caf_solution/add-ons/aks_applications/app/module.tf deleted file mode 100644 index 2d4288893..000000000 --- a/landingzones/caf_solution/add-ons/aks_applications/app/module.tf +++ /dev/null @@ -1,48 +0,0 @@ -resource "kubernetes_namespace" "namespaces" { - for_each = var.namespaces - metadata { - annotations = try(each.value.annotations, null) - labels = try(each.value.labels, null) - name = each.value.name - } - - provider = kubernetes.k8s -} - -# https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release -resource "helm_release" "charts" { - for_each = var.helm_charts - - name = each.value.name - repository = each.value.repository - chart = each.value.chart - - namespace = each.value.namespace - wait = try(each.value.wait, true) - timeout = try(each.value.timeout, 900) - skip_crds = try(each.value.skip_crds, false) - create_namespace = try(each.value.create_namespace, false) - - dynamic "set" { - for_each = try(each.value.sets, {}) - content { - name = set.key - value = set.value - } - } - - dynamic "set_sensitive" { - for_each = try(each.value.sets_sensitive, {}) - content { - name = set_sensitive.key - value = set_sensitive.value - } - } - - provider = helm.helm - - depends_on = [kubernetes_namespace.namespaces] - # values = [ - # "${file("values.yaml")}" - # ] -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/app/output.tf b/landingzones/caf_solution/add-ons/aks_applications/app/output.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/landingzones/caf_solution/add-ons/aks_applications/app/variables.tf b/landingzones/caf_solution/add-ons/aks_applications/app/variables.tf deleted file mode 100644 index 4a0225192..000000000 --- a/landingzones/caf_solution/add-ons/aks_applications/app/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "cluster" {} - -variable "namespaces" {} - -variable "helm_charts" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/applications.tf b/landingzones/caf_solution/add-ons/aks_applications/applications.tf deleted file mode 100644 index b1f674491..000000000 --- a/landingzones/caf_solution/add-ons/aks_applications/applications.tf +++ /dev/null @@ -1,27 +0,0 @@ -module "app1" { - source = "./app" - for_each = try(local.clusters[var.cluster_re1_key], null) != null ? { (var.cluster_re1_key) = local.clusters[var.cluster_re1_key] } : {} - - cluster = each.value - namespaces = var.namespaces - helm_charts = var.helm_charts - - providers = { - kubernetes.k8s = kubernetes.k8s1 - helm.helm = helm.helm1 - } -} - -module "app2" { - source = "./app" - for_each = try(local.clusters[var.cluster_re2_key], null) != null ? { (var.cluster_re2_key) = local.clusters[var.cluster_re2_key] } : {} - - cluster = each.value - namespaces = var.namespaces - helm_charts = var.helm_charts - - providers = { - kubernetes.k8s = kubernetes.k8s2 - helm.helm = helm.helm2 - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/backend.azurerm b/landingzones/caf_solution/add-ons/aks_applications/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_solution/add-ons/aks_applications/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf b/landingzones/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf deleted file mode 100644 index cf16e86c6..000000000 --- a/landingzones/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf +++ /dev/null @@ -1,54 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - remote = { - aks_clusters = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aks_clusters[key], {})) - } - } - - clusters = local.remote.aks_clusters[var.landingzone.global_settings_key] - k8sconfigs = { for key, value in values(local.clusters) : key => { - host = value.enable_rbac ? value.kube_admin_config.0.host : value.kube_config.0.host - username = value.enable_rbac ? value.kube_admin_config.0.username : value.kube_config.0.username - password = value.enable_rbac ? value.kube_admin_config.0.password : value.kube_config.0.password - client_certificate = value.enable_rbac ? base64decode(value.kube_admin_config.0.client_certificate) : base64decode(value.kube_config.0.client_certificate) - client_key = value.enable_rbac ? base64decode(value.kube_admin_config.0.client_key) : base64decode(value.kube_config.0.client_key) - cluster_ca_certificate = value.enable_rbac ? base64decode(value.kube_admin_config.0.cluster_ca_certificate) : base64decode(value.kube_config.0.cluster_ca_certificate) - } - } - -} diff --git a/landingzones/caf_solution/add-ons/aks_applications/main.tf b/landingzones/caf_solution/add-ons/aks_applications/main.tf deleted file mode 100644 index 2222bc4d2..000000000 --- a/landingzones/caf_solution/add-ons/aks_applications/main.tf +++ /dev/null @@ -1,75 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 1.13.2" - } - helm = { - source = "hashicorp/helm" - version = "~> 1.3.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - - -provider "kubernetes" { - load_config_file = false - host = try(local.k8sconfigs[0].host, null) - username = try(local.k8sconfigs[0].username, null) - password = try(local.k8sconfigs[0].password, null) - client_certificate = try(local.k8sconfigs[0].client_certificate, null) - client_key = try(local.k8sconfigs[0].client_key, null) - cluster_ca_certificate = try(local.k8sconfigs[0].cluster_ca_certificate, null) - alias = "k8s1" -} - -provider "helm" { - kubernetes { - load_config_file = false - host = try(local.k8sconfigs[0].host, null) - username = try(local.k8sconfigs[0].username, null) - password = try(local.k8sconfigs[0].password, null) - client_certificate = try(local.k8sconfigs[0].client_certificate, null) - client_key = try(local.k8sconfigs[0].client_key, null) - cluster_ca_certificate = try(local.k8sconfigs[0].cluster_ca_certificate, null) - } - alias = "helm1" -} - -provider "kubernetes" { - load_config_file = false - host = try(local.k8sconfigs[1].host, null) - username = try(local.k8sconfigs[1].username, null) - password = try(local.k8sconfigs[1].password, null) - client_certificate = try(local.k8sconfigs[1].client_certificate, null) - client_key = try(local.k8sconfigs[1].client_key, null) - cluster_ca_certificate = try(local.k8sconfigs[1].cluster_ca_certificate, null) - alias = "k8s2" -} - -provider "helm" { - kubernetes { - load_config_file = false - host = try(local.k8sconfigs[1].host, null) - username = try(local.k8sconfigs[1].username, null) - password = try(local.k8sconfigs[1].password, null) - client_certificate = try(local.k8sconfigs[1].client_certificate, null) - client_key = try(local.k8sconfigs[1].client_key, null) - cluster_ca_certificate = try(local.k8sconfigs[1].cluster_ca_certificate, null) - } - alias = "helm2" -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/aks_applications/output.tf b/landingzones/caf_solution/add-ons/aks_applications/output.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/landingzones/caf_solution/add-ons/aks_applications/variables.tf b/landingzones/caf_solution/add-ons/aks_applications/variables.tf deleted file mode 100644 index 7ad77ea93..000000000 --- a/landingzones/caf_solution/add-ons/aks_applications/variables.tf +++ /dev/null @@ -1,36 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_resource_group_name" {} -# variable tfstate_key {} - -variable "global_settings" { - default = {} -} - -# variable tenant_id {} -variable "landingzone" {} - -variable "namespaces" {} - -variable "tags" { - default = null - type = map(any) -} - -variable "helm_charts" {} - -variable "rover_version" { - default = null -} - -variable "cluster_re1_key" { - default = null -} -variable "cluster_re2_key" { - default = null -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo.tf deleted file mode 100644 index 9d2b42c02..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/azdo.tf +++ /dev/null @@ -1,15 +0,0 @@ -# The PAT token must be provisioned in a different deployment -provider "azuredevops" { - org_service_url = var.azure_devops.url - personal_access_token = data.azurerm_key_vault_secret.pat.value -} - -data "azurerm_key_vault_secret" "pat" { - name = var.azure_devops.pats["admin"].secret_name - key_vault_id = local.remote.keyvaults[var.azure_devops.pats["admin"].lz_key][var.azure_devops.pats["admin"].keyvault_key].id - -} - -data "azuredevops_project" "project" { - name = var.azure_devops.project -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf deleted file mode 100644 index 7832ba6e9..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf +++ /dev/null @@ -1,52 +0,0 @@ - -locals { - organization_agent_pools = try(var.azure_devops.organization_agent_pools, {}) - project_agent_pools = try(var.azure_devops.project_agent_pools, {}) -} - - -## Agent pools -## Those pools are created in the organization, not the project -resource "azuredevops_agent_pool" "pool" { - for_each = try(var.azure_devops.organization_agent_pools, {}) - - name = each.value.name - auto_provision = lookup(each.value, "auto_provision", false) -} - -# -# add the agent pools into the project -# - -data "azuredevops_agent_pool" "pool" { - depends_on = [azuredevops_agent_pool.pool] - for_each = try(var.azure_devops.project_agent_pools, {}) - - name = each.value.name -} - -resource "azuredevops_agent_queue" "agent_queue" { - for_each = data.azuredevops_agent_pool.pool - - project_id = data.azuredevops_project.project.id - agent_pool_id = each.value.id - - lifecycle { - ignore_changes = [ - agent_pool_id - ] - } -} - -# -# Grant acccess to queue to all pipelines in the project -# - -resource "azuredevops_resource_authorization" "queue" { - for_each = data.azuredevops_agent_pool.pool - - project_id = data.azuredevops_project.project.id - resource_id = azuredevops_agent_queue.agent_queue[each.key].id - type = "queue" - authorized = true -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo_pipelines.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo_pipelines.tf deleted file mode 100644 index 6fe4fdcbb..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/azdo_pipelines.tf +++ /dev/null @@ -1,43 +0,0 @@ -data "azuredevops_git_repositories" "repos" { - project_id = data.azuredevops_project.project.id -} - - -locals { - repositories = zipmap(tolist(data.azuredevops_git_repositories.repos.repositories.*.name), tolist(data.azuredevops_git_repositories.repos.repositories)) -} - -resource "azuredevops_build_definition" "build_definition" { - - for_each = try(var.azure_devops.pipelines, {}) - project_id = data.azuredevops_project.project.id - name = each.value.name - path = each.value.folder - - variable_groups = lookup(each.value, "variable_group_keys", null) == null ? null : [ - for key in each.value.variable_group_keys : - azuredevops_variable_group.variable_group[key].id - ] - - repository { - repo_id = local.repositories[each.value.git_repo_name].id - repo_type = each.value.repo_type - yml_path = each.value.yaml - branch_name = lookup(each.value, "branch_name", null) - # service_connection_id = lookup(each.value, "repo_type", null) == "github" ? null : azuredevops_serviceendpoint_azurerm.github[each.value.service_connection_key].id - } - - ci_trigger { - use_yaml = true - } - - dynamic "variable" { - for_each = try(each.value.variables, {}) - - content { - name = variable.key - value = variable.value - } - } - -} diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf deleted file mode 100644 index 760919a25..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf +++ /dev/null @@ -1,36 +0,0 @@ - -data "azurerm_key_vault_secret" "client_secret" { - depends_on = [module.caf] - for_each = try(var.azure_devops.service_endpoints, {}) - - name = format("%s-client-secret", local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].secret_name_client_secret) - key_vault_id = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].id -} - -resource "azuredevops_serviceendpoint_azurerm" "azure" { - depends_on = [module.caf] - for_each = try(var.azure_devops.service_endpoints, {}) - - project_id = data.azuredevops_project.project.id - service_endpoint_name = each.value.endpoint_name - credentials { - serviceprincipalid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].azuread_application.application_id - serviceprincipalkey = data.azurerm_key_vault_secret.client_secret[each.key].value - } - azurerm_spn_tenantid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].tenant_id - azurerm_subscription_id = each.value.subscription_id - azurerm_subscription_name = each.value.subscription_name -} - -# -# Grant acccess to service endpoint to all pipelines in the project -# - -resource "azuredevops_resource_authorization" "endpoint" { - for_each = azuredevops_serviceendpoint_azurerm.azure - - project_id = data.azuredevops_project.project.id - resource_id = each.value.id - type = "endpoint" - authorized = true -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf b/landingzones/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf deleted file mode 100644 index 7cd1ed1c2..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf +++ /dev/null @@ -1,39 +0,0 @@ -# -# permissions required: -# - vso.variablegroups_manage (create) -# + vso.buid (update) -# + vso.build_execute (destroy) -# -resource "azuredevops_variable_group" "variable_group" { - for_each = try(var.azure_devops.variable_groups, {}) - - project_id = data.azuredevops_project.project.id - name = each.value.name - description = try(each.value.description, null) - allow_access = try(each.value.allow_access, false) - - dynamic "key_vault" { - for_each = lookup(each.value, "keyvault", null) == null ? [] : [1] - - content { - name = try(each.value.keyvault.lz_key, null) == null ? local.combined.keyvaults[var.landingzone.key][each.value.keyvault.keyvault_key].name : local.combined.keyvaults[each.value.keyvault.lz_key][each.value.keyvault.keyvault_key].name - service_endpoint_id = azuredevops_serviceendpoint_azurerm.azure[each.value.keyvault.serviceendpoint_key].id - } - } - - dynamic "variable" { - for_each = { - for key, variable in each.value.variables : key => { - name = key == "name" ? variable : key - value = key == "name" ? null : variable - } - } - - content { - # When used with Keyvault, the name must be the keyvault secret name and value must not be set - name = variable.value.name - value = variable.value.value - } - } - -} diff --git a/landingzones/caf_solution/add-ons/azure_devops/backend.azurerm b/landingzones/caf_solution/add-ons/azure_devops/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/documentation/images/pat_token.png b/landingzones/caf_solution/add-ons/azure_devops/documentation/images/pat_token.png deleted file mode 100644 index 84fc549c5baa26167b2a975c5ae917e5a46b162e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78143 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 diff --git a/landingzones/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf b/landingzones/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf deleted file mode 100644 index 4295ebf43..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf +++ /dev/null @@ -1,76 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - } - - - combined = { - aad_apps = merge(local.remote.aad_apps, map(var.landingzone.key, module.caf.aad_apps)) - azuread_groups = merge(local.remote.azuread_groups, map(var.landingzone.key, module.caf.azuread_groups)) - keyvaults = merge(local.remote.keyvaults, map(var.landingzone.key, module.caf.keyvaults)) - managed_identities = merge(local.remote.managed_identities, map(var.landingzone.key, module.caf.managed_identities)) - } - - remote = { - aad_apps = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {})) - } - - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) - } - - keyvaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) - } - - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) - } - - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) - } - } - - -} diff --git a/landingzones/caf_solution/add-ons/azure_devops/main.tf b/landingzones/caf_solution/add-ons/azure_devops/main.tf deleted file mode 100644 index 3cf3eb96f..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/main.tf +++ /dev/null @@ -1,69 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - azuredevops = { - source = "microsoft/azuredevops" - version = "~> 0.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~>1.1.0" - } - } - required_version = ">= 0.13" -} - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - - -locals { - - - tfstates = merge( - map(var.landingzone.backend_type, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} diff --git a/landingzones/caf_solution/add-ons/azure_devops/output.tf b/landingzones/caf_solution/add-ons/azure_devops/output.tf deleted file mode 100644 index a46105168..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/output.tf +++ /dev/null @@ -1,6 +0,0 @@ -output "keyvaults" { - value = map( - var.landingzone.key, module.caf.keyvaults - ) - sensitive = true -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/readme.md b/landingzones/caf_solution/add-ons/azure_devops/readme.md deleted file mode 100644 index 1ebbb675f..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/readme.md +++ /dev/null @@ -1,60 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Azure Devops add-on - -The Azure Devops add-ons allow you to setup you Azure Devops environment as a platform to automate all your subsequent landing zone deployment from level 0 until level 4 through Azure pipelines with self hosted agents. - -* Azure Devops: - - Agent Pools (Organization and Project Level) - - Service Endpoint - - Variables and Variable Groups - - Pipelines - -* Azure (Connection with Azure Devops): - - Azure AD Application - - Custom Role - - Keyvault and access policies for Azure AD App - -Azure Devops add-on landing zone operates at **level 0** - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -## Dependencies - -Landing zone: -* CAF Launchpad (Scenario 200 or above) - -Azure Devops (example): -* Organization: https://dev.azure.com/azure-terraform -* Project : contoso_demo (https://dev.azure.com/azure-terraform/contoso_demo) -* Repo : caf-configuration (https://dev.azure.com/azure-terraform/contoso_demo/_git/caf-configuration) - - In order for pipeline to work properly, YAML file should be in this repo and referred accordingly under pipeline section in azure_devops.tfvars - - sample yaml attached [here](./scenario/200-contoso_demo/pipeline/rover.yaml). - -Azure: -* PAT Token : PAT Token should be updated in keyvault secret that deployed by launchpad LZ as below - -![](./documentation/images/pat_token.png) - -## Deployment - -```bash -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops \ - -tfstate azure_devops-contoso_demo.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo \ - -parallelism 30 \ - -level level0 \ - -env sandpit \ - -a apply - - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops \ - -tfstate_subscription_id \ - -tfstate azure_devops-contoso_demo.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo \ - -parallelism 30 \ - -level level0 \ - -env sandpit \ - -a apply -``` - -We are planning to release more examples on how to deploy the Azure Devops Agents. diff --git a/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars b/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars deleted file mode 100644 index bf0bd6c1f..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars +++ /dev/null @@ -1,232 +0,0 @@ - - -azure_devops = { - - url = "https://dev.azure.com/azure-terraform/" - project = "contoso_demo" - - # PAT Token should be updated manually to the keyvault after running launchpad - pats = { - admin = { - secret_name = "azdo-pat-admin" - lz_key = "launchpad" - keyvault_key = "secrets" - } - } - - organization_agent_pools = { - level0 = { - name = "caf-sandpit-level0" - auto_provision = false # When set to false the agent pool is not populated automatically into the devops projects (recommended) - } - level1 = { - name = "caf-sandpit-level1" - auto_provision = false - } - level2 = { - name = "caf-sandpit-level2" - auto_provision = false - } - level3 = { - name = "caf-sandpit-level3" - auto_provision = false - } - level4 = { - name = "caf-sandpit-level4" - auto_provision = false - } - } - - project_agent_pools = { - level0 = { - name = "caf-sandpit-level0" - } - level1 = { - name = "caf-sandpit-level1" - } - level2 = { - name = "caf-sandpit-level2" - } - level3 = { - name = "caf-sandpit-level3" - } - level4 = { - name = "caf-sandpit-level4" - } - } - - service_endpoints = { - contoso_demo = { - endpoint_name = "terraformdev (terraformdev.onmicrosoft.com) - contoso_demo" - subscription_name = "ase-landingzone" - subscription_id = "1d53e782-9f46-4720-b6b3-cff29106e9f6" - aad_app_key = "contoso_demo" - secret_keyvault_key = "devops" - } - } - - variable_groups = { - global = { - name = "release-global" # changing that name requires to change it in the devops agents yaml variables group - allow_access = true - variables = { - HOME_FOLDER_USER = "vsts_azpcontainer" - ROVER_IMAGE = "aztfmod/rover:2010.2808" - TF_CLI_ARGS = "'-no-color'" - TF_CLI_ARGS_init = "" - TF_CLI_ARGS_plan = "'-input=false'" - TF_VAR_ARGS_destroy = "'-auto-approve -refresh=false'" - ENVIRONMENT = "sandpit" - LANDINGZONE_BRANCH = "2010.0.0" - } - } - - level0 = { - name = "release-level0" - allow_access = true - variables = { - TF_VAR_pipeline_level = "level0" - ARM_USE_MSI = "true" - AGENT_POOL = "caf-sandpit-level0" - } - } - - level0_kv = { - name = "release-level0-msi" - allow_access = true - keyvault = { - lz_key = "launchpad" - keyvault_key = "level0" - serviceendpoint_key = "contoso_demo" - } - variables = { - name = "msi-resource-id" - } - } - - level1 = { - name = "release-level1" - allow_access = true - variables = { - TF_VAR_pipeline_level = "level1" - ARM_USE_MSI = "true" - AGENT_POOL = "caf-sandpit-level1" - } - } - - level1_kv = { - name = "release-level1-msi" - allow_access = true - keyvault = { - lz_key = "launchpad" - keyvault_key = "level1" - serviceendpoint_key = "contoso_demo" - } - variables = { - name = "msi-resource-id" - } - } - - level2 = { - name = "release-level2" - allow_access = true - variables = { - TF_VAR_pipeline_level = "level2" - ARM_USE_MSI = "true" - AGENT_POOL = "caf-sandpit-level2" - } - } - - level2_kv = { - name = "release-level2-msi" - allow_access = true - keyvault = { - lz_key = "launchpad" - keyvault_key = "level2" - serviceendpoint_key = "contoso_demo" - } - variables = { - name = "msi-resource-id" - } - } - - level3 = { - name = "release-level3" - allow_access = true - variables = { - TF_VAR_pipeline_level = "level3" - ARM_USE_MSI = "true" - AGENT_POOL = "caf-sandpit-level3" - } - } - - level3_kv = { - name = "release-level3-msi" - allow_access = true - keyvault = { - lz_key = "launchpad" - keyvault_key = "level3" - serviceendpoint_key = "contoso_demo" - } - variables = { - name = "msi-resource-id" - } - } - } - - pipelines = { - - # - # Agent pools - # - - devops_agent_level1_plan = { - name = "devops_agent_level1_plan" - folder = "\\configuration\\level1" - yaml = "configuration/pipeline/rover.yaml" - repo_type = "TfsGit" - git_repo_name = "caf-configuration" - variables = { - landingZoneName = "azdo-agent-level1", - terraformAction = "plan", - tfstateName = "azdo-agent-level1.tfstate" - configPath = "/configuration/level1/azuredevops/agent" - landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" - level = "level1" - } - variable_group_keys = ["global", "level0", "level0_kv"] - } - devops_agent_level1_apply = { - name = "devops_agent_level1_apply" - folder = "\\configuration\\level1" - yaml = "configuration/pipeline/rover.yaml" - repo_type = "TfsGit" - git_repo_name = "caf-configuration" - variables = { - landingZoneName = "azdo-agent-level1", - terraformAction = "apply", - tfstateName = "azdo-agent-level1.tfstate" - configPath = "/configuration/level1/azuredevops/agent" - landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" - level = "level1" - } - variable_group_keys = ["global", "level0", "level0_kv"] - } - devops_agent_level1_destroy = { - name = "devops_agent_level1_destroy" - folder = "\\configuration\\level1" - yaml = "configuration/pipeline/rover.yaml" - repo_type = "TfsGit" - git_repo_name = "caf-configuration" - variables = { - landingZoneName = "azdo-agent-level1", - terraformAction = "destroy", - tfstateName = "azdo-agent-level1.tfstate" - configPath = "/configuration/level1/azuredevops/agent" - landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" - level = "level1" - } - variable_group_keys = ["global", "level0", "level0_kv"] - } - } -} diff --git a/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars b/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars deleted file mode 100644 index e4d8208f3..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars +++ /dev/null @@ -1,123 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level0" - key = "azdo-contoso_demo" - tfstates = { - launchpad = { - level = "current" - tfstate = "caf_launchpad.tfstate" - } - } -} - -resource_groups = { - rg1 = { - name = "devops-agents-security" - } -} - - -keyvaults = { - devops = { - name = "devops" - resource_group_key = "rg1" - sku_name = "standard" - - creation_policies = { - keyvault_level0_rw = { - # Reference a key to an azure ad group - lz_key = "launchpad" - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - } -} - -keyvault_access_policies_azuread_apps = { - level0 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } - level1 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } - level2 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } - level3 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } - level4 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } -} - - -azuread_apps = { - - contoso_demo = { - useprefix = true - application_name = "caf-level4-contoso_demo" - password_expire_in_days = 60 - tenant_name = "terraformdev.onmicrosoft.com" - reply_urls = ["https://localhost"] - keyvaults = { - devops = { - secret_prefix = "aadapp-caf-level4-azdo-contoso_demo" - } - } - } - -} - -custom_role_definitions = { - - caf-azdo-to-azure-subscription = { - name = "caf-azure-devops-azure-app-service-improvement-program-TO-azure-subscription" - useprefix = true - description = "CAF Custom role for service principal in Azure Devops to access resources" - permissions = { - actions = [ - "Microsoft.Resources/subscriptions/read", - "Microsoft.KeyVault/vaults/read" - ] - } - } - -} - - -role_mapping = { - custom_role_mapping = { - subscriptions = { - logged_in_subscription = { - "caf-azdo-to-azure-subscription" = { - azuread_apps = { - keys = ["contoso_demo"] - } - } - } - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml b/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml deleted file mode 100644 index 156fb9983..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml +++ /dev/null @@ -1,70 +0,0 @@ -parameters: - - name: timeoutInMinutes - displayName: 'Timeout in minutes' - type: number - default: 60 - - variables: - - group: release-global - - resources: - containers: - - container: rover - image: $(ROVER_IMAGE) - options: --user 0:0 -e TF_PLUGIN_CACHE_DIR="/home/$(HOME_FOLDER_USER)/plugin-cache" -e TF_DATA_DIR="/home/$(HOME_FOLDER_USER)" - - trigger: none - - jobs: - - job: CAF_Rover - - displayName: Azure Landing Zone - - pool: $(AGENT_POOL) - - continueOnError: false - - workspace: - clean: all - - container: rover - - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - steps: - - checkout: self - - - bash: | - git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null - - az login --identity -u $(msi-resource-id) - - /tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \ - -tfstate $(tfstateName) \ - -var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \ - -parallelism=30 \ - -level $(level) \ - -a $(terraformAction) \ - -env $(ENVIRONMENT) - - condition: ne(variables['terraformAction'], 'destroy') - failOnStderr: true - displayName: 'Terraform $(terraformAction)' - - - bash: | - git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null - - az login --identity -u $(msi-resource-id) - - /tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \ - -tfstate $(tfstateName) \ - -var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \ - -parallelism=30 \ - -level $(level) \ - -a $(terraformAction) \ - -auto-approve \ - -env $(ENVIRONMENT) - - condition: eq(variables['terraformAction'], 'destroy') - failOnStderr: true - displayName: 'Terraform destroy' diff --git a/landingzones/caf_solution/add-ons/azure_devops/solution.tf b/landingzones/caf_solution/add-ons/azure_devops/solution.tf deleted file mode 100644 index 718e923ba..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/solution.tf +++ /dev/null @@ -1,36 +0,0 @@ -module "caf" { - source = "aztfmod/caf/azurerm" - version = "~>5.1.0" - - current_landingzone_key = var.landingzone.key - tenant_id = var.tenant_id - tfstates = local.tfstates - tags = local.tags - global_settings = local.global_settings - diagnostics = local.diagnostics - diagnostic_storage_accounts = var.diagnostic_storage_accounts - logged_user_objectId = var.logged_user_objectId - logged_aad_app_objectId = var.logged_aad_app_objectId - resource_groups = var.resource_groups - storage_accounts = var.storage_accounts - azuread_groups = var.azuread_groups - keyvaults = var.keyvaults - keyvault_access_policies = var.keyvault_access_policies - keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps - role_mapping = var.role_mapping - custom_role_definitions = var.custom_role_definitions - azuread_apps = var.azuread_apps - compute = { - virtual_machines = var.virtual_machines - } - storage = { - storage_account_blobs = var.storage_account_blobs - } - - remote_objects = { - keyvaults = local.remote.keyvaults - vnets = local.remote.vnets - managed_identities = local.remote.managed_identities - azuread_groups = local.remote.azuread_groups - } -} diff --git a/landingzones/caf_solution/add-ons/azure_devops/variables.tf b/landingzones/caf_solution/add-ons/azure_devops/variables.tf deleted file mode 100644 index 87dcc831a..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops/variables.tf +++ /dev/null @@ -1,102 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} - -variable "global_settings" { - default = {} -} -variable "tenant_id" {} -variable "landingzone" { -} -variable "rover_version" { - default = null -} - -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - default = null -} -variable "app_service_environments" { - default = {} -} -variable "app_service_plans" { - default = {} -} -variable "app_services" { - default = {} -} -variable "diagnostics_definition" { - default = {} -} -variable "resource_groups" { - default = {} -} -variable "network_security_group_definition" { - default = {} -} -variable "vnets" { - default = {} -} -variable "azurerm_redis_caches" { - default = {} -} -variable "mssql_servers" { - default = {} -} -variable "storage_accounts" { - default = {} -} -variable "storage_account_blobs" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "keyvaults" { - default = {} -} -variable "keyvault_access_policies" { - default = {} -} -variable "keyvault_access_policies_azuread_apps" { - default = {} -} -variable "virtual_machines" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "virtual_machine_extension_scripts" { - default = {} -} -variable "azure_devops" { - default = {} -} -variable "role_mapping" { - default = {} -} -variable "custom_role_definitions" { - default = {} -} -variable "azuread_apps" { - default = {} -} -variable "dynamic_keyvault_secrets" { - default = {} -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/backend.azurerm b/landingzones/caf_solution/add-ons/azure_devops_agent/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf deleted file mode 100644 index 63f0367a4..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf +++ /dev/null @@ -1,11 +0,0 @@ - -module "dynamic_keyvault_secrets" { - source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" - version = "~>5.1.0" - - for_each = try(var.dynamic_keyvault_secrets, {}) - - settings = each.value - keyvault = module.caf.keyvaults[each.key] - objects = module.caf -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf deleted file mode 100644 index 5372db558..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf +++ /dev/null @@ -1,44 +0,0 @@ - -resource "azurerm_virtual_machine_extension" "devops_selfhosted_agent" { - for_each = { - for key, value in var.extensions : key => value - if key == "devops_selfhosted_agent" - } - - name = "install_azure_devops_agent" - - virtual_machine_id = var.virtual_machine_id - publisher = "Microsoft.Azure.Extensions" - type = "CustomScript" - type_handler_version = "2.1" - - #timestamp: use this field only to trigger a re-run of the script by changing value of this field. - # Any integer value is acceptable; it must only be different than the previous value. - settings = jsonencode( - { - "timestamp" : each.value.version, - "fileUris" : concat(local.devops_selfhosted_agent.file_uris, local.devops_selfhosted_agent.storage_account_blobs_urls), - - } - ) - protected_settings = jsonencode( - { - "commandToExecute" : format("bash %s '%s' '%s' '%s' '%s' '%s' '%s' '%s'", var.extensions[each.key].agent_init_script, var.settings[each.key].azure_devops.url, var.settings[each.key].agent_pat, var.settings[each.key].azure_devops.agent_pool.name, var.settings[each.key].azure_devops.agent_pool.agent_name_prefix, var.settings[each.key].azure_devops.agent_pool.num_agents, var.settings[each.key].admin_username, var.settings[each.key].azure_devops.rover_version) - } - ) - -} - -locals { - devops_selfhosted_agent = { - file_uris = flatten( - [ - for file_uris_key, file in try(var.extensions.devops_selfhosted_agent.fileUris, {}) : [ - for file_uri_key in file.storage_blob_keys : var.settings.devops_selfhosted_agent.storage_accounts[file.storage_account_key].containers[file.container_key].blobs[file_uri_key].url - ] - ] - ) - - storage_account_blobs_urls = try(var.settings.devops_selfhosted_agent.storage_account_blobs_urls, []) - } -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf deleted file mode 100644 index 9b8d2f8c3..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf +++ /dev/null @@ -1,3 +0,0 @@ -variable "virtual_machine_id" {} -variable "extensions" {} -variable "settings" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf deleted file mode 100644 index fcc2fc189..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf +++ /dev/null @@ -1,74 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - } - - - combined = { - aad_apps = merge(local.remote.aad_apps, map(var.landingzone.key, module.caf.aad_apps)) - azuread_groups = merge(local.remote.azuread_groups, map(var.landingzone.key, module.caf.azuread_groups)) - keyvaults = merge(local.remote.keyvaults, map(var.landingzone.key, module.caf.keyvaults)) - managed_identities = merge(local.remote.managed_identities, map(var.landingzone.key, module.caf.managed_identities)) - } - - remote = { - aad_apps = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {})) - } - - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) - } - - keyvaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) - } - - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) - } - - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) - } - } -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/main.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/main.tf deleted file mode 100644 index 67d570897..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/main.tf +++ /dev/null @@ -1,69 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - azuredevops = { - source = "microsoft/azuredevops" - version = "~> 0.1.1" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~>1.1.0" - } - } - required_version = ">= 0.13" -} - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - - -locals { - - - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/output.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/output.tf deleted file mode 100644 index e19cb88aa..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/output.tf +++ /dev/null @@ -1,34 +0,0 @@ -output "managed_identities" { - value = local.combined.managed_identities - sensitive = false -} - -output "azuread_groups" { - value = local.combined.azuread_groups - sensitive = true -} - -output "keyvaults" { - value = local.combined.keyvaults - sensitive = false -} - -output "vnets" { - value = local.remote.vnets - sensitive = false -} - -output "global_settings" { - value = local.global_settings - sensitive = true -} - -output "diagnostics" { - value = local.diagnostics - sensitive = true -} - -output "tfstates" { - value = local.tfstates - sensitive = true -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/readme.md b/landingzones/caf_solution/add-ons/azure_devops_agent/readme.md deleted file mode 100644 index dd7b29571..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/readme.md +++ /dev/null @@ -1,54 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Azure Devops Agent add-on - -The Azure Devops Agent add-ons is the continuation of Self Hosted Agent implementation for Azure Devops environment that deployed in Azure Devops add on LZ. This will set up the underlying resources required for Agent in Azure. - -* Azure Virtual Machine to host the Agent -* Azure VM Extension to connect the VM to Azure Devops self hosted agent -* Storage account to put the script for VM Extension -* Key Vault to store the SSH key of the VM - -Azure Devops (Self Hosted Agent) add-on landing zone operates base on agent level for example for agent level0 will operates at **level 0** and agent level1 will operates at **level 1** - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -## Dependencies - -Landing zone: -* CAF Launchpad -* Azure DevOps add on (example: scenario 200-contoso_demo) - -## Deployment - -### Deploy the Azure Devops agent for level0 -```bash -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ - -tfstate level0_azure_devops_agents.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0 \ - -parallelism 30 \ - -level level0 \ - -env sandpit \ - -a apply -``` - -### Deploy the Azure Devops agent for level1 -```bash -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ - -tfstate azdo-agent-level1.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1 \ - -parallelism 30 \ - -level level1 \ - -env sandpit \ - -a apply - - -# If the tfstates are stored in a different subscription you need to execute the following command - -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ - -tfstate_subscription_id \ - -tfstate azdo-agent-level1.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1 \ - -parallelism 30 \ - -level level1 \ - -env sandpit \ - -a apply -``` \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars deleted file mode 100644 index 0141decf0..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars +++ /dev/null @@ -1,64 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level0" - key = "azdo-agent-level0" - tfstates = { - launchpad = { - level = "current" - tfstate = "caf_launchpad.tfstate" - } - azdo-contoso_demo = { - level = "current" - tfstate = "azure_devops-contoso_demo" - } - } -} - -resource_groups = { - rg1 = { - name = "devops-agents-level0" - } -} - -azure_devops = { - - # Rover version to apply to the devops self-hosted agents during the setup. - rover_version = "aztfmod/rover:2010.2808" - url = "https://dev.azure.com/azure-terraform/" - - pats = { - agent = { - secret_name = "azdo-pat-agent" - keyvault_key = "secrets" - lz_key = "launchpad" - } - } - - agent_pool = { - name = "caf-sandpit-level0" - auto_provision = true - num_agents = 4 - agent_name_prefix = "agent" - } - -} - -role_mapping = { - built_in_role_mapping = { - storage_accounts = { - scripts_region1 = { - "Storage Blob Data Contributor" = { - azuread_groups = { - lz_key = "launchpad" - keys = ["keyvault_level0_rw"] - } - managed_identities = { - lz_key = "launchpad" - keys = ["level0"] - } - } - } - } - } -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars deleted file mode 100644 index 35f188ba7..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars +++ /dev/null @@ -1,28 +0,0 @@ - -keyvaults = { - ssh = { - name = "sshl0" - resource_group_key = "rg1" - sku_name = "premium" - soft_delete_enabled = true - - creation_policies = { - keyvault_level0_rw = { - # Reference a key to an azure ad group - lz_key = "launchpad" - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } - -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars deleted file mode 100644 index 0af2a98f2..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars +++ /dev/null @@ -1,42 +0,0 @@ - -storage_accounts = { - # Is used to store the azure devops deployment script to setup the Azure Devops Selfhosted agents - scripts_region1 = { - name = "scriptsl0" - resource_group_key = "rg1" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - allow_blob_public_access = true - - containers = { - scripts = { - name = "deployment-scripts" - container_access_type = "blob" - } - } - } -} - -# Attributes available https://www.terraform.io/docs/providers/azurerm/r/storage_blob.html -storage_account_blobs = { - devops_runtime_baremetal = { - storage_account_key = "scripts_region1" - storage_container_name = "deployment-scripts" - name = "devops_runtime_baremetal.sh" - source = "scripts/devops_runtime_baremetal.sh" - } -} - -diagnostic_storage_accounts = { - # Stores boot diagnostic for region1 - bootdiag_region1 = { - name = "bootl4" - resource_group_key = "rg1" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } -} - diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars deleted file mode 100644 index 3140b94e1..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars +++ /dev/null @@ -1,79 +0,0 @@ - -# Virtual machines -virtual_machines = { - - # Configuration to deploy a bastion host linux virtual machine - level0 = { - resource_group_key = "rg1" - provision_vm_agent = true - boot_diagnostics_storage_account_key = "bootdiag_region1" - - os_type = "linux" - - keyvault_key = "ssh" - - # Define the number of networking cards to attach the virtual machine - networking_interfaces = { - nic0 = { - # Value of the keys from networking.tfvars - lz_key = "launchpad" - vnet_key = "devops_region1" - subnet_key = "release_agent_level0" - name = "0-release-agent-level0" - enable_ip_forwarding = false - internal_dns_name_label = "release-agent-level0" - } - } - - virtual_machine_settings = { - linux = { - name = "release-agent-level0" - size = "Standard_F2s_v2" - admin_username = "adminuser" - disable_password_authentication = true - - # Value of the nic keys to attach the VM. The first one in the list is the default nic - network_interface_keys = ["nic0"] - - os_disk = { - name = "release-agent-level0-os" - caching = "ReadWrite" - storage_account_type = "Standard_LRS" - } - - source_image_reference = { - publisher = "canonical" - offer = "0001-com-ubuntu-server-focal" - sku = "20_04-lts" - version = "latest" - } - - identity = { - type = "UserAssigned" - - remote = { - launchpad = { - managed_identity_keys = [ - "level0", - ] - } - } - } - - - } - } - - virtual_machine_extensions = { - devops_selfhosted_agent = { - version = 1 - virtual_machine_key = "vm_devops_level0" - agent_init_script = "devops_runtime_baremetal.sh" - storage_account_blobs = [ - "devops_runtime_baremetal" - ] - } - } - - } -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars deleted file mode 100644 index 7197d9c73..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars +++ /dev/null @@ -1,68 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "azdo-agent-level0" - level = "level1" - key = "azdo-agent-level1" - tfstates = { - azdo-agent-level0 = { - level = "lower" - tfstate = "level0_azure_devops_agents.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - azdo-contoso_demo = { - level = "lower" - tfstate = "azure_devops-contoso_demo" - } - } -} - -resource_groups = { - rg1 = { - name = "devops-agents-level0" - } -} - -azure_devops = { - - # Rover version to apply to the devops self-hosted agents during the setup. - rover_version = "aztfmod/rover:2010.2808" - url = "https://dev.azure.com/azure-terraform/" - - pats = { - agent = { - secret_name = "azdo-pat-agent" - keyvault_key = "secrets" - lz_key = "launchpad" - } - } - - agent_pool = { - name = "caf-sandpit-level1" - auto_provision = true - num_agents = 4 - agent_name_prefix = "agent" - } - -} - -role_mapping = { - built_in_role_mapping = { - storage_accounts = { - scripts_region1 = { - "Storage Blob Data Contributor" = { - azuread_groups = { - lz_key = "launchpad" - keys = ["keyvault_level0_rw"] - } - managed_identities = { - lz_key = "launchpad" - keys = ["level0", "level1"] - } - } - } - } - } -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars deleted file mode 100644 index f25881503..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars +++ /dev/null @@ -1,32 +0,0 @@ - -keyvaults = { - ssh = { - name = "sshl1" - resource_group_key = "rg1" - sku_name = "premium" - soft_delete_enabled = true - - creation_policies = { - keyvault_level0_rw = { - # Reference a key to an azure ad group - lz_key = "launchpad" - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - msi_level0 = { - lz_key = "launchpad" - managed_identity_key = "level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars deleted file mode 100644 index 5ee9634cf..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars +++ /dev/null @@ -1,42 +0,0 @@ - -storage_accounts = { - # Is used to store the azure devops deployment script to setup the Azure Devops Selfhosted agents - scripts_region1 = { - name = "scriptsl1" - resource_group_key = "rg1" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - allow_blob_public_access = true - - containers = { - scripts = { - name = "deployment-scripts" - container_access_type = "blob" - } - } - } -} - -# Attributes available https://www.terraform.io/docs/providers/azurerm/r/storage_blob.html -storage_account_blobs = { - devops_runtime_baremetal = { - storage_account_key = "scripts_region1" - storage_container_name = "deployment-scripts" - name = "devops_runtime_baremetal.sh" - source = "scripts/devops_runtime_baremetal.sh" - } -} - -diagnostic_storage_accounts = { - # Stores boot diagnostic for region1 - bootdiag_region1 = { - name = "bootl1" - resource_group_key = "rg1" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } -} - diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars b/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars deleted file mode 100644 index 41a40da84..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars +++ /dev/null @@ -1,77 +0,0 @@ - -# Virtual machines -virtual_machines = { - - # Configuration to deploy a bastion host linux virtual machine - level1 = { - resource_group_key = "rg1" - provision_vm_agent = true - boot_diagnostics_storage_account_key = "bootdiag_region1" - - os_type = "linux" - - keyvault_key = "ssh" - - # Define the number of networking cards to attach the virtual machine - networking_interfaces = { - nic0 = { - # Value of the keys from networking.tfvars - lz_key = "launchpad" - vnet_key = "devops_region1" - subnet_key = "release_agent_level1" - name = "0-release-agent-level1" - enable_ip_forwarding = false - internal_dns_name_label = "release-agent-level1" - } - } - - virtual_machine_settings = { - linux = { - name = "release-agent-level1" - size = "Standard_F2s_v2" - admin_username = "adminuser" - disable_password_authentication = true - - # Value of the nic keys to attach the VM. The first one in the list is the default nic - network_interface_keys = ["nic0"] - - os_disk = { - name = "release-agent-level1-os" - caching = "ReadWrite" - storage_account_type = "Standard_LRS" - } - - source_image_reference = { - publisher = "canonical" - offer = "0001-com-ubuntu-server-focal" - sku = "20_04-lts" - version = "latest" - } - - identity = { - type = "UserAssigned" - - remote = { - lz_key = "launchpad" - managed_identity_keys = [ - "level1", - ] - } - } - - - } - } - - virtual_machine_extensions = { - devops_selfhosted_agent = { - version = 1 - agent_init_script = "devops_runtime_baremetal.sh" - storage_account_blobs = [ - "devops_runtime_baremetal" - ] - } - } - - } -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config b/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config deleted file mode 100644 index 5bed7c472..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config +++ /dev/null @@ -1,117 +0,0 @@ -#cloud-config -apt: - preserve_sources_list: true - sources: - azure-cli.list: - source: "deb https://packages.microsoft.com/repos/azure-cli/ bionic main" - key: | - -----BEGIN PGP PUBLIC KEY BLOCK----- - Version: GnuPG v1.4.7 (GNU/Linux) - - mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT - LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV - 7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag - OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j - H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr - M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs - ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC - AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH - /32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe - MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy - 7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV - KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ - XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+ - NdCFTW7wY0Fb1fWJ+/KTsC4= - =J6gs - -----END PGP PUBLIC KEY BLOCK----- - docker.list: - source: "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" - key: | - -----BEGIN PGP PUBLIC KEY BLOCK----- - - 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 - YT90qFF93M3v01BbxP+EIY2/9tiIPbrd - =0YYh - -----END PGP PUBLIC KEY BLOCK----- -package_update: true - -packages: - - docker-ce - - azure-cli - - ca-certificates - - curl - - apt-transport-https - - lsb-release - - jq - -snap: - commands: - - snap install kubectl --classic - -apt_upgrade: true - - # Install docker-compose -runcmd: - - [ sh, -c, 'curl -L https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep "tag_name" | cut -d \" -f4)/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose' ] - - [ sh, -c, 'sudo chmod +x /usr/local/bin/docker-compose' ] - -# Add default auto created user to docker group -system_info: - default_user: - groups: [docker] \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh b/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh deleted file mode 100644 index 7abc06a08..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/sh - -url=${1} -pat_token=${2} -agent_pool=${3} -agent_prefix=${4} -num_agent=${5} -admin_user=${6} -rover_version="${7}" - -error() { - local parent_lineno="$1" - local message="$2" - local code="${3:-1}" - if [[ -n "$message" ]] ; then - >&2 echo -e "\e[41mError on or near line ${parent_lineno}: ${message}; exiting with status ${code}\e[0m" - else - >&2 echo -e "\e[41mError on or near line ${parent_lineno}; exiting with status ${code}\e[0m" - fi - echo "" - exit "${code}" -} - -function cleanup { - echo "calling cleanup" - - echo "stopping the service" - sudo ./svc.sh stop || true - echo "uninstall the service" - sudo ./svc.sh uninstall || true - echo "un-register from AZDO" - sudo -u ${admin_user} ./config.sh remove --unattended --auth pat --token ${pat_token} || true -} - -set -ETe -trap 'error ${LINENO}' ERR 1 2 3 6 - -#strict mode, fail on error -# set -euo pipefail - -echo "start" - -echo "install Ubuntu packages" - -# To make it easier for build and release pipelines to run apt-get, -# configure apt to not require confirmation (assume the -y argument by default) -export DEBIAN_FRONTEND=noninteractive -echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes - -apt-get update -apt-get install -y --no-install-recommends \ - ca-certificates \ - jq \ - apt-transport-https \ - docker.io \ - sudo - -echo "Allowing agent to run docker" - -usermod -aG docker ${admin_user} -systemctl daemon-reload -systemctl enable docker -service docker start -docker --version - -# Pull rover base image -echo "Rover docker image ${rover_version}" -docker pull "${rover_version}" 2>/dev/null - -echo "Installing Azure CLI" - -curl -sL https://aka.ms/InstallAzureCLIDeb | bash - -echo "install VSTS Agent" - -cd /home/${admin_user} -mkdir -p agent -cd agent - -AGENTRELEASE="$(curl -s https://api.github.com/repos/Microsoft/azure-pipelines-agent/releases/latest | grep -oP '"tag_name": "v\K(.*)(?=")')" -AGENTURL="https://vstsagentpackage.azureedge.net/agent/${AGENTRELEASE}/vsts-agent-linux-x64-${AGENTRELEASE}.tar.gz" -echo "Release "${AGENTRELEASE}" appears to be latest" -echo "Downloading..." -curl -s ${AGENTURL} -o agent_package.tar.gz - -for agent_num in $(seq 1 ${num_agent}); do - agent_dir="agent-$agent_num" - mkdir -p "$agent_dir" - cd "$agent_dir" - echo "moving to $agent_dir" - - cleanup - - name="${agent_prefix}-${agent_num}" - echo "installing agent $name" - tar zxvf ../agent_package.tar.gz - chmod -R 777 . - echo "extracted" - ./bin/installdependencies.sh || true - echo "dependencies installed" - sudo -u ${admin_user} ./config.sh --unattended --url "${url}" --auth pat --token "${pat_token}" --pool "${agent_pool}" --agent "${name}" --acceptTeeEula --replace --work ./_work --runAsService - echo "configuration done" - ./svc.sh install - echo "service installed" - ./svc.sh start - echo "service started" - echo "config done" - cd .. -done diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh b/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh deleted file mode 100644 index eb0b8cc2a..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc -sudo sh -c 'echo -e "[azure-cli] -name=Azure CLI -baseurl=https://packages.microsoft.com/yumrepos/azure-cli -enabled=1 -gpgcheck=1 -gpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/azure-cli.repo' -sudo yum -y install azure-cli - -sudo yum install -y yum-utils device-mapper-persistent-data lvm2 -sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo -sudo yum makecache fast -sudo yum install -y docker-ce -sudo systemctl daemon-reload -sudo systemctl enable docker -sudo service docker start -sudo docker --version - -sudo az login --identity - -az acr login --name ${7} -sudo docker pull "${7}/${5}" - -for agent_num in $(seq 1 ${6}); do - name="${4}-${agent_num}" - sudo docker run -d -v /var/run/docker.sock:/var/run/docker.sock --name ${name} -e AZP_URL=${1} -e AZP_TOKEN=${2} -e AZP_POOL="${3}" -e AZP_AGENT_NAME="${name}" "${7}/${5}" -done \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/solution.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/solution.tf deleted file mode 100644 index 3316f9894..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/solution.tf +++ /dev/null @@ -1,37 +0,0 @@ -module "caf" { - source = "aztfmod/caf/azurerm" - version = "~>5.1.0" - - current_landingzone_key = var.landingzone.key - tenant_id = var.tenant_id - tfstates = local.tfstates - tags = local.tags - global_settings = local.global_settings - diagnostics = local.diagnostics - diagnostic_storage_accounts = var.diagnostic_storage_accounts - logged_user_objectId = var.logged_user_objectId - logged_aad_app_objectId = var.logged_aad_app_objectId - resource_groups = var.resource_groups - storage_accounts = var.storage_accounts - azuread_groups = var.azuread_groups - keyvaults = var.keyvaults - keyvault_access_policies = var.keyvault_access_policies - managed_identities = var.managed_identities - role_mapping = var.role_mapping - custom_role_definitions = var.custom_role_definitions - azuread_apps = var.azuread_apps - compute = { - virtual_machines = var.virtual_machines - } - storage = { - storage_account_blobs = var.storage_account_blobs - } - - # Pass the remote objects you need to connect to. - remote_objects = { - keyvaults = local.remote.keyvaults - vnets = local.remote.vnets - managed_identities = local.remote.managed_identities - azuread_groups = local.remote.azuread_groups - } -} diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/variables.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/variables.tf deleted file mode 100644 index 45c344a59..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/variables.tf +++ /dev/null @@ -1,102 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} - -variable "global_settings" { - default = {} -} -variable "tenant_id" {} -variable "landingzone" { -} -variable "rover_version" { - default = null -} - -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - default = null -} -variable "app_service_environments" { - default = {} -} -variable "app_service_plans" { - default = {} -} -variable "app_services" { - default = {} -} -variable "diagnostics_definition" { - default = {} -} -variable "resource_groups" { - default = {} -} -variable "network_security_group_definition" { - default = {} -} -variable "vnets" { - default = {} -} -variable "azurerm_redis_caches" { - default = {} -} -variable "mssql_servers" { - default = {} -} -variable "storage_accounts" { - default = {} -} -variable "storage_account_blobs" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "keyvaults" { - default = {} -} -variable "keyvault_access_policies" { - default = {} -} -variable "virtual_machines" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "virtual_machine_extension_scripts" { - default = {} -} -variable "azure_devops" { - default = {} -} -variable "role_mapping" { - default = {} -} -variable "custom_role_definitions" { - default = {} -} -variable "azuread_apps" { - default = {} -} -variable "dynamic_keyvault_secrets" { - default = {} -} -variable "managed_identities" { - default = {} -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf b/landingzones/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf deleted file mode 100644 index 898d03288..000000000 --- a/landingzones/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf +++ /dev/null @@ -1,37 +0,0 @@ - - -# Get PAT token from keyvault -data "azurerm_key_vault_secret" "agent_pat" { - depends_on = [module.caf] - for_each = { - for key, value in try(var.virtual_machines, {}) : key => value - if try(value.virtual_machine_extensions, null) != null - } - - name = var.azure_devops.pats.agent.secret_name - key_vault_id = try(var.azure_devops.pats["agent"].lz_key, null) == null ? local.combined.keyvaults[var.landingzone.key][var.azure_devops.pats["agent"].keyvault_key].id : local.combined.keyvaults[var.azure_devops.pats["agent"].lz_key][var.azure_devops.pats["agent"].keyvault_key].id -} - - -module "vm_extensions" { - source = "./extensions" - depends_on = [module.caf] - for_each = { - for key, value in try(var.virtual_machines, {}) : key => value - if try(value.virtual_machine_extensions, null) != null - } - - virtual_machine_id = module.caf.virtual_machines[each.key].id - extensions = each.value.virtual_machine_extensions - settings = { - devops_selfhosted_agent = { - storage_accounts = module.caf.storage_accounts - agent_pat = data.azurerm_key_vault_secret.agent_pat[each.key].value - admin_username = each.value.virtual_machine_settings[each.value.os_type].admin_username - azure_devops = var.azure_devops - storage_account_blobs_urls = [ - for key, value in try(var.storage_account_blobs, []) : module.caf.storage_account_blobs[key].url - ] - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/README.md b/landingzones/caf_solution/add-ons/caf_eslz/README.md deleted file mode 100644 index afef4f046..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Enterprise-Scale - -The foundations landing zone allows you to manage the core components of an environment: - -* Management groups -* Policies - -Foundations landing zone operates at **level 1**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -
- -## Components - -CAF eslz leverages the enterprise-scale module in order to deploy its core components. - -For full description on enterprise_scale module usage, please [refer to the repository](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale) - -This is currently work in progress. -Use the following configuration file in order to get started with the enterprise-scale module integration: - -```bash -# This example will setup the complete enterprise-scale fundamentals management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription - -rover -lz /tf/caf/public/landingzones/caf_eslz \ - -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/100 \ - -level level1 \ - -a [plan|apply|destroy] - -# This example will setup custom enterprise-scale management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription - -rover -lz /tf/caf/public/landingzones/caf_eslz \ - -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/200 \ - -level level1 \ - -a [plan|apply|destroy] - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/public/landingzones/caf_eslz \ - -tfstate_subscription_id \ - -var-folder /tf/caf/public/landingzones/caf_foundations/scenario/200 \ - -level level1 \ - -a apply -``` diff --git a/landingzones/caf_solution/add-ons/caf_eslz/backend.azurerm b/landingzones/caf_solution/add-ons/caf_eslz/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/es_main.tf b/landingzones/caf_solution/add-ons/caf_eslz/es_main.tf deleted file mode 100644 index a2dff70a0..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/es_main.tf +++ /dev/null @@ -1,25 +0,0 @@ -# For full description on enterprise_scale module usage, please refer to https://github.com/Azure/terraform-azurerm-caf-enterprise-scale - -module "enterprise_scale" { - source = "Azure/caf-enterprise-scale/azurerm" - version = "0.0.8" - - root_parent_id = data.azurerm_client_config.current.tenant_id - - root_id = var.root_id - root_name = var.root_name - deploy_core_landing_zones = var.deploy_core_landing_zones - - # Control whether to deploy the demo landing zones // default = false - deploy_demo_landing_zones = var.deploy_demo_landing_zones - - # Set a path for the custom archetype library path - library_path = try(format("%s", var.library_path), "") - - # Deploys the custom landing zone configuration as defined in config file - custom_landing_zones = var.custom_landing_zones - subscription_id_overrides = var.subscription_id_overrides - archetype_config_overrides = var.archetype_config_overrides - - default_location = local.global_settings.regions[local.global_settings.default_region] -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf b/landingzones/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf deleted file mode 100644 index ee887a2d1..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf +++ /dev/null @@ -1,46 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - diagnostics = { - diagnostics_definition = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.event_hub_namespaces - } - -} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/main.tf b/landingzones/caf_solution/add-ons/caf_eslz/main.tf deleted file mode 100644 index 9dbcda3db..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/main.tf +++ /dev/null @@ -1,18 +0,0 @@ -terraform { - - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} -data "azurerm_subscription" "current" {} - - diff --git a/landingzones/caf_solution/add-ons/caf_eslz/output.tf b/landingzones/caf_solution/add-ons/caf_eslz/output.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars b/landingzones/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars deleted file mode 100644 index 89e2ea1fd..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars +++ /dev/null @@ -1,25 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "caf_eslz" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } -} - -enterprise_scale = { - # Define a custom ID to use for the root Management Group - # Also used as a prefix for all core Management Group IDs - # root_id = "caf" - # root_name = "CAF-RootManagementGroup" - - # Control whether to deploy the default core landing zones // default = true - deploy_core_landing_zones = true - - # Control whether to deploy the demo landing zones // default = false - deploy_demo_landing_zones = false -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars deleted file mode 100644 index 73c92cb7f..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars +++ /dev/null @@ -1,45 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "caf_foundations" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } -} - -enterprise_scale = { - #path to the policies definition and assignment repo - library_path = "/tf/caf/public/landingzones/caf_eslz/scenario/200/lib" - - #management groups hierarchy configuration - custom_landing_zones = { - caf = { - display_name = "CAF-RootManagementGroup" - parent_management_group_id = "" - subscription_ids = [] - archetype_config = { - archetype_id = "es_root" - parameters = {} - access_control = {} - } - } - child-caf = { - display_name = "CAF-ChildManagementGroup" - parent_management_group_id = "caf" - subscription_ids = [] - archetype_config = { - archetype_id = "es_management" - parameters = { - ES-Deploy-ForwardDiagLog = { - logAnalytics = "central_logs_region1" - } - } - access_control = {} - } - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json deleted file mode 100644 index e6d18b5db..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "es_management": { - "policy_assignments": [ - "ES-Deploy-ASC-Standard" - ], - "policy_definitions": [ - ], - "policy_set_definitions": [], - "role_assignments": [], - "role_definitions": [] - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json deleted file mode 100644 index e41b04f6f..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "es_root": { - "policy_assignments": [ - "ES-Deploy-ASC-Standard" - ], - "policy_definitions": [ - "ES-Deploy-ASC-Standard" - ], - "policy_set_definitions": [], - "role_assignments": [], - "role_definitions": [] - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json deleted file mode 100644 index ae28ea455..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "ES-Allowed-Locations", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Specifies the allowed locations (regions) where resources can be deployed", - "displayName": "ES-Allowed-Resource-Locations", - "notScopes": [], - "parameters": { - "listOfAllowedLocations": { - "value": [ - "uksouth", - "ukwest" - ] - } - }, - "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "None" - } -} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json deleted file mode 100644 index b00174588..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "ES-Allowed-RSG-Locations", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Specifies the allowed locations (regions) where Resource Groups can be deployed", - "displayName": "ES-Allowed-ResourceGroup-Locations", - "notScopes": [], - "parameters": { - "listOfAllowedLocations": { - "value": [ - "uksouth", - "ukwest" - ] - } - }, - "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "None" - } -} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json deleted file mode 100644 index 4417b6a01..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "ES-Deploy-ASC-ContExport", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Deploy ASC Continuous Export To Log Analytics Workspace.", - "displayName": "ES-Deploy-ASC-ContinuousExportToWorkspace", - "notScopes": [], - "parameters": { - "resourceGroupLocation": { - "value": null - }, - "workspaceResourceId": { - "value": null - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-ContinuousExportToWorkspace", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json deleted file mode 100644 index ba6d2186f..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "name": "ES-Deploy-ASC-Monitoring", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Enable Monitoring in Azure Security Center.", - "displayName": "ES-Deploy-ASC-Monitoring", - "notScopes": [], - "parameters": { - "aadAuthenticationInSqlServerMonitoringEffect": { - "value": "Disabled" - }, - "diskEncryptionMonitoringEffect": { - "value": "Disabled" - }, - "encryptionOfAutomationAccountMonitoringEffect": { - "value": "Disabled" - }, - "identityDesignateLessThanOwnersMonitoringEffect": { - "value": "Disabled" - }, - "identityDesignateMoreThanOneOwnerMonitoringEffect": { - "value": "Disabled" - }, - "identityEnableMFAForWritePermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveDeprecatedAccountMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveDeprecatedAccountWithOwnerPermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveExternalAccountWithOwnerPermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveExternalAccountWithReadPermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveExternalAccountWithWritePermissionsMonitoringEffect": { - "value": "Disabled" - }, - "jitNetworkAccessMonitoringEffect": { - "value": "Disabled" - }, - "networkSecurityGroupsOnSubnetsMonitoringEffect": { - "value": "AuditIfNotExists" - }, - "sqlDbEncryptionMonitoringEffect": { - "value": "Disabled" - }, - "sqlManagedInstanceAdvancedDataSecurityEmailAdminsMonitoringEffect": { - "value": "Disabled" - }, - "sqlManagedInstanceAdvancedDataSecurityEmailsMonitoringEffect": { - "value": "Disabled" - }, - "sqlServerAdvancedDataSecurityEmailAdminsMonitoringEffect": { - "value": "Disabled" - }, - "sqlServerAdvancedDataSecurityMonitoringEffect": { - "value": "Disabled" - }, - "systemUpdatesMonitoringEffect": { - "value": "Disabled" - }, - "useRbacRulesMonitoringEffect": { - "value": "Disabled" - }, - "vmssSystemUpdatesMonitoringEffect": { - "value": "Disabled" - }, - "windowsDefenderExploitGuardMonitoringEffect": { - "value": "Disabled" - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json deleted file mode 100644 index 1786a9c39..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "ES-Deploy-ASC-Standard", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Deploy Azure Security Center Standard Tier.", - "displayName": "ES-Deploy-ASC-Standard", - "notScopes": [], - "parameters": {}, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-Standard", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json deleted file mode 100644 index 7bf367af8..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "ES-Deploy-ForwardActLogs", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Ensures that Activity Log Diagnostics settings are set to push logs into Log Analytics workspace.", - "displayName": "ES-Deploy-Diagnostics-ForwardActivityLogs", - "notScopes": [], - "parameters": { - "logAnalytics": { - "value": null - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-Diagnostics-LogAnalytics", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json deleted file mode 100644 index 6cae95354..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "ES-Deploy-ForwardDiagLog", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Ensures that Azure resources are configured to forward diagnostic logs and metrics to an Azure Log Analytics workspace.", - "displayName": "ES-Deploy-Diagnostics-ForwardDiagnosticLogs", - "notScopes": [], - "parameters": { - "logAnalytics": { - "value": null - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/ES-Deploy-Diagnostics-LogAnalytics", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json b/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json deleted file mode 100644 index d75c1298a..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json +++ /dev/null @@ -1,284 +0,0 @@ -{ - "name": "ES-Deploy-ASC-Standard", - "type": "Microsoft.Authorization/policyDefinitions", - "apiVersion": "2019-09-01", - "properties": { - "description": "Ensures that subscriptions have Security Center Standard enabled.", - "displayName": "ES-Deploy-ASC-Standard", - "mode": "All", - "parameters": { - "pricingTierVMs": { - "type": "String", - "metadata": { - "displayName": "pricingTierVMs", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierSqlServers": { - "type": "String", - "metadata": { - "displayName": "pricingTierSqlServers", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierAppServices": { - "type": "String", - "metadata": { - "displayName": "pricingTierAppServices", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierStorageAccounts": { - "type": "String", - "metadata": { - "displayName": "pricingTierStorageAccounts", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierContainerRegistry": { - "type": "String", - "metadata": { - "displayName": "pricingTierContainerRegistry", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierKeyVaults": { - "type": "String", - "metadata": { - "displayName": "pricingTierKeyVaults", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierKubernetesService": { - "type": "String", - "metadata": { - "displayName": "pricingTierKubernetesService", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - } - }, - "policyRule": { - "if": { - "allOf": [ - { - "field": "type", - "equals": "Microsoft.Resources/subscriptions" - } - ] - }, - "then": { - "effect": "deployIfNotExists", - "details": { - "type": "Microsoft.Security/pricings", - "deploymentScope": "subscription", - "existenceScope": "subscription", - "roleDefinitionIds": [ - "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635" - ], - "existenceCondition": { - "allOf": [ - { - "field": "Microsoft.Security/pricings/pricingTier", - "equals": "Standard" - }, - { - "field": "type", - "equals": "Microsoft.Security/pricings" - } - ] - }, - "deployment": { - "location": "northeurope", - "properties": { - "mode": "incremental", - "parameters": { - "pricingTierVMs": { - "value": "[parameters('pricingTierVMs')]" - }, - "pricingTierSqlServers": { - "value": "[parameters('pricingTierSqlServers')]" - }, - "pricingTierAppServices": { - "value": "[parameters('pricingTierAppServices')]" - }, - "pricingTierStorageAccounts": { - "value": "[parameters('pricingTierStorageAccounts')]" - }, - "pricingTierContainerRegistry": { - "value": "[parameters('pricingTierContainerRegistry')]" - }, - "pricingTierKeyVaults": { - "value": "[parameters('pricingTierKeyVaults')]" - }, - "pricingTierKubernetesService": { - "value": "[parameters('pricingTierKubernetesService')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "pricingTierVMs": { - "type": "string", - "metadata": { - "description": "pricingTierVMs" - } - }, - "pricingTierSqlServers": { - "type": "string", - "metadata": { - "description": "pricingTierSqlServers" - } - }, - "pricingTierAppServices": { - "type": "string", - "metadata": { - "description": "pricingTierAppServices" - } - }, - "pricingTierStorageAccounts": { - "type": "string", - "metadata": { - "description": "pricingTierStorageAccounts" - } - }, - "pricingTierContainerRegistry": { - "type": "string", - "metadata": { - "description": "ContainerRegistry" - } - }, - "pricingTierKeyVaults": { - "type": "string", - "metadata": { - "description": "KeyVaults" - } - }, - "pricingTierKubernetesService": { - "type": "string", - "metadata": { - "description": "KubernetesService" - } - } - }, - "variables": {}, - "resources": [ - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "VirtualMachines", - "properties": { - "pricingTier": "[parameters('pricingTierVMs')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "StorageAccounts", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/VirtualMachines')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierStorageAccounts')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "AppServices", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/StorageAccounts')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierAppServices')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "SqlServers", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/AppServices')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierSqlServers')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "KeyVaults", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/SqlServers')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierKeyVaults')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "KubernetesService", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/KeyVaults')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierKubernetesService')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "ContainerRegistry", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/KubernetesService')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierContainerRegistry')]" - } - } - ], - "outputs": {} - } - } - } - } - } - } - } -} diff --git a/landingzones/caf_solution/add-ons/caf_eslz/variables.tf b/landingzones/caf_solution/add-ons/caf_eslz/variables.tf deleted file mode 100644 index 2d9c23fac..000000000 --- a/landingzones/caf_solution/add-ons/caf_eslz/variables.tf +++ /dev/null @@ -1,135 +0,0 @@ -# Map of the remote data state -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} -variable "tfstate_storage_account_name" { - description = "This value is propulated by the rover" -} -variable "tfstate_container_name" { - description = "This value is propulated by the rover" -} -variable "tfstate_key" { - description = "This value is propulated by the rover" -} -variable "tfstate_resource_group_name" { - description = "This value is propulated by the rover" -} - -variable "landingzone" { - default = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "enterprise_scale" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } - } -} - -variable "user_type" {} -variable "tenant_id" {} -variable "rover_version" {} -variable "logged_user_objectId" { - default = null -} -variable "tags" { - type = map(any) - default = {} -} - - -variable "root_id" { - type = string - description = "If specified, will set a custom Name (ID) value for the Enterprise-scale \"root\" Management Group, and append this to the ID for all core Enterprise-scale Management Groups." - default = "es" - - validation { - condition = can(regex("^[a-zA-Z0-9-]{2,10}$", var.root_id)) - error_message = "The root_id value must be between 2 to 10 characters long and can only contain alphanumeric characters and hyphens." - } -} - -variable "root_name" { - type = string - description = "If specified, will set a custom Display Name value for the Enterprise-scale \"root\" Management Group." - default = "Enterprise-Scale" - - validation { - condition = can(regex("^[A-Za-z][A-Za-z0-9- ._]{1,22}[A-Za-z0-9]?$", var.root_name)) - error_message = "The root_name value must be between 2 to 24 characters long, start with a letter, end with a letter or number, and can only contain space, hyphen, underscore or period characters." - } -} - -variable "deploy_core_landing_zones" { - type = bool - description = "If set to true, will include the core Enterprise-scale Management Group hierarchy." - default = false -} - -variable "archetype_config_overrides" { - type = map(any) - description = "If specified, will set custom Archetype configurations to the default Enterprise-scale Management Groups." - default = {} -} - -variable "subscription_id_overrides" { - type = map(list(string)) - description = "If specified, will be used to assign subscription_ids to the default Enterprise-scale Management Groups." - default = {} -} - -variable "deploy_demo_landing_zones" { - type = bool - description = "If set to true, will include the demo \"Landing Zone\" Management Groups." - default = false -} - -variable "custom_landing_zones" { - type = map( - object({ - display_name = string - parent_management_group_id = string - subscription_ids = list(string) - archetype_config = object({ - archetype_id = string - parameters = any - access_control = any - }) - }) - ) - description = "If specified, will deploy additional Management Groups alongside Enterprise-scale core Management Groups." - default = {} - - validation { - condition = can(regex("^[a-z0-9-]{2,36}$", keys(var.custom_landing_zones)[0])) || length(keys(var.custom_landing_zones)) == 0 - error_message = "The custom_landing_zones keys must be between 2 to 36 characters long and can only contain lowercase letters, numbers and hyphens." - } -} - -variable "library_path" { - type = string - description = "If specified, sets the path to a custom library folder for archetype artefacts." - default = "" -} - -variable "template_file_variables" { - type = map(any) - description = "If specified, provides the ability to define custom template variables used when reading in template files from the built-in and custom library_path." - default = {} -} - -variable "default_location" { - type = string - description = "If specified, will use set the default location used for resource deployments where needed." - default = "eastus" - - # Need to add validation covering all Azure locations -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/databricks/backend.azurerm b/landingzones/caf_solution/add-ons/databricks/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_solution/add-ons/databricks/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/databricks/databricks.tf b/landingzones/caf_solution/add-ons/databricks/databricks.tf deleted file mode 100644 index 1c81174b7..000000000 --- a/landingzones/caf_solution/add-ons/databricks/databricks.tf +++ /dev/null @@ -1,21 +0,0 @@ -locals { - azure_workspace_resource_id = local.remote.databricks_workspaces[var.databricks.lz_key][var.databricks.workspace_key].id -} - -provider "databricks" { - azure_workspace_resource_id = local.azure_workspace_resource_id - # azure_client_id = var.client_id - # azure_client_secret = var.client_secret - # azure_tenant_id = var.tenant_id -} - -module "databricks" { - source = "../../modules/databricks" - - settings = var.databricks -} - -output "databricks" { - value = module.databricks - sensitive = false -} diff --git a/landingzones/caf_solution/add-ons/databricks/locals.remote_tfstates.tf b/landingzones/caf_solution/add-ons/databricks/locals.remote_tfstates.tf deleted file mode 100644 index b813756c5..000000000 --- a/landingzones/caf_solution/add-ons/databricks/locals.remote_tfstates.tf +++ /dev/null @@ -1,43 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - remote = { - databricks_workspaces = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.databricks_workspaces[key], {})) - } - } - -} diff --git a/landingzones/caf_solution/add-ons/databricks/main.tf b/landingzones/caf_solution/add-ons/databricks/main.tf deleted file mode 100644 index 1325d0f88..000000000 --- a/landingzones/caf_solution/add-ons/databricks/main.tf +++ /dev/null @@ -1,63 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "1.0.0" - } - databricks = { - source = "databrickslabs/databricks" - version = "~> 0.2.5" - } - } - required_version = ">= 0.13" -} - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - -data "terraform_remote_state" "landingzone" { - backend = "azurerm" - config = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - key = var.tfstate_key - resource_group_name = var.tfstate_resource_group_name - } -} - -locals { - diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.landingzone.outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.landingzone.outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.landingzone.outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.landingzone.outputs.diagnostics.log_analytics - } - - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", data.azurerm_client_config.current.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.landingzone.outputs.tfstates - ) - -} diff --git a/landingzones/caf_solution/add-ons/databricks/variables.tf b/landingzones/caf_solution/add-ons/databricks/variables.tf deleted file mode 100644 index 6c3a9e993..000000000 --- a/landingzones/caf_solution/add-ons/databricks/variables.tf +++ /dev/null @@ -1,154 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "global_settings" { - default = {} -} - -variable "landingzone" { - default = "" -} - -variable "environment" { - default = "sandpit" -} -variable "rover_version" { - default = null -} -variable "max_length" { - default = 40 -} -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - default = null - type = map(any) -} -variable "diagnostic_log_analytics" { - default = {} -} -variable "app_service_environments" { - default = {} -} -variable "app_service_plans" { - default = {} -} -variable "app_services" { - default = {} -} -variable "diagnostics_definition" { - default = null -} -variable "resource_groups" { - default = null -} -variable "network_security_group_definition" { - default = {} -} -variable "vnets" { - default = {} -} -variable "azurerm_redis_caches" { - default = {} -} -variable "mssql_servers" { - default = {} -} -variable "mssql_databases" { - default = {} -} -variable "mssql_elastic_pools" { - default = {} -} -variable "storage_accounts" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "keyvaults" { - default = {} -} -variable "keyvault_access_policies" { - default = {} -} -variable "virtual_machines" { - default = {} -} -variable "azure_container_registries" { - default = {} -} -variable "bastion_hosts" { - default = {} -} -variable "public_ip_addresses" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "managed_identities" { - default = {} -} -variable "private_dns" { - default = {} -} -variable "synapse_workspaces" { - default = {} -} -variable "azurerm_application_insights" { - default = {} -} -variable "role_mapping" { - default = {} -} -variable "aks_clusters" { - default = {} -} -variable "databricks_workspaces" { - default = {} -} -variable "machine_learning_workspaces" { - default = {} -} -variable "monitoring" { - default = {} -} -variable "virtual_wans" { - default = {} -} -variable "event_hub_namespaces" { - default = {} -} -variable "application_gateways" { - default = {} -} -variable "application_gateway_applications" { - default = {} -} -variable "dynamic_keyvault_secrets" { - default = {} -} -variable "disk_encryption_sets" { - default = {} -} -variable "keyvault_keys" { - default = {} -} -variable "databricks" { - default = {} -} -variable "var_folder_path" { - default = {} -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/helm-charts/backend.azurerm b/landingzones/caf_solution/add-ons/helm-charts/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_solution/add-ons/helm-charts/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/helm-charts/charts.tf b/landingzones/caf_solution/add-ons/helm-charts/charts.tf deleted file mode 100644 index 74b16be73..000000000 --- a/landingzones/caf_solution/add-ons/helm-charts/charts.tf +++ /dev/null @@ -1,21 +0,0 @@ - -resource "kubernetes_namespace" "gitlab_runners" { - for_each = var.aks_namespaces - - metadata { - name = each.value - } -} - -resource "helm_release" "chart" { - depends_on = [kubernetes_namespace.gitlab_runners] - for_each = var.helm_charts - - chart = each.value.chart - name = each.value.name - namespace = each.value.namespace - repository = try(each.value.repository, null) - timeout = try(each.value.timeout, 4000) - values = [file(each.value.value_file)] - wait = try(each.value.wait, true) -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf b/landingzones/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf deleted file mode 100644 index c87b31046..000000000 --- a/landingzones/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf +++ /dev/null @@ -1,49 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings - diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics - - remote = { - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - global_settings = local.global_settings - diagnostics = local.diagnostics - - - aks_clusters = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) - } - - } - -} diff --git a/landingzones/caf_solution/add-ons/helm-charts/main.tf b/landingzones/caf_solution/add-ons/helm-charts/main.tf deleted file mode 100644 index 263eade2a..000000000 --- a/landingzones/caf_solution/add-ons/helm-charts/main.tf +++ /dev/null @@ -1,17 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.51.0" - } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 2.0.2" - } - helm = { - source = "hashicorp/helm" - version = "~> 2.0.3" - } - } - required_version = ">= 0.13" -} diff --git a/landingzones/caf_solution/add-ons/helm-charts/providers.tf b/landingzones/caf_solution/add-ons/helm-charts/providers.tf deleted file mode 100644 index 3beaf3ead..000000000 --- a/landingzones/caf_solution/add-ons/helm-charts/providers.tf +++ /dev/null @@ -1,39 +0,0 @@ - -provider "azurerm" { - features { - } -} - -provider "kubernetes" { - host = local.k8sconfigs[var.aks_cluster_key].host - username = local.k8sconfigs[var.aks_cluster_key].username - password = local.k8sconfigs[var.aks_cluster_key].password - client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate - client_key = local.k8sconfigs[var.aks_cluster_key].client_key - cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate -} - -provider "helm" { - kubernetes { - host = local.k8sconfigs[var.aks_cluster_key].host - username = local.k8sconfigs[var.aks_cluster_key].username - password = local.k8sconfigs[var.aks_cluster_key].password - client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate - client_key = local.k8sconfigs[var.aks_cluster_key].client_key - cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate - } -} - -locals { - k8sconfigs = { - for key, value in var.aks_clusters : key => { - kube_admin_config_raw = local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config_raw - host = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.host : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.host - username = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.username : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.username - password = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.password : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.password - client_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_certificate) - client_key = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_key) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_key) - cluster_ca_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.cluster_ca_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.cluster_ca_certificate) - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/helm-charts/variables.tf b/landingzones/caf_solution/add-ons/helm-charts/variables.tf deleted file mode 100644 index 2c4c62f35..000000000 --- a/landingzones/caf_solution/add-ons/helm-charts/variables.tf +++ /dev/null @@ -1,32 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "landingzone" {} -variable "rover_version" { - default = null -} -variable "tags" { - default = null -} - -variable "helm_charts" {} -variable "aks_namespaces" { - default = {} -} -variable "aks_cluster_key" { - description = "AKS cluster key to deploy the Gitlab Helm charts. The key must be defined in the variable aks_clusters" -} -variable "aks_cluster_vnet_key" { - -} -variable "aks_clusters" {} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars b/landingzones/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars deleted file mode 100644 index 1ce04bf0f..000000000 --- a/landingzones/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars +++ /dev/null @@ -1,25 +0,0 @@ -landingzone = { - backend_type = "remote" - level = "level0" - key = "launchpad" -} - -# Create the TFC organization -tfe_organizations = { - caf_lz = { - name = "caf-landingzones-test3" - email = "admin@your-company.com" - - } -} - -# Create the required TFE workspaces -tfe_workspaces = { - caf_launchpad = { - # specifies the object key for the organization where to create the workspace - organization_key = "caf_lz" - name = "caf_launchpad" - # path to place the backend file for the corresponding landing zone - backend_file = "/backend.hcl" - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/main.tf b/landingzones/caf_solution/add-ons/terraform_cloud/main.tf deleted file mode 100644 index 413e570f5..000000000 --- a/landingzones/caf_solution/add-ons/terraform_cloud/main.tf +++ /dev/null @@ -1,51 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.40" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - tfe = { - source = "hashicorp/tfe" - version = "~> 0.22.0" - } - } - required_version = ">= 0.13" -} - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - -locals { - tfstates = merge( - map(var.landingzone.backend_type, - map( - "level", var.landingzone.level, - "tenant_id", data.azurerm_client_config.current.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - ) -} \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/readme.md b/landingzones/caf_solution/add-ons/terraform_cloud/readme.md deleted file mode 100644 index 7bfe4e7a6..000000000 --- a/landingzones/caf_solution/add-ons/terraform_cloud/readme.md +++ /dev/null @@ -1,44 +0,0 @@ -# Add-on to deploy a Terraform Cloud / Terraform Enterprise configuration for Azure CAF landing zones - -Supported scenario in this release: - -1. Create the TFE/TFC environment (organization, variables, workspaces) - -Future scenarios: - -1. Use TFE/TFC as remote backend (local execution, backend in TFC) -2. Deploy Terraform Enterprise Server and remote agents -3. Use TFE/TFC in online mode (execution in TFE with remote agents) - -## Authenticating to Terraform Cloud - -First step is to authenticate to TFC using the following commands: - -```bash -terraform login -export TERRAFORM_CONFIG="$HOME/.terraform.d/credentials.tfrc.json" -``` - -## Creating the TFC environment - -This will setup TFC organization, workspaces and variables to host landing zones. - -```bash -# Deploy -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/ \ --var-folder /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/ \ --a plan -launchpad - -or -cd /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/ -terraform init -terraform plan \ --var-file /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars -``` - -Once ready, you can create your configuration: - -```bash -terraform apply \ --var-file /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars -``` \ No newline at end of file diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf b/landingzones/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf deleted file mode 100644 index db9218fc0..000000000 --- a/landingzones/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf +++ /dev/null @@ -1,83 +0,0 @@ - -resource "tfe_organization" "tfe_org" { - for_each = try(var.tfe_organizations, {}) - - name = each.value.name - email = each.value.email - session_timeout_minutes = try(each.value.session_timeout_minutes, 20160) - session_remember_minutes = try(each.value.session_remember_minutes, 20160) - collaborator_auth_policy = try(each.value.collaborator_auth_policy, "password") - owners_team_saml_role_id = try(each.value.owners_team_saml_role_id, null) -} - -resource "tfe_workspace" "tfe_wks" { - for_each = try(var.tfe_workspaces, {}) - - name = each.value.name - organization = tfe_organization.tfe_org[each.value.organization_key].name - auto_apply = try(each.value.auto_apply, false) - file_triggers_enabled = try(each.value.file_triggers_enabled, true) - operations = try(each.value.operations, true) - queue_all_runs = try(each.value.queue_all_runs, true) - speculative_enabled = try(each.value.speculative_enabled, true) - ssh_key_id = try(each.value.ssh_key_id, null) - terraform_version = try(each.value.terraform_version, null) - trigger_prefixes = try(each.value.trigger_prefixes, null) - working_directory = try(each.value.working_directory, null) - - dynamic "vcs_repo" { - for_each = lookup(each.value, "vcs_repo", null) == null ? [] : [1] - - content { - identifier = each.value.vcs_repo.identifier - branch = try(each.value.vcs_repo.branch, null) - ingress_submodules = try(each.value.vcs_repo.ingress_submodules, false) - oauth_token_id = each.value.vcs_repo.oauth_token_id - } - } -} - -resource "tfe_variable" "variable" { - for_each = try(var.tfe_variables, {}) - - key = each.value.key_name - value = each.value.value - category = each.value.category - workspace_id = tfe_workspace.tfe_wks[each.value.workspace_key].id - description = each.value.description - hcl = try(each.value.hcl, false) - sensitive = try(each.value.sensitive, false) -} - -resource "null_resource" "backend_file" { - depends_on = [tfe_workspace.tfe_wks] - for_each = try(var.tfe_workspaces, {}) - - provisioner "local-exec" { - working_dir = "./" - command = "echo workspaces '{' name = \\\"${each.value.name}\\\" '}' >> ${path.cwd}${each.value.backend_file}" - } - provisioner "local-exec" { - working_dir = "./" - command = "echo hostname = \\\"app.terraform.io\\\" >> ${path.cwd}${each.value.backend_file}" - } - provisioner "local-exec" { - working_dir = "./" - command = "echo organization = \\\"${tfe_organization.tfe_org[each.value.organization_key].name}\\\" >> ${path.cwd}${each.value.backend_file}" - } -} - -resource "null_resource" "backend_file_destroy" { - depends_on = [tfe_workspace.tfe_wks] - for_each = try(var.tfe_workspaces, {}) - - triggers = { - backend_file = lookup(each.value, "backend_file") - } - - provisioner "local-exec" { - command = format("rm %s%s", path.cwd, self.triggers.backend_file) - when = destroy - on_failure = fail - } -} diff --git a/landingzones/caf_solution/add-ons/terraform_cloud/variables.tf b/landingzones/caf_solution/add-ons/terraform_cloud/variables.tf deleted file mode 100644 index 499b0aba5..000000000 --- a/landingzones/caf_solution/add-ons/terraform_cloud/variables.tf +++ /dev/null @@ -1,85 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" { - default = {} -} -variable "lower_container_name" { - default = {} -} -variable "lower_resource_group_name" { - default = {} -} - -variable "tfstate_storage_account_name" { - default = {} -} -variable "tfstate_container_name" { - default = {} -} -variable "tfstate_key" { - default = {} -} -variable "tfstate_resource_group_name" { - default = {} -} - -variable "global_settings" { - default = {} -} -variable "tenant_id" { - default = {} -} -variable "landingzone" { - default = {} -} - -variable "rover_version" { - default = null -} - -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - default = null -} -variable "keyvaults" { - default = {} -} -variable "keyvault_access_policies" { - default = {} -} -variable "role_mapping" { - default = {} -} -variable "secrets_from_keys" { - default = {} -} -variable "custom_role_definitions" { - default = {} -} -variable "azuread_apps" { - default = {} -} - -variable "tfe_organizations" { - default = {} -} - -variable "tfe_workspaces" { - default = {} -} - -variable "tfe_variables" { - default = {} -} - -variable "tfe_servers" { - default = {} -} - -variable "tfe_agents" { - default = {} -} \ No newline at end of file diff --git a/landingzones/caf_solution/backend.azurerm b/landingzones/caf_solution/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones/caf_solution/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/dynamic_secrets.tf b/landingzones/caf_solution/dynamic_secrets.tf deleted file mode 100644 index fde3df0e0..000000000 --- a/landingzones/caf_solution/dynamic_secrets.tf +++ /dev/null @@ -1,9 +0,0 @@ -module "dynamic_keyvault_secrets" { - source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=5.3.0_preview" - - for_each = try(var.dynamic_keyvault_secrets, {}) - - settings = each.value - keyvault = module.solution.keyvaults[each.key] - objects = module.solution -} \ No newline at end of file diff --git a/landingzones/caf_solution/landingzone.tf b/landingzones/caf_solution/landingzone.tf deleted file mode 100644 index bfa7422a6..000000000 --- a/landingzones/caf_solution/landingzone.tf +++ /dev/null @@ -1,43 +0,0 @@ -module "solution" { - source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git?ref=5.3.0_preview" - - azuread_api_permissions = var.azuread_api_permissions - azuread_apps = var.azuread_apps - azuread_groups = var.azuread_groups - azuread_roles = var.azuread_roles - azuread_users = var.azuread_users - compute = var.compute - current_landingzone_key = var.landingzone.key - custom_role_definitions = var.custom_role_definitions - database = var.database - event_hub_namespaces = var.event_hub_namespaces - global_settings = local.global_settings - keyvault_access_policies = var.keyvault_access_policies - keyvault_certificate_issuers = var.keyvault_certificate_issuers - keyvaults = var.keyvaults - log_analytics = var.log_analytics - logged_aad_app_objectId = var.logged_aad_app_objectId - logged_user_objectId = var.logged_user_objectId - managed_identities = var.managed_identities - networking = var.networking - remote_objects = local.remote_objects - resource_groups = var.resource_groups - role_mapping = var.role_mapping - security = var.security - shared_services = var.shared_services - storage_accounts = var.storage_accounts - subscription_billing_role_assignments = var.subscription_billing_role_assignments - subscriptions = var.subscriptions - tags = var.tags - tenant_id = var.tenant_id - tfstates = var.tfstates - user_type = var.user_type - webapp = var.webapp - - diagnostics = { - diagnostic_event_hub_namespaces = try(local.diagnostics.diagnostic_event_hub_namespaces, var.diagnostic_event_hub_namespaces) - diagnostic_log_analytics = try(local.diagnostics.diagnostic_log_analytics, var.diagnostic_log_analytics) - diagnostic_storage_accounts = try(local.diagnostics.diagnostic_storage_accounts, var.diagnostic_storage_accounts) - } - -} diff --git a/landingzones/caf_solution/local.remote.tf b/landingzones/caf_solution/local.remote.tf deleted file mode 100644 index 6d76fb1ff..000000000 --- a/landingzones/caf_solution/local.remote.tf +++ /dev/null @@ -1,100 +0,0 @@ -locals { - remote = { - aks_clusters = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) - } - app_service_environments = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_service_environments, {})) - } - app_service_plans = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_service_plans, {})) - } - app_services = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_services, {})) - } - application_gateway_applications = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].application_gateway_applications, {})) - } - application_gateways = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].application_gateways, {})) - } - availability_sets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].availability_sets, {})) - } - azuread_applications = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azuread_applications, {})) - } - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azuread_groups, {})) - } - azuread_users = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azuread_users, {})) - } - azurerm_firewalls = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azurerm_firewalls, {})) - } - container_registry = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].container_registry, {})) - } - event_hub_namespaces = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].event_hub_namespaces, {})) - } - front_door_waf_policies = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].front_door_waf_policies, {})) - } - keyvaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].keyvaults, {})) - } - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) - } - mssql_databases = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_databases, {})) - } - mssql_elastic_pools = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_elastic_pools, {})) - } - mssql_managed_databases = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_managed_databases, {})) - } - mssql_managed_instances = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_managed_instances, {})) - } - mssql_servers = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_servers, {})) - } - mysql_servers = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mysql_servers, {})) - } - network_watchers = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].network_watchers, {})) - } - postgresql_servers = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].postgresql_servers, {})) - } - private_dns = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].private_dns, {})) - } - proximity_placement_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].proximity_placement_groups, {})) - } - public_ip_addresses = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].public_ip_addresses, {})) - } - recovery_vaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].recovery_vaults, {})) - } - resource_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].resource_groups, {})) - } - storage_accounts = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].storage_accounts, {})) - } - synapse_workspaces = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].synapse_workspaces, {})) - } - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/local.remote_objects.tf b/landingzones/caf_solution/local.remote_objects.tf deleted file mode 100644 index 8863c7ff0..000000000 --- a/landingzones/caf_solution/local.remote_objects.tf +++ /dev/null @@ -1,36 +0,0 @@ -locals { - remote_objects = { - aks_clusters = local.remote.aks_clusters - app_service_environments = local.remote.app_service_environments - app_service_plans = local.remote.app_service_plans - app_services = local.remote.app_services - application_gateway_applications = local.remote.application_gateway_applications - application_gateways = local.remote.application_gateways - availability_sets = local.remote.availability_sets - azuread_applications = local.remote.azuread_applications - azuread_groups = local.remote.azuread_groups - azuread_users = local.remote.azuread_users - azurerm_firewalls = local.remote.azurerm_firewalls - container_registry = local.remote.container_registry - event_hub_namespaces = local.remote.event_hub_namespaces - front_door_waf_policies = local.remote.front_door_waf_policies - keyvaults = local.remote.keyvaults - managed_identities = local.remote.managed_identities - mssql_databases = local.remote.mssql_databases - mssql_elastic_pools = local.remote.mssql_elastic_pools - mssql_managed_databases = local.remote.mssql_managed_databases - mssql_managed_instances = local.remote.mssql_managed_instances - mssql_servers = local.remote.mssql_servers - mysql_servers = local.remote.mysql_servers - network_watchers = local.remote.network_watchers - postgresql_servers = local.remote.postgresql_servers - private_dns = local.remote.private_dns - proximity_placement_groups = local.remote.proximity_placement_groups - public_ip_addresses = local.remote.public_ip_addresses - recovery_vaults = local.remote.recovery_vaults - resource_groups = local.remote.resource_groups - storage_accounts = local.remote.storage_accounts - synapse_workspaces = local.remote.synapse_workspaces - vnets = local.remote.vnets - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/locals.remote_tfstates.tf b/landingzones/caf_solution/locals.remote_tfstates.tf deleted file mode 100644 index e05465330..000000000 --- a/landingzones/caf_solution/locals.remote_tfstates.tf +++ /dev/null @@ -1,45 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = try(each.value.workspace, local.landingzone[try(each.value.level, "current")].container_name) - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings - - diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.log_analytics - event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.event_hub_namespaces - } - -} diff --git a/landingzones/caf_solution/main.tf b/landingzones/caf_solution/main.tf deleted file mode 100644 index 909659c2d..000000000 --- a/landingzones/caf_solution/main.tf +++ /dev/null @@ -1,66 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.50" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.4.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~>1.2.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - - -locals { - - # Update the tfstates map - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} \ No newline at end of file diff --git a/landingzones/caf_solution/modules/databricks/cluster.tf b/landingzones/caf_solution/modules/databricks/cluster.tf deleted file mode 100644 index 25310d783..000000000 --- a/landingzones/caf_solution/modules/databricks/cluster.tf +++ /dev/null @@ -1,17 +0,0 @@ -resource "databricks_cluster" "cluster" { - cluster_name = var.settings.name - spark_version = var.settings.spark_version - node_type_id = var.settings.node_type_id - autotermination_minutes = var.settings.autotermination_minutes - - dynamic "autoscale" { - for_each = try(var.settings.autoscale, null) == null ? [] : [1] - - content { - min_workers = try(var.settings.autoscale.min_workers, null) - max_workers = try(var.settings.autoscale.max_workers, null) - } - } - - -} \ No newline at end of file diff --git a/landingzones/caf_solution/modules/databricks/instance_pool.tf b/landingzones/caf_solution/modules/databricks/instance_pool.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/landingzones/caf_solution/modules/databricks/main.tf b/landingzones/caf_solution/modules/databricks/main.tf deleted file mode 100644 index 8993136bd..000000000 --- a/landingzones/caf_solution/modules/databricks/main.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_providers { - databricks = { - source = "databrickslabs/databricks" - } - } - required_version = ">= 0.13" -} - diff --git a/landingzones/caf_solution/modules/databricks/output.tf b/landingzones/caf_solution/modules/databricks/output.tf deleted file mode 100644 index d6bc7bc48..000000000 --- a/landingzones/caf_solution/modules/databricks/output.tf +++ /dev/null @@ -1,7 +0,0 @@ -output "cluster" { - value = { - id = databricks_cluster.cluster.id - default_tags = databricks_cluster.cluster.default_tags - state = databricks_cluster.cluster.state - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/modules/databricks/variables.tf b/landingzones/caf_solution/modules/databricks/variables.tf deleted file mode 100644 index 719f36726..000000000 --- a/landingzones/caf_solution/modules/databricks/variables.tf +++ /dev/null @@ -1,4 +0,0 @@ -variable "azure_workspace_resource_id" { - default = {} -} -variable "settings" {} \ No newline at end of file diff --git a/landingzones/caf_solution/output.tf b/landingzones/caf_solution/output.tf deleted file mode 100644 index 6c2f8c16d..000000000 --- a/landingzones/caf_solution/output.tf +++ /dev/null @@ -1,16 +0,0 @@ -output "objects" { - value = tomap( - { - (var.landingzone.key) = { - for key, value in module.solution : key => value - if try(value, {}) != {} - } - } - ) - sensitive = true -} - -output "tfstates" { - value = local.tfstates - sensitive = true -} diff --git a/landingzones/caf_solution/readme.md b/landingzones/caf_solution/readme.md deleted file mode 100644 index 48f6c0333..000000000 --- a/landingzones/caf_solution/readme.md +++ /dev/null @@ -1,22 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Solutions - -The landing zones solutions provide the underlying infrastructure to support your applications. The following are solutions accelerator ready to be deployed into your environment. They would require some review to match your operating model. - -* App Services (including App Service Environment) -* Azure Kubernetes Service (AKS) -* Azure Databricks -* Azure SQL Database -* Azure Application Gateway -* Azure Redis Cache -* Azure Keyvault -* Azure Virtual Machine -* Azure Machine Learning -* Azure Synapse - -Solutions landing zone operates at **level 3**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -## Deploying solutions - -Solution examples are available in the CAF Landing zones Starter repo: https://github.com/Azure/caf-terraform-landingzones-starter diff --git a/landingzones/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars b/landingzones/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars deleted file mode 100644 index 9340de718..000000000 --- a/landingzones/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars +++ /dev/null @@ -1,12 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "caf_foundations" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars b/landingzones/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars deleted file mode 100644 index 7269553e2..000000000 --- a/landingzones/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars +++ /dev/null @@ -1,62 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "networking_hub" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - vnet_hub_re1 = { - name = "vnet-hub-re1" - region = "region1" - } -} - -vnets = { - hub_re1 = { - resource_group_key = "vnet_hub_re1" - region = "region1" - vnet = { - name = "hub-re1" - address_space = ["100.64.100.0/22"] - } - specialsubnets = { - GatewaySubnet = { - name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway - cidr = ["100.64.100.0/27"] - } - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["100.64.101.0/26"] - } - } - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["100.64.101.64/26"] - nsg_key = "azure_bastion_nsg" - } - jumpbox = { - name = "jumpbox" - cidr = ["100.64.102.0/27"] - nsg_key = "jumpbox" - } - private_endpoints = { - name = "private_endpoints" - cidr = ["100.64.103.128/25"] - enforce_private_link_endpoint_network_policies = true - } - } - } - -} diff --git a/landingzones/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars b/landingzones/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars deleted file mode 100644 index 232a5432d..000000000 --- a/landingzones/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars +++ /dev/null @@ -1,327 +0,0 @@ -# -# Definition of the networking security groups -# -network_security_group_definition = { - # This entry is applied to all subnets with no NSG defined - empty_nsg = { - } - - azure_bastion_nsg = { - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } - - application_gateway = { - nsg = [ - { - name = "Inbound-HTTP", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "80-82" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "Inbound-HTTPs", - priority = "130" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "Inbound-AGW", - priority = "140" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "65200-65535" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - ] - } - - api_management = { - nsg = [ - { - name = "Inbound-APIM", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3443" - source_address_prefix = "ApiManagement" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Inbound-Redis", - priority = "110" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "6381-6383" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Inbound-LoadBalancer", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "AzureLoadBalancer" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Outbound-StorageHttp", - priority = "100" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "80" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-StorageHttps", - priority = "110" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-AADHttp", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "80" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureActiveDirectory" - }, - { - name = "Outbound-AADHttps", - priority = "130" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureActiveDirectory" - }, - { - name = "Outbound-SQL", - priority = "140" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "1433" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "SQL" - }, - { - name = "Outbound-EventHub", - priority = "150" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "5671-5672" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "EventHub" - }, - { - name = "Outbound-EventHubHttps", - priority = "160" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "EventHub" - }, - { - name = "Outbound-FileShareGit", - priority = "170" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "445" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-Health", - priority = "180" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "1886" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-Monitor", - priority = "190" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureMonitor" - }, - { - name = "Outbound-MoSMTP1itor", - priority = "200" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "25" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-SMTP2", - priority = "210" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "587" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-SMTP3", - priority = "220" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "25028" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-Redis", - priority = "230" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "6381-6383" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - - jumpbox = { - nsg = [ - { - name = "ssh-inbound-22", - priority = "200" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - -} - diff --git a/landingzones/caf_solution/scenario/networking/100-single-region-hub/readme.md b/landingzones/caf_solution/scenario/networking/100-single-region-hub/readme.md deleted file mode 100644 index 624dfff6b..000000000 --- a/landingzones/caf_solution/scenario/networking/100-single-region-hub/readme.md +++ /dev/null @@ -1,45 +0,0 @@ -# CAF landing zones for Terraform - Single region hub virtual network - -The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. - -* Hub and spoke -* Virtual WAN -* Application DMZ scenario -* Any custom network topology based on virtual networks or virtual WAN -* Library of network security groups definition - -Networking landing zone operates at **level 2**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). - -## Architecture diagram - -This example allows you to deploy the following topology: - -![100-example](../../documentation/img/100-single-region-hub.png) - - -## Components deployed by this example - -| Component | Type of resource | Purpose | -|----------------------------------------------------------------------------------|-------------------------|------------------------------------------------------------------| -| vnet-hub-re1 | Resource group | resource group to host the virtual network | -| vnet_hub_re1 | Virtual network | virtual network used as a hub | -| GatewaySubnet,AzureFirewallSubnet,AzureBastionSubnet, jumpbox, private_endpoints | Virtual Subnets | virtual subnets | -| azure_bastion_nsg, empty_nsg, application_gateway, api_management, jumpbox | Network security groups | network security groups that can be attached to virtual subnets. | - - -## Customizing this example - -Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. - -## Deploying this example - -Once you have picked a scenario for test, you can deploy it using: - -```bash -rover -lz /tf/caf/landingzones/caf_networking \ --level level2 \ --var-folder /tf/caf/landingzones/caf_networking/scenario/100-single-region-hub \ --a apply -``` diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars deleted file mode 100644 index 26f860340..000000000 --- a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars +++ /dev/null @@ -1,27 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "networking_hub" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - vnet_hub_re1 = { - name = "vnet-hub-re1" - region = "region1" - } - vnet_hub_re2 = { - name = "vnet-hub-re2" - region = "region2" - } -} diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars deleted file mode 100644 index 6352fec33..000000000 --- a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars +++ /dev/null @@ -1,344 +0,0 @@ -# -# Definition of the networking security groups -# -network_security_group_definition = { - # This entry is applied to all subnets with no NSG defined - empty_nsg = { - } - - azure_bastion_nsg = { - - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } - - application_gateway = { - - nsg = [ - { - name = "Inbound-HTTP", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "80-82" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "Inbound-HTTPs", - priority = "130" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "Inbound-AGW", - priority = "140" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "65200-65535" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - ] - } - - api_management = { - - nsg = [ - { - name = "Inbound-APIM", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3443" - source_address_prefix = "ApiManagement" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Inbound-Redis", - priority = "110" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "6381-6383" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Inbound-LoadBalancer", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "AzureLoadBalancer" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Outbound-StorageHttp", - priority = "100" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "80" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-StorageHttps", - priority = "110" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-AADHttp", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "80" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureActiveDirectory" - }, - { - name = "Outbound-AADHttps", - priority = "130" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureActiveDirectory" - }, - { - name = "Outbound-SQL", - priority = "140" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "1433" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "SQL" - }, - { - name = "Outbound-EventHub", - priority = "150" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "5671-5672" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "EventHub" - }, - { - name = "Outbound-EventHubHttps", - priority = "160" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "EventHub" - }, - { - name = "Outbound-FileShareGit", - priority = "170" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "445" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-Health", - priority = "180" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "1886" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-Monitor", - priority = "190" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureMonitor" - }, - { - name = "Outbound-MoSMTP1itor", - priority = "200" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "25" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-SMTP2", - priority = "210" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "587" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-SMTP3", - priority = "220" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "25028" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-Redis", - priority = "230" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "6381-6383" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - - jumpbox = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "ssh-inbound-22", - priority = "200" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - -} diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars deleted file mode 100644 index 40a1eb491..000000000 --- a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars +++ /dev/null @@ -1,31 +0,0 @@ - -vnet_peerings = { - hub_re1_TO_hub_re2 = { - name = "hub_re1_TO_hub_re2" - from = { - vnet_key = "hub_re1" - } - to = { - vnet_key = "hub_re2" - } - allow_virtual_network_access = true - allow_forwarded_traffic = false - allow_gateway_transit = false - use_remote_gateways = false - } - - hub_re2_TO_hub_re1 = { - name = "hub_re2_TO_hub_re1" - from = { - vnet_key = "hub_re2" - } - to = { - vnet_key = "hub_re1" - } - allow_virtual_network_access = true - allow_forwarded_traffic = false - allow_gateway_transit = false - use_remote_gateways = false - } - -} diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/readme.md b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/readme.md deleted file mode 100644 index 8d7ad2ac7..000000000 --- a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/readme.md +++ /dev/null @@ -1,50 +0,0 @@ -# CAF landing zones for Terraform - Multi-region hub with global peering - -This scenario deploys the networking hub across multiple regions - -The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. - -* Hub and spoke -* Virtual WAN -* Application DMZ scenario -* Any custom network topology based on virtual networks or virtual WAN -* Library of network security groups definition - -Networking landing zone operates at **level 2**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). - -## Architecture diagram - -This example allows you to deploy the following topology: - -![101-example](../../documentation/img/101-multi-region-hub.png) - - -## Components deployed by this example - -| Component | Type of resource | Purpose | -|----------------------------------------------------------------------------------|-------------------------|--------------------------------------------------------------------------------------------| -| vnet-hub-re1, vnet-hub-re2 | Resource group | resource group to host the virtual network | -| vnet_hub_re1, vnet-hub-re2 | Virtual network | virtual network used as a hub | -| GatewaySubnet,AzureFirewallSubnet,AzureBastionSubnet, jumpbox, private_endpoints | Virtual Subnets | virtual subnets | -| azure_bastion_nsg, empty_nsg, application_gateway, api_management, jumpbox | Network security groups | network security groups that can be attached to virtual subnets. | -| hub_re1_TO_hub_re2, and hub_re2_TO_hub_re1 | Virtual network peering | Peering between vnet_hub_re1 and vnet-hub-re2 | -| bastion-re1-pip1, bastion-re2-pip1 | Public IP address | Public IP address to be used in vnet_hub_re1 and vnet-hub-re2, to be used by Azure Bastion | -| bastion-re1, bastion-re2 | Azure Bastion | Azure Bastion host in order to access the virtual network. | - - -## Customizing this example - -Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. - -## Deploying this example - -Once you have picked a scenario for test, you can deploy it using: - -```bash -rover -lz /tf/caf/landingzones/caf_networking \ --level level2 \ --var-folder /tf/caf/landingzones/caf_networking/scenario/101-multi-region-hub \ --a apply -``` diff --git a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars b/landingzones/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars deleted file mode 100644 index 67af89832..000000000 --- a/landingzones/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars +++ /dev/null @@ -1,78 +0,0 @@ - -vnets = { - hub_re1 = { - resource_group_key = "vnet_hub_re1" - region = "region1" - vnet = { - name = "hub-re1" - address_space = ["100.64.100.0/22"] - } - specialsubnets = { - GatewaySubnet = { - name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway - cidr = ["100.64.100.0/27"] - } - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["100.64.101.0/26"] - } - } - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["100.64.101.64/26"] - nsg_key = "azure_bastion_nsg" - } - jumpbox = { - name = "jumpbox" - cidr = ["100.64.102.0/27"] - nsg_key = "jumpbox" - } - private_endpoints = { - name = "private_endpoints" - cidr = ["100.64.103.128/25"] - enforce_private_link_endpoint_network_policies = true - } - } - - } - - hub_re2 = { - resource_group_key = "vnet_hub_re2" - region = "region2" - vnet = { - name = "hub-re2" - address_space = ["100.65.100.0/22"] - } - specialsubnets = { - GatewaySubnet = { - name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway - cidr = ["100.65.100.0/27"] - } - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["100.65.101.0/26"] - } - } - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["100.65.101.64/26"] - nsg_key = "azure_bastion_nsg" - } - jumpbox = { - name = "jumpbox" - cidr = ["100.65.102.0/27"] - nsg_key = "jumpbox" - } - private_endpoints = { - name = "private_endpoints" - cidr = ["100.65.103.128/25"] - enforce_private_link_endpoint_network_policies = true - } - } - - } - - -} diff --git a/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars b/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars deleted file mode 100644 index b32be7ef7..000000000 --- a/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars +++ /dev/null @@ -1,155 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "networking_hub" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - vnet_hub_region1 = { - name = "vnet-hub-re1" - } - vnet_spoke_region1 = { - name = "vnet-spoke-re1" - } -} - -vnets = { - hub_re1 = { - resource_group_key = "vnet_hub_region1" - vnet = { - name = "hub-re1" - address_space = ["10.10.100.0/24"] - } - specialsubnets = { - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["10.10.100.192/26"] - } - } - subnets = { - jumphost = { - name = "jumphost" - cidr = ["10.10.100.0/25"] - nsg_key = "jumphost" - } - } - } - - spoke_re1 = { - resource_group_key = "vnet_spoke_region1" - vnet = { - name = "spoke-re1" - address_space = ["10.11.100.0/24"] - } - specialsubnets = {} - subnets = { - jumphost = { - name = "jumphost" - cidr = ["10.11.100.0/25"] - nsg_key = "jumphost" - } - webapp1 = { - name = "webapp-presentation-tier" - cidr = ["10.11.100.128/25"] - } - } - } -} - -azurerm_firewalls = { - # Southeastasia firewall (do not change the key when created) - fw_re1 = { - region = "region1" - name = "azfwre1" - resource_group_key = "vnet_hub_region1" - vnet_key = "hub_re1" - public_ip_key = "az_fw_pip" - - } - -} - -public_ip_addresses = { - - az_fw_pip = { - name = "az_fw_re1_pip1" - region = "region1" - resource_group_key = "vnet_hub_region1" - sku = "Standard" - allocation_method = "Static" - ip_version = "IPv4" - idle_timeout_in_minutes = "4" - - } -} - -route_tables = { - default_to_firewall_re1 = { - name = "default_to_firewall_re1" - resource_group_key = "vnet_spoke_region1" - } -} - -azurerm_routes = { - default_to_firewall_rg1 = { - name = "0-0-0-0-through-firewall-re1" - resource_group_key = "vnet_spoke_region1" - route_table_key = "default_to_firewall_re1" - address_prefix = "0.0.0.0/0" - next_hop_type = "VirtualAppliance" - - # To be set when next_hop_type = "VirtualAppliance" - private_ip_keys = { - azurerm_firewall = { - key = "fw_re1" - interface_index = 0 - } - # virtual_machine = { - # key = "" - # nic_key = "" - # } - } - } -} - -vnet_peerings = { - hub-re1_TO_spoke-re1 = { - name = "hub-re1_TO_spoke-re1" - from = { - vnet_key = "hub_re1" - } - to = { - vnet_key = "spoke_re1" - } - allow_virtual_network_access = true - allow_forwarded_traffic = true - allow_gateway_transit = false - use_remote_gateways = false - } - - spoke-re1_TO_hub-re1 = { - name = "hub_re2_TO_hub_re1" - from = { - vnet_key = "spoke_re1" - } - to = { - vnet_key = "hub_re1" - } - allow_virtual_network_access = true - allow_forwarded_traffic = false - allow_gateway_transit = false - use_remote_gateways = false - } - -} diff --git a/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars b/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars deleted file mode 100644 index 40dfc522a..000000000 --- a/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars +++ /dev/null @@ -1,122 +0,0 @@ -# -# Definition of the networking security groups -# -network_security_group_definition = { - azure_bastion_nsg = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } - - jumphost = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "ssh-inbound-22", - priority = "200" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - -} diff --git a/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/readme.md b/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/readme.md deleted file mode 100644 index b2820fb78..000000000 --- a/landingzones/caf_solution/scenario/networking/105-hub-and-spoke/readme.md +++ /dev/null @@ -1,52 +0,0 @@ -# CAF landing zones for Terraform - Secure Hub and Spoke with Azure Firewall - -This scenario deploys the networking hub across multiple regions - -The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. - -* Hub and spoke -* Virtual WAN -* Application DMZ scenario -* Any custom network topology based on virtual networks or virtual WAN -* Library of network security groups definition - -Networking landing zone operates at **level 2**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). - -## Architecture diagram - -This example allows you to deploy the following topology: - -![101-example](../../documentation/img/105-hub-and-spoke.png) - - -## Components deployed by this example - -| Component | Type of resource | Purpose | -|--|--|--| -| vnet-hub-re1, vnet-spoke-re2 | Resource group | resource group to host the virtual network | -| hub-re1, spoke-re1 | Virtual network | virtual networks for hub and spokeshub | -| AzureFirewallSubnet,jumphost, webapp-presentation-tier | Virtual Subnets | virtual subnets | -| azure_bastion_nsg, , jumphost_nsg | Network security groups | network security groups that can be attached to virtual subnets. | -| hub_re1_TO_spoke_re1, and spoke_re1_TO_hub_re1 | Virtual network peering | Peering between hub-re1 and spoke-re1 | -| azfwre1 | Azure Firewall | Azure Firewall in Hub network | -| az_fw_re1_pip1 | Public IP address | Public IP address used by Azure Firewall | -| default_to_firewall_re1 | Route table | Route table to host route entries | -| 0-0-0-0-through-firewall-re1 | Route table entry | Route all traffic to Azure Firewall in hub | - - -## Customizing this example - -Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. - -## Deploying this example - -Once you have picked a scenario for test, you can deploy it using: - -```bash -rover -lz /tf/caf/landingzones/caf_networking \ --level level2 \ --var-folder /tf/caf/landingzones/caf_networking/scenario/105-hub-and-spoke \ --a apply -``` diff --git a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars deleted file mode 100644 index ea7eb6d12..000000000 --- a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars +++ /dev/null @@ -1,71 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "networking_hub" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - vnet_re1 = { - name = "vnet-spoke-re1" - region = "region1" - } - hub_re1 = { - name = "vnet-hub-re1" - region = "region1" - } -} - -vnets = { - vnet_re1 = { - resource_group_key = "vnet_re1" - region = "region1" - vnet = { - name = "hub-re1" - address_space = ["10.10.100.0/24"] - } - specialsubnets = { - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["10.10.100.192/26"] - } - } - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["10.10.100.160/27"] - nsg_key = "azure_bastion_nsg" - } - } - } -} - -vhub_peerings = { - # Establish the peering with Virtual Hubs - hub_rg1-TO-vnet_rg1 = { - vhub = { - virtual_wan_key = "vwan_re1" - virtual_hub_key = "hub_re1" - } - vnet = { - # If the virtual network is stored in another another landing zone, use the following attributes to refer the state file: - # lz_key = "networking" - # output_key = "vnets" - vnet_key = "vnet_re1" - } - name = "vhub_peering_hub_sg" - hub_to_virtual_network_traffic_allowed = true - virtual_network_to_hub_gateways_traffic_allowed = true - internet_security_enabled = true - } -} diff --git a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars deleted file mode 100644 index 3d3d06e3a..000000000 --- a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars +++ /dev/null @@ -1,104 +0,0 @@ -network_security_group_definition = { - empty_nsg = { - - nsg = [] - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } - - azure_bastion_nsg = { - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } -} \ No newline at end of file diff --git a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md deleted file mode 100644 index eb0b2487b..000000000 --- a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md +++ /dev/null @@ -1,47 +0,0 @@ -# CAF landing zones for Terraform - Azure Virtual WAN with Firewall manager - -The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. - -* Hub and spoke -* Virtual WAN -* Application DMZ scenario -* Any custom network topology based on virtual networks or virtual WAN -* Library of network security groups definition - -Networking landing zone operates at **level 2**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). - -## Architecture diagram - -This example allows you to deploy the following topology: - -![virtual_wan_lz](../../documentation/img/106-hub-virtual-wan-firewall.png) - - -## Components deployed by this example - -| Component | Type of resource | Purpose | -|------------------------------|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| vnet-spoke-re1, vnet-hub-re1 | Resource group | resource group to host the virtual network and virtual WAN | -| vnet_re1 | Virtual network with subnets, network security groups | virtual network used as a spoke, attached to the virtual hub from Azure Virtual WAN | -| contosovWAN-re1 | Virtual WAN | virtual WAN infrastructure | -| hub-re1, hub-re2 | Virtual Hubs | virtual hubs to be deployed in region, the hubs can be configured to deploy point-to-site connectivity, site-to-site connectivity or Express Route connectivity. | -| hub_fw_re1, hub_fw_re2 | Azure Firewall | traffic filtering between hubs and outside | -| hub_rg1-TO-vnet_rg1 | Virtual network and Virtual Hubs peering objects | network peering between virtual hubs and virtual network | - - -## Customizing this example - -Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. - -## Deploying this example - -Once you have picked a scenario for test, you can deploy it using: - -```bash -rover -lz /tf/caf/landingzones/caf_networking \ --level level2 \ --var-folder /tf/caf/landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall \ --a apply -``` diff --git a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars b/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars deleted file mode 100644 index 547e62450..000000000 --- a/landingzones/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars +++ /dev/null @@ -1,84 +0,0 @@ -virtual_wans = { - vwan_re1 = { - resource_group_key = "hub_re1" - name = "contosovWAN-re1" - region = "region1" - - hubs = { - hub_re1 = { - hub_name = "hub-re1" - region = "region1" - hub_address_prefix = "10.0.3.0/24" - deploy_firewall = true - firewall_name = "hub-fw-re1" - firewall_resource_group_key = "hub_re1" - deploy_p2s = false - p2s_config = { - name = "caf-sea-vpn-p2s" - scale_unit = 2 - connection_configuration = { - name = "client-connections" - vpn_client_address_pool = { - address_prefixes = ["192.168.0.0/24"] - } - } - server_config = { - vpn_authentication_types = ["Certificate"] - client_root_certificate = { - name = "DigiCert-Federated-ID-Root-CA" - public_cert_data = < Date: Sat, 27 Mar 2021 06:56:00 +0000 Subject: [PATCH 05/38] Add to root folder --- caf_launchpad/.terraform.lock.hcl | 72 ++ caf_launchpad/backend.azurerm | 4 + .../documentation/img/launchpad-100.PNG | Bin 0 -> 143702 bytes .../documentation/img/launchpad-200.png | Bin 0 -> 232335 bytes .../documentation/img/launchpad_workflow.png | Bin 0 -> 40149 bytes caf_launchpad/documentation/variables.md | 41 + caf_launchpad/dynamic_secrets.tf | 10 + caf_launchpad/landingzone.tf | 53 ++ caf_launchpad/main.tf | 88 ++ caf_launchpad/output.tf | 16 + caf_launchpad/readme.md | 206 +++++ caf_launchpad/scenario/100/README.md | 44 + .../scenario/100/configuration.tfvars | 68 ++ .../scenario/100/dynamic_secrets.tfvars | 114 +++ .../scenario/100/iam_role_mapping.tfvars | 47 ++ caf_launchpad/scenario/100/keyvaults.tfvars | 99 +++ .../scenario/100/storage_accounts.tfvars | 102 +++ caf_launchpad/scenario/200/compute.tfvars | 100 +++ .../scenario/200/configuration.tfvars | 100 +++ .../diagnostic_event_hub_namespaces.tfvars | 20 + .../200/diagnostic_log_analytics.tfvars | 48 ++ .../200/diagnostic_storage_accounts.tfvars | 64 ++ .../200/diagnostics_definition.tfvars | 274 +++++++ .../200/diagnostics_destinations.tfvars | 31 + .../scenario/200/dynamic_secrets.tfvars | 152 ++++ caf_launchpad/scenario/200/iam_azuread.tfvars | 184 +++++ .../200/iam_azuread_api_permissions.tfvars | 43 + .../scenario/200/iam_custom_roles.tfvars | 76 ++ .../scenario/200/iam_keyvault_policies.tfvars | 114 +++ .../200/iam_managed_identities.tfvars | 32 + .../scenario/200/iam_role_mapping.tfvars | 154 ++++ caf_launchpad/scenario/200/keyvaults.tfvars | 204 +++++ caf_launchpad/scenario/200/networking.tfvars | 110 +++ .../200/networking_nsg_definition.tfvars | 141 ++++ caf_launchpad/scenario/200/readme.md | 56 ++ .../scenario/200/storage_accounts.tfvars | 101 +++ .../scenario/200/subscriptions.tfvars | 20 + .../cloud-init-install-rover-tools.config | 49 ++ caf_launchpad/variables.tf | 211 +++++ .../aad-pod-identity/aad-msi-binding.yaml | 16 + .../aad-pod-identity/aad_pod_identity.tf | 120 +++ .../add-ons/aad-pod-identity/backend.azurerm | 4 + .../build/kustomization_build.tf | 16 + .../add-ons/aad-pod-identity/build/main.tf | 7 + .../aad-pod-identity/build/variables.tf | 2 + .../aad-pod-identity/local.remote_tfstates.tf | 54 ++ caf_solution/add-ons/aad-pod-identity/main.tf | 17 + .../add-ons/aad-pod-identity/providers.tf | 32 + .../add-ons/aad-pod-identity/variables.tf | 36 + .../aks-pod-identity-assignment.tf | 58 ++ .../aks-secure-baseline/backend.azurerm | 4 + .../aks-secure-baseline/kustomization.yaml | 5 + .../local.remote_tfstates.tf | 54 ++ .../add-ons/aks-secure-baseline/main.tf | 17 + .../add-ons/aks-secure-baseline/providers.tf | 32 + .../aks-secure-baseline/secure-baseline.tf | 22 + .../add-ons/aks-secure-baseline/variables.tf | 36 + .../add-ons/aks_applications/app/main.tf | 7 + .../add-ons/aks_applications/app/module.tf | 48 ++ .../add-ons/aks_applications/app/output.tf | 0 .../add-ons/aks_applications/app/variables.tf | 5 + .../add-ons/aks_applications/applications.tf | 27 + .../add-ons/aks_applications/backend.azurerm | 4 + .../locals.remote_tfstates.tf | 54 ++ caf_solution/add-ons/aks_applications/main.tf | 75 ++ .../add-ons/aks_applications/output.tf | 0 .../add-ons/aks_applications/variables.tf | 36 + caf_solution/add-ons/azure_devops/azdo.tf | 15 + .../add-ons/azure_devops/azdo_agent_pools.tf | 52 ++ .../add-ons/azure_devops/azdo_pipelines.tf | 43 + .../azure_devops/azdo_service_endpoint.tf | 36 + .../azure_devops/azdo_variable_groups.tf | 39 + .../add-ons/azure_devops/backend.azurerm | 4 + .../documentation/images/pat_token.png | Bin 0 -> 78143 bytes .../azure_devops/locals.remote_tfstates.tf | 76 ++ caf_solution/add-ons/azure_devops/main.tf | 69 ++ caf_solution/add-ons/azure_devops/output.tf | 6 + caf_solution/add-ons/azure_devops/readme.md | 60 ++ .../200-contoso_demo/azure_devops.tfvars | 232 ++++++ .../200-contoso_demo/configurations.tfvars | 123 +++ .../200-contoso_demo/pipeline/rover.yaml | 70 ++ caf_solution/add-ons/azure_devops/solution.tf | 36 + .../add-ons/azure_devops/variables.tf | 102 +++ .../azure_devops_agent/backend.azurerm | 4 + .../azure_devops_agent/dynamic_secrets.tf | 11 + .../extensions/devops_selfhosted_agent.tf | 44 + .../extensions/variables.tf | 3 + .../locals.current_tfstates.tf | 74 ++ .../add-ons/azure_devops_agent/main.tf | 69 ++ .../add-ons/azure_devops_agent/output.tf | 34 + .../add-ons/azure_devops_agent/readme.md | 54 ++ .../level0/configuration.tfvars | 64 ++ .../200-contoso_demo/level0/keyvaults.tfvars | 28 + .../level0/storage_accounts.tfvars | 42 + .../level0/virtual_machines.tfvars | 79 ++ .../level1/configuration.tfvars | 68 ++ .../200-contoso_demo/level1/keyvaults.tfvars | 32 + .../level1/storage_accounts.tfvars | 42 + .../level1/virtual_machines.tfvars | 77 ++ .../cloud-init-install-rover-tools.config | 117 +++ .../scripts/devops_runtime_baremetal.sh | 109 +++ .../scripts/devops_runtime_docker.sh | 29 + .../add-ons/azure_devops_agent/solution.tf | 37 + .../add-ons/azure_devops_agent/variables.tf | 102 +++ .../vm_extention_devops_agent.tf | 37 + caf_solution/add-ons/caf_eslz/README.md | 44 + caf_solution/add-ons/caf_eslz/backend.azurerm | 4 + caf_solution/add-ons/caf_eslz/es_main.tf | 25 + .../caf_eslz/locals.remote_tfstates.tf | 46 ++ caf_solution/add-ons/caf_eslz/main.tf | 18 + caf_solution/add-ons/caf_eslz/output.tf | 0 .../100/enterprise_scale_contoso_com.tfvars | 25 + .../200/enterprise_scale_contoso_com.tfvars | 45 + ...chetype_definition_es_management.tmpl.json | 12 + .../200/lib/archetype_definition_es_root.json | 13 + ...nt_es_allowed_resource-locations.tmpl.json | 28 + ..._allowed_resourcegroup-locations.tmpl.json | 28 + ...licy_assignment_es_deploy_asc_ce.tmpl.json | 28 + ...ignment_es_deploy_asc_monitoring.tmpl.json | 88 ++ ...ssignment_es_deploy_asc_standard.tmpl.json | 21 + ...nment_es_deploy_diag_activitylog.tmpl.json | 25 + ...ment_es_deploy_diag_loganalytics.tmpl.json | 25 + ...icy_definition_es_deploy_asc_standard.json | 284 +++++++ caf_solution/add-ons/caf_eslz/variables.tf | 135 +++ .../add-ons/databricks/backend.azurerm | 4 + caf_solution/add-ons/databricks/databricks.tf | 21 + .../databricks/locals.remote_tfstates.tf | 43 + caf_solution/add-ons/databricks/main.tf | 63 ++ caf_solution/add-ons/databricks/variables.tf | 154 ++++ .../add-ons/helm-charts/backend.azurerm | 4 + caf_solution/add-ons/helm-charts/charts.tf | 21 + .../helm-charts/local.remote_tfstates.tf | 49 ++ caf_solution/add-ons/helm-charts/main.tf | 17 + caf_solution/add-ons/helm-charts/providers.tf | 39 + caf_solution/add-ons/helm-charts/variables.tf | 32 + .../terraform_cloud/example/tfc.tfvars | 25 + caf_solution/add-ons/terraform_cloud/main.tf | 51 ++ .../add-ons/terraform_cloud/readme.md | 44 + .../terraform_cloud/terraform_cloud.tf | 83 ++ .../add-ons/terraform_cloud/variables.tf | 85 ++ caf_solution/backend.azurerm | 4 + caf_solution/dynamic_secrets.tf | 9 + caf_solution/landingzone.tf | 43 + caf_solution/local.remote.tf | 100 +++ caf_solution/local.remote_objects.tf | 36 + caf_solution/locals.remote_tfstates.tf | 45 + caf_solution/main.tf | 66 ++ caf_solution/modules/databricks/cluster.tf | 17 + .../modules/databricks/instance_pool.tf | 0 caf_solution/modules/databricks/main.tf | 9 + caf_solution/modules/databricks/output.tf | 7 + caf_solution/modules/databricks/variables.tf | 4 + caf_solution/output.tf | 16 + caf_solution/readme.md | 22 + .../100-passthrough/landingzone.tfvars | 12 + .../configuration.tfvars | 62 ++ .../network_security_group_definition.tfvars | 327 ++++++++ .../100-single-region-hub/readme.md | 45 + .../101-multi-region-hub/configuration.tfvars | 27 + .../network_security_group_definition.tfvars | 344 ++++++++ .../101-multi-region-hub/peering.tfvars | 31 + .../networking/101-multi-region-hub/readme.md | 50 ++ .../virtual_networks.tfvars | 78 ++ .../105-hub-and-spoke/configuration.tfvars | 155 ++++ .../network_security_group_definition.tfvars | 122 +++ .../networking/105-hub-and-spoke/readme.md | 52 ++ .../configuration.tfvars | 71 ++ .../network_security_group_definition.tfvars | 104 +++ .../106-hub-virtual-wan-firewall/readme.md | 47 ++ .../virtual_wan.tfvars | 84 ++ .../configuration.tfvars | 612 ++++++++++++++ .../201-multi-region-hub/configuration.tfvars | 767 +++++++++++++++++ .../210-aks-private/configuration.tfvars | 772 ++++++++++++++++++ .../peerings/launchpad/configuration.tfvars | 41 + .../shared_services/100/configuration.tfvars | 140 ++++ .../shared_services/200/configuration.tfvars | 156 ++++ .../cloud-init-install-rover-tools.config | 119 +++ caf_solution/scripts/grant_consent.sh | 28 + caf_solution/variables.tf | 299 +++++++ 179 files changed, 12707 insertions(+) create mode 100644 caf_launchpad/.terraform.lock.hcl create mode 100644 caf_launchpad/backend.azurerm create mode 100644 caf_launchpad/documentation/img/launchpad-100.PNG create mode 100644 caf_launchpad/documentation/img/launchpad-200.png create mode 100644 caf_launchpad/documentation/img/launchpad_workflow.png create mode 100644 caf_launchpad/documentation/variables.md create mode 100644 caf_launchpad/dynamic_secrets.tf create mode 100644 caf_launchpad/landingzone.tf create mode 100644 caf_launchpad/main.tf create mode 100644 caf_launchpad/output.tf create mode 100644 caf_launchpad/readme.md create mode 100644 caf_launchpad/scenario/100/README.md create mode 100644 caf_launchpad/scenario/100/configuration.tfvars create mode 100644 caf_launchpad/scenario/100/dynamic_secrets.tfvars create mode 100644 caf_launchpad/scenario/100/iam_role_mapping.tfvars create mode 100644 caf_launchpad/scenario/100/keyvaults.tfvars create mode 100644 caf_launchpad/scenario/100/storage_accounts.tfvars create mode 100644 caf_launchpad/scenario/200/compute.tfvars create mode 100644 caf_launchpad/scenario/200/configuration.tfvars create mode 100644 caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars create mode 100644 caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars create mode 100644 caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars create mode 100644 caf_launchpad/scenario/200/diagnostics_definition.tfvars create mode 100644 caf_launchpad/scenario/200/diagnostics_destinations.tfvars create mode 100644 caf_launchpad/scenario/200/dynamic_secrets.tfvars create mode 100644 caf_launchpad/scenario/200/iam_azuread.tfvars create mode 100644 caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars create mode 100644 caf_launchpad/scenario/200/iam_custom_roles.tfvars create mode 100644 caf_launchpad/scenario/200/iam_keyvault_policies.tfvars create mode 100644 caf_launchpad/scenario/200/iam_managed_identities.tfvars create mode 100644 caf_launchpad/scenario/200/iam_role_mapping.tfvars create mode 100644 caf_launchpad/scenario/200/keyvaults.tfvars create mode 100644 caf_launchpad/scenario/200/networking.tfvars create mode 100644 caf_launchpad/scenario/200/networking_nsg_definition.tfvars create mode 100644 caf_launchpad/scenario/200/readme.md create mode 100644 caf_launchpad/scenario/200/storage_accounts.tfvars create mode 100644 caf_launchpad/scenario/200/subscriptions.tfvars create mode 100644 caf_launchpad/scripts/cloud-init-install-rover-tools.config create mode 100644 caf_launchpad/variables.tf create mode 100644 caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml create mode 100644 caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf create mode 100644 caf_solution/add-ons/aad-pod-identity/backend.azurerm create mode 100644 caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf create mode 100644 caf_solution/add-ons/aad-pod-identity/build/main.tf create mode 100644 caf_solution/add-ons/aad-pod-identity/build/variables.tf create mode 100644 caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf create mode 100644 caf_solution/add-ons/aad-pod-identity/main.tf create mode 100644 caf_solution/add-ons/aad-pod-identity/providers.tf create mode 100644 caf_solution/add-ons/aad-pod-identity/variables.tf create mode 100644 caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf create mode 100644 caf_solution/add-ons/aks-secure-baseline/backend.azurerm create mode 100644 caf_solution/add-ons/aks-secure-baseline/kustomization.yaml create mode 100644 caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf create mode 100644 caf_solution/add-ons/aks-secure-baseline/main.tf create mode 100644 caf_solution/add-ons/aks-secure-baseline/providers.tf create mode 100644 caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf create mode 100644 caf_solution/add-ons/aks-secure-baseline/variables.tf create mode 100644 caf_solution/add-ons/aks_applications/app/main.tf create mode 100644 caf_solution/add-ons/aks_applications/app/module.tf create mode 100644 caf_solution/add-ons/aks_applications/app/output.tf create mode 100644 caf_solution/add-ons/aks_applications/app/variables.tf create mode 100644 caf_solution/add-ons/aks_applications/applications.tf create mode 100644 caf_solution/add-ons/aks_applications/backend.azurerm create mode 100644 caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf create mode 100644 caf_solution/add-ons/aks_applications/main.tf create mode 100644 caf_solution/add-ons/aks_applications/output.tf create mode 100644 caf_solution/add-ons/aks_applications/variables.tf create mode 100644 caf_solution/add-ons/azure_devops/azdo.tf create mode 100644 caf_solution/add-ons/azure_devops/azdo_agent_pools.tf create mode 100644 caf_solution/add-ons/azure_devops/azdo_pipelines.tf create mode 100644 caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf create mode 100644 caf_solution/add-ons/azure_devops/azdo_variable_groups.tf create mode 100644 caf_solution/add-ons/azure_devops/backend.azurerm create mode 100644 caf_solution/add-ons/azure_devops/documentation/images/pat_token.png create mode 100644 caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf create mode 100644 caf_solution/add-ons/azure_devops/main.tf create mode 100644 caf_solution/add-ons/azure_devops/output.tf create mode 100644 caf_solution/add-ons/azure_devops/readme.md create mode 100644 caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars create mode 100644 caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars create mode 100644 caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml create mode 100644 caf_solution/add-ons/azure_devops/solution.tf create mode 100644 caf_solution/add-ons/azure_devops/variables.tf create mode 100644 caf_solution/add-ons/azure_devops_agent/backend.azurerm create mode 100644 caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf create mode 100644 caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf create mode 100644 caf_solution/add-ons/azure_devops_agent/extensions/variables.tf create mode 100644 caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf create mode 100644 caf_solution/add-ons/azure_devops_agent/main.tf create mode 100644 caf_solution/add-ons/azure_devops_agent/output.tf create mode 100644 caf_solution/add-ons/azure_devops_agent/readme.md create mode 100644 caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars create mode 100644 caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars create mode 100644 caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars create mode 100644 caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars create mode 100644 caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars create mode 100644 caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars create mode 100644 caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars create mode 100644 caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars create mode 100644 caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config create mode 100644 caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh create mode 100644 caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh create mode 100644 caf_solution/add-ons/azure_devops_agent/solution.tf create mode 100644 caf_solution/add-ons/azure_devops_agent/variables.tf create mode 100644 caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf create mode 100644 caf_solution/add-ons/caf_eslz/README.md create mode 100644 caf_solution/add-ons/caf_eslz/backend.azurerm create mode 100644 caf_solution/add-ons/caf_eslz/es_main.tf create mode 100644 caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf create mode 100644 caf_solution/add-ons/caf_eslz/main.tf create mode 100644 caf_solution/add-ons/caf_eslz/output.tf create mode 100644 caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json create mode 100644 caf_solution/add-ons/caf_eslz/variables.tf create mode 100644 caf_solution/add-ons/databricks/backend.azurerm create mode 100644 caf_solution/add-ons/databricks/databricks.tf create mode 100644 caf_solution/add-ons/databricks/locals.remote_tfstates.tf create mode 100644 caf_solution/add-ons/databricks/main.tf create mode 100644 caf_solution/add-ons/databricks/variables.tf create mode 100644 caf_solution/add-ons/helm-charts/backend.azurerm create mode 100644 caf_solution/add-ons/helm-charts/charts.tf create mode 100644 caf_solution/add-ons/helm-charts/local.remote_tfstates.tf create mode 100644 caf_solution/add-ons/helm-charts/main.tf create mode 100644 caf_solution/add-ons/helm-charts/providers.tf create mode 100644 caf_solution/add-ons/helm-charts/variables.tf create mode 100644 caf_solution/add-ons/terraform_cloud/example/tfc.tfvars create mode 100644 caf_solution/add-ons/terraform_cloud/main.tf create mode 100644 caf_solution/add-ons/terraform_cloud/readme.md create mode 100644 caf_solution/add-ons/terraform_cloud/terraform_cloud.tf create mode 100644 caf_solution/add-ons/terraform_cloud/variables.tf create mode 100644 caf_solution/backend.azurerm create mode 100644 caf_solution/dynamic_secrets.tf create mode 100644 caf_solution/landingzone.tf create mode 100644 caf_solution/local.remote.tf create mode 100644 caf_solution/local.remote_objects.tf create mode 100644 caf_solution/locals.remote_tfstates.tf create mode 100644 caf_solution/main.tf create mode 100644 caf_solution/modules/databricks/cluster.tf create mode 100644 caf_solution/modules/databricks/instance_pool.tf create mode 100644 caf_solution/modules/databricks/main.tf create mode 100644 caf_solution/modules/databricks/output.tf create mode 100644 caf_solution/modules/databricks/variables.tf create mode 100644 caf_solution/output.tf create mode 100644 caf_solution/readme.md create mode 100644 caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars create mode 100644 caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars create mode 100644 caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars create mode 100644 caf_solution/scenario/networking/100-single-region-hub/readme.md create mode 100644 caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars create mode 100644 caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars create mode 100644 caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars create mode 100644 caf_solution/scenario/networking/101-multi-region-hub/readme.md create mode 100644 caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars create mode 100644 caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars create mode 100644 caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars create mode 100644 caf_solution/scenario/networking/105-hub-and-spoke/readme.md create mode 100644 caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars create mode 100644 caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars create mode 100644 caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md create mode 100644 caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars create mode 100644 caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars create mode 100644 caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars create mode 100644 caf_solution/scenario/networking/210-aks-private/configuration.tfvars create mode 100644 caf_solution/scenario/networking/210-aks-private/peerings/launchpad/configuration.tfvars create mode 100644 caf_solution/scenario/shared_services/100/configuration.tfvars create mode 100644 caf_solution/scenario/shared_services/200/configuration.tfvars create mode 100644 caf_solution/scripts/cloud-init-install-rover-tools.config create mode 100644 caf_solution/scripts/grant_consent.sh create mode 100644 caf_solution/variables.tf diff --git a/caf_launchpad/.terraform.lock.hcl b/caf_launchpad/.terraform.lock.hcl new file mode 100644 index 000000000..f8ae181d8 --- /dev/null +++ b/caf_launchpad/.terraform.lock.hcl @@ -0,0 +1,72 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/aztfmod/azurecaf" { + version = "1.2.2" + constraints = "~> 1.2.0" + hashes = [ + "h1:5GMOMtQg1/i6yigQ++Nol/lno2D67D5LhO3/VLPMq9A=", + ] +} + +provider "registry.terraform.io/hashicorp/azuread" { + version = "1.4.0" + constraints = "~> 1.4.0" + hashes = [ + "h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=", + ] +} + +provider "registry.terraform.io/hashicorp/azurerm" { + version = "2.50.0" + constraints = "~> 2.50.0, ~> 2.50" + hashes = [ + "h1:Vr6WUm88s9hXGkyVjHtHsP2Jmc2ypQXn6ww7dXtvk1M=", + ] +} + +provider "registry.terraform.io/hashicorp/external" { + version = "1.2.0" + constraints = "~> 1.2.0" + hashes = [ + "h1:wDfbBn+171g9/+aWqkicrN5l1S3kuqEX4J1zyPCDsoY=", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "2.1.2" + constraints = "~> 2.1.0" + hashes = [ + "h1:CFnENdqQu4g3LJNevA32aDxcUz2qGkRGQpFfkI8TCdE=", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "2.2.1" + constraints = "~> 2.2.1" + hashes = [ + "h1:Zg1Bpi6vr7b0H6no8kVDfEucn5pvNALivdrVKVHarGs=", + ] +} + +provider "registry.terraform.io/hashicorp/template" { + version = "2.2.0" + hashes = [ + "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", + ] +} + +provider "registry.terraform.io/hashicorp/time" { + version = "0.7.0" + hashes = [ + "h1:1VPBq+jeoCf0wVCxnzK6BNnOmNbXf3fRnDmS43Jw7Oo=", + ] +} + +provider "registry.terraform.io/hashicorp/tls" { + version = "2.2.0" + constraints = "~> 2.2.0" + hashes = [ + "h1:BRvNNW/32RAFXRcEAovtJWVbFt8zesIKkQm2N0GBCn8=", + ] +} diff --git a/caf_launchpad/backend.azurerm b/caf_launchpad/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_launchpad/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_launchpad/documentation/img/launchpad-100.PNG b/caf_launchpad/documentation/img/launchpad-100.PNG new file mode 100644 index 0000000000000000000000000000000000000000..c93a36c46bafe2b787394e8729e469a1c98bc6db GIT binary patch literal 143702 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%0A}!)1#qO;^}XKhld?yny=?0OQ;f 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ȿ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
fW#D|re`0@a z6BQNDw?^~V1M&aKp?+iKk15Rj_QW*UCgaS_7#J6;&<*KdcORY;A4#{X#wa*P$OQYc zB(N-zYF;O=mP%2trk*EHBa@qGXQ4YCJwF1k@I54|aM+{nir%xx z?q|vKzL_%`b+c)*AF(Df*Zb}*N$6JxZl12&Py8!IiS#VhNScCu;na%)7?`UjgMKPA zKpBZp{*M+X-)RRkKxj$K_FR@!=G znY>1p{AqeikHZ*WtZcD)Va3E92;i_|yTF$$7lqPGHf)Z7Mt_syhelnzw`Uo~b zx%s`FXsabN#_GMlEksara~n>8fT88&20bJIM!AQIw$KSUYD9f^ovhLA zz_D+Z2Auoztjv8GHf;uQ0T&LFS9hiV?SkkjT@ZZgf&c!56fonU0b&C|F`)!u1&Td) za~Bsv-Md#;S6OC%|BeA|1*@a)3Dq8ZAKg~FjjDv~mboFGWA_e{8^i08I8-8^J^}n9 zU)*ds437j~L>NWJW-F+Vnd;1eii~3s{qf8M2o(cFfZiV{Q0^}t0DS1eiyi)NTT*}j zf3!(%VeH6k12!>GK;%1kjGJM*+D43-_zu62Tu6uomnLxVt5E_=Ej&$TNqs=xY{H{& ztq~k@B`2H|-`w+1E@l(c?#&WrX^p*1;3VR=Sm_cwBw%_=F@n&NpwQy&@fDUXqo$uF zV!)aAS7ZGoV2CrBd~>^XJKu8N<{Br5IK?Fne3IRrkhpw4S!32&YgZydIaX`i_m&DK zZz?|D0hw#AfB>V0j`}5tMPrb<&}~1CMO5A}g}+u92^ulK{PFW+y{zW8X3~#%H}@Dr z-m=S(hJNJ%J$fb22&C*}hJ}?4zKD*MzERo-vvgH>NFEvau6xTsf-W$gy1o|`2tX=! z@)f8}RxiPta~dD9yuBZc08!D}mMQ1+e(5v!3VP@$o2OVKLy|+l!ymxwKOiV>@(_At zzJQOWQ5sv+GC~W1wEeDt^OA0A?}gtXUNd(dp#rP`Eh6H^o*pWy{Yvf|_Hn1j2eU(K zGLix76g6&llZ552;w&5@dd(55(^b%ox`Rvz5)kF*&hgo;xf)S_IH0Zsmz~EMkrck% z7*H%T;^2RM$5=0zdhR=uuFGa(G5_9D|1>pnv7ft7t=gjR1B3h!+ml!PXI4N4Tsp4Lz`RFL85(jklPr+s+G+a;&Jl1MF@ z63#{+85wzlS}jH9`3-UBi3pJ8-COa~dPCoB7MxouzHP}0U$qG}4?q;0OvJOW2392A zdf!U?_N~q(vhA|o96^{A(~pQ)lH|PFZMWyauh0U zfk-YcoZOgY4ct+8WPfuX{hHg@TbGsOl1kCgZ&8GnO(*dzG$FV}_|i1?B=I3XVJP-U z|Laq(q0c5!G0UZIKYXrqojzk@>7F0&DO1 zFLls!cq+OGm{igNao+NoOk>}ap&wG+{88ae6R1gkd6AH>G5@8-mDuf<#sj)l%Gs}r zj!c)DhJL~U0yk3eL~ecJD|m3c?{F(cbSc3>nPrZ4AvN91M%z3QS(N7=ar@lu&msiU*S1h@+{@lV%eJS>L>O0_-ij*AQQ ze$;)oxKt5V^@`LtgCgP0d&Ra4l3fAK+lJ9Mox3Qt(y}7EDy*&T@;Jq$*n|=|NT@cG zhXyy@o&|k+B}Z-5)SLhOrrXLCtI0QyBx6uozA>Xhjy%u-Nsq7A5D_7J#X6LbJrQ4V zZ>ic;&S_>HXniH1kVCHvPs&-0KgsT1Ncbn3iNXEt$G0^+u4Sz9_kC^HMAOQHFkfrmUaZ^qIozJ#Y3R|u=Dmg+oW$Dy43O1fYK>=0p+z}^}JM7$lMy}w+b%#@chYU4EMMA!-Z5B?*ueNJpTlhS{P=rQ~)a@3r^cCSo zQ^SfW>^P?2SID|z3T@>*bBV&cG4WMZcP&8l$OIW&}+!cs7BtJ-!3je!NT zRV3N@3T|Tf^J;;#Ncw+rV_+ITYd4Jrb(0?#-`e@RqL1N_ir<}C^saj6DYkQ{;-qD6 z17JCvwftXC@#`F9#yafj1mlT^PmcFpCaSlt-N-=3b*B$m0ah_^Tn_1~xca@Vg`Ja= zm5VF4V5yG~4TZIil+L~HA|qSw7uBfnXvwTQE^)(9j2JPij$Z0cZ-AH-4gG8y&m%5M zU|I>1Z^36ANzVoH7$vm=0ndK>BjLvD$^dl2$Jnv zSnwdUD&M|MRO7Z33=oFh)zKaN6Gkz|0m2!DY;-o%#<(j}?illS!8-T~1T`Y6Pjg+p z>HWP|eeaCKo(`Ty#692;;83iiOc*-cd|axep?A6FBUV+%h3LpfNqN#$$I7o-TQA}b z9pH__^R}CNbI@EVO+&}oJH3Ys*sPlZPkZueui!BBQrFFa%6bbgWayMV8^caAzMUuB zL7h|M#_|Pq5SZ8hcBku&1gtp>SQF{-ULlx-7i}wMzh*UFQ=c_=A%Q82+#;4_Z||h{ z(7Q$gqin5yVwLMrZ2B!MUBXob3z1_6e(E;>EPud^LyaP2apneW5J?ix_MA{z9i>OS zubU~q8p!#p+V-Mdn09gR%H-Ss>rMgrhflcw{wY5Oc7#&(bNBGjn>a799sbPoELa_; zTXfb}RMGH39hqiSVb5`hE47MrPb>r(nWp8BnJUMEc@L#9j4Cugi#3JQ}3dYaJum z7gbIvW^E!gPRODTRM0efP!Xqa3^9{5Sm6|ypkun15J6IhbbpZ8LC%X%#(f=a9KH)W%oJ*X^(`+LHiSem|*+eNBQlad=^zDTP<+*-3`D%Bv zrsU$^q!O6jd^lo|+Jx!RHtYwz5ym0MV{d6r;6!}tbbRHSv|^fK$5bmz4;8S(fAT7? zBa(#jJ0Qui@z-ngyOwsrmZ34MF`Vi9k!Cw+bw4gF9=LOX=pd>}o4ivB|K2T#c7b{@ zpIc^2)NAvxT?cJ(<$L$3esL0BT6KxTgYl7ihd?~92+PuXd3{|RZpa$YbVTQkza<&~ zug*#KhhhLN86ZwXANuBn|J;2*q1E0!LzEiMWL;_IU(4dXd5m+0vH1eJPo>J^cO1Z? z<|0%6Upw&4@(nvu|C7G6Pp031j}me)Mz^ZZ=<2`hY)(_(nu`$?^F*lQyMUdeCqco< zJg2|z&_9~04Rsp+Jo~F9>Sv;UMLk6Q>-RDkZYd>}Rpwd|YU{`;98SL&q*nx#@S}L7 z9F-BIPlNNL#3FwZ#Ai{5G+n((!M&&SD4MmYt~()>mN>u+205%@?;R)QHM8SU#q^I- zYgAqXe$z_sx}g<4P!#N<)DR@5ynGeVa$2DcC6Ymx4Xx0^Hx}iH_DBQca}ONj5EAsd zbZ_Dr5j;g(vum>u2|F1{8GTGkpW*44UK(%5WDDCPjmphEH^ryE5Fl%^u(Al=G7Uu&-RBIqQfQE0ocshm8rp9unFYG3ZQ8DfaSZr0(y?Rt z$9}&%==PpHUXWPv2mCx@dCx_RrW029 ztaO1+SpEM*U{L$uI8NIBFEzAq^ucY~_PmBa`HkWz_z_eI-l>{6r1C2Be~j_xZGqz&cq zXEdRS(of>Ee5aU@emSUw{bs>Q#_XCmat;h#qM#DLR#Gk;mLDZh^Zb({*0hc-5SHd0 z#ZIVxvjvZ^Q!PgUsV;JRgH&3Or0lMVxYzd8f&KN^Z7M15u6v3qzLFF34DIUS2*+*_U`EsYKqgxb6#6gC{I0Hoq6Cn7F!e`W zr4(+xPQ)_vqiiaA1T6o;a{s5H{gG!zNhgGR&1bCeBTTE$?0NeEDKcGLNa)hR16+bS zxnDo6+UjA>hM>3R??Ng$9ZJ83Ql57&sc8aqdI<46*c{Ovi@s?D^KSBvpM=~Uf}ZN0 z9x$cuWtrs%7nz}4dTBKZ%e|r+OC0zg_n}SVGG? z(pa-MD(IM8!m*d28qvZGBsbz6B6)%-DT4WpYFMo9P%7WPM^7fwG96B+d0VJi)Rr6l7&1i2T(9}1lccd7wCMPKUL6HJN z>;@oZ0BK8N;u@-VuIy+!(@k^f>}Oq`4^|jClK4>e#2ovQ#eWm;7OC}S>g8>}v@S$* zAw(VkO<<9$|oIp=00V!)?$^n*TDBXVlC;y`@U3rMCNjg5qk{lt$H(kpijdx4(|me`-!oGC?xiTfI-}Q^K5h;8>c>MlnKJ0 zq6siAfSFHg+Cap6GUcLx1(KYg&5G6^Dw{2M^_3aaLBjfV)CKa1FW5o+E5GioU1-*J zBtG2x^E_S%U~JpKm1w%`3&l_%=!@dRxq5Se18NTPpKkmCdfmY&mE%nDPs?as{>`@Z z;5gceUuYNFnU~OskaL#u?8SHTs;i8-KD_*e*2$$gFNs<|oWzA7tdFQ>8G39NuI)?< z@R#&Ju}tv!P7*3@xueXN$eoHfv%47^$U#?bAH_YWF(Kf-F0`&b91M`?#NM`QYz_My zG=056-d}b^G9l^nH;(c-obZ|PiC2NkvdDP;QcY;Ue^t--+0*dh^wqZD@CTQ;qeud^ z*fVTGHsK+{M2{w_gCtyym5V#51Vw}bgX*b(BMS#l6D;{po}h$7cr_R|&%6vK-!QCy z?rGN`2`o;htTo}Ev9u$DI=wrtd|M>+RQT2V!bnhR-`hmbG|m5b#kGkEBv7BbrE{-z zDZ>+9=Do-Jz`Y~3W$eFD0p)}G*>nCm>fbdoLq zvq8k+^b&#S0D=H44WozO35&-%H01N&(d$Ft^>VxW-JYU0pv zt=#8oLw-|JT9=>wnU2{(hS(At#D`3lhR;co)VA1rtr_W!pTx(Zv)2eHQjEWJh zCM_471v;^p&x!77Iw1YdwV6`GnQIMfiO&5xjx?sFR07d{;ZDm@*UIZRZJZ~PGMO$T z5)QW({+nAItNIe7^k>p+f;LxzL?I|fyc~0>PCT!jKLXAHHe$iP85Y_38?kmh_b=GOT4_i@0W7z z)hW|7B0*-(ak~*6NRT>IY;MbLJ=gkBFrbH`;KZa4%theBSvVF#l~q|8mqcGRDv#@R z3p#(d2PVX!V;wAsfATrRr0|&>?zMMnDC>C(3lA34{CW##q7NqdqNIxDhHLK=?|?GoDu7oSQQ2sAC``Kj zr=NCuAl;+{n|JT&)lJkv^18^RYt4q+`H~cS=PXnNrZB&$M5S<<95r78_S#dB4+XR3 z8o>Z5=OPx!lGF>+H~e+}x@ar+8}VrERv6~uA-Ny7G=|HT4ECByBD+*j^$U~Eg^By8 z2DS?Wv=emn$?34l{skSNMzF=Wm;D4z01qATplR~Qt3IIwe+r|6j~?8azD?;jti}4& zD)aeJKvH2qt=OPfh7&t-RT3NvwLt}B(z5L8QDRT7_OR}@+`6Q6Sl8>)b7lL>&y#8> z55I<-Oa8~X@~wghxq=AZm2h_2kv|+H{yM3h3%{>}ncC6yK;sTMtk z88b$-hIzkq;irhFTZx4uuiqm6#wkBQw;ucF@fV3#!t$&9l<$u`lEVP7cE`Zr0|aTW z^5NdAYxi{S-nWHfAclqMwczYPi${ING@Ts5KnTxW~~5q^aRz2EC!(4EpGnUxLyF=?(=eyS9k2b8kmM(X14n zno2{|2+FN7QLZ0^^le|}w9v4Itq$+P@yk1sD56t0d}^SOQLE25L{y6p`EtCwx9k- zxdJ1ELx(*>E$B%yz9QyXn)Hj{jfI=Wjepdgz_=l@XF7x_j7z}9{9&2D46CGmdSmMZ z{KcgUirK57s%aHB}t|-*&cgTC@VUP67Q~Dw|NgrMM8wL0ClkF zzy--X8`_X9)$qBkIUAa)ZqbqrXe;nlb3Fn!H&;;Z=&aVK4ANw8{{UATtqBwH>Xt^!>L*sb>Z{;`sRb9WCyZyBH zY4NNBygFa&2u1~~J9k_XR(DslQ3>cS`iO)D_zxk~QGEXEp1G$_bz}Gi^cvsL;V3YL#Gi+@|G9*YwFDG(sz=Z$%#?Ki|$mwcf4!PPnI<&tOp=W9CC9{_vo z<+L3=;~#Wt+Gi7e{Z~s;f3o<5<))pHKG%MnJn333|NQa1u)R~vul};*>$8_JM~(Fx z?I(73`=6-TF5Lfd)MljfrmZe4oHf59E9rD}^Id74RlACfn?`+xLGF6t*s_PHhu#i)LiSRp zF{6xFe;-P;@!K%>n0eVWO(^+?b@pOR3{g>ktG9a||5z}!oSKlpY=I+7!ds-sMK zVKpURDiy46RVQwtR_x$v`eoKH5>Y4}LvU)01bqPk=%=XmH;=U=vyG{kNtr56ISvYM z>7u?o-Dmb+9H{u_Dhqn{LelGmDh%r&h=2wvyYqj!`T4z0uZ%iO)o%ERL2YX+W~=C1jfkOS*wH61Tl}Kxu6c5 z9$vsMdt*O7{v^Fl|E$_#!soIimkKMq5ND?kTAbz-o%mK{ z?ca}&ADoTj=qyHuOBCLe?b0HX)Ry{Yck*PFQ5u1)tcaV&PQ4O~`84q$jg|PDmGpS~Mb~-V5o`;_O)-BNY`tdp z5`S!Q16h}}>BaH+9{hv91RS3evt{tw5Y_PD)KQPgqRUrdWZ63AZwS_DBN{xns7+*Ec(Lb>*pJvoE(|PCPuB6-O|J} zjuz$yP(3}7jW>MPJSw!m!H4Ia;yM5hEEg&T?#7UY=%v%!PnJoIIeZBTdgMfVeT1WR znl|%>_+8cL+ZNu{HAptCLut(9C|PFDpLWeCg(t`S*6+V_%E&PpEIHhbhzjN9hMTfI zdhGr*usEE?Tkm<(`xmbSty(EQG+Z!jhnQzEfQ3*5nsR;S$|;YEL||EF+i^f1Q`?$Sz0F{ zj^Dl&+UwQGj^zc@gC$^U5B4zEyf!mo$(@AvKOR}(@aXGazy2|qBK;J}zuCI~X~6Fn ziXfFp&H-Vjv0-3VKqV7f>6|6|EI7EPLUZc52cn(Q=IQ3B)y#Yf9e4Tk|UA}TmHQ)jxz&G>}zVAb?QT2N-V!0><4n(TKCjzUhu(>)sxk_ zybWvg75$Hh zKr7|eQHoMkcT~h~`JMb)#@$7Ds443!p)xzF;JP*Q_r-*o$|8xc|8R&2(J%dYa#tlH ziCz{)x{Yp#lQ|hUeg3QjOpm#2+w(p;?huw&^Y#ohfD;WxtO)Qh0Z$wu@ zWZ9tJC2Fur8}f`!O!!}rfeHyQE<%JXo(1-y(nW%aTSx|ILwg*-#kkJQ=>I7s40*J^ z2M5y*{OU{v=5kl%+uJ+lF`UGAJoOdN?cWKLb#1u=1C*A;JT;bM z$L6GZ2MevU#kT)_kS^fR;xq0|jO^khV#Nsj)3K0Sfgg5t2Oa`imr|fIksxHJCCQ(W zBwUDoZ&Ew!R?k5L65862g^LC>2dUA2w7{A)>u|Pb=TXC zRh;7-33GoaS>wIeFxXd0srB zhP)sl4Q#05n|QM}vu;g^e9jDzG>i3&QCQxex1mF%1DhA;gpkeIkgqcEa8AQ17g!5r z1E62eHyPxtwWQu9L_G*1e_6-a%Ap7XUlLNeH~)b6|0boE$ggN?-OWAPpuO7# zo)KVqsQeolr*f1EbT-Z@Lw^tq!UDNjE_HjWpY^2nCo1M+oi}k22PsKw+7(wgA zz1a#~(bCHiC|svGUAb+XSQ!y|VmZ@G^iFgS&G;H*aM%>3ETd|m|X|KP`A>-%vv+x&d~ zh~wDbadvx`j|zpIJ~n?28nYW#b-!FgEQ}ts7B@Y4UX!3#dCti1XuDvk2^5lT; z&|)}$$rvWGg09VI@Su~RACMqELF|DCryRhXeti#gRq*BxygTiX!&#`icMF6pgDkxS zQ(>Zf_;6uxOy)tUL)6N1R|DlnmREkemj@oOGUPH*>qY*s*tB`HeBm*!-AUUPqHY6x zE7h3TAXN4>+~P%ar{gcmWb9)o2regzp;E6V3SkroT!|U&eYDrg?KFVF5m60*(*Z9P zC%wceHA01#r5{ zfxUP)LvUZOGgEYru_IGm5aXl{V7wWwUYWz18toL4$`sftmAD)Enjj5ZXh)Z)gD!v^{0@K zcdAc|?S7p{w(T0~%%o+S)!!hhS@N=atU;wVVwW{&5%fg(i&EC@dU;SMK~x#Pvws@M zB0BSltExSBV`0SxP>n1oPhAv7B~IBcR>eW7M_p!6+)h6`mAgWHb_(K0O+)qJhQXZDcCITetM4JR z`*Fii);*A)SiH>^B&Y39hVj1g!g~t{HGz|GP#EF8u?f~{#V7j3qo5h&O*W$wm=$~u zAtJHg>{l%PkW-KmL|I86HsS0-;jL~SRFsZdGp#=%4%;sdD-F6aR^b?AF2QNtB6$Tl z%8*m!+Xe-p=B!P)JR2FCieJ#Rtzc2hIo2k{A)sa=!AVbg9|LSJ!+@Jzt+DgW z+#_Su)Ig4~t&TPzEulB}X+vO`t((t#~ldreI>D@ZiRWv3a)#L6LQI zgb0Z2qJMi12q#@>jp5gD7`%2w(&<+9CORBcHj5~*4Bp!pk>elsTIG&pxcH1`qM8`>o=iraz>c_~ph)%8BCbROT{_-#|`#odgK2>+S`UX!te-^Z8BRC3O1 zlg8c)&7)rcX?|PBp|I`H^Q5K`3Ac&n!huIttuNMwMXv#2Ufgx;Zrckl>BaLEiXvE+WN zfpH`IT<#1fYt=E&4CkO7$yY!UosmYuDdN*Rn7C)EtO-c13CLwBz7~Ei_g-?=H(~@N z9KDMvtX4`UBZjF>Q$y6=V*&}RYtbAgR=phE%wk0NDOxmPI4z0yS8rvPS;;?rg}$`9 z60Lw>aA2PIL#}}47wu=NKVT>?<`>aUiT7R_)BqtW#}LE8qW(2c_dG( z@g0&m8qEQ-()(tX>2HAd7OLsQ$L-x)x*5d$R0-4E3fW64)LujamjfnTcEdz6BL8P^ zrnXF1;RbJLsq12OxWNY#y&m32~#{Z$r-GqG^~0=&vfjs$lj8J;yi!ABTG6tM9KWE4Z_b4N8s5z35Uo?pv6mMns+4ckM|*dLo_=B@^e++4b+CG%DRshLF23Y7)A{4%S+;}P#ZF9u7A{hqp8DvM)1fl* zgx=adkV&>37o#Z>;60sxHmq?SiQz+>YX#f^7a;6bkh#3R+8@Fn)?V4E7+7U4yBN8l z4m_Rc3r~CZ*>YBwFrj`)MmPumVow=d|8XYKx)*y>7y1%g1pJmcJj4bK$NTF2Ti9Ed zzNuXSRx{@E7f*$qdKhkQ?W5eBg(q0mF3q}ze@}rYCMTMo;I>kvp3r3Ic;z=3oD zGu_W74~7bqN`!*BtP`uUTCeoK^O&b}*|ov8=tSRZlj^dl`4l5AIUQd(L3cFt$LjH*(~ly=EkJ(W47T z{3R5g8T`(&lG^-xHR>*|#tX53&9cnWEuRrFYc1nyS9zA*@2@Tx6n@G1(}TF_n^5-M z%wUggFh+%AMAQ94G(T*&^!CV)I0A!qe$Rpr=d04B!R>?x5Z=X!?Xv=Z=*bKRdHT1^ zwO9X&QXf^1A5b>JxU{weog80du3uJWo9UHeRJh`Fna09mR$1cMKRy5oTogi?KiP>f z>w`yP*<*#7C}r!zop{u>lr5zE)|RW^$-C+5qodb*cC;Wpz3Xe90%Lh~m@RC;=4Okr zr_Z*7z1Y~fPDX2v zav{sP)}EWLaf1t;DPkxx;M(YbG|{nY)6n@Q8haw5bUa#@bLLb-4EC-~0*$c5cb(10 z{AHYCKUv=JJzEr<8}XB2JKn4}d$`#L^Pel|M+|4(2bm(r55n)hc&Vu{!JQzxKfrcr z|Me;VW_R$c3VR3!PVZ}n@*-B!$1|f+1Ud`6AYpEOVv-;z5UT!aQI&N6#a)wZ-83;k z;$1WLlUCpVGZ@qH6*D#lJRn*(pOoJ*E?{;Z+|WhgGs-!N+G?anWB_We&lpCtE~_!T zoK^j~4T0Skt0qE0yM47nlPW3zdNl!&4xsvy)PSY8@!3ped%DO0WuwGUef4TbS}A0$uOm0jD!bfIBmWSd|l;|ZAGlVhh12Eu|%lwI*t z{%FOQY-T53F<1K@{$ZFfkG?{BtWyCSKEyF<@Vbt9M$ZRYw}&6F>hAOX_6Y`N1~P7s zyw81tmj|wq54=h`i%biS`gr7Dy7SYAcR_@;y)ZLRzEphvx0`7_!p&qrLONXACvA+w zDVWxJ`6f(ZF(als#bQl+dj7b8(($#N^1uydRS#_9`iBzm0XotJX)tF&_nc59QGwWi zSmbJhhh`b!PQpQwA5IQe?_Yct4WcyVJsvH!KjWHdU^=+U!CYCgIuGgI!J)9MPeQeC1TI|uZCkw` zS61D663K8<$711RLty5r>9&><_nt)4^Q$3dxZ5yoy8|yd5YV;|7-~mFZ}BZSozmF+&4Qt$x;qy3ZK^5|Foe}c^%=c+-G*m zPcO$n?VXYs+){hkD4YtDesvfqno9H$Sj`YsF+nU)kLelhf}XO4#50jt;CsnG*2MVJ zBPRgcbK#NZFJqFDUV$#PkV#==Zp@za z!~3=7962HR9GHqWHgy4*-!y{cFx=h{1d^z@|? z?5tj%!W$g%09%~h3puls@;2ma73_@*g}~B(q4$eHk$=DQp?_ayHZoyROf-7F>UKc{~*`eMx!x6Y^bryq48_T1neK=&mkbcv=@BTo_UPhj6Tmf3cfjRz>i=5IiIZ zk1Y^9lcNaW7zDJY5CK_@mB&EiLh|Y14J8AAG8SjGoM{axvG*95@DK#pFly1e=C+o2 z%1)dq>5I)ReV0?8)Neki3i|dcS9CC`F6mP3Bx_&pGp0X1Z=$-5D({kK(BJ^~Q`E>! zqvOcj$rt>>84A!FwwBs8f2<6i!Cnj@6`QkQHOh!sVuZ15SoCw(ZYGr3dBUM{n%tJn zqu1YK!xQlAOYDN=7*-8tvk?1gTUh3EeqOn9a3M5{FWyIiQTM8|q~3RTm)hzs?$gD$ z>H1ekv0KZ#jXT~GR3a8ip;KrLI34oau&UoN+o*FLudCw9XQ2T$1&dGK)84iHL)g>h ztB@9s0Lyj!go7lNXu=>qlW5CeCMysRLqGuCUIj0<7I8a}jg&s$Fzw2a#$O`kyqTvc%}gqjC-LtERQMGoDsZE!wS(D!2fR5n6-6b^MgcOqD?5Sc7=+7c3U3gl zmsFkYpB!lF>UsVlx=CJy>z~6k%2QZlb zezVgx7rMt_?-2sJk7$hM znM=5gAke)2Y{c*~Ci@LNAkCnZzfpEYk8|+0Gi~KOdi=aBxGqM@w{{{SH6b=fDa^bj zl5V8b3QEN$8!>DaV3MY{GV%2pj9%(B8Z;^YwK5ll#!Z;q{GYaP6xG5LZzJCicU5~0~vnSN#QoTch`-vC8dCgoqK*%7x@ zc-E^6=Ft6nNId_=lz5Pz$`z08PCe{kM;GE-$GfCFuRm;Lh-YqAH<1hNE|0FopX1cBp^2R_!b-+#Q)uXB|0)_tz% zTg~8WA^@MaiGd@SzZV!^0!Hl$X0VX3kMWtAVI3cNqZx%1)0Q3A#=Zc%$^67U)aX^n zgOMu>5P6bH_-^(p%^~f>vqqkbqd+g6fh1$kV(l|6h{j#Uc6c8KDzUJj1i) z4x%UnXJpiWdT6|O`at|^@#Mjf)8>Rb;fDXQ&M6aEQUBsZ0&suK(^6r^uP)r*p|!v9 zLMGslS@gavp1FA-J3b+a^B6Y)C4^j z0!#)a3zU3EXJ=or88VtlgjmG3tMTpas1n=m%V6*Z-SPgK4&pcstW5s}qprHC5p+1e zvUuBfY|mI+U zos3VG&_^N{4dsMi=$@zLcw(+zf<{yd`n~Dl>|MTibsQv31jn?i*UR}yh*9kj+WArT z#2^g)?dx~9{&c5PS7#G-0(Vig*r$i8qpTM)^Hr&5S7%Cn51;akTLG_ukvg9PbTrIx z0j=(SyWhB!=kt7{5~+va3`Pm2UV=tZj&&5Lci|Dkr1j#BKD!bSo0utK_&}bIj~sZFfVp`-r!-@deL`2I9}Rxg{W+p@ zM@z|a!RiWQYg8lSG)yn6k!e~yNp96xQ4#y?AI19r=h|S8w)4#rQDMYDZJj=)Rq?x3 z6}DQxM>ci3-}bK+>eD8>wUZ3}{9}7Y9C2cschChxv-^TLyPe9!V%{4F<)9FTKV~OE zDFn|z(&?ju;+Z9;z7GQ1Qao`?43KH6u6P3}XhS`;2%)$V0a^$C-h9cksJv&?yXFhS z5SbK^x`(q+*l+%6Q*baIN%_$hYbw%?X-y8$w6(e^0h1a@mH;^N=xH*NX4~%0(&!bD zOO4q=S6QW=&SUCwhp+CZ4RTy^%l7G*fv&w125J-@d&G;ux!W$O>FKKR=-7ok+jCi4a4Y*Wa9nB(H%(E~DU zlG(9OgU5F%z3P-pW^HrY4GUHab4$g0TiBk2Rb%a2ytf84O&8_pSRQ2b`hH58J=pa# z_FwSB!i1@%CmdoJp0w@a3%l+uNp#WuK2e4z{2dTRV+xbz8@5}U=% zeBht$yn6aDcj6FgGuL-Bh5;|-PI7^V^$(ZZZy<3kaf~;DB~#ZS-(IZ=-77BEnCIKt zm~UtfC1jx99VCj-hi}nbKBLpUVTt>aHUId#_zgF1%LezHW;2udh}pMySgPt z+=V#FvG-1U^) z4-b|U344nRn*0^n99M7LMG_j#$Z&f2#;#55dB&xO6Nh)bmcKHz)p=;mT1~qq$K0%c z#8)pEiH-YJ4~u5TOVLZNj=g`qmQEwAZQfHYqpg6PgX;S7oA1xRhcrY%O6{{BTcFJ7 zwwB1l$>>aON8wBZYG)EDvXv<8&`A4Bp3joyfB> zH++uEzryC)(9?5C8NtA<78cwRxyOz)_c~8CC z-#0h-5v)biE4$4$bIA>6;-4GL`Rcdx%C>&@4d0CU6~&PF6pM&qCK!q3Pi1ZXu_0|) zW;|={&8kt~cD1(op6~Tzx*KGY#w?EqLPMp?6mOXon3#-2bT0QEKao9~GMlSjIel@= zbYL`l7%_VwXZB?MWb8h+d;!T8cT~+&HutH$C!FzBFAY7fXmz$0gP?J|RsyPp;=Bmv zw_zsp+r7eg>rji?mJ)+J0LMNktwcSwu zpP#G${JPl$x0%m!%l0>zywQ~Z#?tom`G&~v;YT$M#<&mYImr^btU{}E+XBXIKA(Cc z|AX=C634jqIc$=0*2>+?H~!U$bque|7EZM5g(JUBf7zS*!D%x$E1l3C6PdICYJnsKwhd$ zLS9QPqXxndqCy^V%sN&#Zu^+&Vk8Oua|6Y*qav-knU~$DFlA8Gg*0%x5=n9!b5eL2 z#Tv+4%C{}i3e5!x;q{=i`jA-Bg9fmf^|y5}?v2yu7IB`QP3Y2@+4CRa>2bzH=&wrg>yi^Y^Q*OuFqXN2(f$$w1)I+%J#2RU ztNlBGKPn%qJ?voRT-9ANqNdZ^RAf1hRS1VH7^P2@z#T*qMR>#opifub-f9f8w-!zjbK&GLRYy%_er{~$m)2G z=Ue_-Dmx0%sxxx(C!g96Quu8fML}{bArx{Bxd#MFf^+f7MVf?2e$QJ@CV6Eg87X!$ z*;vb5MoKOV^E@6%$^*YLZGPN-CEV~no)B^5^ut&GDmiJboiy)q%PaAsCiH<%=AK)j zb^dW$bt(usx2(jg4b;AU`@HmEzm{kT1eIhLwAmFi7q~yydoRc??QaH{R^>h#1UTs} zCmI9-xvCe%iAKLsO`vv12;9OOvmQ{wCq)91(i16;RvP2qo3?mxP}XSqIBBEk^zA8V z?meO5N*uStCFdSpBUG8x7iZ?~LfFYF;~FH2om%;l4&ChqF}&8}1+Bz84fC56nyH+79i0Cz^RfY~L3xfEOwm0VTLjM$sgDb&m_) z62p5_nZ0JEymrQGGRB&AL$q*FoEaetxl;U&e8I=-!vyy9?2Sa$;@W3Jh+bOdia_?| zxPdz~ao6R<-C`{!TCldnIljX+S6jkdzfNWIMW(E@^NBh{YG$8{9Ox(8Bj&k}7<=C+ z#4XHR*x)WbqZQzHfpL(UM`$BYm%zPZ8i-tkGZ zZns!JQ+9V*YSq^_ue!U2WJi_!cYwH;IetAFNKpE8IYh}+yaNP!a~vZ2TJdcTfrct? z{?#dSchDmIYX$Q{UI5Ez%3T&>4woax^aT|b!3Fvx!xnxR#O z9>6KKVE64;cAKa9eYu<2N09wSb+mU_12}gOf!=)3Kx!Y|OagIp%y`p(eUSu#ny!mF zPaCg(+&>FmMl^`t^`S#dkn2>xSxh#iP>N=@5joZ*3pQRW`sQn;tb-(gQ)Jb8{k8jjV;B$mMG|unPrB>1>WJ5OJX#vpb)+zj*V9zib8NwE!aK# zkL#`QFXAnycXjq#advf{2K4n7tPvyl&VKEyM!?8Uh1sRL*|hZ?0n= z{eIUuG}eq02@t8D^^?S0&4WslQ6f)oQOjo0bwDO(0UdF@4e0FR1Q-`A+SjRlF!sMh zW+XS>h!*n*Cfqe$EAW&y5*NH#8@aB+$uU8S7vCjsP{|!(N7;KoiwS?r!nTaaI?ExS zsjYbk`CGn8BOHtcI=5(@(HwAG-e+^7ZgcHRA9nPcwJ+suZxfO<60jMi$;ZX9*a_oi zY3=>W9h*>c{7#UGB1sZd2?P^anqS)N0H=#m`!8=ZMTxT;-_8{gqIJT*T$6mkh8~L# zB~(2Q!?!)I^r>}PF-!>6j7BjAf^F6(7#w{+MH^ zBFWDM{oiK+`2*-M3i#iggt@osz0l2(Y2aCWoSWuU3{0~qW|rzAYqpAFx7cc;nvSNODxd_}a@}o7OKlN65y9 zYAk>?kIk5QL-9J=v!63LlUwY114cAzZ%y17+-#YCDcM2KkZZmx&V+Ym`DwRWlS_hi z;(Z1g21=#pS`YdeWz&Dk{XZ)ogS9(PugzFU=Iu9!-y)L_`m|JqjK?4~!SSX;NJgU zc|vnda{A@H1vK}9H(ZE9o42nT%u_l(C*`wLbvY&4xl97x9*;Rs7O=J1s^R% zn)u%6+Un+Uv;xp7{bxX>t`c{qlg_^9gVY$s@|E@0**?t3zVoz4Q?XAbT{7PdtF6l9S&!rC!+s4RVjZ2wh708$II|4h zri`V9S`*QIYo+>A{iS(i@u2Bx(`3|QMNZo_ucRmb%b@359wRelk6e22p{-u1R=Fws zc=*MOdy?8*pGWDfW6Tat`*+B!+xL@+$PTk+2jaVneTaZPc~84uHaT=aYi}JUm$F&n z533_AD_&H+QS`G<{iM8>O&uIjTus)C1o{9L1*-J;&ueS4NtVyo02KxF;FOxskNEDs zVX?RRP~ju&enkf{#+ytew1D|+_(D`;oY1RnY=k63vGQ8$S=G`)`Y*uZ6~m_%cBZxz zlGVoUm>IBt7lMtWK?BJEs(U?PY->OjT3ZUso*6n^@;O0_8D{ZS7g?7(fZdxBA6plP z(z$YtvvE^1y>k}0LPJb32^}|82aD_r3(4!N9%f4xnt1=8u+}$lCm~qWXlb@S9i?+QC0(xmG?IuvXTdxK5&(9* zt+?TRTQchu%-gKCyZ*I1&gGJs)}0n$dHDjlNbkM#q?2Ya+@z{lKD=iS8jF#{g2|;z zR1&(Xn*ocVj~YBYV*X+Sa;|55$In~A_$jIV+W*x%e}c>^oMEOW?5HVvn&PR@o%I#| zZ_9>`d{L49uh^!vr;`zb7sa$aKb)bgR$$OoYnigfrps*unH}=YdJSt1eBEWrxEe|p zRCe)iTZFH*t9JpR2T&??Y>6H&wLe~I!nC*^-oHOnW(5^zGNkg=DP1Jf z4j(2@k%tW6mp>kj$OUfJY|l1;6&+h5SG~nb*|Oz^Ys!QAER9%9W2%(QB0$9NDO`U; zBlw0Du|O}tO_7|pYSy&gh&lH+bFAOD718H^V$nai2Q=vvY=ti_4xG{rC)c#V3*uux zS&4%?>;A*W??!(8B~{my0jA{i0zSG?%TOu6rR@fzzRUxFGux)nv$58CDN$o`rT7HE zi%3#9&Bk1%4@-SPw+Fy{=g~wf!KrUOQ%wd~N`Bct^Eb936k zGFyFZ)jo_3zXb*(714x@_yKSoK-~9F3I5xpw$5F({((YZ9PY*6ZFuVjbsM6$Y5+nx zZ+qzNdQ#)xCbV@{^&R`SZ``T|F!P`Cf78V+i9=wBXTK4%ps!`_X>b?&T@+mee7g=; z5Wn2|OeoAmC-{qWzMd@t=lLMl*OaSvqCDuK&x&kyJ0c?zr#Pr+Ac+Y2D6{QSWJ@JK z3jQh}S;~7gw2G)6VamfI4^B99ch{sp>ue?>LV^DJ`jVCXY&+P~{(xmMgZWp2yVwNsPy z=!NWXjMhXik1gdqv)u#G1oS3GL^%ei_XA?lA-3QzC3?sOPTmRYb_7S_xN71rWfO+x zqPFLwsn9G~bAH>6<>=EpgAN!&-xwQ)!rEa--`c&PHwxq70Ef<3?TB#kl{7@P+ID{{8zwjP`yYaE~dB*y5OCuoB z@Y>`}^BtXxZAEZBVNYyC+ML}O=2oSHO>2Krw7~o|+6T-n(U)S1beae)-I>L_LHg_N z(qo~QsdRmipat-gHN_B(o(*SUQ<#?XEnfa*at81*V zpVnGl7upRa-z^AVoDAa~Wx7vAR|p4!`NdddVs}i?D7=_k&#pMC?58@-D41`YWN94> z9M4v|0hUx3uUvjeTM{TrVV<=dY#hM{6_w^+g^>;qjkE294&e0Sh_T!AQxexVc?p^i zCo4^-I0-4_;hBMN?l>QRrWeBOb;o2n{aBn?(<`4oc)?~29-u$ebk3WA+0_{4HT9&J z3^U=&v&*rSc1p>s*g2T6JJ3_S)N4EsmNV=MUAa6>qym|6)lt05GVve|x7MB4A%w z*j+X>ZTi%tRq@;aAz{6A!|n}n^^ARFpm9ba~ zoDwxlhuK^v`8z6)woOLEZp_TP`>+FgOgTp7!7tDM&{5>2{%7;lvGOh~Z9#pAmfUqT z5Bh=5-nSHgh2~D3EEaz;jxIAQ^#Z?mWl=;&@Un?bm# zJ0pP<@2T&Pk37&uWw$c}57;jRnFn)_nW|5dz0qkk!EI0d z&N2xQEbAKI2{l>S+<&^$a>-Gt8&1tN-0x%o36$Kb}uc)f<2jwOuA zpHEGy75U9P_F2%arhoKwoCTPmxhD&Lt!GDKl1tXl;I+a(uD{b%v-U0dnSO)#`TkVI zWx?c9!B0a`IZD@w_Yon_RMqt%VJ?Wk;{{4Xb@{)f2$iO2$N=AWHTHpaCN7BKWLhsO zQ?ME}(G^jJNb5b~_NNwR@9~IhLfXQ6=CjoaE|&IGJ;Tzc1Amf^nj`fhL>;=}j|7tp z(b~Afs}5A&NlfzSC)FBxpI`(`cU74})(EvC(^)}NER|=uv<6)-MBq5D_M;$>qvtr^ zh~1AEQ5Z>#TBb!v(}{j%h^lK5b|f~9d~=41j9-*)o;EtiQ)EJx>vKt5M{#^eS_`o5 zL6db>OH(2XW@?A?8zqCvYsm=b_L|^2TinK3j_E6ODrJ|h3;pSwYEvp#4qb7IbqaOj zS%7YD&0Uy!e`A-qCU1tc&KLW=^sC_9)lnae9%n$v@$UzO zwmAESPbXRovz=7o}2cVN8v`pL_>)Hs~2o zieh_)5?EE+_kxKcMj1y<;_+0n;|`Fk(sCQ%u(VF9?JRKpW&VAfD5+X<6aL#7wfV=9 z-O|4-^dg2+_i+r`q^0C!4()?swKxj&JE`vK7xY&{T4Th9HTk>yqz$B*`lv9uh!NGA zJk=o_VV|mf5WK`%JW_D;PtHOKe!|MYJX~p?YV<;E3fBdFO6_Jls*rq`3F$}Es)Z<+ z{zG@FRfjm{k!)j(chFR@`xLjTyZ=`_q+zNSZJmv`z>+mknkEF5WXHawnYoI=&Z zH->w0s8j7aI6GDVLy#6C#?yvpFigGk>W&@~?_wygnn$8x2S%b% zZn!%hOAVAz8XVnE6nZpa&`vCGRWGKXYS{>at$RlrU=8-FpFtA2b?}3Y{bwkYD(Ru> z8H2u#6GA@4k2)Ux1rSuQwO|)_^W#NZ_+Ay63->q;L<8;Kf7D+Ozlb1zAMuT z%l&%qU9tUP&9~1v8Yh@9p5eP*xck%T>oOD#$WPV^y^mAD2WMe=;wW^fp`zCNKvLvFj}Xg3$5*LkvR)% zLH0SOk7%Jvd>p!>LAvo+(PTQ=PE5s_wi~EPQEI6iZbD;?%+WY6Y6A>g4k>A=!cuA? z%RD}XKs^)i>!_`=^xNdF-pG(P zBBTzm;7L}v`(kP6xfKzXwBECC-<-iHqzm$}|Dw{Sc7I{aT-lTu6!(V5dRLqu9{UxOd&bc^{vvkLDHm92!BjVR7|7xE6A@}=D;#*MW`4sK(u-C@M>jKHLIwhbg0(f5+BsUL++35x^#c|JYDicS?)i~l&mmjSfu z7bdVr1W4=mh+KuV9;&v~+-J*N(9sXzZ$d#z>Ko@v7u{igzP|2mS)M)~62)#Go$~TS zUT0^7>$GJ>Nb@y=X*sXb9^a1ySHE!7DjpikE0!pBuLS=2*}EDZ2sWM?w~q)47i$j& z>*={PKPy8UKD?_D`z6+8I6|iRCFfeuBw1hWfky;YTISu*qTgpRY+^41KHS`akB^bZ z-cbKAV@6^si^-=p-zm|3Q?(-BLT{ZQi5YDRY$yoDJ#rr($_ zotU_{txFD@ytpBaPGn65HCOOeG4hB_Dy>cMh_P0OQ2H}@zQD0vuz984Fj|BcEJ(9q zJRsA?y&zV%2ArVw$3KXEb_rAwlC>+&R`hi;?}gLJcQ9eY*r9874H~0!kb(x5?XlR= zhKP}@4Dv&jljptF?;X*ZzwAxTIqV1yE$yD`qzCq048|c7|1=8egMJ3g`p{CTR(LsF zgv^a>$Uj`U|LV}nprD6U90?%?pI+YlgIh^r^|SI171rm*zyfGp*Dcu5oZ};7%`tt~ zvP6$8)8p(J2|VTOm>O~fyxU0cGiIpG$1d&~G!9Af8&H*#R(rB(Xr5h=ZGrZv1mt9i zo3hx1{xRY6P~4h_E}$M$dt6Osyt9nWA(lj6BGrid?54_Q2<}3z7?199PW+aekR(#$CBK z3^IkzGA6j=mQ7I=2cFbJ>RST32WlIZTOC3!SZ7wUTy0oNDBpI$r-Mf7f@LEFKi$o9 z=nR7FxryvzWOSVy9*F;UHGKSGfd{8WV^doEu+jT5EWuNNJV2)>n%y~Dk z+dH+57s0DC66)eT~d0oc2& zJBwlr_5Ica39WBou1x3xcxpIR9dBO-Cr}Gwgs3=k51J#+Uj3*GtEG>zanc)8$g)`0 zJ(ic(xKWK_{tQIL<}B7^0}?UGFQhqc(!J6V^9liCVr>8-gg-8&%MwKY=$)9hI4J?j z*WFHOn|Rt?Z-f|ky85dy< z)sLtg0cV^Rm#q*-NSAQ8EEp2Ryee8ufN=!I0q2gPg<;AvmI%+wOAG-fj5osq!b}4+ z2iLtU@7+`w+@>1p6S26C7J?~SXVQnS2w$(dmwl~8iS0`OD24+LtgXxVE;xwItB-h( zD-1d03r;gk<|w^JcaTTm-nO_Ocx`hKr7@qP%^+}Iv@!u$MM>we8k@nCqE9~nnT&A+ zkcNnA0T!S+3Tde=i|_H-3e^L9H$oKQ@6@gw$(E=tdX;km=I2-?>*n}wK_#_`9$*qN zV(GWiX7i{2LT%STUCg8QRU?cp{FP+J=u`kA=D-+1C)}rw_@rs@LNfePNVh13oTu9F z3tk|w3Y_N07o;hD#tmMD*hxYS*IIZT%lZX8nMZXE3J15BU_8<#NY4I3eTrX@F~NiU zu{gFjQn~pAEkS<;scyVkAElQtaqR<(^|b$hk=hvA`5v8lOKvQ5++3ORltx*WuWu<6 zHlT7Y(VR`$!L=~Cr&HGGLfVpXXgZ$Yk09zriiKLCLvZMzFf`lJAkmw8-dvhYJN^1D z*n^go`&~jMt?4Y{*G48{&~OJR9oQ=cl0C`Xy}}dV0`WzN?d4QRipdGab&rm6$$7V| zx4vgBi+9@=4%|EGe^oj-&_i|Lu}Veukz?suGH#c292K!cIh{Qr0X1jsPrgRi_-AM7 zEqFvQU_nzIXnVESXy;4nEDO54dT^WIYg~2fJqD~BPb5ATI1@(o6wjKM%zDkFOI(Cm zkgqP`Q24I(kii(nC*D|uM!1RBW5ZzHba=&t%5d`PspB)$@hh0@mYPd`L&ETc##rSc z4f@08QUq16zu#kscbtEXWfxbS)L{oCv@M|4@=8H@0W!Dk$m1-{fLX#~5mM zv47nwSdY8=U>{f%bYk%c4{Wk`YbyrWQ3DpU6hetrVkzinbF=B1?Z?B~+p0dkz*M0BnAy`*Oo#(*m z16*8OJR0}!JmTWohvDMdy}EBNaHSA^#uxap%k`1^ZLa)|Gn2qCzgnwmt8#G_gdbdg zvIqEmzw>=#S1zvK+_wJh8h$S9$;Gw#N#l;Hz9(dw!`*d;h{|}EJw-4ofjd#6P)?|_ z8V-RpZbCn+dEz3Lpb9|*MLui!LjwOtwTZedy58gu3H3cRVpA`1AMRr-!+A zz5jLp>-%@Y?(Bu!Iq$ds5Qx9_>-twe)`p_igpb$r#EdD??+oX)g~`O&8CRcPRva*| ze{WqE{K5Zzg^Mf6dTXiw-fnds1?~FxOI$A#&w2myAJ@2))mDD}&uhrQx&8lnZQ;-; z?|)vKI8`U|pVzvs|KAC6as7WsQ2E8eME7Us(Yg+c_R#=-$i5JMshRaH#oTGS5`W=} zv}}BPe6&fx>5$xzvzq7kSKJDE@n4H=dr6CbgoD;>tgrm_4%e+4e`&$QYdD<{Fzd5i zB~mXqzedL%sd8sbiC-(3CYNE&G37o7S{%rwc}0Kg!WYZGv_qKAGkG?zWhL^Du%IK*asL0bBGvc_v(WX`rPP z)#)|d8+$-h+d%}v|0kwb-yQ|oo*b4FJAT{t7b)D_Yjz&EMq=AqQX6Ve?7AC7v+I+U za(GqqBePzj{)kS0=O5!8{-AE&gVk&4Q$AygBda<$y;q#A+rNH2>jggw66OAvWxYh6 z_3k-J$TN*$w?9zc56zC1g~gf5W$Cu|e9~0h#)j*V6j+7hR=z?FsfWgxpUAIXGFe_T zdi5^$x^*eWWI(EUWAVGLvD-E6OW7%c4Gr|o*uu~y{?*+adN7rKA&8oLc)5g?8hA9_XoGC z{>#%O3GKsZ9Xo)Yu)PHRMeq^2UhmYDE~**{%?g8U0sZpH?>v}~MiwaeK)H*Rb=Jnf z>eGE5XBN~%vP^VTTCVRag^>w0+!a6m(7ePD9*r1%J*OcLIKe|wYi-r*^Z0so(EKro z*pAH9xJDyHw`_)i$zt9X$eKDS)HjCXelA?D6fDz8ro1VLYxNY+6&QTE?5EIO3uvAUER8x+O$|)t`YZ^!U}K#% zJhA=Ot)-_-7jTiuH~%n(~MloIv-fCUSzH1A=`mi5|Ec+nU}wc_qT%y z8V5=*;!W-?J~SWu?lg!@pQyY?)HfMv{lktMRxfs)o@g`K^NEo`X@q6cZ%0`y__yau z=lNV|{%K!pAeX0iLW0i7Xf;5GOvOB9#~ERBQP~H~g)?ZMH-u*`Vp)=R*&l?A6jcht zUQIp4XPdYFrlRqX+;*OhE3ryqm9~NRTMMSDqCFt;JspZAdImORg(i|zKc&>%ZMtx- z!%sDVWem$(#N#q}=24GWu)*_1bEWp|)HNQeNdAtJT1tnC6SWN0mpIEKBgQFmYmDzR z%N}EmZL!xWs0-fG-jB%-zNLq`Pq_;)?Jr^Y=e^K8To8hD{ZC0Q1gV?Xy5~;f^u%Y?_k7aRQDdqWz zc2;|23+Gz<&N_A%h>|Q|dU#KIdi1G@6Ht;iu^vuQwA;i_r!HaJ5Z00MBWcmhFjepA z)~JdUl^Rc>9U>N# zcWZZ?aRWXoS&P#Hb+FXmJ!S~zSxMiW7#AJ1*Sr^{cgh3|Z6g0MX=#fD^AYu6&!A~! z-RkOH79XOsxL$JdUgSCsZ~UahG{TFZc|LaaGSA-2eUqTNe{iXq9Pz}AL0MA+N9;P? zg!O|wg~yiO($iLrJ!$v79eTf_W=oQnKCfo0AG7l^g}`-~Q+yZ!X=RYKl)ipHB7^fT z<{eoFYOKs^orvO*L;Gdy~usnLrgD?T^vpxhskqBNTo5$ z8V79}$M17S(&Miwc=WEB2xydqz*JBwJ0}0~>z8jY+7C&4KQiDhYwhb?b~`v4(fxJD z()7y6x*2g2822Uv)v`r_-{G@>Qw}{s2?RfPX95r+C^bjZ8K``{dOcgal{>^mlms0D@Gg!}mviS;J=?6yE1x3csBf5+}U0CDhm}p1!3`YhJ!%C>1pcyAG?( zeKk|8)h~v1WOf#P!^!H)uMzFbWV*fwTn=6F%xufeu(PTBNiHnR_Gk#*xjkg3e$yA(xML@W+!~+oP8|BFc5HNYRIM&Bu=VN4F!D^<9QPvC(iXw;3ob zL)Zbckodl2gvkz=`gqq{t9U4>V|AhAM~T`RNgu6DE!?{bIu#SYY;ugb8f^ehc0K15 zzpZFoU5bFAwVkaKfpY?JrOB|UfVq|lOPJWXztl`#?%&i*)_Xo`_qp}O;iHlQUwZd( zkLIx<`+Y0jz$@hARf;#1qS7~}b&fG#LJ9M-7SY>iJ%e1mJ@6%`?EsxItaQR|Y-6i|du$+?O=2EOQy6AGX(T4Ca-F_w*aTMtY9(KE530@>!jY@i=s6 z@QaQaV3F^_p{sKB8WxIkT z%e2@Hc(27!vgu(e>XDo48JPT^n>W4P9?x#{+OIsz_Em$BA}i%F9|mz5DW7Fgm1EnRl48LWuYp@$e8PvZAT0gzf`vvlF|^Di=9 z?AJboX+XzJz0nnUqagllXxAl{LK^i&G2{GJ?7PIsEkHJ*wF|Yl;itcK)!3WhW(n6) zYxSt`F{B;Y$n#{%$jb_V}$r z4s5lMZI{M&Ab%e3btRE&CQ2BDxi`hKr|Ie^Md^ zq{J47A6?cd*6uem!D*oZ^`3KuaJENB3@I?(R`zWTQIjTHiyv zUMM6Eum0ZSs_aCDF89B&Xg0={EF>&J?EUN%xwvd3{SIJ0`c`|)5f{p4ye_U!_9#0} zG@MDF3kHF2s0fC(OVih`ZliAGE*!d2*^^`Kt^EgFTR-q`qse4*qKauBJ zFf;PqPt0jnRmx-Ph|Q^?ye+7C>qSog-f{Y*ELEpGw~%`H5UlEr^rEJscVBm+5%K1o z569>4|v>EKG{{_pqN^8awhDqcRo$R!rkJocjAd^0+sk7TKkkfc^B6$*HdmQ4LD1#uP>@3 zHvX78VCKkdnpj?A)%g+8U)@5d(kRYqSXg#}4S zDI-Po0OW+L9`8Yv;Oe;S$T<2^_S7Y+Rf08gy-HawG-Z*xT0Ie!MYr%mPmV<1Jo#hK z^|wfP5e=LhU8WICfm`a#wKx?8A{9FZ7@sWU_cq;{s@Smh^%i9uB)rA)k9x=LB4 zb;h)8{J`RF1V+@3oh$Wa8(OX}mYI$Xd}c@<%r_O##%8uKnUUpW&=fu|ls>0%s&DWa z6oGcWP5uns@hOZs(E|?~@Yem;XReBquZ=x{-iN~h=i z@-x^X(Tz)q{IYYG1u7?F{t4;fx8*QaN0g(&`LT@t$iWfMRhbo;%+lRlFMmEVSZP>C z9@!On^N=_PeAmpSCz+ZEi*O2KGEeUTAc%Xf`b=|6*&g`r92K z8;HG=i>5<93WUo1<=5lqu`pzwY3!mKICK21mfrzNqQJdwB-6X!*w-UzHXG(JwqNsTcB zQ~Ob3Z`N_PbJeqE#JyoJu%?ZX{jT8Fz9B;wz_vTs(vbba`uRr+Tpj-SmB567Gp1s2b~|9 zxg&KBWdrUusX|{6^r13cN}<$1*UKW7Z67NOLv#|l;(GIOV9E{gFDAk*mxZ3 z4H^2L=I!k(lS#Z&)|@hZZMM|x2*b&{Q;NO%;@}Q&&-5s7M9UAI_kL=)sHb#yB>N0u zE*RyiA*el7tZQvLB>D{5fX@mAq8&B{^?4lnKx!QNp-eDbn$Zi3J%6|_a{ol8nhBZ6 zG_d|->bS?12iW>6`MwW>JhjXm4cw~U6{204tLOXo8aGRZmxnq&6iF)0I&9o;0DptI zdH#k(NFn=l(8pGH>7P-`f9j_?pr6fS#1Z4K^YKg7zim8e-?bcv3*EvKTmKdW9{W0* zYwz#a%Ik9UcRDh~M)(oceh)U$#WImb6!EHH**U3M+lok;_IrZIN27YO&o+(;pTmqC!MB z?m-hF^-v@eePU^@m6<-CVI5$cs9gE-6;_P(*rbe z9N8`Ab#yE9YX8(R7kr8v@3k5%*!kojh7ZW>;qQ(fdBM+fiGE$NCa|qC@iHkWGKIdr zlC}Gh?{ZzztjHZCCk_r1=A8{EU9UOu7B6O3B~1>SrMI3rc+A2h8kSLLW0B`D2=i*m z<-F-^hjbnbUr{hzZgoMueNA#PwWCO<(Sp=ttuTLh3`cz;6Wxt-+frD0ZC<(tH1BnY z@zUd;-7wRpW+g1TQlf01*iNOB>&y31$DHTc`!M&FOW9MP+n14%%NR+@n7c{FVa=60 zg7U`6ym=S;5yw29-#;Q@&%(R;M`c+Ic0`{v1tMsn-X$kRAt)(>Ed36*NOh`h$}ZA| zKe~Juc8u6*AMZ(Vylf%`YC`-J-1MxFcJmU-40EBSW$Ea`LHuxP6P+*FNwW!^lb)W% z)3+;Ip?PEjZyyinqZBd37`jY$2dW=t>F2%At5hobV`qItaht)68MtTJVbhi0XIu76 z!VL&FZm+kyqjYE=0yT<2tdOO17xV26mB%;)Wlbp}541GmDPZ8mXndbU4ebHu$8Rwi zs9 zR0r7rgrp=Ou{SC$y4VyQBT8{!`tdKLzl~Ne4O3`%N?nSWa&9~Q`LbPnc>(}6c+p5X zq>X+{oOJI2miB7un1^#blJNt6r5XP-xwPwAF%;gBS>H=Pt8Y#nFT7lZWxluq-ii|u z>ey|?g@hukfKe!w?SL;#p+i=H z2{cXavP3S#B^JWD(+x_CtcdPjw7|g_UIe&by1hz|{U3!yt!t&Yg*SMaqN#MN} zRVJC5;X%v(0p$th+C7}(CbEY&?GR4#qk?0Fj6NQPXu}%uUWg02utQV=Lr|ulIc7`? z4%#E9U(>JA+iFQCtr?T`P*j#0{Sz(d+5}4{v%1*KFy0ouVs@q15gLqVEGu8mvxdZb zcy-t(N@T!(l)Rcsp6|y}pOB-6ebO2L8whi`e-FM8R-%g_In63Jz44PrkpJ994^KL# z9S4pP025XzB^P1T5l7Tkeow>@Ri6wL_FR~`-$HM@+Uk}T$#4iR0KDAMhtMsnK}*Y&pwb<~cE6xWMQJE5$Sv7lL?(^#%OuaE*e6{~J01^ZPDFNAnVz^`h5dL|rTRK>OvrPH z?48y5&>U}PjKWj)R^F(d{_AW80KRK(q_^fd;8s5Bx{UOluB z{Rz5U5<@gmiG*$MHsJnXA9^`P-Y3u3_(h&j5V*}FU+D)VhF=~K)Q7`;>7-jv20Pt& z44a5TiKpKbf6vs$XK!W6l@&`}K7+U1K1|-YD@DBNf)KKewM+HvBIq@%)1eR34+*S? zhnqrT?LyqTlnfZ8c0{k#U0Ol0EaPXwBTmRte;+8Og7`>~x~N~19(5Pr)O-a@rYU9L zoW&)*wMJs(FH^mAI~|Ap?ikQ;9Wg1TvLze{MmDZTTaX1Y4O}9}W9(pmp7QnUZY3do zr$E;>kxu*M&g>f{ps@b6W*f!iYm|5OCqOOq_rEa#{XZO$$(ysUzXgEr{$zSlO(GhhvOikB%KGiT4RP_jB)z)2Mz3qX#3s}l8zwKMFd^OxcTGJ(&IFA@K#1gWmPyR zT6Z&C+Am1vyzv~wjdi!zG|_Gi&grQ{+HQkt5D4Z|ShWvmi0IOQtlaUjWQ&<^@^u3H z4u22^jyi6!Ik{P>Q}l}Nh{eE_6F{T4{BkQx%cSvr*lEy73PJC&`54Ejx};``ZeF`k zC};{nK8wm)o1FDT<;0gjk3mk6Xr5OU6D{0$J~8arcNeEVp^AF*SZoY2|M zO63eH>RqRGmMxMI$2t<*_IREuqs+te@C1f|H$HN|*uMb?q3ZlxPrIz0tGO4T>5B@`SB6f!R{$Ex%h^ zL~kg&GE%f;V-e1f4U+Iq=?D_3Tv{*>;ig za+S*Yh{X_mEB$1+1;6xc$+21cVY*oZnhv#aGX5*2J`P$<9V3qO&n&8mJU3iv@E%FG z8s-1VaKrZM#UBN|8cm7u;(O^ciW3ko7TH;j)^UHZU3$ly#@c14_+h$LRr`~Dn9E9* ztfJS4=lQ z+9--<*GgbYs>`)vjmmE7pRFFJj(u3vRu&Th2^qgSgyLtt`oQ7zu~wW>kj z4NIea7!@D$#J$=|A$1}@tB7Yr4@L8WUO9G`fW51K)#Xm`@VmPVB_tXzx9+Tz%iz{Z z+ViOcm`tt7U20pmz+nZ%G$LdlqifCWoAvlTdM9@8Yw==H2 z$3YtP-=X3Hplhtxq+ZvAU9Qt)VfUJqNEgu<%EnG}+_8Y0P(3 zrS{$&Q>}-m4#;Fm@E!PUyXJcW!gbN0xtz>O7oMN`!2l{J5=huLPm7|7be}7D(~jw% zi&j6PCX);C(^dNW8od-+lSqfTxZ?0Y-QTyy>%~c2C~*4mgS)hrx);A6bE|COMffjW zQh*3A@Nj6#jAJ_zwCvKCdwM|9AOPIzozr95*(Y}iAE*l~;k>x#(Ia8@x{s6h@VpR^ z1)oTU*>hGV_bvG!q7R7b)j|{o91zBPbL>wa?po3xDd%}gh2oRu9T2eIdNDnG6Zpx8 zZ2O_;yU(JIaT~Snl|B@(x3v%dv*k)RA|cT=J3R5nhez%f2I-{x&62}ljzzBwcKX`Z z+OE?VQ(xRE!}7pHK-?uq6nu=IF{)tTMb?z#p~9_gZtMatsO6wvOhL?CaF*q2r%Day z2V8NKcOu#mThFz37mZ@sg?c+vpDO{k__KVcE7BkKvF`W1f}qKt4~K`>vaH2boF8;G z6zw17JqgO)t+gdinOI1jh`afWd60+IR@IndA6D%556Q=b|8jBdwST~(a$lg!+?}tU zzc6<&)RhbU1vqc17oqs%^oZ5#jeJ}XBExBp+_?T`F8H>H z_2OJ!YjMK)8J0#vQGzObz8)@sA^Lk;U(BdSs96$zTo|fGOtJ2*5R;BtWTW? z^$Y%-SxE)B;k-6Z4>D3wEw;4b|(FrDhLP)_ax2W;OUtA@iyO*l< zmz}o?yAOjF8#RL5ut;FT97n9sUioz%=n8nEzAmXwWQ$wyg0?nP^tz*+!0IdstPFy`b4=<4ce<&w+ZJ>ZFko!)_aK-*c= z4ezHDrV$Vk_^Ij+`uVEKp-cZ*OZHrFR|JpL$gBkxkDJqwQYjewo94pBwU-Cbl3u5k zI}SeAYU>p=vAY$)a7QTszYfEYKk-X_>Cx`faxuo=KELA9G^r$~NZ(hZ~-Qa+tuyRoLh7TNzd-|rUoC@3pd)gOEaWnUPNp=u}=6zNa=C`C!R zl|B;MVfkD=kVc%2vG75Z&s5Uuc;tq6r`mQGtY48fMI%t-XPujUJV3+5flMi&KQx?tOx{*;_1l&U*^~HI}r;%#hye(|0A! z%0CzV?ECD=q&@;WTw7eIOH~KBZaX}MtuZEefHhc+@+vcar#~F_TPOU;3)11iOo+H| zS$~c1Q}xUUlab7YB~|vl9kSKEJpnR3_K?mXVW0A%roPXP6ooQKL8XuH+*j`X=&e4t z+m|l@C+zwf$5WZ{17LT#D!#TlK7I06Zph)$dCs}@nP~pHd25R)Ee0CbrIGv70$_pd z&=Dtk z%WmniyUoLMAP15sYW|Evz%-K{0F<o-XXl8e5qX$iJ3$6$wxR_YJ33S;fz3KVUDVW!x4KGs>S9-|{g3Y-7KSMg(5- z-B{Q7dRTceZU4yQzFx3?OtB*}RBj~mPq+Nn3n#(*Ffx356sD~mxA~8KS=KFoT=duZ z>;9iVzyH3)p-hyKw(dw+s@1*?CzaS6(WL(4sgwU_GK9li*Me$5S5*)*6!aqzR@XX@ zNDTghBvv>pL<-LQBw5qf7*o0Oh~Hw0s%h@Mbum_aYh^OrJ3fJntC^`#Pe;HJA%|6jr5=HVSa=F8DrU`UJC z+5@!bZpAl1(=N8#hw1Z&KRa?;2s`oTjQ(xB7uj7}H$mIrcS#I?ISh3ClsE4*V6?}M z$S#Qa$^G|=fcG;FwEK_kXd;EmGrct(+3xIf-j8_Qo^4+y`nL!E|9ar1&%DU2^%eyl zXqM%3d)<#7J9aGI23T{}{=cx?zL^>z_t_6v>%g5Hproe#7be^HCNM!ioovXz;$8{f zxpSxClF1EVKlS<_KAh{;rc72XMPNV`xbKhxz@2vK->B&eM@D&pTe)~CACJ4`K0hlz zqn-vS`hLvag6N-dlgqMrXOb>%>%BSAK_2MZ^Xsconsw8k;wjL;#%*-|B1CUb?%qKs zOKxCM>dh)O-Yz#;2_obgcEX;~X|iEpi9lHuUY7EYm%b;j3XpDJAB_VxSwO37+@5no zcYz>C-s_TPss1qw03=xc5orqxPP5UQo zjmy4^jEhfZ<|Ss3JKFQB;NaGPUv4}ps-Pzuz;-Bjtvg}|UZ)vJ+Hz}C=YkPG_10d?L1C`g-ecr^WTfW^`L&s1unP@y`OlKTcUB3J>wtqHD z8=IaOkIC{%_CS`I*dP##vL4d+H_)ri-$HA~8 zWy+->@0sZ1qh*q2M>~|fR246$h(sqa$5(wmrl}u)+TFPfsB%dC7{06=KGg^__czYo z{@|i7a9K6z&A_kp6b-?&tEa+_Y)$)%b61+Z$E*Kfef7$s3H3R-r`@p+HCa~FSYwvIZ}CkecV8^&dJv*xhm0m+xfjD&4DJ49*eg$Kk8^Bdq#L`_?M$e8o=?G@}(`O zq_#&cI*)v!Mvk2|Hy9rsG=g(}a+8%imFW1$aF6-$Vt>?VJ-_6E5nnfyB43dmr}V1z z;7@1b5YH&Nml%j0DwSSml;8n*L->5g?3-g$==~WP#dIgOv+QU@fnS&d7nftxv4RT1 zp1(cb)iW}aBuZ8DmdD9*9g7a0o1?am#xLg{_I#_w5XJc`$^O96?|rAgew0+@1e2 zYUk@=12VOXT_5Hexgq;35(wg*aU0&APun479R|kyX1uZj|1A}|D=iHDWRjFO8m&$! zt3M;WL3-`{b8yKm;%>45tyjB7Y4%Q68cPp!AZ&eJo>e#NWB+iaSs*$hsP5S78NFRh(Q z=!kf*fSqEh)D~Rzo+5o3{R2=3HVx*mIo-Lmzjo#)amK7)vYw)|zgk)uhyg$nv!j=K zV>iMDoz;Z3nFp7F;?vsy7*WVtigISyVU~a$GuK(6>LpoqCbt;tN6zrEkL{khc=z1rlPf|0{g|I&NibV@j zsRm*TyEJM`)IlPK4*Lbl4qdXLYHTIjNt(DL3U?At*RpJi>P0YBv&Ln^fYSI2#PKw5 z7gQ~8+VqrEd4vbQ8OW*Kcy+{o>w6Q1Z}lpoW~l@V!+LEXXcerWZo{1Z;SAt&j!ISm zvVTcouQWQtR$tfmfAEY|l@-m74CP>Xi-bB(;VtW}v)R-N?{}mKBFgUJ4R$EI+3eFDv2jxOSKl zq-yfNraS1fRD@BMe=~^xzLq&Sbtu=%Zde4g!Mr*fJn#1wp7rYao--yI9Izszc&nZN%*SRQ*9F==lXFrRq?_Bh?+a)%x^~3ykm%F{hd=;v0xq2F7QtMfUxg zSGI-P0mlhXGxtI0%=(kAFh4EY_jehcp&;LDE+_O;9Z%X+Sv@|-81O;331gqLe6mzeM4sw~^k&s25us=JqXI#OtH zEJs%j*LgtE6A!lvnQPHth+ah`3suWH)Upz?GrkUh?mKN<{m2h0$Viz`K8H4n!V_T! zYZu=&GBRR3&mG$Hh>zOUIk7%J2zUc;*KKbQgcp9yD`ZxFE!V78Sxal$8K3w7C=VL_ z8E2YK&H6bGIlvu-?v3xY)bD%u+3_&^gOX&pGY&oz=G@e%C_r~I!~Kk$3+{{1%|;%0 z@V}h+8tLq(HA``S={E50lm2$Qu~^;Yy(QXb2oFDAfIPpVkIn^U$8Ut~z9cv7T;H+* zmY)KbJxuz#)VowMlHpLi4^#ZkPucj~C9kPK2SFz(w683fo`y|U<<_MtJQws3JlJle z49M6LI217vXl7VMkwx77!!3%$6Jn3`+#Ji@GpfcfzK?&TN?}OR$?9>bqv^+wb9lQr zpo}Xv@og{HW#8+L{L-l_o=t|qbHPida^g!ozi@JDxd(+RPa0mq9j6?Mo8mgTuoUO$ zy-Qj0Ym({DnSHejdFYIl8Zq~vi@eQt%e~7&AN6C7n90a{pT`1KiO(>)p$BHIK(hRj z!+!>~H4^Uu87_xS;f9FwfrHYVhfFTEejvOLW5bD3a72J_*gin#7&4Mj`kz}jMrQTw zO#Hzllg}b_<=d*<7=(+A07aByKShXOqEJ9umo5FHVt zV@6UgL|Elti#+Rn-gM7s#0q(LB4;>v@~L9YD&E!X_Q@W{+f9=#B62D<7uKnA;6*FB zSq9F8K3>z`sgsSzLjA!%JZjnI|FxFy5wu}S>3+}Uj}!J^_wa0x^mM14oK{^vJE$b^ zB!b6#d2_)Jo3BZEJ|*=YEv(yJpO3D0*Af@+p1o#w3}j2bGNE3^$}vbmF9=z|dYx`w zj-G4DVl57TZx>FhUF*Ng!1Ocg`2U#GDA-OTx8$_71bO~;=G}y!WbK5Fcfynb`i@{eH4zOvA zLZ9dKs>Ciw{-OwRQAsFyIG7rkhw!zwIn;>4t$w{A|`D%-9}d*u;z^1sT%Hq*LGVKMfcxwJM+{=5F1fE zZqVs@YjAJor%+_GGDR5PDgT$1*6GY4nei^6#y^XFO>(v934!r$omlOY;cK zN?M5%ZuY=w+tu=R*d}ynqtslx%r<>WC}uQkbrRIX;0?k(s%9m@aYC{qQwcNbI9zC1 zOvm-SLr(F23nJkI-Z;ti zlqX^vVqzx%F^5#Dv4JngRsLsh55$2BAbD_XypGwSIJ<}YB0%tombJt z_puzufY90hV6Q7{F9P}}v{{uT?|%H+sKXb7&ns7QKL3F3DcOU{6q zLlY+nd+e@~i2jNwX5~U?=PrOat?g7}Jyhnn7~w8HR$Ag}#z=APB4~D6nHrH4vJ8pQ zMVo|tQt6U0x!0{fLT1mMirZm{8Z3?$vpm+y=J!aQ|M^jk9qbMZ0F*oNs9IytPB{WT*RO zApCIBGo}yN1c%DjcYZttvNzF(Z^h^7)LIOpK9o|5v0X*|q86JZ8G$sg+R^8@PUhKS z9;6rQgF6m56Me<@96S$0yKOpDmVOXYKc&+CbqdC&qSfK{ulyGt+gs!gPjc0SvTdtb z_gM@j`-?P}GvDS&;-Gubj*NknLTHZb#wS`_^-LPS(!}_XC{n_dT_*k0>v{FY*d$Up z?FofE8aXuz}=^AMt5IDcRP()n0CmvfX@d-Myro*MrK?VhlGh(w#JCF~Ij;!I89q3- zMDzs&%?mHz!F0o#>9L@(EYVVfl zr^!BoY1qw5WbQHPZqK&m?>CW6%wHTks+t|W>r=_g%;tvZQU@$s^R72{F7v?_RQ)$dG zZ7$n#J%SjTgx)1BOY*yz?$w^DX{%fhq4C9tW^DgT`EkG|%K-ZtgN{d?suikUO(b+; z@>3O#M;({q<#qyu$Bym?t(o>N)|>!?ONh4KTKK+-eo+-jXCESK>3%1VlWAew5>ozB z_5J@89S^1<`OV6CWBy0X0I*rQ`854rWBMnOHq85)B;z@l|Cvi{lx!4QEHNldLA2MW=p=0 zf8(@{n}8>5VOcOET4b~)oe(~Pa5MGf z7|EikSRd;YmR(*9Ia(O4AF~XpK|Dg2!6*u%-tz;g;W{Sy{M&U*OSb`+=_u!~9af_; zhROoNmFuw&yf=ZFl6AlAnWAmgTxE9wp4Z~WOt@`{j^Mg1tY$6HT^@R0U@pdG#Z5241UN7h?9rxFua9)Tp50(gZ~1IlR06(dZS5I}J8LyA-*;@XATJb}+lE6e zM%%($HQ$97Xp1S74!iq#=w|ZN; zXYwzT6s<;E*lhX@Nx4KU%qC82koAi@ehGdk}j1liz_z zKzLWKMJ}?aRrWHy$w+vYu`(h#NJ5kl@XIm6vHCF{F^4d~W*^q`qI!pvUf)@lD&=uo zi=R+|3)pZI!GMYk%NgqOoe9~^4DiMMY9O#zy<<*RMho@=`#r1c+gg{k=$MtTL7gx>v*fh z5jWh`qTrApd+d;l*@NUddI#xdi^|6E3<)*1Ctjp~tW8s{Vi8~uY&%3z4g{c(xoD&th zwEt770>^H$##jZ4{Tfp4Bm+7;9FsJC(*~U)`-Z!s+DC${W9Ze~d}Vg%1L25R^{SuD z#-kLukfjJR(ZbFlL(G~X?qGww7(-2S2%_OI2oXlgbl-90$yP_3)))D z%DId?H^vg3snVtafhP|%=@L$CCza)*3O1H-uIGHTo5o|ZfQ?a21MPLSVX^SAeffCq zg(}-r!;WhL{{JlljU3m9X(1VIkX)mDb7urU!o3>}d2b?*kOLX>Kg$a}c+<4h2E#a? z-*&g8?LnG{y;$mSqVbcn9CQ79hE>PgS$*@Q=&4?X8kl0@Bj0BHgZP+Iy+KB40;dQb z;&`7?Uit@e(7o5y`6y)d8)0s?rnsh{RB~{@r)Mi3)$zL0N)5VzKQ998c8)(GT-ePD`^^x*eVyTPGDoHztMOgDKANm11-IiKdkO49McU{dnk7E*#hqe@ zQG5YMsnF^e_?A+!)m!Z%N_ z?C$&h;s-x6&&-`$&OP_c@HI(>?OwLOdwTA}byHr?J>Xv3BjoZd-kPvqovh&^lp3P%9%l4ukHEqfM57%t>Op-FwrxxXg-ypklPcQY<8Y7U0 zN@Luv)U_kKPdgkcPH68xJ@<%$kMYVmXjxq!`LsYH!0?KyUERASWA{=yo0W9A+SDTs z=60=h`DnZa2b{*r(l`AimesK1hC}XUmr7;I+=kzk5C*;p(io3Pd+omd)d)!x(K*{! zd*|eUc=zcA$HpMMymrr7h0Y57OI5s3>Tb(c+<9znsJhCpUWFwkyf`!mi@w%Z+q5e+ zK>AD8O~2IJ-5t+?$ClopcXHPi_T!xd`As#I-R`Yy{a)pSzOh-=bExZPbtZ_Hd_Ebp z3qW)M2yDzfIB!2rc(APYwMoMQUnG?;$Ckpo8JehArg92nYacDOesgawwBC6;ME7>+zGxKI@g-L zUdHzuqU1!7VFhk=Oy@i5rZDZKixpR(#D(fqAQ-JiyyWC zfOk#%&-xYg;qKoKM7}dO{-}Dx-8ri7S8`E@(nElHD3&E*o2r528T)` zT-IHB*B)gZdaj+ffYUxp5NIL@bP>Ej;XM|3k|x@rp61ljt~;Oe+1^ znLlb5$49jmMr~ZdDWq$Dv@F5sLMfrDg1T0UJc?+0vNYblBi;GrzIathqTQA2dx4Tb z`^S?rs`&x8Ny>mz4cc7U%;G5WlA)9!N*$}vd<&7wjCMcEcSZs_Zb4%5L9SR0B z`VY~=YmU(N)Qtx}9)9m5XVPk=e2g+SyK**Q!z@034gJlLD~@ry2RMla1;+_&!z8_S zm~E@Wf`P!vvk_M7zM5R?+=G<3Fy9_kXl7xO>PyhWEFaB^$VW#XJBzq>>^x<5DCy2h zhLZ--(YwzpgPn^Vjdb}u-GC~1-`>13(-0*)uy}h^NY^OSa3Z3NO!0p^{SBag( zHpdPJ^(7m-X;#nJ8H!U@wOpgFO!rocB?Wur6w$n-7)tVDA|+oLMB$d&7sK7!kdvM_ z!aK1KVY$EY)B8htj1gU`RNXeZ+ELMRRNFImW4<$DP+~_5yMlYJ+7AjR(;QBY+K1=w zJNVz(P4T2HCa0r5@_DzGE5}$Q3ZEIoYq%*FXt$M8;IW2RLQ@uPy>Ztm>FB|iD za2Q!o9A`A@^@^U?eR(O}ZNl@NPg>%l#K4T{3Vyn6`>RB&_)McSlUgk+%5vi`yY0)| zmW$raTsV{#GjMCkII*l?<&J_q%5IoAG#Iy{!S5)=jw?isd+s>BM!X=*(Ui7LX7UZQ zc~OHorE)cr2^(jhqS@AY&se9;Xq;>0rC4A>98KG|kB(>AqU|IM4^YD$RvT#NE;cM&rpabJHQnL3)t(k^(fQ+K3r2Pqem?EghwUsG^)gB{>$=B8s#+I1HDAOhWyG}G zZLwHxie#)T_Po-^kUJ8G9!sjq!jFP`xHP1n^hH(SehZ3mirZox$_z3rfK*)W-_B)x zf=*N@2ro$t65n^#X6^pB5bFA9!LVyM;O*-Gl`lA2z03>iCG25Jy24w-KmYN8icN}r zl3t@9@77fYGTyuCW(#EX?5J z=>GjS;*SrH*6p^lCFjq&Sa|Ny6~G&pl?tAy6r*~*mMA^YRQ}Gfb?0?frTzSy1?Ll` zSM^z^x}C@ON?KDcjvw8i@Tx$4Ii@i^{yVC-sLb8>TiQ5Cvuw)Covy^;%<_|;e|^m5 z5Zu3=$LxwCYeq_MLU~Ppy_8yFFLQmC0s5qe`wuP=?jD_(*Y&ZMqs#|)F=woMo%a4K zj~@soiA=si`?894CP~r;6dH!prDspd9`I@M>i%esc6tUtpADB%GFrBT1l)U9`$S=}z{#xK<8@bUmxn$Df275$JFs5Aw`{@P>{>N` zTL-fGep$PkqMM!WAT?OyfB1=?eBj zq+B23i2cC9F^~Bn;cFyVm$$XIAz*pjf6^?1BwXT+G(sMG(EMR3VJ1JgZ1+Hn2(R$O zMiH-}-locNG&RuJ+`#1TKO0@k43G2d5%PR@P&AxRtmNvSK}Y5yEu?0~Y`iN(x(;@F zn7HPk{*3J`(sI;{LyfWSn6Qagtyrgq+UmY6j(V#oOcH3-3jM?b%hg%wLWt#st52uJ z6imdnr}xs^P4r?^GNiP+vaw~FL~c!5GWgX+A)tQAa)a)^c)KOW;z^pXvLFv%5NRhd zclnZj6??tt>W#^8GflvMM-Mn5t9KRR89QFEy zo8{%s?qth19tr~H;P^fr7j7&#_({IsglRJcy9R&8TE^I4z; zII}Fq6QjT(yJ$jij;oBTbH-pnnQNDYfqHjG`;_CmG-xJ4Q?1e z)~`_>9~$I=aRl>yVoQ*C;Vxm`i*(~01ZKLSo+@W)x*a>BBtWv~xI1Mg#m(JfeQmQR z4<|X=^Xu~@sKSe>wrW09&a>%dN3B7;CE(2n;oI>#II-kTFWEqJU|~N zjS4WIz7q%|bav^E@RDGFeKs(>)L?n)SEFO?rNjQn#VDYb^c8C7+Ag*6djvK1EV)|8 zt6Jeodz~O3ra1fJdHdc&y4t<(WadP-Vc+oYijh(vNOCCQOXQegg!c10{Rtji22d!@ z_wH0U^|Q-%yrcS`q9oYIRXhF@(?SFqbNmobK&L}uh`z}(9-Ds8CTkYo|CHyOi`YdJ z7>gfx9H2)?I2&=$e=Se=LQmCOCtIr*1lJ{{xUvAJKQRv;Q?Y=uW}rUu?7Pp#n*N6hAj zw>EgU2>M+J@Sc7`QsfzEkjc~%@6+;VG-eeG25F)Ndw+A0#+}CtrKo*g66AhMqAX#2 zVu32sk?9&`|D(?-4UA?M2q-mIK(vGAx!NufYDk^ORXU|y?GS-&Nw-^qMIpYmzyI{B z-&7Tx)!3&#h}4`ih>N_y(3ey!msN9>U7j5%t**j1_LEzY-oM#M?UT<7C?tpq)&&Sr zUWf33fP5t|u8Q=}pm_L8X}TAUA3aTiHEnaf6{he{^BM83w=xBmZ)ZJ+omiqO6Vbir zh_k)ZVwBtFcQ1B2Km^W#2kg(GV#~JAJ<>b-Qx1RdoO-OxPewL&DI4}>`+YFM|AUk? z)3Vg=uhd{6+UL?hU_8i@-ypM4^@fq7yFFlqP1{SAK^bo^UoP85mGHEAQglv=2W-2xxAB*EVLLDZPH_B(;f zO{@;HHC29l6w0<@sgHZ97sF@{ z@1h*Ece-n>+)M1!u>Jx+>G6-nyHr<(GK5t#H%w}In1BxbLbbU#;H+JS2$W>5?RdRh zG(8^C9yJ``5vQy`m?W$=@rmsE0BV>5`UqxuY%f(wRZiHl*wMP^dtV!MF?yUt1Lwjo z=C~OSS_@;r)W|=pFXx~c=fkVJtz=|C>9ErVVeR4+w#zYy)`4_< zwZXKIwn5V)Hdz7GTKhq7pK~<{9>NECztBuO)~VOe{2GZpcwrO<@Tm+)MKUtH`}>sV zvGd-WXRen1acqq(+!9yTD(JDl~pdc&t4{OGN%2AQMR3YZ*1d!AbT)7qim6EWxV{lQPy_l)|LY5}8nXW$Ltp0cz_*DCW zG^SK->u>HNRavRMz)!~Fy4Cp*T;^7`u4Laip0syOf}KO($_Y&ZH9#Y<26%l<^m@ftvTCdoo&#ixgyRiX zrAd;+whs^P{WkR>Rm(6dz9}0X(zQ-=yLwzdjXrJGKLbRl0gyHp6<<%INq`&sR z`AwOuo{K3A3N!cqmV_ekRA;B+<`5-Ljn~2%$Ut;$!f6t0S zNMY}^x1UM7e?huWqt~;ykR10s;n6dgl^ekS&C%eN*mm_FY$Q!OwW68do3j+ z(|d>Ls7P+*3HNB81zrb?Tc}NR=B!&{e68?{YxloV&Gq2Q?5?=h22<57+ipFs+lyK2 zce5u<7?}EBn6*t>Lh$)3YP57%@0M!Cr5sZgSLT-M`JVH!j~V((_!rYBXFLMK;Kh`y zGXyt2>Krfi?{njyyLVz2bIhsrF7y7X3Y}toxvWc`3}KX-M2fai*p#7AA0s-X*vOj3czEj@uxBg7eT&^r zcNSTbdKh04lgB z_V!05p9NS zHw|#!H>YPs#83Ar`smxukYF?Oh{;T_O3Jq&q`M?~uUYntF@Txhg6+knRL*Dl6qY^R zqp)IclQvKfwO1WQpmGS%Mx&j2ae6==M~v>0m&4IVITjO2wTHP9BCkM5nRXk>2g8=z==*s)sc#DezPWt9LmJtF9;;3sqxnYuP7&Q=JYsilO(FRjZ?~9PQUxLTfg-&+h;hyrFivf^ z%MiRXB)XF+>3@IP6<>R={-JhU3r`^K@vy~al;`!6b{&!poY9npC7esg4*w2E_#g1* zRvr1yg%hmz5jtekD5>ZpSNUIhL$w%~rzix(at=s}z27`0!Mw-Ll|bBX(!&T-(#QEs zA)+q`S`B$(@f+U!MU6O~hGRGD8b?#euk(qXbLP>P%T_D9zh;>)I*=V0+yj+_nu3dV6qf`AhS5gW_}9`k}m z5!diJENYGlKBIp2p_CS{b?VRcJM{wAUYkc`0eR0R%zn(hj)4Vg zc;`is)M+CfHm|r23Od%6Nd3{%ZNm^%URb{SyAxjK*R@Gja%fGw7!Ya? z5RYJkpSj<_K*>c)Pxhw-c9pq6FKyUF45u|uFXXxCziMgwk!{rQ#O3dy=^7Xka`Hp6 z;?zVi6*g&Z)ZN3VDIe}}TbvSXRSj$vliGkXxmVPTy+u=^;nqL&27PyM=bhEe2=1mV zMgZ_i4Hlh3p*@Ff%1X_irKvgyt7(wKI0xJ9!5G5zbn)`mko1sr5cH}t^RGp|+#(XO{or;a;KeG-pEzrTo4nAOX zBT7<^Sk8C!+aqp#q`1fP0KEcB5My5?jWKEx9!mLTgTJ609e=Swv1dPKT4X+5jy489 zCXcQ$)OBdypMsaVSLWXO;9MP%T5*v&3lk2+%c`%Ukr0xsnX$(0D>qbpV02RacOl|x5OVef2-pcy@M82uJ0lrvdEU^iZmNilluK3S+qk{3 z@b&@0Rt=<<3C1=VQ=LoRBXi8lmJ?Wb@x$s61a%q=KWv;VzwQR6Ig)x7%8GoJLK&Sc z_0(mGQ9%FVB1r^kWXFGbd+b)NW|1p>F7!8dX`kJk)cv^QYwLjw`bQG%HvUgh_N~wQ zNbRd5U_xHU!uv2t@m_1+Z@PsbdS7Oh2IL8_XLDgabNsXj)AoFdP%0Uu0jC@u{ywT& zMh$sfxcJYfvfG3%Z~4oxm0*p|8DpF?T;L%Go{&LcJH}cv;V(qsUW+Ck(C6&|pC{5W z0GqUw(X%W<5Kbetcbw?YnZ0DZG%><=>D8D1)#(21Zn4iz9ah?;tbnREp(3t7%llQ$ zx*1jf#y)};=4+Y&DSBAe2{C#Kd3vEfOJS3enB%<;iF|GnvjMkR!H)HgvgLd)RU`lg zrP=tClEGJhqIL;TB>E#}7mxqlYUWd_{-O8}(q%VW$Mkg99{U3vRHjLGwV>Utg&Iv& zk9JJNUd?#tDB8zVGHe6B%H}xhJL?F-YqI3-BFTp; zhm;n-(~tjlNo{(X=+1P?-vuE8kNlW5%BJMmfVQAx?VwGuo4B%*vq{y(rv|`IceT(CJl_ z_x+YZm<-Y7s^<)$jE1A^;9apbckkrm^Mf$oe~ka_uy_KD#c+dlW4!haT6aN!P-@=d zxP(#3gH5to((1xM4P|x0O6?DL^vjnYr04i5)_h0;p@8(4#j!ngmp9->k^*@G0c-&OSJMpJhK9Gp$M_Cr6a0}sZ=KumUBz7?OH<9e=wPxsTL;WdjB-uZ zAIT>HFSg=ET0FeN8qp3Sqx!JPN5D|OdjPT=pPwJF>RS9|I=iPxbyQj~Gf1`3*ZVIv z3OQ|YdE08X1cp>!z21ylzRnD7uq3ZrCrH*+MZ&?eDRnYF^!E+j;DLtA|JZAYAk2j* z2A=Rak_MX=hZg?ILflr-) z1!}YzrW;?5!I>*k1P!ixZNwP_t*_H3Ba=R{4EPOu zh(H6mJ4zTe*(X@HJZl7S-vjhQ;;Jn_)kP^N%$DyBCdqt`>%&jRx!@o`cq=?b2nu#N z8`mDQMHE}j4Alpe&t72`OzwY^@U%lH1DO+7k>&&*16Epo*RbCc4qWM3- z5eee{1->b5MI!9L_@{^ZuUi1{MA0ol$dZk5;+pOgcgg!wyze{~^B)1%62!fC8b2M? zYj)mY2~{UqS4lF=Lh~J%Cd43w1r)D>uQy|T2Uv9bfj_P@mMeOLNI|}LvyUJ*;v{|k zTpkge(KQu^JGUQ}>2XiU`@RvLGjyFbs$N=ED-lX;6x8%bLQ~A8c<4GFajc*#+I%c; zu;gibn|)58Wt$kNQ_Ov>+L9LB!d}pXkw8L?v((}%zHSI;n$_9;k(A5G4QdC_og^;5fPCa zQ{O%YY=zr}{=ViscXwl^zvv^kX?$YTJd3i}Y~*CpTF$wXYH3!gw%kkV3gFDN6w?>| z3~2>33lnQp@87u3sQF5Q;c$f+`nx}TT_`IR3g|DQUANZTgfm+@WhX#}H30KAwe*=R z!hW;$Y<;V_b6ikl0l6PQG~<;sWOnQCjf4>5&rBMH9FByW?5BngCF}Vl^ZhX8M~&u3 z%VRXSlXMTD3<(kUlIrp7;w>`k^Rrm@d^d5JG|pY?s|XI}nB#`QP;j zWNwV9FOtClPbH9MlqEk1uKyxaCLZ${g7Sc`X6#6UayWhwzV)BJ?ZL}zm?XOSaxG`h zHiI)fDF^n&*7R)|cIla(z=G$v>%hZxjUMNB!hZoVKa~mw`krYwIP{h%gIBzWP5eXk zf|f5e4=oQ2C@oHB4b^X6v7+a{W`xDR{DYJ3zk+Vw17%*x^@mhvHq4~{96N^4cK~XD zoMun@wSrWY6?YEVDS2%j2-_cQ%t$bkIUe!9h;x2yst=x?_Sq&h4q)QKMh%&5GDNf^ zE5*cAf;LB)CIg550{{yQ`vrjgkZ-6o7tXjNFc1U~lA-#vi)?DK8<2Lg)c}BytJL>^Q>kF~2^91XZk$2PC_66BmTP;vPB&f-(Pe!P-L|B;ca1?c zs;>~STr0P9(B%s2`?SuTIYD8E4G3iy-2;fDzBa6p@KVU&ZMIlgZV{SlAFU!<6yo(; z7{4K+oX4v+-j!>u>-p_5?2b$QE9DzEZ?0YXn{m!zDm2N$rbF-h=whA&#GWS zbw>K$$!*4Z0Hpm4icXqa$2^V04qqoeumw&{fn5@lDR;E=oUBJ04K@FTnJ%f5PHj`w z%7!n038{Z?=JMS*DKWem+2IL6D){aG$XK_Mskg!IZvQ=DDD>s?mXfbvTek;3s*h0( zDs~xePb9%8cvLl9>+aWM!y^?xGVAN+A?TvlqfoBm)-*j>C&1=>7x)XM2+VL_>C(N1Z!j{HDG8SeT@c^=-wV14 zCu>@m-ZU>Ld-NV&Nw5x-X@TG|!?LA{v<`QsXo5F(0KG&iMfI3QJF{+4o(+@3%(U`U zER%4((SM%>Yp(9r^v?;_j3v0~U_Y~sMNISd1h z4D#qL!gC`fR(|;t{`Qxlae1^Ff%-u3y}1i3K<^?<$#=ztuHnZhspkbLV4Tx(S9FZV zUO|~(1LCXtA8V4u1CY|_iJTL@G}GbI8_%7}7!OLxk#eS++K_eJWa?TdKYE_-M%nGw zU+x3Yl&1fhBS<{J%aO)xT*8~-q|Xa9$hB^G+}Ak z{f6-v->{3|G*i)FhylmzX8gO63FJp^kC0#;7b!criJ(BjfCa8TD$%Jwj@lT?Lq@As7QY7Sog?e~>cK#z%1JSJ z@od9IDu14bD`%(l4-_3h1Al5wf7%nk8B^sK1Hhi)6Uh$7-v?{AEr|S6P4)I zI>`Iz=^B`TPrucC$&E+!y_l9TFaZA&G^FFYVOS^r#D|up)=0I1#oh?7+0HcN_p7Y$ zE1bo31q*w`>Nh~eXUk9^lBqq+g?wET^0t8}>a?8I>NQ=nYZasVA@}l_3oMTb;mq## z$I+59MAb8?B4Fd@X0$E|{+_mI100P=v_XIJmXprd*2^RF8(?3g5aAz70h z^h_v>X7yUeAg1dKn;P^0Vx9n{oRYSH24<-0D9XwtBMj6J4z)>-e6o=KSLi?Mb(x zokJjsz@wS}u)PDY3Xzw0`aD|W8KL&>S0Tgm5bH6DSsabS75#u*^jmB4xp`5DxsIl; z-tBK)V!c3>OH~hx3x?dYaD#LoZg%l|u?OC9?XMCE5~-;;MrJ_?S^yXy-?qp>#g7M` zE1651?`!V6{cK<-e5!jlAoKmY&(O><2qUvIe%vrk4(pu^{IevAaSj2+6F>pT!4X`P zz=H2_I?R_yC?8*xb^KPi`m6)XW4K>GW`#4}N($>QC;=q_kUWgXwwqVS=8T`Usj1=C z@?4CyWC|Dg#Y5p}?e78=np<2a2#8CYm24VhXW9Kg-b>k<3@i1Rq^Ga(t6GI}+$w+! z4FE#l0#~~*BT(kkH$W9|u?g_SV9r=#@AaiK5JP(Q1YcIAAGI<5<>e7eIgA?S&PR~~ zuaAjsaeMd`F@RXW41(wF!uY88RVc=%_qY_P$aK5!T4qTd(v6XUdsRUT2LJz-Ze>w= z!_wv)WSCm$kC}SsnuPynYjd4?OBAiDLQW7dGj7l&ZzK*gnJU5mdv$&+9Re8@QGJAN zgAosqes;d)7m^&2RKHL4V?55n-nOZ!REpDHbN}G~kAXZHyDSP?m7`TVG;_!K23OJ0 zpSnnVJFCP3c0l4=Eq!h)Y@db7I%UT_?%#L-My$JA^;pqT_ZMx0;7+C% z0Df>G!O%ER@Xf51K0R0D&Tfs{>jV7aWl9j||65ri5@!*!D8*?@Gm5$gt`4m_EiBkV z!jqm(t@khkFc;tG=l5umj2ZfFLcG^#yP`{%y9fG_n#PZLx?>_BVW#&K7o_~n1UY|> z&bD+ual;L`*h{a&8ZUHtf~QU!H=`1^6;0Kt>24Od98fx1`9 z_9XCZ?Hzq0nRut|;KWJoD#=tp7m;|Uif~Sl5?`2!5e{%kl%mx&_W8UsZ%0~Y?v{1ertrJ?-($%sNzU=2mRYf5TqDygJ#d+_y6arwP?EPw+>7~*>A-Blb z3!3W(fbGtF>1%in2LuXs5HCgJ{W0S2%LbL7>7bak6oq?%*LcDA;3j#0p*Irmw!;^y zPO^hU@pRvXTdeQOEBViPHhp^}zyl+}xXFR9xtlX9M}ckCZ!y>8cVoOg^5G}m zOYwVw5bEtJptlT*-GBE@QmpI_l7c}6>)ud-CfT>_-kT#yTA1nHz3=P6+f?e%Aq0XX z?z4USHYk~^UA(SW7Wm+YY8SVQ^c!1az3I;-0?|Wgxx||vH%**m2g145d^T+}ZVT9B z$2DIo-NvoLv<*iTVpn)oFSKMBHN288bm+P=()?D3d?+hcLru9>Qp5F=W6+l}^bG%7 zo>w6j9m3kncl%RgU)XP-*a%u+v==FiI@n}S4>lLViwns6w5aO?Ba||`cJ#S_JY}ut z#`->o*D~QI1fdIGnSKB!);9>VZ>NvSjt*q#SK&F=?bI+6ZA|eqzcAvTh)naJWjA1$ zBjp6}ATG5JJ(+P)dy~(?^k6_A{?=udUvX=76#{+p3=1ToPNwh1Op~A}*Sjl219O6h z*V&c#KJ?tK*zLx6^AR8@YVx;P%DVOhput^GAMDY3EuVeReLsz$U`(~m&X3vJT`v$2)c_s$4;j{6t_5L^@3er zEpr!SfS>{flz`)a`YPB`LV~Tov_%KWlZ?RJTL|GNRXvpukg5hrj!;Ue$FT4jFi|sG zr)<(5^0<;P2n$f`%b@ir^FZN!ZcyH_Tj zC281`6aJOG0C@b87?8Cdg`MVb23mXWSM6Vlaghcq`w?~h45;D#GS^wBtgQo(f2|P( zl5X$~0!y6O64A>x+x)`rI2>bG{$$4 zp}gDm2WN*HB>=RRk`#aN=hvlAl?hyLlGJpUmDKjmM`;rVORmn%Fd}K~>A7oOeNw=p z(VjDVO(C!g!&u@cp?ci2kH7+unLck;G31$wj3tmOB_>N7WgXlA+VI~OY=kq$(>MB6 z{&Mk<;Gekd{gTddAG9Zw&`PbQyrzW?qxt(b?*tk)fA=ZQA7kPAyJX~Fs=s7BuJs;R z0MtPfYaZ(_C&bDCZWxPWv8s`Qde^G!p!O}<+@o()KKRE+LRwhvW|vu~9u(~62X8XF zF8VkngTsFes8`~*XTQhWXO)(t<|lDl37W%G)xFlGQ*<<)_QL&OUv6*7owhMOJD&Ps znvtV0!l$MkI#d}}ABQpCkGK?V$NHXcKNQIv*DVa1%<3Oc^#Z_fzjk4tITCBrrUx)l zl=)~z_+Sj`+7?6FlRbCf=|E710Dk1Sgno8^=?ab&pw4bIyF@1h17CB;`yfH1}ZxD4m%7x z`0h4#nQe|Er4V|J{)8{8VVx6j z0N`0L``|C2^!Kug#zeiaBON_mMM67a%V7vLn3C0|<78iol{9I$6(_3|*O$sjDs0Rq4s~*DEiv zZdE+w4Zto>@%KWW0_Kuf>iDe0t~C+R_aV4~Z&cZZ86a%2;L56ii}w>s*aBAvqYmGINHXQ;`bDVWqpe9DiScSlp!|HB*;sX2yRFjR&p>->%XMQw zCsUMMp4eteMq=$7Z4>g8Ti&*fayxE8#Leny#e?P;-j$oG{M0dHSV_<2A>FvuU`+iavu8 z$)D@(sKW>1SVKd#TCx7fK6G6xjpzJTy2d>aJP>B;=O8u$@ODG2x}9%s{$Q>_*-WI}-a&iIqxD0krfHe4WEyAk@4YL`Uk7_sIe{M(LHp&p8cQJxwGqLozZel6 zi0pHjX{8!Dbs2HdEX0wP^3hl7dnB~}_-DIfEzbgI)$G-psubxA0zqixr+2iN8)>DM zMbU*UF<-CS1p8Tag<8E|4k{JOA7|8?AWPjQ+H?QpRTA25`?cH+qixqJD*7lY3QX@O z&Rj4>2-|5=nks~naj=jy zZuUN6(IKER+Y;Z>eX`Ct=IoN`17RTf?;wQ~2sSQrl+t&!turqDNYOW?jlCF*xZ##R zkUFT`dr0@rj+DWSbk7}!kSkSdUgQp*r-esYIZAh!zkcDlaC{@rYqq}pe6NQkWNAqm z*HH&ug??V}er{W_(ncJCo*Q(gUDbkZ%j)ZHE^p+L z=^u5LfyO>`F9=>PfGa7_1ov?aK*oHd5n*ttKA%xKV__2sX1y?$PNr#KtcJd5Eu2FB z(X25V4*Rx-ee_l{u%twEgX!`oT+O4f9B{|bNlP#~^FiUnm1yZzNwj(WJ z`qnjJN6Of9K68f>-W@HDCS6zDLWk#C;;*Toh;p90P4|Y`OEMWlx|Fa;{Y2);8PRWN zDLU3R1?LXE#a`2Kj4zC;ElhYMw)Mb4Ri{!GtFEYi+h0$H1yAry6$dBcrHm{vQy=e6 zmd&>(o*;U6pMTbGN!Ybq(KBjA#c3bjW47{L3omtLn+E?6*NrN3b@5~eNI+4UuvAq> zjY4^sKv7vfTKReT6eW*5-yXuz{#UbU1m+P6*qFl#JZCSnzE4%lC=ANA(uMnr=jl1k z_Ujr!6aAM9SHP925@w#8Q(fj|MjUdm4KZHH=0O5U`!Uaxv=9F!$eSM;l`(2}X}95w z_0GlY(TtEq>$d)}=X#ATwa@IN-klKMe&JK#*}9ow#7twgjmhg9=uYqB_qw}!tk~Td&ej~rd9LKuw)DS>7rW4eiQYDG7RR}9J78b#!`&v=ddrUab=7tXQ?Q0o@7t8J zmcOJk^J(vqB9H5@sn!9u2LXojbT=h-5=yp5#1zD*l-QRy$e^%@c3$qVMoJV2&c&~v zd~p`QodtRSZ+l6yBpg^y%5qGGA|-%b{r`g!hrF09wzfbMs{;Pp76B?(P-3mc?6eBt zbmJR5*6n;dp{bxnaSZ;F6z`qd`U=8SOOAVw?m?3^%L|k+i+$jQT^zy2i1k__eWT10 z=afzD#(3WY{&Gu}qq-4)xHN?L(KO5$U%!CYl6aa*yft*jStU&U{T3!bBc%YNrQP0s zk-QsB%_}@gz#*Iad)IHM%|Cg_3gNJ1;`U~-{k0Rw^p4OJFY78~U^B5h z?6|*GK9SjaDr2DTd|FaSRD{=H)sk_QD;t{u0hfZ+Nk9{_xfS_Da)k|%( z`)lH2#tc+>poao%pnL*gR=@Izk6{xVQ7c2C4CK5X-QUT)*b6j-((*zB6p)ihuqo|+ z{1i7eUqGta`2mk}J-kiDR>~4Fo@4=(MeI$dW{nRW61;osqH0-_|3&+V9+*j@)U_Q; zHz}OFDwjQ|zeaS)L?X`(W5Rp3#X7k5%H8*F7z?vVIT?PJ zZ*I3NiVMTq%TLqKw@-Hb7_%9(2Jiy6^ISfeGbI4!ia(kkJmdsy*9HN4c2AetGwbknk-k8x)>g4Hs+j;0Z->4S&TgMIH3 zj@{SpJu&|NMsRxWEItE_&bMKrBcqjjXHSTzIBr2Wi%@>vB<-A2-T4;Xc@yOkT{z<` zDgC<0lr2x<4Yvl}shu!Q=e>YsuamLON;~3cVPQT~D@Sqvsm_{Y0WgiN@tEnF6aDj@ zWl*|12QtvtF86N$p;+K$5>bwuSEy;@kRQ&^?A_K-g!QndYfX=Z9~Xr$5Q&@*O^b91 z8DS%M@q(vBd1u$#ski^>*YfNEHNV3~+y!l@>|?i|M3WjVinN#6z2RiorudOzkJO>y zR$&n4BkbmakPas7cjx<-4X;G5UH>X`VaipBbMDpAcYlKqf4ITf%L~EYY6?uFde|=7 z72#kC>2)4xwNfaZ$UQeW-xA*~L$Q$jboOdAs91-1H9jA4d~pYP!fx;Q_XumZ%RGDI z#2TYU350uSbp<}VRi#iIVEu9X>!DU4)ei#XQ>gI-rQhR`G^$R6Zz?xpo97)`p11cf zf~=y0E~9~1F7vXI(K!6y-k0LdbW0*!Yned~DE9@#4@=ED;7XM3+g*Rw55%b^I>S=F zM;h+d@ttwb9E0uVxJxxelNgUVb3^#hC~Cyje8Cun*1ylSyDA-e)HL?xbOjK!h_vp0 z-F85!*OyX0RNZPtJFsih>&~N;+t=c|#vDLC(hAgP=0tO|VX67|#zbSpMilGvFQ-PN zEmpS9)aJSoyjt2LOlGd_7%vP(b}XlVKt}xXt59b%KtOD}Mkwfs{L`_z;NcP+wigm= zCwNu2m69|wQyPGeos=&^?ZE*brrOd*H>Yocieju!JDm|JP#8cgo*8Y}j=alQh$26aYxLlxM*4bP_bnB&(ax^R zu)@2G>~BJ**qQ{$e1qxipSX@JV$?qIy?4gCa%ST3uG>40)Vy*6aps$2s?(_ciTvIo zd1$vb%G-8%mN-^ZA~`4|_M9*MeFrmyBI}5Zcnb>zvhnFXYU}qDTs)+dmNC*;3m55AfzI^-b+giw>h(iN2r#EKAEhiz1Y=DQ?~7Lx5`(7!*-zxk0Af3(cxQrOOlr;SkE0>EM2V19IY| zxCLEP9<@Kt7x{MiG3ufK0{tpQp*2mlD)_VdcS2KU-08ng%-1hEt?-pAzKIwn z#|Na2qnwIBdWE@}_5FPb*L6e;wwyt{B_l^&|J|Yln|~$*^qd2B zDBTua9E{0wfsQApap3~%dz(=ah+%iyQh&uTUL}tJ)p+9GWw)*H=5X-TA;=@a)S=!5 zG~JSHWFsYD8Q+IHxJT$UW|6yXQ&?hX@0|w^cgy)-M+QFPXU*aH*uiThU!m4)Oj#K} zx9ycpE8hO-zC#?-7xWy&AC7p)yVC#ZAHB6Zb#EQI8UiO9Mj;@ zZYQLp?)dkNv|MFvpXtY6yjA*ZgHMWk%{4oJ!BVhi+v>-{R>7v0)GXY?pV=kli+~r*#O$#Nq zg-$^@81&Z8dGG`}_NPiWmj(;9p>=TR6geIi;Guu@6OLqNE=|fvl(FZ{itky2*%qiB z?l+qTHVvnRa$%)W=3NUt*RsDi*bQe0KnarOqurw7;Ax}j#(C}DOtKiALT&$Jyn`fg zHDLSQqrc7=lz|(NT3`$;IdcipBC3k`SCYo_ksJRRMeV4yzJ8`L$w^H*($Pj`H$A84^FvP?!fyvnT$@>=3u(MX!Or>lheo0W6N2 zVPhpg>Hqo*&s%jf5wE_OdWhttdAdp7KA;{ZxO5kAPkx1T7n_OAh{cGD zR3O~i+x2aus2Vh->L}C4x&Zw+y9`ZnW65$ETkGqLS5Axez;9RUE(ErsqoU>xv{q2`;|DkVTGD5NDU(r)ABxwIKUYnmlMVoH_}T40iGhc)RKjcRVX=At{1}`+7Jr%SYWz zeg0#4Y#DV>&kn}=ZjSDDV}Z8S(`WzOJ`=o?IX5#N5C~0HLV=B$m#VBXFqXvwkp%a% z=FolJ3$E4~Kg$yD-GsSZ#|W?Q0s7=!ZYW`{e$8*_K4FgpPr_o%lmcAw4^E>3d>iL$ zyFTKWFns0S(qowS^tt6$&C;-Cd*jmKh;l7f57GU+W`$*cajAI_5r%oFX7J+;3w z=%)TS35rKyP^&`kwP-u>cXV3C$ZujZ^wJQB5Im{G9V^T0C}d$DtU0UqFVJ(ujSRcb zqS}@RrAooMQ#2tRh;W`uh=2AOh}?b;AVN>({{?iMY#G7*ebRjxF1Y^xY%Bnmt&0aE zO-YnKW+BwrNX+2y0lg7WTP`Zhql8x`eN7~=OGA$vwvP`tqWZfs$*{@JG3YZ7@O%j) z!5~7zkEVt^=$HY9KM&8_3QAVDGMF!fFD*9umZ6#wBMdh;^?spqfD!#TWqp4}Tm4sw6{Gx%-d!o(QE zR9_svFd#Ew+d<7j^?&>E#f`NQhsb`yaO3V$I?-2lmf6dFnJ;7~!eg+V5g4ojYBjzT z$T@PQEue?2Hk-3<0T{YPbBRf_NBr@9F3Z=)rq&i}A$z{T^*rb+25n!G4t)AqZM?Y4 z!eA6WtQmB9+oRX^f@u!H7G!^^+_DVLVjFfMZJZp0>QUKyhmuNO;jE#GRNmOiGp54@ zz^%eS*Ye%ZueZoiUjB~%wVIOO?Qw{ULJjY0-bK{@{e<0IX6;tJ1c6iE-Hv$ z+LH(UV)e4F3{C^6l2{C&O2xCi6u;(wav9z(xEM|d=yu4Aas7QSAW5%0wrnsQ6>n)G4fDO5`Bwpwo zk-ij4pZh&^=tb5>a-{ytV|B|PEtfwYX!URJ=-Xto`3%7n^RBoW{1TJ91mGA?l!i&U2lcm(po~EN%;}|=cyvR|0 zlXw-}Qf78)dDC?5%bwS<0FU zDNOc#Y)$r5jAe$Qgb*qr>)5h0b|piW5)!fuCWLG=80(D2_Pa-Q&ikCt`F&r1lt+2Z z+^_3(-Pe6>&*#O!T$xgtQ?Xn$GV$~ujaVMIYXw7BmH*b@KMEwP_#>vaSb#k!S?&ic z7dY#;rTp zlIM@?-88ZPPM|!ESCT$b&(*# z;o9vtt88|LHQUib6h>(vq$8Z)y;WWfz=y>3c!dL*iwpbngbf+2QTFl~2Xu5c4*ghe zmr{N6{q4d~cIZ^A587bPG{-FyK^z!V!fa{of^-461Xw=054{hmACnpbs6!$DP$>_~ z@1-cWf%9N;C6$U{i_FJVO94wXVFNH`k3MBKAbA%%8&kW|)dJkFSO;wzYw(zs%u2I9 zYc{=q?QZbVCymTzkc!U*K_y++jcuAx0z&Q^Vz{bwfW#j3FG1YEq&_$(2Y9-Qksf47I;o?5ND4{N8X+H3=$7_%Q_BC{&3c$7OuFnibe*I9dNfxd=8FuoK80*k0)|W? z;;j}%a z1|)Vt|M$FvU{$cmcr&44ldYeTRbzR+7n~tXX*YszuU5p?+Jv@=<|pk{SXz1-nS&fq zA|3zaX5IhbFEo_4wDXml{gU{m=;R$kn$stb@(6nWJ?)I2zT^`~_K59PD?d2Eyog`8 zFE+;4t$$o3SJx}oE=9T*4pZtV*f9e%)zI{OK%Ir^^=9ecLN>EyYyzt{x^(hWHqv%) zruO}7kjWA-_v}L&-01X#A( zvCQ1<2OExN%D=An%;kxh%{vSzxz~@w+ZFEpdHw$$=$3|>y5}#qxv`R(4|HHT#Qom= zc-~ha&;nKZ-dpSYTeO08p&RZyMfeugWBDpj`8G1aNQg6d2!nkjs z^9#pTvNor26_?QYw*B%PAtL#jBUKVIV{T1tU-5Oe^DnlUy8%>=`GD{0&zRbIuD;RK ztc-_B;a}yGrsw1LO310Q@;4OxUS7$$#9lSVnBOzEv?ay8>kq5=t&kUEMom@kv#AC+ zAOAUh4*&CdWB^mi2P3?%7>mY3d!n60|8-AHOHSLSE{Op3qx8 z4#ZR9tXq3Or7B%Gz%h02S@M%835n#T7twxM7bo|_$Z8z(pT z@gm2=8U=Bd{*~`7tq3^*`G4uigrQ2GoKguS(fn(PR5HFGfteorh~pG!=xKn zn3V5q@jYui0Tg5n>(&g$9al%+ia*!!T_eH&uyM3>!%OMiW!_O9R_EYnD2Q*np{Ho! za~<)sNNP@0RzW!8@zwu0=x9t?;5yFwI}(k0$(ZV+7O7_hQCk|?)6%n^Cv3p4bRpnA z-c6Xeng==Z`fBsSp9vOTBuBbYl^f-I4?MV{ev&QtyxnT=5#_K(rh5a3tq_PSH@E8A zReZmfq|(buNhX~;Zl_VFLaU<_(OkE=tH3ZM$Rx5wTFUj#7+Ym9a$C2GI~LXKN(r37P8OO@KBDn|HP?8d@O7*n)4= zPO@}F?-MFb6sRt3nFJ%L+Z3eTdTQO8qfY-nl;W6h+-^atn2dK}<5NARpl7`e20?py zZyP$L9|x^+zn(rdGY0+>3i>bqso`zfbG6OY!%T;=1`IUD(YoDbj0_?&KZ1|BzC$$$ zHxjtrRZ%y!z>ZwitB5T0@AaZDWiyV>V@2mmu5rZ3bY)Uu{I{;Dp?#FMR5e@(WFv(`C%I`3O?1{nBp~bVJRF?_In6VgD5NgN=!c-|v6QE!ZLt z?P~#aEl)2w(+nFOT`tRCXYmgS+dou`wUQSX%pW~+OlYB2!u36&+_pn;r(+;*tAD$I z|GQjcDTu&NMJ3Wo<8*Y+e+=-S)DHLl{wp01;1g!f>QF8}Y6RcHs0>12rHqG2B} z;$t%)BX~r!W0yb#{oWB_K^OSoZ*%-E37>XMR5XC!pNTwvfJf$Y`lHrpzn`at8C1>$ zz3R)T+F8v}9cJC2GgRv*qIyAraH6Z$UB_tsiLkMn>MLb;$)9I(#{D%L%nk`fL1YFajL~6&ORh z?9+lA*8#fEVDF41>6@Js zoX5)O9jCt5r(nQOUr9dwj};t3zlvFGT?Ys|ni#lipyf_XUZJ2(8xEi>|9cg~%vW80 z^zRknX&#$~=7ZU+h8=I8KxAwRw<;)-2P6}39>XA0Gxi%9c#ep@bxvnfR(BJdJ$u6r zjwXC4sx0MF(R-`8A=fvrNZ8F<&?Z874DcDQ-`NnXJ;%4cxzXeizYV+OHLMzXpCaFQ ztJ?2^(n_SND}>U|{R*$@WqxU~LzPvtct`sZd8TOWO)%w&L!GzoCC`t-jZvxrG4FM& z0k0xp?Aq1F)xCoL=oZMbiYJvZ^eLG%Fe#=Z`+CtL9C z-Sv;$N^@TRT6(D@KOje;WN02T)7&n8{bH=Ca_@*J`H3(V)8qr_MOc%94x;CNHRFfW z*bnHI8J>W(2yQueZ=t@gbUK8X7%TBLQV%4Ey&f;ZM?Qgk`n&hNYXFV}oO=Kx>{`4F z!f^VwGz&XCL?83*QB=mB!z?2+7VA}Yz187sZo?UmPFUbl@0>7-Qf@uruIlQ`ThT53 zfPXcBMfzB}TV63)$1#sO!`q_1&tRwu4DP@3zDv4DoOLFSg~Qi(#qG%WZDcsYhkHN6l_~9(In8Fj`sZYma z^^8G#Kj105&L>+CqBxug`XcE9fpW|JE<(%9uCGcTblb--E#yvjeJtt{-PkNk{=owV z%l&4?zqVaFxk~R~^A&9B;qVPMIK|v(P-wvJ92V z4E!2^>?|n>yJ||cXebcUUrk&H7Hix8v=xw}zfH&4CgeQp4TkO*W0b}}nD;v%Q%tSK zJKau`hL|+iX__|&2q}nCBc3-GfBq`i&Q{h@ZLn__aXreQSK+5rZ?Yy6bIEdfGidbC z`|YXeA=QS=U PN94}M=5~?7mvILFc-Ff!3!WH25~FQV@_q%k_~C!OV+B^R=ASHq z14=BL%@BdE9m&HP?q_lw>sU^?yz}{?9(2vPSaM=MG#gJH(y-L1_28bBAzR^P zD{5Js+gA^X@pzW|&USJ*rBddJ()&L7w&$XJ;Z^hIimUpX$L~=Op=WBlFCS4osX3hh zWms|%XR;WDmV-{O>{wB8CS>$C;)fEakqzx}Iw2IK`ZV75xNVQOKV4GMJdSM@k>rsCrSYI?{>B8*$EDKkgvO)D-DGLbyb9=ijNt zX+8UTAthpIx^x@kv@{)Gg0t&(h=IBovx%SHu5Cw1hObw~-?QFGt`nZwNsK$^GVsus zbtz2k9Qu?I$c= z%|S2JeS&mOxgRzN(lZOX&0|=({0%1aI&+riNgGdZ>7#SA^PwF*bg$$CdEHg{`6~D1 zW~j+9rDg5I`?|eUH{SU4Q_>zUp}2^<#c%s|b`mZ%m$%1visfL-zM9mfO%%PZ+s-#! zIg~vyRepxAzG{_P3Rl7^5Vp<;ydtj-DHCPg@DR#bjkOARr9Xa0Vq%^PyKUsvz1=*3 ztP&<&$karPe8P;?;>@(Wi4t3z)t!DtF`@qFa!6WUD$`gKSdj}RUcyM2Wd3n#8jBeu z_9Ih#i1-SLm8t{aeMDb&CG)5Zu7p*mFvrZa3aLXbcKcaC$t$Zd*G&Az@4U|X(xW|| zlcnTMkspTrxAYikvjWCG{vrC&X`)xG;ePU!=Zqvz^OvT!2!>lSf%ZKS^rfyp+VJ4T zlBVSf`M*69+Tir+hQOQm#Q6xiKGzPiG8;>HRY;C(wfHo2H7F1^^Cs&2_toW^=pbQp zDb|OxwWYZFRj3r1V{hK0VITi3ReybrO$9>8dgXEVYo_N0j5{R(oR z7e%Y;$igEGl`q_^v*8idy!OQ0b7ljj-E#J2ZO>YfqfyuP456qhh4m9_S;bswgPe%{^odjI6X1|Ns%=fD0iANK!*JZPCL7JPM;C2h* zbmfc6pdm3KVr9Xy8)7IsBsQVWtG!n6XJvefuybf3IeeB}`*=)PrDaY@``T^a<}oo6 zU&JVK9G8eSxr0Ryxbz}fT3`sYcU7?pmjTCW8$$ADkptcU3A4ork}6+Uqefhg(*r(o z`3f3la;jv|1pu#7?A2bE zW(O-t_+{LGCNEej29OQh(2XHnRj2A!K|OYou(;X-amQU7q0JVSzBHIGI=W(Xboj(i zs|pI!e`;-Jd_!ZQ`}j0VpkvqPs#xcJ#?o~y<&WkH_xyNWyS3P+yF@6SbQ_kw)2Bu$ ze(*tKqX1S$|FYdx-X-DQkVH0Kq49nU1+i2j?DFa|W^RoyzG$WWYf}Y#0w-Xa-H#iYeC6g;qk{1-dl4^%ZD8%J-P#VR3G1W@TP0>`7K z{ioLYoz2Y{)n74WB-LeSzMh5HUks1Wv*^2Kd%W+~+De>SVWZFiNY-BA{0P@d^IeIy z*7eLkS{J%R4AJO;>y5ZLaQ~-VPrICuVdJgUVYpic)b{)xqG|3)tVxd&H(R0S#k7~z zg3v+Hk*bQ?B8!k(gCFTAe!Qx!Qb-r{@07d{tK1&?9qtkhs zb-&2@+d_eKO*+)X@*g28is4c9MFp^x&k9`gYp+lmvqOz-9SFgaw7WHK7A8}D)+>e~ zglvSC1tfdGbKZl~IE0eeZc!hP6Y~TtrVT?b>p!~&1r@l@h;DGi_@tCUZY@;^qi+Q3 z)xz{A;2@@mTVkjl_F7i1KctGy{1Fy>Wm49}dj4GKCC7;$VYN#kyx%7YRejDWh3pVj zQHQ>tqm|xaR;I|&?5;?4L^r0s{NAN9Q2e4hU;8KHl;$*mjaevdvjO{_h3Wu&0vn9{ zeP`2zr4QjOZ#h}C5AiN8lbgg9KNh@SI0;OFDSxkqZ*Jjws;s0%0KQhDEG~>8U?V*j zSXa-D8q$=~BJ@_jlhu^g-eFhqv#8~(+*m1b7`95kZ0I(L*KDl|nb5n_v$k9XTHvrg zSCmlE1h{qW#Mzq5cP|*H=26tK@!oi0h9)&c)W_+3m6eq!B%+ujAvLoKH6-tf;~O#1 zdA44e*{Rc1{GhDZq@pkwsy{I+DyK~H?-()ow#DH~bijt#dIGR&Xa|V<8KX^~Uk90y zxUk`E1`Jb6@y2uvac(_xXYQQIr*&aZatZ~%AYDrHt8~wecJ%1m0nYdwGP}IKs>ezm z#6O>(nv0k6Uy7KYx3Dsl!qhzt@)}`>0A9Oyb7fPtT+6F5fL~|xJ^5TI(?b%ksaMR4 zeBP0J_q=F8IA*Co8GlC}FZVYM5vOEkoPutS1m5YVyU{H-?#|P)Pkbm5uE(zF8|qG*eNaDG#|>rhsUl z!dBVU$~{9XWo?T_7gk9P6?a4vU0cqg9$wQ<@GqsjUB$K!iKL83Dx4#$6xUETQulY9 zBJxF8GnrwK78=u^%Egs_E{gI()`TqbK$KMv`#6IAcD| z6xa5}XhJD9xRg!i*Nm0^eb*ix$3#61l4JGq1DF|%x*E6dEl zhx9K@GIv-4n<-99%E?vfYJ4m=hBiHI&I<5-^S4ntk+tKJ*k7%Xy>YUvEvhyDJ-LrQ zxq`n>cqE`8r~|T3%pCe@jWa)D-ut`I)k&9{Ub>Rd{%V;1H}{mBeLaa7uWItHPj?5q zP+qclBcVYDDftP)+O;FAGi@NC&{>iE1&KursK8j5TV^b)=d&=;wK(HvxDYea=?i8g zBUqISG5>27TVkAgf^<2-wdHDy1W~zO!W>O`*?oq@SB}H3LgSZ+=eIURBT{lWXpt0o|4sh z#J=@Kchi%@cV>?5-J~ZG?=B2g1AgcDDYQj>zj&|a9)|xpmh0-99@R)kW zZRG-ibk~n;o;s9lGc4w6hf^w|-^q$h{c5+?+quuT{YQbZ&bAdYet<>W&$fv7*!$NI zcW3$s*Dgw&?*b59kV{E&+0DByARLYGLTN~`_acbpHx*<`Cdt~IS*CXnCrBBwky=HJ@5Pzzo8)v1i=;@pe}FXac_mS#j3_$I zEai*gieC3?=k1NWCiKAOBp8S_lpR;yV3I&V=!CUHn$DOFxR_%qUuWRr#wydXajqwn z&I&w(;M2c&x%p#-+$_xIMZu`zi6i!tJ|sL@K>8_#&V^Ll;C);r{40Ka1+Pf-?>>zVIuKdYbLRbNXvC1ttAknkGcVcAD`R? z3;M=^o8y6DIafs(RCZ9_ThP83oo{sEIdOyDBku2EuRxlMJOR?TWb$+n;NJ6V7V?LU#-MdkS!M#39b4Zk0(DBO_MiQdOuBWUPL zp4^LPb3aj)>-xgP``SKzC!|w}Ch=}%G+Aocz0YdnrTkO(c^Cytm4`w%>?UF9(uVT9 z-`j`0Fz_d1XGv=>gTEe8RIPw+eiTr|xz>4)WD#31+$o(3kO>c2(psV&zTej(&Zk7a zC_<;R$)(B1N?E<3t*^dH8L87k3@gJpi8l?2k(i9DYQG@DUsk42Msg+`i7g~t$blW^ z*f&lOkl}BORtQW@nh7g%D61S2%Mx|ua`uWkac1ju#Cq6Ss=WIkM+(MVczg3!r*%^s zt}MSgUBN|gzEaX)9QTsI<$evrR^&oNV$?xjc(Luq39JqCGXa`Qe);KQ*!MLqcSfm^ z^>;t0cyGHr%<7M7|{L0x$~U42)|x2&p28Ur65$OnC0s*+iE0c<0_ zro3J~8U#$6IcCmlVi~JO;9!}-FW;?o+fv087S>gpX3o^MDahOShC|b zVx*@{N8Sn4$HC-D{HItWe_}&(N0!P!wSg3>IkJJSa={3?Tf1Eb-8JOM`6_-J9{?^7 z?Er|IpWRHVV4CeIHq;XC`y|6GFy!ziVT3|>wI4_({uV-7>irDil!3K~tNbGmbuMnt z^7oBe&_hgRe|dK*XGDEmAGhKnLa$oMAFR?IbT|74=^x#P^S^0I)##2ZE&VVV+)xgD zkS%h?CVS7JbX?M2mZcMg^eTOV22*P}dxqW$Y7(6l`{V6<+F6r7VRr5{IdFct?f>j; ztx_QiR_?9in$cl?z@1!KR0u@UYx*_V2@J zTlkPz$cPFGJ*m>M-2od_2(3yUI_YK)GXJ}9RX(}hyzwFO=`nUb`Ux}!M6Iwy!fXy2 zRkpB_>eFaNA1dRg&xzchd5^K}DkxFd`24O%ouFgpWLY1$qC4_KlukyFCC;1y+HJG) z)(&DalO4ch(_7kgbCctApc)|BEIFzo3bKfEnvKE(p1>M}#86Pwcl^pa%@)OZw9``6 zY{%BuuHDd7)__N)^m@&=85n36__v2mS95KjR!wwI^^2YcN1cdzwJ+6vdqQ}TjG9sq zspDL8%2Gt(oIRf+*PX6B=}!Zoc4m;wn*<8K1$r-&3LgtGCJ)FaKNbP6+xQWCK|T0M z`qKCqyKYtAVwg2*OZ>PKGzQWiH~{EacmVL*r^*C_CmK z`#C=orkFzMhX3o)?o8x_c&>OTdJp?fx2|zOm*QsoS29(EV=sG5X?wrxeS5CRxP4ck z8LWqt&CTjvF3)_`0IdIXO%Z=u0-C4KC5~{0cXJ(FU1cAp41TD{b4qNHPuY_gO&_vW z!RmiOL<3{J_39b6ZmpLc+7qMq-i&vtmpzc3#E-D=#Elw@t_;vqR8lmWwO<)!Nz-(}XSt1aVlQoM#*;Tv1;lGbwq?o>l;O4sO*J>ga_ zxcdW8x9V>1%xy7M@R|7Mu$0%y`i@F9?bkec=FG)2y8EBdg*|#|dE*8`DBvyFZ7*N^g^VR#f794R@$E2m-_Cuyco)BbXP zqTo)e3E3M}L>1iX>@OzdFXVgVzehV1Ii&O$z4tPj&tK>n-tZ=q<%4^N<9KPo$Zz)K3Tz=ImQe*Dv zH4&cDD?65k)2i%|NBeboj)crUrMnBL!iUssSf(D!VZ9;#pZMfL0U^lQ`{QT*9zR^k z*0CLqH3^|4qYyqTNux^Bbw3VB&1@GbEnM!@Dt0$dp}dK=eCf)|XFcKMu>iQ!%!+Tg zOZ(lf=!WiHowExv`jK zHGk74VLvdzkmlCliIxq>Mz5x|KUMId)e+@2ZjS+1kM*q44`HCETFi5~28X?uZGcGb z`z$U$>S<7xa(~nCbJId3N<;ZVWl>)bwMO!i@dRyTT%)rBSBpTg9-v zlQ$yzC;#)U9UvXTv)~wLwMUyvjy*_9uLCGWxQ($hCG%}gQz-nGF0cj6_t=sEI{O_u zA7tNjk12IKp6)*>x#m;s)>MaejyFV(t@}){$bYF3rso!I#u>r)9}^7JI|zF|F$4JZ zoO)yc*kM&s;Qi+dJdZE9TM1ZD_?R~YE+s4T2=rT4mWtDTxD-RZ7W#C6ewwk7Wj=)X zr*WZT7K#S^a0;VgNKU70NtH|9v z(ko-7x~fa&O5VduDy$0TT7_&c0JZVL+On&>e`fYDw`YDb>sU;xoKDdgd&g{E1b645 z!prw7EjnihfqK;&$@p`I;U0p#@StTrF1n#IP1Wgf{l zQTD$@1XRQf^iWgmocD7;MxKf^-UDYm=)Q#z*!WM`@g|EOl&|0|27Qj8E$x0+Hf15N z^L5jdWe9}8nyj?`LKWj?o&p7LN99;?3F=1V<_oclCRJzsP8I2JT-PdU={8Ygd(Xyk zRV#K@Gg!B9B;$NozvzAaY}aF;xe_rXQyBuu&dzRpe1NHjt2Y{@@34N|V1e(_sv#Ln zGY<*-ue}8p5jd8nLmDv|?_y4?n!qL@H$+u~Cl1CZR5@b-~aD#q7P;y!K#NSeUERh3TRZ&U4ti?*Dg9ZZ#@oZZSxab&aPJ<)RV3TUFHYl{SC* zR{7&zl6iK3->EWCKZDyzwOfKBX&SLI~KF3WzK}2 zd96=;uqvr|RZEq6M2ABr47cHrMiBB^3I(qVIs=)WWJVwKKjh41Y%Max^-RStW7O>( zDvp+r1{brq8}%_q)EgaKj>&rSdqDTmA99;Rp|sNLPIPIg)vf1PPSDkDvy+@l zxw!IZyH$@Q30MKIe}F%60z1*Lc_aZM{A{_3$t;>~=*dpb{sVV7u9pVfC|T*6))3TP z>Z#uQ!3Wr>G&3P#;r9XV1`Wo+7xVq3EaHB#q6fC$U@3v!nKX^yS8TeQGRCe`6vOyx zwXEp3L{~c8Q63bM8t+w3GIt$|!EnW_>HP)lOe2%ShP@m_!O0`dt&|K1Sz z9COmjF%|9*nwf1~^j*=Bhwl?17S~F@L!Ij@t=*b;Cv9sNp>M&NNtd@)jro|qVo`Tq z*5qI>Y#kI%?04uO^j(ZTc0)_2ec07zmkq)o`aFn@xb)bu#uX$-#8e z7GPXwJI>P<{)Mep*i|0913(?v7%Jb}Ej^kdLEUr^B(HTIge^{|>FLwi_|X>4Og-11 zYJsp$C)uvao6qE=A`$5B=Fd(#A&}KnwNddE)E?Sl(N}uW^($=s&cI&b-R2WUvDdaF z_G1G#Vz~_u=(-9rX7B}UE)9>$c63I{e}De{?ro4a(g}9fXvof6i@_eyPTVZp?SH2! z@1M09H3~O+k9?)f2+IxY_MLd9%8)&}=eQt9k;nw;xR}TtG#3V|@adqNC~~msuVl$m z@Cxa8cMz@gV4f>v*BCs0nwh2{P)ae-IiPkYrzc@B+HmoD`m48=R@81|nabPw%&cbX zSp=@EEudU9xr7`WVXsP(vqGa(ECxTH^yOD(e4MMI`Y{rPE4y?iV@If;3f*CGOS!dO zA6-;_YbVz7m}1r2%r9j7>Fk|>{?frZ*QAVYS$GuVlqvqE8>WTud2isaM^SeIsY{&& zzt(xVc7}`Dp%>F4|1Q?iH-GayARSS@H&T(O==LnT*LScT$_ZV3%*C9g0&%{X+*^kj z{A91k59f~{+?r&o#LyqP4{}f0K;XyZS)IriFU^R^I7uI zMNiVwzqoS%)+cqtZ9(ts^lo7B&nG}N3X^}`M6AB+XyjqEnJG=ZQaj1vrDcesZj_t(ISU~K{EUT&&ZkbJJ~OZDnLesR z#u!P?j2J|uNMemdrD|S_uNz6vV%BdCZZhOzK0;P-sIQlvXH7%)EhL~cPF>We6!t2c ztyY(d_}RgmJN2T6S5U|ur5m%O7uOJ0N48Qe2$k16wRX%irYlB-8`huyOTw+21uv92 z4wvFAx3*~vVYL2DqJP39y*FC zx@Fq@pBmWnoF3@Ih+WZT-+rRNE^7^7fbK>1VB~QK12^}wc9a@H^i z-f?6N7k0rc0a1K#<30Zf66eR%=etUzWG7P7P9D<48IEj59AP z#TFc;fRg%4J)`;nu`oMG@Az4xVnHKxU(u24`mkCLxC9UUjL|1z&?y~(2y%>AP}79v z69~t4iGMOUX@|E4>?3a|aB=1|>f<4$$t{PVoq z5k&@<`(hFNZO9S4%ky5+g(~+xqBWQ2GciH;2}&kzVBM!8C7>uQNT~`-=5?P|{AGaA z+qSI02KbjvL}DV`k@c#h3+B_9LxGx_LEu$LvfLWcG#>$&EF?CVRtw$BXU*;&Hp=M> z_!cJY75__5i$f!<8XOnqGJR3=nR$WjxdSp={-f6e(_ z0;RSbC+f8Rb*#4A($#;E6tju)Ec8uhVH*GZ_S$8XK9WWG3c z4EnqR?Nrd&O;t$OLlLcKFJdt0tuGEQVf1|rmNMg-`OkW{@ed^gx4S~`w#go2UYaf- zJ_m}M&W7&g-@kN{UFW_1$-{!I-JLZ}CsFmBJ`H|J+4b)GJxUITk2J@#WW9zB)=b;r zY=eF~igd3&Dp>XU8gLR#$^0iDgc?Xq=n51Vq_hhVU85A0{X@0&a`Xi_kA^9Fge#QV z>2H`!V|Jz)@>=p<@PNZ|LqG@x9a_0bc^?}Vbb<_q3sLDU3G%G+;zW2-?CB*bxv~!+ZLR-A>TlkNzVn zgImHap?Q-#rlQJ3!x<2x%j1*g@E(5X^5 zR-w>fz~R%|rgypQ;-AQ9LhrY-w<|huG9hs9ae9e6M?*iZ)_x-fl}M`?+Vba#O_xsJ zAiU$S?;Kv2Z6}COM_R~I?evf*DG|M>6%FGHK(NZw5zwH@B8B8i-Im-kxtCX+lQL?S zOKQS3v=^uM-R4w=_#HRstX@~?!REtZ+f&r@p*gv%;?}D}cAZJRWZ1%1tu#E@VsJV& zTa$fb zdYAj0Qoh3!(&>hxf_ zg=^e$a99qbucC03A!|P9Mfi8Gxd*%h%e52XOD$%`f%!A23gksp^zBLI8zU<>@y=!h zQbDW~!m7mnhMV=&yJVB>C=c=S06my>m*5i!0see3?6Gj@xsA^k_QYsP`Dpqqo(>q< z`qf*#z4m%7uV(1nSj;a#Us}Tl#FPPc=mm8hJ|$5e->jYw2hXCe$JXQ=;W0|eUblM4 z^lwqbvNEaaUr`!*3Rh~+ZwP35EZNWPdYbPioadKr0`xT3aYAn;!hm0=KkUtlMC0QN z*f#EM(+xMlKsj663rN(^3NBhHV>&b-YQUp28g;wMqwh1aqf7yGR6ZGv57zSZQ_n>C zRQU5Tb}!AqKN?IX>rdOad%7ZujHa=wpVWpvOhlI#(rx`9$?ovH@RrK?jD!x3y7e8i zpNvRl_hQbQUm?%7iW{`Niyf@bEt5Kq(g#7;)Cs_w1rj6)x5Kjg^?sZ&(rx#rgB{QL zanet^{-}yp{As_(Myq2nx;Zft2K|ci_vWJP?AAmNz7%ty=K1Pg8hdglL5$jM$Pw7R zl+`xo`dcX6wmclt#Jn~dJ;7-UyA(HQ${huhGY+v&h>RUGy=(u! z{wZYAluikzDA8M57=6|<^Cn;*;V}t>py|M65SpOywP?;IEalqZv9_k5PM6|j_-^q;9T>Wq;BwjIC)_mm zv_AS>Z-a{(Q{Gn{xM}uc${B)Zl%j`G&i2GRkrLY!K-Kzy!Gn>wKVHFjzKL99-}fMo z{j);&o1IRVXtuAt}A8)bmhz zXOnb+%+pgaVTd^?COm=TvJg<+QQDThIrDaF<(>2SFSzL@UX-t1O5RE-E-izVSW7O$ zB}k_XhxEl#5)aW@I7FzCt1E8NGDklhRiUD|NP1;1~%;Hj@> zdrQ8?odU?AkR43GU_sNTlCL??{FuDliv!+vg8`B`Ux>N7v9c>wdyX5=jr3D4P`Me7 zOIX^D;%B^-TkPk2am35xO->ig&qdU6-Gu)n$bM2lw|gE%8uk-bTIMMRs|bhb%q`x2 zPUmut{(fnc4tYb8SEv+snd!(LLv;!Yla^aAzvU9Ra9NpDVTn27>nK>|zsW}lsJ5?= za8Ft6%rWE+0Jv>7>rY@uPxkTKPjlA`eQ?~3_CUo~fD=7BO`^gePe~4_WkMNeS0$fWAh5M9dsDy zP1ahb?@a4uUzA&D))!7tv8LAank9L&=54tk-6k|O=#C$ld(VxG%363}k%LCu%jsHa zZOeO>TCjaN8{uYcj%Lht1j!9n5zJ|mwLxN3)M*roSSeC$0;{mZuP;7b+|a`+c#XK4TJ2NxsJS~nXN0Rcpjx@^o|{XjaJsz_R=p*AxeA*aExPF;cel$! zJRfgQQq;#BI*-`R0szz!?GVv^eutLlHWM;Fc?_RD=P2s-0*r6CxqikfYVnY9WzXyv z%g%g*(e)R%?x>C(5rlS=@}$+N_O}n7HKJc}OEhm1zAA{Ce;ltTm@&b|14hv81|@XI zrGV!~XCqflTXfZ9&qjf#)Hr@1z9D?sUySrB0e=3nmtsboR`7v?h zFRsFCmyC+zQEhx?@Shx!Rd#r?;={H}c$vz8o0V*A%A|6OD?Qr>*P$ zXpl_Y{|v&)AnWrP*fo7?|Cboc^9T z!*^xWynvC1ZKAExqFbJdK>|&0ceCcJLe^Xs?!7B@eqhv}k***ZwQ##T6uIkE(H*yL z^R(MT$Dvo%bR1;1g4jpa)Bm{2WZqp@xpTi(>fn8NXP&o=LU`Mt-2YjM_r33zJd|a_ zZ{$BS$&6U<)}SVc3HL{5WYoa5^BzL8@p&yEeaBwC)$&w-LS4k{UMm?2`>l31wKSI| zXtzWRMy2Xw02DGyu=VF6PGy)SE30jOBgy(8#Bw7zp)9dX*r@oQ2O4V5Q{f`c^LTdg zlEIotp*}2MAla>_mm2oI?fzpP?vEN*M0whNGT*(GBp$Bw1dMW*&L#OOVpX?$=FGFQFkiq@CW67Cl z#5C}PA#qMY3c5O__AU8&-ujazwK@hw;e}XnldqPWyOjkMo~`CK7qL|7dgd%B1L(quyfdEjL(6v&J*xWZbn5GWJd`y=VW~NR znD6AK51Yb+S%1D$$Jdbg%*N$T&Rfm%Ip4ZFrF&)vSPZ-f{ImiOxVrYcQTOuF(Ghlg z*>}H#co6-X=4|+Yy*f*;C({;&B9vy2YQ+i)fouxq3FO=4L9|W1GnEJA^)j;BzT~L* zfM{PIR#Ky5upztvCggqneo(*Zl#3aosy+>RK)YT;{>1Cd48V7;{JPjG0t#5Dt=$4v z&fA4H@fZ;0hDrd?-?nKYV`DB9uc`N=DHM_j3OLpC*G{Gxa`WlRPDWYbX?)OTcU3G) z?LK~aAnKDbOOtDjPS59hBp5H}e0M(w=CR0BV=$9LT!E|E-!uXHAB%XL6%dyYN5s$R zhDhG8a?UZ_82f&SE7N`bb{Gm0`@&6u)4Dj%=CkE~%loL+lhIY$F4q>b%#yN8OErW+ z_2DG@`^(`pGO8*g_y76Pb3dm*8r%Wd$zPp?XPf@QRr}+>FzO>MQ#z!ns+aZ?CWRc- z-ojqx1ZgLN0oJ%aO43M|dO|y4qS)C_B2W6#_bR7Vc0r}f3vVaPWqD|6kVuGU!Qr+t zSo=#gj!0C7o__wHgf(3vz+chC`{6#Aw2h)9Q{-De91zf(k8zeywvfX9d}+4zERjd^ zbhKl0v|8_H0nU==FpY~#r=tc+vk1k`Nl`FbOPF`7_ z0-;Q@C4=r}ti4(@dDmFEdd2|FxOI#EQdvw}+JMXosE;2M z1yg33h&W7V-0uCLK=Qj>MHd2GW*XH`pIhQ15a=d|D3t+9z4I3?=w0^9a5F>!9{Rzf zyZ3-R|G!_wE|GeT&c)m7&5c5(=EZtCpmJ6I^49=JfBg=6R}TIA=?|Scb;=G7GU1D@ zfYHSvSXbZKkUdyWhUX^VjnWs8JA;d@lky}soZIU*f#2q}7vLLd-%69+zwZva{rY

8x zse4A4F<)CJ7OnB$FPSd)X1+ZGjfX38*LOak&2i4G9_3$^h5GMZ6qpa(B0v&y1n)>| zUPxg2fBnKLKW#kqj4rwylp1gLOfmnpH~(7l?O4MWR+@l$-4g4Xgu$3k=1xR^Ij!7$ zGZ?~QOsjmGzV~wTMx>(thT*#}l#Z5H3IgwbKqDy|v)Gz%R8Rx*>Z1|2XJ~w?7bkTh z6Td+Y{`F{o-&67EAK%s}3`hy)>2Jsow2m;w=W6pQU8vL@dnIOxTG>8dIyp9Xi}0V7U1zjLGk^rPIWnIi|X3p>bjppL-n_k?cNq> zd-^}5FjVQ{@c68_N%5CBfsfJ7v;l#xv!#GP-!D6PuQ=?|&TRzh5mRyGwQYvMM?xVy&NasOT-*y&e$2#!x;z-U45z6wQH&>2*CYS~|x`nO!<{=J%u z_rVZiniMs3%qkr9sw(9FSdZUNpGGT9{!!>J7VCGw6r+oosgBhD`o!bbx;_)3HC6x6 zAYUe02xhQm`1jd%Kk&mkaI0ur2^bi6Fsb&h1a|-Pd>!Z?2SO^m*F)nAvukg%C8h@b z@hN_<=eY21N-^VVCqO>=+a`4F&+%UkFW&uyu6wlqufmtdOR>?m%GI16tzu0}Kn6$= zc#*fJ{xD$8z2~nmUT5oA+w8udD=JSQL$;vII(unV!2A1yF>sbJyBK41?}ZNB8dls! z-HhedRJ`2z4x|TFk^w1m5#nnKt(*lJoDEnQIT{P#7+t+b9t)p z*QYIcHLjfG>-zubdh>Xw+wXr|Nrb47%2uhyRz!)hMo8KBr3fk8 z5E<)ODiT>LTb40)#x~i;PL`Tbmh8roEz8)qu?@d#sQbR(pU3a}`p3f`^Lky&xz2UY z^E}TvHRp62@+@P7-p^+gSW;`=KI3WMy;QCSj37JEf$(59f0vbPq!h^$ZUjrzr7ffi zNWhOI>%6O*XWM=#Duw*^z>4FyF!%y?PDpZ+hMGRzKhPuO$*2-H+JY~>ECLvzy*K_! zVEP~F*uSv@x~)IX&_pBE0$Oh8(Ue6Nu7 zp)A%Zmu2+5RN>IpA5eXP!QN;~nkU zDaWCR3wj{#S0g&;*Xa>*_=LlxZh$>R;+l5Y+n2{@HoA%gPrqzam*Vt)FV>&l-^{{#QSk4w*C{~91DUJtcx+GAP-9umEc;IW)KHJhlI`cxJ~B56wC2KBxq&{9 zG~waleLqup-W51aG}((;f?{J{R676ncKWk*ZTH~}S%dp6YX|wA+YOo5081+*;F;H{lxwtyepa1 zML2A2i?w!^-5XYPPfx&9)g9_JrZb;1xu4quFSdPzdAM8L({H-vDYzCpyI{M={;q$h zsjol`VUEA=c}>|k-69B8BaP5jp$}P?8t>#A!;K8cD>)1-?Bq_SEwax4>+)4_)}nPGLxwb&xpkQ zdAKblY4tWM%z{`NEH6|Y0_~Vg!C|j?C*WH3C3@77IX=ZpzdKoi>4bMf_qI}<$~kTJ zHi~W;gyk!-fHxUZ)J!L^KUr|(U{2PJ$A1hcwWo^?{8(M6}fCsW8+$Jw7TBF2vP(MB{_lR z$%E-t{YrggE_yk0NI{HUCJ`@Mn{v2kZR z7)AWqa(%(QH*ltCTWTR;ZCho|f!!_^@R#?^X!hGFalQTz3LY!pvP`#;{N5J1Ftfql6WUbv z6B&2D|BS*Wkg_llQ_G$N>7o6V*Gb}^|wmTS{dB(`gFav zx4Q|_BWJ>BA=)#ynr~9*-oEYXf7dx5w7QD9D*p1Se(z(lMm$#stivZ!(SMD>|J~Ih z2Fc;ZjCa0NvRW^W6NDm=Y7jJ321b%D$>qdtznyz*iBPJzdf)$CCHhwo)D1BCvW7aX zu8EbFn|8LKDFTZK?`XODyjX^x(`xmS#tCc4q5gCcuds&xrEgw+E_;y)mcbR>`a=dkDu3w$ZHQ@_>7TlpJvMKf&A%|D zbGAlO)WK65mt79EN4aCBcR5#@tEz)#Kp*?!g8q!|v?5{mNuinjxzmLUJSctkgpVWS zr8%qP=Bnzv=7}%e*3J>ac7xA_W<7sB`~P#n`jgfcGMU;0i5z`PP=b(v#Q?g$5qf+K zT7}FB_Ws%&gbhc=J3+aOpUzyr5V5sNR53ZzPzRaO8DfQD)U5F)S(QaNN1iXPRz$7s z;;0lt(Ec%}>X6Zbp-Lyq{$tJ7#A?P9hKbxa z`9ioFue4Tr7IutzOu#Uc(TsL!vv=UpWjMsynpW~eE!lf|7Squ;5f_;y^WQ${SiBoz zZ~lTgEH^A;=D;5Qc>jNHyS0T>XdNu;O=YO(baZrn$27;q>Bp8kQ)jR_sQ2oXv|?7s z$PV>A)JAWOXpp?&n3@INgos?AXk|Nj2_s(-?84}ptmfcgGKkGxZEm)~{~k=?g|R70 zpEa3V(;*ge;@5&qP19=ZJxm&UTDm6&(FeCU`3gw*0RcSQvTM2iD|kD zQV-ko{PBQYY=1rETk8SdLYQ|1=MvIWf#akb>DS9s? z&&)_DnWUMRuHlak|(C->2m05#*CC3(S>Eb+YFiZ(&mstHLMknn%q;(c%P>4TzO4*22p zZez$J9GoF)u1&2kCQk{^YxVA2U~SmvUp?EQcpY43QOiK*-NU>Refi@^iKrge2gGyA zR~Dds>$>x3;iTXQcjS10AqeOjADxj*|a5OTdN5(f)&XtTRkVaj$OQSWa!eUzFnkwlOB^fk(mf{e$cRl`zK5rHi13PU zcPO7>#^CCL$}nU3SI19Z0zPOFKQ-C9BSKc7RaJTp1GNhh_&Jjf?@^294lLM~G@U`0 znye773bd5OygQ4`B!UgSGK}eg+Pad0<*E0V!SvSLQ;gGY_0QtMp4(^tECQEJ`>vOJ zw!TYpIceqg%tnq0M@7i!#b!=S&2X_7!gMA-p<~H0G+b2#Gs5Jr=DZZGUi0}cqxm1O z=_+d&6U`P~pX01CiIGN_%{gFDg3UR!mQE7^P~K zakJLibbq!=M&e5UjIzIQkqX@SEQfa1gC^nDGD&S>fs}(su~$}z^T7H86_|E9@>A?? zG5^BN`~AgOLK?~iIk(B=V7l&Mh(wbJo1qB zLaRg`n&3~9a?il`gVBmY?`?bXj_;e(9{=OL9$+p%dZ*cs13vyUgf66Xo(^u5(S4tv zTbpq5B<>4YLl?L$jmEG#ls&3_IbQ&!+|R)wE4Te;-`oCl7NiykC54Q)HJ&|m+h&z2 zaw#S4{Ke1|vfWB1n~T(jOODAlb$04t;o^VP`oZsm1^>Ze9*MXBq+2e|TRuH~sx1>D zs!Ky;xENZoZ~UsLsQBq->-k$YM{$Upx|aZeB>^eEzwp!kyL^`>{()u=-c?8DKB$#h zc!ko&I;StNpx>+6m2u)lK?z@*j!sT#WwRF%$wEzAYlOm|U;et-`|mnqN&|{0K#*?c zB{G4F$G-CUCZE)R8p<~6oKPT!qz?v`+`hxE6!%1}4#MfL0+{@rUhO^Vs#S%+SNYko z@IUYJ{V#SgIl^Qy{WDGEPy`=2=R*Hr6%NL~dFdZ0<;f7BV=KxUl9BHNr}&Y#RY%(( z1;yAmcm-oX__aRPA;%w-BO^FeV-yyJ43q4Vdcv{YpBrX*{}9Ea2meBbF`#*D`T*!k z1S&QE4|w`{C+SyX9g9Rgqqm!9kG}U4qQ(&oX36&ae#hok2hjZx1VbGE1Ihs|{`mOg zbz^sC>Gw=bOno2BvGd}+pnC#%64ef}dnmqNbzE$)^Q5@ULTZDf7|2zd;M|J^EXguOPpd**L#r<9(b3&=%jxUzH`rFMeg*zsCPF7xNo+ji9VN z9VIXDR;OO;{UuU^*F17VpObtKqeWGY#ZrI38Gshb6u#i>y#)BC!C<=e4a5hz7ZE_7 z;Tgm2t&NS1cB=n57W5F(5p^B!dN1|IH^0lo9?qN*zk8U6f`Sab`~jjSN5XIadz6I` z!E%cYy_?^(k7xj#?c`t3@n4`Le!ZQ){4khEu-0P3d0&v-=|cvt8XSo&A#C-1pk%vR z22-fSeCcA&Q>kpiF-ZIgGGt>mSPpNTdsYb}dm6F#o&w1wH$4*pCF?KcJSZzzz9Dh_ zA8?|7l}eQ2Gtc#)TBcXzt=b{yx}C%s`l}&+U1|+ilgww+Qto;&W=%eNh5#pA{=Lo@ zEPVa?dzfa(ir_G)o(Pr>l;I?!*d`$)6R7YtR^2HgptPwf)qtimwMZN4u4I0)smD?fEJW54EoLQ53uME zS(HDKXAazH{PO)MXNL{Y$k_7!Pay2x-88(k>HDvs z_zoej+l(3eE67o@aFhYe@#4kMIPXp-nICGpH?M}xv_(jHAl3nTnH0sOCT6B*NM)iX zwbnWBgfD4I0EskaAQz>uDORthDXsfH9<@Ffoo#Zpq`cUHBV*2(pj$KiRVU8s#+htm znKgsScYHE=`z{4r*W=CAke_csG&F`HNKu)$8P1ko*ANv@sB|#0HS%ITdiGWPV6m(? z$U7aw0J%PuslwK0E=(!c{e9!vY`Li zM_h5LblQ~@5!xRJ%`^2Ev@S5RDSuI9Z@0Q2U6~~G28KxtpfXD}g@6DmD3C*dji2fw zP+swtkl-Y(HpA`w)Smz*!)x^$F9WaTq!07fgUhF+vQtOW@-JyrbzdrcXcE}z$UE@+ zJo$KzrLUoJFOH)vvC^WPmm31)nI)A~@25;Z%TXC(mO%>eoC=Vbp+ViHt8-(ylD{Us z`qPm+y;oRe|66vKKq3IV>Cwdh_yLJBGzsJKKnEqB-Iu#kYp)sfVj$z&hOZYGxEKOo z@jijjJx@*Vx~`vNa9ul$F|+feH1D~=FJVFE%{viy&_c&Ki^*hI8r7tfw-r|H$@AZ? zD5$8ZxisJVqws`K(Zm3n zFRgroxO0EbgcVhB9ZOU340)>x?twd24NP$_GonG3rNBS>h-_y>y!xfQx4$GH3P%=W zK3Ov_0{LDq2<~ZGXOeE8;se}cY~VxC)VYAu)W>A1zMIG-oez8a^7=AaH-gr$!-dtr zfILSQ-?S7>wbLNd_nh0!Q?)t#<$r^#zC$M@&$5%{_ti>w;Wa}4QD9sGg|9lLB*RPl z`YwNu`bNWgil#hhcN>}Sdym~u(>>et5KE2PR@*%jfbyuSMyGrZgc(19BGm$gngJdf z@>*RIT(yHI)$IC_)p?%?_W3lxXEsEz(0SNrr`~ERWn8`=!9b;{{IfD$z3RnhP z#}lnqLH?!H!L8qLWo_icMV9I}8P&W@((k?fK1i;}ad>m((u4 z)1ifR%h^L`c8Rg3G!A>CtpO}OJD9~Exu)Omt>Tg(T*spwcHK6n;6A5zTWfaZHca=H zJ4WP9_r?~>2z%1A9=}?0bbMxIK*LwUysN*@!0K?lVM&!}?#s7R;TE2q7@(SEP;+{uQf^lr~$#;&yY3U+KD3)?aC zvfd$PnV*57&2@a(2OU!zFlb*{?;A*e7}b5d8nm^q77k7NvSx9=9&$fQAf^m(AeiXV z1PneUZdauDwDa&D(b}JV;vD&Wi=C!YPuN@f{SrbOkW;;qvq&^0eRPkTfa<>lzs!>Ue8lqrYclO;Vl%lP9x=N9}+a@?&q2=`6f$}Shc6btAqf(#H0P-D&NHGGom8{B<*Rqnsq5@><$^TbzaH`T89_(ad*S(n{;!ur_qxY*X!tm@S|P{XrAIojyEfFlF!+*K)EZl zaiB(!0oPsL=KmAO2l4;%>053EE(8n1<5gu(@Kk9pAwHF({v%>dy8)#0k@H*x3*{iT$sGTpn_a{O{Mh7nOq*Z?*G4ED!T~ zZzWv(*Fn00OAkn}k#xH_R5&japj~Zn&CPshZ))C-fUqAf$;WAh8xI;9m8y1FZCp|?`G*|}0IQvq zX4A@BXP^%VAj*97?Z!NcY1wrvLBzzOrUO+6ru1PqSu=B-VMwid+qNi%rN*j|WKehU< z)7HSyvcLY*n-NNfn2TXqKeTO9&jD8jDB}ZW2Vh|Ddl)v4!_)s>_JDiE4$^OFB`epB z!~B~Wp0MftlJM-&1s_v4S@S74x4gM{ODzvfyToqWNKZbtUR}mW+-;eabw@|c>xZ)8 z@d?ei-AM@)j})nWsiTJ;*xCOHvxAUBtfG?q$X(Tp6f`_5*hcH|c{F=@F&{z-6(eOA6NB82|i&a%78uY2_>q zh_f%}oyC_39z<4!&J|ft*;Dv#{#KY=P<_q*7*Hg#k7^7R%ydP*gcS5lT^hwc)YoH3 zh~H{;_=dgqJ2}K5msxVNL%m82F>So}4mQZfC3)SGO2Y(eV_G`dCSnL`f(!Nh8*m4f z^GVtm;2H=6;9BUcTuf|i)4g?^7~so8H)r%~&Rr}0_43(>KkI8yI04@myQzdrw)g=0 ztu;pNN5<)8$k%shvXDHV?*~>ex+5CZRVz*RYQw`2aBHlk!%)>$>d#sx!z-N^IVCGg z#N3uQxog8^_GZ=LuOJRJrA(ZjJMZlX=32E(B7(khi@=oK{g3A-g%~CCU~WAdrQ{Li zP_Oxi8`3_NZ&v^MS-S%3k0X+)ay+nK;NqA0-8){~V-gp+uY}K-{PA(wFEAvo(k6Ta znFw5E2x~Mr4BlJ1Y4Yr&yGq0ehJ*)*!LxmO6QxgZWDRj&X8ZX_Ue&E9#w^;*lGn#5 zXlubm=JFpu)@q}n&5Fm7#uD&c%*YYFLvgnp7_#+pp;vm%Y%WD?{sw)F)H&mHc>DkKHoDQAE)O(p<1o(=u+aSn#sZlp^aCUo()(*f2^b3V`z7;wd_Ak0pE7N0 z7lf27_8zYG>eG83mVSQ*9=vS2J7M~JP3#YACDDZ0Y2%dy1El_hg5I&jfwIZ3^F`2e zBX^QckaVWTmlqIN%(FL2@XTv;@no@@n$Moqk#L{&p2~aH2z&aPF>ia!esLTlXu=$Y zA=N+oGB*)cc5ks^C%gi6-t90&+rJ6;O`u7clxfL`4^cHS8qH%+-sWhoAP*H@J zY3ki1%4fIoHPpEhJ=UcCVn4kW?Ae*)4AM+>!viP=d1k}QzUDlo*R6hC3QM1v3-Epk zDL-0%8sI4{|J7LJGbJK8!W80L;4;^5cnG97H9gy%kf;ZYuvX6F5YSz8N=-YQ7S_NQ zUjRCm+i#>CpEA(G#Z30p?5^20d$g0xi7mjgElks3?Z%#3PC~wBQazboBSXdr)Lf75 zOVY&0W{Rdvd9rW{kzE4vRbYK??z*n5?1ga9Kg~4*uX*>gYqv);=&){Fb@hSAkD=N2 zMaMl7F+kmWIlM9PwSE#4JjkXz?za1A#f1U4#W!1C8k`{MfANc;_jUIH6XdIwwS=Sg zkLw^mMp1F^80T)pH+0nO@0qMSO(H!5SqN+YK_t+{J+O(U$iefzTDcw{x;kHa*Np*{l22Mua_V6r^vxaybZbHzPRE>n*sK;$=m$`{H*Omek_ z(irS(Nb51b8lTE+_sxrMJ_n`D5gU_N$K@rCLsTjNSH}G>_~Ag4s1xuDn9E>Te@Hu> z{T4QRs`K(!W_tN0($vl>UPYK^AsN`k-bK!!&>3>2Ps(F;eqBmylHPL0F8NwDM1}e6 zjNt&?K76FUUr$cDsKYAdS*l4~^tFfmq;0UhDe7_6pN~?UIZBflvH!8Ee?CV4Fl;*W zwR-h(BJCK!&*HCF zM{K_o$VRYQk-{60%N6pXJDbT?XqI zB3ju3kUZdzQBZ7U3{x~^DHYNxo-a zKM*nD4Q2_;F6kl+xctv@>^wgM4uv9{$y3mqcRxh^>Nds1zBY>8cPGi*%=B(f?GUF? z2@6#!4Z!p&&{ERmNt^k`!(`0KU`(W6D9r(6aONXra0WR@J{yB2b=xb^0Cl}wBbKOZ z56=NO_6A|76MHTV0{8LIX~DKvdusmPSZ=Z^3xxv|RD=K@unZMZoM55RCV6lgc>xwn z(KX$S$ne)qSBIY|??e$D*GVVrddQQ1Y=od#a-k#~TV=GR= z_4M5DDg??U2G_4{=q!mv_5)j@pUln$=kegiy7tdbp^I^y(7Dc$3D15X zEeSpfMgdhg4C`)L{8P-QH-h}moK<pIHP@Rw*>Yeg^>5C;IqeP~q^V_MaH~uoAxJfH_VX$UZwzB30ZG1#+iA78sBdGdvoP1tpEZ8ach5Prv zhXi1$)#2($o9^1vV-gh22mHEv<*voX08aXm4#w11=T}C)bl{c)A5s^j#HkwBLuPKY zuo<48S81h#Y$U#@safH9j;Idyr|EP=#RfIKGYTHr`{eur zzS5Jw`n5YT3cEJ3Ji}y^Q2qp)EAT4sMPzFQXLayH+rdKbBc}$R?(VMjKo^EiSvF52 zav!uyJ(=pwLG*nB2b2OKssCo>yQCXtU?Q|HtRuMH1&AIe~8 z`xo|48A-9(7#EzETJ~?~TVa~)V2mo`<*s;`_f@OpDmaQtMCA+r{5UC)KL2`ERQD~zU!>rm0Tj%am`S5c8M zzZ>eLgcr6ph23vc%l9-!N5e&|26xL>%S(2=QVKxYm~3shNozJUwn{+0YcX)Q8=MNw z-9kw@_SSQ&Ms)R6T{zMgmCrT>8~u_PY97e83~h~m4>H!h zHY>+gQ!H0$HJHud--NkE3_h#;E)K&K_N-oey^z}T<{D{~pd5l7RZ9LwXW9^Pd~mfn z5xy;SC&sfoI_#CSG)=1Qp!(t+1C9cE-FirY%CD^NE7}oPAv>VMr%(1=&VxQrV7rs0 z65y?g@BHgdOCvPDn$aYZubPjb?#~~y#AfdL8giq0ABv;dJiOk;h=#tL64}(Y&5{ zmIk_o6B=}JXtFqNOyLH$&W9^*Rq-Oqgo!pWV}wa|Fy`ruYRRDW z@MM*3om}k=29oe0j;eI4z4B^W<*8EUyNlau{%3ZUa4Fu*BZOQwuB>++Fx|{ldg&r< zQGrn+Yl&tI!T4yld{olZM|#ur**8#26u&M?Te>0Q*5S8Y$jsTbBLMIxQ_^Htg6~oI z1C!+Q&Oan$ZO5Iyi|MfS*=T;ck#Gyrxcu}9WnC8N=D3vl_-nQAW^|}b zrru%ODizJ*m8$Pcx^um!^-R7-OlJz-Z}--UutsIU&sAZysjHzR(%lOR>HS|Z7&*+` z&dqDWaMIejX?$1o4?58^yCze((vY3<+nGk{F`nfrF&_(BtFl@(O{H1ia5JwW$+UIljz@T?0ceiVd0+ zq4d+Z@ukI7Wgw0|u7TnH#-#=6B3LRk+iS8|C8+>wvOTX5GnU<-e|3NTnWV##NvS*? z(z*oDu4qO3qZ^A`$MxxA1=vWKV3(*jo^Q3k#dPfA+q|0eC(2Z|&Y|ud*ao7r?wIH@ z;b@YL)UKpfk7@)jllFR9PwVr}u%eWn^I>_>x%?7q%s@k3C9CG&q27mih|)-yWZ2Z1 z-O1h6r3qy)t^Mcgi&~FUp6`0BXS%ldv>8uG^R5R|%WXLOPrF@<-LiLU?N<75AzTua zk{qR^?$$)PVhqJ&>Utts^A;n-tG%JvT(TJbXBx~il_juMqmiXK2+NH|Lfb-@XmtXZ zg&GbsHftG!_GT_xnzKuv=kTdE!r*i}ueH-A)JPS`5o{^+1WweK7A04XS@ADwO=dKxjWybY)$-Py92L#Zr1)f&47dyj9>~;& zCQDZEm55|38K51FCnJ+>kja@LJJKtP6xThdm=SmLnruJ7xF>1jo_t#{#-wq|TvX|k zRXkbkmE}iev2&AOTOC8V(i9QMyFEad6wg{IfPstC+Z|B_BF6_a@N7D&Ax*lAy-nAa zpBj2S3Y>}kCzz>t{i99iA$Z%`3=QWIP_3m)=o3Guq^O%yt(STLS&KG4Qa&31y053n z_q)U^Nl8DGS^^to@H90Q zL>O?xNjpo?NQN&ZCGoa9QhGP|RQf!#Y5aL|s)a|gC7T8yoHfIhlMlNl(|PdHBy5U| zI-SU-XW1+XT=QhL4-l0keF_D$Fs#4W?#Re$ek|F!CO?k`GRYR)Ky19$Baj$iHcScP zZ1p%$%<+3owV)pz7yStNGN>sh?LJOS4XQsaJ>Atf*WAQhoiZHua2pJ9P- zYG$TI_HNylJ6yHSG}d|xQ{{!Uls~+S81;a;W3bwjHC$!f#SUEbJf2ra+m(L5N+$K( z1ge%BO@GR6+3bVKg)hQAsvDCIecM^H&oQXU%*8p&R{4tP?9Tmk0wJ|=Dvka#lGm3H zkb(Wdvjg)}2WjJ+$0EWt5-!urS|^cCFsz)G-Pl~~%IFK^z%DAcGqXBUm#CZ!bJFaL z!Mqni^i@vE1F@+dV&1KUn?UEir;1T$Jm;ImE}3sYo7v+S{ZbDzR#zvZoe*)~bYw4Z zlG62`L8`ePBd6SgS{ix!YZ!6#Te0ji>RZU}#(+`}e}kR1X!qJvK3*$L4XYqzqvNRi zX;7Mu?ntw!J%Qg%R7s%?!Rl!Y*2}h5F52N&w!dd#9 zC9pd^3vOa(`FIIJe(F2lD1jkxRXd{{76y4t;Uv8f7N!EUX5@M1U7&r*S12UwtY0Z7h zdM*igPVg+lfM+pi<*nO)3VT{@e9T^Kj9d3#WF&GNLw@uoEzBbLD%ZQWKa6}ZVUXXr zv+?ZZVE9aYRR7l~9CF6Jfjc&n+mPeCUWUJPQKi0+Y{VP|(ZD?>0Q$`wg`v{e323MEd+!I{ddT^K&9C5MQewST0?4eKB0x?=2Wm1E9rnCiJ z>%fF91VERFulwtVE0!Fsyi9m5N-LsmE#b;tb0~gy5F(THH*~h+-6?+O$fjRqZ#0yx zq7pf2GSKakWAio{`}1c0oC<7zLC8D*>UkZTOy_=>zhAyeD!pSP)B%34n`AolZZ@u3mOOhC5qO?2@uMhBejIkv*=iGlL4uI)4X<%RJ_TJ%e zua@t1?d(1TuFEB630`e{Ol(kw9gU>{-~mBDjkVJ`hi!#EGKP32dD(gn=jRNwsN{!k z3*+?DC-{ytVKQwBg-*-P%E| z1xPjHnF`vosVZIXwX~P^Www?HP(`+CWr&Bq9+H7-^=aAwMeA(_knO*Z@2*u5t3gT} z2we%kh^RzE&1q2V$B^;Yt0Y;3c!l#aqG^*-)5*zfq+h57ij>gZ^*&ObbqJZU`)|Ym z#0RRXc#GG3pbj!D&R&N*b^C+2iobH!*0w|fjlR^*9T(?9unwSt z#S2Y^lsG{96%cq>?)-#L9F6-sA`KZx<&ymVyb?j{PP&}7Kw3oYv9BSZM#ooHPBrTLO&{qaR~J*ITAk$~+bF~piI)f(l;b3>Uiv3JTXs9M80>zm0d+id3?wW|j{&|}=-HDBw^>3Wgw^Oli~^6M zH=CfG_Emn5ey03B)_igu*AyoFH&bzce6g?h0ZZ_*0}7;l<{g<8gBov=iZ~s}jz44x z?(>HMk-jSPldtagc1Pfw&hJ@PKdp zR2BqD4dP6)?aY#v;tp%rXVW)5foY%w3hJiJ>PVs!1528KA~=Wzeio`{?cE<${h@_H z@>}|qxI5+}j)(K4nja!FC>k?*z>hu$0>~ZX!Z|PDY<}=HU$fVOpY{dvHRTW)4W%dw z1Hmdl1|2-F+=q77`3i_#p&9fkXQVeba59_#LyL?&6FjdY*`aDGib&>l$@ACir@M}(t3S}403|!41?PO1NaLR86c>Hcq9uc_qD5kl|m#>2S^jkTK(w+D}^37 zw<`=%sB`Sg2dkg@Q0YqJBAOIX`193%)Me=lt844+$pZ5)L57o{X#n}f|M^1y&XCuz z6p`$ZGWf&EJd%_c0izvQ;M*!44}Zf-81(DiJkEivguM(;^#26h?{c2Z7w)e>?5Ow%)wodWWg50cQua^`!V ztCwzIIYu55O8iSqZl0BP>j+(paafqWrXK0=vz*M01?*P)#XB-L*Fxnk15WC9q}CHa zUlUd3h~t)|?ksaulphM$S!~F5LeIs0vIqOib0?V`As1a%7Q87O1VSS!RU&|b zD_Hy6fcj>jiZ|?!E~2|2Ya)9I)|2?BZ-FLyj zpwBSuS5?K|Jzxvq>I-VaBbm1Aj}s-&xyWqYAx>_xEvQDVT&r>tetQqBA`X~AN zZ|W<>D^Smhylm|yDvRTD!@Wbt<5GKfevOQa{zjQpU)~85bYQTxAAUdJBh&r2Bv~W8ChHsLc1LZE>$wo_&u<~L zo`S9U^Lq-Fze@b*pTzVO+rD3c@z5O|BI%_ZMBicS$5{vbTFKxD>n)$ow%DDtzPngFhM5WT600|DUy0YUQhC+FW3 zJ8gnpnX9GiW>uJ!xVB!$+|Ee9MFw6OB}G^$9!J&LYbL<>$HoO z-fEjFYF+=>{NTMQ2cvg<34@|=d%pQ&yB^N=+94=GCqusGr+fH+-~I0=g^jHspk>O(`?C_vB<|MC z>m*NSbW{6Ogi`QQpK`Er9RZE>#U0C(IKOq+mNqhT8(5lG>jgK!~zPzDF-Mq7d+A6|2X2K=c6P zGj-PLim0l3BxC8pUHQmhM9Qqf@Ojr)P*uU*s{fH!nC9gZBN;sF94oq+Hu{kE|mVKr0-SYYD&sa;8xHv$|svPf4a3(OUws?-M-wSNVa=!(V%W>EEr`s}b7V z@x7T$z^-dA<6TS|ZuVo_8Z;FYICDWM1XP)I@!E>9hkSi$lp=ZV1Vu2lV+O-T(WjuC zggeRww3mo=BZ*Z!S(}N$lItRUu&e|{B6_br#k&<(iVSw!SVX=p;Q%Qf`73%9Y2kww zMj6j#);hIu$s9pCY-kSWu(WQ*3ZO7)+ zd!2TBOOIyiZHGR^d8aayBN6*gn~Pm}yl~2+-n+b8)Ercrv5z|IA<`S|wnow3#2!$0 z%zAb=&sK*kBsphG(b4ZLMJ7trXBgPLC-TL~4X$E{R$8}T=#)9`rwnvS)6%Cl#YpF9 zrM~0=e1f~(*J=CTKx}H5k~r3>^kbC zmT6rCh-Lqo&Ue;bl)Z20n8{W!n_@C$j9wD2KFPLec_0Y>r9UidT% zZPrVvr%fu8$0^3Z4RojIyl?uQc6GGuy{uU=n?r|eQ92*%2=x%hPv(FyF!=u3&NrTv zbFz)Ll-96R7mc_Eg3|4W`p7ZBT|zw&l<2b(s+vceJ;x<@-V1RPb{wvq74)W2m-0Hl zJx61te+A45)QO|gxH9i4fWL=Zv|7iX6jkH6XHOs%V(b~%N*1OQTnBHgqYdj}{jBG! z1VnUl|GmzBGsQW%0rFYj2a9&%#q}zstmoA{H_Y+8tBIfdK{>%@#F>lgDR$55n#TPN zR>Kr&*?Pzq}58 zlB@5T_UWXI7JMqd`qta9Fa6REsJf;sDV=N8VRr_)ub)1uxxFp>W~OjLA$6W@j(?#- zmhE!c6ktw}%kEfl>+l?TR8vFFAh5)##z7TpnPfs#+I2v~awcuOv2n8|{r0NOD^2|i z+_tYew=~yB@h+F-FAlBT8p4x|F>Q?xw_A=AN-D2EsG7c2zrHOvb&YkQ!pzkP-wRqK zEYImXFse(E2IobM=O3Q!9$d2>S(Y$i0dzIkpr!ejhU#(b5aZydD$gN!$3~6alzf%6 zP=A0fCQ6sI0LJ%6ID}9UF&;ROP2Xhj@jT1Wrv=qjr1FkekR0Vt!TZ)51quc+olC2< zX5&<>c2!gyO&@6QY-qZyD1MnLuBm+Q@x#q8)?^X}v#brOTqs4fU1m9*?|C_)T5)o^ zMD=WdoTT2B1?f{@!WFIB+n?H05#KqvTmpYoJT2nN?O8fZ!3?(3u~PTforSY@&PUm( z(yWSJJN{IZ$ZuD+Yxt1dey<4>-8&4?8_o4 zIXs)!@eP88SuDuxJT9r!6h%1Ie%&sgSnyh%v7c(FFl((SCsY^j$vPQh6lL1odsN3p z!pqBcev`~V!JIyDVH}(l*$VN48hlg!@ORCXp+1D!R<_#Om&d{Q;j`HZ$%~4bphY0K z4+&zU?Y9MPT+rqY=q(2xcwNg)!H*h6GIaOv`d>uQ+`-u&`p~&aw2^-Z$-eb9%$Hkx z?lFG5UA73x5#Dl(0Xy|^mQ!0iGA!Tg^q`VE>>;z{N$kU{D!)Ote(51h%Vh_Nq`6BJ zvL`{%8fP5xESX3r`ZMtG$#u?)4p8P{bb{8Q)22g*PrI)fewLRZInmYed`x;TH)~)i zDf~89-|B0V)#H;Kw(UHZ6>KE3n`hecryLPELj@yD)@z$y5xR#ys)@qhc9vyVSGt5Y z-GF7n!R^7a&g=j3}2yF6H`dfH!=>e((B)~Y!%>)o}v z=~P~`V|9}+gY>nhv}vV2)EK`3RT*S5(tlF(M5ZU#zFDQLaJwB+?nAgW>rT8r!o)@z zf9=VsYEO9RG4c48-6$`c^kx&5x?;jr7AU-5&CQq77rddT;klQte-DU4$m2zCHih^LVXsSeQN+Cd*#GOkeE4g(o#{{eY>Z`xwV4qVoy;POY6+Y zyAM&1Ir{&v9i{t;VN2)N=WaBURG9Eccx9sB(`$7Qh0IFq+gBIsW^(uu7wsO}6opli z`Z6K?=~LT$x$3at?Blu_xnYz{r&B-uQbE)h4DOmNtxfn#(9>0aJ7a9(%=HB}N4OvI z)4bO!+7)&+{sZmhwPbyeXqxaO?`<@sM;CGJZ^N(8ZLH!I+a7VpsDM z6OMjf@SOMg;LM`P@K6kWkej~R?80uY5AY=m6=m|<0yci-5-*k9+?!p#I=HA*GZKF5 zVg6>nfrEJMi`-e-ib;_3-2N0T)#dK6j$yD)Alo~8L&x@XI|w<3!S>V zZ|OR|ekNZ5`XS1)FbjWLkQx2_B1CZ{Lo+acK?A7s;4b6NO$X*KZVxI5J%6}WEKAu2hn_X#Z`+^I-f)Nf<#*`oW_qbq0f6B8%HK>cL_TETf zSBef@Ub*5dI zjpb5zHT6%&27{Qa3y0?fF=`{NjbZd3N@Q$P3ckWL(vQPDIJlnW3xWK`*-C_L8qd2A zuDjRy_{UaSjOX*cHVMYevBEj3&7H8B2VJMDs_6u@Z&6T;Ff}Z7$ zujT@OnE_oWR{ITicJ=U6U!I9Xawbvs+3xY?uE?;w)HsiuQK6zlO!~xl8TBPU7a~%% zsJzIog#~#Z71D!}^2+)7!N#_`IjS|FSvrM6$D9F0Dhhu^|4aDB5oIZ2C6N{ zCM&2@zqr@;h%3<(Eyx#C{chJ$*gMIGAq!=NHvILUv6^Z>7Ey>t4z+EyQFG zznM>4L7#*jrKDvOr;V987jc#Z?c2xjK$a6T)$05E)YHQMvz|sAriw&gPQ0thX_W%c zdc~{l;%-gxHAG%QQ762kM;qB zo;iyM%elg`&cwmQbMe2LMoG$V!`wSKvZ#mpwW5}W;ahR5zV74 zWWo&sVV=sG+JiC~>zfwHm-!XEFkKvS=YxSP1Ms`Q!EolA2`mIQqq(xCORbo?VViis zAX{MQ(i};fjGUnY&)Y)xEA5^>XVd%QY*1!Z3qH0mvb*+J*8ax~s}H=bS%yvpX6l~k zkeKaHt(S`pcbad*nW==LtVPlH1og4!U7KBlfNsd>Xih5}=`0KAedIM94bSo%b&oAZ zy2B<)T+1z2RNvoB^qgLDz$@e&R5_2VbhCG3`hqOBxxN=W$_(g`pFVp8%ZEH@`sN5s zUC@?vB|R9j)00vQ+ld%s;yP6@o6B;?PBwOK?`+;83}@hx8|Rw6st$JwEh#abO$$cZWLnvuKhLI5^G5Qua}TwKrlN;jOm)cmvxFPf$e-@{fqnaOXi7#39+ z-$fr%+6-87g2QD8JkQ%rKPHs9FnuX%E+;R5R&0o6s@BZk;UrSIPyOhk`j3w--po5e z$2c!wLE#tNOrs=tZR~nTMZdFmcW-2Fn|Ah~6hPw*tqzGP-l7`-qtI|8>Dlx*n9NC} zeVHYjrWOXj^LUmc+BWmITzX*=;516cxqguOrFqKVu%G7o$0rt%!cn7KpIVrnVBH$T zc@d6MekZ}pN8Vcwi`Zz;IUWYVXf<=J$vTw89{o!|7D^%3`f5OFe~ z@R9YH7oU$r{g#W}%G2EVsGTwI+jE`unN*u|(7|M!k@-qlZf#3l#{TyYEi&a2gj|L; zc84)^5Fg3~JDuXHL{9SfeY_{d5l=&tE!)4CmR1}vQrO<8E`LEV(ELp-Ys!7CQ+-fm znihZk++ZcwQ$L(6q^L#)5w5XMkSsdFQY^Tn>u=3E#ay(gqxjW~~3~Oq3LXWTZk#x{un))4? zodlq}{#JMDdm?^_3a&#_-rtq8l=Z;axcIZ(pb(WR81%8`A=A9(p)*gauH>yXh03@T zu!mVKsJ|*a9=gQ8so>-4E~Kv+qIko7#;c+#7=!CtrJlcTpSVa#-+92FW+UE*?L0#b z?7z;caSiQhbF zXf4W%QEN!JOr1^`8Ohg=wVMtuq}uJg$s{=l`WSr5IghGMe%C}lKge=E+q0tk@v;1O zLKY_u&GeI1PjJmtM8^jW#nD=}D)xuLN)~4aWWtE4Q&S>OZxYnzuIXxk&QAt zUQ-ME6_ z^TY#S&1%HhQr2z1Gpzh_9QF8F-ol!S#crq!u?TdBxd9u7`5~aj3F!_mJ>5d2cYiyg zZb9UFgANdM_(?v`Dk7qC3-?KrS=2?aNZecT{ZPbSqli~xtP-ZH`4iUMorw|3RcRZJ zm=;2Wf*0b(^(BkALab{hHfv$i@*6$3xdoY_zD04U7A52H9jnW0b3d966>8v%mTOYv z?%$qx&6+WpqE+~*X`DYgD#JkLGc(hO4#@m65f@Gl-+Iq=lg!nThXHi8nadw_7tu2` z-J{WnHym_1rd#iA26mo%-|cR4ItVaxU9vB$DEO(8sG$7;#&LVp@x(!90hdJbx`Y8; zl#A(!ap0QgQ)bBkMZ?V4R6Y}5^y1jUOBGQ@8^Q3xYIjca%(8W#JJVHNWFN~c z@ZStGf0zAu1?E>n<_mL(oca4TMei@5(L<<&W|tj4RBbaOG9k$1=N*x z0LkY+PxmA`gY};2En$v0zZ_*niHncwZ17A?zrW<#9QfvQaR^^a2%!5oE# zp|XXx(+!a@9hbgT-N>v24?k^Yy>&168R-FZ$x7P?`^&IF7LLJR7I@ITe>w|;me@v# zeB%*`P?=UfQE@Eh({%Dj77nFX8vw_#sP?xF_*au1^l{g|gQ+gu4A8h&|ir9VL#khC}}3;r5JjpcoBn_m2vryu}F z_5YtGGI~wmg`XUDCZ>elzY&#-A&4jVrEUX9aCZA;^Zi9^Ox1DC} z{{amGHOW_a*U3RPnZfuAc`-@$r9&HWa(L4G^!+q_oo9i9l?t=|llhcM;*Z`KAzTXR zoD81{n*L+PAzg&T&ykl!5RdZ#m3(%G{zcIz56>7H8urEjcMmY(AqF9-`wukq=2KGk zGycRakK8gx=WdzpV|_egjc0oDP`GUkfN)oI}pp)eBSpxB7(H8!MP;`*0jlq zK(`)@_yp)f7%7`X~Qg34y(vg>iDbg|{zV1L6ISm!;4q0D}n)C?~2!UWUDP z0($6aQ~uerfS#?$>mu=~3)2zde^3A8Kz6B<%{J5A{ow6yQ5EM^N&N8Viq>WfMFI@! z4(`&R)rG{d`HMx zJ>}!@IEhHI8v4baJUKznP1*}!C8AWmnvQop7SueB(QD!I{W;6>WG8&^0Zv97< z;_vyuN9MA-!XVZvtbs^7eQgOR?J; z2Uf)P_M6xqX0}6KnVn~zW{jL+%wn!G-iU@ql;1*J$m{aok*mJ(i06ta*89~TZJRr2 zQyl=F2O89aeiJL!!8TUTWmrSyJnZ!8{Ilq^REY4d4lqsBrKvr=(-g;^`kybm*fA-z zctG*IG&6F#q|eO^vNk3TFc88+zxW6TfbsojSFOPKau1I${_va+&10(0heL~Vv! z^8o7`akG5eJ4r7gYZD#;SsOm~t@&ws?3?GMOAo0l!qGWD;==xb3&3xdfoNz^Xa0US2U!4-06+JMsh|jMh&>861n8p-Eb$=pO;u|SMBR^x5aj>DqQiZ& zO(Dw5K*nQO-eWQg+;hng#xYaq#ajS;^7{g3QSAyIb5+2`Jgn_M+CdPF-(8QHj69$> zsSLnG%1WFN_aKz^$n^)4iZ-kp?FA-V*#!1&QD>sVhRQcRXqE0t0>R|IE5z!Y01=C# zhrAIEOI-hNoELO%5K$Eyp!NYw@jICozg&q(;V2&Pl*=BZY0@a(h89RGUn@UC{EBZU zdBL+-kvlg<@ko&}&9+GRbKdsXm$`OVeVo0v5;3&ZVPqFVUf4zS^$nI?pIf4LnC4t_ zHS975qza0IGOQ2~XM3l%m2rlDcR@rFfH64f?9t?$Kn@?~`?t9->VF>9iSOqM-n1dq zMknXVE7A+fYgaHuXA~zeNws$uERt$h?5BOtwky2S?o&qrCxd+8FlY{{?-_8M9dp5d{cVSSsYr-d)<{=9e_BY z4`cdUb*CmL=|L?+j|LJS0^}Ogx}Uggh_MhZ@Y?Q)e+lXCYY4?TaC3#}q@boP297tb zR6Be6&6UeWOkje2X>S~{TPbIW8iVD+>yyvSFGMSLfp0c*#km?sOdDX7*9U(Lpd73u ztDv2{O$Qjr*r6W5%{8`_u&ssY70yv|@JOC*V|UL$_H3LEFOn|-GlwFBs5|3FV4 zZyNyvCk(TJ%TXfN{qdh(3a`&)^2*7Ra_9D(W_@P*b94xsCtdLyWnLFu?Jl)mPlweZ zQ%cXS*Jw!WC2w>j62q@q9+nB7H>sVIhK1r$#FaV?M7j9-G)qvfC| z3bN=~!dD-xEt?1~^*0H7ZXk0XiftJxJd%5c5)^wd)9Sb=(@E9#;q_5^^fQk% zk8jN_g9n1glQBe|i8)sM+UMMllaI>l8miWQcuc-F3HRt+yhEpc_tv0Vzl3#FN(Rk} z4b67FDKpBP?m`qukPPWv=S}wj4NjYNz7sEBoTjok>5=v}`A>Q&5KBhTNmSWk zAl1hSvGCo4t7-?fgRo+2y}#0W-k(Y%nDEJ+);x*qTOF|V_a7!9PZzI}K5(3F&Rmzk z_6xRHRpSE@S&J@D|4jtJBfs<~PX-ZmQCk_{_>M_4IsSImOR?@4V#krc08xgOL?8d= zfTOQ>X4zD@ZcERxU@6`)Rl`vSuNbbDfnN5=3ZfysmZf^$qr`hN zMbsf3pJ04lSzF;7a};tbSmf|V?0~)o_xeYD-Qc-L<>kcZ1DwkIRY|VA94>o^U%`R? z;LO-ix7FQ0R&G))8LE*v)0Ch<^D_NJyyc6PIraox$?fHNe{T&TkI%_}b^y^}Cw`_Y zCuwgAP;CNIqF(Wi81*aql3&zS=Lu11KvUD&H#FW5sU%%0ke5x~T&SX85!a*fGY1r3 zRC_iP%?RsjusL>o^>UuA8QC4R@j09H-fww~bZjr+Z~V`ax7qWB7&p0YxU$@RFQ>Z_ zjIU=wmN*}UXGiwWKcVzw2oqnNCGRtYcbzJ}R8K5)`$P48E7`PizKwz-mj~V{h!qSR zvh^b-Y5-cjcS5Ye4p;fYbOl13PT#v1`iS>($?B^U*;_RQvf}%!7x+)iT6x#=H`}uq z1npNl@zVV}N9rDu=a2A)vW8Tfw)0axUe6S+^D>Y1W)5~L9R@O^A*pM|)@*D55fdYN z;hc{G#?5>`qUO?iw|NHnZFJYjFn*aMCBYpUdnof}DI-j-7$v^!J6%YYN(rh_B7QCZ zMUw3PH}(IM7vHXOucD#*DpqqXE>JB4Mr`xHAAjGHfkrJZD}9<)Pv#U%zIh;}0%h&D z23LOhVdojvcj-kM^~6tZKxpb7U@ZcM&D3M9jLvYi>%Ys%9Lj5hLO6^=KvH~4B@RCJ zqZM__MAj=!UlV<)Cf2=DDs(28@@^<-PG2_pNbN{@el0pvfP)B!{SY|%B|Y9E6DKU(8dkfHr?`*H@$Qvj{%oQ{h*U|<@Ye)jFtQN+HE5GTnVgVS#bA? za>&>VN_o3`>G)-mnD;(A3)wu`UI9->vpuo}P|Xqg*>@F`QpV}o#THgcGpBvNchHG= zSKYXy^~F~A>}?w69$k3snNxe}*uW_snMT7)uZ%1n`@0RHkfzoC-I}F$|9bey8;D79 z-PfOZa|IcpTs@jXN%j>;yfdMkoF^^rg~L=V>?*HKs`jwz2^xyk$n2gM@w?Y779Fac zi}YJW3hYfBeFMs-4qh+iLJjt-9C*E;0nAu|zMj{t0t@D8%akmlR7i}y4p?R*AhRwH z@f34RPE?o5t}kfpE?!)v*G0lpIAElWx#TQV2KsIGBEJfVy~F<}5v&g~y!0$sIOw6N z1vBzup|0qyU)OY6W8ZU~AIpgitlgq5jK5d_9q-aW%dAEILo=ZNsq$2hGFoj}P|o{{ z_NJZ8A>lXFHODQZTp1Kd>-9vVePZ@u_An#eP-=T*6;~e1p6>soD0cI6awLC7zyx8r!yg9z%Mt5WF$)fKc7G4`n0=qtw+l^G} zS|~~Ge32>PPN;9lUT)7X5l6>wjd%vuN}&8aLIOv)8t-eyiq6I;#N}^(ZCD8q_LzFRCrgA(aaLOf4KX1B5T6Jh z)TaOyzYM$yeQD-4N+iRHmfpR(mM>>%88V?noKP;XzZEiXvvR8L#JD@zPhtHlCVJ&< zkxr+h(-6=Ln@KvCQr(7Zx?J)nRV)Dc_`g?TFmT0>KRU5~w>NQb%rAE#=c|IfK2-hpOC~ zV;cj;B&@uw782gm-n#!lGQIt`q~vOVJ$in~Xg|(sFZOucCl|_SBjIp(oo^+g^xSey z;~?(&h#$bgx|au-Cj`-c{w((z82v8aNKJ|$7gjLL-#@~JP+=zZaqGZ>9<8cfCJaRJ zw(t3Y-s?PY_Z>9?HL;N*DA~2(aHqX{@hTEsk{oqiGDjFNGta$XgvHq?9_M z#*nWst;TnVf3xnWc^zA;;xR>ihmk4!{D)`6{SLC|2K9^*Uiem@Ae7uc8{&8B+ik-Y zkQ1HfeyY%N$4|sT~>4y6`=5g`$GYU%3*q-VPPw*K9dp=}{XIO>;!T4!)4H5|%(LJzXYvn{R0^mVy{%gv*{Yoo1>`PDs7`ZlG1yQ-F*5j_f`GL(bmz6^k&zjzD*cpx{lS(1YBAXAjQs^~?Vq8LuN zu`5&Net=CWmljv_G^b6C5$g6%%+2Z+;vAjt0qSMA8Kpi#SKRiVd2Qr(I;*;J;@bL) zGV!0cPjCbDtjPTZhhQeP6UTIFaGve*(>J|a6jmmxeLaiM-tq%)?0vi6lVe9&5H2XE zzYe&=4orSjFf<$*ovMRnP5Icu2quccx-Ns8aIhzR_%KIZIbx`-2unlvkZGRS`geJ_ z^L*z78M#|^^jh~mIa15O)U9TT+%gG&@eRL0V^8HZEl^LEs{&wXXiHQTop}1zdqut7 z65K@}x8XryXVKUry_;Jh+Vw_Ee;2&aM(3Wn#13w4d0irxyf|b0NlF9Qlrx(%YUOoz z$$i`@P_hdfR6c5%&u}(A;gFH_QSP^a-jG(9uDHVjhR=7ycu#~|t7x)%HF=dT?{^ zP9@ap@U>-_hVp75UO7fFJXmQy79LCLNC(e`NQ)_Rhw51e=HKBiPxnjyZBsIgDXKLw zMtb!hvb+rl4a>)r)DEiD^xS0wP6kZLK~Cl&diP^9D1s#GmWwHpm&)s+E8V3SdFj~1 z>^|j{2NuNFIn3=pO@T*%9a7ZVty@(c+CDZXw>epK$TDyL)lQ}+=`TB8LMeli2IfPH z*+j04p7}eSTXNtoI9+8{6?Y+KHcl-aMV#R}snr`ti3E)OUOddm>~n?sgI+3f0#$2| z2<0_Z3Z$F#$@7<9lx=i+b4J7mPil(fo$EZ5CFAr9l=nS?v<74$0=~z79r`E!bKKE| zE`U_FoE~S(pT|ID5zkw176gr@hx$g(OE~xBpR+ID@VXj~tWd~Bvke=`!}!jI%y7ZW-c$jsurnauoD0r45Hi*jQFjgDcj}pG zvAIt=A?r*tRAz4qhZ2z)A8K*`?oFMjsl z@>_8cwVs3Wfn^ww2Ob?<52G(Ug57Qw6yQ~CWW$(#8$}DONj~9xW5k|%6P^-@r>~Ohxd}fkWkLQFZt`02rP$$ zystB;V1d9<&c@lV&5Up-gV4J{X*bLIi*CaG7c!sn7(8Ut{5JoIyBgGH&nqHk8)`ea zb*gbpR~0wV>dI!aq!y$tONh833pOPYEI74DFKPYT(WFlYf8JpvKSBu(7h^gUrZNZg z&8qu1zZ&s7suDR|GXuJF%;Uwm%ufg1YYRJkJ-3_CxbxJeVzZM_O){W{Zlubs1^W%; zLX{uh#X{-bdX|fY5w*3R#jq8_2xZSX+x)241&lp_+UA9O4OZAeihuH?fVYt*hIc%P z_4bk&0A30$b1A;)J8cZKrz}h&VD454{Z-%cYYy>QG$?`NKC&G+fp8y8$$=sJUHt5~ zlB?#bJZ{QNH!`YbOA91M!9#HUYn@r-Uq~droCJIF2zE#y?`I@uQvWL(K6UV*dx2tx zGAL`=FU69V6M`rBodqXT%KKDY-^l0_-bJMjFjAl}Y3>xg&vg$)Slva8ZsT48DQbhf z{gEAH*+GxGZ0h?f&8?PIL0$JcZ45`>S&|yMa{`7*V9>%A#`ZjY`qg_4T^^H|5*F#X}Fc^}06n9QME7h1Y@r4$dMO+KTkFMuEERN43vPE(fX5rD!I zUTQo(SgyjlyB)Rq)I{+}@cOK4W5CQ(NQk3-KI%1h>ftQM2=wDmr+?*J3O#T@!FY4(J4XDf0fYIS_m*J>3+hVerM;s$ z@sqyhnI2Dyq6t~w{fGT%(L+5)gO@7JkF7|XC~*&dT+F(7V4tSIJ~agpF)IfVSs+}}0Atd_ zUnX4kLc!9&R#PyrDYeb5y+?y{yWhcX&j<>@2Xrkds=2GxS4t*_mdIi9md{rU?FHFW zN27w%pr*%ai=aL1#rV{ep$YH1vmK|McnjM&L7;SfXP+jc@>yrKL9?Y1S6m$Xtt_`R zX&4Oh)k3Eg>iGJknWyJX2?ghC`4+Da{pZMUFxSFxHrtVo$4xN1`m5kCy|2hxSSWIL zMkJ*XP&jjTyCyUVuyckYe@{0)BKBqu@B~i+$39QS?vpU9QcCuiYoU}{;!++DgoJ=1 zA^>qn|7cMTK`Iy-d`Y7;_JzO$fkFe;VJX&c8Y4jD%DYon;|4rBI8~v-&UhI_%&YrF zjBY83!pplHI-ygImLWxlcxli`{K(~{!(B>8QbNYNZ25Kk`l|Tpq{T%19g7!+fcveN?A46Tp3TTNn!c?d4fvVL7s_6F@q8A<``hSh) z30>D0dfXu|+;TI3mfH<$-K$~9I4g*&5fn6^w)P%Np@U$Y+1`a+0^uA;OZ4;!Hwp3Z z_3cYc;Y$eK6bTyEP}0&VHY|Q`PS^jbM(^0<>cBb zUE;(Mb_Rz_((!)`DukCkF#pX9&dAhz&Wl3^b+nW?sYMH=G=AQXkY^>v&W{%bazxl; z6#|gg+q<(@ z7n0_4*|r?rO#+h_!Vb@Bbs5Hopc;#8;oo1`F{b?AU@oqvDE+&XpW|eL;Y9f3o={HR zT+Q7I==oeMTdT`zj{kXoMct^r7zJ5ArM*C2=qO-v(r{c%vUW(}w36*49SPhFED8;? zcVmBP+?_v!iC(5+=Ob(YR4XBm464p@ER) zWcv52mDAC%>p~^zEu0$H7#HsjpyU9(=Tks`l==*6A0D zpiiuGiSwSMmzU&X+!s{WU7?{F{}j3^!M)c|s^&^l#pL36wE6P3UBQv4M|@*nf? z-<8e?T3$R_wbB81_O3DWjp%k&>hLBWUiK<%$djmc387W3xLobJ@Q%FY1Ru)`g&A`^~T26Zh{K7oXWY)V%tDmqCBo&fS7fNjLx z&qv8p0^HJWo$}y5UMyE_PCLCS=XlUP^UNhLc#7;+JAk1=FRSAY)c5SY;lRbP5pF{( zog^YG-ko);8$Or)Wg^+%*R*0RFIRarOv!?jx6&;uuxD#|X>Hkg`esYDoBhJgi7QYi zn-Q?IV2zIlNh$oP|26!8&H1TGeLp~0rZm=>w`!#bqT?VlSa1-e?azY9S-wz7$Cow_ z>VWa$Ljsm}=W;*Zsk7BD%71F-gK2bVDJPzsIig>0HQJU3)w>i|U^XN~U*2gEmq` z+ph!bVe6&6UAsXi;SM7FJ?LK=7wg)<^anBaI-uqVk0Q*;^QEBrEQk@h)$r}!t^`=x zDkI~J_;e7JKT_Oo{i3W8xKi^e9z<#7*6&EDZ}sqsIprb1smGoeMxYu*I^f!u;HzPgN&qjwrM@Oh(fg z9X@Q(J=0GC-uKG&3r0Ycd=QU!f_*?LZ!B28|3Q)q&)N9j&46-Lsqg1qpp+H5vb|p^ zjqxzS$=z2*g?)#x;)W5S$Q$1wKh9;oM(*F8;C$UZ=v2^m7x!)FbClM9UPsLf4=*y7i(_pGVW! zB$A~MetQ?~hI^qqt4K=b(bRf%);WTrbpkm2hV9br?~<$oR}3DYZ7N38h*MD#SV6;v zk⪙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 z%0D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

eWxqjS32AL3iKBq8=c>e-zj+ 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 HA13EtOFTXU literal 0 HcmV?d00001 diff --git a/caf_launchpad/documentation/variables.md b/caf_launchpad/documentation/variables.md new file mode 100644 index 000000000..ce3e5b190 --- /dev/null +++ b/caf_launchpad/documentation/variables.md @@ -0,0 +1,41 @@ +# Variables of the landing zone launchpad + +The launchpad landing zone leverage object variables to provide better understanding of the variables to set in the configuration files. + +## launchpad_mode + +There are two launchpad versions that can be deployed in an Azure subscription. When set to launchpad_light it not impersonating the rover to the launchpad aad application and keep the execution under the logged-in user. It is designed to provide a way to experience the landing zone when the logged-in user has limited privileges in the Azure AD tenant. + +| Variable | Default | Allowed value | Type | Example | +|---|---|---|---|---| +| launchpad_mode | "launchpad_light" | ["launchpad_light", "launchpad"] | string | | + +## level + +| Variable | Description | +|---|---| +| level | The Cloud Adoption Framework for the Terraform Edition proposes to group landing zones into different levels to group per function and more importantly to secure the levels and prevent a level to access to an un-authorized level. More details on this link | + + +"level0" | ["level0", "level1", "level2", "level3", "level4"] | string | | + +## global_settings + +| Variable | Description | +|---|---| +| global_settings | The global_settings is an object containing the default settings the landing zones from a higher level can hinerit. | + +| Default | +|---| +```hcl +default = { + default_location = "southeastasia" + prefix = null +} +``` +### Attributes + +| Attribute | Allowed values +|---| +* prefix is not set or null it generates a random 4 alpha char +* prefix = "" disable the prefix in the naming conventions diff --git a/caf_launchpad/dynamic_secrets.tf b/caf_launchpad/dynamic_secrets.tf new file mode 100644 index 000000000..3b78eb1c8 --- /dev/null +++ b/caf_launchpad/dynamic_secrets.tf @@ -0,0 +1,10 @@ + +module "dynamic_keyvault_secrets" { + source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=5.3.0_preview" + + for_each = try(var.dynamic_keyvault_secrets, {}) + + settings = each.value + keyvault = module.launchpad.keyvaults[each.key] + objects = module.launchpad +} diff --git a/caf_launchpad/landingzone.tf b/caf_launchpad/landingzone.tf new file mode 100644 index 000000000..fe36988d8 --- /dev/null +++ b/caf_launchpad/landingzone.tf @@ -0,0 +1,53 @@ +module "launchpad" { + source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git?ref=5.3.0_preview" + + azuread_api_permissions = var.azuread_api_permissions + azuread_apps = var.azuread_apps + azuread_groups = var.azuread_groups + azuread_roles = var.azuread_roles + azuread_users = var.azuread_users + current_landingzone_key = var.landingzone.key + custom_role_definitions = var.custom_role_definitions + enable = var.enable + event_hub_namespaces = var.event_hub_namespaces + global_settings = local.global_settings + keyvault_access_policies = var.keyvault_access_policies + keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps + keyvaults = var.keyvaults + log_analytics = var.log_analytics + logged_aad_app_objectId = var.logged_aad_app_objectId + logged_user_objectId = var.logged_user_objectId + managed_identities = var.managed_identities + resource_groups = var.resource_groups + role_mapping = var.role_mapping + storage_accounts = var.storage_accounts + subscriptions = var.subscriptions + tags = local.tags + tenant_id = var.tenant_id + user_type = var.user_type + + diagnostics = { + diagnostics_definition = try(var.diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = try(var.diagnostics.diagnostics_destinations, var.diagnostics_destinations) + diagnostic_event_hub_namespaces = try(var.diagnostics.diagnostic_event_hub_namespaces, var.diagnostic_event_hub_namespaces) + diagnostic_log_analytics = try(var.diagnostics.diagnostic_log_analytics, var.diagnostic_log_analytics) + diagnostic_storage_accounts = try(var.diagnostics.diagnostic_storage_accounts, var.diagnostic_storage_accounts) + } + + compute = { + virtual_machines = try(var.compute.virtual_machines, var.virtual_machines) + bastion_hosts = try(var.compute.bastion_hosts, var.bastion_hosts) + } + + networking = { + vnets = try(var.networking.vnets, var.vnets) + network_security_group_definition = try(var.networking.network_security_group_definition, var.network_security_group_definition) + public_ip_addresses = try(var.networking.public_ip_addresses, var.public_ip_addresses) + azurerm_routes = try(var.networking.azurerm_routes, var.azurerm_routes) + route_tables = try(var.networking.route_tables, var.route_tables) + } + + security = { + keyvault_keys = var.keyvault_keys + } +} diff --git a/caf_launchpad/main.tf b/caf_launchpad/main.tf new file mode 100644 index 000000000..2c52ea02b --- /dev/null +++ b/caf_launchpad/main.tf @@ -0,0 +1,88 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.50" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.4.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + tls = { + source = "hashicorp/tls" + version = "~> 2.2.0" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "~> 1.2.0" + } + } + required_version = ">= 0.13" +} + + +provider "azurerm" { + features {} +} + +resource "random_string" "prefix" { + count = var.prefix == null ? 1 : 0 + length = 4 + special = false + upper = false + number = false +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = { + default_region = var.default_region + environment = var.environment + inherit_tags = var.inherit_tags + passthrough = var.passthrough + prefix = var.prefix + prefixes = var.prefix == "" ? null : [try(random_string.prefix.0.result, var.prefix)] + prefix_with_hyphen = var.prefix == "" ? null : format("%s", try(random_string.prefix.0.result, var.prefix)) + random_length = var.random_length + regions = var.regions + tags = var.tags + use_slug = var.use_slug + } + + tfstates = map( + var.landingzone.key, + local.backend[var.landingzone.backend_type] + ) + + backend = { + azurerm = { + storage_account_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].name + container_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].containers["tfstate"].name + resource_group_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].resource_group_name + key = var.tf_name + level = var.landingzone.level + tenant_id = data.azurerm_client_config.current.tenant_id + subscription_id = data.azurerm_client_config.current.subscription_id + } + } + +} + +data "azurerm_client_config" "current" {} \ No newline at end of file diff --git a/caf_launchpad/output.tf b/caf_launchpad/output.tf new file mode 100644 index 000000000..313425b12 --- /dev/null +++ b/caf_launchpad/output.tf @@ -0,0 +1,16 @@ + +output "objects" { + value = tomap( + { (var.landingzone.key) = { + for key, value in module.launchpad : key => value + if try(value, {}) != {} + } + } + ) + sensitive = true +} + +output "tfstates" { + value = local.tfstates + sensitive = true +} diff --git a/caf_launchpad/readme.md b/caf_launchpad/readme.md new file mode 100644 index 000000000..9bc5aa947 --- /dev/null +++ b/caf_launchpad/readme.md @@ -0,0 +1,206 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Launchpad + +The launchpad allows you to manage the foundations of landing zone environments by: + +* Securing remote Terraform state storage for multiple subscriptions. +* Managing the transition from manual to automated environments. +* Bring up the DevOps foundations using Azure DevOps, Terraform Cloud and GitHub actions (more to come). + +Launchpad operates at **level 0**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +
+ +## Getting started with launchpad + +Depending on what you are trying to achieve, we provide you with different levels of launchpads to cover different scenario: + +| level | scenario | supported environments | +|-----------------------|------------------------------------------------------------------------------------------------------------------|--------------------------------------------| +| [100](./scenario/100) | Start with this one! basic functionalities and features, no RBAC or security hardening - for demo and simple POC | working on AIRS subscriptions | +| [200](./scenario/200) | intermediate functionalities includes diagnostics features | may not work in AIRS, need AAD permissions | +| [300](./scenario/300) | advanced functionalities, includes RBAC features | not working in AIRS, need AAD permissions | +| [400](./scenario/400) | advanced functionalities, includes RBAC features and security hardening | not working in AIRS, need AAD permissions | + +You can pick your scenario and use one of the following commands: + +```bash +# Simple scenario for learning and demonstration +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \ + -parallelism=30 \ + -a apply + +# Advanced scenario - Requires Azure AD privileges +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ + -parallelism=30 \ + -a apply + +# If the tfstates are stored in a different subscription you need to execute the following command +rover -lz /tf/caf/landingzones/caf_launchpad \ + -tfstate_subscription_id \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ + -parallelism=30 \ + -a apply +``` + +
+ +## Overview of launchpad initialization + +![Launchpad Worklow](./documentation/img/launchpad_workflow.png) + +The rover executed in launchpad mode performs the following option to bootstrap your environment: + +1. **Initialize a terraform state**: + * The launchpad tries to retrieve an existing terraform state on Azure using the name of the tfstate file and the name of the workspace (level0 by default) + * Creates a tfstates folder if no remote state have been retrieved, this happens when your environment does not contain a storage account containing a tfstate matching the input parameters + + The Launchpad deployment relies on the following providers: + + * hashicorp/azurerm + * hashicorp/azuread + * hashicorp/random + * aztfmod/azurecaf + * hashicorp/null + + The latest version of the Launchpad relies on the new capabilities of **Terraform 0.13** + +2. **Call Terraform init**: + + * The launchpad then call terraform init to retrieve the provides and modules associated with the deployment + +3. **Call terraform apply**: + * deploy the resources as specified in the launchpad configuration files (see description below) + +```bash +Outputs: + +aad_apps = +azure_subscriptions = +diagnostics_map = +github_token_keyvault = +global_settings = +keyvaults = +log_analytics = +networking = +resource_groups = +``` + +4. **Create a workspace to host the local tfsate** - the launchpad will create two containers in the newly created storage account (in step 3): + * "sandpit" workspace + * "level0" (by default) workspace + +5. **Upload the launchpad state (tfstate) to the storage level0 workspace** - the state contains the default settings, keyvault id, and service principal id created during the launchpad deployment + +```bash +Moving launchpad to the cloud + - storage_account_name: storageaccname + - resource_group: hrjx-rg-launchpad-tfstates-rVb7GtKPXxHMa + - storage_key: retrieved +{ + "etag": "\"0x8D833A974C32C5F\"", + "lastModified": "2020-07-29T10:23:37+00:00" +} +``` + +
+ +## Launchpad architecture + +Each resource deployed with the launchpad is leveraging the [azurecaf provider](https://github.com/aztfmod/terraform-provider-azurecaf) to enforce naming convention. + +The launchpad deploys the following Azure components: + +1. Resource groups - By default the launchpad light auto variables will create three resources groups : launchpad-tfstates to host a the tfstate storage account, launchpad-security to host a keyvault, launchpad-devops-agents to host deployment agents should you choose to deploy VMs to automate subsequent deployment using Azure DevOps or GitHub + +2. Storage Accounts - a storage account in the launchpad-tfstates reosource group. The storage account contains the tfstate of the launchpad deployment and will be automatically configured as the Terraform remote backend when deploying landing zones with the rover + +3. KeyVaults - a keyvault resource to store with Get,List,Set,Delete access to for the logged in user (using the Azure CLI) - the keyvault will contain secrets of service principal accounts and managed identities + +4. A Log Analytics workspace and a KeyVault analytics solution deployed in the launchpad-devops-agent resource group. The Log Analytics workspace will gather the monitoring information and logs of both the DevOps agents and of the Keyvault + +5. Diagnostic settings - Creates Storage Account and Event Hubs (optional) to be used for diagnostics and operations logs. The resources are created in the launchpad-devops-agent resource group + +6. Virtual Network: The Launchpad can create Virtual Networks and subnets to deploy additional workloads during the bootstrap process - typically CI/CD agents + +7. Azure Active Directory Applications and role assignment + + This a critical aspect of the launchpad bootstrap process. The deployment creates an Azure AD Application named "caf_launchpad_level0" by default. The launchpad can be configured to create additional Azure AD Applications + + * The user deploying the launchpad is set to be the application owner + * A Service Principal + random password is created for each Application - the data is then stored in the referenced keyvault as multiple secrets + * Resource Access is assigned based on the aad_api_permissions object + * Each application can be assigned one or multiple Azure AD roles through the aad_roles object - empty by default + + By default the underlying service principal will be granted **owner** access to the subscription targeted by the launchpad deployment. This Azure AD Application + Service Principal will be used in subsequent deployments using the Rover. + + API permissions and admin consent are also granted during the bootstrap process. The grant_consent.sh scripts is called for to enable API access for a given Application + * The variable `aad_api_permissions` object can contains multiple entries + * each key references one of the Application defined in the `aad_apps` variable. The content of each entry is an api permission definition. + + The objectId, ApplicationId, ServicePrincipalID, client_secret are each stored in a keyvault using the secret_prefix value as defined in the code example + + The example below shows an App Definition, a role assignment and an API permission assignment. using three terraform variables with define an app called "caf_launchpad_github_terraformdev_github-integration-landingzones", we assign the Application Developer role to this application, finally we grand admin consent to the Active Directory Graph APIs. + + ```terraform + aad_apps = { + azure_caf-terraform-landingzones = { + application_name = "caf_launchpad_github_terraformdev_github-integration-landingzones" + password_expire_in_days = 60 + tenant_name = "terraformdev.onmicrosoft.com" + keyvault = { + keyvault_key = "launchpad" + secret_prefix = "caf-launchpad-github-terraformdev-github-integration-landingzones" + } + } + } + aad_roles = { + azure_caf-terraform-landingzones = { + roles = [ + "Application Developer" + ] + } + } + + aad_api_permissions = { + azure_caf-terraform-landingzones = { + active_directory_graph = { + resource_app_id = "00000002-0000-0000-c000-000000000000" + resource_access = { + active_directory_graph_resource_access_id_Application_ReadWrite_OwnedBy = { + id = "824c81eb-e3f8-4ee6-8f6d-de7f50d565b7" + type = "Role" + } + active_directory_graph_resource_access_id_Directory_ReadWrite_All = { + id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175" + type = "Role" + } + } + } + } + } + ``` + + The Azure Active Directory Application creation, Role assignment and Admin Consent delegation plays a critical role in the launchpad bootstrapping process. Make sure to work with your Tenant administrators to define the scope and the roles assigned the Application created by the launchpad. + +8. Release Agents (Optional): + * Deploys Virtual machines in the targeted Virtual Network. You may choose to leverage an existing Azure DevOps organization and deploy CI/CD agents and pipelines. The Agents will then be in charge of subsequent rover deployments to automate the IaC provisioning with Terraform + +## Launchpad add-ons + +Add-ons are additional capabilities to enhance the launchpad, that are deployed separately and managed by a different state. + +Current add-ons: + +* Azure DevOps Self Hosted Agents and Pipeline + +In-development add-ons: + +* Terrform Cloud Enterprise +* GitHub Actions diff --git a/caf_launchpad/scenario/100/README.md b/caf_launchpad/scenario/100/README.md new file mode 100644 index 000000000..dfa8197a7 --- /dev/null +++ b/caf_launchpad/scenario/100/README.md @@ -0,0 +1,44 @@ +# Launchpad - scenario 100 + +The 100 scenario is designed to demonstrate a basic functional foundations to store Terraform state on Azure storage and use it centrally. +The focus of this scenario is to be able to deploy a basic launchpad from a remote machine and use the portal to review the settings in a non-constrained environment. +For example in this scenario you can go to the Key Vaults and view the secrets from the portal, a feature that is disabled in the 300+ scenarios. +We recommend using the 100 scenario for demonstration purposes. + +An estimated time of 5 minutes is required to deploy this scenario. + +## Pre-requisites + +This scenario require the following privileges: + +| Component | Privileges | +|--------------------|--------------------| +| Active Directory | None | +| Azure subscription | Subscription owner | + +## Deployment + +```bash +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad -var-folder \ + /tf/caf/landingzones/caf_launchpad/scenario/100 \ + -a apply + +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \ + -a destroy +``` + +## Architecture diagram +![Launchpad 100](../../documentation/img/launchpad-100.PNG) + +## Services deployed in this scenario + +| Component | Purpose | +|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Resource group | Multiple resource groups are created to isolate the services. | +| Storage account | A storage account for remote tfstate management is provided for each level of the framework. Additional storage accounts are created for diagnostic logs. | +| Key Vault | The launchpad Key Vault hosts all secrets required by the rover to access the remote states, the Key Vault policies are created allowing the logged-in user to see secrets created and stored. | +| Virtual network | To secure the communication between the services a dedicated virtual network is deployed with a gateway subnet, bastion service, jumpbox and azure devops release agents. Service endpoints is enabled but not configured. | +| Azure AD Applications | An Azure AD application is created. This account is mainly use to bootstrap the services during the initialization. It is also considered as a breakglass account for the launchpad landing zones | diff --git a/caf_launchpad/scenario/100/configuration.tfvars b/caf_launchpad/scenario/100/configuration.tfvars new file mode 100644 index 000000000..ad53a6ba0 --- /dev/null +++ b/caf_launchpad/scenario/100/configuration.tfvars @@ -0,0 +1,68 @@ +landingzone = { + backend_type = "azurerm" + level = "level0" + key = "launchpad" +} + + +# Default region. When not set to a resource it will use that value +default_region = "region1" + +# naming convention settings +# for more settings on naming convention, please refer to the provider documentation: https://github.com/aztfmod/terraform-provider-azurecaf +# +# passthrough means the default CAF naming convention is not applied and you are responsible +# of the unicity of the names you are giving. the CAF provider will clear out +# passthrough = false +# adds random chars at the end of the names produced by the provider +# random_length = 3 + +# Inherit_tags defines if a resource will inherit it's resource group tags +inherit_tags = true + +regions = { + region1 = "southeastasia" + region2 = "eastasia" +} + +launchpad_key_names = { + azuread_app = "caf_launchpad_level0" + keyvault_client_secret = "aadapp-caf-launchpad-level0" + tfstates = [ + "level0", + ] +} + +resource_groups = { + level0 = { + name = "launchpad-level0" + tags = { + level = "level0" + } + } + level1 = { + name = "launchpad-level1" + tags = { + level = "level1" + } + } + level2 = { + name = "launchpad-level2" + tags = { + level = "level2" + } + } + level3 = { + name = "launchpad-level3" + tags = { + level = "level3" + } + } + level4 = { + name = "launchpad-level4" + tags = { + level = "level4" + } + } +} + diff --git a/caf_launchpad/scenario/100/dynamic_secrets.tfvars b/caf_launchpad/scenario/100/dynamic_secrets.tfvars new file mode 100644 index 000000000..23a0258d4 --- /dev/null +++ b/caf_launchpad/scenario/100/dynamic_secrets.tfvars @@ -0,0 +1,114 @@ + +# Store output attributes into keyvault secret +# Those values are used by the rover to connect the current remote state and +# identity the lower level +dynamic_keyvault_secrets = { + level0 = { + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level1 = { + lower_stg = { + output_key = "storage_accounts" + resource_key = "level0" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level0" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level2 = { + lower_stg = { + output_key = "storage_accounts" + resource_key = "level1" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level1" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level3 = { + lower_stg = { + output_key = "storage_accounts" + resource_key = "level2" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level2" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level4 = { + lower_stg = { + output_key = "storage_accounts" + resource_key = "level3" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level3" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } +} \ No newline at end of file diff --git a/caf_launchpad/scenario/100/iam_role_mapping.tfvars b/caf_launchpad/scenario/100/iam_role_mapping.tfvars new file mode 100644 index 000000000..87a218b80 --- /dev/null +++ b/caf_launchpad/scenario/100/iam_role_mapping.tfvars @@ -0,0 +1,47 @@ + +# +# Services supported: subscriptions, storage accounts and resource groups +# Can assign roles to: AD groups, AD object ID, AD applications, Managed identities +# +role_mapping = { + built_in_role_mapping = { + storage_accounts = { + level0 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + level1 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + level2 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + level3 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + level4 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + } + } + } + } + +} diff --git a/caf_launchpad/scenario/100/keyvaults.tfvars b/caf_launchpad/scenario/100/keyvaults.tfvars new file mode 100644 index 000000000..00de22b41 --- /dev/null +++ b/caf_launchpad/scenario/100/keyvaults.tfvars @@ -0,0 +1,99 @@ + +keyvaults = { + level0 = { + name = "level0" + resource_group_key = "level0" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level0" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + } + + level1 = { + name = "level1" + resource_group_key = "level1" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level1" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } + + level2 = { + name = "level2" + resource_group_key = "level2" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level2" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + } + + level3 = { + name = "level3" + resource_group_key = "level3" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level3" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } + + level4 = { + name = "level4" + resource_group_key = "level4" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level4" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} diff --git a/caf_launchpad/scenario/100/storage_accounts.tfvars b/caf_launchpad/scenario/100/storage_accounts.tfvars new file mode 100644 index 000000000..bb2834b9c --- /dev/null +++ b/caf_launchpad/scenario/100/storage_accounts.tfvars @@ -0,0 +1,102 @@ + +storage_accounts = { + level0 = { + name = "level0" + resource_group_key = "level0" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + ## Those tags must never be changed after being set as they are used by the rover to locate the launchpad and the tfstates. + # Only adjust the environment value at creation time + tfstate = "level0" + environment = "sandpit" + launchpad = "launchpad" + ## + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + + level1 = { + name = "level1" + resource_group_key = "level1" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level1" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level2 = { + name = "level2" + resource_group_key = "level2" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level2" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level3 = { + name = "level3" + resource_group_key = "level3" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level3" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level4 = { + name = "level4" + resource_group_key = "level4" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level4" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + + } + +} \ No newline at end of file diff --git a/caf_launchpad/scenario/200/compute.tfvars b/caf_launchpad/scenario/200/compute.tfvars new file mode 100644 index 000000000..88164c5a4 --- /dev/null +++ b/caf_launchpad/scenario/200/compute.tfvars @@ -0,0 +1,100 @@ +################################################## +# +# Compute resources +# +################################################## + +bastion_hosts = { + launchpad_host = { + name = "bastion" + resource_group_key = "bastion_launchpad" + vnet_key = "devops_region1" + subnet_key = "AzureBastionSubnet" + public_ip_key = "bastion_host_rg1" + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "bastion_host" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + } +} + +# Virtual machines +virtual_machines = { + + # Configuration to deploy a bastion host linux virtual machine + bastion_host = { + resource_group_key = "bastion_launchpad" + region = "region1" + boot_diagnostics_storage_account_key = "bootdiag_region1" + provision_vm_agent = true + + os_type = "linux" + + # the auto-generated ssh key in keyvault secret. Secret name being {VM name}-ssh-public and {VM name}-ssh-private + keyvault_key = "secrets" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + vnet_key = "devops_region1" + subnet_key = "jumpbox" + name = "0" + enable_ip_forwarding = false + internal_dns_name_label = "nic0" + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "network_interface_card" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + } + + virtual_machine_settings = { + linux = { + name = "bastion" + size = "Standard_F2" + admin_username = "adminuser" + disable_password_authentication = true + custom_data = "scripts/cloud-init-install-rover-tools.config" + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "bastion-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference = { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "18.04-LTS" + version = "latest" + } + + identity = { + type = "UserAssigned" + managed_identity_keys = [ + "level0", "level1", "level2", "level3", "level4" + ] + } + + } + } + + } +} + diff --git a/caf_launchpad/scenario/200/configuration.tfvars b/caf_launchpad/scenario/200/configuration.tfvars new file mode 100644 index 000000000..36645019e --- /dev/null +++ b/caf_launchpad/scenario/200/configuration.tfvars @@ -0,0 +1,100 @@ +landingzone = { + backend_type = "azurerm" + level = "level0" + key = "launchpad" +} + +enable = { + bastion_hosts = false + virtual_machines = false +} + +# Default region. When not set to a resource it will use that value +default_region = "region1" + +regions = { + region1 = "southeastasia" + region2 = "eastasia" +} + +# core tags to be applied accross this landing zone +tags = { + owner = "CAF" + deploymentType = "Terraform" + costCenter = "0" + BusinessUnit = "SHARED" + DR = "NON-DR-ENABLED" +} + +# naming convention settings +# for more settings on naming convention, please refer to the provider documentation: https://github.com/aztfmod/terraform-provider-azurecaf +# +# passthrough means the default CAF naming convention is not applied and you are responsible +# of the unicity of the names you are giving. the CAF provider will clear out +# passthrough = false +# adds random chars at the end of the names produced by the provider +# random_length = 3 + +# all resources deployed will inherit tags from the parent resource group +inherit_tags = true + +launchpad_key_names = { + azuread_app = "caf_launchpad_level0" + keyvault_client_secret = "aadapp-caf-launchpad-level0" + tfstates = [ + "level0", + "level1", + "level2", + "level3", + "level4" + ] +} + +resource_groups = { + level0 = { + name = "launchpad-level0" + tags = { + level = "level0" + } + } + level1 = { + name = "launchpad-level1" + tags = { + level = "level1" + } + } + level2 = { + name = "launchpad-level2" + tags = { + level = "level2" + } + } + level3 = { + name = "launchpad-level3" + tags = { + level = "level3" + } + } + level4 = { + name = "launchpad-level4" + tags = { + level = "level4" + } + } + security = { + name = "launchpad-security" + } + networking = { + name = "launchpad-networking" + } + ops = { + name = "operations" + } + siem = { + name = "siem-logs" + } + bastion_launchpad = { + name = "launchpad-bastion" + } +} + diff --git a/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars b/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars new file mode 100644 index 000000000..75c3e3e90 --- /dev/null +++ b/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars @@ -0,0 +1,20 @@ + +# Event hub diagnostics +diagnostic_event_hub_namespaces = { + central_logs_region1 = { + name = "logs" + resource_group_key = "ops" + sku = "Standard" + region = "region1" + + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "event_hub_namespace" + destination_type = "storage" + destination_key = "all_regions" + } + } + } +} + + diff --git a/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars b/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars new file mode 100644 index 000000000..fd2cb048f --- /dev/null +++ b/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars @@ -0,0 +1,48 @@ +# +# Define the settings for log analytics workspace and solution map +# +diagnostic_log_analytics = { + central_logs_region1 = { + region = "region1" + name = "logs" + resource_group_key = "ops" + # you can setup up to 5 key + diagnostic_profiles = { + central_logs_region1 = { + definition_key = "log_analytics" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + solutions_maps = { + NetworkMonitoring = { + "publisher" = "Microsoft" + "product" = "OMSGallery/NetworkMonitoring" + }, + ADAssessment = { + "publisher" = "Microsoft" + "product" = "OMSGallery/ADAssessment" + }, + ADReplication = { + "publisher" = "Microsoft" + "product" = "OMSGallery/ADReplication" + }, + AgentHealthAssessment = { + "publisher" = "Microsoft" + "product" = "OMSGallery/AgentHealthAssessment" + }, + DnsAnalytics = { + "publisher" = "Microsoft" + "product" = "OMSGallery/DnsAnalytics" + }, + ContainerInsights = { + "publisher" = "Microsoft" + "product" = "OMSGallery/ContainerInsights" + }, + KeyVaultAnalytics = { + "publisher" = "Microsoft" + "product" = "OMSGallery/KeyVaultAnalytics" + } + } + } +} diff --git a/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars b/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars new file mode 100644 index 000000000..a58c5eee8 --- /dev/null +++ b/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars @@ -0,0 +1,64 @@ +# Defines different repositories for the diagnostics logs +# Storage accounts, log analytics, event hubs + +diagnostic_storage_accounts = { + # Stores diagnostic logging for region1 + diaglogs_region1 = { + name = "diaglogsrg1" + region = "region1" + resource_group_key = "ops" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores diagnostic logging for region2 + diaglogs_region2 = { + name = "diaglogrg2" + region = "region2" + resource_group_key = "ops" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores security logs for siem default region" + diagsiem_region1 = { + name = "siemsg1" + resource_group_key = "siem" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores diagnostic logging for region2 + diagsiem_region2 = { + name = "siemrg2" + region = "region2" + resource_group_key = "siem" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores boot diagnostic for region1 + bootdiag_region1 = { + name = "bootrg1" + region = "region1" + resource_group_key = "ops" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } + # Stores boot diagnostic for region2 + bootdiag_region2 = { + name = "bootrg2" + region = "region2" + resource_group_key = "ops" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } +} \ No newline at end of file diff --git a/caf_launchpad/scenario/200/diagnostics_definition.tfvars b/caf_launchpad/scenario/200/diagnostics_definition.tfvars new file mode 100644 index 000000000..10a20c4dd --- /dev/null +++ b/caf_launchpad/scenario/200/diagnostics_definition.tfvars @@ -0,0 +1,274 @@ + +# +# Define a set of settings for the various type of Azure resources +# + +diagnostics_definition = { + log_analytics = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["Audit", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + default_all = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AuditEvent", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + bastion_host = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["BastionAuditLogs", true, false, 7], + ] + } + + } + + networking_all = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["VMProtectionAlerts", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + public_ip_address = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["DDoSProtectionNotifications", true, false, 7], + ["DDoSMitigationFlowLogs", true, false, 7], + ["DDoSMitigationReports", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + network_security_group = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["NetworkSecurityGroupEvent", true, false, 7], + ["NetworkSecurityGroupRuleCounter", true, false, 7], + ] + } + + } + + network_interface_card = { + name = "operational_logs_and_metrics" + categories = { + # log = [ + # # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + # ["AuditEvent", true, false, 7], + # ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + azure_container_registry = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["ContainerRegistryRepositoryEvents", true, false, 7], + ["ContainerRegistryLoginEvents", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + } + + azure_kubernetes_cluster = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["kube-apiserver", true, false, 7], + ["kube-audit", true, false, 7], + ["kube-audit-admin", true, false, 7], + ["kube-controller-manager", true, false, 7], + ["kube-scheduler", true, false, 7], + ["cluster-autoscaler", true, false, 7], + ["guard", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + } + + azure_site_recovery = { + name = "operational_logs_and_metrics" + log_analytics_destination_type = "Dedicated" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AzureBackupReport", true, true, 7], + ["CoreAzureBackup", true, true, 7], + ["AddonAzureBackupAlerts", true, true, 7], + ["AddonAzureBackupJobs", true, true, 7], + ["AddonAzureBackupPolicy", true, true, 7], + ["AddonAzureBackupProtectedInstance", true, true, 7], + ["AddonAzureBackupStorage", true, true, 7], + ["AzureSiteRecoveryJobs", true, true, 7], + ["AzureSiteRecoveryEvents", true, true, 7], + ["AzureSiteRecoveryReplicatedItems", true, true, 7], + ["AzureSiteRecoveryReplicationStats", true, true, 7], + ["AzureSiteRecoveryRecoveryPoints", true, true, 7], + ["AzureSiteRecoveryReplicationDataUploadRate", true, true, 7], + ["AzureSiteRecoveryProtectedDiskDataChurn", true, true, 30], + ] + metric = [ + #["AllMetrics", 60, True], + ] + } + + } + + azure_automation = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["JobLogs", true, true, 30], + ["JobStreams", true, true, 30], + ["DscNodeStatus", true, true, 30], + ] + metric = [ + # ["Category name", "Metric Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, true, 30], + ] + } + + } + + event_hub_namespace = { + name = "operational_logs_and_metrics" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["ArchiveLogs", true, false, 7], + ["OperationalLogs", true, false, 7], + ["AutoScaleLogs", true, false, 7], + ["KafkaCoordinatorLogs", true, false, 7], + ["KafkaUserErrorLogs", true, false, 7], + ["EventHubVNetConnectionEvent", true, false, 7], + ["CustomerManagedKeyUserLogs", true, false, 7], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", true, false, 7], + ] + } + + } + + compliance_all = { + name = "compliance_logs" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AuditEvent", true, true, 365], + ] + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", false, false, 7], + ] + } + + } + + siem_all = { + name = "siem" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AuditEvent", true, true, 0], + ] + + metric = [ + #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] + ["AllMetrics", false, false, 0], + ] + } + + } + + subscription_operations = { + name = "subscription_operations" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)"] + ["Administrative", true], + ["Security", true], + ["ServiceHealth", true], + ["Alert", true], + ["Policy", true], + ["Autoscale", true], + ["ResourceHealth", true], + ["Recommendation", true], + ] + } + } + + subscription_siem = { + name = "activity_logs_for_siem" + categories = { + log = [ + # ["Category name", "Diagnostics Enabled(true/false)"] + ["Administrative", false], + ["Security", true], + ["ServiceHealth", false], + ["Alert", false], + ["Policy", true], + ["Autoscale", false], + ["ResourceHealth", false], + ["Recommendation", false], + ] + } + + } + +} \ No newline at end of file diff --git a/caf_launchpad/scenario/200/diagnostics_destinations.tfvars b/caf_launchpad/scenario/200/diagnostics_destinations.tfvars new file mode 100644 index 000000000..95ede1c24 --- /dev/null +++ b/caf_launchpad/scenario/200/diagnostics_destinations.tfvars @@ -0,0 +1,31 @@ +# Defines the different destination for the different log profiles +# Different profiles to target different operational teams + +diagnostics_destinations = { + # Storage keys must reference the azure region name + # For storage, reference "all_regions" and we will send the logs to the storage account + # in the region of the deployment + storage = { + all_regions = { + southeastasia = { + storage_account_key = "diagsiem_region1" + } + eastasia = { + storage_account_key = "diagsiem_region2" + } + } + } + + log_analytics = { + central_logs = { + log_analytics_key = "central_logs_region1" + log_analytics_destination_type = "Dedicated" + } + } + + event_hub_namespaces = { + central_logs = { + event_hub_namespace_key = "central_logs_region1" + } + } +} diff --git a/caf_launchpad/scenario/200/dynamic_secrets.tfvars b/caf_launchpad/scenario/200/dynamic_secrets.tfvars new file mode 100644 index 000000000..94042fd05 --- /dev/null +++ b/caf_launchpad/scenario/200/dynamic_secrets.tfvars @@ -0,0 +1,152 @@ + +# Store output attributes into keyvault secret +# Those values are used by the rover to connect the current remote state and +# identity the lower level +dynamic_keyvault_secrets = { + level0 = { + msi = { + output_key = "managed_identities" + resource_key = "level0" + attribute_key = "id" + secret_name = "msi-resource-id" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + admin = { + secret_name = "azdo-pat-admin" + value = "" + } + agent = { + secret_name = "azdo-pat-agent" + value = "" + } + } + level1 = { + msi = { + output_key = "managed_identities" + resource_key = "level1" + attribute_key = "id" + secret_name = "msi-resource-id" + } + lower_stg = { + output_key = "storage_accounts" + resource_key = "level0" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level0" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level2 = { + msi = { + output_key = "managed_identities" + resource_key = "level2" + attribute_key = "id" + secret_name = "msi-resource-id" + } + lower_stg = { + output_key = "storage_accounts" + resource_key = "level1" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level1" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level3 = { + msi = { + output_key = "managed_identities" + resource_key = "level3" + attribute_key = "id" + secret_name = "msi-resource-id" + } + lower_stg = { + output_key = "storage_accounts" + resource_key = "level2" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level2" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } + level4 = { + msi = { + output_key = "managed_identities" + resource_key = "level4" + attribute_key = "id" + secret_name = "msi-resource-id" + } + lower_stg = { + output_key = "storage_accounts" + resource_key = "level3" + attribute_key = "name" + secret_name = "lower-storage-account-name" + } + lower_rg = { + output_key = "resource_groups" + resource_key = "level3" + attribute_key = "name" + secret_name = "lower-resource-group-name" + } + subscription_id = { + output_key = "client_config" + attribute_key = "subscription_id" + secret_name = "subscription-id" + } + tenant_id = { + output_key = "client_config" + attribute_key = "tenant_id" + secret_name = "tenant-id" + } + } +} \ No newline at end of file diff --git a/caf_launchpad/scenario/200/iam_azuread.tfvars b/caf_launchpad/scenario/200/iam_azuread.tfvars new file mode 100644 index 000000000..4a4856f72 --- /dev/null +++ b/caf_launchpad/scenario/200/iam_azuread.tfvars @@ -0,0 +1,184 @@ + +azuread_groups = { + keyvault_level0_rw = { + name = "caf-level0-keyvault-rw" + description = "Provide read and write access to the keyvault secrets / level0." + members = { + user_principal_names = [ + ] + group_names = [] + object_ids = [] + group_keys = [] + + service_principal_keys = [ + "caf_launchpad_level0" + ] + + } + owners = { + user_principal_names = [ + ] + service_principal_keys = [ + "caf_launchpad_level0" + ] + } + prevent_duplicate_name = false + } + + keyvault_level1_rw = { + name = "caf-level1-landingzones-rw" + description = "Provide read and write access to manage landingzones / level1." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + keyvault_level2_rw = { + name = "caf-level2-landingzones-rw" + description = "Provide read and write access to manage landingzones / level2." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + keyvault_level3_rw = { + name = "caf-level3-landingzones-rw" + description = "Provide read and write access to manage landingzones / level3." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + keyvault_level4_rw = { + name = "caf-level4-applications" + description = "Provide read access to the applications who need to deploy on the level4." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + caf_launchpad_Reader = { + name = "caf-launchpad-Reader" + description = "Provide Reader role to the caf launchpad landing zone resource groups." + members = { + } + owners = { + + } + prevent_duplicate_name = false + } + + keyvault_password_rotation = { + name = "caf-level0-password-rotation-rw" + description = "Provide read and write access to the keyvault secrets / level0." + members = { + user_principal_names = [ + ] + group_names = [] + object_ids = [] + group_keys = [] + + service_principal_keys = [ + "caf_launchpad_level0" + ] + + } + owners = { + user_principal_names = [ + ] + service_principal_keys = [ + "caf_launchpad_level0" + ] + } + prevent_duplicate_name = false + } +} + +azuread_users = { + + # don't change that key + aad-user-devops-user-admin = { + useprefix = true + user_name = "caf-level0-security-devops-pat-rotation" + password_expire_in_days = 180 + + # Value must match with var.keyvaults[keyname] to store username and password for password rotation + keyvault_key = "secrets" + } + +} + +azuread_apps = { + # Do not rename the key "launchpad" to be able to upgrade to the standard launchpad + caf_launchpad_level0 = { + useprefix = true + application_name = "caf_launchpad_level0" + password_expire_in_days = 180 + + # Store the ${secret_prefix}-client-id, ${secret_prefix}-client-secret... + # Set the policy during the creation process of the launchpad + keyvaults = { + level0 = { + secret_prefix = "aadapp-caf-launchpad-level0" + } + } + } + +} + +# +# Available roles: +# az rest --method Get --uri https://graph.microsoft.com/v1.0/directoryRoleTemplates -o json | jq -r .value[].displayName +# +azuread_roles = { + azuread_apps = { + caf_launchpad_level0 = { + roles = [ + "Application Administrator", + "Application Developer", + "User Administrator" + ] + } + } + managed_identities = { + level0 = { + roles = [ + "Directory Readers", + "Application Developer", + "User Administrator" + ] + } + level1 = { + roles = [ + "Directory Readers" + ] + } + level2 = { + roles = [ + "Directory Readers" + ] + } + level3 = { + roles = [ + "Directory Readers" + ] + } + level4 = { + roles = [ + "Directory Readers" + ] + } + } +} diff --git a/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars b/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars new file mode 100644 index 000000000..f73f3b73d --- /dev/null +++ b/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars @@ -0,0 +1,43 @@ + + +azuread_api_permissions = { + + caf_launchpad_level0 = { + active_directory_graph = { + resource_app_id = "00000002-0000-0000-c000-000000000000" + resource_access = { + Application_ReadWrite_OwnedBy = { + id = "824c81eb-e3f8-4ee6-8f6d-de7f50d565b7" + type = "Role" + } + Directory_ReadWrite_All = { + id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175" + type = "Role" + } + } + } + + microsoft_graph = { + resource_app_id = "00000003-0000-0000-c000-000000000000" + resource_access = { + AppRoleAssignment_ReadWrite_All = { + id = "06b708a9-e830-4db3-a914-8e69da51d44f" + type = "Role" + } + DelegatedPermissionGrant_ReadWrite_All = { + id = "8e8e4742-1d95-4f68-9d56-6ee75648c72a" + type = "Role" + } + GroupReadWriteAll = { + id = "62a82d76-70ea-41e2-9197-370581804d09" + type = "Role" + } + RoleManagement_ReadWrite_Directory = { + id = "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8" + type = "Role" + } + } + } + } + +} diff --git a/caf_launchpad/scenario/200/iam_custom_roles.tfvars b/caf_launchpad/scenario/200/iam_custom_roles.tfvars new file mode 100644 index 000000000..f314abf3a --- /dev/null +++ b/caf_launchpad/scenario/200/iam_custom_roles.tfvars @@ -0,0 +1,76 @@ + +custom_role_definitions = { + caf-launchpad = { + name = "caf-launchpad" + useprefix = true + description = "Provide addition permissions on top of built-in Contributor role to manage landing zones deployment" + permissions = { + actions = [ + "Microsoft.Authorization/roleAssignments/delete", + "Microsoft.Authorization/roleAssignments/read", + "Microsoft.Authorization/roleAssignments/write", + "Microsoft.Authorization/roleDefinitions/delete", + "Microsoft.Authorization/roleDefinitions/read", + "Microsoft.Authorization/roleDefinitions/write", + "microsoft.insights/diagnosticSettings/delete", + "microsoft.insights/diagnosticSettings/read", + "microsoft.insights/diagnosticSettings/write", + "Microsoft.KeyVault/vaults/delete", + "Microsoft.KeyVault/vaults/read", + "Microsoft.KeyVault/vaults/write", + "Microsoft.KeyVault/vaults/accessPolicies/write", + "Microsoft.Network/networkSecurityGroups/delete", + "Microsoft.Network/networkSecurityGroups/read", + "Microsoft.Network/networkSecurityGroups/write", + "Microsoft.Network/networkSecurityGroups/join/action", + "Microsoft.Network/virtualNetworks/subnets/delete", + "Microsoft.Network/virtualNetworks/subnets/read", + "Microsoft.Network/virtualNetworks/subnets/write", + "Microsoft.OperationalInsights/workspaces/delete", + "Microsoft.OperationalInsights/workspaces/read", + "Microsoft.OperationalInsights/workspaces/write", + "Microsoft.OperationalInsights/workspaces/sharedKeys/action", + "Microsoft.OperationsManagement/solutions/delete", + "Microsoft.OperationsManagement/solutions/read", + "Microsoft.OperationsManagement/solutions/write", + "Microsoft.Storage/storageAccounts/delete", + "Microsoft.Storage/storageAccounts/read", + "Microsoft.Storage/storageAccounts/write", + "Microsoft.Storage/storageAccounts/blobServices/containers/delete", + "Microsoft.Storage/storageAccounts/blobServices/containers/read", + "Microsoft.Storage/storageAccounts/blobServices/containers/write", + "Microsoft.Storage/storageAccounts/blobServices/containers/lease/action", + "Microsoft.Storage/storageAccounts/blobServices/read", + "Microsoft.Storage/storageAccounts/listKeys/action", + "Microsoft.Resources/subscriptions/providers/read", + "Microsoft.Resources/subscriptions/read", + "Microsoft.Resources/subscriptions/resourcegroups/delete", + "Microsoft.Resources/subscriptions/resourcegroups/read", + "Microsoft.Resources/subscriptions/resourcegroups/write", + "Microsoft.Network/virtualNetworks/delete", + "Microsoft.Network/virtualNetworks/read", + "Microsoft.Network/virtualNetworks/write", + ] + } + + } + + caf-launchpad-contributor = { + name = "caf-launchpad-contributor" + useprefix = true + description = "Provide addition permissions on top of built-in Contributor role to manage landing zones deployment" + permissions = { + actions = [ + "Microsoft.Authorization/roleAssignments/delete", + "Microsoft.Authorization/roleAssignments/read", + "Microsoft.Authorization/roleAssignments/write", + "Microsoft.Authorization/roleDefinitions/delete", + "Microsoft.Authorization/roleDefinitions/read", + "Microsoft.Authorization/roleDefinitions/write", + "Microsoft.Resources/subscriptions/providers/read" + ] + } + } + +} + diff --git a/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars b/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars new file mode 100644 index 000000000..e755b1ebd --- /dev/null +++ b/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars @@ -0,0 +1,114 @@ +keyvault_access_policies_azuread_apps = { + level0 = { + caf_launchpad_level0 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + # A maximum of 16 access policies per keyvault + level1 = { + caf_launchpad_level0 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # A maximum of 16 access policies per keyvault + level2 = { + caf_launchpad_level0 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + + # A maximum of 16 access policies per keyvault + level3 = { + caf_launchpad_level0 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + + # A maximum of 16 access policies per keyvault + level4 = { + caf_launchpad_level1 = { + # Reference a key to an azure ad applications + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + + secrets = { + caf_launchpad_level0 = { + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } +} + +keyvault_access_policies = { + # A maximum of 16 access policies per keyvault + level0 = { + keyvault_level0_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + # A maximum of 16 access policies per keyvault + level1 = { + keyvault_level1_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level1_rw" + secret_permissions = ["Get", "List"] + } + } + + # A maximum of 16 access policies per keyvault + level2 = { + keyvault_level2_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level2_rw" + secret_permissions = ["Get", "List"] + } + } + + + # A maximum of 16 access policies per keyvault + level3 = { + keyvault_level3_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level3_rw" + secret_permissions = ["Get", "List"] + } + } + + + # A maximum of 16 access policies per keyvault + level4 = { + keyvault_level4_rw = { + # Reference a key to an azure ad group + azuread_group_key = "keyvault_level4_rw" + secret_permissions = ["Get", "List"] + } + } + + + secrets = { + keyvault_level0_rw = { + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + keyvault_password_rotation = { + azuread_group_key = "keyvault_password_rotation" + secret_permissions = ["Set", "Get", "List", "Delete", ] + } + } +} diff --git a/caf_launchpad/scenario/200/iam_managed_identities.tfvars b/caf_launchpad/scenario/200/iam_managed_identities.tfvars new file mode 100644 index 000000000..a5e76137c --- /dev/null +++ b/caf_launchpad/scenario/200/iam_managed_identities.tfvars @@ -0,0 +1,32 @@ + +managed_identities = { + level0 = { + # Used by the release agent to access the level0 keyvault and storage account with the tfstates in read / write + name = "landingzone-level0-msi" + resource_group_key = "security" + } + level1 = { + # Used by the release agent to access the level1 keyvault and storage account with the tfstates in read / write + # Has read access to level0 + name = "landingzone-level1-msi" + resource_group_key = "security" + } + level2 = { + # Used by the release agent to access the level2 keyvault and storage account with the tfstates in read / write + # Has read access to level1 + name = "landingzone-level2-msi" + resource_group_key = "security" + } + level3 = { + # Used by the release agent to access the level3 keyvault and storage account with the tfstates in read / write + # Has read access to level2 + name = "landingzone-level3-msi" + resource_group_key = "security" + } + level4 = { + # Used by the release agent to access the level4 keyvault and storage account with the tfstates in read / write + # Has read access to level3 + name = "landingzone-level4-msi" + resource_group_key = "security" + } +} diff --git a/caf_launchpad/scenario/200/iam_role_mapping.tfvars b/caf_launchpad/scenario/200/iam_role_mapping.tfvars new file mode 100644 index 000000000..23a919f2a --- /dev/null +++ b/caf_launchpad/scenario/200/iam_role_mapping.tfvars @@ -0,0 +1,154 @@ + +# +# Services supported: subscriptions, storage accounts and resource groups +# Can assign roles to: AD groups, AD object ID, AD applications, Managed identities +# +role_mapping = { + custom_role_mapping = { + subscriptions = { + logged_in_subscription = { + "caf-launchpad-contributor" = { + azuread_groups = { + keys = ["keyvault_level0_rw", "keyvault_level1_rw", "keyvault_level2_rw", "keyvault_level3_rw", "keyvault_level4_rw", ] + } + managed_identities = { + keys = ["level0", "level1", "level2", "level3", "level4"] + } + azuread_apps = { + keys = ["caf_launchpad_level0"] + } + } + } + } + } + + built_in_role_mapping = { + subscriptions = { + logged_in_subscription = { + "Contributor" = { + azuread_apps = { + keys = ["caf_launchpad_level0"] + } + managed_identities = { + keys = ["level0", "level1", "level2", "level3", "level4"] + } + } + } + } + resource_groups = { + level0 = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + security = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + networking = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + ops = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + siem = { + "Reader" = { + azuread_groups = { + keys = ["caf_launchpad_Reader"] + } + } + } + } + storage_accounts = { + level0 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + azuread_groups = { + keys = ["keyvault_level0_rw"] + } + azuread_apps = { + keys = ["caf_launchpad_level0"] + } + managed_identities = { + keys = ["level0"] + } + } + "Storage Blob Data Reader" = { + azuread_groups = { + keys = ["keyvault_level1_rw"] + } + } + } + level1 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + azuread_groups = { + keys = ["keyvault_level1_rw"] + } + managed_identities = { + keys = ["level1"] + } + } + "Storage Blob Data Reader" = { + azuread_groups = { + keys = ["keyvault_level2_rw"] + } + } + } + level2 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + azuread_groups = { + keys = ["keyvault_level2_rw"] + } + managed_identities = { + keys = ["level2"] + } + } + "Storage Blob Data Reader" = { + azuread_groups = { + keys = ["keyvault_level3_rw"] + } + } + } + level3 = { + "Storage Blob Data Contributor" = { + logged_in = { + keys = ["user"] + } + azuread_groups = { + keys = ["keyvault_level3_rw"] + } + managed_identities = { + keys = ["level3"] + } + } + "Storage Blob Data Reader" = { + azuread_groups = { + keys = ["keyvault_level4_rw"] + } + } + } + } + } + +} diff --git a/caf_launchpad/scenario/200/keyvaults.tfvars b/caf_launchpad/scenario/200/keyvaults.tfvars new file mode 100644 index 000000000..9b407a31d --- /dev/null +++ b/caf_launchpad/scenario/200/keyvaults.tfvars @@ -0,0 +1,204 @@ + +keyvaults = { + level0 = { + name = "level0" + resource_group_key = "level0" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level0" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + level1 = { + name = "level1" + resource_group_key = "level1" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level1" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + level2 = { + name = "level2" + resource_group_key = "level2" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level2" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + level3 = { + name = "level3" + resource_group_key = "level3" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level3" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + level4 = { + name = "level4" + resource_group_key = "level4" + sku_name = "standard" + soft_delete_enabled = true + tags = { + tfstate = "level4" + environment = "sandpit" + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } + + secrets = { + name = "secrets" + resource_group_key = "security" + region = "region1" + sku_name = "premium" + soft_delete_enabled = true + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + + } +} diff --git a/caf_launchpad/scenario/200/networking.tfvars b/caf_launchpad/scenario/200/networking.tfvars new file mode 100644 index 000000000..e21c316fe --- /dev/null +++ b/caf_launchpad/scenario/200/networking.tfvars @@ -0,0 +1,110 @@ + +################################################## +# +# Networking resources +# +################################################## + + +public_ip_addresses = { + bastion_host_rg1 = { + name = "pip1" + resource_group_key = "networking" + sku = "Standard" + allocation_method = "Static" + ip_version = "IPv4" + idle_timeout_in_minutes = "4" + + # you can setup up to 5 key + diagnostic_profiles = { + bastion_host_rg1 = { + definition_key = "public_ip_address" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + } +} + +vnets = { + devops_region1 = { + resource_group_key = "networking" + region = "region1" + vnet = { + name = "devops" + address_space = ["10.100.100.0/24"] + } + specialsubnets = {} + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["10.100.100.24/29"] + nsg_key = "azure_bastion_nsg" + } + jumpbox = { + name = "jumpbox" + cidr = ["10.100.100.32/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level0 = { + name = "level0" + cidr = ["10.100.100.40/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level1 = { + name = "level1" + cidr = ["10.100.100.48/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level2 = { + name = "level2" + cidr = ["10.100.100.56/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level3 = { + name = "level3" + cidr = ["10.100.100.64/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + release_agent_level4 = { + name = "level4" + cidr = ["10.100.100.72/29"] + service_endpoints = ["Microsoft.KeyVault"] + } + private_endpoints = { + name = "private_endpoints" + cidr = ["10.100.100.128/25"] + enforce_private_link_endpoint_network_policies = true + } + } + + # you can setup up to 5 keys - vnet diganostic + diagnostic_profiles = { + vnet = { + definition_key = "networking_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + } +} + + +route_tables = { + default_no_internet = { + name = "default_no_internet" + resource_group_key = "networking" + } +} + +azurerm_routes = { + no_internet = { + name = "no_internet" + resource_group_key = "networking" + route_table_key = "default_no_internet" + address_prefix = "0.0.0.0/0" + next_hop_type = "None" + } +} diff --git a/caf_launchpad/scenario/200/networking_nsg_definition.tfvars b/caf_launchpad/scenario/200/networking_nsg_definition.tfvars new file mode 100644 index 000000000..8b558b104 --- /dev/null +++ b/caf_launchpad/scenario/200/networking_nsg_definition.tfvars @@ -0,0 +1,141 @@ + +# +# Definition of the networking security groups +# +network_security_group_definition = { + # This entry is applied to all subnets with no NSG defined + empty_nsg = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } + + azure_bastion_nsg = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } + + jumphost = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "ssh-inbound-22", + priority = "200" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + +} diff --git a/caf_launchpad/scenario/200/readme.md b/caf_launchpad/scenario/200/readme.md new file mode 100644 index 000000000..82f7b4440 --- /dev/null +++ b/caf_launchpad/scenario/200/readme.md @@ -0,0 +1,56 @@ +# Launchpad - scenario 200 + +The 200 scenario is an extension of the 100 scenario, meaning you can upgrade a 100 scenario to a 200. +The 200 scenario is designed to demonstrate a more secure environment but is not recommended for production use. +The focus of this scenario is to be able to deploy a more advanced launchpad from a remote machine and use the portal to review the settings in a non-constrained environment. +For example in this scenario you can go to the Key Vaults and view the secrets from the portal. A feature that is disabled in the 300+ scenarios. We recommend using the 200 scenario for demonstration or building new capabilities. + +An estimated time of 20 minutes is required to deploy this scenario. + +## Pre-requisites + +This scenario require the following privileges: + +| Component | Privileges | +|--------------------|--------------------------------| +| Active Directory | Application Administrator role | +| Azure subscription | Subscription owner | + +## Deployment + +```bash +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ + -level level0 \ + -a apply + +rover -lz /tf/caf/landingzones/caf_launchpad \ + -launchpad \ + -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ + -level level0 \ + -a destroy +``` + +## Architecture diagram + +![Launchpad 200](../../documentation/img/launchpad-200.png) + +## Services deployed in this scenario + +| Component | Purpose | +|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Resource group | Multiple resource groups are created to isolate the services | +| Storage account | A storage account for remote tfstate management is provided for each level of the framework. Additional storage accounts are created for diagnostic logs. | +| Keyvault | The launchpad keyvault hosts all secrets required by the rover to access the remote states. The secret keyvault is used to host all Azure AD users, applications and virtual machines's ssh key. | +| Virtual network | To secure the communication between the services a dedicated virtual network is deployed with a gateway subnet, bastion service, jumpbox and azure DevOps release agents. Service endpoints is enabled but not configured. | +| Bastion host service | Is use to support the access to the rover in scenario 300 and 400. | +| Jumpbox | A Linux server with the docker engine to run the rover and perform the deployment of the scenario 300 and 400. | +| Log analytics | A central log analytics workspace is created to collect all diagnostics and metrics information. Solutions are also deployed. | +| Diagnostic profiles | Default settings with 7 days retention of diagnostic profile is provided for all services. | +| Diagnostic destination | Operation sends the logs to a log analytics workspace and SIEM send all security logs to a storage account. | +| Diagnostic | Is enabled by default on all services. | +| Azure AD Users | An Azure AD user is created. This user is used in scenario 300 and 400 to own the Azure DevOps Personal Access Token (PAT) rotation. | +| Azure AD Applications | An Azure AD application is created. This account is mainly use to bootstrap the services during the initialization. It is also considered as a breakglass account for the launchpad landing zones. | +| Azure AD API permissions | A set of API permissions assigned to the Azure AD application to support management of the landing zones in a pipeline. | +| Managed Identities | A user managed Identity account is created for each Azure DevOps agent. This account is configured to get access to the keyvaults and Azure storage accounts | \ No newline at end of file diff --git a/caf_launchpad/scenario/200/storage_accounts.tfvars b/caf_launchpad/scenario/200/storage_accounts.tfvars new file mode 100644 index 000000000..bd60a50f5 --- /dev/null +++ b/caf_launchpad/scenario/200/storage_accounts.tfvars @@ -0,0 +1,101 @@ + +storage_accounts = { + level0 = { + name = "level0" + resource_group_key = "level0" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + ## Those tags must never be changed after being set as they are used by the rover to locate the launchpad and the tfstates. + # Only adjust the environment value at creation time + tfstate = "level0" + environment = "sandpit" + launchpad = "launchpad" + ## + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level1 = { + name = "level1" + resource_group_key = "level1" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level1" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level2 = { + name = "level2" + resource_group_key = "level2" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level2" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level3 = { + name = "level3" + resource_group_key = "level3" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level3" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + } + + level4 = { + name = "level4" + resource_group_key = "level4" + account_kind = "BlobStorage" + account_tier = "Standard" + account_replication_type = "RAGRS" + tags = { + # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. + tfstate = "level4" + environment = "sandpit" + launchpad = "launchpad" + } + containers = { + tfstate = { + name = "tfstate" + } + } + + } + +} \ No newline at end of file diff --git a/caf_launchpad/scenario/200/subscriptions.tfvars b/caf_launchpad/scenario/200/subscriptions.tfvars new file mode 100644 index 000000000..9e98ae770 --- /dev/null +++ b/caf_launchpad/scenario/200/subscriptions.tfvars @@ -0,0 +1,20 @@ + +subscriptions = { + logged_in_subscription = { + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "subscription_operations" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "subscription_siem" + destination_type = "storage" + destination_key = "all_regions" + } + } + + } +} \ No newline at end of file diff --git a/caf_launchpad/scripts/cloud-init-install-rover-tools.config b/caf_launchpad/scripts/cloud-init-install-rover-tools.config new file mode 100644 index 000000000..53cd432e8 --- /dev/null +++ b/caf_launchpad/scripts/cloud-init-install-rover-tools.config @@ -0,0 +1,49 @@ +#cloud-config + +apt: + preserve_sources_list: true + sources: + azure-cli.list: + source: "deb https://packages.microsoft.com/repos/azure-cli/ bionic main" + key: | + -----BEGIN PGP PUBLIC KEY BLOCK----- + Version: GnuPG v1.4.7 (GNU/Linux) + + mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT + LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV + 7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag + OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j + H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr + M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs + ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC + AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH + /32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe + MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy + 7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV + KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ + XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+ + NdCFTW7wY0Fb1fWJ+/KTsC4= + =J6gs + -----END PGP PUBLIC KEY BLOCK----- +package_update: true + +packages: + - ca-certificates + - curl + - apt-transport-https + - lsb-release + - azure-cli + +snap: + commands: + - snap install kubectl --classic +# Install docker and docker-compose +runcmd: + - [ sh, -c, 'curl -sSL https://get.docker.com/ | sh' ] + - [ sh, -c, 'curl -L https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep "tag_name" | cut -d \" -f4)/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose' ] + - [ sh, -c, 'sudo chmod +x /usr/local/bin/docker-compose' ] + +# Add default auto created user to docker group +system_info: + default_user: + groups: [docker] \ No newline at end of file diff --git a/caf_launchpad/variables.tf b/caf_launchpad/variables.tf new file mode 100644 index 000000000..6ff3d9dd7 --- /dev/null +++ b/caf_launchpad/variables.tf @@ -0,0 +1,211 @@ +# Map of the current tfstate +variable "tfstate_storage_account_name" { + default = null +} +variable "tfstate_container_name" { + default = null +} +variable "tfstate_key" { + default = null +} +variable "tfstate_resource_group_name" { + default = null +} + +variable "tenant_id" {} +variable "landingzone" { + description = "The landing zone name is used to reference the tfstate in configuration files. Therefore while set it is recommended not to change" +} + +variable "passthrough" { + default = false +} +variable "random_length" { + default = null +} + +variable "inherit_tags" { + default = false +} + +variable "default_region" { + description = "Define the default region where services are deployed if the location is not set at the resource level" + default = "region1" +} + +variable "regions" { + type = map(any) + description = "List of the regions where services can be deployed. This impact the diagnostics logs settings" + default = { + region1 = "southeastasia" + } +} + +variable "enable" { + description = "Map of services defined in the configuration file you want to disable during a deployment" + default = {} +} + +variable "prefix" { + default = null +} + +variable "use_slug" { + default = true +} + +variable "log_analytics" { + default = {} +} + +variable "event_hub_namespaces" { + default = {} +} + +# Do not change the default value to be able to upgrade to the standard launchpad +variable "tf_name" { + description = "Name of the terraform state in the blob storage (Does not include the extension .tfstate). Setup by the rover. Leave empty in the configuration file" + default = "" +} + +variable "resource_groups" {} + +variable "storage_accounts" {} +variable "keyvaults" {} +variable "keyvault_access_policies" { + default = {} +} +variable "keyvault_keys" { + default = {} +} +variable "dynamic_keyvault_secrets" {} + +variable "subscriptions" { + default = {} +} + +## Azure Active Directory +variable "azuread_apps" { + default = {} +} +variable "azuread_groups" { + default = {} +} +variable "azuread_users" { + default = {} +} +variable "azuread_roles" { + default = {} +} +variable "managed_identities" { + default = {} +} + +variable "networking" { + default = {} +} + +variable "compute" { + default = {} +} + +variable "launchpad_key_names" {} + +variable "custom_role_definitions" { + default = {} +} +variable "role_mapping" { + default = { + built_in_role_mapping = {} + custom_role_mapping = {} + } +} + +variable "tags" { + type = map(any) + default = {} +} + +variable "rover_version" {} + +variable "user_type" {} + +variable "logged_user_objectId" { + default = null +} +variable "logged_aad_app_objectId" { + default = null +} + +variable "aad_users" { + default = {} +} + +variable "aad_roles" { + default = {} +} + +variable "azuread_api_permissions" { + default = {} +} + +variable "environment" { + type = string + description = "This variable is set by the rover during the deployment based on the -env or -environment flags. Default to sandpit" +} + +variable "diagnostics" { + default = {} +} + +variable "diagnostics_definition" { + default = {} +} + +variable "diagnostics_destinations" { + default = {} +} + +variable "diagnostic_event_hub_namespaces" { + default = {} +} + +variable "diagnostic_log_analytics" { + default = {} +} + +variable "diagnostic_storage_accounts" { + default = {} +} + +variable "keyvault_access_policies_azuread_apps" { + default = {} +} + +variable "virtual_machines" { + default = {} +} + +variable "bastion_hosts" { + default = {} +} + +variable "vnets" { + default = {} +} + +variable "network_security_group_definition" { + default = {} +} + +variable "public_ip_addresses" { + default = {} +} + +variable "azurerm_routes" { + default = {} +} + +variable "route_tables" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml b/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml new file mode 100644 index 000000000..c430b2385 --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/aad-msi-binding.yaml @@ -0,0 +1,16 @@ +apiVersion: aadpodidentity.k8s.io/v1 +kind: AzureIdentity +metadata: + name: podmi-caf-rover-platform-level0 +spec: + type: 0 + resourceID: ${resource_id} + clientID: ${client_id} +--- +apiVersion: aadpodidentity.k8s.io/v1 +kind: AzureIdentityBinding +metadata: + name: podmi-gitlab-runner-binding +spec: + azureIdentity: podmi-caf-rover-platform-level0 + selector: podmi-caf-rover-platform-level0 \ No newline at end of file diff --git a/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf b/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf new file mode 100644 index 000000000..05f60b4d1 --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/aad_pod_identity.tf @@ -0,0 +1,120 @@ +resource "kubernetes_namespace" "ns" { + metadata { + name = var.aad_pod_identity.namespace + } +} + +module "build" { + depends_on = [kubernetes_namespace.ns] + source = "./build" + for_each = try(data.kustomization_overlay.aad_pod_identity, {}) + + settings = each.value +} + + + +data "kustomization_overlay" "aad_pod_identity" { + for_each = local.msi + + resources = [ + "aad-msi-binding.yaml", + ] + + namespace = var.aad_pod_identity.namespace + + patches { + patch = <<-EOF + - op: replace + path: /spec/resourceID + value: ${each.value.id} + EOF + + target = { + kind = "AzureIdentity" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /spec/clientID + value: ${each.value.client_id} + EOF + + target = { + kind = "AzureIdentity" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /metadata/name + value: ${each.value.azureIdentity} + EOF + + target = { + kind = "AzureIdentity" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /metadata/name + value: ${each.value.azureIdentity}-binding + EOF + + target = { + kind = "AzureIdentityBinding" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /spec/azureIdentity + value: ${each.value.azureIdentity} + EOF + + target = { + kind = "AzureIdentityBinding" + } + } + + patches { + patch = <<-EOF + - op: replace + path: /spec/selector + value: ${each.value.selector} + EOF + + target = { + kind = "AzureIdentityBinding" + } + } +} + +output "manifests" { + value = data.kustomization_overlay.aad_pod_identity +} + +locals { + msi = { + for msi in flatten( + [ + for key, value in var.managed_identities : [ + for msi_key in value.msi_keys : { + key = key + msi_key = msi_key + client_id = local.remote.managed_identities[value.lz_key][msi_key].client_id + id = local.remote.managed_identities[value.lz_key][msi_key].id + azureIdentity = value["aad_msi_bindings"][msi_key].azureIdentity + selector = value["aad_msi_bindings"][msi_key].selector + } + ] + ] + ) : format("%s-%s", msi.key, msi.msi_key) => msi + } +} diff --git a/caf_solution/add-ons/aad-pod-identity/backend.azurerm b/caf_solution/add-ons/aad-pod-identity/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf b/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf new file mode 100644 index 000000000..985bd96f5 --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/build/kustomization_build.tf @@ -0,0 +1,16 @@ +resource "kustomization_resource" "p0" { + for_each = var.settings.ids_prio[0] + manifest = var.settings.manifests[each.value] +} + +resource "kustomization_resource" "p1" { + depends_on = [kustomization_resource.p0] + for_each = var.settings.ids_prio[1] + manifest = var.settings.manifests[each.value] +} + +resource "kustomization_resource" "p2" { + depends_on = [kustomization_resource.p1] + for_each = var.settings.ids_prio[2] + manifest = var.settings.manifests[each.value] +} diff --git a/caf_solution/add-ons/aad-pod-identity/build/main.tf b/caf_solution/add-ons/aad-pod-identity/build/main.tf new file mode 100644 index 000000000..e65c6fa22 --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/build/main.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + kustomization = { + source = "kbst/kustomization" + } + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/aad-pod-identity/build/variables.tf b/caf_solution/add-ons/aad-pod-identity/build/variables.tf new file mode 100644 index 000000000..f5c321890 --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/build/variables.tf @@ -0,0 +1,2 @@ +variable "settings" { +} diff --git a/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf b/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf new file mode 100644 index 000000000..d458c18a1 --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/local.remote_tfstates.tf @@ -0,0 +1,54 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = try(each.value.container, local.landingzone[try(each.value.level, "current")].container_name) + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics + + remote = { + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + global_settings = local.global_settings + diagnostics = local.diagnostics + + + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) + } + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) + } + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) + } + } + +} diff --git a/caf_solution/add-ons/aad-pod-identity/main.tf b/caf_solution/add-ons/aad-pod-identity/main.tf new file mode 100644 index 000000000..f0cc7ddbe --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/main.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.51.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.0.2" + } + kustomization = { + source = "kbst/kustomization" + version = "~> 0.4.0" + } + } + required_version = ">= 0.13" +} diff --git a/caf_solution/add-ons/aad-pod-identity/providers.tf b/caf_solution/add-ons/aad-pod-identity/providers.tf new file mode 100644 index 000000000..be2b3abb1 --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/providers.tf @@ -0,0 +1,32 @@ + +provider "azurerm" { + features { + } +} + +provider "kubernetes" { + host = local.k8sconfigs[var.aks_cluster_key].host + username = local.k8sconfigs[var.aks_cluster_key].username + password = local.k8sconfigs[var.aks_cluster_key].password + client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate + client_key = local.k8sconfigs[var.aks_cluster_key].client_key + cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate +} + +provider "kustomization" { + kubeconfig_raw = local.k8sconfigs[var.aks_cluster_key].kube_admin_config_raw +} + +locals { + k8sconfigs = { + for key, value in var.aks_clusters : key => { + kube_admin_config_raw = local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config_raw + host = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.host : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.host + username = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.username : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.username + password = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.password : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.password + client_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_certificate) + client_key = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_key) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_key) + cluster_ca_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.cluster_ca_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.cluster_ca_certificate) + } + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/aad-pod-identity/variables.tf b/caf_solution/add-ons/aad-pod-identity/variables.tf new file mode 100644 index 000000000..971033737 --- /dev/null +++ b/caf_solution/add-ons/aad-pod-identity/variables.tf @@ -0,0 +1,36 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "landingzone" {} +variable "rover_version" { + default = null +} +variable "tags" { + default = {} +} + +###### + +variable "aks_cluster_key" { + description = "AKS cluster key to deploy the Gitlab Helm charts. The key must be defined in the variable aks_clusters" +} +variable "aks_cluster_vnet_key" { + +} +variable "aks_clusters" {} +variable "vnets" {} +variable "managed_identities" { + description = "Map of the user managed identities." +} + +variable "aad_pod_identity" {} \ No newline at end of file diff --git a/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf b/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf new file mode 100644 index 000000000..96c672df0 --- /dev/null +++ b/caf_solution/add-ons/aks-secure-baseline/aks-pod-identity-assignment.tf @@ -0,0 +1,58 @@ + +# Get the details of the node pool's resource group created by AKS +data "azurerm_resource_group" "noderg" { + for_each = var.aks_clusters + name = local.remote.aks_clusters[each.value.lz_key][each.value.key].node_resource_group +} + +# +# Set permissions to the kubelet and cluster identity +# +resource "azurerm_role_assignment" "kubelet_noderg_miop" { + for_each = var.aks_clusters + + scope = data.azurerm_resource_group.noderg[each.key].id + role_definition_name = "Managed Identity Operator" + principal_id = local.remote.aks_clusters[each.value.lz_key][each.value.key].kubelet_identity[0].object_id +} + +resource "azurerm_role_assignment" "kubelet_noderg_vmcontrib" { + for_each = var.aks_clusters + + scope = data.azurerm_resource_group.noderg[each.key].id + role_definition_name = "Virtual Machine Contributor" + principal_id = local.remote.aks_clusters[each.value.lz_key][each.value.key].kubelet_identity[0].object_id +} + + +resource "azurerm_role_assignment" "kubelet_vnet_networkcontrib" { + for_each = toset(var.vnets[var.aks_cluster_vnet_key].subnet_keys) + + scope = local.remote.vnets[var.vnets[var.aks_cluster_vnet_key].lz_key][var.vnets[var.aks_cluster_vnet_key].key].subnets[each.value].id + role_definition_name = "Network Contributor" + principal_id = local.remote.aks_clusters[var.aks_clusters[var.aks_cluster_key].lz_key][var.aks_cluster_key].identity[0].principal_id +} + +resource "azurerm_role_assignment" "kubelet_user_msi" { + for_each = local.msi_to_grant_permissions + + scope = each.value.id + role_definition_name = "Managed Identity Operator" + principal_id = local.remote.aks_clusters[var.aks_clusters[var.aks_cluster_key].lz_key][var.aks_cluster_key].kubelet_identity[0].object_id +} + +locals { + msi_to_grant_permissions = { + for msi in flatten( + [ + for key, value in var.managed_identities : [ + for msi_key in value.msi_keys : { + key = key + msi_key = msi_key + id = local.remote.managed_identities[value.lz_key][msi_key].id + } + ] + ] + ) : format("%s-%s", msi.key, msi.msi_key) => msi + } +} diff --git a/caf_solution/add-ons/aks-secure-baseline/backend.azurerm b/caf_solution/add-ons/aks-secure-baseline/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_solution/add-ons/aks-secure-baseline/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml b/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml new file mode 100644 index 000000000..373d8b437 --- /dev/null +++ b/caf_solution/add-ons/aks-secure-baseline/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - https://raw.githubusercontent.com/Azure/caf-terraform-landingzones-starter/starter/enterprise_scale/construction_sets/aks/online/aks_secure_baseline/cluster-baseline-settings/flux.yaml \ No newline at end of file diff --git a/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf b/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf new file mode 100644 index 000000000..d458c18a1 --- /dev/null +++ b/caf_solution/add-ons/aks-secure-baseline/local.remote_tfstates.tf @@ -0,0 +1,54 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = try(each.value.container, local.landingzone[try(each.value.level, "current")].container_name) + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics + + remote = { + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + global_settings = local.global_settings + diagnostics = local.diagnostics + + + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) + } + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) + } + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) + } + } + +} diff --git a/caf_solution/add-ons/aks-secure-baseline/main.tf b/caf_solution/add-ons/aks-secure-baseline/main.tf new file mode 100644 index 000000000..ac7602c81 --- /dev/null +++ b/caf_solution/add-ons/aks-secure-baseline/main.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.51.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.0.2" + } + kustomization = { + source = "kbst/kustomization" + version = ">= 0.4.0" + } + } + required_version = ">= 0.13" +} diff --git a/caf_solution/add-ons/aks-secure-baseline/providers.tf b/caf_solution/add-ons/aks-secure-baseline/providers.tf new file mode 100644 index 000000000..be2b3abb1 --- /dev/null +++ b/caf_solution/add-ons/aks-secure-baseline/providers.tf @@ -0,0 +1,32 @@ + +provider "azurerm" { + features { + } +} + +provider "kubernetes" { + host = local.k8sconfigs[var.aks_cluster_key].host + username = local.k8sconfigs[var.aks_cluster_key].username + password = local.k8sconfigs[var.aks_cluster_key].password + client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate + client_key = local.k8sconfigs[var.aks_cluster_key].client_key + cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate +} + +provider "kustomization" { + kubeconfig_raw = local.k8sconfigs[var.aks_cluster_key].kube_admin_config_raw +} + +locals { + k8sconfigs = { + for key, value in var.aks_clusters : key => { + kube_admin_config_raw = local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config_raw + host = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.host : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.host + username = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.username : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.username + password = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.password : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.password + client_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_certificate) + client_key = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_key) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_key) + cluster_ca_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.cluster_ca_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.cluster_ca_certificate) + } + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf b/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf new file mode 100644 index 000000000..f2208c9bd --- /dev/null +++ b/caf_solution/add-ons/aks-secure-baseline/secure-baseline.tf @@ -0,0 +1,22 @@ +# Process the Kustomization in the current folder +data "kustomization_build" "flux" { + path = "." +} + +resource "kustomization_resource" "cluster_secure_baseline_p0" { + # depends_on = [kubernetes_namespace.cluster_secure_baseline] + for_each = data.kustomization_build.flux.ids_prio[0] + manifest = data.kustomization_build.flux.manifests[each.value] +} + +resource "kustomization_resource" "cluster_secure_baseline_p1" { + depends_on = [kustomization_resource.cluster_secure_baseline_p0] + for_each = data.kustomization_build.flux.ids_prio[1] + manifest = data.kustomization_build.flux.manifests[each.value] +} + +resource "kustomization_resource" "cluster_secure_baseline_p2" { + depends_on = [kustomization_resource.cluster_secure_baseline_p1] + for_each = data.kustomization_build.flux.ids_prio[2] + manifest = data.kustomization_build.flux.manifests[each.value] +} diff --git a/caf_solution/add-ons/aks-secure-baseline/variables.tf b/caf_solution/add-ons/aks-secure-baseline/variables.tf new file mode 100644 index 000000000..971033737 --- /dev/null +++ b/caf_solution/add-ons/aks-secure-baseline/variables.tf @@ -0,0 +1,36 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "landingzone" {} +variable "rover_version" { + default = null +} +variable "tags" { + default = {} +} + +###### + +variable "aks_cluster_key" { + description = "AKS cluster key to deploy the Gitlab Helm charts. The key must be defined in the variable aks_clusters" +} +variable "aks_cluster_vnet_key" { + +} +variable "aks_clusters" {} +variable "vnets" {} +variable "managed_identities" { + description = "Map of the user managed identities." +} + +variable "aad_pod_identity" {} \ No newline at end of file diff --git a/caf_solution/add-ons/aks_applications/app/main.tf b/caf_solution/add-ons/aks_applications/app/main.tf new file mode 100644 index 000000000..1191eedce --- /dev/null +++ b/caf_solution/add-ons/aks_applications/app/main.tf @@ -0,0 +1,7 @@ +provider "kubernetes" { + alias = "k8s" +} + +provider "helm" { + alias = "helm" +} diff --git a/caf_solution/add-ons/aks_applications/app/module.tf b/caf_solution/add-ons/aks_applications/app/module.tf new file mode 100644 index 000000000..2d4288893 --- /dev/null +++ b/caf_solution/add-ons/aks_applications/app/module.tf @@ -0,0 +1,48 @@ +resource "kubernetes_namespace" "namespaces" { + for_each = var.namespaces + metadata { + annotations = try(each.value.annotations, null) + labels = try(each.value.labels, null) + name = each.value.name + } + + provider = kubernetes.k8s +} + +# https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release +resource "helm_release" "charts" { + for_each = var.helm_charts + + name = each.value.name + repository = each.value.repository + chart = each.value.chart + + namespace = each.value.namespace + wait = try(each.value.wait, true) + timeout = try(each.value.timeout, 900) + skip_crds = try(each.value.skip_crds, false) + create_namespace = try(each.value.create_namespace, false) + + dynamic "set" { + for_each = try(each.value.sets, {}) + content { + name = set.key + value = set.value + } + } + + dynamic "set_sensitive" { + for_each = try(each.value.sets_sensitive, {}) + content { + name = set_sensitive.key + value = set_sensitive.value + } + } + + provider = helm.helm + + depends_on = [kubernetes_namespace.namespaces] + # values = [ + # "${file("values.yaml")}" + # ] +} \ No newline at end of file diff --git a/caf_solution/add-ons/aks_applications/app/output.tf b/caf_solution/add-ons/aks_applications/app/output.tf new file mode 100644 index 000000000..e69de29bb diff --git a/caf_solution/add-ons/aks_applications/app/variables.tf b/caf_solution/add-ons/aks_applications/app/variables.tf new file mode 100644 index 000000000..4a0225192 --- /dev/null +++ b/caf_solution/add-ons/aks_applications/app/variables.tf @@ -0,0 +1,5 @@ +variable "cluster" {} + +variable "namespaces" {} + +variable "helm_charts" {} \ No newline at end of file diff --git a/caf_solution/add-ons/aks_applications/applications.tf b/caf_solution/add-ons/aks_applications/applications.tf new file mode 100644 index 000000000..b1f674491 --- /dev/null +++ b/caf_solution/add-ons/aks_applications/applications.tf @@ -0,0 +1,27 @@ +module "app1" { + source = "./app" + for_each = try(local.clusters[var.cluster_re1_key], null) != null ? { (var.cluster_re1_key) = local.clusters[var.cluster_re1_key] } : {} + + cluster = each.value + namespaces = var.namespaces + helm_charts = var.helm_charts + + providers = { + kubernetes.k8s = kubernetes.k8s1 + helm.helm = helm.helm1 + } +} + +module "app2" { + source = "./app" + for_each = try(local.clusters[var.cluster_re2_key], null) != null ? { (var.cluster_re2_key) = local.clusters[var.cluster_re2_key] } : {} + + cluster = each.value + namespaces = var.namespaces + helm_charts = var.helm_charts + + providers = { + kubernetes.k8s = kubernetes.k8s2 + helm.helm = helm.helm2 + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/aks_applications/backend.azurerm b/caf_solution/add-ons/aks_applications/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_solution/add-ons/aks_applications/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf b/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf new file mode 100644 index 000000000..cf16e86c6 --- /dev/null +++ b/caf_solution/add-ons/aks_applications/locals.remote_tfstates.tf @@ -0,0 +1,54 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + remote = { + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aks_clusters[key], {})) + } + } + + clusters = local.remote.aks_clusters[var.landingzone.global_settings_key] + k8sconfigs = { for key, value in values(local.clusters) : key => { + host = value.enable_rbac ? value.kube_admin_config.0.host : value.kube_config.0.host + username = value.enable_rbac ? value.kube_admin_config.0.username : value.kube_config.0.username + password = value.enable_rbac ? value.kube_admin_config.0.password : value.kube_config.0.password + client_certificate = value.enable_rbac ? base64decode(value.kube_admin_config.0.client_certificate) : base64decode(value.kube_config.0.client_certificate) + client_key = value.enable_rbac ? base64decode(value.kube_admin_config.0.client_key) : base64decode(value.kube_config.0.client_key) + cluster_ca_certificate = value.enable_rbac ? base64decode(value.kube_admin_config.0.cluster_ca_certificate) : base64decode(value.kube_config.0.cluster_ca_certificate) + } + } + +} diff --git a/caf_solution/add-ons/aks_applications/main.tf b/caf_solution/add-ons/aks_applications/main.tf new file mode 100644 index 000000000..2222bc4d2 --- /dev/null +++ b/caf_solution/add-ons/aks_applications/main.tf @@ -0,0 +1,75 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.43" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 1.13.2" + } + helm = { + source = "hashicorp/helm" + version = "~> 1.3.0" + } + } + required_version = ">= 0.13" +} + + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + + +provider "kubernetes" { + load_config_file = false + host = try(local.k8sconfigs[0].host, null) + username = try(local.k8sconfigs[0].username, null) + password = try(local.k8sconfigs[0].password, null) + client_certificate = try(local.k8sconfigs[0].client_certificate, null) + client_key = try(local.k8sconfigs[0].client_key, null) + cluster_ca_certificate = try(local.k8sconfigs[0].cluster_ca_certificate, null) + alias = "k8s1" +} + +provider "helm" { + kubernetes { + load_config_file = false + host = try(local.k8sconfigs[0].host, null) + username = try(local.k8sconfigs[0].username, null) + password = try(local.k8sconfigs[0].password, null) + client_certificate = try(local.k8sconfigs[0].client_certificate, null) + client_key = try(local.k8sconfigs[0].client_key, null) + cluster_ca_certificate = try(local.k8sconfigs[0].cluster_ca_certificate, null) + } + alias = "helm1" +} + +provider "kubernetes" { + load_config_file = false + host = try(local.k8sconfigs[1].host, null) + username = try(local.k8sconfigs[1].username, null) + password = try(local.k8sconfigs[1].password, null) + client_certificate = try(local.k8sconfigs[1].client_certificate, null) + client_key = try(local.k8sconfigs[1].client_key, null) + cluster_ca_certificate = try(local.k8sconfigs[1].cluster_ca_certificate, null) + alias = "k8s2" +} + +provider "helm" { + kubernetes { + load_config_file = false + host = try(local.k8sconfigs[1].host, null) + username = try(local.k8sconfigs[1].username, null) + password = try(local.k8sconfigs[1].password, null) + client_certificate = try(local.k8sconfigs[1].client_certificate, null) + client_key = try(local.k8sconfigs[1].client_key, null) + cluster_ca_certificate = try(local.k8sconfigs[1].cluster_ca_certificate, null) + } + alias = "helm2" +} \ No newline at end of file diff --git a/caf_solution/add-ons/aks_applications/output.tf b/caf_solution/add-ons/aks_applications/output.tf new file mode 100644 index 000000000..e69de29bb diff --git a/caf_solution/add-ons/aks_applications/variables.tf b/caf_solution/add-ons/aks_applications/variables.tf new file mode 100644 index 000000000..7ad77ea93 --- /dev/null +++ b/caf_solution/add-ons/aks_applications/variables.tf @@ -0,0 +1,36 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_resource_group_name" {} +# variable tfstate_key {} + +variable "global_settings" { + default = {} +} + +# variable tenant_id {} +variable "landingzone" {} + +variable "namespaces" {} + +variable "tags" { + default = null + type = map(any) +} + +variable "helm_charts" {} + +variable "rover_version" { + default = null +} + +variable "cluster_re1_key" { + default = null +} +variable "cluster_re2_key" { + default = null +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops/azdo.tf b/caf_solution/add-ons/azure_devops/azdo.tf new file mode 100644 index 000000000..9d2b42c02 --- /dev/null +++ b/caf_solution/add-ons/azure_devops/azdo.tf @@ -0,0 +1,15 @@ +# The PAT token must be provisioned in a different deployment +provider "azuredevops" { + org_service_url = var.azure_devops.url + personal_access_token = data.azurerm_key_vault_secret.pat.value +} + +data "azurerm_key_vault_secret" "pat" { + name = var.azure_devops.pats["admin"].secret_name + key_vault_id = local.remote.keyvaults[var.azure_devops.pats["admin"].lz_key][var.azure_devops.pats["admin"].keyvault_key].id + +} + +data "azuredevops_project" "project" { + name = var.azure_devops.project +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf b/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf new file mode 100644 index 000000000..7832ba6e9 --- /dev/null +++ b/caf_solution/add-ons/azure_devops/azdo_agent_pools.tf @@ -0,0 +1,52 @@ + +locals { + organization_agent_pools = try(var.azure_devops.organization_agent_pools, {}) + project_agent_pools = try(var.azure_devops.project_agent_pools, {}) +} + + +## Agent pools +## Those pools are created in the organization, not the project +resource "azuredevops_agent_pool" "pool" { + for_each = try(var.azure_devops.organization_agent_pools, {}) + + name = each.value.name + auto_provision = lookup(each.value, "auto_provision", false) +} + +# +# add the agent pools into the project +# + +data "azuredevops_agent_pool" "pool" { + depends_on = [azuredevops_agent_pool.pool] + for_each = try(var.azure_devops.project_agent_pools, {}) + + name = each.value.name +} + +resource "azuredevops_agent_queue" "agent_queue" { + for_each = data.azuredevops_agent_pool.pool + + project_id = data.azuredevops_project.project.id + agent_pool_id = each.value.id + + lifecycle { + ignore_changes = [ + agent_pool_id + ] + } +} + +# +# Grant acccess to queue to all pipelines in the project +# + +resource "azuredevops_resource_authorization" "queue" { + for_each = data.azuredevops_agent_pool.pool + + project_id = data.azuredevops_project.project.id + resource_id = azuredevops_agent_queue.agent_queue[each.key].id + type = "queue" + authorized = true +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops/azdo_pipelines.tf b/caf_solution/add-ons/azure_devops/azdo_pipelines.tf new file mode 100644 index 000000000..6fe4fdcbb --- /dev/null +++ b/caf_solution/add-ons/azure_devops/azdo_pipelines.tf @@ -0,0 +1,43 @@ +data "azuredevops_git_repositories" "repos" { + project_id = data.azuredevops_project.project.id +} + + +locals { + repositories = zipmap(tolist(data.azuredevops_git_repositories.repos.repositories.*.name), tolist(data.azuredevops_git_repositories.repos.repositories)) +} + +resource "azuredevops_build_definition" "build_definition" { + + for_each = try(var.azure_devops.pipelines, {}) + project_id = data.azuredevops_project.project.id + name = each.value.name + path = each.value.folder + + variable_groups = lookup(each.value, "variable_group_keys", null) == null ? null : [ + for key in each.value.variable_group_keys : + azuredevops_variable_group.variable_group[key].id + ] + + repository { + repo_id = local.repositories[each.value.git_repo_name].id + repo_type = each.value.repo_type + yml_path = each.value.yaml + branch_name = lookup(each.value, "branch_name", null) + # service_connection_id = lookup(each.value, "repo_type", null) == "github" ? null : azuredevops_serviceendpoint_azurerm.github[each.value.service_connection_key].id + } + + ci_trigger { + use_yaml = true + } + + dynamic "variable" { + for_each = try(each.value.variables, {}) + + content { + name = variable.key + value = variable.value + } + } + +} diff --git a/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf b/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf new file mode 100644 index 000000000..760919a25 --- /dev/null +++ b/caf_solution/add-ons/azure_devops/azdo_service_endpoint.tf @@ -0,0 +1,36 @@ + +data "azurerm_key_vault_secret" "client_secret" { + depends_on = [module.caf] + for_each = try(var.azure_devops.service_endpoints, {}) + + name = format("%s-client-secret", local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].secret_name_client_secret) + key_vault_id = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].id +} + +resource "azuredevops_serviceendpoint_azurerm" "azure" { + depends_on = [module.caf] + for_each = try(var.azure_devops.service_endpoints, {}) + + project_id = data.azuredevops_project.project.id + service_endpoint_name = each.value.endpoint_name + credentials { + serviceprincipalid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].azuread_application.application_id + serviceprincipalkey = data.azurerm_key_vault_secret.client_secret[each.key].value + } + azurerm_spn_tenantid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].tenant_id + azurerm_subscription_id = each.value.subscription_id + azurerm_subscription_name = each.value.subscription_name +} + +# +# Grant acccess to service endpoint to all pipelines in the project +# + +resource "azuredevops_resource_authorization" "endpoint" { + for_each = azuredevops_serviceendpoint_azurerm.azure + + project_id = data.azuredevops_project.project.id + resource_id = each.value.id + type = "endpoint" + authorized = true +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf b/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf new file mode 100644 index 000000000..7cd1ed1c2 --- /dev/null +++ b/caf_solution/add-ons/azure_devops/azdo_variable_groups.tf @@ -0,0 +1,39 @@ +# +# permissions required: +# - vso.variablegroups_manage (create) +# + vso.buid (update) +# + vso.build_execute (destroy) +# +resource "azuredevops_variable_group" "variable_group" { + for_each = try(var.azure_devops.variable_groups, {}) + + project_id = data.azuredevops_project.project.id + name = each.value.name + description = try(each.value.description, null) + allow_access = try(each.value.allow_access, false) + + dynamic "key_vault" { + for_each = lookup(each.value, "keyvault", null) == null ? [] : [1] + + content { + name = try(each.value.keyvault.lz_key, null) == null ? local.combined.keyvaults[var.landingzone.key][each.value.keyvault.keyvault_key].name : local.combined.keyvaults[each.value.keyvault.lz_key][each.value.keyvault.keyvault_key].name + service_endpoint_id = azuredevops_serviceendpoint_azurerm.azure[each.value.keyvault.serviceendpoint_key].id + } + } + + dynamic "variable" { + for_each = { + for key, variable in each.value.variables : key => { + name = key == "name" ? variable : key + value = key == "name" ? null : variable + } + } + + content { + # When used with Keyvault, the name must be the keyvault secret name and value must not be set + name = variable.value.name + value = variable.value.value + } + } + +} diff --git a/caf_solution/add-ons/azure_devops/backend.azurerm b/caf_solution/add-ons/azure_devops/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_solution/add-ons/azure_devops/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops/documentation/images/pat_token.png b/caf_solution/add-ons/azure_devops/documentation/images/pat_token.png new file mode 100644 index 0000000000000000000000000000000000000000..84fc549c5baa26167b2a975c5ae917e5a46b162e GIT binary patch literal 78143 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 literal 0 HcmV?d00001 diff --git a/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf b/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf new file mode 100644 index 000000000..4295ebf43 --- /dev/null +++ b/caf_solution/add-ons/azure_devops/locals.remote_tfstates.tf @@ -0,0 +1,76 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + diagnostics = { + diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics + } + + + combined = { + aad_apps = merge(local.remote.aad_apps, map(var.landingzone.key, module.caf.aad_apps)) + azuread_groups = merge(local.remote.azuread_groups, map(var.landingzone.key, module.caf.azuread_groups)) + keyvaults = merge(local.remote.keyvaults, map(var.landingzone.key, module.caf.keyvaults)) + managed_identities = merge(local.remote.managed_identities, map(var.landingzone.key, module.caf.managed_identities)) + } + + remote = { + aad_apps = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {})) + } + + azuread_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) + } + + keyvaults = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) + } + + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) + } + + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) + } + } + + +} diff --git a/caf_solution/add-ons/azure_devops/main.tf b/caf_solution/add-ons/azure_devops/main.tf new file mode 100644 index 000000000..3cf3eb96f --- /dev/null +++ b/caf_solution/add-ons/azure_devops/main.tf @@ -0,0 +1,69 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.43" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.0.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + azuredevops = { + source = "microsoft/azuredevops" + version = "~> 0.1.0" + } + tls = { + source = "hashicorp/tls" + version = "~> 2.2.0" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "~>1.1.0" + } + } + required_version = ">= 0.13" +} + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + + +locals { + + + tfstates = merge( + map(var.landingzone.backend_type, + map( + "storage_account_name", var.tfstate_storage_account_name, + "container_name", var.tfstate_container_name, + "resource_group_name", var.tfstate_resource_group_name, + "key", var.tfstate_key, + "level", var.landingzone.level, + "tenant_id", var.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + , + data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates + ) + +} diff --git a/caf_solution/add-ons/azure_devops/output.tf b/caf_solution/add-ons/azure_devops/output.tf new file mode 100644 index 000000000..a46105168 --- /dev/null +++ b/caf_solution/add-ons/azure_devops/output.tf @@ -0,0 +1,6 @@ +output "keyvaults" { + value = map( + var.landingzone.key, module.caf.keyvaults + ) + sensitive = true +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops/readme.md b/caf_solution/add-ons/azure_devops/readme.md new file mode 100644 index 000000000..1ebbb675f --- /dev/null +++ b/caf_solution/add-ons/azure_devops/readme.md @@ -0,0 +1,60 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Azure Devops add-on + +The Azure Devops add-ons allow you to setup you Azure Devops environment as a platform to automate all your subsequent landing zone deployment from level 0 until level 4 through Azure pipelines with self hosted agents. + +* Azure Devops: + - Agent Pools (Organization and Project Level) + - Service Endpoint + - Variables and Variable Groups + - Pipelines + +* Azure (Connection with Azure Devops): + - Azure AD Application + - Custom Role + - Keyvault and access policies for Azure AD App + +Azure Devops add-on landing zone operates at **level 0** + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +## Dependencies + +Landing zone: +* CAF Launchpad (Scenario 200 or above) + +Azure Devops (example): +* Organization: https://dev.azure.com/azure-terraform +* Project : contoso_demo (https://dev.azure.com/azure-terraform/contoso_demo) +* Repo : caf-configuration (https://dev.azure.com/azure-terraform/contoso_demo/_git/caf-configuration) + - In order for pipeline to work properly, YAML file should be in this repo and referred accordingly under pipeline section in azure_devops.tfvars + - sample yaml attached [here](./scenario/200-contoso_demo/pipeline/rover.yaml). + +Azure: +* PAT Token : PAT Token should be updated in keyvault secret that deployed by launchpad LZ as below + +![](./documentation/images/pat_token.png) + +## Deployment + +```bash +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops \ + -tfstate azure_devops-contoso_demo.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo \ + -parallelism 30 \ + -level level0 \ + -env sandpit \ + -a apply + + +# If the tfstates are stored in a different subscription you need to execute the following command +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops \ + -tfstate_subscription_id \ + -tfstate azure_devops-contoso_demo.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo \ + -parallelism 30 \ + -level level0 \ + -env sandpit \ + -a apply +``` + +We are planning to release more examples on how to deploy the Azure Devops Agents. diff --git a/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars b/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars new file mode 100644 index 000000000..bf0bd6c1f --- /dev/null +++ b/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars @@ -0,0 +1,232 @@ + + +azure_devops = { + + url = "https://dev.azure.com/azure-terraform/" + project = "contoso_demo" + + # PAT Token should be updated manually to the keyvault after running launchpad + pats = { + admin = { + secret_name = "azdo-pat-admin" + lz_key = "launchpad" + keyvault_key = "secrets" + } + } + + organization_agent_pools = { + level0 = { + name = "caf-sandpit-level0" + auto_provision = false # When set to false the agent pool is not populated automatically into the devops projects (recommended) + } + level1 = { + name = "caf-sandpit-level1" + auto_provision = false + } + level2 = { + name = "caf-sandpit-level2" + auto_provision = false + } + level3 = { + name = "caf-sandpit-level3" + auto_provision = false + } + level4 = { + name = "caf-sandpit-level4" + auto_provision = false + } + } + + project_agent_pools = { + level0 = { + name = "caf-sandpit-level0" + } + level1 = { + name = "caf-sandpit-level1" + } + level2 = { + name = "caf-sandpit-level2" + } + level3 = { + name = "caf-sandpit-level3" + } + level4 = { + name = "caf-sandpit-level4" + } + } + + service_endpoints = { + contoso_demo = { + endpoint_name = "terraformdev (terraformdev.onmicrosoft.com) - contoso_demo" + subscription_name = "ase-landingzone" + subscription_id = "1d53e782-9f46-4720-b6b3-cff29106e9f6" + aad_app_key = "contoso_demo" + secret_keyvault_key = "devops" + } + } + + variable_groups = { + global = { + name = "release-global" # changing that name requires to change it in the devops agents yaml variables group + allow_access = true + variables = { + HOME_FOLDER_USER = "vsts_azpcontainer" + ROVER_IMAGE = "aztfmod/rover:2010.2808" + TF_CLI_ARGS = "'-no-color'" + TF_CLI_ARGS_init = "" + TF_CLI_ARGS_plan = "'-input=false'" + TF_VAR_ARGS_destroy = "'-auto-approve -refresh=false'" + ENVIRONMENT = "sandpit" + LANDINGZONE_BRANCH = "2010.0.0" + } + } + + level0 = { + name = "release-level0" + allow_access = true + variables = { + TF_VAR_pipeline_level = "level0" + ARM_USE_MSI = "true" + AGENT_POOL = "caf-sandpit-level0" + } + } + + level0_kv = { + name = "release-level0-msi" + allow_access = true + keyvault = { + lz_key = "launchpad" + keyvault_key = "level0" + serviceendpoint_key = "contoso_demo" + } + variables = { + name = "msi-resource-id" + } + } + + level1 = { + name = "release-level1" + allow_access = true + variables = { + TF_VAR_pipeline_level = "level1" + ARM_USE_MSI = "true" + AGENT_POOL = "caf-sandpit-level1" + } + } + + level1_kv = { + name = "release-level1-msi" + allow_access = true + keyvault = { + lz_key = "launchpad" + keyvault_key = "level1" + serviceendpoint_key = "contoso_demo" + } + variables = { + name = "msi-resource-id" + } + } + + level2 = { + name = "release-level2" + allow_access = true + variables = { + TF_VAR_pipeline_level = "level2" + ARM_USE_MSI = "true" + AGENT_POOL = "caf-sandpit-level2" + } + } + + level2_kv = { + name = "release-level2-msi" + allow_access = true + keyvault = { + lz_key = "launchpad" + keyvault_key = "level2" + serviceendpoint_key = "contoso_demo" + } + variables = { + name = "msi-resource-id" + } + } + + level3 = { + name = "release-level3" + allow_access = true + variables = { + TF_VAR_pipeline_level = "level3" + ARM_USE_MSI = "true" + AGENT_POOL = "caf-sandpit-level3" + } + } + + level3_kv = { + name = "release-level3-msi" + allow_access = true + keyvault = { + lz_key = "launchpad" + keyvault_key = "level3" + serviceendpoint_key = "contoso_demo" + } + variables = { + name = "msi-resource-id" + } + } + } + + pipelines = { + + # + # Agent pools + # + + devops_agent_level1_plan = { + name = "devops_agent_level1_plan" + folder = "\\configuration\\level1" + yaml = "configuration/pipeline/rover.yaml" + repo_type = "TfsGit" + git_repo_name = "caf-configuration" + variables = { + landingZoneName = "azdo-agent-level1", + terraformAction = "plan", + tfstateName = "azdo-agent-level1.tfstate" + configPath = "/configuration/level1/azuredevops/agent" + landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" + level = "level1" + } + variable_group_keys = ["global", "level0", "level0_kv"] + } + devops_agent_level1_apply = { + name = "devops_agent_level1_apply" + folder = "\\configuration\\level1" + yaml = "configuration/pipeline/rover.yaml" + repo_type = "TfsGit" + git_repo_name = "caf-configuration" + variables = { + landingZoneName = "azdo-agent-level1", + terraformAction = "apply", + tfstateName = "azdo-agent-level1.tfstate" + configPath = "/configuration/level1/azuredevops/agent" + landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" + level = "level1" + } + variable_group_keys = ["global", "level0", "level0_kv"] + } + devops_agent_level1_destroy = { + name = "devops_agent_level1_destroy" + folder = "\\configuration\\level1" + yaml = "configuration/pipeline/rover.yaml" + repo_type = "TfsGit" + git_repo_name = "caf-configuration" + variables = { + landingZoneName = "azdo-agent-level1", + terraformAction = "destroy", + tfstateName = "azdo-agent-level1.tfstate" + configPath = "/configuration/level1/azuredevops/agent" + landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" + level = "level1" + } + variable_group_keys = ["global", "level0", "level0_kv"] + } + } +} diff --git a/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars b/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars new file mode 100644 index 000000000..e4d8208f3 --- /dev/null +++ b/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars @@ -0,0 +1,123 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level0" + key = "azdo-contoso_demo" + tfstates = { + launchpad = { + level = "current" + tfstate = "caf_launchpad.tfstate" + } + } +} + +resource_groups = { + rg1 = { + name = "devops-agents-security" + } +} + + +keyvaults = { + devops = { + name = "devops" + resource_group_key = "rg1" + sku_name = "standard" + + creation_policies = { + keyvault_level0_rw = { + # Reference a key to an azure ad group + lz_key = "launchpad" + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + } +} + +keyvault_access_policies_azuread_apps = { + level0 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } + level1 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } + level2 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } + level3 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } + level4 = { + contoso_demo = { + lz_key = "launchpad" + azuread_app_key = "contoso_demo" + secret_permissions = ["Get", "List"] + } + } +} + + +azuread_apps = { + + contoso_demo = { + useprefix = true + application_name = "caf-level4-contoso_demo" + password_expire_in_days = 60 + tenant_name = "terraformdev.onmicrosoft.com" + reply_urls = ["https://localhost"] + keyvaults = { + devops = { + secret_prefix = "aadapp-caf-level4-azdo-contoso_demo" + } + } + } + +} + +custom_role_definitions = { + + caf-azdo-to-azure-subscription = { + name = "caf-azure-devops-azure-app-service-improvement-program-TO-azure-subscription" + useprefix = true + description = "CAF Custom role for service principal in Azure Devops to access resources" + permissions = { + actions = [ + "Microsoft.Resources/subscriptions/read", + "Microsoft.KeyVault/vaults/read" + ] + } + } + +} + + +role_mapping = { + custom_role_mapping = { + subscriptions = { + logged_in_subscription = { + "caf-azdo-to-azure-subscription" = { + azuread_apps = { + keys = ["contoso_demo"] + } + } + } + } + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml b/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml new file mode 100644 index 000000000..156fb9983 --- /dev/null +++ b/caf_solution/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml @@ -0,0 +1,70 @@ +parameters: + - name: timeoutInMinutes + displayName: 'Timeout in minutes' + type: number + default: 60 + + variables: + - group: release-global + + resources: + containers: + - container: rover + image: $(ROVER_IMAGE) + options: --user 0:0 -e TF_PLUGIN_CACHE_DIR="/home/$(HOME_FOLDER_USER)/plugin-cache" -e TF_DATA_DIR="/home/$(HOME_FOLDER_USER)" + + trigger: none + + jobs: + - job: CAF_Rover + + displayName: Azure Landing Zone + + pool: $(AGENT_POOL) + + continueOnError: false + + workspace: + clean: all + + container: rover + + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + + steps: + - checkout: self + + - bash: | + git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null + + az login --identity -u $(msi-resource-id) + + /tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \ + -tfstate $(tfstateName) \ + -var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \ + -parallelism=30 \ + -level $(level) \ + -a $(terraformAction) \ + -env $(ENVIRONMENT) + + condition: ne(variables['terraformAction'], 'destroy') + failOnStderr: true + displayName: 'Terraform $(terraformAction)' + + - bash: | + git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null + + az login --identity -u $(msi-resource-id) + + /tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \ + -tfstate $(tfstateName) \ + -var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \ + -parallelism=30 \ + -level $(level) \ + -a $(terraformAction) \ + -auto-approve \ + -env $(ENVIRONMENT) + + condition: eq(variables['terraformAction'], 'destroy') + failOnStderr: true + displayName: 'Terraform destroy' diff --git a/caf_solution/add-ons/azure_devops/solution.tf b/caf_solution/add-ons/azure_devops/solution.tf new file mode 100644 index 000000000..718e923ba --- /dev/null +++ b/caf_solution/add-ons/azure_devops/solution.tf @@ -0,0 +1,36 @@ +module "caf" { + source = "aztfmod/caf/azurerm" + version = "~>5.1.0" + + current_landingzone_key = var.landingzone.key + tenant_id = var.tenant_id + tfstates = local.tfstates + tags = local.tags + global_settings = local.global_settings + diagnostics = local.diagnostics + diagnostic_storage_accounts = var.diagnostic_storage_accounts + logged_user_objectId = var.logged_user_objectId + logged_aad_app_objectId = var.logged_aad_app_objectId + resource_groups = var.resource_groups + storage_accounts = var.storage_accounts + azuread_groups = var.azuread_groups + keyvaults = var.keyvaults + keyvault_access_policies = var.keyvault_access_policies + keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps + role_mapping = var.role_mapping + custom_role_definitions = var.custom_role_definitions + azuread_apps = var.azuread_apps + compute = { + virtual_machines = var.virtual_machines + } + storage = { + storage_account_blobs = var.storage_account_blobs + } + + remote_objects = { + keyvaults = local.remote.keyvaults + vnets = local.remote.vnets + managed_identities = local.remote.managed_identities + azuread_groups = local.remote.azuread_groups + } +} diff --git a/caf_solution/add-ons/azure_devops/variables.tf b/caf_solution/add-ons/azure_devops/variables.tf new file mode 100644 index 000000000..87dcc831a --- /dev/null +++ b/caf_solution/add-ons/azure_devops/variables.tf @@ -0,0 +1,102 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} + +variable "global_settings" { + default = {} +} +variable "tenant_id" {} +variable "landingzone" { +} +variable "rover_version" { + default = null +} + +variable "logged_user_objectId" { + default = null +} +variable "logged_aad_app_objectId" { + default = null +} +variable "tags" { + default = null +} +variable "app_service_environments" { + default = {} +} +variable "app_service_plans" { + default = {} +} +variable "app_services" { + default = {} +} +variable "diagnostics_definition" { + default = {} +} +variable "resource_groups" { + default = {} +} +variable "network_security_group_definition" { + default = {} +} +variable "vnets" { + default = {} +} +variable "azurerm_redis_caches" { + default = {} +} +variable "mssql_servers" { + default = {} +} +variable "storage_accounts" { + default = {} +} +variable "storage_account_blobs" { + default = {} +} +variable "azuread_groups" { + default = {} +} +variable "keyvaults" { + default = {} +} +variable "keyvault_access_policies" { + default = {} +} +variable "keyvault_access_policies_azuread_apps" { + default = {} +} +variable "virtual_machines" { + default = {} +} +variable "diagnostic_storage_accounts" { + default = {} +} +variable "virtual_machine_extension_scripts" { + default = {} +} +variable "azure_devops" { + default = {} +} +variable "role_mapping" { + default = {} +} +variable "custom_role_definitions" { + default = {} +} +variable "azuread_apps" { + default = {} +} +variable "dynamic_keyvault_secrets" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops_agent/backend.azurerm b/caf_solution/add-ons/azure_devops_agent/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf b/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf new file mode 100644 index 000000000..63f0367a4 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/dynamic_secrets.tf @@ -0,0 +1,11 @@ + +module "dynamic_keyvault_secrets" { + source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" + version = "~>5.1.0" + + for_each = try(var.dynamic_keyvault_secrets, {}) + + settings = each.value + keyvault = module.caf.keyvaults[each.key] + objects = module.caf +} diff --git a/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf b/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf new file mode 100644 index 000000000..5372db558 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf @@ -0,0 +1,44 @@ + +resource "azurerm_virtual_machine_extension" "devops_selfhosted_agent" { + for_each = { + for key, value in var.extensions : key => value + if key == "devops_selfhosted_agent" + } + + name = "install_azure_devops_agent" + + virtual_machine_id = var.virtual_machine_id + publisher = "Microsoft.Azure.Extensions" + type = "CustomScript" + type_handler_version = "2.1" + + #timestamp: use this field only to trigger a re-run of the script by changing value of this field. + # Any integer value is acceptable; it must only be different than the previous value. + settings = jsonencode( + { + "timestamp" : each.value.version, + "fileUris" : concat(local.devops_selfhosted_agent.file_uris, local.devops_selfhosted_agent.storage_account_blobs_urls), + + } + ) + protected_settings = jsonencode( + { + "commandToExecute" : format("bash %s '%s' '%s' '%s' '%s' '%s' '%s' '%s'", var.extensions[each.key].agent_init_script, var.settings[each.key].azure_devops.url, var.settings[each.key].agent_pat, var.settings[each.key].azure_devops.agent_pool.name, var.settings[each.key].azure_devops.agent_pool.agent_name_prefix, var.settings[each.key].azure_devops.agent_pool.num_agents, var.settings[each.key].admin_username, var.settings[each.key].azure_devops.rover_version) + } + ) + +} + +locals { + devops_selfhosted_agent = { + file_uris = flatten( + [ + for file_uris_key, file in try(var.extensions.devops_selfhosted_agent.fileUris, {}) : [ + for file_uri_key in file.storage_blob_keys : var.settings.devops_selfhosted_agent.storage_accounts[file.storage_account_key].containers[file.container_key].blobs[file_uri_key].url + ] + ] + ) + + storage_account_blobs_urls = try(var.settings.devops_selfhosted_agent.storage_account_blobs_urls, []) + } +} diff --git a/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf b/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf new file mode 100644 index 000000000..9b8d2f8c3 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/extensions/variables.tf @@ -0,0 +1,3 @@ +variable "virtual_machine_id" {} +variable "extensions" {} +variable "settings" {} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf b/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf new file mode 100644 index 000000000..fcc2fc189 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/locals.current_tfstates.tf @@ -0,0 +1,74 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + diagnostics = { + diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics + } + + + combined = { + aad_apps = merge(local.remote.aad_apps, map(var.landingzone.key, module.caf.aad_apps)) + azuread_groups = merge(local.remote.azuread_groups, map(var.landingzone.key, module.caf.azuread_groups)) + keyvaults = merge(local.remote.keyvaults, map(var.landingzone.key, module.caf.keyvaults)) + managed_identities = merge(local.remote.managed_identities, map(var.landingzone.key, module.caf.managed_identities)) + } + + remote = { + aad_apps = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {})) + } + + azuread_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) + } + + keyvaults = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) + } + + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) + } + + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) + } + } +} diff --git a/caf_solution/add-ons/azure_devops_agent/main.tf b/caf_solution/add-ons/azure_devops_agent/main.tf new file mode 100644 index 000000000..67d570897 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/main.tf @@ -0,0 +1,69 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.43" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.0.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + azuredevops = { + source = "microsoft/azuredevops" + version = "~> 0.1.1" + } + tls = { + source = "hashicorp/tls" + version = "~> 2.2.0" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "~>1.1.0" + } + } + required_version = ">= 0.13" +} + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + + +locals { + + + tfstates = merge( + map(var.landingzone.key, + map( + "storage_account_name", var.tfstate_storage_account_name, + "container_name", var.tfstate_container_name, + "resource_group_name", var.tfstate_resource_group_name, + "key", var.tfstate_key, + "level", var.landingzone.level, + "tenant_id", var.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + , + data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates + ) + +} diff --git a/caf_solution/add-ons/azure_devops_agent/output.tf b/caf_solution/add-ons/azure_devops_agent/output.tf new file mode 100644 index 000000000..e19cb88aa --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/output.tf @@ -0,0 +1,34 @@ +output "managed_identities" { + value = local.combined.managed_identities + sensitive = false +} + +output "azuread_groups" { + value = local.combined.azuread_groups + sensitive = true +} + +output "keyvaults" { + value = local.combined.keyvaults + sensitive = false +} + +output "vnets" { + value = local.remote.vnets + sensitive = false +} + +output "global_settings" { + value = local.global_settings + sensitive = true +} + +output "diagnostics" { + value = local.diagnostics + sensitive = true +} + +output "tfstates" { + value = local.tfstates + sensitive = true +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops_agent/readme.md b/caf_solution/add-ons/azure_devops_agent/readme.md new file mode 100644 index 000000000..dd7b29571 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/readme.md @@ -0,0 +1,54 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Azure Devops Agent add-on + +The Azure Devops Agent add-ons is the continuation of Self Hosted Agent implementation for Azure Devops environment that deployed in Azure Devops add on LZ. This will set up the underlying resources required for Agent in Azure. + +* Azure Virtual Machine to host the Agent +* Azure VM Extension to connect the VM to Azure Devops self hosted agent +* Storage account to put the script for VM Extension +* Key Vault to store the SSH key of the VM + +Azure Devops (Self Hosted Agent) add-on landing zone operates base on agent level for example for agent level0 will operates at **level 0** and agent level1 will operates at **level 1** + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +## Dependencies + +Landing zone: +* CAF Launchpad +* Azure DevOps add on (example: scenario 200-contoso_demo) + +## Deployment + +### Deploy the Azure Devops agent for level0 +```bash +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ + -tfstate level0_azure_devops_agents.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0 \ + -parallelism 30 \ + -level level0 \ + -env sandpit \ + -a apply +``` + +### Deploy the Azure Devops agent for level1 +```bash +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ + -tfstate azdo-agent-level1.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1 \ + -parallelism 30 \ + -level level1 \ + -env sandpit \ + -a apply + + +# If the tfstates are stored in a different subscription you need to execute the following command + +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ + -tfstate_subscription_id \ + -tfstate azdo-agent-level1.tfstate \ + -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1 \ + -parallelism 30 \ + -level level1 \ + -env sandpit \ + -a apply +``` \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars new file mode 100644 index 000000000..0141decf0 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars @@ -0,0 +1,64 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level0" + key = "azdo-agent-level0" + tfstates = { + launchpad = { + level = "current" + tfstate = "caf_launchpad.tfstate" + } + azdo-contoso_demo = { + level = "current" + tfstate = "azure_devops-contoso_demo" + } + } +} + +resource_groups = { + rg1 = { + name = "devops-agents-level0" + } +} + +azure_devops = { + + # Rover version to apply to the devops self-hosted agents during the setup. + rover_version = "aztfmod/rover:2010.2808" + url = "https://dev.azure.com/azure-terraform/" + + pats = { + agent = { + secret_name = "azdo-pat-agent" + keyvault_key = "secrets" + lz_key = "launchpad" + } + } + + agent_pool = { + name = "caf-sandpit-level0" + auto_provision = true + num_agents = 4 + agent_name_prefix = "agent" + } + +} + +role_mapping = { + built_in_role_mapping = { + storage_accounts = { + scripts_region1 = { + "Storage Blob Data Contributor" = { + azuread_groups = { + lz_key = "launchpad" + keys = ["keyvault_level0_rw"] + } + managed_identities = { + lz_key = "launchpad" + keys = ["level0"] + } + } + } + } + } +} diff --git a/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars new file mode 100644 index 000000000..35f188ba7 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars @@ -0,0 +1,28 @@ + +keyvaults = { + ssh = { + name = "sshl0" + resource_group_key = "rg1" + sku_name = "premium" + soft_delete_enabled = true + + creation_policies = { + keyvault_level0_rw = { + # Reference a key to an azure ad group + lz_key = "launchpad" + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } + +} diff --git a/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars new file mode 100644 index 000000000..0af2a98f2 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars @@ -0,0 +1,42 @@ + +storage_accounts = { + # Is used to store the azure devops deployment script to setup the Azure Devops Selfhosted agents + scripts_region1 = { + name = "scriptsl0" + resource_group_key = "rg1" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + allow_blob_public_access = true + + containers = { + scripts = { + name = "deployment-scripts" + container_access_type = "blob" + } + } + } +} + +# Attributes available https://www.terraform.io/docs/providers/azurerm/r/storage_blob.html +storage_account_blobs = { + devops_runtime_baremetal = { + storage_account_key = "scripts_region1" + storage_container_name = "deployment-scripts" + name = "devops_runtime_baremetal.sh" + source = "scripts/devops_runtime_baremetal.sh" + } +} + +diagnostic_storage_accounts = { + # Stores boot diagnostic for region1 + bootdiag_region1 = { + name = "bootl4" + resource_group_key = "rg1" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } +} + diff --git a/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars new file mode 100644 index 000000000..3140b94e1 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars @@ -0,0 +1,79 @@ + +# Virtual machines +virtual_machines = { + + # Configuration to deploy a bastion host linux virtual machine + level0 = { + resource_group_key = "rg1" + provision_vm_agent = true + boot_diagnostics_storage_account_key = "bootdiag_region1" + + os_type = "linux" + + keyvault_key = "ssh" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + lz_key = "launchpad" + vnet_key = "devops_region1" + subnet_key = "release_agent_level0" + name = "0-release-agent-level0" + enable_ip_forwarding = false + internal_dns_name_label = "release-agent-level0" + } + } + + virtual_machine_settings = { + linux = { + name = "release-agent-level0" + size = "Standard_F2s_v2" + admin_username = "adminuser" + disable_password_authentication = true + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "release-agent-level0-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference = { + publisher = "canonical" + offer = "0001-com-ubuntu-server-focal" + sku = "20_04-lts" + version = "latest" + } + + identity = { + type = "UserAssigned" + + remote = { + launchpad = { + managed_identity_keys = [ + "level0", + ] + } + } + } + + + } + } + + virtual_machine_extensions = { + devops_selfhosted_agent = { + version = 1 + virtual_machine_key = "vm_devops_level0" + agent_init_script = "devops_runtime_baremetal.sh" + storage_account_blobs = [ + "devops_runtime_baremetal" + ] + } + } + + } +} diff --git a/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars new file mode 100644 index 000000000..7197d9c73 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars @@ -0,0 +1,68 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "azdo-agent-level0" + level = "level1" + key = "azdo-agent-level1" + tfstates = { + azdo-agent-level0 = { + level = "lower" + tfstate = "level0_azure_devops_agents.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + azdo-contoso_demo = { + level = "lower" + tfstate = "azure_devops-contoso_demo" + } + } +} + +resource_groups = { + rg1 = { + name = "devops-agents-level0" + } +} + +azure_devops = { + + # Rover version to apply to the devops self-hosted agents during the setup. + rover_version = "aztfmod/rover:2010.2808" + url = "https://dev.azure.com/azure-terraform/" + + pats = { + agent = { + secret_name = "azdo-pat-agent" + keyvault_key = "secrets" + lz_key = "launchpad" + } + } + + agent_pool = { + name = "caf-sandpit-level1" + auto_provision = true + num_agents = 4 + agent_name_prefix = "agent" + } + +} + +role_mapping = { + built_in_role_mapping = { + storage_accounts = { + scripts_region1 = { + "Storage Blob Data Contributor" = { + azuread_groups = { + lz_key = "launchpad" + keys = ["keyvault_level0_rw"] + } + managed_identities = { + lz_key = "launchpad" + keys = ["level0", "level1"] + } + } + } + } + } +} diff --git a/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars new file mode 100644 index 000000000..f25881503 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars @@ -0,0 +1,32 @@ + +keyvaults = { + ssh = { + name = "sshl1" + resource_group_key = "rg1" + sku_name = "premium" + soft_delete_enabled = true + + creation_policies = { + keyvault_level0_rw = { + # Reference a key to an azure ad group + lz_key = "launchpad" + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + msi_level0 = { + lz_key = "launchpad" + managed_identity_key = "level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars new file mode 100644 index 000000000..5ee9634cf --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars @@ -0,0 +1,42 @@ + +storage_accounts = { + # Is used to store the azure devops deployment script to setup the Azure Devops Selfhosted agents + scripts_region1 = { + name = "scriptsl1" + resource_group_key = "rg1" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + allow_blob_public_access = true + + containers = { + scripts = { + name = "deployment-scripts" + container_access_type = "blob" + } + } + } +} + +# Attributes available https://www.terraform.io/docs/providers/azurerm/r/storage_blob.html +storage_account_blobs = { + devops_runtime_baremetal = { + storage_account_key = "scripts_region1" + storage_container_name = "deployment-scripts" + name = "devops_runtime_baremetal.sh" + source = "scripts/devops_runtime_baremetal.sh" + } +} + +diagnostic_storage_accounts = { + # Stores boot diagnostic for region1 + bootdiag_region1 = { + name = "bootl1" + resource_group_key = "rg1" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + access_tier = "Cool" + } +} + diff --git a/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars new file mode 100644 index 000000000..41a40da84 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars @@ -0,0 +1,77 @@ + +# Virtual machines +virtual_machines = { + + # Configuration to deploy a bastion host linux virtual machine + level1 = { + resource_group_key = "rg1" + provision_vm_agent = true + boot_diagnostics_storage_account_key = "bootdiag_region1" + + os_type = "linux" + + keyvault_key = "ssh" + + # Define the number of networking cards to attach the virtual machine + networking_interfaces = { + nic0 = { + # Value of the keys from networking.tfvars + lz_key = "launchpad" + vnet_key = "devops_region1" + subnet_key = "release_agent_level1" + name = "0-release-agent-level1" + enable_ip_forwarding = false + internal_dns_name_label = "release-agent-level1" + } + } + + virtual_machine_settings = { + linux = { + name = "release-agent-level1" + size = "Standard_F2s_v2" + admin_username = "adminuser" + disable_password_authentication = true + + # Value of the nic keys to attach the VM. The first one in the list is the default nic + network_interface_keys = ["nic0"] + + os_disk = { + name = "release-agent-level1-os" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference = { + publisher = "canonical" + offer = "0001-com-ubuntu-server-focal" + sku = "20_04-lts" + version = "latest" + } + + identity = { + type = "UserAssigned" + + remote = { + lz_key = "launchpad" + managed_identity_keys = [ + "level1", + ] + } + } + + + } + } + + virtual_machine_extensions = { + devops_selfhosted_agent = { + version = 1 + agent_init_script = "devops_runtime_baremetal.sh" + storage_account_blobs = [ + "devops_runtime_baremetal" + ] + } + } + + } +} diff --git a/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config b/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config new file mode 100644 index 000000000..5bed7c472 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config @@ -0,0 +1,117 @@ +#cloud-config +apt: + preserve_sources_list: true + sources: + azure-cli.list: + source: "deb https://packages.microsoft.com/repos/azure-cli/ bionic main" + key: | + -----BEGIN PGP PUBLIC KEY BLOCK----- + Version: GnuPG v1.4.7 (GNU/Linux) + + mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT + LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV + 7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag + OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j + H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr + M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs + ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC + AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH + /32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe + MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy + 7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV + KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ + XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+ + NdCFTW7wY0Fb1fWJ+/KTsC4= + =J6gs + -----END PGP PUBLIC KEY BLOCK----- + docker.list: + source: "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" + key: | + -----BEGIN PGP PUBLIC KEY BLOCK----- + + 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 + YT90qFF93M3v01BbxP+EIY2/9tiIPbrd + =0YYh + -----END PGP PUBLIC KEY BLOCK----- +package_update: true + +packages: + - docker-ce + - azure-cli + - ca-certificates + - curl + - apt-transport-https + - lsb-release + - jq + +snap: + commands: + - snap install kubectl --classic + +apt_upgrade: true + + # Install docker-compose +runcmd: + - [ sh, -c, 'curl -L https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep "tag_name" | cut -d \" -f4)/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose' ] + - [ sh, -c, 'sudo chmod +x /usr/local/bin/docker-compose' ] + +# Add default auto created user to docker group +system_info: + default_user: + groups: [docker] \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh b/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh new file mode 100644 index 000000000..7abc06a08 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh @@ -0,0 +1,109 @@ +#!/bin/sh + +url=${1} +pat_token=${2} +agent_pool=${3} +agent_prefix=${4} +num_agent=${5} +admin_user=${6} +rover_version="${7}" + +error() { + local parent_lineno="$1" + local message="$2" + local code="${3:-1}" + if [[ -n "$message" ]] ; then + >&2 echo -e "\e[41mError on or near line ${parent_lineno}: ${message}; exiting with status ${code}\e[0m" + else + >&2 echo -e "\e[41mError on or near line ${parent_lineno}; exiting with status ${code}\e[0m" + fi + echo "" + exit "${code}" +} + +function cleanup { + echo "calling cleanup" + + echo "stopping the service" + sudo ./svc.sh stop || true + echo "uninstall the service" + sudo ./svc.sh uninstall || true + echo "un-register from AZDO" + sudo -u ${admin_user} ./config.sh remove --unattended --auth pat --token ${pat_token} || true +} + +set -ETe +trap 'error ${LINENO}' ERR 1 2 3 6 + +#strict mode, fail on error +# set -euo pipefail + +echo "start" + +echo "install Ubuntu packages" + +# To make it easier for build and release pipelines to run apt-get, +# configure apt to not require confirmation (assume the -y argument by default) +export DEBIAN_FRONTEND=noninteractive +echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes + +apt-get update +apt-get install -y --no-install-recommends \ + ca-certificates \ + jq \ + apt-transport-https \ + docker.io \ + sudo + +echo "Allowing agent to run docker" + +usermod -aG docker ${admin_user} +systemctl daemon-reload +systemctl enable docker +service docker start +docker --version + +# Pull rover base image +echo "Rover docker image ${rover_version}" +docker pull "${rover_version}" 2>/dev/null + +echo "Installing Azure CLI" + +curl -sL https://aka.ms/InstallAzureCLIDeb | bash + +echo "install VSTS Agent" + +cd /home/${admin_user} +mkdir -p agent +cd agent + +AGENTRELEASE="$(curl -s https://api.github.com/repos/Microsoft/azure-pipelines-agent/releases/latest | grep -oP '"tag_name": "v\K(.*)(?=")')" +AGENTURL="https://vstsagentpackage.azureedge.net/agent/${AGENTRELEASE}/vsts-agent-linux-x64-${AGENTRELEASE}.tar.gz" +echo "Release "${AGENTRELEASE}" appears to be latest" +echo "Downloading..." +curl -s ${AGENTURL} -o agent_package.tar.gz + +for agent_num in $(seq 1 ${num_agent}); do + agent_dir="agent-$agent_num" + mkdir -p "$agent_dir" + cd "$agent_dir" + echo "moving to $agent_dir" + + cleanup + + name="${agent_prefix}-${agent_num}" + echo "installing agent $name" + tar zxvf ../agent_package.tar.gz + chmod -R 777 . + echo "extracted" + ./bin/installdependencies.sh || true + echo "dependencies installed" + sudo -u ${admin_user} ./config.sh --unattended --url "${url}" --auth pat --token "${pat_token}" --pool "${agent_pool}" --agent "${name}" --acceptTeeEula --replace --work ./_work --runAsService + echo "configuration done" + ./svc.sh install + echo "service installed" + ./svc.sh start + echo "service started" + echo "config done" + cd .. +done diff --git a/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh b/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh new file mode 100644 index 000000000..eb0b8cc2a --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc +sudo sh -c 'echo -e "[azure-cli] +name=Azure CLI +baseurl=https://packages.microsoft.com/yumrepos/azure-cli +enabled=1 +gpgcheck=1 +gpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/azure-cli.repo' +sudo yum -y install azure-cli + +sudo yum install -y yum-utils device-mapper-persistent-data lvm2 +sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo +sudo yum makecache fast +sudo yum install -y docker-ce +sudo systemctl daemon-reload +sudo systemctl enable docker +sudo service docker start +sudo docker --version + +sudo az login --identity + +az acr login --name ${7} +sudo docker pull "${7}/${5}" + +for agent_num in $(seq 1 ${6}); do + name="${4}-${agent_num}" + sudo docker run -d -v /var/run/docker.sock:/var/run/docker.sock --name ${name} -e AZP_URL=${1} -e AZP_TOKEN=${2} -e AZP_POOL="${3}" -e AZP_AGENT_NAME="${name}" "${7}/${5}" +done \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops_agent/solution.tf b/caf_solution/add-ons/azure_devops_agent/solution.tf new file mode 100644 index 000000000..3316f9894 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/solution.tf @@ -0,0 +1,37 @@ +module "caf" { + source = "aztfmod/caf/azurerm" + version = "~>5.1.0" + + current_landingzone_key = var.landingzone.key + tenant_id = var.tenant_id + tfstates = local.tfstates + tags = local.tags + global_settings = local.global_settings + diagnostics = local.diagnostics + diagnostic_storage_accounts = var.diagnostic_storage_accounts + logged_user_objectId = var.logged_user_objectId + logged_aad_app_objectId = var.logged_aad_app_objectId + resource_groups = var.resource_groups + storage_accounts = var.storage_accounts + azuread_groups = var.azuread_groups + keyvaults = var.keyvaults + keyvault_access_policies = var.keyvault_access_policies + managed_identities = var.managed_identities + role_mapping = var.role_mapping + custom_role_definitions = var.custom_role_definitions + azuread_apps = var.azuread_apps + compute = { + virtual_machines = var.virtual_machines + } + storage = { + storage_account_blobs = var.storage_account_blobs + } + + # Pass the remote objects you need to connect to. + remote_objects = { + keyvaults = local.remote.keyvaults + vnets = local.remote.vnets + managed_identities = local.remote.managed_identities + azuread_groups = local.remote.azuread_groups + } +} diff --git a/caf_solution/add-ons/azure_devops_agent/variables.tf b/caf_solution/add-ons/azure_devops_agent/variables.tf new file mode 100644 index 000000000..45c344a59 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/variables.tf @@ -0,0 +1,102 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} + +variable "global_settings" { + default = {} +} +variable "tenant_id" {} +variable "landingzone" { +} +variable "rover_version" { + default = null +} + +variable "logged_user_objectId" { + default = null +} +variable "logged_aad_app_objectId" { + default = null +} +variable "tags" { + default = null +} +variable "app_service_environments" { + default = {} +} +variable "app_service_plans" { + default = {} +} +variable "app_services" { + default = {} +} +variable "diagnostics_definition" { + default = {} +} +variable "resource_groups" { + default = {} +} +variable "network_security_group_definition" { + default = {} +} +variable "vnets" { + default = {} +} +variable "azurerm_redis_caches" { + default = {} +} +variable "mssql_servers" { + default = {} +} +variable "storage_accounts" { + default = {} +} +variable "storage_account_blobs" { + default = {} +} +variable "azuread_groups" { + default = {} +} +variable "keyvaults" { + default = {} +} +variable "keyvault_access_policies" { + default = {} +} +variable "virtual_machines" { + default = {} +} +variable "diagnostic_storage_accounts" { + default = {} +} +variable "virtual_machine_extension_scripts" { + default = {} +} +variable "azure_devops" { + default = {} +} +variable "role_mapping" { + default = {} +} +variable "custom_role_definitions" { + default = {} +} +variable "azuread_apps" { + default = {} +} +variable "dynamic_keyvault_secrets" { + default = {} +} +variable "managed_identities" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf b/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf new file mode 100644 index 000000000..898d03288 --- /dev/null +++ b/caf_solution/add-ons/azure_devops_agent/vm_extention_devops_agent.tf @@ -0,0 +1,37 @@ + + +# Get PAT token from keyvault +data "azurerm_key_vault_secret" "agent_pat" { + depends_on = [module.caf] + for_each = { + for key, value in try(var.virtual_machines, {}) : key => value + if try(value.virtual_machine_extensions, null) != null + } + + name = var.azure_devops.pats.agent.secret_name + key_vault_id = try(var.azure_devops.pats["agent"].lz_key, null) == null ? local.combined.keyvaults[var.landingzone.key][var.azure_devops.pats["agent"].keyvault_key].id : local.combined.keyvaults[var.azure_devops.pats["agent"].lz_key][var.azure_devops.pats["agent"].keyvault_key].id +} + + +module "vm_extensions" { + source = "./extensions" + depends_on = [module.caf] + for_each = { + for key, value in try(var.virtual_machines, {}) : key => value + if try(value.virtual_machine_extensions, null) != null + } + + virtual_machine_id = module.caf.virtual_machines[each.key].id + extensions = each.value.virtual_machine_extensions + settings = { + devops_selfhosted_agent = { + storage_accounts = module.caf.storage_accounts + agent_pat = data.azurerm_key_vault_secret.agent_pat[each.key].value + admin_username = each.value.virtual_machine_settings[each.value.os_type].admin_username + azure_devops = var.azure_devops + storage_account_blobs_urls = [ + for key, value in try(var.storage_account_blobs, []) : module.caf.storage_account_blobs[key].url + ] + } + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/README.md b/caf_solution/add-ons/caf_eslz/README.md new file mode 100644 index 000000000..afef4f046 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/README.md @@ -0,0 +1,44 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Enterprise-Scale + +The foundations landing zone allows you to manage the core components of an environment: + +* Management groups +* Policies + +Foundations landing zone operates at **level 1**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +
+ +## Components + +CAF eslz leverages the enterprise-scale module in order to deploy its core components. + +For full description on enterprise_scale module usage, please [refer to the repository](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale) + +This is currently work in progress. +Use the following configuration file in order to get started with the enterprise-scale module integration: + +```bash +# This example will setup the complete enterprise-scale fundamentals management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription + +rover -lz /tf/caf/public/landingzones/caf_eslz \ + -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/100 \ + -level level1 \ + -a [plan|apply|destroy] + +# This example will setup custom enterprise-scale management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription + +rover -lz /tf/caf/public/landingzones/caf_eslz \ + -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/200 \ + -level level1 \ + -a [plan|apply|destroy] + +# If the tfstates are stored in a different subscription you need to execute the following command +rover -lz /tf/caf/public/landingzones/caf_eslz \ + -tfstate_subscription_id \ + -var-folder /tf/caf/public/landingzones/caf_foundations/scenario/200 \ + -level level1 \ + -a apply +``` diff --git a/caf_solution/add-ons/caf_eslz/backend.azurerm b/caf_solution/add-ons/caf_eslz/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/es_main.tf b/caf_solution/add-ons/caf_eslz/es_main.tf new file mode 100644 index 000000000..a2dff70a0 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/es_main.tf @@ -0,0 +1,25 @@ +# For full description on enterprise_scale module usage, please refer to https://github.com/Azure/terraform-azurerm-caf-enterprise-scale + +module "enterprise_scale" { + source = "Azure/caf-enterprise-scale/azurerm" + version = "0.0.8" + + root_parent_id = data.azurerm_client_config.current.tenant_id + + root_id = var.root_id + root_name = var.root_name + deploy_core_landing_zones = var.deploy_core_landing_zones + + # Control whether to deploy the demo landing zones // default = false + deploy_demo_landing_zones = var.deploy_demo_landing_zones + + # Set a path for the custom archetype library path + library_path = try(format("%s", var.library_path), "") + + # Deploys the custom landing zone configuration as defined in config file + custom_landing_zones = var.custom_landing_zones + subscription_id_overrides = var.subscription_id_overrides + archetype_config_overrides = var.archetype_config_overrides + + default_location = local.global_settings.regions[local.global_settings.default_region] +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf b/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf new file mode 100644 index 000000000..ee887a2d1 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf @@ -0,0 +1,46 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + diagnostics = { + diagnostics_definition = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition + diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics + event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.event_hub_namespaces + } + +} diff --git a/caf_solution/add-ons/caf_eslz/main.tf b/caf_solution/add-ons/caf_eslz/main.tf new file mode 100644 index 000000000..9dbcda3db --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/main.tf @@ -0,0 +1,18 @@ +terraform { + + required_version = ">= 0.13" +} + + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} +data "azurerm_subscription" "current" {} + + diff --git a/caf_solution/add-ons/caf_eslz/output.tf b/caf_solution/add-ons/caf_eslz/output.tf new file mode 100644 index 000000000..e69de29bb diff --git a/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars b/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars new file mode 100644 index 000000000..89e2ea1fd --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars @@ -0,0 +1,25 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "caf_eslz" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } +} + +enterprise_scale = { + # Define a custom ID to use for the root Management Group + # Also used as a prefix for all core Management Group IDs + # root_id = "caf" + # root_name = "CAF-RootManagementGroup" + + # Control whether to deploy the default core landing zones // default = true + deploy_core_landing_zones = true + + # Control whether to deploy the demo landing zones // default = false + deploy_demo_landing_zones = false +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars b/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars new file mode 100644 index 000000000..73c92cb7f --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars @@ -0,0 +1,45 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "caf_foundations" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } +} + +enterprise_scale = { + #path to the policies definition and assignment repo + library_path = "/tf/caf/public/landingzones/caf_eslz/scenario/200/lib" + + #management groups hierarchy configuration + custom_landing_zones = { + caf = { + display_name = "CAF-RootManagementGroup" + parent_management_group_id = "" + subscription_ids = [] + archetype_config = { + archetype_id = "es_root" + parameters = {} + access_control = {} + } + } + child-caf = { + display_name = "CAF-ChildManagementGroup" + parent_management_group_id = "caf" + subscription_ids = [] + archetype_config = { + archetype_id = "es_management" + parameters = { + ES-Deploy-ForwardDiagLog = { + logAnalytics = "central_logs_region1" + } + } + access_control = {} + } + } + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json new file mode 100644 index 000000000..e6d18b5db --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json @@ -0,0 +1,12 @@ +{ + "es_management": { + "policy_assignments": [ + "ES-Deploy-ASC-Standard" + ], + "policy_definitions": [ + ], + "policy_set_definitions": [], + "role_assignments": [], + "role_definitions": [] + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json new file mode 100644 index 000000000..e41b04f6f --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json @@ -0,0 +1,13 @@ +{ + "es_root": { + "policy_assignments": [ + "ES-Deploy-ASC-Standard" + ], + "policy_definitions": [ + "ES-Deploy-ASC-Standard" + ], + "policy_set_definitions": [], + "role_assignments": [], + "role_definitions": [] + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json new file mode 100644 index 000000000..ae28ea455 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json @@ -0,0 +1,28 @@ +{ + "name": "ES-Allowed-Locations", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Specifies the allowed locations (regions) where resources can be deployed", + "displayName": "ES-Allowed-Resource-Locations", + "notScopes": [], + "parameters": { + "listOfAllowedLocations": { + "value": [ + "uksouth", + "ukwest" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "None" + } +} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json new file mode 100644 index 000000000..b00174588 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json @@ -0,0 +1,28 @@ +{ + "name": "ES-Allowed-RSG-Locations", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Specifies the allowed locations (regions) where Resource Groups can be deployed", + "displayName": "ES-Allowed-ResourceGroup-Locations", + "notScopes": [], + "parameters": { + "listOfAllowedLocations": { + "value": [ + "uksouth", + "ukwest" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "None" + } +} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json new file mode 100644 index 000000000..4417b6a01 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json @@ -0,0 +1,28 @@ +{ + "name": "ES-Deploy-ASC-ContExport", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Deploy ASC Continuous Export To Log Analytics Workspace.", + "displayName": "ES-Deploy-ASC-ContinuousExportToWorkspace", + "notScopes": [], + "parameters": { + "resourceGroupLocation": { + "value": null + }, + "workspaceResourceId": { + "value": null + } + }, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-ContinuousExportToWorkspace", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json new file mode 100644 index 000000000..ba6d2186f --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json @@ -0,0 +1,88 @@ +{ + "name": "ES-Deploy-ASC-Monitoring", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Enable Monitoring in Azure Security Center.", + "displayName": "ES-Deploy-ASC-Monitoring", + "notScopes": [], + "parameters": { + "aadAuthenticationInSqlServerMonitoringEffect": { + "value": "Disabled" + }, + "diskEncryptionMonitoringEffect": { + "value": "Disabled" + }, + "encryptionOfAutomationAccountMonitoringEffect": { + "value": "Disabled" + }, + "identityDesignateLessThanOwnersMonitoringEffect": { + "value": "Disabled" + }, + "identityDesignateMoreThanOneOwnerMonitoringEffect": { + "value": "Disabled" + }, + "identityEnableMFAForWritePermissionsMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveDeprecatedAccountMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveDeprecatedAccountWithOwnerPermissionsMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveExternalAccountWithOwnerPermissionsMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveExternalAccountWithReadPermissionsMonitoringEffect": { + "value": "Disabled" + }, + "identityRemoveExternalAccountWithWritePermissionsMonitoringEffect": { + "value": "Disabled" + }, + "jitNetworkAccessMonitoringEffect": { + "value": "Disabled" + }, + "networkSecurityGroupsOnSubnetsMonitoringEffect": { + "value": "AuditIfNotExists" + }, + "sqlDbEncryptionMonitoringEffect": { + "value": "Disabled" + }, + "sqlManagedInstanceAdvancedDataSecurityEmailAdminsMonitoringEffect": { + "value": "Disabled" + }, + "sqlManagedInstanceAdvancedDataSecurityEmailsMonitoringEffect": { + "value": "Disabled" + }, + "sqlServerAdvancedDataSecurityEmailAdminsMonitoringEffect": { + "value": "Disabled" + }, + "sqlServerAdvancedDataSecurityMonitoringEffect": { + "value": "Disabled" + }, + "systemUpdatesMonitoringEffect": { + "value": "Disabled" + }, + "useRbacRulesMonitoringEffect": { + "value": "Disabled" + }, + "vmssSystemUpdatesMonitoringEffect": { + "value": "Disabled" + }, + "windowsDefenderExploitGuardMonitoringEffect": { + "value": "Disabled" + } + }, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json new file mode 100644 index 000000000..1786a9c39 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json @@ -0,0 +1,21 @@ +{ + "name": "ES-Deploy-ASC-Standard", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Deploy Azure Security Center Standard Tier.", + "displayName": "ES-Deploy-ASC-Standard", + "notScopes": [], + "parameters": {}, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-Standard", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json new file mode 100644 index 000000000..7bf367af8 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json @@ -0,0 +1,25 @@ +{ + "name": "ES-Deploy-ForwardActLogs", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Ensures that Activity Log Diagnostics settings are set to push logs into Log Analytics workspace.", + "displayName": "ES-Deploy-Diagnostics-ForwardActivityLogs", + "notScopes": [], + "parameters": { + "logAnalytics": { + "value": null + } + }, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-Diagnostics-LogAnalytics", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json new file mode 100644 index 000000000..6cae95354 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json @@ -0,0 +1,25 @@ +{ + "name": "ES-Deploy-ForwardDiagLog", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Ensures that Azure resources are configured to forward diagnostic logs and metrics to an Azure Log Analytics workspace.", + "displayName": "ES-Deploy-Diagnostics-ForwardDiagnosticLogs", + "notScopes": [], + "parameters": { + "logAnalytics": { + "value": null + } + }, + "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/ES-Deploy-Diagnostics-LogAnalytics", + "scope": "${current_scope_resource_id}" + }, + "sku": { + "name": "A0", + "tier": "Free" + }, + "location": "${default_location}", + "identity": { + "type": "SystemAssigned" + } +} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json new file mode 100644 index 000000000..d75c1298a --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json @@ -0,0 +1,284 @@ +{ + "name": "ES-Deploy-ASC-Standard", + "type": "Microsoft.Authorization/policyDefinitions", + "apiVersion": "2019-09-01", + "properties": { + "description": "Ensures that subscriptions have Security Center Standard enabled.", + "displayName": "ES-Deploy-ASC-Standard", + "mode": "All", + "parameters": { + "pricingTierVMs": { + "type": "String", + "metadata": { + "displayName": "pricingTierVMs", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierSqlServers": { + "type": "String", + "metadata": { + "displayName": "pricingTierSqlServers", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierAppServices": { + "type": "String", + "metadata": { + "displayName": "pricingTierAppServices", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierStorageAccounts": { + "type": "String", + "metadata": { + "displayName": "pricingTierStorageAccounts", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierContainerRegistry": { + "type": "String", + "metadata": { + "displayName": "pricingTierContainerRegistry", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierKeyVaults": { + "type": "String", + "metadata": { + "displayName": "pricingTierKeyVaults", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + }, + "pricingTierKubernetesService": { + "type": "String", + "metadata": { + "displayName": "pricingTierKubernetesService", + "description": "" + }, + "allowedValues": [ + "Standard", + "Free" + ], + "defaultValue": "Standard" + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.Resources/subscriptions" + } + ] + }, + "then": { + "effect": "deployIfNotExists", + "details": { + "type": "Microsoft.Security/pricings", + "deploymentScope": "subscription", + "existenceScope": "subscription", + "roleDefinitionIds": [ + "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635" + ], + "existenceCondition": { + "allOf": [ + { + "field": "Microsoft.Security/pricings/pricingTier", + "equals": "Standard" + }, + { + "field": "type", + "equals": "Microsoft.Security/pricings" + } + ] + }, + "deployment": { + "location": "northeurope", + "properties": { + "mode": "incremental", + "parameters": { + "pricingTierVMs": { + "value": "[parameters('pricingTierVMs')]" + }, + "pricingTierSqlServers": { + "value": "[parameters('pricingTierSqlServers')]" + }, + "pricingTierAppServices": { + "value": "[parameters('pricingTierAppServices')]" + }, + "pricingTierStorageAccounts": { + "value": "[parameters('pricingTierStorageAccounts')]" + }, + "pricingTierContainerRegistry": { + "value": "[parameters('pricingTierContainerRegistry')]" + }, + "pricingTierKeyVaults": { + "value": "[parameters('pricingTierKeyVaults')]" + }, + "pricingTierKubernetesService": { + "value": "[parameters('pricingTierKubernetesService')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "pricingTierVMs": { + "type": "string", + "metadata": { + "description": "pricingTierVMs" + } + }, + "pricingTierSqlServers": { + "type": "string", + "metadata": { + "description": "pricingTierSqlServers" + } + }, + "pricingTierAppServices": { + "type": "string", + "metadata": { + "description": "pricingTierAppServices" + } + }, + "pricingTierStorageAccounts": { + "type": "string", + "metadata": { + "description": "pricingTierStorageAccounts" + } + }, + "pricingTierContainerRegistry": { + "type": "string", + "metadata": { + "description": "ContainerRegistry" + } + }, + "pricingTierKeyVaults": { + "type": "string", + "metadata": { + "description": "KeyVaults" + } + }, + "pricingTierKubernetesService": { + "type": "string", + "metadata": { + "description": "KubernetesService" + } + } + }, + "variables": {}, + "resources": [ + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "VirtualMachines", + "properties": { + "pricingTier": "[parameters('pricingTierVMs')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "StorageAccounts", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/VirtualMachines')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierStorageAccounts')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "AppServices", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/StorageAccounts')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierAppServices')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "SqlServers", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/AppServices')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierSqlServers')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "KeyVaults", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/SqlServers')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierKeyVaults')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "KubernetesService", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/KeyVaults')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierKubernetesService')]" + } + }, + { + "type": "Microsoft.Security/pricings", + "apiVersion": "2018-06-01", + "name": "ContainerRegistry", + "dependsOn": [ + "[concat('Microsoft.Security/pricings/KubernetesService')]" + ], + "properties": { + "pricingTier": "[parameters('pricingTierContainerRegistry')]" + } + } + ], + "outputs": {} + } + } + } + } + } + } + } +} diff --git a/caf_solution/add-ons/caf_eslz/variables.tf b/caf_solution/add-ons/caf_eslz/variables.tf new file mode 100644 index 000000000..2d9c23fac --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/variables.tf @@ -0,0 +1,135 @@ +# Map of the remote data state +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} +variable "tfstate_storage_account_name" { + description = "This value is propulated by the rover" +} +variable "tfstate_container_name" { + description = "This value is propulated by the rover" +} +variable "tfstate_key" { + description = "This value is propulated by the rover" +} +variable "tfstate_resource_group_name" { + description = "This value is propulated by the rover" +} + +variable "landingzone" { + default = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "enterprise_scale" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } + } +} + +variable "user_type" {} +variable "tenant_id" {} +variable "rover_version" {} +variable "logged_user_objectId" { + default = null +} +variable "tags" { + type = map(any) + default = {} +} + + +variable "root_id" { + type = string + description = "If specified, will set a custom Name (ID) value for the Enterprise-scale \"root\" Management Group, and append this to the ID for all core Enterprise-scale Management Groups." + default = "es" + + validation { + condition = can(regex("^[a-zA-Z0-9-]{2,10}$", var.root_id)) + error_message = "The root_id value must be between 2 to 10 characters long and can only contain alphanumeric characters and hyphens." + } +} + +variable "root_name" { + type = string + description = "If specified, will set a custom Display Name value for the Enterprise-scale \"root\" Management Group." + default = "Enterprise-Scale" + + validation { + condition = can(regex("^[A-Za-z][A-Za-z0-9- ._]{1,22}[A-Za-z0-9]?$", var.root_name)) + error_message = "The root_name value must be between 2 to 24 characters long, start with a letter, end with a letter or number, and can only contain space, hyphen, underscore or period characters." + } +} + +variable "deploy_core_landing_zones" { + type = bool + description = "If set to true, will include the core Enterprise-scale Management Group hierarchy." + default = false +} + +variable "archetype_config_overrides" { + type = map(any) + description = "If specified, will set custom Archetype configurations to the default Enterprise-scale Management Groups." + default = {} +} + +variable "subscription_id_overrides" { + type = map(list(string)) + description = "If specified, will be used to assign subscription_ids to the default Enterprise-scale Management Groups." + default = {} +} + +variable "deploy_demo_landing_zones" { + type = bool + description = "If set to true, will include the demo \"Landing Zone\" Management Groups." + default = false +} + +variable "custom_landing_zones" { + type = map( + object({ + display_name = string + parent_management_group_id = string + subscription_ids = list(string) + archetype_config = object({ + archetype_id = string + parameters = any + access_control = any + }) + }) + ) + description = "If specified, will deploy additional Management Groups alongside Enterprise-scale core Management Groups." + default = {} + + validation { + condition = can(regex("^[a-z0-9-]{2,36}$", keys(var.custom_landing_zones)[0])) || length(keys(var.custom_landing_zones)) == 0 + error_message = "The custom_landing_zones keys must be between 2 to 36 characters long and can only contain lowercase letters, numbers and hyphens." + } +} + +variable "library_path" { + type = string + description = "If specified, sets the path to a custom library folder for archetype artefacts." + default = "" +} + +variable "template_file_variables" { + type = map(any) + description = "If specified, provides the ability to define custom template variables used when reading in template files from the built-in and custom library_path." + default = {} +} + +variable "default_location" { + type = string + description = "If specified, will use set the default location used for resource deployments where needed." + default = "eastus" + + # Need to add validation covering all Azure locations +} \ No newline at end of file diff --git a/caf_solution/add-ons/databricks/backend.azurerm b/caf_solution/add-ons/databricks/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_solution/add-ons/databricks/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/databricks/databricks.tf b/caf_solution/add-ons/databricks/databricks.tf new file mode 100644 index 000000000..1c81174b7 --- /dev/null +++ b/caf_solution/add-ons/databricks/databricks.tf @@ -0,0 +1,21 @@ +locals { + azure_workspace_resource_id = local.remote.databricks_workspaces[var.databricks.lz_key][var.databricks.workspace_key].id +} + +provider "databricks" { + azure_workspace_resource_id = local.azure_workspace_resource_id + # azure_client_id = var.client_id + # azure_client_secret = var.client_secret + # azure_tenant_id = var.tenant_id +} + +module "databricks" { + source = "../../modules/databricks" + + settings = var.databricks +} + +output "databricks" { + value = module.databricks + sensitive = false +} diff --git a/caf_solution/add-ons/databricks/locals.remote_tfstates.tf b/caf_solution/add-ons/databricks/locals.remote_tfstates.tf new file mode 100644 index 000000000..b813756c5 --- /dev/null +++ b/caf_solution/add-ons/databricks/locals.remote_tfstates.tf @@ -0,0 +1,43 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + + remote = { + databricks_workspaces = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.databricks_workspaces[key], {})) + } + } + +} diff --git a/caf_solution/add-ons/databricks/main.tf b/caf_solution/add-ons/databricks/main.tf new file mode 100644 index 000000000..1325d0f88 --- /dev/null +++ b/caf_solution/add-ons/databricks/main.tf @@ -0,0 +1,63 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.43" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "1.0.0" + } + databricks = { + source = "databrickslabs/databricks" + version = "~> 0.2.5" + } + } + required_version = ">= 0.13" +} + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + +data "terraform_remote_state" "landingzone" { + backend = "azurerm" + config = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + key = var.tfstate_key + resource_group_name = var.tfstate_resource_group_name + } +} + +locals { + diagnostics = { + diagnostics_definition = merge(data.terraform_remote_state.landingzone.outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = data.terraform_remote_state.landingzone.outputs.diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.landingzone.outputs.diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.landingzone.outputs.diagnostics.log_analytics + } + + tfstates = merge( + map(var.landingzone.key, + map( + "storage_account_name", var.tfstate_storage_account_name, + "container_name", var.tfstate_container_name, + "resource_group_name", var.tfstate_resource_group_name, + "key", var.tfstate_key, + "level", var.landingzone.level, + "tenant_id", data.azurerm_client_config.current.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + , + data.terraform_remote_state.landingzone.outputs.tfstates + ) + +} diff --git a/caf_solution/add-ons/databricks/variables.tf b/caf_solution/add-ons/databricks/variables.tf new file mode 100644 index 000000000..6c3a9e993 --- /dev/null +++ b/caf_solution/add-ons/databricks/variables.tf @@ -0,0 +1,154 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "global_settings" { + default = {} +} + +variable "landingzone" { + default = "" +} + +variable "environment" { + default = "sandpit" +} +variable "rover_version" { + default = null +} +variable "max_length" { + default = 40 +} +variable "logged_user_objectId" { + default = null +} +variable "logged_aad_app_objectId" { + default = null +} +variable "tags" { + default = null + type = map(any) +} +variable "diagnostic_log_analytics" { + default = {} +} +variable "app_service_environments" { + default = {} +} +variable "app_service_plans" { + default = {} +} +variable "app_services" { + default = {} +} +variable "diagnostics_definition" { + default = null +} +variable "resource_groups" { + default = null +} +variable "network_security_group_definition" { + default = {} +} +variable "vnets" { + default = {} +} +variable "azurerm_redis_caches" { + default = {} +} +variable "mssql_servers" { + default = {} +} +variable "mssql_databases" { + default = {} +} +variable "mssql_elastic_pools" { + default = {} +} +variable "storage_accounts" { + default = {} +} +variable "azuread_groups" { + default = {} +} +variable "keyvaults" { + default = {} +} +variable "keyvault_access_policies" { + default = {} +} +variable "virtual_machines" { + default = {} +} +variable "azure_container_registries" { + default = {} +} +variable "bastion_hosts" { + default = {} +} +variable "public_ip_addresses" { + default = {} +} +variable "diagnostic_storage_accounts" { + default = {} +} +variable "managed_identities" { + default = {} +} +variable "private_dns" { + default = {} +} +variable "synapse_workspaces" { + default = {} +} +variable "azurerm_application_insights" { + default = {} +} +variable "role_mapping" { + default = {} +} +variable "aks_clusters" { + default = {} +} +variable "databricks_workspaces" { + default = {} +} +variable "machine_learning_workspaces" { + default = {} +} +variable "monitoring" { + default = {} +} +variable "virtual_wans" { + default = {} +} +variable "event_hub_namespaces" { + default = {} +} +variable "application_gateways" { + default = {} +} +variable "application_gateway_applications" { + default = {} +} +variable "dynamic_keyvault_secrets" { + default = {} +} +variable "disk_encryption_sets" { + default = {} +} +variable "keyvault_keys" { + default = {} +} +variable "databricks" { + default = {} +} +variable "var_folder_path" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/add-ons/helm-charts/backend.azurerm b/caf_solution/add-ons/helm-charts/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_solution/add-ons/helm-charts/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/helm-charts/charts.tf b/caf_solution/add-ons/helm-charts/charts.tf new file mode 100644 index 000000000..74b16be73 --- /dev/null +++ b/caf_solution/add-ons/helm-charts/charts.tf @@ -0,0 +1,21 @@ + +resource "kubernetes_namespace" "gitlab_runners" { + for_each = var.aks_namespaces + + metadata { + name = each.value + } +} + +resource "helm_release" "chart" { + depends_on = [kubernetes_namespace.gitlab_runners] + for_each = var.helm_charts + + chart = each.value.chart + name = each.value.name + namespace = each.value.namespace + repository = try(each.value.repository, null) + timeout = try(each.value.timeout, 4000) + values = [file(each.value.value_file)] + wait = try(each.value.wait, true) +} \ No newline at end of file diff --git a/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf b/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf new file mode 100644 index 000000000..c87b31046 --- /dev/null +++ b/caf_solution/add-ons/helm-charts/local.remote_tfstates.tf @@ -0,0 +1,49 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics + + remote = { + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + global_settings = local.global_settings + diagnostics = local.diagnostics + + + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) + } + + } + +} diff --git a/caf_solution/add-ons/helm-charts/main.tf b/caf_solution/add-ons/helm-charts/main.tf new file mode 100644 index 000000000..263eade2a --- /dev/null +++ b/caf_solution/add-ons/helm-charts/main.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.51.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.0.2" + } + helm = { + source = "hashicorp/helm" + version = "~> 2.0.3" + } + } + required_version = ">= 0.13" +} diff --git a/caf_solution/add-ons/helm-charts/providers.tf b/caf_solution/add-ons/helm-charts/providers.tf new file mode 100644 index 000000000..3beaf3ead --- /dev/null +++ b/caf_solution/add-ons/helm-charts/providers.tf @@ -0,0 +1,39 @@ + +provider "azurerm" { + features { + } +} + +provider "kubernetes" { + host = local.k8sconfigs[var.aks_cluster_key].host + username = local.k8sconfigs[var.aks_cluster_key].username + password = local.k8sconfigs[var.aks_cluster_key].password + client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate + client_key = local.k8sconfigs[var.aks_cluster_key].client_key + cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate +} + +provider "helm" { + kubernetes { + host = local.k8sconfigs[var.aks_cluster_key].host + username = local.k8sconfigs[var.aks_cluster_key].username + password = local.k8sconfigs[var.aks_cluster_key].password + client_certificate = local.k8sconfigs[var.aks_cluster_key].client_certificate + client_key = local.k8sconfigs[var.aks_cluster_key].client_key + cluster_ca_certificate = local.k8sconfigs[var.aks_cluster_key].cluster_ca_certificate + } +} + +locals { + k8sconfigs = { + for key, value in var.aks_clusters : key => { + kube_admin_config_raw = local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config_raw + host = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.host : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.host + username = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.username : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.username + password = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.password : local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.password + client_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_certificate) + client_key = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.client_key) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.client_key) + cluster_ca_certificate = local.remote.aks_clusters[value.lz_key][value.key].enable_rbac ? base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_admin_config.0.cluster_ca_certificate) : base64decode(local.remote.aks_clusters[value.lz_key][value.key].kube_config.0.cluster_ca_certificate) + } + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/helm-charts/variables.tf b/caf_solution/add-ons/helm-charts/variables.tf new file mode 100644 index 000000000..2c4c62f35 --- /dev/null +++ b/caf_solution/add-ons/helm-charts/variables.tf @@ -0,0 +1,32 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} + +variable "landingzone" {} +variable "rover_version" { + default = null +} +variable "tags" { + default = null +} + +variable "helm_charts" {} +variable "aks_namespaces" { + default = {} +} +variable "aks_cluster_key" { + description = "AKS cluster key to deploy the Gitlab Helm charts. The key must be defined in the variable aks_clusters" +} +variable "aks_cluster_vnet_key" { + +} +variable "aks_clusters" {} \ No newline at end of file diff --git a/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars b/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars new file mode 100644 index 000000000..1ce04bf0f --- /dev/null +++ b/caf_solution/add-ons/terraform_cloud/example/tfc.tfvars @@ -0,0 +1,25 @@ +landingzone = { + backend_type = "remote" + level = "level0" + key = "launchpad" +} + +# Create the TFC organization +tfe_organizations = { + caf_lz = { + name = "caf-landingzones-test3" + email = "admin@your-company.com" + + } +} + +# Create the required TFE workspaces +tfe_workspaces = { + caf_launchpad = { + # specifies the object key for the organization where to create the workspace + organization_key = "caf_lz" + name = "caf_launchpad" + # path to place the backend file for the corresponding landing zone + backend_file = "/backend.hcl" + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/terraform_cloud/main.tf b/caf_solution/add-ons/terraform_cloud/main.tf new file mode 100644 index 000000000..413e570f5 --- /dev/null +++ b/caf_solution/add-ons/terraform_cloud/main.tf @@ -0,0 +1,51 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.40" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.0.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + tfe = { + source = "hashicorp/tfe" + version = "~> 0.22.0" + } + } + required_version = ">= 0.13" +} + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + +locals { + tfstates = merge( + map(var.landingzone.backend_type, + map( + "level", var.landingzone.level, + "tenant_id", data.azurerm_client_config.current.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + ) +} \ No newline at end of file diff --git a/caf_solution/add-ons/terraform_cloud/readme.md b/caf_solution/add-ons/terraform_cloud/readme.md new file mode 100644 index 000000000..7bfe4e7a6 --- /dev/null +++ b/caf_solution/add-ons/terraform_cloud/readme.md @@ -0,0 +1,44 @@ +# Add-on to deploy a Terraform Cloud / Terraform Enterprise configuration for Azure CAF landing zones + +Supported scenario in this release: + +1. Create the TFE/TFC environment (organization, variables, workspaces) + +Future scenarios: + +1. Use TFE/TFC as remote backend (local execution, backend in TFC) +2. Deploy Terraform Enterprise Server and remote agents +3. Use TFE/TFC in online mode (execution in TFE with remote agents) + +## Authenticating to Terraform Cloud + +First step is to authenticate to TFC using the following commands: + +```bash +terraform login +export TERRAFORM_CONFIG="$HOME/.terraform.d/credentials.tfrc.json" +``` + +## Creating the TFC environment + +This will setup TFC organization, workspaces and variables to host landing zones. + +```bash +# Deploy +rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/ \ +-var-folder /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/ \ +-a plan -launchpad + +or +cd /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/ +terraform init +terraform plan \ +-var-file /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars +``` + +Once ready, you can create your configuration: + +```bash +terraform apply \ +-var-file /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars +``` \ No newline at end of file diff --git a/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf b/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf new file mode 100644 index 000000000..db9218fc0 --- /dev/null +++ b/caf_solution/add-ons/terraform_cloud/terraform_cloud.tf @@ -0,0 +1,83 @@ + +resource "tfe_organization" "tfe_org" { + for_each = try(var.tfe_organizations, {}) + + name = each.value.name + email = each.value.email + session_timeout_minutes = try(each.value.session_timeout_minutes, 20160) + session_remember_minutes = try(each.value.session_remember_minutes, 20160) + collaborator_auth_policy = try(each.value.collaborator_auth_policy, "password") + owners_team_saml_role_id = try(each.value.owners_team_saml_role_id, null) +} + +resource "tfe_workspace" "tfe_wks" { + for_each = try(var.tfe_workspaces, {}) + + name = each.value.name + organization = tfe_organization.tfe_org[each.value.organization_key].name + auto_apply = try(each.value.auto_apply, false) + file_triggers_enabled = try(each.value.file_triggers_enabled, true) + operations = try(each.value.operations, true) + queue_all_runs = try(each.value.queue_all_runs, true) + speculative_enabled = try(each.value.speculative_enabled, true) + ssh_key_id = try(each.value.ssh_key_id, null) + terraform_version = try(each.value.terraform_version, null) + trigger_prefixes = try(each.value.trigger_prefixes, null) + working_directory = try(each.value.working_directory, null) + + dynamic "vcs_repo" { + for_each = lookup(each.value, "vcs_repo", null) == null ? [] : [1] + + content { + identifier = each.value.vcs_repo.identifier + branch = try(each.value.vcs_repo.branch, null) + ingress_submodules = try(each.value.vcs_repo.ingress_submodules, false) + oauth_token_id = each.value.vcs_repo.oauth_token_id + } + } +} + +resource "tfe_variable" "variable" { + for_each = try(var.tfe_variables, {}) + + key = each.value.key_name + value = each.value.value + category = each.value.category + workspace_id = tfe_workspace.tfe_wks[each.value.workspace_key].id + description = each.value.description + hcl = try(each.value.hcl, false) + sensitive = try(each.value.sensitive, false) +} + +resource "null_resource" "backend_file" { + depends_on = [tfe_workspace.tfe_wks] + for_each = try(var.tfe_workspaces, {}) + + provisioner "local-exec" { + working_dir = "./" + command = "echo workspaces '{' name = \\\"${each.value.name}\\\" '}' >> ${path.cwd}${each.value.backend_file}" + } + provisioner "local-exec" { + working_dir = "./" + command = "echo hostname = \\\"app.terraform.io\\\" >> ${path.cwd}${each.value.backend_file}" + } + provisioner "local-exec" { + working_dir = "./" + command = "echo organization = \\\"${tfe_organization.tfe_org[each.value.organization_key].name}\\\" >> ${path.cwd}${each.value.backend_file}" + } +} + +resource "null_resource" "backend_file_destroy" { + depends_on = [tfe_workspace.tfe_wks] + for_each = try(var.tfe_workspaces, {}) + + triggers = { + backend_file = lookup(each.value, "backend_file") + } + + provisioner "local-exec" { + command = format("rm %s%s", path.cwd, self.triggers.backend_file) + when = destroy + on_failure = fail + } +} diff --git a/caf_solution/add-ons/terraform_cloud/variables.tf b/caf_solution/add-ons/terraform_cloud/variables.tf new file mode 100644 index 000000000..499b0aba5 --- /dev/null +++ b/caf_solution/add-ons/terraform_cloud/variables.tf @@ -0,0 +1,85 @@ +# Map of the remote data state for lower level +variable "lower_storage_account_name" { + default = {} +} +variable "lower_container_name" { + default = {} +} +variable "lower_resource_group_name" { + default = {} +} + +variable "tfstate_storage_account_name" { + default = {} +} +variable "tfstate_container_name" { + default = {} +} +variable "tfstate_key" { + default = {} +} +variable "tfstate_resource_group_name" { + default = {} +} + +variable "global_settings" { + default = {} +} +variable "tenant_id" { + default = {} +} +variable "landingzone" { + default = {} +} + +variable "rover_version" { + default = null +} + +variable "logged_user_objectId" { + default = null +} +variable "logged_aad_app_objectId" { + default = null +} +variable "tags" { + default = null +} +variable "keyvaults" { + default = {} +} +variable "keyvault_access_policies" { + default = {} +} +variable "role_mapping" { + default = {} +} +variable "secrets_from_keys" { + default = {} +} +variable "custom_role_definitions" { + default = {} +} +variable "azuread_apps" { + default = {} +} + +variable "tfe_organizations" { + default = {} +} + +variable "tfe_workspaces" { + default = {} +} + +variable "tfe_variables" { + default = {} +} + +variable "tfe_servers" { + default = {} +} + +variable "tfe_agents" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/backend.azurerm b/caf_solution/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_solution/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_solution/dynamic_secrets.tf b/caf_solution/dynamic_secrets.tf new file mode 100644 index 000000000..fde3df0e0 --- /dev/null +++ b/caf_solution/dynamic_secrets.tf @@ -0,0 +1,9 @@ +module "dynamic_keyvault_secrets" { + source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=5.3.0_preview" + + for_each = try(var.dynamic_keyvault_secrets, {}) + + settings = each.value + keyvault = module.solution.keyvaults[each.key] + objects = module.solution +} \ No newline at end of file diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf new file mode 100644 index 000000000..bfa7422a6 --- /dev/null +++ b/caf_solution/landingzone.tf @@ -0,0 +1,43 @@ +module "solution" { + source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git?ref=5.3.0_preview" + + azuread_api_permissions = var.azuread_api_permissions + azuread_apps = var.azuread_apps + azuread_groups = var.azuread_groups + azuread_roles = var.azuread_roles + azuread_users = var.azuread_users + compute = var.compute + current_landingzone_key = var.landingzone.key + custom_role_definitions = var.custom_role_definitions + database = var.database + event_hub_namespaces = var.event_hub_namespaces + global_settings = local.global_settings + keyvault_access_policies = var.keyvault_access_policies + keyvault_certificate_issuers = var.keyvault_certificate_issuers + keyvaults = var.keyvaults + log_analytics = var.log_analytics + logged_aad_app_objectId = var.logged_aad_app_objectId + logged_user_objectId = var.logged_user_objectId + managed_identities = var.managed_identities + networking = var.networking + remote_objects = local.remote_objects + resource_groups = var.resource_groups + role_mapping = var.role_mapping + security = var.security + shared_services = var.shared_services + storage_accounts = var.storage_accounts + subscription_billing_role_assignments = var.subscription_billing_role_assignments + subscriptions = var.subscriptions + tags = var.tags + tenant_id = var.tenant_id + tfstates = var.tfstates + user_type = var.user_type + webapp = var.webapp + + diagnostics = { + diagnostic_event_hub_namespaces = try(local.diagnostics.diagnostic_event_hub_namespaces, var.diagnostic_event_hub_namespaces) + diagnostic_log_analytics = try(local.diagnostics.diagnostic_log_analytics, var.diagnostic_log_analytics) + diagnostic_storage_accounts = try(local.diagnostics.diagnostic_storage_accounts, var.diagnostic_storage_accounts) + } + +} diff --git a/caf_solution/local.remote.tf b/caf_solution/local.remote.tf new file mode 100644 index 000000000..6d76fb1ff --- /dev/null +++ b/caf_solution/local.remote.tf @@ -0,0 +1,100 @@ +locals { + remote = { + aks_clusters = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) + } + app_service_environments = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_service_environments, {})) + } + app_service_plans = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_service_plans, {})) + } + app_services = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_services, {})) + } + application_gateway_applications = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].application_gateway_applications, {})) + } + application_gateways = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].application_gateways, {})) + } + availability_sets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].availability_sets, {})) + } + azuread_applications = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azuread_applications, {})) + } + azuread_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azuread_groups, {})) + } + azuread_users = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azuread_users, {})) + } + azurerm_firewalls = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].azurerm_firewalls, {})) + } + container_registry = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].container_registry, {})) + } + event_hub_namespaces = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].event_hub_namespaces, {})) + } + front_door_waf_policies = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].front_door_waf_policies, {})) + } + keyvaults = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].keyvaults, {})) + } + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) + } + mssql_databases = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_databases, {})) + } + mssql_elastic_pools = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_elastic_pools, {})) + } + mssql_managed_databases = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_managed_databases, {})) + } + mssql_managed_instances = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_managed_instances, {})) + } + mssql_servers = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mssql_servers, {})) + } + mysql_servers = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mysql_servers, {})) + } + network_watchers = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].network_watchers, {})) + } + postgresql_servers = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].postgresql_servers, {})) + } + private_dns = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].private_dns, {})) + } + proximity_placement_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].proximity_placement_groups, {})) + } + public_ip_addresses = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].public_ip_addresses, {})) + } + recovery_vaults = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].recovery_vaults, {})) + } + resource_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].resource_groups, {})) + } + storage_accounts = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].storage_accounts, {})) + } + synapse_workspaces = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].synapse_workspaces, {})) + } + vnets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) + } + } +} \ No newline at end of file diff --git a/caf_solution/local.remote_objects.tf b/caf_solution/local.remote_objects.tf new file mode 100644 index 000000000..8863c7ff0 --- /dev/null +++ b/caf_solution/local.remote_objects.tf @@ -0,0 +1,36 @@ +locals { + remote_objects = { + aks_clusters = local.remote.aks_clusters + app_service_environments = local.remote.app_service_environments + app_service_plans = local.remote.app_service_plans + app_services = local.remote.app_services + application_gateway_applications = local.remote.application_gateway_applications + application_gateways = local.remote.application_gateways + availability_sets = local.remote.availability_sets + azuread_applications = local.remote.azuread_applications + azuread_groups = local.remote.azuread_groups + azuread_users = local.remote.azuread_users + azurerm_firewalls = local.remote.azurerm_firewalls + container_registry = local.remote.container_registry + event_hub_namespaces = local.remote.event_hub_namespaces + front_door_waf_policies = local.remote.front_door_waf_policies + keyvaults = local.remote.keyvaults + managed_identities = local.remote.managed_identities + mssql_databases = local.remote.mssql_databases + mssql_elastic_pools = local.remote.mssql_elastic_pools + mssql_managed_databases = local.remote.mssql_managed_databases + mssql_managed_instances = local.remote.mssql_managed_instances + mssql_servers = local.remote.mssql_servers + mysql_servers = local.remote.mysql_servers + network_watchers = local.remote.network_watchers + postgresql_servers = local.remote.postgresql_servers + private_dns = local.remote.private_dns + proximity_placement_groups = local.remote.proximity_placement_groups + public_ip_addresses = local.remote.public_ip_addresses + recovery_vaults = local.remote.recovery_vaults + resource_groups = local.remote.resource_groups + storage_accounts = local.remote.storage_accounts + synapse_workspaces = local.remote.synapse_workspaces + vnets = local.remote.vnets + } +} \ No newline at end of file diff --git a/caf_solution/locals.remote_tfstates.tf b/caf_solution/locals.remote_tfstates.tf new file mode 100644 index 000000000..e05465330 --- /dev/null +++ b/caf_solution/locals.remote_tfstates.tf @@ -0,0 +1,45 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = try(each.value.workspace, local.landingzone[try(each.value.level, "current")].container_name) + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + + diagnostics = { + diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_destinations + storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.log_analytics + event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.event_hub_namespaces + } + +} diff --git a/caf_solution/main.tf b/caf_solution/main.tf new file mode 100644 index 000000000..909659c2d --- /dev/null +++ b/caf_solution/main.tf @@ -0,0 +1,66 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.50" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 1.4.0" + } + random = { + source = "hashicorp/random" + version = "~> 2.2.1" + } + external = { + source = "hashicorp/external" + version = "~> 1.2.0" + } + null = { + source = "hashicorp/null" + version = "~> 2.1.0" + } + tls = { + source = "hashicorp/tls" + version = "~> 2.2.0" + } + azurecaf = { + source = "aztfmod/azurecaf" + version = "~>1.2.0" + } + } + required_version = ">= 0.13" +} + + +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +data "azurerm_client_config" "current" {} + + +locals { + + # Update the tfstates map + tfstates = merge( + map(var.landingzone.key, + map( + "storage_account_name", var.tfstate_storage_account_name, + "container_name", var.tfstate_container_name, + "resource_group_name", var.tfstate_resource_group_name, + "key", var.tfstate_key, + "level", var.landingzone.level, + "tenant_id", var.tenant_id, + "subscription_id", data.azurerm_client_config.current.subscription_id + ) + ) + , + data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates + ) + +} \ No newline at end of file diff --git a/caf_solution/modules/databricks/cluster.tf b/caf_solution/modules/databricks/cluster.tf new file mode 100644 index 000000000..25310d783 --- /dev/null +++ b/caf_solution/modules/databricks/cluster.tf @@ -0,0 +1,17 @@ +resource "databricks_cluster" "cluster" { + cluster_name = var.settings.name + spark_version = var.settings.spark_version + node_type_id = var.settings.node_type_id + autotermination_minutes = var.settings.autotermination_minutes + + dynamic "autoscale" { + for_each = try(var.settings.autoscale, null) == null ? [] : [1] + + content { + min_workers = try(var.settings.autoscale.min_workers, null) + max_workers = try(var.settings.autoscale.max_workers, null) + } + } + + +} \ No newline at end of file diff --git a/caf_solution/modules/databricks/instance_pool.tf b/caf_solution/modules/databricks/instance_pool.tf new file mode 100644 index 000000000..e69de29bb diff --git a/caf_solution/modules/databricks/main.tf b/caf_solution/modules/databricks/main.tf new file mode 100644 index 000000000..8993136bd --- /dev/null +++ b/caf_solution/modules/databricks/main.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + databricks = { + source = "databrickslabs/databricks" + } + } + required_version = ">= 0.13" +} + diff --git a/caf_solution/modules/databricks/output.tf b/caf_solution/modules/databricks/output.tf new file mode 100644 index 000000000..d6bc7bc48 --- /dev/null +++ b/caf_solution/modules/databricks/output.tf @@ -0,0 +1,7 @@ +output "cluster" { + value = { + id = databricks_cluster.cluster.id + default_tags = databricks_cluster.cluster.default_tags + state = databricks_cluster.cluster.state + } +} \ No newline at end of file diff --git a/caf_solution/modules/databricks/variables.tf b/caf_solution/modules/databricks/variables.tf new file mode 100644 index 000000000..719f36726 --- /dev/null +++ b/caf_solution/modules/databricks/variables.tf @@ -0,0 +1,4 @@ +variable "azure_workspace_resource_id" { + default = {} +} +variable "settings" {} \ No newline at end of file diff --git a/caf_solution/output.tf b/caf_solution/output.tf new file mode 100644 index 000000000..6c2f8c16d --- /dev/null +++ b/caf_solution/output.tf @@ -0,0 +1,16 @@ +output "objects" { + value = tomap( + { + (var.landingzone.key) = { + for key, value in module.solution : key => value + if try(value, {}) != {} + } + } + ) + sensitive = true +} + +output "tfstates" { + value = local.tfstates + sensitive = true +} diff --git a/caf_solution/readme.md b/caf_solution/readme.md new file mode 100644 index 000000000..48f6c0333 --- /dev/null +++ b/caf_solution/readme.md @@ -0,0 +1,22 @@ +# Cloud Adoption Framework for Azure - Landing zones on Terraform - Solutions + +The landing zones solutions provide the underlying infrastructure to support your applications. The following are solutions accelerator ready to be deployed into your environment. They would require some review to match your operating model. + +* App Services (including App Service Environment) +* Azure Kubernetes Service (AKS) +* Azure Databricks +* Azure SQL Database +* Azure Application Gateway +* Azure Redis Cache +* Azure Keyvault +* Azure Virtual Machine +* Azure Machine Learning +* Azure Synapse + +Solutions landing zone operates at **level 3**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). + +## Deploying solutions + +Solution examples are available in the CAF Landing zones Starter repo: https://github.com/Azure/caf-terraform-landingzones-starter diff --git a/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars b/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars new file mode 100644 index 000000000..9340de718 --- /dev/null +++ b/caf_solution/scenario/foundations/100-passthrough/landingzone.tfvars @@ -0,0 +1,12 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "caf_foundations" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } +} \ No newline at end of file diff --git a/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars b/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars new file mode 100644 index 000000000..7269553e2 --- /dev/null +++ b/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars @@ -0,0 +1,62 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "foundations" + level = "level2" + key = "networking_hub" + tfstates = { + foundations = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + } +} + +resource_groups = { + vnet_hub_re1 = { + name = "vnet-hub-re1" + region = "region1" + } +} + +vnets = { + hub_re1 = { + resource_group_key = "vnet_hub_re1" + region = "region1" + vnet = { + name = "hub-re1" + address_space = ["100.64.100.0/22"] + } + specialsubnets = { + GatewaySubnet = { + name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway + cidr = ["100.64.100.0/27"] + } + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["100.64.101.0/26"] + } + } + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["100.64.101.64/26"] + nsg_key = "azure_bastion_nsg" + } + jumpbox = { + name = "jumpbox" + cidr = ["100.64.102.0/27"] + nsg_key = "jumpbox" + } + private_endpoints = { + name = "private_endpoints" + cidr = ["100.64.103.128/25"] + enforce_private_link_endpoint_network_policies = true + } + } + } + +} diff --git a/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars b/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars new file mode 100644 index 000000000..232a5432d --- /dev/null +++ b/caf_solution/scenario/networking/100-single-region-hub/network_security_group_definition.tfvars @@ -0,0 +1,327 @@ +# +# Definition of the networking security groups +# +network_security_group_definition = { + # This entry is applied to all subnets with no NSG defined + empty_nsg = { + } + + azure_bastion_nsg = { + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } + + application_gateway = { + nsg = [ + { + name = "Inbound-HTTP", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "80-82" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "Inbound-HTTPs", + priority = "130" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "Inbound-AGW", + priority = "140" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "65200-65535" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + ] + } + + api_management = { + nsg = [ + { + name = "Inbound-APIM", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3443" + source_address_prefix = "ApiManagement" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Inbound-Redis", + priority = "110" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "6381-6383" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Inbound-LoadBalancer", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "*" + source_address_prefix = "AzureLoadBalancer" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Outbound-StorageHttp", + priority = "100" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "80" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-StorageHttps", + priority = "110" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-AADHttp", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "80" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureActiveDirectory" + }, + { + name = "Outbound-AADHttps", + priority = "130" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureActiveDirectory" + }, + { + name = "Outbound-SQL", + priority = "140" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "1433" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "SQL" + }, + { + name = "Outbound-EventHub", + priority = "150" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "5671-5672" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "EventHub" + }, + { + name = "Outbound-EventHubHttps", + priority = "160" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "EventHub" + }, + { + name = "Outbound-FileShareGit", + priority = "170" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "445" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-Health", + priority = "180" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "1886" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-Monitor", + priority = "190" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureMonitor" + }, + { + name = "Outbound-MoSMTP1itor", + priority = "200" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "25" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-SMTP2", + priority = "210" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "587" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-SMTP3", + priority = "220" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "25028" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-Redis", + priority = "230" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "6381-6383" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + + jumpbox = { + nsg = [ + { + name = "ssh-inbound-22", + priority = "200" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + +} + diff --git a/caf_solution/scenario/networking/100-single-region-hub/readme.md b/caf_solution/scenario/networking/100-single-region-hub/readme.md new file mode 100644 index 000000000..624dfff6b --- /dev/null +++ b/caf_solution/scenario/networking/100-single-region-hub/readme.md @@ -0,0 +1,45 @@ +# CAF landing zones for Terraform - Single region hub virtual network + +The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. + +* Hub and spoke +* Virtual WAN +* Application DMZ scenario +* Any custom network topology based on virtual networks or virtual WAN +* Library of network security groups definition + +Networking landing zone operates at **level 2**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). + +## Architecture diagram + +This example allows you to deploy the following topology: + +![100-example](../../documentation/img/100-single-region-hub.png) + + +## Components deployed by this example + +| Component | Type of resource | Purpose | +|----------------------------------------------------------------------------------|-------------------------|------------------------------------------------------------------| +| vnet-hub-re1 | Resource group | resource group to host the virtual network | +| vnet_hub_re1 | Virtual network | virtual network used as a hub | +| GatewaySubnet,AzureFirewallSubnet,AzureBastionSubnet, jumpbox, private_endpoints | Virtual Subnets | virtual subnets | +| azure_bastion_nsg, empty_nsg, application_gateway, api_management, jumpbox | Network security groups | network security groups that can be attached to virtual subnets. | + + +## Customizing this example + +Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. + +## Deploying this example + +Once you have picked a scenario for test, you can deploy it using: + +```bash +rover -lz /tf/caf/landingzones/caf_networking \ +-level level2 \ +-var-folder /tf/caf/landingzones/caf_networking/scenario/100-single-region-hub \ +-a apply +``` diff --git a/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars b/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars new file mode 100644 index 000000000..26f860340 --- /dev/null +++ b/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars @@ -0,0 +1,27 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "foundations" + level = "level2" + key = "networking_hub" + tfstates = { + foundations = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + } +} + +resource_groups = { + vnet_hub_re1 = { + name = "vnet-hub-re1" + region = "region1" + } + vnet_hub_re2 = { + name = "vnet-hub-re2" + region = "region2" + } +} diff --git a/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars b/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars new file mode 100644 index 000000000..6352fec33 --- /dev/null +++ b/caf_solution/scenario/networking/101-multi-region-hub/network_security_group_definition.tfvars @@ -0,0 +1,344 @@ +# +# Definition of the networking security groups +# +network_security_group_definition = { + # This entry is applied to all subnets with no NSG defined + empty_nsg = { + } + + azure_bastion_nsg = { + + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } + + application_gateway = { + + nsg = [ + { + name = "Inbound-HTTP", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "80-82" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "Inbound-HTTPs", + priority = "130" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "Inbound-AGW", + priority = "140" + direction = "Inbound" + access = "Allow" + protocol = "*" + source_port_range = "*" + destination_port_range = "65200-65535" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + ] + } + + api_management = { + + nsg = [ + { + name = "Inbound-APIM", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3443" + source_address_prefix = "ApiManagement" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Inbound-Redis", + priority = "110" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "6381-6383" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Inbound-LoadBalancer", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "*" + source_address_prefix = "AzureLoadBalancer" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "Outbound-StorageHttp", + priority = "100" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "80" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-StorageHttps", + priority = "110" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-AADHttp", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "80" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureActiveDirectory" + }, + { + name = "Outbound-AADHttps", + priority = "130" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureActiveDirectory" + }, + { + name = "Outbound-SQL", + priority = "140" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "1433" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "SQL" + }, + { + name = "Outbound-EventHub", + priority = "150" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "5671-5672" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "EventHub" + }, + { + name = "Outbound-EventHubHttps", + priority = "160" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "EventHub" + }, + { + name = "Outbound-FileShareGit", + priority = "170" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "445" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "Storage" + }, + { + name = "Outbound-Health", + priority = "180" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "1886" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-Monitor", + priority = "190" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "AzureMonitor" + }, + { + name = "Outbound-MoSMTP1itor", + priority = "200" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "25" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-SMTP2", + priority = "210" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "587" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-SMTP3", + priority = "220" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "25028" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "INTERNET" + }, + { + name = "Outbound-Redis", + priority = "230" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "6381-6383" + source_address_prefix = "VirtualNetwork" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + + jumpbox = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "ssh-inbound-22", + priority = "200" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + +} diff --git a/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars b/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars new file mode 100644 index 000000000..40a1eb491 --- /dev/null +++ b/caf_solution/scenario/networking/101-multi-region-hub/peering.tfvars @@ -0,0 +1,31 @@ + +vnet_peerings = { + hub_re1_TO_hub_re2 = { + name = "hub_re1_TO_hub_re2" + from = { + vnet_key = "hub_re1" + } + to = { + vnet_key = "hub_re2" + } + allow_virtual_network_access = true + allow_forwarded_traffic = false + allow_gateway_transit = false + use_remote_gateways = false + } + + hub_re2_TO_hub_re1 = { + name = "hub_re2_TO_hub_re1" + from = { + vnet_key = "hub_re2" + } + to = { + vnet_key = "hub_re1" + } + allow_virtual_network_access = true + allow_forwarded_traffic = false + allow_gateway_transit = false + use_remote_gateways = false + } + +} diff --git a/caf_solution/scenario/networking/101-multi-region-hub/readme.md b/caf_solution/scenario/networking/101-multi-region-hub/readme.md new file mode 100644 index 000000000..8d7ad2ac7 --- /dev/null +++ b/caf_solution/scenario/networking/101-multi-region-hub/readme.md @@ -0,0 +1,50 @@ +# CAF landing zones for Terraform - Multi-region hub with global peering + +This scenario deploys the networking hub across multiple regions + +The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. + +* Hub and spoke +* Virtual WAN +* Application DMZ scenario +* Any custom network topology based on virtual networks or virtual WAN +* Library of network security groups definition + +Networking landing zone operates at **level 2**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). + +## Architecture diagram + +This example allows you to deploy the following topology: + +![101-example](../../documentation/img/101-multi-region-hub.png) + + +## Components deployed by this example + +| Component | Type of resource | Purpose | +|----------------------------------------------------------------------------------|-------------------------|--------------------------------------------------------------------------------------------| +| vnet-hub-re1, vnet-hub-re2 | Resource group | resource group to host the virtual network | +| vnet_hub_re1, vnet-hub-re2 | Virtual network | virtual network used as a hub | +| GatewaySubnet,AzureFirewallSubnet,AzureBastionSubnet, jumpbox, private_endpoints | Virtual Subnets | virtual subnets | +| azure_bastion_nsg, empty_nsg, application_gateway, api_management, jumpbox | Network security groups | network security groups that can be attached to virtual subnets. | +| hub_re1_TO_hub_re2, and hub_re2_TO_hub_re1 | Virtual network peering | Peering between vnet_hub_re1 and vnet-hub-re2 | +| bastion-re1-pip1, bastion-re2-pip1 | Public IP address | Public IP address to be used in vnet_hub_re1 and vnet-hub-re2, to be used by Azure Bastion | +| bastion-re1, bastion-re2 | Azure Bastion | Azure Bastion host in order to access the virtual network. | + + +## Customizing this example + +Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. + +## Deploying this example + +Once you have picked a scenario for test, you can deploy it using: + +```bash +rover -lz /tf/caf/landingzones/caf_networking \ +-level level2 \ +-var-folder /tf/caf/landingzones/caf_networking/scenario/101-multi-region-hub \ +-a apply +``` diff --git a/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars b/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars new file mode 100644 index 000000000..67af89832 --- /dev/null +++ b/caf_solution/scenario/networking/101-multi-region-hub/virtual_networks.tfvars @@ -0,0 +1,78 @@ + +vnets = { + hub_re1 = { + resource_group_key = "vnet_hub_re1" + region = "region1" + vnet = { + name = "hub-re1" + address_space = ["100.64.100.0/22"] + } + specialsubnets = { + GatewaySubnet = { + name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway + cidr = ["100.64.100.0/27"] + } + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["100.64.101.0/26"] + } + } + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["100.64.101.64/26"] + nsg_key = "azure_bastion_nsg" + } + jumpbox = { + name = "jumpbox" + cidr = ["100.64.102.0/27"] + nsg_key = "jumpbox" + } + private_endpoints = { + name = "private_endpoints" + cidr = ["100.64.103.128/25"] + enforce_private_link_endpoint_network_policies = true + } + } + + } + + hub_re2 = { + resource_group_key = "vnet_hub_re2" + region = "region2" + vnet = { + name = "hub-re2" + address_space = ["100.65.100.0/22"] + } + specialsubnets = { + GatewaySubnet = { + name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway + cidr = ["100.65.100.0/27"] + } + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["100.65.101.0/26"] + } + } + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["100.65.101.64/26"] + nsg_key = "azure_bastion_nsg" + } + jumpbox = { + name = "jumpbox" + cidr = ["100.65.102.0/27"] + nsg_key = "jumpbox" + } + private_endpoints = { + name = "private_endpoints" + cidr = ["100.65.103.128/25"] + enforce_private_link_endpoint_network_policies = true + } + } + + } + + +} diff --git a/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars b/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars new file mode 100644 index 000000000..b32be7ef7 --- /dev/null +++ b/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars @@ -0,0 +1,155 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "foundations" + level = "level2" + key = "networking_hub" + tfstates = { + foundations = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + } +} + +resource_groups = { + vnet_hub_region1 = { + name = "vnet-hub-re1" + } + vnet_spoke_region1 = { + name = "vnet-spoke-re1" + } +} + +vnets = { + hub_re1 = { + resource_group_key = "vnet_hub_region1" + vnet = { + name = "hub-re1" + address_space = ["10.10.100.0/24"] + } + specialsubnets = { + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["10.10.100.192/26"] + } + } + subnets = { + jumphost = { + name = "jumphost" + cidr = ["10.10.100.0/25"] + nsg_key = "jumphost" + } + } + } + + spoke_re1 = { + resource_group_key = "vnet_spoke_region1" + vnet = { + name = "spoke-re1" + address_space = ["10.11.100.0/24"] + } + specialsubnets = {} + subnets = { + jumphost = { + name = "jumphost" + cidr = ["10.11.100.0/25"] + nsg_key = "jumphost" + } + webapp1 = { + name = "webapp-presentation-tier" + cidr = ["10.11.100.128/25"] + } + } + } +} + +azurerm_firewalls = { + # Southeastasia firewall (do not change the key when created) + fw_re1 = { + region = "region1" + name = "azfwre1" + resource_group_key = "vnet_hub_region1" + vnet_key = "hub_re1" + public_ip_key = "az_fw_pip" + + } + +} + +public_ip_addresses = { + + az_fw_pip = { + name = "az_fw_re1_pip1" + region = "region1" + resource_group_key = "vnet_hub_region1" + sku = "Standard" + allocation_method = "Static" + ip_version = "IPv4" + idle_timeout_in_minutes = "4" + + } +} + +route_tables = { + default_to_firewall_re1 = { + name = "default_to_firewall_re1" + resource_group_key = "vnet_spoke_region1" + } +} + +azurerm_routes = { + default_to_firewall_rg1 = { + name = "0-0-0-0-through-firewall-re1" + resource_group_key = "vnet_spoke_region1" + route_table_key = "default_to_firewall_re1" + address_prefix = "0.0.0.0/0" + next_hop_type = "VirtualAppliance" + + # To be set when next_hop_type = "VirtualAppliance" + private_ip_keys = { + azurerm_firewall = { + key = "fw_re1" + interface_index = 0 + } + # virtual_machine = { + # key = "" + # nic_key = "" + # } + } + } +} + +vnet_peerings = { + hub-re1_TO_spoke-re1 = { + name = "hub-re1_TO_spoke-re1" + from = { + vnet_key = "hub_re1" + } + to = { + vnet_key = "spoke_re1" + } + allow_virtual_network_access = true + allow_forwarded_traffic = true + allow_gateway_transit = false + use_remote_gateways = false + } + + spoke-re1_TO_hub-re1 = { + name = "hub_re2_TO_hub_re1" + from = { + vnet_key = "spoke_re1" + } + to = { + vnet_key = "hub_re1" + } + allow_virtual_network_access = true + allow_forwarded_traffic = false + allow_gateway_transit = false + use_remote_gateways = false + } + +} diff --git a/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars b/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars new file mode 100644 index 000000000..40dfc522a --- /dev/null +++ b/caf_solution/scenario/networking/105-hub-and-spoke/network_security_group_definition.tfvars @@ -0,0 +1,122 @@ +# +# Definition of the networking security groups +# +network_security_group_definition = { + azure_bastion_nsg = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } + + jumphost = { + + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "ssh-inbound-22", + priority = "200" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + ] + } + +} diff --git a/caf_solution/scenario/networking/105-hub-and-spoke/readme.md b/caf_solution/scenario/networking/105-hub-and-spoke/readme.md new file mode 100644 index 000000000..b2820fb78 --- /dev/null +++ b/caf_solution/scenario/networking/105-hub-and-spoke/readme.md @@ -0,0 +1,52 @@ +# CAF landing zones for Terraform - Secure Hub and Spoke with Azure Firewall + +This scenario deploys the networking hub across multiple regions + +The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. + +* Hub and spoke +* Virtual WAN +* Application DMZ scenario +* Any custom network topology based on virtual networks or virtual WAN +* Library of network security groups definition + +Networking landing zone operates at **level 2**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). + +## Architecture diagram + +This example allows you to deploy the following topology: + +![101-example](../../documentation/img/105-hub-and-spoke.png) + + +## Components deployed by this example + +| Component | Type of resource | Purpose | +|--|--|--| +| vnet-hub-re1, vnet-spoke-re2 | Resource group | resource group to host the virtual network | +| hub-re1, spoke-re1 | Virtual network | virtual networks for hub and spokeshub | +| AzureFirewallSubnet,jumphost, webapp-presentation-tier | Virtual Subnets | virtual subnets | +| azure_bastion_nsg, , jumphost_nsg | Network security groups | network security groups that can be attached to virtual subnets. | +| hub_re1_TO_spoke_re1, and spoke_re1_TO_hub_re1 | Virtual network peering | Peering between hub-re1 and spoke-re1 | +| azfwre1 | Azure Firewall | Azure Firewall in Hub network | +| az_fw_re1_pip1 | Public IP address | Public IP address used by Azure Firewall | +| default_to_firewall_re1 | Route table | Route table to host route entries | +| 0-0-0-0-through-firewall-re1 | Route table entry | Route all traffic to Azure Firewall in hub | + + +## Customizing this example + +Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. + +## Deploying this example + +Once you have picked a scenario for test, you can deploy it using: + +```bash +rover -lz /tf/caf/landingzones/caf_networking \ +-level level2 \ +-var-folder /tf/caf/landingzones/caf_networking/scenario/105-hub-and-spoke \ +-a apply +``` diff --git a/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars new file mode 100644 index 000000000..ea7eb6d12 --- /dev/null +++ b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars @@ -0,0 +1,71 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "foundations" + level = "level2" + key = "networking_hub" + tfstates = { + foundations = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + launchpad = { + level = "lower" + tfstate = "caf_foundations.tfstate" + } + } +} + +resource_groups = { + vnet_re1 = { + name = "vnet-spoke-re1" + region = "region1" + } + hub_re1 = { + name = "vnet-hub-re1" + region = "region1" + } +} + +vnets = { + vnet_re1 = { + resource_group_key = "vnet_re1" + region = "region1" + vnet = { + name = "hub-re1" + address_space = ["10.10.100.0/24"] + } + specialsubnets = { + AzureFirewallSubnet = { + name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet + cidr = ["10.10.100.192/26"] + } + } + subnets = { + AzureBastionSubnet = { + name = "AzureBastionSubnet" #Must be called AzureBastionSubnet + cidr = ["10.10.100.160/27"] + nsg_key = "azure_bastion_nsg" + } + } + } +} + +vhub_peerings = { + # Establish the peering with Virtual Hubs + hub_rg1-TO-vnet_rg1 = { + vhub = { + virtual_wan_key = "vwan_re1" + virtual_hub_key = "hub_re1" + } + vnet = { + # If the virtual network is stored in another another landing zone, use the following attributes to refer the state file: + # lz_key = "networking" + # output_key = "vnets" + vnet_key = "vnet_re1" + } + name = "vhub_peering_hub_sg" + hub_to_virtual_network_traffic_allowed = true + virtual_network_to_hub_gateways_traffic_allowed = true + internet_security_enabled = true + } +} diff --git a/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars new file mode 100644 index 000000000..3d3d06e3a --- /dev/null +++ b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars @@ -0,0 +1,104 @@ +network_security_group_definition = { + empty_nsg = { + + nsg = [] + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + } + + azure_bastion_nsg = { + diagnostic_profiles = { + nsg = { + definition_key = "network_security_group" + destination_type = "storage" + destination_key = "all_regions" + } + operations = { + name = "operations" + definition_key = "network_security_group" + destination_type = "log_analytics" + destination_key = "central_logs" + } + } + + nsg = [ + { + name = "bastion-in-allow", + priority = "100" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "*" + }, + { + name = "bastion-control-in-allow-443", + priority = "120" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "135" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "Kerberos-password-change", + priority = "121" + direction = "Inbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "4443" + source_address_prefix = "GatewayManager" + destination_address_prefix = "*" + }, + { + name = "bastion-vnet-out-allow-22", + priority = "103" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-vnet-out-allow-3389", + priority = "101" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "*" + destination_address_prefix = "VirtualNetwork" + }, + { + name = "bastion-azure-out-allow", + priority = "120" + direction = "Outbound" + access = "Allow" + protocol = "tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "*" + destination_address_prefix = "AzureCloud" + } + ] + } +} \ No newline at end of file diff --git a/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md new file mode 100644 index 000000000..eb0b2487b --- /dev/null +++ b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/readme.md @@ -0,0 +1,47 @@ +# CAF landing zones for Terraform - Azure Virtual WAN with Firewall manager + +The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. + +* Hub and spoke +* Virtual WAN +* Application DMZ scenario +* Any custom network topology based on virtual networks or virtual WAN +* Library of network security groups definition + +Networking landing zone operates at **level 2**. + +For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). + +## Architecture diagram + +This example allows you to deploy the following topology: + +![virtual_wan_lz](../../documentation/img/106-hub-virtual-wan-firewall.png) + + +## Components deployed by this example + +| Component | Type of resource | Purpose | +|------------------------------|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| vnet-spoke-re1, vnet-hub-re1 | Resource group | resource group to host the virtual network and virtual WAN | +| vnet_re1 | Virtual network with subnets, network security groups | virtual network used as a spoke, attached to the virtual hub from Azure Virtual WAN | +| contosovWAN-re1 | Virtual WAN | virtual WAN infrastructure | +| hub-re1, hub-re2 | Virtual Hubs | virtual hubs to be deployed in region, the hubs can be configured to deploy point-to-site connectivity, site-to-site connectivity or Express Route connectivity. | +| hub_fw_re1, hub_fw_re2 | Azure Firewall | traffic filtering between hubs and outside | +| hub_rg1-TO-vnet_rg1 | Virtual network and Virtual Hubs peering objects | network peering between virtual hubs and virtual network | + + +## Customizing this example + +Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. + +## Deploying this example + +Once you have picked a scenario for test, you can deploy it using: + +```bash +rover -lz /tf/caf/landingzones/caf_networking \ +-level level2 \ +-var-folder /tf/caf/landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall \ +-a apply +``` diff --git a/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars new file mode 100644 index 000000000..547e62450 --- /dev/null +++ b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/virtual_wan.tfvars @@ -0,0 +1,84 @@ +virtual_wans = { + vwan_re1 = { + resource_group_key = "hub_re1" + name = "contosovWAN-re1" + region = "region1" + + hubs = { + hub_re1 = { + hub_name = "hub-re1" + region = "region1" + hub_address_prefix = "10.0.3.0/24" + deploy_firewall = true + firewall_name = "hub-fw-re1" + firewall_resource_group_key = "hub_re1" + deploy_p2s = false + p2s_config = { + name = "caf-sea-vpn-p2s" + scale_unit = 2 + connection_configuration = { + name = "client-connections" + vpn_client_address_pool = { + address_prefixes = ["192.168.0.0/24"] + } + } + server_config = { + vpn_authentication_types = ["Certificate"] + client_root_certificate = { + name = "DigiCert-Federated-ID-Root-CA" + public_cert_data = < Date: Sat, 27 Mar 2021 09:14:54 +0000 Subject: [PATCH 06/38] Update remote diagnostics --- caf_solution/landingzone.tf | 5 +++++ caf_solution/main.tf | 2 +- caf_solution/variables.tf | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf index bfa7422a6..ef261f14a 100644 --- a/caf_solution/landingzone.tf +++ b/caf_solution/landingzone.tf @@ -35,6 +35,11 @@ module "solution" { webapp = var.webapp diagnostics = { + diagnostics_definition = local.diagnostics.diagnostics_definition + diagnostics_destinations = local.diagnostics.diagnostics_destinations + storage_accounts = local.diagnostics.storage_accounts + log_analytics = local.diagnostics.log_analytics + event_hub_namespaces = local.diagnostics.event_hub_namespaces diagnostic_event_hub_namespaces = try(local.diagnostics.diagnostic_event_hub_namespaces, var.diagnostic_event_hub_namespaces) diagnostic_log_analytics = try(local.diagnostics.diagnostic_log_analytics, var.diagnostic_log_analytics) diagnostic_storage_accounts = try(local.diagnostics.diagnostic_storage_accounts, var.diagnostic_storage_accounts) diff --git a/caf_solution/main.tf b/caf_solution/main.tf index 909659c2d..0ab6b978b 100644 --- a/caf_solution/main.tf +++ b/caf_solution/main.tf @@ -36,7 +36,7 @@ terraform { provider "azurerm" { features { key_vault { - purge_soft_delete_on_destroy = true + purge_soft_delete_on_destroy = var.provider_azurerm_features_keyvault.purge_soft_delete_on_destroy } } } diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index b92fb1ac4..c8162258c 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -16,6 +16,13 @@ variable "landingzone" {} variable "global_settings" { default = {} } + +variable provider_azurerm_features_keyvault { + default = { + purge_soft_delete_on_destroy = false + } +} + variable "rover_version" { default = {} } From d4cbbc7bf663c86566a450ac78c1e3ba445af351 Mon Sep 17 00:00:00 2001 From: lolorol Date: Sat, 27 Mar 2021 09:55:41 +0000 Subject: [PATCH 07/38] fmt and networking --- .gitignore | 3 +- caf_solution/landingzone.tf | 2 +- caf_solution/local.networking.tf | 30 +++ caf_solution/variables.networking.tf | 77 +++++++ caf_solution/variables.tf | 16 +- landingzones.old/caf_eslz/output.tf | 14 +- landingzones.old/caf_eslz/variables.tf | 52 ++--- .../caf_foundations/dynamic_secrets.tf | 2 +- .../caf_foundations/landingzone.tf | 16 +- .../caf_foundations/locals.remote_tfstates.tf | 8 +- landingzones.old/caf_foundations/output.tf | 26 +-- landingzones.old/caf_foundations/variables.tf | 68 +++---- .../add-ons/azure_devops/main.tf | 2 +- .../add-ons/azure_devops/output.tf | 2 +- .../add-ons/azure_devops/variables.tf | 76 +++---- .../azure_devops_agent/dynamic_secrets.tf | 2 +- .../extensions/variables.tf | 6 +- .../add-ons/azure_devops_agent/main.tf | 2 +- .../add-ons/azure_devops_agent/output.tf | 14 +- .../add-ons/azure_devops_agent/variables.tf | 76 +++---- .../vm_extention_devops_agent.tf | 2 +- .../add-ons/terraform_cloud/variables.tf | 50 ++--- .../caf_launchpad/dynamic_secrets.tf | 2 +- landingzones.old/caf_launchpad/main.tf | 2 +- landingzones.old/caf_launchpad/output.tf | 18 +- landingzones.old/caf_launchpad/variables.tf | 110 +++++----- landingzones.old/caf_networking/main.tf | 2 +- landingzones.old/caf_networking/output.tf | 24 +-- .../configuration.tfvars | 4 +- landingzones.old/caf_networking/variables.tf | 98 ++++----- landingzones.old/caf_shared_services/main.tf | 2 +- .../caf_shared_services/output.tf | 12 +- .../caf_shared_services/variables.tf | 48 ++--- .../add-ons/aks_applications/app/variables.tf | 6 +- .../add-ons/aks_applications/variables.tf | 30 +-- .../add-ons/databricks/databricks.tf | 4 +- .../caf_solutions/add-ons/databricks/main.tf | 2 +- .../add-ons/databricks/variables.tf | 84 ++++---- .../caf_solutions/dynamic_secrets.tf | 2 +- landingzones.old/caf_solutions/main.tf | 2 +- .../modules/databricks/output.tf | 10 +- .../modules/databricks/variables.tf | 4 +- landingzones.old/caf_solutions/output.tf | 40 ++-- landingzones.old/caf_solutions/variables.tf | 192 +++++++++--------- 44 files changed, 670 insertions(+), 574 deletions(-) create mode 100644 caf_solution/local.networking.tf create mode 100644 caf_solution/variables.networking.tf diff --git a/.gitignore b/.gitignore index 7afced0f7..4c2a5948b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ **/~*.* **/*.log **/backend.azurerm.tf -public \ No newline at end of file +public +**/*.lock.* \ No newline at end of file diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf index ef261f14a..97aa28278 100644 --- a/caf_solution/landingzone.tf +++ b/caf_solution/landingzone.tf @@ -19,7 +19,7 @@ module "solution" { logged_aad_app_objectId = var.logged_aad_app_objectId logged_user_objectId = var.logged_user_objectId managed_identities = var.managed_identities - networking = var.networking + networking = local.networking remote_objects = local.remote_objects resource_groups = var.resource_groups role_mapping = var.role_mapping diff --git a/caf_solution/local.networking.tf b/caf_solution/local.networking.tf new file mode 100644 index 000000000..1cfa0533b --- /dev/null +++ b/caf_solution/local.networking.tf @@ -0,0 +1,30 @@ +locals { + networking = merge( + var.networking, + { + application_gateway_applications = var.application_gateway_applications + application_gateways = var.application_gateways + azurerm_firewall_application_rule_collection_definition = var.azurerm_firewall_application_rule_collection_definition + azurerm_firewall_nat_rule_collection_definition = var.azurerm_firewall_nat_rule_collection_definition + azurerm_firewall_network_rule_collection_definition = var.azurerm_firewall_network_rule_collection_definition + azurerm_firewalls = var.azurerm_firewalls + azurerm_routes = var.azurerm_routes + ddos_services = var.ddos_services + dns_zone_records = var.dns_zone_records + dns_zones = var.dns_zones + express_route_circuit_authorizations = var.express_route_circuit_authorizations + express_route_circuits = var.express_route_circuits + network_security_group_definition = var.network_security_group_definition + private_dns = var.private_dns + private_endpoints = var.private_endpoints + public_ip_addresses = var.public_ip_addresses + load_balancers = var.load_balancers + route_tables = var.route_tables + vhub_peerings = var.vhub_peerings + virtual_network_gateways = var.virtual_network_gateways + virtual_wans = var.virtual_wans + vnet_peerings = var.vnet_peerings + vnets = var.vnets + } + ) +} diff --git a/caf_solution/variables.networking.tf b/caf_solution/variables.networking.tf new file mode 100644 index 000000000..3387057b5 --- /dev/null +++ b/caf_solution/variables.networking.tf @@ -0,0 +1,77 @@ + +variable "application_gateways" { + default = {} +} +variable "application_gateway_applications" { + default = {} +} +variable "azurerm_firewalls" { + default = {} +} +variable "azurerm_firewall_application_rule_collection_definition" { + default = {} +} +variable "azurerm_firewall_nat_rule_collection_definition" { + default = {} +} +variable "azurerm_firewall_network_rule_collection_definition" { + default = {} +} +variable "azurerm_routes" { + default = {} +} +variable "ddos_services" { + default = {} +} +variable "dns_zones" { + default = {} +} +variable "dns_zone_records" { + default = {} +} +variable "express_route_circuits" { + default = {} +} +variable "express_route_circuit_authorizations" { + default = {} +} +variable "load_balancers" { + default = {} +} +variable "network_watchers" { + default = {} +} +variable "networking" { + default = {} + type = map(any) +} +variable "network_security_group_definition" { + default = {} +} +variable "private_endpoints" { + default = {} +} +variable "private_dns" { + default = {} +} +variable "public_ip_addresses" { + default = {} +} +variable "route_tables" { + default = {} +} +variable "virtual_network_gateways" { + default = {} +} +variable "virtual_wans" { + default = {} +} +variable "vnets" { + default = {} +} +variable "vhub_peerings" { + default = {} +} +variable "vnet_peerings" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index c8162258c..fbb3bc586 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -17,12 +17,13 @@ variable "global_settings" { default = {} } -variable provider_azurerm_features_keyvault { +variable "provider_azurerm_features_keyvault" { default = { purge_soft_delete_on_destroy = false } } + variable "rover_version" { default = {} } @@ -182,11 +183,6 @@ variable "database" { default = {} } -## Networking variables -variable "networking" { - description = "Networking configuration objects" - default = {} -} ## Security variables variable "security" { @@ -252,14 +248,6 @@ variable "automations" { default = {} } -variable "virtual_network_gateways" { - default = {} -} - -variable "virtual_network_gateway_connections" { - default = {} -} - variable "shared_image_galleries" { default = {} } diff --git a/landingzones.old/caf_eslz/output.tf b/landingzones.old/caf_eslz/output.tf index f856906a6..915837487 100644 --- a/landingzones.old/caf_eslz/output.tf +++ b/landingzones.old/caf_eslz/output.tf @@ -1,28 +1,28 @@ -output global_settings { +output "global_settings" { value = local.global_settings sensitive = true } -output diagnostics { +output "diagnostics" { value = module.foundations.diagnostics sensitive = true } -output vnets { +output "vnets" { value = local.remote.vnets sensitive = true } -output managed_identities { +output "managed_identities" { value = local.remote.managed_identities sensitive = true } -output azuread_groups { +output "azuread_groups" { value = local.remote.azuread_groups sensitive = true } -output tfstates { +output "tfstates" { value = local.tfstates sensitive = true } -output keyvaults { +output "keyvaults" { value = tomap({ (var.landingzone.key) = try(module.foundations.keyvaults, {}) }) diff --git a/landingzones.old/caf_eslz/variables.tf b/landingzones.old/caf_eslz/variables.tf index fc19f2f99..0c1e834c0 100644 --- a/landingzones.old/caf_eslz/variables.tf +++ b/landingzones.old/caf_eslz/variables.tf @@ -1,25 +1,25 @@ # Map of the remote data state -variable lower_storage_account_name {} -variable lower_container_name {} -variable lower_resource_group_name {} +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} -variable tfstate_subscription_id { +variable "tfstate_subscription_id" { description = "This value is propulated by the rover. subscription id hosting the remote tfstates" } -variable tfstate_storage_account_name { +variable "tfstate_storage_account_name" { description = "This value is propulated by the rover" } -variable tfstate_container_name { +variable "tfstate_container_name" { description = "This value is propulated by the rover" } -variable tfstate_key { +variable "tfstate_key" { description = "This value is propulated by the rover" } -variable tfstate_resource_group_name { +variable "tfstate_resource_group_name" { description = "This value is propulated by the rover" } -variable landingzone { +variable "landingzone" { default = { backend_type = "azurerm" global_settings_key = "launchpad" @@ -34,50 +34,50 @@ variable landingzone { } } -variable tenant_id {} -variable rover_version {} -variable logged_user_objectId { +variable "tenant_id" {} +variable "rover_version" {} +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable tags { - type = map +variable "tags" { + type = map(any) default = {} } -variable enterprise_scale { +variable "enterprise_scale" { default = {} } -variable diagnostics_definition { +variable "diagnostics_definition" { default = {} } -variable keyvaults { +variable "keyvaults" { default = {} } -variable resource_groups { +variable "resource_groups" { default = {} } -variable log_analytics { +variable "log_analytics" { default = {} } -variable event_hub_namespaces { +variable "event_hub_namespaces" { default = {} } -variable diagnostic_storage_accounts { +variable "diagnostic_storage_accounts" { default = {} } -variable diagnostic_event_hub_namespaces { +variable "diagnostic_event_hub_namespaces" { default = {} } -variable diagnostic_log_analytics { +variable "diagnostic_log_analytics" { default = {} } -variable diagnostics_destinations { +variable "diagnostics_destinations" { default = {} } -variable dynamic_keyvault_secrets { +variable "dynamic_keyvault_secrets" { default = {} } \ No newline at end of file diff --git a/landingzones.old/caf_foundations/dynamic_secrets.tf b/landingzones.old/caf_foundations/dynamic_secrets.tf index ae6338236..ae28233b0 100644 --- a/landingzones.old/caf_foundations/dynamic_secrets.tf +++ b/landingzones.old/caf_foundations/dynamic_secrets.tf @@ -1,5 +1,5 @@ -module dynamic_keyvault_secrets { +module "dynamic_keyvault_secrets" { source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" version = "~>5.2.0" diff --git a/landingzones.old/caf_foundations/landingzone.tf b/landingzones.old/caf_foundations/landingzone.tf index d44b5b6ee..8bda58b4c 100644 --- a/landingzones.old/caf_foundations/landingzone.tf +++ b/landingzones.old/caf_foundations/landingzone.tf @@ -19,12 +19,12 @@ module "foundations" { event_hub_namespaces = var.event_hub_namespaces ## Azure Active Directory - azuread_apps = var.azuread_apps - azuread_api_permissions = var.azuread_api_permissions - azuread_groups = var.azuread_groups - azuread_roles = var.azuread_roles - azuread_users = var.azuread_users - managed_identities = var.managed_identities - custom_role_definitions = var.custom_role_definitions - role_mapping = var.role_mapping + azuread_apps = var.azuread_apps + azuread_api_permissions = var.azuread_api_permissions + azuread_groups = var.azuread_groups + azuread_roles = var.azuread_roles + azuread_users = var.azuread_users + managed_identities = var.managed_identities + custom_role_definitions = var.custom_role_definitions + role_mapping = var.role_mapping } diff --git a/landingzones.old/caf_foundations/locals.remote_tfstates.tf b/landingzones.old/caf_foundations/locals.remote_tfstates.tf index 287208e10..b2c4c2d2b 100644 --- a/landingzones.old/caf_foundations/locals.remote_tfstates.tf +++ b/landingzones.old/caf_foundations/locals.remote_tfstates.tf @@ -83,10 +83,10 @@ locals { } combined = { - managed_identities = merge(local.remote.managed_identities, tomap({ (var.landingzone.key) = module.foundations.managed_identities })) - azuread_groups = merge(local.remote.azuread_groups, tomap({ (var.landingzone.key) = module.foundations.azuread_groups })) - aad_apps = merge(local.remote.azuread_applications, tomap({ (var.landingzone.key) = module.foundations.aad_apps })) - azuread_users = merge(local.remote.azuread_users, tomap({ (var.landingzone.key) = module.foundations.azuread_users })) + managed_identities = merge(local.remote.managed_identities, tomap({ (var.landingzone.key) = module.foundations.managed_identities })) + azuread_groups = merge(local.remote.azuread_groups, tomap({ (var.landingzone.key) = module.foundations.azuread_groups })) + aad_apps = merge(local.remote.azuread_applications, tomap({ (var.landingzone.key) = module.foundations.aad_apps })) + azuread_users = merge(local.remote.azuread_users, tomap({ (var.landingzone.key) = module.foundations.azuread_users })) } } diff --git a/landingzones.old/caf_foundations/output.tf b/landingzones.old/caf_foundations/output.tf index 2db7ccbc4..a66bb9edd 100644 --- a/landingzones.old/caf_foundations/output.tf +++ b/landingzones.old/caf_foundations/output.tf @@ -1,39 +1,39 @@ -output global_settings { +output "global_settings" { value = local.global_settings sensitive = true } -output diagnostics { +output "diagnostics" { value = module.foundations.diagnostics sensitive = true } -output vnets { +output "vnets" { value = local.remote.vnets sensitive = true } -output tfstates { +output "tfstates" { value = local.tfstates sensitive = true } -output keyvaults { +output "keyvaults" { value = tomap({ (var.landingzone.key) = try(module.foundations.keyvaults, {}) }) sensitive = true } # Active Directory -output managed_identities { - value = local.combined.managed_identities +output "managed_identities" { + value = local.combined.managed_identities sensitive = true } -output azuread_groups { - value = local.combined.azuread_groups +output "azuread_groups" { + value = local.combined.azuread_groups sensitive = true } -output aad_apps { - value = local.combined.aad_apps +output "aad_apps" { + value = local.combined.aad_apps sensitive = true } -output azuread_users { - value = local.combined.managed_identities +output "azuread_users" { + value = local.combined.managed_identities sensitive = true } diff --git a/landingzones.old/caf_foundations/variables.tf b/landingzones.old/caf_foundations/variables.tf index ae7930164..fa721b4e2 100644 --- a/landingzones.old/caf_foundations/variables.tf +++ b/landingzones.old/caf_foundations/variables.tf @@ -1,25 +1,25 @@ # Map of the remote data state -variable lower_storage_account_name {} -variable lower_container_name {} -variable lower_resource_group_name {} +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} -variable tfstate_subscription_id { +variable "tfstate_subscription_id" { description = "This value is propulated by the rover. subscription id hosting the remote tfstates" } -variable tfstate_storage_account_name { +variable "tfstate_storage_account_name" { description = "This value is propulated by the rover" } -variable tfstate_container_name { +variable "tfstate_container_name" { description = "This value is propulated by the rover" } -variable tfstate_key { +variable "tfstate_key" { description = "This value is propulated by the rover" } -variable tfstate_resource_group_name { +variable "tfstate_resource_group_name" { description = "This value is propulated by the rover" } -variable landingzone { +variable "landingzone" { default = { backend_type = "azurerm" global_settings_key = "launchpad" @@ -34,77 +34,77 @@ variable landingzone { } } -variable tenant_id {} -variable rover_version {} -variable logged_user_objectId { +variable "tenant_id" {} +variable "rover_version" {} +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable tags { - type = map +variable "tags" { + type = map(any) default = {} } -variable enterprise_scale { +variable "enterprise_scale" { default = {} } -variable diagnostics_definition { +variable "diagnostics_definition" { default = {} } -variable keyvaults { +variable "keyvaults" { default = {} } -variable resource_groups { +variable "resource_groups" { default = {} } -variable log_analytics { +variable "log_analytics" { default = {} } -variable event_hub_namespaces { +variable "event_hub_namespaces" { default = {} } -variable diagnostic_storage_accounts { +variable "diagnostic_storage_accounts" { default = {} } -variable diagnostic_event_hub_namespaces { +variable "diagnostic_event_hub_namespaces" { default = {} } -variable diagnostic_log_analytics { +variable "diagnostic_log_analytics" { default = {} } -variable diagnostics_destinations { +variable "diagnostics_destinations" { default = {} } -variable dynamic_keyvault_secrets { +variable "dynamic_keyvault_secrets" { default = {} } ## Azure Active Directory -variable azuread_apps { +variable "azuread_apps" { default = {} } -variable azuread_api_permissions { +variable "azuread_api_permissions" { default = {} } -variable azuread_groups { +variable "azuread_groups" { default = {} } -variable azuread_users { +variable "azuread_users" { default = {} } -variable azuread_roles { +variable "azuread_roles" { default = {} } -variable managed_identities { +variable "managed_identities" { default = {} } -variable custom_role_definitions { +variable "custom_role_definitions" { default = {} } -variable role_mapping { +variable "role_mapping" { default = { built_in_role_mapping = {} custom_role_mapping = {} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf index 37fc556e3..a85b06a80 100644 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf +++ b/landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf @@ -1,7 +1,7 @@ terraform { required_providers { azurerm = { - source = "hashicorp/azurerm" + source = "hashicorp/azurerm" version = "~> 2.43" } azuread = { diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf index c8ebf3f9d..a46105168 100644 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf +++ b/landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf @@ -1,4 +1,4 @@ -output keyvaults { +output "keyvaults" { value = map( var.landingzone.key, module.caf.keyvaults ) diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf index 8cf5b7916..87dcc831a 100644 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf +++ b/landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf @@ -1,102 +1,102 @@ # Map of the remote data state for lower level -variable lower_storage_account_name {} -variable lower_container_name {} -variable lower_resource_group_name {} +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} -variable tfstate_storage_account_name {} -variable tfstate_container_name {} -variable tfstate_key {} -variable tfstate_resource_group_name {} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} -variable tfstate_subscription_id { +variable "tfstate_subscription_id" { description = "This value is propulated by the rover. subscription id hosting the remote tfstates" } -variable global_settings { +variable "global_settings" { default = {} } -variable tenant_id {} -variable landingzone { +variable "tenant_id" {} +variable "landingzone" { } -variable rover_version { +variable "rover_version" { default = null } -variable logged_user_objectId { +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable tags { +variable "tags" { default = null } -variable app_service_environments { +variable "app_service_environments" { default = {} } -variable app_service_plans { +variable "app_service_plans" { default = {} } -variable app_services { +variable "app_services" { default = {} } -variable diagnostics_definition { +variable "diagnostics_definition" { default = {} } -variable resource_groups { +variable "resource_groups" { default = {} } -variable network_security_group_definition { +variable "network_security_group_definition" { default = {} } -variable vnets { +variable "vnets" { default = {} } -variable azurerm_redis_caches { +variable "azurerm_redis_caches" { default = {} } -variable mssql_servers { +variable "mssql_servers" { default = {} } -variable storage_accounts { +variable "storage_accounts" { default = {} } -variable storage_account_blobs { +variable "storage_account_blobs" { default = {} } -variable azuread_groups { +variable "azuread_groups" { default = {} } -variable keyvaults { +variable "keyvaults" { default = {} } -variable keyvault_access_policies { +variable "keyvault_access_policies" { default = {} } -variable keyvault_access_policies_azuread_apps { +variable "keyvault_access_policies_azuread_apps" { default = {} } -variable virtual_machines { +variable "virtual_machines" { default = {} } -variable diagnostic_storage_accounts { +variable "diagnostic_storage_accounts" { default = {} } -variable virtual_machine_extension_scripts { +variable "virtual_machine_extension_scripts" { default = {} } -variable azure_devops { +variable "azure_devops" { default = {} } -variable role_mapping { +variable "role_mapping" { default = {} } -variable custom_role_definitions { +variable "custom_role_definitions" { default = {} } -variable azuread_apps { +variable "azuread_apps" { default = {} } -variable dynamic_keyvault_secrets { +variable "dynamic_keyvault_secrets" { default = {} } \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf index 7d3f50ba1..48c0cd240 100644 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf +++ b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf @@ -1,5 +1,5 @@ -module dynamic_keyvault_secrets { +module "dynamic_keyvault_secrets" { source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" version = "~>5.2.0" diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf index 88453a149..9b8d2f8c3 100644 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf +++ b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf @@ -1,3 +1,3 @@ -variable virtual_machine_id {} -variable extensions {} -variable settings {} \ No newline at end of file +variable "virtual_machine_id" {} +variable "extensions" {} +variable "settings" {} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf index f0376bf7c..4ae9c573e 100644 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf +++ b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf @@ -1,7 +1,7 @@ terraform { required_providers { azurerm = { - source = "hashicorp/azurerm" + source = "hashicorp/azurerm" version = "~> 2.43" } azuread = { diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf index 816e24587..e19cb88aa 100644 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf +++ b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf @@ -1,34 +1,34 @@ -output managed_identities { +output "managed_identities" { value = local.combined.managed_identities sensitive = false } -output azuread_groups { +output "azuread_groups" { value = local.combined.azuread_groups sensitive = true } -output keyvaults { +output "keyvaults" { value = local.combined.keyvaults sensitive = false } -output vnets { +output "vnets" { value = local.remote.vnets sensitive = false } -output global_settings { +output "global_settings" { value = local.global_settings sensitive = true } -output diagnostics { +output "diagnostics" { value = local.diagnostics sensitive = true } -output tfstates { +output "tfstates" { value = local.tfstates sensitive = true } \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf index 4efef26b0..45c344a59 100644 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf +++ b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf @@ -1,102 +1,102 @@ # Map of the remote data state for lower level -variable lower_storage_account_name {} -variable lower_container_name {} -variable lower_resource_group_name {} +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} -variable tfstate_storage_account_name {} -variable tfstate_container_name {} -variable tfstate_key {} -variable tfstate_resource_group_name {} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} -variable tfstate_subscription_id { +variable "tfstate_subscription_id" { description = "This value is propulated by the rover. subscription id hosting the remote tfstates" } -variable global_settings { +variable "global_settings" { default = {} } -variable tenant_id {} -variable landingzone { +variable "tenant_id" {} +variable "landingzone" { } -variable rover_version { +variable "rover_version" { default = null } -variable logged_user_objectId { +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable tags { +variable "tags" { default = null } -variable app_service_environments { +variable "app_service_environments" { default = {} } -variable app_service_plans { +variable "app_service_plans" { default = {} } -variable app_services { +variable "app_services" { default = {} } -variable diagnostics_definition { +variable "diagnostics_definition" { default = {} } -variable resource_groups { +variable "resource_groups" { default = {} } -variable network_security_group_definition { +variable "network_security_group_definition" { default = {} } -variable vnets { +variable "vnets" { default = {} } -variable azurerm_redis_caches { +variable "azurerm_redis_caches" { default = {} } -variable mssql_servers { +variable "mssql_servers" { default = {} } -variable storage_accounts { +variable "storage_accounts" { default = {} } -variable storage_account_blobs { +variable "storage_account_blobs" { default = {} } -variable azuread_groups { +variable "azuread_groups" { default = {} } -variable keyvaults { +variable "keyvaults" { default = {} } -variable keyvault_access_policies { +variable "keyvault_access_policies" { default = {} } -variable virtual_machines { +variable "virtual_machines" { default = {} } -variable diagnostic_storage_accounts { +variable "diagnostic_storage_accounts" { default = {} } -variable virtual_machine_extension_scripts { +variable "virtual_machine_extension_scripts" { default = {} } -variable azure_devops { +variable "azure_devops" { default = {} } -variable role_mapping { +variable "role_mapping" { default = {} } -variable custom_role_definitions { +variable "custom_role_definitions" { default = {} } -variable azuread_apps { +variable "azuread_apps" { default = {} } -variable dynamic_keyvault_secrets { +variable "dynamic_keyvault_secrets" { default = {} } -variable managed_identities { +variable "managed_identities" { default = {} } \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf index fa9a97718..898d03288 100644 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf +++ b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf @@ -13,7 +13,7 @@ data "azurerm_key_vault_secret" "agent_pat" { } -module vm_extensions { +module "vm_extensions" { source = "./extensions" depends_on = [module.caf] for_each = { diff --git a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf index e84068bba..499b0aba5 100644 --- a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf +++ b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf @@ -1,85 +1,85 @@ # Map of the remote data state for lower level -variable lower_storage_account_name { +variable "lower_storage_account_name" { default = {} } -variable lower_container_name { +variable "lower_container_name" { default = {} } -variable lower_resource_group_name { +variable "lower_resource_group_name" { default = {} } -variable tfstate_storage_account_name { +variable "tfstate_storage_account_name" { default = {} } -variable tfstate_container_name { +variable "tfstate_container_name" { default = {} } -variable tfstate_key { +variable "tfstate_key" { default = {} } -variable tfstate_resource_group_name { +variable "tfstate_resource_group_name" { default = {} } -variable global_settings { +variable "global_settings" { default = {} } -variable tenant_id { +variable "tenant_id" { default = {} } -variable landingzone { +variable "landingzone" { default = {} } -variable rover_version { +variable "rover_version" { default = null } -variable logged_user_objectId { +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable tags { +variable "tags" { default = null } -variable keyvaults { +variable "keyvaults" { default = {} } -variable keyvault_access_policies { +variable "keyvault_access_policies" { default = {} } -variable role_mapping { +variable "role_mapping" { default = {} } -variable secrets_from_keys { +variable "secrets_from_keys" { default = {} } -variable custom_role_definitions { +variable "custom_role_definitions" { default = {} } -variable azuread_apps { +variable "azuread_apps" { default = {} } -variable tfe_organizations { +variable "tfe_organizations" { default = {} } -variable tfe_workspaces { +variable "tfe_workspaces" { default = {} } -variable tfe_variables { +variable "tfe_variables" { default = {} } -variable tfe_servers { +variable "tfe_servers" { default = {} } -variable tfe_agents { +variable "tfe_agents" { default = {} } \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/dynamic_secrets.tf b/landingzones.old/caf_launchpad/dynamic_secrets.tf index 5dd97a475..17d72202d 100644 --- a/landingzones.old/caf_launchpad/dynamic_secrets.tf +++ b/landingzones.old/caf_launchpad/dynamic_secrets.tf @@ -1,5 +1,5 @@ -module dynamic_keyvault_secrets { +module "dynamic_keyvault_secrets" { source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" version = "~>5.2.0" diff --git a/landingzones.old/caf_launchpad/main.tf b/landingzones.old/caf_launchpad/main.tf index 7064f4f8f..f5180c8bc 100644 --- a/landingzones.old/caf_launchpad/main.tf +++ b/landingzones.old/caf_launchpad/main.tf @@ -70,7 +70,7 @@ locals { passthrough = var.passthrough prefix = var.prefix prefixes = var.prefix == "" ? null : [try(var.prefix, random_string.prefix.0.result)] - prefix_with_hyphen = var.prefix == "" ? "" : try(format("%s-", var.prefix) , format("%s-", random_string.prefix.0.result)) + prefix_with_hyphen = var.prefix == "" ? "" : try(format("%s-", var.prefix), format("%s-", random_string.prefix.0.result)) random_length = var.random_length regions = var.regions tags = var.tags diff --git a/landingzones.old/caf_launchpad/output.tf b/landingzones.old/caf_launchpad/output.tf index cd0c82677..01d7898d6 100644 --- a/landingzones.old/caf_launchpad/output.tf +++ b/landingzones.old/caf_launchpad/output.tf @@ -1,9 +1,9 @@ -output global_settings { +output "global_settings" { value = local.global_settings sensitive = true } -output diagnostics { +output "diagnostics" { value = module.launchpad.diagnostics sensitive = true } @@ -20,45 +20,45 @@ output diagnostics { # description = "[WARNING] deprecated. Use vnets from 0.4" # } -output vnets { +output "vnets" { value = tomap({ (var.landingzone.key) = module.launchpad.vnets }) sensitive = true } -output tfstates { +output "tfstates" { value = local.tfstates sensitive = true } -output backend_type { +output "backend_type" { value = var.landingzone.backend_type sensitive = true } -output keyvaults { +output "keyvaults" { value = tomap({ (var.landingzone.key) = module.launchpad.keyvaults }) sensitive = true } -output managed_identities { +output "managed_identities" { value = tomap({ (var.landingzone.key) = module.launchpad.managed_identities }) sensitive = true } -output aad_apps { +output "aad_apps" { value = tomap({ (var.landingzone.key) = module.launchpad.aad_apps }) sensitive = true } -output azuread_groups { +output "azuread_groups" { value = tomap({ (var.landingzone.key) = module.launchpad.azuread_groups }) diff --git a/landingzones.old/caf_launchpad/variables.tf b/landingzones.old/caf_launchpad/variables.tf index acf69cd2f..4836eda20 100644 --- a/landingzones.old/caf_launchpad/variables.tf +++ b/landingzones.old/caf_launchpad/variables.tf @@ -1,191 +1,191 @@ # Map of the current tfstate -variable tfstate_storage_account_name { +variable "tfstate_storage_account_name" { default = null } -variable tfstate_container_name { +variable "tfstate_container_name" { default = null } -variable tfstate_key { +variable "tfstate_key" { default = null } -variable tfstate_resource_group_name { +variable "tfstate_resource_group_name" { default = null } -variable tenant_id {} -variable landingzone { +variable "tenant_id" {} +variable "landingzone" { description = "The landing zone name is used to reference the tfstate in configuration files. Therefore while set it is recommended not to change" } -variable passthrough { +variable "passthrough" { default = false } -variable random_length { +variable "random_length" { default = null } -variable inherit_tags { +variable "inherit_tags" { default = false } -variable default_region { +variable "default_region" { description = "Define the default region where services are deployed if the location is not set at the resource level" default = "region1" } -variable regions { - type = map +variable "regions" { + type = map(any) description = "List of the regions where services can be deployed. This impact the diagnostics logs settings" default = { region1 = "southeastasia" } } -variable enable { +variable "enable" { description = "Map of services defined in the configuration file you want to disable during a deployment" default = {} } -variable prefix { +variable "prefix" { default = null } -variable use_slug { +variable "use_slug" { default = true } -variable log_analytics { +variable "log_analytics" { default = {} } -variable event_hub_namespaces { +variable "event_hub_namespaces" { default = {} } # Do not change the default value to be able to upgrade to the standard launchpad -variable tf_name { +variable "tf_name" { description = "Name of the terraform state in the blob storage (Does not include the extension .tfstate). Setup by the rover. Leave empty in the configuration file" default = "" } -variable resource_groups {} +variable "resource_groups" {} -variable storage_accounts {} -variable diagnostic_storage_accounts { +variable "storage_accounts" {} +variable "diagnostic_storage_accounts" { default = {} } -variable diagnostic_event_hub_namespaces { +variable "diagnostic_event_hub_namespaces" { default = {} } -variable diagnostic_log_analytics { +variable "diagnostic_log_analytics" { default = {} } -variable keyvaults {} -variable keyvault_access_policies { +variable "keyvaults" {} +variable "keyvault_access_policies" { default = {} } -variable dynamic_keyvault_secrets {} +variable "dynamic_keyvault_secrets" {} -variable subscriptions { +variable "subscriptions" { default = {} } ## Azure Active Directory -variable azuread_apps { +variable "azuread_apps" { default = {} } -variable azuread_groups { +variable "azuread_groups" { default = {} } -variable azuread_users { +variable "azuread_users" { default = {} } -variable azuread_roles { +variable "azuread_roles" { default = {} } -variable managed_identities { +variable "managed_identities" { default = {} } -variable virtual_machines { +variable "virtual_machines" { description = "Virtual machine object" default = {} } -variable bastion_hosts { +variable "bastion_hosts" { default = {} } -variable launchpad_key_names {} +variable "launchpad_key_names" {} -variable custom_role_definitions { +variable "custom_role_definitions" { default = {} } -variable role_mapping { +variable "role_mapping" { default = { built_in_role_mapping = {} custom_role_mapping = {} } } -variable tags { - type = map +variable "tags" { + type = map(any) default = {} } -variable rover_version {} +variable "rover_version" {} -variable user_type {} +variable "user_type" {} -variable logged_user_objectId { +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable aad_users { +variable "aad_users" { default = {} } -variable aad_roles { +variable "aad_roles" { default = {} } -variable azuread_api_permissions { +variable "azuread_api_permissions" { default = {} } -variable environment { +variable "environment" { type = string description = "This variable is set by the rover during the deployment based on the -env or -environment flags. Default to sandpit" } -variable diagnostics_definition { +variable "diagnostics_definition" { default = {} } -variable diagnostics_destinations { +variable "diagnostics_destinations" { default = {} } -variable vnets { +variable "vnets" { default = {} } -variable network_security_group_definition { +variable "network_security_group_definition" { default = {} } -variable public_ip_addresses { +variable "public_ip_addresses" { default = {} } -variable route_tables { +variable "route_tables" { default = {} } -variable azurerm_routes { +variable "azurerm_routes" { default = {} } -variable keyvault_access_policies_azuread_apps { +variable "keyvault_access_policies_azuread_apps" { default = {} } diff --git a/landingzones.old/caf_networking/main.tf b/landingzones.old/caf_networking/main.tf index abdc1b7f0..8eb1f3590 100644 --- a/landingzones.old/caf_networking/main.tf +++ b/landingzones.old/caf_networking/main.tf @@ -1,7 +1,7 @@ terraform { required_providers { azurerm = { - source = "hashicorp/azurerm" + source = "hashicorp/azurerm" version = "~> 2.43" } azuread = { diff --git a/landingzones.old/caf_networking/output.tf b/landingzones.old/caf_networking/output.tf index 8a177ac7f..500b278c8 100644 --- a/landingzones.old/caf_networking/output.tf +++ b/landingzones.old/caf_networking/output.tf @@ -1,58 +1,58 @@ -output diagnostics { +output "diagnostics" { value = module.networking.diagnostics sensitive = true } -output tfstates { +output "tfstates" { value = local.tfstates sensitive = true } -output vnets { +output "vnets" { value = local.combined.vnets sensitive = true } -output azurerm_firewalls { +output "azurerm_firewalls" { value = local.combined.azurerm_firewalls sensitive = true } -output virtual_wans { +output "virtual_wans" { value = local.combined.virtual_wans sensitive = true description = "Virtual WAN output" } -output private_dns { +output "private_dns" { value = local.combined.private_dns sensitive = true } -output application_gateways { +output "application_gateways" { value = local.combined.application_gateways sensitive = true } -output application_gateway_applications { +output "application_gateway_applications" { value = local.combined.application_gateway_applications sensitive = true } -output public_ip_addresses { +output "public_ip_addresses" { value = local.combined.public_ip_addresses sensitive = true } -output managed_identities { +output "managed_identities" { value = local.remote.managed_identities sensitive = true } -output azuread_groups { +output "azuread_groups" { value = local.remote.azuread_groups sensitive = true } -output express_route_circuits { +output "express_route_circuits" { value = module.networking.express_route_circuits sensitive = false } diff --git a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars index 591d780e0..ea7eb6d12 100644 --- a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars +++ b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars @@ -63,9 +63,9 @@ vhub_peerings = { # output_key = "vnets" vnet_key = "vnet_re1" } - name = "vhub_peering_hub_sg" + name = "vhub_peering_hub_sg" hub_to_virtual_network_traffic_allowed = true virtual_network_to_hub_gateways_traffic_allowed = true - internet_security_enabled = true + internet_security_enabled = true } } diff --git a/landingzones.old/caf_networking/variables.tf b/landingzones.old/caf_networking/variables.tf index 3d450ce15..4f51d13e1 100644 --- a/landingzones.old/caf_networking/variables.tf +++ b/landingzones.old/caf_networking/variables.tf @@ -1,17 +1,17 @@ # Map of the remote data state for lower level -variable lower_storage_account_name {} -variable lower_container_name {} -variable lower_resource_group_name {} +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} -variable tfstate_subscription_id { +variable "tfstate_subscription_id" { description = "This value is propulated by the rover. subscription id hosting the remote tfstates" } -variable tfstate_storage_account_name {} -variable tfstate_container_name {} -variable tfstate_key {} -variable tfstate_resource_group_name {} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} -variable landingzone { +variable "landingzone" { default = { backend_type = "azurerm" current = { @@ -30,118 +30,118 @@ variable landingzone { } } } -variable tenant_id {} +variable "tenant_id" {} -variable global_settings { +variable "global_settings" { default = {} } -variable rover_version {} -variable logged_user_objectId { +variable "rover_version" {} +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable tags { - type = map +variable "tags" { + type = map(any) default = {} } -variable diagnostics_definition { +variable "diagnostics_definition" { default = null } -variable resource_groups { +variable "resource_groups" { default = {} } -variable vnets { +variable "vnets" { default = {} } -variable virtual_wans { +variable "virtual_wans" { default = {} } -variable public_ip_addresses { +variable "public_ip_addresses" { default = {} } -variable vnet_peerings { +variable "vnet_peerings" { default = {} } -variable vhub_peerings { +variable "vhub_peerings" { default = {} } -variable azurerm_firewalls { +variable "azurerm_firewalls" { default = {} } -variable network_security_group_definition { +variable "network_security_group_definition" { default = null } -variable route_tables { +variable "route_tables" { default = {} } -variable azurerm_routes { +variable "azurerm_routes" { default = {} } -variable storage_accounts { +variable "storage_accounts" { default = {} } -variable virtual_machines { +variable "virtual_machines" { default = {} } -variable managed_identities { +variable "managed_identities" { default = {} } -variable azurerm_firewall_network_rule_collection_definition { +variable "azurerm_firewall_network_rule_collection_definition" { default = {} } -variable azurerm_firewall_application_rule_collection_definition { +variable "azurerm_firewall_application_rule_collection_definition" { default = {} } -variable azurerm_firewall_nat_rule_collection_definition { +variable "azurerm_firewall_nat_rule_collection_definition" { default = {} } -variable azure_container_registries { +variable "azure_container_registries" { default = {} } -variable bastion_hosts { +variable "bastion_hosts" { default = {} } -variable ddos_services { +variable "ddos_services" { default = {} } -variable private_dns { +variable "private_dns" { default = {} } -variable application_gateways { +variable "application_gateways" { default = {} } -variable application_gateway_applications { +variable "application_gateway_applications" { default = {} } -variable keyvaults { +variable "keyvaults" { default = {} } -variable keyvault_access_policies { +variable "keyvault_access_policies" { default = {} } -variable express_route_circuits { +variable "express_route_circuits" { default = {} } -variable express_route_circuit_authorizations { +variable "express_route_circuit_authorizations" { default = {} } -variable network_watchers { +variable "network_watchers" { default = {} } -variable private_endpoints { +variable "private_endpoints" { default = {} } -variable dns_zones { +variable "dns_zones" { default = {} } -variable dns_zone_records { +variable "dns_zone_records" { default = {} } -variable virtual_network_gateways { +variable "virtual_network_gateways" { default = {} } -variable load_balancers { +variable "load_balancers" { default = {} } \ No newline at end of file diff --git a/landingzones.old/caf_shared_services/main.tf b/landingzones.old/caf_shared_services/main.tf index abdc1b7f0..8eb1f3590 100644 --- a/landingzones.old/caf_shared_services/main.tf +++ b/landingzones.old/caf_shared_services/main.tf @@ -1,7 +1,7 @@ terraform { required_providers { azurerm = { - source = "hashicorp/azurerm" + source = "hashicorp/azurerm" version = "~> 2.43" } azuread = { diff --git a/landingzones.old/caf_shared_services/output.tf b/landingzones.old/caf_shared_services/output.tf index 2a9e22029..775534ced 100644 --- a/landingzones.old/caf_shared_services/output.tf +++ b/landingzones.old/caf_shared_services/output.tf @@ -1,28 +1,28 @@ -output global_settings { +output "global_settings" { value = local.global_settings sensitive = true } -output diagnostics { +output "diagnostics" { value = local.diagnostics sensitive = true } -output tfstates { +output "tfstates" { value = local.tfstates sensitive = true } -output managed_identities { +output "managed_identities" { value = local.remote.managed_identities sensitive = true } -output azuread_groups { +output "azuread_groups" { value = local.remote.azuread_groups sensitive = true } -output recovery_vaults { +output "recovery_vaults" { value = tomap({ (var.landingzone.key) = module.landingzones_shared_services.recovery_vaults }) diff --git a/landingzones.old/caf_shared_services/variables.tf b/landingzones.old/caf_shared_services/variables.tf index 32e251869..9916a4178 100644 --- a/landingzones.old/caf_shared_services/variables.tf +++ b/landingzones.old/caf_shared_services/variables.tf @@ -1,18 +1,18 @@ # Map of the remote data state for lower level -variable lower_storage_account_name {} -variable lower_container_name {} -variable lower_resource_group_name {} +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} -variable tfstate_storage_account_name {} -variable tfstate_container_name {} -variable tfstate_key {} -variable tfstate_resource_group_name {} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} -variable tfstate_subscription_id { +variable "tfstate_subscription_id" { description = "This value is propulated by the rover. subscription id hosting the remote tfstates" } -variable landingzone { +variable "landingzone" { default = { backend_type = "azurerm" level = "level2" @@ -30,42 +30,42 @@ variable landingzone { } } } -variable tenant_id {} -variable global_settings { +variable "tenant_id" {} +variable "global_settings" { default = {} } -variable rover_version {} -variable logged_user_objectId { +variable "rover_version" {} +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable tags { - type = map +variable "tags" { + type = map(any) default = {} } -variable diagnostics_definition { +variable "diagnostics_definition" { default = {} } -variable resource_groups { +variable "resource_groups" { default = {} } -variable automations { +variable "automations" { default = {} } -variable recovery_vaults { +variable "recovery_vaults" { default = {} } -variable replicated_vms { +variable "replicated_vms" { default = {} } -variable network_mappings { +variable "network_mappings" { default = {} } -variable diagnostic_storage_accounts { +variable "diagnostic_storage_accounts" { default = {} } -variable virtual_machines { +variable "virtual_machines" { default = {} } \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf index ee6af89a5..4a0225192 100644 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf +++ b/landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf @@ -1,5 +1,5 @@ -variable cluster {} +variable "cluster" {} -variable namespaces {} +variable "namespaces" {} -variable helm_charts {} \ No newline at end of file +variable "helm_charts" {} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf index 97a3e84dc..7ad77ea93 100644 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf +++ b/landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf @@ -1,36 +1,36 @@ # Map of the remote data state for lower level -variable lower_storage_account_name {} -variable lower_container_name {} -variable lower_resource_group_name {} +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} -variable tfstate_storage_account_name {} -variable tfstate_container_name {} -variable tfstate_resource_group_name {} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_resource_group_name" {} # variable tfstate_key {} -variable global_settings { +variable "global_settings" { default = {} } # variable tenant_id {} -variable landingzone {} +variable "landingzone" {} -variable namespaces {} +variable "namespaces" {} -variable tags { +variable "tags" { default = null - type = map + type = map(any) } -variable helm_charts {} +variable "helm_charts" {} -variable rover_version { +variable "rover_version" { default = null } -variable cluster_re1_key { +variable "cluster_re1_key" { default = null } -variable cluster_re2_key { +variable "cluster_re2_key" { default = null } \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/databricks/databricks.tf b/landingzones.old/caf_solutions/add-ons/databricks/databricks.tf index dcb9053ec..1c81174b7 100644 --- a/landingzones.old/caf_solutions/add-ons/databricks/databricks.tf +++ b/landingzones.old/caf_solutions/add-ons/databricks/databricks.tf @@ -9,13 +9,13 @@ provider "databricks" { # azure_tenant_id = var.tenant_id } -module databricks { +module "databricks" { source = "../../modules/databricks" settings = var.databricks } -output databricks { +output "databricks" { value = module.databricks sensitive = false } diff --git a/landingzones.old/caf_solutions/add-ons/databricks/main.tf b/landingzones.old/caf_solutions/add-ons/databricks/main.tf index 516a9e382..743b254d2 100644 --- a/landingzones.old/caf_solutions/add-ons/databricks/main.tf +++ b/landingzones.old/caf_solutions/add-ons/databricks/main.tf @@ -1,7 +1,7 @@ terraform { required_providers { azurerm = { - source = "hashicorp/azurerm" + source = "hashicorp/azurerm" version = "~> 2.48" } azurecaf = { diff --git a/landingzones.old/caf_solutions/add-ons/databricks/variables.tf b/landingzones.old/caf_solutions/add-ons/databricks/variables.tf index 1523ef38c..848b0ece0 100644 --- a/landingzones.old/caf_solutions/add-ons/databricks/variables.tf +++ b/landingzones.old/caf_solutions/add-ons/databricks/variables.tf @@ -1,115 +1,115 @@ # Map of the remote data state for lower level -variable lower_storage_account_name {} -variable lower_container_name {} -variable lower_resource_group_name {} +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} -variable tfstate_storage_account_name {} -variable tfstate_container_name {} -variable tfstate_key {} -variable tfstate_resource_group_name {} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} -variable global_settings { +variable "global_settings" { default = {} } -variable landingzone { +variable "landingzone" { default = "" } -variable environment { +variable "environment" { default = "sandpit" } -variable rover_version { +variable "rover_version" { default = null } -variable max_length { +variable "max_length" { default = 40 } -variable logged_user_objectId { +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable tags { +variable "tags" { default = null - type = map + type = map(any) } -variable app_service_environments { +variable "app_service_environments" { default = {} } -variable app_service_plans { +variable "app_service_plans" { default = {} } -variable app_services { +variable "app_services" { default = {} } -variable diagnostics_definition { +variable "diagnostics_definition" { default = null } -variable resource_groups { +variable "resource_groups" { default = null } -variable network_security_group_definition { +variable "network_security_group_definition" { default = null } -variable vnets { +variable "vnets" { default = {} } -variable azurerm_redis_caches { +variable "azurerm_redis_caches" { default = {} } -variable mssql_servers { +variable "mssql_servers" { default = {} } -variable storage_accounts { +variable "storage_accounts" { default = {} } -variable azuread_groups { +variable "azuread_groups" { default = {} } -variable keyvaults { +variable "keyvaults" { default = {} } -variable keyvault_access_policies { +variable "keyvault_access_policies" { default = {} } -variable virtual_machines { +variable "virtual_machines" { default = {} } -variable azure_container_registries { +variable "azure_container_registries" { default = {} } -variable bastion_hosts { +variable "bastion_hosts" { default = {} } -variable public_ip_addresses { +variable "public_ip_addresses" { default = {} } -variable diagnostic_storage_accounts { +variable "diagnostic_storage_accounts" { default = {} } -variable managed_identities { +variable "managed_identities" { default = {} } -variable private_dns { +variable "private_dns" { default = {} } -variable synapse_workspaces { +variable "synapse_workspaces" { default = {} } -variable azurerm_application_insights { +variable "azurerm_application_insights" { default = {} } -variable role_mapping { +variable "role_mapping" { default = {} } -variable aks_clusters { +variable "aks_clusters" { default = {} } -variable databricks_workspaces { +variable "databricks_workspaces" { default = {} } -variable databricks { +variable "databricks" { default = {} } diff --git a/landingzones.old/caf_solutions/dynamic_secrets.tf b/landingzones.old/caf_solutions/dynamic_secrets.tf index d026418de..6515cd772 100644 --- a/landingzones.old/caf_solutions/dynamic_secrets.tf +++ b/landingzones.old/caf_solutions/dynamic_secrets.tf @@ -1,4 +1,4 @@ -module dynamic_keyvault_secrets { +module "dynamic_keyvault_secrets" { source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" version = "~>5.2.0" diff --git a/landingzones.old/caf_solutions/main.tf b/landingzones.old/caf_solutions/main.tf index 141e1ce9d..7710e1318 100644 --- a/landingzones.old/caf_solutions/main.tf +++ b/landingzones.old/caf_solutions/main.tf @@ -1,7 +1,7 @@ terraform { required_providers { azurerm = { - source = "hashicorp/azurerm" + source = "hashicorp/azurerm" version = "~> 2.43" } azuread = { diff --git a/landingzones.old/caf_solutions/modules/databricks/output.tf b/landingzones.old/caf_solutions/modules/databricks/output.tf index 5a3ec0668..5ac9d541c 100644 --- a/landingzones.old/caf_solutions/modules/databricks/output.tf +++ b/landingzones.old/caf_solutions/modules/databricks/output.tf @@ -1,9 +1,9 @@ -output cluster { +output "cluster" { value = { - id = databricks_cluster.cluster.id - default_tags = databricks_cluster.cluster.default_tags - state = databricks_cluster.cluster.state + id = databricks_cluster.cluster.id + default_tags = databricks_cluster.cluster.default_tags + state = databricks_cluster.cluster.state spark_version = databricks_cluster.cluster.spark_version - + } } \ No newline at end of file diff --git a/landingzones.old/caf_solutions/modules/databricks/variables.tf b/landingzones.old/caf_solutions/modules/databricks/variables.tf index 3f8e42ce5..719f36726 100644 --- a/landingzones.old/caf_solutions/modules/databricks/variables.tf +++ b/landingzones.old/caf_solutions/modules/databricks/variables.tf @@ -1,4 +1,4 @@ -variable azure_workspace_resource_id { +variable "azure_workspace_resource_id" { default = {} } -variable settings {} \ No newline at end of file +variable "settings" {} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/output.tf b/landingzones.old/caf_solutions/output.tf index a6bc22b2b..adac00b3c 100644 --- a/landingzones.old/caf_solutions/output.tf +++ b/landingzones.old/caf_solutions/output.tf @@ -1,80 +1,80 @@ #Core outputs -output diagnostics { +output "diagnostics" { value = local.diagnostics sensitive = true } -output tfstates { +output "tfstates" { value = local.tfstates sensitive = true } -output global_settings { +output "global_settings" { value = local.global_settings sensitive = true } # ASE -output app_service_environments { +output "app_service_environments" { value = local.combined.app_service_environments sensitive = true } -output app_service_plans { +output "app_service_plans" { value = local.combined.app_service_plans sensitive = true } -output app_services { +output "app_services" { value = local.combined.app_services sensitive = true } # DB -output mssql_servers { +output "mssql_servers" { value = local.combined.mssql_servers sensitive = true } -output mssql_elastic_pools { +output "mssql_elastic_pools" { value = local.combined.mssql_elastic_pools sensitive = true } -output redis_caches { +output "redis_caches" { value = module.caf.redis_caches sensitive = true } -output managed_identities { +output "managed_identities" { value = local.combined.managed_identities sensitive = true } -output keyvaults { +output "keyvaults" { value = tomap({ (var.landingzone.key) = module.caf.keyvaults }) sensitive = true } # App Gateways -output application_gateways { +output "application_gateways" { value = local.combined.application_gateways sensitive = true } -output application_gateway_applications { +output "application_gateway_applications" { value = local.combined.application_gateway_applications sensitive = true } # DNS -output private_dns { +output "private_dns" { value = local.combined.private_dns sensitive = true } # Kubernetes related outputs -output aks_clusters_kubeconfig { +output "aks_clusters_kubeconfig" { value = { for key, aks_cluster in module.caf.aks_clusters : key => { aks_kubeconfig_cmd = aks_cluster.aks_kubeconfig_cmd @@ -84,28 +84,28 @@ output aks_clusters_kubeconfig { sensitive = false } -output aks_clusters { +output "aks_clusters" { value = tomap({ (var.landingzone.key) = module.caf.aks_clusters }) sensitive = true } -output virtual_machines { +output "virtual_machines" { value = module.caf.virtual_machines sensitive = false } # Data and AI outputs -output databricks_workspaces { +output "databricks_workspaces" { value = tomap({ (var.landingzone.key) = module.caf.databricks_workspaces }) sensitive = true } -output machine_learning_workspaces { +output "machine_learning_workspaces" { value = tomap({ (var.landingzone.key) = module.caf.machine_learning_workspaces }) sensitive = true } -output synapse_workspaces { +output "synapse_workspaces" { value = tomap({ (var.landingzone.key) = module.caf.synapse_workspaces }) sensitive = true } diff --git a/landingzones.old/caf_solutions/variables.tf b/landingzones.old/caf_solutions/variables.tf index 7d6273cb1..cfafad2d5 100644 --- a/landingzones.old/caf_solutions/variables.tf +++ b/landingzones.old/caf_solutions/variables.tf @@ -1,272 +1,272 @@ # Map of the remote data state for lower level -variable lower_storage_account_name {} -variable lower_container_name {} -variable lower_resource_group_name {} +variable "lower_storage_account_name" {} +variable "lower_container_name" {} +variable "lower_resource_group_name" {} -variable tfstate_subscription_id { +variable "tfstate_subscription_id" { description = "This value is propulated by the rover. subscription id hosting the remote tfstates" } -variable tfstate_storage_account_name {} -variable tfstate_container_name {} -variable tfstate_key {} -variable tfstate_resource_group_name {} +variable "tfstate_storage_account_name" {} +variable "tfstate_container_name" {} +variable "tfstate_key" {} +variable "tfstate_resource_group_name" {} -variable landingzone {} -variable tenant_id {} +variable "landingzone" {} +variable "tenant_id" {} -variable global_settings { +variable "global_settings" { default = {} } -variable rover_version { +variable "rover_version" { default = null } -variable logged_user_objectId { +variable "logged_user_objectId" { default = null } -variable logged_aad_app_objectId { +variable "logged_aad_app_objectId" { default = null } -variable tags { - type = map +variable "tags" { + type = map(any) default = {} } -variable resource_groups { +variable "resource_groups" { default = {} } -variable azurerm_redis_caches { +variable "azurerm_redis_caches" { default = {} } -variable mssql_servers { +variable "mssql_servers" { default = {} } -variable mssql_databases { +variable "mssql_databases" { default = {} } -variable mssql_elastic_pools { +variable "mssql_elastic_pools" { default = {} } -variable storage_accounts { +variable "storage_accounts" { default = {} } -variable azuread_groups { +variable "azuread_groups" { default = {} } -variable keyvaults { +variable "keyvaults" { default = {} } -variable keyvault_access_policies { +variable "keyvault_access_policies" { default = {} } -variable keyvault_certificates { +variable "keyvault_certificates" { default = {} } -variable managed_identities { +variable "managed_identities" { default = {} } -variable azurerm_application_insights { +variable "azurerm_application_insights" { default = {} } -variable role_mapping { +variable "role_mapping" { default = {} } -variable custom_role_definitions { +variable "custom_role_definitions" { default = {} } -variable dynamic_keyvault_secrets { +variable "dynamic_keyvault_secrets" { default = {} } -variable app_service_environments { +variable "app_service_environments" { default = {} } -variable app_service_plans { +variable "app_service_plans" { default = {} } -variable app_services { +variable "app_services" { default = {} } -variable diagnostics_definition { +variable "diagnostics_definition" { default = null } -variable network_security_group_definition { +variable "network_security_group_definition" { default = null } -variable route_tables { +variable "route_tables" { default = {} } -variable azurerm_routes { +variable "azurerm_routes" { default = {} } -variable vnets { +variable "vnets" { default = {} } -variable mssql_managed_instances { +variable "mssql_managed_instances" { default = {} } -variable mssql_managed_instances_secondary { +variable "mssql_managed_instances_secondary" { default = {} } -variable mssql_managed_databases { +variable "mssql_managed_databases" { default = {} } -variable mssql_managed_databases_restore { +variable "mssql_managed_databases_restore" { default = {} } -variable mariadb_servers { +variable "mariadb_servers" { default = {} } -variable mariadb_databases { +variable "mariadb_databases" { default = {} } -variable mssql_failover_groups { +variable "mssql_failover_groups" { default = {} } -variable mssql_mi_failover_groups { +variable "mssql_mi_failover_groups" { default = {} } -variable mssql_mi_administrators { +variable "mssql_mi_administrators" { default = {} } -variable azuread_roles { +variable "azuread_roles" { default = {} } -variable keyvault_certificate_issuers { +variable "keyvault_certificate_issuers" { default = {} } -variable keyvault_certificate_requests { +variable "keyvault_certificate_requests" { default = {} } -variable virtual_machines { +variable "virtual_machines" { default = {} } -variable bastion_hosts { +variable "bastion_hosts" { default = {} } -variable public_ip_addresses { +variable "public_ip_addresses" { default = {} } -variable diagnostic_storage_accounts { +variable "diagnostic_storage_accounts" { default = {} } -variable diagnostic_event_hub_namespaces { +variable "diagnostic_event_hub_namespaces" { default = {} } -variable diagnostic_log_analytics { +variable "diagnostic_log_analytics" { default = {} } -variable private_dns { +variable "private_dns" { default = {} } -variable synapse_workspaces { +variable "synapse_workspaces" { default = {} } -variable aks_clusters { +variable "aks_clusters" { default = {} } -variable databricks_workspaces { +variable "databricks_workspaces" { default = {} } -variable machine_learning_workspaces { +variable "machine_learning_workspaces" { default = {} } -variable monitoring { +variable "monitoring" { default = {} } -variable virtual_wans { +variable "virtual_wans" { default = {} } -variable event_hub_namespaces { +variable "event_hub_namespaces" { default = {} } -variable application_gateways { +variable "application_gateways" { default = {} } -variable application_gateway_applications { +variable "application_gateway_applications" { default = {} } -variable mysql_servers { +variable "mysql_servers" { default = {} } -variable postgresql_servers { +variable "postgresql_servers" { default = {} } -variable cosmos_db { +variable "cosmos_db" { default = {} } -variable log_analytics { +variable "log_analytics" { default = {} } -variable recovery_vaults { +variable "recovery_vaults" { default = {} } -variable availability_sets { +variable "availability_sets" { default = {} } -variable proximity_placement_groups { +variable "proximity_placement_groups" { default = {} } -variable network_watchers { +variable "network_watchers" { default = {} } -variable virtual_network_gateways { +variable "virtual_network_gateways" { default = {} } -variable virtual_network_gateway_connections { +variable "virtual_network_gateway_connections" { default = {} } -variable express_route_circuits { +variable "express_route_circuits" { default = {} } -variable express_route_circuit_authorizations { +variable "express_route_circuit_authorizations" { default = {} } -variable diagnostics_destinations { +variable "diagnostics_destinations" { default = {} } -variable vnet_peerings { +variable "vnet_peerings" { default = {} } -variable cosmos_dbs { +variable "cosmos_dbs" { default = {} } -variable front_doors { +variable "front_doors" { default = {} } -variable front_door_waf_policies { +variable "front_door_waf_policies" { default = {} } -variable dns_zones { +variable "dns_zones" { default = {} } -variable private_endpoints { +variable "private_endpoints" { default = {} } -variable local_network_gateways { +variable "local_network_gateways" { default = {} } -variable azure_container_registries { +variable "azure_container_registries" { default = {} } -variable azuread_api_permissions { +variable "azuread_api_permissions" { default = {} } -variable azuread_apps { +variable "azuread_apps" { default = {} } -variable azuread_users { +variable "azuread_users" { default = {} } -variable user_type {} -variable domain_name_registrations { +variable "user_type" {} +variable "domain_name_registrations" { default = {} } -variable dns_zone_records { +variable "dns_zone_records" { default = {} } -variable keyvault_keys { +variable "keyvault_keys" { default = {} } -variable load_balancers { +variable "load_balancers" { default = {} } \ No newline at end of file From 698b636b6ea5ec92a1d64fd9439734b6f53322d4 Mon Sep 17 00:00:00 2001 From: lolorol Date: Sat, 27 Mar 2021 10:19:03 +0000 Subject: [PATCH 08/38] Update shared services and networking --- caf_solution/landingzone.tf | 2 +- caf_solution/local.networking.tf | 9 ++++++ caf_solution/local.shared_services.tf | 14 +++++++++ caf_solution/variables.networking.tf | 24 +++++++++++++++ caf_solution/variables.shared_services.tf | 37 +++++++++++++++++++++++ caf_solution/variables.tf | 29 ------------------ 6 files changed, 85 insertions(+), 30 deletions(-) create mode 100644 caf_solution/local.shared_services.tf create mode 100644 caf_solution/variables.shared_services.tf diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf index 97aa28278..4247384ce 100644 --- a/caf_solution/landingzone.tf +++ b/caf_solution/landingzone.tf @@ -24,7 +24,7 @@ module "solution" { resource_groups = var.resource_groups role_mapping = var.role_mapping security = var.security - shared_services = var.shared_services + shared_services = local.shared_services storage_accounts = var.storage_accounts subscription_billing_role_assignments = var.subscription_billing_role_assignments subscriptions = var.subscriptions diff --git a/caf_solution/local.networking.tf b/caf_solution/local.networking.tf index 1cfa0533b..4e4edada4 100644 --- a/caf_solution/local.networking.tf +++ b/caf_solution/local.networking.tf @@ -4,6 +4,7 @@ locals { { application_gateway_applications = var.application_gateway_applications application_gateways = var.application_gateways + application_security_groups = var.application_security_groups azurerm_firewall_application_rule_collection_definition = var.azurerm_firewall_application_rule_collection_definition azurerm_firewall_nat_rule_collection_definition = var.azurerm_firewall_nat_rule_collection_definition azurerm_firewall_network_rule_collection_definition = var.azurerm_firewall_network_rule_collection_definition @@ -12,15 +13,23 @@ locals { ddos_services = var.ddos_services dns_zone_records = var.dns_zone_records dns_zones = var.dns_zones + domain_name_registrations = var.domain_name_registrations express_route_circuit_authorizations = var.express_route_circuit_authorizations express_route_circuits = var.express_route_circuits + front_door_waf_policies = var.front_door_waf_policies + front_doors = var.front_doors + ip_groups = var.ip_groups + local_network_gateways = var.local_network_gateways + networking_interface_asg_associations = var.networking_interface_asg_associations network_security_group_definition = var.network_security_group_definition + network_watchers = var.network_watchers private_dns = var.private_dns private_endpoints = var.private_endpoints public_ip_addresses = var.public_ip_addresses load_balancers = var.load_balancers route_tables = var.route_tables vhub_peerings = var.vhub_peerings + virtual_network_gateway_connections = var.virtual_network_gateway_connections virtual_network_gateways = var.virtual_network_gateways virtual_wans = var.virtual_wans vnet_peerings = var.vnet_peerings diff --git a/caf_solution/local.shared_services.tf b/caf_solution/local.shared_services.tf new file mode 100644 index 000000000..9baef5330 --- /dev/null +++ b/caf_solution/local.shared_services.tf @@ -0,0 +1,14 @@ +locals { + shared_services = merge( + var.shared_services, + { + automations = var.automations + recovery_vaults = var.recovery_vaults + monitoring = var.monitoring + shared_image_galleries = var.shared_image_galleries + image_definitions = var.image_definitions + packer_service_principal = var.packer_service_principal + packer_managed_identity = var.packer_managed_identity + } + ) +} diff --git a/caf_solution/variables.networking.tf b/caf_solution/variables.networking.tf index 3387057b5..4c44f41de 100644 --- a/caf_solution/variables.networking.tf +++ b/caf_solution/variables.networking.tf @@ -5,6 +5,9 @@ variable "application_gateways" { variable "application_gateway_applications" { default = {} } +variable "application_security_groups" { + default = {} +} variable "azurerm_firewalls" { default = {} } @@ -29,6 +32,9 @@ variable "dns_zones" { variable "dns_zone_records" { default = {} } +variable "domain_name_registrations" { + default = {} +} variable "express_route_circuits" { default = {} } @@ -45,6 +51,21 @@ variable "networking" { default = {} type = map(any) } +variable "front_door_waf_policies" { + default = {} +} +variable "front_doors" { + default = {} +} +variable "ip_groups" { + default = {} +} +variable "local_network_gateways" { + default = {} +} +variable "networking_interface_asg_associations" { + default = {} +} variable "network_security_group_definition" { default = {} } @@ -60,6 +81,9 @@ variable "public_ip_addresses" { variable "route_tables" { default = {} } +variable "virtual_network_gateway_connections" { + default = {} +} variable "virtual_network_gateways" { default = {} } diff --git a/caf_solution/variables.shared_services.tf b/caf_solution/variables.shared_services.tf new file mode 100644 index 000000000..90c1d0697 --- /dev/null +++ b/caf_solution/variables.shared_services.tf @@ -0,0 +1,37 @@ +# Shared services +variable "shared_services" { + description = "Shared services configuration objects" + default = { + # automations = {} + # monitoring = {} + # recovery_vaults = {} + } +} + +variable "automations" { + default = {} +} + +variable "image_definitions" { + default = {} +} + +variable "monitoring" { + default = {} +} + +variable "packer_service_principal" { + default = {} +} + +variable "packer_managed_identity" { + default = {} +} + +variable "recovery_vaults" { + default = {} +} + +variable "shared_image_galleries" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index fbb3bc586..d0740c509 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -234,35 +234,6 @@ variable "diagnostic_storage_accounts" { default = {} } -# Shared services -variable "shared_services" { - description = "Shared services configuration objects" - default = { - # automations = {} - # monitoring = {} - # recovery_vaults = {} - } -} - -variable "automations" { - default = {} -} - -variable "shared_image_galleries" { - default = {} -} - -variable "image_definitions" { - default = {} -} - -variable "packer_service_principal" { - default = {} -} - -variable "packer_managed_identity" { - default = {} -} variable "keyvault_certificate_issuers" { default = {} From 1f4e2daebd0aad0b4b7907851a7a097d1a8aa4ce Mon Sep 17 00:00:00 2001 From: lolorol Date: Sat, 27 Mar 2021 10:41:47 +0000 Subject: [PATCH 09/38] compute, security and storage --- caf_solution/landingzone.tf | 5 +++-- caf_solution/local.compute.tf | 14 +++++++++++++ caf_solution/local.security.tf | 12 +++++++++++ caf_solution/local.shared_services.tf | 4 ++-- caf_solution/local.storage.tf | 9 +++++++++ caf_solution/variables.compute.tf | 29 +++++++++++++++++++++++++++ caf_solution/variables.security.tf | 19 ++++++++++++++++++ caf_solution/variables.storage.tf | 13 ++++++++++++ caf_solution/variables.tf | 25 ++--------------------- 9 files changed, 103 insertions(+), 27 deletions(-) create mode 100644 caf_solution/local.compute.tf create mode 100644 caf_solution/local.security.tf create mode 100644 caf_solution/local.storage.tf create mode 100644 caf_solution/variables.compute.tf create mode 100644 caf_solution/variables.security.tf create mode 100644 caf_solution/variables.storage.tf diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf index 4247384ce..9a25b2be9 100644 --- a/caf_solution/landingzone.tf +++ b/caf_solution/landingzone.tf @@ -6,7 +6,7 @@ module "solution" { azuread_groups = var.azuread_groups azuread_roles = var.azuread_roles azuread_users = var.azuread_users - compute = var.compute + compute = local.compute current_landingzone_key = var.landingzone.key custom_role_definitions = var.custom_role_definitions database = var.database @@ -23,8 +23,9 @@ module "solution" { remote_objects = local.remote_objects resource_groups = var.resource_groups role_mapping = var.role_mapping - security = var.security + security = local.security shared_services = local.shared_services + storage = local.storage storage_accounts = var.storage_accounts subscription_billing_role_assignments = var.subscription_billing_role_assignments subscriptions = var.subscriptions diff --git a/caf_solution/local.compute.tf b/caf_solution/local.compute.tf new file mode 100644 index 000000000..f0aa3a454 --- /dev/null +++ b/caf_solution/local.compute.tf @@ -0,0 +1,14 @@ +locals { + compute = merge( + var.compute, + { + aks_clusters = var.aks_clusters + availability_sets = var.availability_sets + azure_container_registries = var.azure_container_registries + bastion_hosts = var.bastion_hosts + container_groups = var.container_groups + proximity_placement_groups = var.proximity_placement_groups + virtual_machines = var.virtual_machines + } + ) +} diff --git a/caf_solution/local.security.tf b/caf_solution/local.security.tf new file mode 100644 index 000000000..8ae7b7e2d --- /dev/null +++ b/caf_solution/local.security.tf @@ -0,0 +1,12 @@ +locals { + security = merge( + var.security, + { + disk_encryption_sets = var.disk_encryption_sets + keyvault_certificate_issuers = var.keyvault_certificate_issuers + keyvault_certificate_requests = var.keyvault_certificate_requests + keyvault_certificates = var.keyvault_certificates + keyvault_keys = var.keyvault_keys + } + ) +} diff --git a/caf_solution/local.shared_services.tf b/caf_solution/local.shared_services.tf index 9baef5330..a1aa3d091 100644 --- a/caf_solution/local.shared_services.tf +++ b/caf_solution/local.shared_services.tf @@ -2,8 +2,8 @@ locals { shared_services = merge( var.shared_services, { - automations = var.automations - recovery_vaults = var.recovery_vaults + automations = var.automations + recovery_vaults = var.recovery_vaults monitoring = var.monitoring shared_image_galleries = var.shared_image_galleries image_definitions = var.image_definitions diff --git a/caf_solution/local.storage.tf b/caf_solution/local.storage.tf new file mode 100644 index 000000000..9f1bf953f --- /dev/null +++ b/caf_solution/local.storage.tf @@ -0,0 +1,9 @@ +locals { + storage = merge( + var.storage, + { + netapp_accounts = var.netapp_accounts + storage_account_blobs = var.storage_account_blobs + } + ) +} diff --git a/caf_solution/variables.compute.tf b/caf_solution/variables.compute.tf new file mode 100644 index 000000000..fdffa3519 --- /dev/null +++ b/caf_solution/variables.compute.tf @@ -0,0 +1,29 @@ +variable "aks_clusters" { + default = {} +} +variable "availability_sets" { + default = {} +} +variable "azure_container_registries" { + default = {} +} +variable "bastion_hosts" { + default = {} +} +## Compute variables +variable "compute" { + description = "Compute configuration objects" + default = { + # virtual_machines = {} + # ... + } +} +variable "container_groups" { + default = {} +} +variable "proximity_placement_groups" { + default = {} +} +variable "virtual_machines" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/variables.security.tf b/caf_solution/variables.security.tf new file mode 100644 index 000000000..5caae44dd --- /dev/null +++ b/caf_solution/variables.security.tf @@ -0,0 +1,19 @@ +variable "disk_encryption_sets" { + default = {} +} +variable "keyvault_certificate_issuers" { + default = {} +} +variable "keyvault_certificate_requests" { + default = {} +} +variable "keyvault_certificates" { + default = {} +} +variable "keyvault_keys" { + default = {} +} +## Security variables +variable "security" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/variables.storage.tf b/caf_solution/variables.storage.tf new file mode 100644 index 000000000..8a373b8ac --- /dev/null +++ b/caf_solution/variables.storage.tf @@ -0,0 +1,13 @@ +variable "netapp_accounts" { + default = {} +} +variable "storage" { + description = "Storage configuration objects" + default = {} +} +variable "storage_account_blobs" { + default = {} +} +variable "storage_accounts" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index d0740c509..61e37f535 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -158,14 +158,6 @@ variable "azuread_api_permissions" { default = {} } -## Compute variables -variable "compute" { - description = "Compute configuration objects" - default = { - virtual_machines = {} - } -} - variable "webapp" { description = "Web applications configuration objects" default = { @@ -173,6 +165,7 @@ variable "webapp" { # app_service_environments = {} # app_service_plans = {} # azurerm_application_insights = {} + # ... } } @@ -184,10 +177,6 @@ variable "database" { } -## Security variables -variable "security" { - default = {} -} variable "managed_identities" { description = "Managed Identity configuration objects" @@ -222,22 +211,12 @@ variable "dynamic_keyvault_secrets" { default = {} } -## Storage variables -variable "storage_accounts" { - default = {} -} -variable "storage" { - description = "Storage configuration objects" - default = {} -} + variable "diagnostic_storage_accounts" { default = {} } -variable "keyvault_certificate_issuers" { - default = {} -} variable "cosmos_dbs" { default = {} } From 501268de6ebf4456126b913765865a4a1af30e7d Mon Sep 17 00:00:00 2001 From: lolorol Date: Sat, 27 Mar 2021 10:55:42 +0000 Subject: [PATCH 10/38] database --- caf_solution/landingzone.tf | 2 +- caf_solution/local.database.tf | 31 +++++++++++++ caf_solution/variables.database.tf | 72 ++++++++++++++++++++++++++++++ caf_solution/variables.tf | 3 -- 4 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 caf_solution/local.database.tf create mode 100644 caf_solution/variables.database.tf diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf index 9a25b2be9..38f345f01 100644 --- a/caf_solution/landingzone.tf +++ b/caf_solution/landingzone.tf @@ -9,7 +9,7 @@ module "solution" { compute = local.compute current_landingzone_key = var.landingzone.key custom_role_definitions = var.custom_role_definitions - database = var.database + database = local.database event_hub_namespaces = var.event_hub_namespaces global_settings = local.global_settings keyvault_access_policies = var.keyvault_access_policies diff --git a/caf_solution/local.database.tf b/caf_solution/local.database.tf new file mode 100644 index 000000000..4671bc5ba --- /dev/null +++ b/caf_solution/local.database.tf @@ -0,0 +1,31 @@ +locals { + database = merge( + var.database, + { + app_config = var.app_config + azurerm_redis_caches = var.azurerm_redis_caches + cosmos_dbs = var.cosmos_dbs + databricks_workspaces = var.databricks_workspaces + machine_learning_workspaces = var.machine_learning_workspaces + mariadb_databases = var.mariadb_databases + mariadb_servers = var.mariadb_servers + mssql_databases = var.mssql_databases + mssql_elastic_pools = var.mssql_elastic_pools + mssql_failover_groups = var.mssql_failover_groups + mssql_managed_databases = var.mssql_managed_databases + mssql_managed_databases_backup_ltr = var.mssql_managed_databases_backup_ltr + mssql_managed_databases_restore = var.mssql_managed_databases_restore + mssql_managed_instances = var.mssql_managed_instances + mssql_managed_instances_secondary = var.mssql_managed_instances_secondary + mssql_mi_administrators = var.mssql_mi_administrators + mssql_mi_failover_groups = var.mssql_mi_failover_groups + mssql_mi_secondary_tdes = var.mssql_mi_secondary_tdes + mssql_mi_tdes = var.mssql_mi_tdes + mssql_servers = var.mssql_servers + mysql_databases = var.mysql_databases + mysql_servers = var.mysql_servers + postgresql_servers = var.postgresql_servers + synapse_workspaces = var.synapse_workspaces + } + ) +} diff --git a/caf_solution/variables.database.tf b/caf_solution/variables.database.tf new file mode 100644 index 000000000..c1c7549a7 --- /dev/null +++ b/caf_solution/variables.database.tf @@ -0,0 +1,72 @@ +variable "app_config" { + default = {} +} +variable "azurerm_redis_caches" { + default = {} +} +variable "cosmos_dbs" { + default = {} +} +variable "databricks_workspaces" { + default = {} +} +variable "machine_learning_workspaces" { + default = {} +} +variable "mariadb_databases" { + default = {} +} +variable "mariadb_servers" { + default = {} +} +variable "mssql_databases" { + default = {} +} +variable "mssql_elastic_pools" { + default = {} +} +variable "mssql_failover_groups" { + default = {} +} +variable "mssql_managed_databases" { + default = {} +} +variable "mssql_managed_databases_backup_ltr" { + default = {} +} +variable "mssql_managed_databases_restore" { + default = {} +} +variable "mssql_managed_instances" { + default = {} +} +variable "mssql_managed_instances_secondary" { + default = {} +} +variable "mssql_mi_administrators" { + default = {} +} +variable "mssql_mi_failover_groups" { + default = {} +} +variable "mssql_mi_secondary_tdes" { + default = {} +} +variable "mssql_mi_tdes" { + default = {} +} +variable "mssql_servers" { + default = {} +} +variable "mysql_databases" { + default = {} +} +variable "mysql_servers" { + default = {} +} +variable "postgresql_servers" { + default = {} +} +variable "synapse_workspaces" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index 61e37f535..516c0a7dd 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -217,9 +217,6 @@ variable "diagnostic_storage_accounts" { } -variable "cosmos_dbs" { - default = {} -} variable "event_hubs" { default = {} } From d7e6b9d5a0e1607bbfcf9feb054368ee9b4e7265 Mon Sep 17 00:00:00 2001 From: lolorol Date: Sat, 27 Mar 2021 11:20:15 +0000 Subject: [PATCH 11/38] data factory, logic app, database, webapp --- caf_solution/landingzone.tf | 4 +++- caf_solution/local.data_factory.tf | 22 +++++++++++++++++++++ caf_solution/local.logic_app.tf | 15 ++++++++++++++ caf_solution/local.webapp.tf | 12 ++++++++++++ caf_solution/variables.data_factory.tf | 26 +++++++++++++++++++++++++ caf_solution/variables.database.tf | 4 ++++ caf_solution/variables.logic_app.tf | 27 ++++++++++++++++++++++++++ caf_solution/variables.tf | 20 ------------------- caf_solution/variables.webapp.tf | 26 +++++++++++++++++++++++++ 9 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 caf_solution/local.data_factory.tf create mode 100644 caf_solution/local.logic_app.tf create mode 100644 caf_solution/local.webapp.tf create mode 100644 caf_solution/variables.data_factory.tf create mode 100644 caf_solution/variables.logic_app.tf create mode 100644 caf_solution/variables.webapp.tf diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf index 38f345f01..d86f7934d 100644 --- a/caf_solution/landingzone.tf +++ b/caf_solution/landingzone.tf @@ -9,6 +9,7 @@ module "solution" { compute = local.compute current_landingzone_key = var.landingzone.key custom_role_definitions = var.custom_role_definitions + data_factory = local.data_factory database = local.database event_hub_namespaces = var.event_hub_namespaces global_settings = local.global_settings @@ -18,6 +19,7 @@ module "solution" { log_analytics = var.log_analytics logged_aad_app_objectId = var.logged_aad_app_objectId logged_user_objectId = var.logged_user_objectId + logic_app = var.logic_app managed_identities = var.managed_identities networking = local.networking remote_objects = local.remote_objects @@ -33,7 +35,7 @@ module "solution" { tenant_id = var.tenant_id tfstates = var.tfstates user_type = var.user_type - webapp = var.webapp + webapp = local.webapp diagnostics = { diagnostics_definition = local.diagnostics.diagnostics_definition diff --git a/caf_solution/local.data_factory.tf b/caf_solution/local.data_factory.tf new file mode 100644 index 000000000..557defcf3 --- /dev/null +++ b/caf_solution/local.data_factory.tf @@ -0,0 +1,22 @@ +locals { + data_factory = merge( + var.data_factory, + { + data_factory_pipeline = var.data_factory_pipeline + data_factory_trigger_schedule = var.data_factory_trigger_schedule + datasets = { + azure_blob = try(var.datasets.azure_blob, {}) + cosmosdb_sqlapi = try(var.datasets.cosmosdb_sqlapi, {}) + delimited_text = try(var.datasets.delimited_text, {}) + http = try(var.datasets.http, {}) + json = try(var.datasets.json, {}) + mysql = try(var.datasets.mysql, {}) + postgresql = try(var.datasets.postgresql, {}) + sql_server_table = try(var.datasets.sql_server_table, {}) + } + linked_services = { + azure_blob_storage = try(var.linked_services.azure_blob_storage, {}) + } + } + ) +} diff --git a/caf_solution/local.logic_app.tf b/caf_solution/local.logic_app.tf new file mode 100644 index 000000000..297cfefc1 --- /dev/null +++ b/caf_solution/local.logic_app.tf @@ -0,0 +1,15 @@ +locals { + logic_app = merge( + var.logic_app, + { + integration_service_environment = var.integration_service_environment + logic_app_action_custom = var.logic_app_action_custom + logic_app_action_http = var.logic_app_action_http + logic_app_integration_account = var.logic_app_integration_account + logic_app_trigger_custom = var.logic_app_trigger_custom + logic_app_trigger_http_request = var.logic_app_trigger_http_request + logic_app_trigger_recurrence = var.logic_app_trigger_recurrence + logic_app_workflow = var.logic_app_workflow + } + ) +} diff --git a/caf_solution/local.webapp.tf b/caf_solution/local.webapp.tf new file mode 100644 index 000000000..c69c19622 --- /dev/null +++ b/caf_solution/local.webapp.tf @@ -0,0 +1,12 @@ +locals { + webapp = merge( + var.webapp, + { + app_service_environments = var.app_service_environments + app_service_plans = var.app_service_plans + app_services = var.app_services + azurerm_application_insights = var.azurerm_application_insights + function_apps = var.function_apps + } + ) +} diff --git a/caf_solution/variables.data_factory.tf b/caf_solution/variables.data_factory.tf new file mode 100644 index 000000000..39ff7f01d --- /dev/null +++ b/caf_solution/variables.data_factory.tf @@ -0,0 +1,26 @@ +variable "data_factory" { + default = {} +} +variable "data_factory_pipeline" { + default = {} +} +variable "data_factory_trigger_schedule" { + default = {} +} +variable "datasets" { + default = { + # azure_blob + # cosmosdb_sqlapi + # delimited_text + # http + # json + # mysql + # postgresql + # sql_server_table + } +} +variable "linked_services" { + default = { + # azure_blob_storage + } +} \ No newline at end of file diff --git a/caf_solution/variables.database.tf b/caf_solution/variables.database.tf index c1c7549a7..d6b4a7ab4 100644 --- a/caf_solution/variables.database.tf +++ b/caf_solution/variables.database.tf @@ -7,6 +7,10 @@ variable "azurerm_redis_caches" { variable "cosmos_dbs" { default = {} } +variable "database" { + description = "Database configuration objects" + default = {} +} variable "databricks_workspaces" { default = {} } diff --git a/caf_solution/variables.logic_app.tf b/caf_solution/variables.logic_app.tf new file mode 100644 index 000000000..0e48766fe --- /dev/null +++ b/caf_solution/variables.logic_app.tf @@ -0,0 +1,27 @@ +variable "logic_app" { + default = {} +} +variable "integration_service_environment" { + default = {} +} +variable "logic_app_action_custom" { + default = {} +} +variable "logic_app_action_http" { + default = {} +} +variable "logic_app_integration_account" { + default = {} +} +variable "logic_app_trigger_custom" { + default = {} +} +variable "logic_app_trigger_http_request" { + default = {} +} +variable "logic_app_trigger_recurrence" { + default = {} +} +variable "logic_app_workflow" { + default = {} +} \ No newline at end of file diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index 516c0a7dd..00f6595c8 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -158,26 +158,6 @@ variable "azuread_api_permissions" { default = {} } -variable "webapp" { - description = "Web applications configuration objects" - default = { - # app_services = {} - # app_service_environments = {} - # app_service_plans = {} - # azurerm_application_insights = {} - # ... - } -} - - -## Databases variables -variable "database" { - description = "Database configuration objects" - default = {} -} - - - variable "managed_identities" { description = "Managed Identity configuration objects" default = {} diff --git a/caf_solution/variables.webapp.tf b/caf_solution/variables.webapp.tf new file mode 100644 index 000000000..68afec4d7 --- /dev/null +++ b/caf_solution/variables.webapp.tf @@ -0,0 +1,26 @@ + +variable "webapp" { + description = "Web applications configuration objects" + default = { + # app_services = {} + # app_service_environments = {} + # app_service_plans = {} + # azurerm_application_insights = {} + # ... + } +} +variable "app_service_environments" { + default = {} +} +variable "app_service_plans" { + default = {} +} +variable "app_services" { + default = {} +} +variable "azurerm_application_insights" { + default = {} +} +variable "function_apps" { + default = {} +} \ No newline at end of file From 623402250c5f20bc33be157caaf1f94d3f9dd693 Mon Sep 17 00:00:00 2001 From: lolorol Date: Mon, 29 Mar 2021 06:19:52 +0000 Subject: [PATCH 12/38] Add caf_eslz --- caf_eslz/archetype_config_overrides.tf | 44 ++++++ caf_eslz/backend.azurerm | 4 + caf_eslz/custom_landing_zones.tf | 12 ++ caf_eslz/enterprise_scale.tf | 18 +++ caf_eslz/lib/archetype_definitions/README.md | 10 ++ caf_eslz/lib/policy_assignments/README.md | 10 ++ caf_eslz/lib/policy_definitions/README.md | 10 ++ caf_eslz/lib/policy_set_definitions/README.md | 10 ++ caf_eslz/lib/role_definitions/README.md | 11 ++ caf_eslz/locals.remote_tfstates.tf | 51 ++++++ caf_eslz/main.tf | 18 +++ caf_eslz/variables.tf | 147 ++++++++++++++++++ 12 files changed, 345 insertions(+) create mode 100644 caf_eslz/archetype_config_overrides.tf create mode 100644 caf_eslz/backend.azurerm create mode 100644 caf_eslz/custom_landing_zones.tf create mode 100644 caf_eslz/enterprise_scale.tf create mode 100644 caf_eslz/lib/archetype_definitions/README.md create mode 100644 caf_eslz/lib/policy_assignments/README.md create mode 100644 caf_eslz/lib/policy_definitions/README.md create mode 100644 caf_eslz/lib/policy_set_definitions/README.md create mode 100644 caf_eslz/lib/role_definitions/README.md create mode 100644 caf_eslz/locals.remote_tfstates.tf create mode 100644 caf_eslz/main.tf create mode 100644 caf_eslz/variables.tf diff --git a/caf_eslz/archetype_config_overrides.tf b/caf_eslz/archetype_config_overrides.tf new file mode 100644 index 000000000..b8d1b6360 --- /dev/null +++ b/caf_eslz/archetype_config_overrides.tf @@ -0,0 +1,44 @@ +locals { + + archetype_config_overrides = { + for mg_id , mg_value in try(var.archetype_config_overrides, {}) : mg_id => { + archetype_id = mg_value.archetype_id + access_control = try(mg_value.access_control, {}) + parameters = { + for param_key, param_value in try(mg_value.parameters, {}) : param_key => { + for key, value in param_value : key => try(local.caf[value.output_key][value.lz_key][value.resource_type][value.resource_key][value.attribute_key], value) + } + } + } + } + +} + +## Process the following variable + +# archetype_config_overrides = { + +# root = { // var.root_id +# archetype_id = "es_root" +# parameters = { +# "Deploy-Resource-Diag" = { +# "logAnalytics" = { +# # value = "resource_id" +# lz_key = "caf_foundations_sharedservices" +# output_key = "diagnostics" +# resource_type = "log_analytics" +# resource_key = "eus_logs_ss" +# attribute_key = "id" +# } +# } +# } +# access_control = {} +# } //root + +# # decommissioned = {} +# # sandboxes = {} +# # landing-zones = {} +# # platform = {} +# # connectivity = {} +# # management = {} +# } \ No newline at end of file diff --git a/caf_eslz/backend.azurerm b/caf_eslz/backend.azurerm new file mode 100644 index 000000000..5d026b233 --- /dev/null +++ b/caf_eslz/backend.azurerm @@ -0,0 +1,4 @@ +terraform { + backend "azurerm" { + } +} \ No newline at end of file diff --git a/caf_eslz/custom_landing_zones.tf b/caf_eslz/custom_landing_zones.tf new file mode 100644 index 000000000..6b2b1a714 --- /dev/null +++ b/caf_eslz/custom_landing_zones.tf @@ -0,0 +1,12 @@ +locals { + + custom_landing_zones = { + for lz_key, lz_value in var.custom_landing_zones : lz_key => { + display_name = lz_value.display_name + parent_management_group_id = lz_value.parent_management_group_id + subscription_ids = lz_value.subscription_ids + archetype_config = lz_value.archetype_config + } + } + +} \ No newline at end of file diff --git a/caf_eslz/enterprise_scale.tf b/caf_eslz/enterprise_scale.tf new file mode 100644 index 000000000..1e3972eff --- /dev/null +++ b/caf_eslz/enterprise_scale.tf @@ -0,0 +1,18 @@ +# For full description on enterprise_scale module usage, please refer to https://github.com/Azure/terraform-azurerm-caf-enterprise-scale + +module "enterprise_scale" { + source = "Azure/caf-enterprise-scale/azurerm" + version = "~> 0.1.0" + + root_parent_id = data.azurerm_client_config.current.tenant_id + default_location = local.global_settings.regions[local.global_settings.default_region] + + #path to the policies definition and assignment repo + library_path = var.library_path + archetype_config_overrides = local.archetype_config_overrides + custom_landing_zones = local.custom_landing_zones + deploy_core_landing_zones = var.deploy_core_landing_zones + root_id = var.root_id + root_name = var.root_name + subscription_id_overrides = var.subscription_id_overrides +} \ No newline at end of file diff --git a/caf_eslz/lib/archetype_definitions/README.md b/caf_eslz/lib/archetype_definitions/README.md new file mode 100644 index 000000000..cb8923540 --- /dev/null +++ b/caf_eslz/lib/archetype_definitions/README.md @@ -0,0 +1,10 @@ + +# Public documentation of the custom landingzones + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BUser-Guide%5D-Archetype-Definitions + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BExamples%5D-Deploy-Custom-Landing-Zone-Archetypes + +# List of the default archetypes + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/tree/main/modules/archetypes/lib/archetype_definitions diff --git a/caf_eslz/lib/policy_assignments/README.md b/caf_eslz/lib/policy_assignments/README.md new file mode 100644 index 000000000..def2a5a6d --- /dev/null +++ b/caf_eslz/lib/policy_assignments/README.md @@ -0,0 +1,10 @@ + +# Public documentation of the custom landingzones + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BUser-Guide%5D-Archetype-Definitions + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BExamples%5D-Deploy-Custom-Landing-Zone-Archetypes + +# List of the default policy assignments + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/tree/main/modules/archetypes/lib/policy_assignments diff --git a/caf_eslz/lib/policy_definitions/README.md b/caf_eslz/lib/policy_definitions/README.md new file mode 100644 index 000000000..e47f922fd --- /dev/null +++ b/caf_eslz/lib/policy_definitions/README.md @@ -0,0 +1,10 @@ + +# Public documentation of the custom landingzones + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BUser-Guide%5D-Archetype-Definitions + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BExamples%5D-Deploy-Custom-Landing-Zone-Archetypes + +# List of the default policy definitions + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/tree/main/modules/archetypes/lib/policy_definitions diff --git a/caf_eslz/lib/policy_set_definitions/README.md b/caf_eslz/lib/policy_set_definitions/README.md new file mode 100644 index 000000000..c09d2c016 --- /dev/null +++ b/caf_eslz/lib/policy_set_definitions/README.md @@ -0,0 +1,10 @@ + +# Public documentation of the custom landingzones + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BUser-Guide%5D-Archetype-Definitions + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BExamples%5D-Deploy-Custom-Landing-Zone-Archetypes + +# List of the default policy set definitions + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/tree/main/modules/archetypes/lib/policy_set_definitions diff --git a/caf_eslz/lib/role_definitions/README.md b/caf_eslz/lib/role_definitions/README.md new file mode 100644 index 000000000..2230928aa --- /dev/null +++ b/caf_eslz/lib/role_definitions/README.md @@ -0,0 +1,11 @@ + +# Public documentation of the custom landingzones + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BUser-Guide%5D-Archetype-Definitions + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/wiki/%5BExamples%5D-Deploy-Custom-Landing-Zone-Archetypes + + +# List of the default role defitions + +https://github.com/Azure/terraform-azurerm-caf-enterprise-scale/tree/main/modules/archetypes/lib/role_definitions diff --git a/caf_eslz/locals.remote_tfstates.tf b/caf_eslz/locals.remote_tfstates.tf new file mode 100644 index 000000000..6a6ae17a0 --- /dev/null +++ b/caf_eslz/locals.remote_tfstates.tf @@ -0,0 +1,51 @@ +locals { + landingzone = { + current = { + storage_account_name = var.tfstate_storage_account_name + container_name = var.tfstate_container_name + resource_group_name = var.tfstate_resource_group_name + } + lower = { + storage_account_name = var.lower_storage_account_name + container_name = var.lower_container_name + resource_group_name = var.lower_resource_group_name + } + } +} + +data "terraform_remote_state" "remote" { + for_each = try(var.landingzone.tfstates, {}) + + backend = var.landingzone.backend_type + config = { + storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name + container_name = local.landingzone[try(each.value.level, "current")].container_name + resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name + subscription_id = var.tfstate_subscription_id + key = each.value.tfstate + } +} + +locals { + landingzone_tag = { + "landingzone" = var.landingzone.key + } + + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics + + caf = { + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + + global_settings = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].global_settings, {})) + } + diagnostics = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].diagnostics, {})) + } + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) + } + } + +} diff --git a/caf_eslz/main.tf b/caf_eslz/main.tf new file mode 100644 index 000000000..9f0c7006e --- /dev/null +++ b/caf_eslz/main.tf @@ -0,0 +1,18 @@ + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.52.0" + } + } + required_version = ">= 0.13" +} + + +provider "azurerm" { + features {} +} + +data "azurerm_client_config" "current" {} + diff --git a/caf_eslz/variables.tf b/caf_eslz/variables.tf new file mode 100644 index 000000000..ff8b9d834 --- /dev/null +++ b/caf_eslz/variables.tf @@ -0,0 +1,147 @@ + +variable "landing_zones_variables" { + default = {} +} +# Map of the remote data state +variable "lower_storage_account_name" { + description = "This value is propulated by the rover" +} +variable "lower_container_name" { + description = "This value is propulated by the rover" +} +variable "lower_resource_group_name" { + description = "This value is propulated by the rover" +} + +variable "tfstate_subscription_id" { + description = "This value is propulated by the rover. subscription id hosting the remote tfstates" +} +variable "tfstate_storage_account_name" { + description = "This value is propulated by the rover" +} +variable "tfstate_container_name" { + description = "This value is propulated by the rover" +} +variable "tfstate_resource_group_name" { + description = "This value is propulated by the rover" +} + +variable "diagnostics_definition" { + default = {} +} + +variable "landingzone" { + default = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "enterprise_scale" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } + } +} + + +variable "user_type" {} +variable "tenant_id" {} +variable "rover_version" {} +variable "logged_user_objectId" { + default = null +} +variable "tags" { + type = map(any) + default = {} +} + + +variable "root_id" { + type = string + description = "If specified, will set a custom Name (ID) value for the Enterprise-scale \"root\" Management Group, and append this to the ID for all core Enterprise-scale Management Groups." + default = "es" + + validation { + condition = can(regex("^[a-zA-Z0-9-]{2,10}$", var.root_id)) + error_message = "The root_id value must be between 2 to 10 characters long and can only contain alphanumeric characters and hyphens." + } +} + +variable "root_name" { + type = string + description = "If specified, will set a custom Display Name value for the Enterprise-scale \"root\" Management Group." + default = "Enterprise-Scale" + + validation { + condition = can(regex("^[A-Za-z][A-Za-z0-9- ._]{1,22}[A-Za-z0-9]?$", var.root_name)) + error_message = "The root_name value must be between 2 to 24 characters long, start with a letter, end with a letter or number, and can only contain space, hyphen, underscore or period characters." + } +} + +variable "deploy_core_landing_zones" { + type = bool + description = "If set to true, will include the core Enterprise-scale Management Group hierarchy." + default = false +} + +variable "archetype_config_overrides" { + type = map(any) + description = "If specified, will set custom Archetype configurations to the default Enterprise-scale Management Groups." + default = {} +} + +variable "subscription_id_overrides" { + type = map(list(string)) + description = "If specified, will be used to assign subscription_ids to the default Enterprise-scale Management Groups." + default = {} +} + +variable "deploy_demo_landing_zones" { + type = bool + description = "If set to true, will include the demo \"Landing Zone\" Management Groups." + default = false +} + +variable "custom_landing_zones" { + type = map( + object({ + display_name = string + parent_management_group_id = string + subscription_ids = list(string) + archetype_config = object({ + archetype_id = string + parameters = any + access_control = any + }) + }) + ) + description = "If specified, will deploy additional Management Groups alongside Enterprise-scale core Management Groups." + default = {} + + validation { + condition = can(regex("^[a-z0-9-]{2,36}$", keys(var.custom_landing_zones)[0])) || length(keys(var.custom_landing_zones)) == 0 + error_message = "The custom_landing_zones keys must be between 2 to 36 characters long and can only contain lowercase letters, numbers and hyphens." + } +} + +variable "library_path" { + type = string + description = "If specified, sets the path to a custom library folder for archetype artefacts." + default = "" +} + +variable "template_file_variables" { + type = map(any) + description = "If specified, provides the ability to define custom template variables used when reading in template files from the built-in and custom library_path." + default = {} +} + +variable "default_location" { + type = string + description = "If specified, will use set the default location used for resource deployments where needed." + default = "eastus" + + # Need to add validation covering all Azure locations +} From ddc80c3ea3c2f3ec029ae132fb2dc85a666af743 Mon Sep 17 00:00:00 2001 From: lolorol Date: Mon, 29 Mar 2021 12:43:17 +0000 Subject: [PATCH 13/38] Add CAF managed_identities in accesscontrol --- .gitignore | 2 +- caf_eslz/archetype_config_overrides.tf | 58 ++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 4c2a5948b..27e8f9be5 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ **/*.log **/backend.azurerm.tf public -**/*.lock.* \ No newline at end of file +**/.terraform.lock.hcl \ No newline at end of file diff --git a/caf_eslz/archetype_config_overrides.tf b/caf_eslz/archetype_config_overrides.tf index b8d1b6360..c2a4b65c9 100644 --- a/caf_eslz/archetype_config_overrides.tf +++ b/caf_eslz/archetype_config_overrides.tf @@ -1,19 +1,58 @@ locals { - archetype_config_overrides = { - for mg_id , mg_value in try(var.archetype_config_overrides, {}) : mg_id => { + archetype_config_overrides = { + for mg_id , mg_value in try(var.archetype_config_overrides, {}) : mg_id => { + archetype_id = mg_value.archetype_id - access_control = try(mg_value.access_control, {}) + + access_control = { + for mapping in + flatten( + [ + for role, roles in try(mg_value.access_control, {}) : { + role = role + ids = coalescelist( + flatten( + [ + for resource_type, value in roles : [ + for resource_key in try(value.resource_keys, []) : [ + local.caf[resource_type][value.lz_key][resource_key][value.attribute_key] + ] + ] + ] + ) //flatten + , + flatten( + [ + for resource_type, value in roles : [ + for principal_id in try(value.principal_ids, []) : [ + principal_id + ] + ] + ] + ) //flatten + ) //coalescelist (ids) + } + ] + ) : mapping.role => mapping.ids + } + parameters = { for param_key, param_value in try(mg_value.parameters, {}) : param_key => { for key, value in param_value : key => try(local.caf[value.output_key][value.lz_key][value.resource_type][value.resource_key][value.attribute_key], value) } + } } } } +# output caf { +# value = local.caf +# } + + ## Process the following variable # archetype_config_overrides = { @@ -32,7 +71,18 @@ locals { # } # } # } -# access_control = {} +# access_control = { +# "Contributor" = { +# "managed_identities" = { +# # principal_ids = ["principal_id1", "principal_id2"] +# lz_key = "launchpad" +# attribute_key = "principal_id" +# resource_keys = [ +# "level1" +# ] +# } +# } +# } # } //root # # decommissioned = {} From 060ce72a59c873cca93075df17ded3fca9894c00 Mon Sep 17 00:00:00 2001 From: lolorol Date: Mon, 29 Mar 2021 15:19:26 +0000 Subject: [PATCH 14/38] Move eslz under caf_solution add-ons --- caf_eslz/backend.azurerm | 4 - caf_eslz/locals.remote_tfstates.tf | 51 ---- caf_eslz/main.tf | 18 -- caf_eslz/variables.tf | 147 --------- caf_solution/add-ons/caf_eslz/README.md | 44 --- .../caf_eslz}/archetype_config_overrides.tf | 2 +- .../add-ons/caf_eslz}/custom_landing_zones.tf | 0 .../add-ons/caf_eslz}/enterprise_scale.tf | 0 caf_solution/add-ons/caf_eslz/es_main.tf | 25 -- .../lib/archetype_definitions/README.md | 0 .../lib/policy_assignments/README.md | 0 .../lib/policy_definitions/README.md | 0 .../lib/policy_set_definitions/README.md | 0 .../caf_eslz}/lib/role_definitions/README.md | 0 .../caf_eslz/locals.remote_tfstates.tf | 21 +- caf_solution/add-ons/caf_eslz/main.tf | 16 +- caf_solution/add-ons/caf_eslz/output.tf | 0 .../100/enterprise_scale_contoso_com.tfvars | 25 -- .../200/enterprise_scale_contoso_com.tfvars | 45 --- ...chetype_definition_es_management.tmpl.json | 12 - .../200/lib/archetype_definition_es_root.json | 13 - ...nt_es_allowed_resource-locations.tmpl.json | 28 -- ..._allowed_resourcegroup-locations.tmpl.json | 28 -- ...licy_assignment_es_deploy_asc_ce.tmpl.json | 28 -- ...ignment_es_deploy_asc_monitoring.tmpl.json | 88 ------ ...ssignment_es_deploy_asc_standard.tmpl.json | 21 -- ...nment_es_deploy_diag_activitylog.tmpl.json | 25 -- ...ment_es_deploy_diag_loganalytics.tmpl.json | 25 -- ...icy_definition_es_deploy_asc_standard.json | 284 ------------------ .../contoso/archetype_config_overrides.tfvars | 77 +++++ .../contoso/custom_landing_zones.tfvars | 47 +++ .../scenario/contoso/enterprise_scale.tfvars | 4 + .../scenario/contoso/landingzone.tfvars | 19 ++ .../contoso/subscription_id_overrides.tfvars | 10 + caf_solution/add-ons/caf_eslz/variables.tf | 28 +- 35 files changed, 199 insertions(+), 936 deletions(-) delete mode 100644 caf_eslz/backend.azurerm delete mode 100644 caf_eslz/locals.remote_tfstates.tf delete mode 100644 caf_eslz/main.tf delete mode 100644 caf_eslz/variables.tf delete mode 100644 caf_solution/add-ons/caf_eslz/README.md rename {caf_eslz => caf_solution/add-ons/caf_eslz}/archetype_config_overrides.tf (92%) rename {caf_eslz => caf_solution/add-ons/caf_eslz}/custom_landing_zones.tf (100%) rename {caf_eslz => caf_solution/add-ons/caf_eslz}/enterprise_scale.tf (100%) delete mode 100644 caf_solution/add-ons/caf_eslz/es_main.tf rename {caf_eslz => caf_solution/add-ons/caf_eslz}/lib/archetype_definitions/README.md (100%) rename {caf_eslz => caf_solution/add-ons/caf_eslz}/lib/policy_assignments/README.md (100%) rename {caf_eslz => caf_solution/add-ons/caf_eslz}/lib/policy_definitions/README.md (100%) rename {caf_eslz => caf_solution/add-ons/caf_eslz}/lib/policy_set_definitions/README.md (100%) rename {caf_eslz => caf_solution/add-ons/caf_eslz}/lib/role_definitions/README.md (100%) delete mode 100644 caf_solution/add-ons/caf_eslz/output.tf delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json delete mode 100644 caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json create mode 100644 caf_solution/add-ons/caf_eslz/scenario/contoso/archetype_config_overrides.tfvars create mode 100644 caf_solution/add-ons/caf_eslz/scenario/contoso/custom_landing_zones.tfvars create mode 100644 caf_solution/add-ons/caf_eslz/scenario/contoso/enterprise_scale.tfvars create mode 100644 caf_solution/add-ons/caf_eslz/scenario/contoso/landingzone.tfvars create mode 100644 caf_solution/add-ons/caf_eslz/scenario/contoso/subscription_id_overrides.tfvars diff --git a/caf_eslz/backend.azurerm b/caf_eslz/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/caf_eslz/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/caf_eslz/locals.remote_tfstates.tf b/caf_eslz/locals.remote_tfstates.tf deleted file mode 100644 index 6a6ae17a0..000000000 --- a/caf_eslz/locals.remote_tfstates.tf +++ /dev/null @@ -1,51 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings - diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics - - caf = { - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].global_settings, {})) - } - diagnostics = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].diagnostics, {})) - } - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) - } - } - -} diff --git a/caf_eslz/main.tf b/caf_eslz/main.tf deleted file mode 100644 index 9f0c7006e..000000000 --- a/caf_eslz/main.tf +++ /dev/null @@ -1,18 +0,0 @@ - -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.52.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features {} -} - -data "azurerm_client_config" "current" {} - diff --git a/caf_eslz/variables.tf b/caf_eslz/variables.tf deleted file mode 100644 index ff8b9d834..000000000 --- a/caf_eslz/variables.tf +++ /dev/null @@ -1,147 +0,0 @@ - -variable "landing_zones_variables" { - default = {} -} -# Map of the remote data state -variable "lower_storage_account_name" { - description = "This value is propulated by the rover" -} -variable "lower_container_name" { - description = "This value is propulated by the rover" -} -variable "lower_resource_group_name" { - description = "This value is propulated by the rover" -} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} -variable "tfstate_storage_account_name" { - description = "This value is propulated by the rover" -} -variable "tfstate_container_name" { - description = "This value is propulated by the rover" -} -variable "tfstate_resource_group_name" { - description = "This value is propulated by the rover" -} - -variable "diagnostics_definition" { - default = {} -} - -variable "landingzone" { - default = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "enterprise_scale" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } - } -} - - -variable "user_type" {} -variable "tenant_id" {} -variable "rover_version" {} -variable "logged_user_objectId" { - default = null -} -variable "tags" { - type = map(any) - default = {} -} - - -variable "root_id" { - type = string - description = "If specified, will set a custom Name (ID) value for the Enterprise-scale \"root\" Management Group, and append this to the ID for all core Enterprise-scale Management Groups." - default = "es" - - validation { - condition = can(regex("^[a-zA-Z0-9-]{2,10}$", var.root_id)) - error_message = "The root_id value must be between 2 to 10 characters long and can only contain alphanumeric characters and hyphens." - } -} - -variable "root_name" { - type = string - description = "If specified, will set a custom Display Name value for the Enterprise-scale \"root\" Management Group." - default = "Enterprise-Scale" - - validation { - condition = can(regex("^[A-Za-z][A-Za-z0-9- ._]{1,22}[A-Za-z0-9]?$", var.root_name)) - error_message = "The root_name value must be between 2 to 24 characters long, start with a letter, end with a letter or number, and can only contain space, hyphen, underscore or period characters." - } -} - -variable "deploy_core_landing_zones" { - type = bool - description = "If set to true, will include the core Enterprise-scale Management Group hierarchy." - default = false -} - -variable "archetype_config_overrides" { - type = map(any) - description = "If specified, will set custom Archetype configurations to the default Enterprise-scale Management Groups." - default = {} -} - -variable "subscription_id_overrides" { - type = map(list(string)) - description = "If specified, will be used to assign subscription_ids to the default Enterprise-scale Management Groups." - default = {} -} - -variable "deploy_demo_landing_zones" { - type = bool - description = "If set to true, will include the demo \"Landing Zone\" Management Groups." - default = false -} - -variable "custom_landing_zones" { - type = map( - object({ - display_name = string - parent_management_group_id = string - subscription_ids = list(string) - archetype_config = object({ - archetype_id = string - parameters = any - access_control = any - }) - }) - ) - description = "If specified, will deploy additional Management Groups alongside Enterprise-scale core Management Groups." - default = {} - - validation { - condition = can(regex("^[a-z0-9-]{2,36}$", keys(var.custom_landing_zones)[0])) || length(keys(var.custom_landing_zones)) == 0 - error_message = "The custom_landing_zones keys must be between 2 to 36 characters long and can only contain lowercase letters, numbers and hyphens." - } -} - -variable "library_path" { - type = string - description = "If specified, sets the path to a custom library folder for archetype artefacts." - default = "" -} - -variable "template_file_variables" { - type = map(any) - description = "If specified, provides the ability to define custom template variables used when reading in template files from the built-in and custom library_path." - default = {} -} - -variable "default_location" { - type = string - description = "If specified, will use set the default location used for resource deployments where needed." - default = "eastus" - - # Need to add validation covering all Azure locations -} diff --git a/caf_solution/add-ons/caf_eslz/README.md b/caf_solution/add-ons/caf_eslz/README.md deleted file mode 100644 index afef4f046..000000000 --- a/caf_solution/add-ons/caf_eslz/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Enterprise-Scale - -The foundations landing zone allows you to manage the core components of an environment: - -* Management groups -* Policies - -Foundations landing zone operates at **level 1**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -
- -## Components - -CAF eslz leverages the enterprise-scale module in order to deploy its core components. - -For full description on enterprise_scale module usage, please [refer to the repository](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale) - -This is currently work in progress. -Use the following configuration file in order to get started with the enterprise-scale module integration: - -```bash -# This example will setup the complete enterprise-scale fundamentals management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription - -rover -lz /tf/caf/public/landingzones/caf_eslz \ - -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/100 \ - -level level1 \ - -a [plan|apply|destroy] - -# This example will setup custom enterprise-scale management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription - -rover -lz /tf/caf/public/landingzones/caf_eslz \ - -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/200 \ - -level level1 \ - -a [plan|apply|destroy] - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/public/landingzones/caf_eslz \ - -tfstate_subscription_id \ - -var-folder /tf/caf/public/landingzones/caf_foundations/scenario/200 \ - -level level1 \ - -a apply -``` diff --git a/caf_eslz/archetype_config_overrides.tf b/caf_solution/add-ons/caf_eslz/archetype_config_overrides.tf similarity index 92% rename from caf_eslz/archetype_config_overrides.tf rename to caf_solution/add-ons/caf_eslz/archetype_config_overrides.tf index c2a4b65c9..583ead684 100644 --- a/caf_eslz/archetype_config_overrides.tf +++ b/caf_solution/add-ons/caf_eslz/archetype_config_overrides.tf @@ -39,7 +39,7 @@ locals { parameters = { for param_key, param_value in try(mg_value.parameters, {}) : param_key => { - for key, value in param_value : key => try(local.caf[value.output_key][value.lz_key][value.resource_type][value.resource_key][value.attribute_key], value) + for key, value in param_value : key => jsonencode(try(local.caf[value.output_key][value.lz_key][value.resource_type][value.resource_key][value.attribute_key], value.value)) } } diff --git a/caf_eslz/custom_landing_zones.tf b/caf_solution/add-ons/caf_eslz/custom_landing_zones.tf similarity index 100% rename from caf_eslz/custom_landing_zones.tf rename to caf_solution/add-ons/caf_eslz/custom_landing_zones.tf diff --git a/caf_eslz/enterprise_scale.tf b/caf_solution/add-ons/caf_eslz/enterprise_scale.tf similarity index 100% rename from caf_eslz/enterprise_scale.tf rename to caf_solution/add-ons/caf_eslz/enterprise_scale.tf diff --git a/caf_solution/add-ons/caf_eslz/es_main.tf b/caf_solution/add-ons/caf_eslz/es_main.tf deleted file mode 100644 index a2dff70a0..000000000 --- a/caf_solution/add-ons/caf_eslz/es_main.tf +++ /dev/null @@ -1,25 +0,0 @@ -# For full description on enterprise_scale module usage, please refer to https://github.com/Azure/terraform-azurerm-caf-enterprise-scale - -module "enterprise_scale" { - source = "Azure/caf-enterprise-scale/azurerm" - version = "0.0.8" - - root_parent_id = data.azurerm_client_config.current.tenant_id - - root_id = var.root_id - root_name = var.root_name - deploy_core_landing_zones = var.deploy_core_landing_zones - - # Control whether to deploy the demo landing zones // default = false - deploy_demo_landing_zones = var.deploy_demo_landing_zones - - # Set a path for the custom archetype library path - library_path = try(format("%s", var.library_path), "") - - # Deploys the custom landing zone configuration as defined in config file - custom_landing_zones = var.custom_landing_zones - subscription_id_overrides = var.subscription_id_overrides - archetype_config_overrides = var.archetype_config_overrides - - default_location = local.global_settings.regions[local.global_settings.default_region] -} \ No newline at end of file diff --git a/caf_eslz/lib/archetype_definitions/README.md b/caf_solution/add-ons/caf_eslz/lib/archetype_definitions/README.md similarity index 100% rename from caf_eslz/lib/archetype_definitions/README.md rename to caf_solution/add-ons/caf_eslz/lib/archetype_definitions/README.md diff --git a/caf_eslz/lib/policy_assignments/README.md b/caf_solution/add-ons/caf_eslz/lib/policy_assignments/README.md similarity index 100% rename from caf_eslz/lib/policy_assignments/README.md rename to caf_solution/add-ons/caf_eslz/lib/policy_assignments/README.md diff --git a/caf_eslz/lib/policy_definitions/README.md b/caf_solution/add-ons/caf_eslz/lib/policy_definitions/README.md similarity index 100% rename from caf_eslz/lib/policy_definitions/README.md rename to caf_solution/add-ons/caf_eslz/lib/policy_definitions/README.md diff --git a/caf_eslz/lib/policy_set_definitions/README.md b/caf_solution/add-ons/caf_eslz/lib/policy_set_definitions/README.md similarity index 100% rename from caf_eslz/lib/policy_set_definitions/README.md rename to caf_solution/add-ons/caf_eslz/lib/policy_set_definitions/README.md diff --git a/caf_eslz/lib/role_definitions/README.md b/caf_solution/add-ons/caf_eslz/lib/role_definitions/README.md similarity index 100% rename from caf_eslz/lib/role_definitions/README.md rename to caf_solution/add-ons/caf_eslz/lib/role_definitions/README.md diff --git a/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf b/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf index ee887a2d1..6a6ae17a0 100644 --- a/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf +++ b/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf @@ -31,16 +31,21 @@ locals { "landingzone" = var.landingzone.key } - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings + caf = { + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - diagnostics = { - diagnostics_definition = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.event_hub_namespaces + global_settings = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].global_settings, {})) + } + diagnostics = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].diagnostics, {})) + } + managed_identities = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) + } } } diff --git a/caf_solution/add-ons/caf_eslz/main.tf b/caf_solution/add-ons/caf_eslz/main.tf index 9dbcda3db..9f0c7006e 100644 --- a/caf_solution/add-ons/caf_eslz/main.tf +++ b/caf_solution/add-ons/caf_eslz/main.tf @@ -1,18 +1,18 @@ -terraform { +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.52.0" + } + } required_version = ">= 0.13" } provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } + features {} } data "azurerm_client_config" "current" {} -data "azurerm_subscription" "current" {} - diff --git a/caf_solution/add-ons/caf_eslz/output.tf b/caf_solution/add-ons/caf_eslz/output.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars b/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars deleted file mode 100644 index 89e2ea1fd..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars +++ /dev/null @@ -1,25 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "caf_eslz" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } -} - -enterprise_scale = { - # Define a custom ID to use for the root Management Group - # Also used as a prefix for all core Management Group IDs - # root_id = "caf" - # root_name = "CAF-RootManagementGroup" - - # Control whether to deploy the default core landing zones // default = true - deploy_core_landing_zones = true - - # Control whether to deploy the demo landing zones // default = false - deploy_demo_landing_zones = false -} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars b/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars deleted file mode 100644 index 73c92cb7f..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars +++ /dev/null @@ -1,45 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "caf_foundations" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } -} - -enterprise_scale = { - #path to the policies definition and assignment repo - library_path = "/tf/caf/public/landingzones/caf_eslz/scenario/200/lib" - - #management groups hierarchy configuration - custom_landing_zones = { - caf = { - display_name = "CAF-RootManagementGroup" - parent_management_group_id = "" - subscription_ids = [] - archetype_config = { - archetype_id = "es_root" - parameters = {} - access_control = {} - } - } - child-caf = { - display_name = "CAF-ChildManagementGroup" - parent_management_group_id = "caf" - subscription_ids = [] - archetype_config = { - archetype_id = "es_management" - parameters = { - ES-Deploy-ForwardDiagLog = { - logAnalytics = "central_logs_region1" - } - } - access_control = {} - } - } - } -} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json deleted file mode 100644 index e6d18b5db..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "es_management": { - "policy_assignments": [ - "ES-Deploy-ASC-Standard" - ], - "policy_definitions": [ - ], - "policy_set_definitions": [], - "role_assignments": [], - "role_definitions": [] - } -} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json deleted file mode 100644 index e41b04f6f..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/archetype_definition_es_root.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "es_root": { - "policy_assignments": [ - "ES-Deploy-ASC-Standard" - ], - "policy_definitions": [ - "ES-Deploy-ASC-Standard" - ], - "policy_set_definitions": [], - "role_assignments": [], - "role_definitions": [] - } -} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json deleted file mode 100644 index ae28ea455..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "ES-Allowed-Locations", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Specifies the allowed locations (regions) where resources can be deployed", - "displayName": "ES-Allowed-Resource-Locations", - "notScopes": [], - "parameters": { - "listOfAllowedLocations": { - "value": [ - "uksouth", - "ukwest" - ] - } - }, - "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "None" - } -} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json deleted file mode 100644 index b00174588..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "ES-Allowed-RSG-Locations", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Specifies the allowed locations (regions) where Resource Groups can be deployed", - "displayName": "ES-Allowed-ResourceGroup-Locations", - "notScopes": [], - "parameters": { - "listOfAllowedLocations": { - "value": [ - "uksouth", - "ukwest" - ] - } - }, - "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "None" - } -} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json deleted file mode 100644 index 4417b6a01..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "ES-Deploy-ASC-ContExport", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Deploy ASC Continuous Export To Log Analytics Workspace.", - "displayName": "ES-Deploy-ASC-ContinuousExportToWorkspace", - "notScopes": [], - "parameters": { - "resourceGroupLocation": { - "value": null - }, - "workspaceResourceId": { - "value": null - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-ContinuousExportToWorkspace", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json deleted file mode 100644 index ba6d2186f..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "name": "ES-Deploy-ASC-Monitoring", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Enable Monitoring in Azure Security Center.", - "displayName": "ES-Deploy-ASC-Monitoring", - "notScopes": [], - "parameters": { - "aadAuthenticationInSqlServerMonitoringEffect": { - "value": "Disabled" - }, - "diskEncryptionMonitoringEffect": { - "value": "Disabled" - }, - "encryptionOfAutomationAccountMonitoringEffect": { - "value": "Disabled" - }, - "identityDesignateLessThanOwnersMonitoringEffect": { - "value": "Disabled" - }, - "identityDesignateMoreThanOneOwnerMonitoringEffect": { - "value": "Disabled" - }, - "identityEnableMFAForWritePermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveDeprecatedAccountMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveDeprecatedAccountWithOwnerPermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveExternalAccountWithOwnerPermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveExternalAccountWithReadPermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveExternalAccountWithWritePermissionsMonitoringEffect": { - "value": "Disabled" - }, - "jitNetworkAccessMonitoringEffect": { - "value": "Disabled" - }, - "networkSecurityGroupsOnSubnetsMonitoringEffect": { - "value": "AuditIfNotExists" - }, - "sqlDbEncryptionMonitoringEffect": { - "value": "Disabled" - }, - "sqlManagedInstanceAdvancedDataSecurityEmailAdminsMonitoringEffect": { - "value": "Disabled" - }, - "sqlManagedInstanceAdvancedDataSecurityEmailsMonitoringEffect": { - "value": "Disabled" - }, - "sqlServerAdvancedDataSecurityEmailAdminsMonitoringEffect": { - "value": "Disabled" - }, - "sqlServerAdvancedDataSecurityMonitoringEffect": { - "value": "Disabled" - }, - "systemUpdatesMonitoringEffect": { - "value": "Disabled" - }, - "useRbacRulesMonitoringEffect": { - "value": "Disabled" - }, - "vmssSystemUpdatesMonitoringEffect": { - "value": "Disabled" - }, - "windowsDefenderExploitGuardMonitoringEffect": { - "value": "Disabled" - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json deleted file mode 100644 index 1786a9c39..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "ES-Deploy-ASC-Standard", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Deploy Azure Security Center Standard Tier.", - "displayName": "ES-Deploy-ASC-Standard", - "notScopes": [], - "parameters": {}, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-Standard", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json deleted file mode 100644 index 7bf367af8..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "ES-Deploy-ForwardActLogs", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Ensures that Activity Log Diagnostics settings are set to push logs into Log Analytics workspace.", - "displayName": "ES-Deploy-Diagnostics-ForwardActivityLogs", - "notScopes": [], - "parameters": { - "logAnalytics": { - "value": null - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-Diagnostics-LogAnalytics", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json deleted file mode 100644 index 6cae95354..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "ES-Deploy-ForwardDiagLog", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Ensures that Azure resources are configured to forward diagnostic logs and metrics to an Azure Log Analytics workspace.", - "displayName": "ES-Deploy-Diagnostics-ForwardDiagnosticLogs", - "notScopes": [], - "parameters": { - "logAnalytics": { - "value": null - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/ES-Deploy-Diagnostics-LogAnalytics", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json b/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json deleted file mode 100644 index d75c1298a..000000000 --- a/caf_solution/add-ons/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json +++ /dev/null @@ -1,284 +0,0 @@ -{ - "name": "ES-Deploy-ASC-Standard", - "type": "Microsoft.Authorization/policyDefinitions", - "apiVersion": "2019-09-01", - "properties": { - "description": "Ensures that subscriptions have Security Center Standard enabled.", - "displayName": "ES-Deploy-ASC-Standard", - "mode": "All", - "parameters": { - "pricingTierVMs": { - "type": "String", - "metadata": { - "displayName": "pricingTierVMs", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierSqlServers": { - "type": "String", - "metadata": { - "displayName": "pricingTierSqlServers", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierAppServices": { - "type": "String", - "metadata": { - "displayName": "pricingTierAppServices", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierStorageAccounts": { - "type": "String", - "metadata": { - "displayName": "pricingTierStorageAccounts", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierContainerRegistry": { - "type": "String", - "metadata": { - "displayName": "pricingTierContainerRegistry", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierKeyVaults": { - "type": "String", - "metadata": { - "displayName": "pricingTierKeyVaults", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierKubernetesService": { - "type": "String", - "metadata": { - "displayName": "pricingTierKubernetesService", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - } - }, - "policyRule": { - "if": { - "allOf": [ - { - "field": "type", - "equals": "Microsoft.Resources/subscriptions" - } - ] - }, - "then": { - "effect": "deployIfNotExists", - "details": { - "type": "Microsoft.Security/pricings", - "deploymentScope": "subscription", - "existenceScope": "subscription", - "roleDefinitionIds": [ - "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635" - ], - "existenceCondition": { - "allOf": [ - { - "field": "Microsoft.Security/pricings/pricingTier", - "equals": "Standard" - }, - { - "field": "type", - "equals": "Microsoft.Security/pricings" - } - ] - }, - "deployment": { - "location": "northeurope", - "properties": { - "mode": "incremental", - "parameters": { - "pricingTierVMs": { - "value": "[parameters('pricingTierVMs')]" - }, - "pricingTierSqlServers": { - "value": "[parameters('pricingTierSqlServers')]" - }, - "pricingTierAppServices": { - "value": "[parameters('pricingTierAppServices')]" - }, - "pricingTierStorageAccounts": { - "value": "[parameters('pricingTierStorageAccounts')]" - }, - "pricingTierContainerRegistry": { - "value": "[parameters('pricingTierContainerRegistry')]" - }, - "pricingTierKeyVaults": { - "value": "[parameters('pricingTierKeyVaults')]" - }, - "pricingTierKubernetesService": { - "value": "[parameters('pricingTierKubernetesService')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "pricingTierVMs": { - "type": "string", - "metadata": { - "description": "pricingTierVMs" - } - }, - "pricingTierSqlServers": { - "type": "string", - "metadata": { - "description": "pricingTierSqlServers" - } - }, - "pricingTierAppServices": { - "type": "string", - "metadata": { - "description": "pricingTierAppServices" - } - }, - "pricingTierStorageAccounts": { - "type": "string", - "metadata": { - "description": "pricingTierStorageAccounts" - } - }, - "pricingTierContainerRegistry": { - "type": "string", - "metadata": { - "description": "ContainerRegistry" - } - }, - "pricingTierKeyVaults": { - "type": "string", - "metadata": { - "description": "KeyVaults" - } - }, - "pricingTierKubernetesService": { - "type": "string", - "metadata": { - "description": "KubernetesService" - } - } - }, - "variables": {}, - "resources": [ - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "VirtualMachines", - "properties": { - "pricingTier": "[parameters('pricingTierVMs')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "StorageAccounts", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/VirtualMachines')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierStorageAccounts')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "AppServices", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/StorageAccounts')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierAppServices')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "SqlServers", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/AppServices')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierSqlServers')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "KeyVaults", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/SqlServers')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierKeyVaults')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "KubernetesService", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/KeyVaults')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierKubernetesService')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "ContainerRegistry", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/KubernetesService')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierContainerRegistry')]" - } - } - ], - "outputs": {} - } - } - } - } - } - } - } -} diff --git a/caf_solution/add-ons/caf_eslz/scenario/contoso/archetype_config_overrides.tfvars b/caf_solution/add-ons/caf_eslz/scenario/contoso/archetype_config_overrides.tfvars new file mode 100644 index 000000000..5ce8c38e7 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/contoso/archetype_config_overrides.tfvars @@ -0,0 +1,77 @@ +archetype_config_overrides = { + + root = { + archetype_id = "es_root" + parameters = { + "Deploy-Resource-Diag" = { + "logAnalytics" = { + # value = "resource_id" + lz_key = "caf_foundations_sharedservices" + output_key = "diagnostics" + resource_type = "log_analytics" + resource_key = "central_logs_region1" + attribute_key = "id" + } + } + } + access_control = { + "Contributor" = { + "managed_identities" = { + # principal_ids = ["principal_id1", "principal_id2"] + lz_key = "launchpad" + attribute_key = "principal_id" + resource_keys = [ + "level1" + ] + } + } + } + } + + # decommissioned = { + # archetype_id = "es_decommissioned" + # parameters = {} + # access_control = {} + # } + + # sandboxes = { + # archetype_id = "es_sandboxes" + # parameters = {} + # access_control = {} + # } + + landing-zones = { + archetype_id = "es_landing_zones" + parameters = {} + access_control = { + "Contributor" = { + "managed_identities" = { + # principal_ids = ["principal_id1", "principal_id2"] + lz_key = "launchpad" + attribute_key = "principal_id" + resource_keys = [ + "level3", "subscription_creation_landingzones" + ] + } + } + } + } + + # platform = { + # archetype_id = "es_platform" + # parameters = {} + # access_control = {} + # } + + # connectivity = { + # archetype_id = "es_connectivity_foundation" + # parameters = {} + # access_control = {} + # } + + # management = { + # archetype_id = "es_management" + # parameters = {} + # access_control = {} + # } +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/contoso/custom_landing_zones.tfvars b/caf_solution/add-ons/caf_eslz/scenario/contoso/custom_landing_zones.tfvars new file mode 100644 index 000000000..0d1d97cae --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/contoso/custom_landing_zones.tfvars @@ -0,0 +1,47 @@ +custom_landing_zones = { + + contoso-devops = { + display_name = "Devops" + parent_management_group_id = "contoso-platform" + subscription_ids = [] + archetype_config = { + archetype_id = "default_empty" + parameters = {} + access_control = {} + } + } + + contoso-staging = { + display_name = "Staging" + parent_management_group_id = "contoso-landing-zones" + subscription_ids = [] + archetype_config = { + archetype_id = "default_empty" + parameters = {} + access_control = {} + } + } + + contoso-dev = { + display_name = "Dev" + parent_management_group_id = "contoso-landing-zones" + subscription_ids = [] + archetype_config = { + archetype_id = "default_empty" + parameters = {} + access_control = {} + } + } + + contoso-production = { + display_name = "Production" + parent_management_group_id = "contoso-landing-zones" + subscription_ids = [] + archetype_config = { + archetype_id = "default_empty" + parameters = {} + access_control = {} + } + } + +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/contoso/enterprise_scale.tfvars b/caf_solution/add-ons/caf_eslz/scenario/contoso/enterprise_scale.tfvars new file mode 100644 index 000000000..1bb11770b --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/contoso/enterprise_scale.tfvars @@ -0,0 +1,4 @@ +library_path = "landingzones/caf_solution/add-ons/caf_eslz/scenario/contoso" // Adjust the path as needed +root_id = "contoso" +root_name = "Contoso" +deploy_core_landing_zones = true \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/contoso/landingzone.tfvars b/caf_solution/add-ons/caf_eslz/scenario/contoso/landingzone.tfvars new file mode 100644 index 000000000..5ef87fc15 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/contoso/landingzone.tfvars @@ -0,0 +1,19 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "caf_foundations_sharedservices" + level = "level1" + key = "caf_foundations_enterprise_scale" + tfstates = { + // Remote tfstate to retrieve default location and log analytics workspace + caf_foundations_sharedservices = { + level = "current" + tfstate = "caf_foundations_sharedservices.tfstate" + } + // Remote tfstate to retrieve the MSI created by the launchpad and set permissions on the MG hierarchy + // Requires scenarion 200 to get access to Log Analytics key 'central_logs_region1' + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/scenario/contoso/subscription_id_overrides.tfvars b/caf_solution/add-ons/caf_eslz/scenario/contoso/subscription_id_overrides.tfvars new file mode 100644 index 000000000..915ca2691 --- /dev/null +++ b/caf_solution/add-ons/caf_eslz/scenario/contoso/subscription_id_overrides.tfvars @@ -0,0 +1,10 @@ +subscription_id_overrides = { + root = [] + decommissioned = [] + sandboxes = [] + landing-zones = [] + platform = [] + connectivity = [] + management = [] + identity = [] +} \ No newline at end of file diff --git a/caf_solution/add-ons/caf_eslz/variables.tf b/caf_solution/add-ons/caf_eslz/variables.tf index 2d9c23fac..dcf13848c 100644 --- a/caf_solution/add-ons/caf_eslz/variables.tf +++ b/caf_solution/add-ons/caf_eslz/variables.tf @@ -1,7 +1,17 @@ + +variable "landing_zones_variables" { + default = {} +} # Map of the remote data state -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} +variable "lower_storage_account_name" { + description = "This value is propulated by the rover" +} +variable "lower_container_name" { + description = "This value is propulated by the rover" +} +variable "lower_resource_group_name" { + description = "This value is propulated by the rover" +} variable "tfstate_subscription_id" { description = "This value is propulated by the rover. subscription id hosting the remote tfstates" @@ -12,13 +22,14 @@ variable "tfstate_storage_account_name" { variable "tfstate_container_name" { description = "This value is propulated by the rover" } -variable "tfstate_key" { - description = "This value is propulated by the rover" -} variable "tfstate_resource_group_name" { description = "This value is propulated by the rover" } +variable "diagnostics_definition" { + default = {} +} + variable "landingzone" { default = { backend_type = "azurerm" @@ -34,6 +45,7 @@ variable "landingzone" { } } + variable "user_type" {} variable "tenant_id" {} variable "rover_version" {} @@ -75,7 +87,7 @@ variable "deploy_core_landing_zones" { } variable "archetype_config_overrides" { - type = map(any) + # type = map(any) description = "If specified, will set custom Archetype configurations to the default Enterprise-scale Management Groups." default = {} } @@ -132,4 +144,4 @@ variable "default_location" { default = "eastus" # Need to add validation covering all Azure locations -} \ No newline at end of file +} From 4b36c08af5767ff2fa592ab86090b80e88ab7643 Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 30 Mar 2021 01:20:30 +0000 Subject: [PATCH 15/38] Fix diagnostics --- caf_launchpad/.terraform.lock.hcl | 6 +++--- caf_solution/locals.remote_tfstates.tf | 26 +++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/caf_launchpad/.terraform.lock.hcl b/caf_launchpad/.terraform.lock.hcl index f8ae181d8..bc50f2e74 100644 --- a/caf_launchpad/.terraform.lock.hcl +++ b/caf_launchpad/.terraform.lock.hcl @@ -18,10 +18,10 @@ provider "registry.terraform.io/hashicorp/azuread" { } provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.50.0" - constraints = "~> 2.50.0, ~> 2.50" + version = "2.52.0" + constraints = "~> 2.50, ~> 2.52.0" hashes = [ - "h1:Vr6WUm88s9hXGkyVjHtHsP2Jmc2ypQXn6ww7dXtvk1M=", + "h1:bYwfAgIZFgbGVGYjnZ0OO+RumXn6UDNl2VmIm5gi8tI=", ] } diff --git a/caf_solution/locals.remote_tfstates.tf b/caf_solution/locals.remote_tfstates.tf index e05465330..bc1eda611 100644 --- a/caf_solution/locals.remote_tfstates.tf +++ b/caf_solution/locals.remote_tfstates.tf @@ -33,10 +33,30 @@ locals { tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings - + diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_destinations + # Get the diagnostics settings of services to create + diagnostic_event_hub_namespaces = var.diagnostic_event_hub_namespaces + diagnostic_log_analytics = var.diagnostic_log_analytics + diagnostic_storage_accounts = var.diagnostic_storage_accounts + + # Combine the diagnostics definitions + diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_definition, var.diagnostics_definition) + diagnostics_destinations = { + event_hub_namespaces = merge( + try(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_destinations.event_hub_namespaces, {}), + try(var.diagnostics_destinations.event_hub_namespaces, {}) + ) + log_analytics = merge( + try(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_destinations.log_analytics, {}), + try(var.diagnostics_destinations.log_analytics, {}) + ) + storage = merge( + try(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.diagnostics_destinations.storage, {}), + try(var.diagnostics_destinations.storage, {}) + ) + } + # Get the remote existing diagnostics objects storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.storage_accounts log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.log_analytics event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.event_hub_namespaces From 64c4b654a5b12ca6e107bc406be3ec14ce55c203 Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 30 Mar 2021 03:43:45 +0000 Subject: [PATCH 16/38] Add missing variables --- caf_solution/landingzone.tf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf index d86f7934d..cde94d6bd 100644 --- a/caf_solution/landingzone.tf +++ b/caf_solution/landingzone.tf @@ -11,6 +11,9 @@ module "solution" { custom_role_definitions = var.custom_role_definitions data_factory = local.data_factory database = local.database + diagnostic_storage_accounts = var.diagnostic_storage_accounts + diagnostics_definition = var.diagnostics_definition + diagnostics_destinations = var.diagnostics_destinations event_hub_namespaces = var.event_hub_namespaces global_settings = local.global_settings keyvault_access_policies = var.keyvault_access_policies From 8c6c71b32a6968c9e8532813ea0ca8a88ca7658a Mon Sep 17 00:00:00 2001 From: lolorol Date: Thu, 1 Apr 2021 00:45:43 +0000 Subject: [PATCH 17/38] Add vhub route tables --- caf_solution/local.networking.tf | 6 ++++-- caf_solution/variables.tf | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/caf_solution/local.networking.tf b/caf_solution/local.networking.tf index 4e4edada4..ea00c2282 100644 --- a/caf_solution/local.networking.tf +++ b/caf_solution/local.networking.tf @@ -19,16 +19,18 @@ locals { front_door_waf_policies = var.front_door_waf_policies front_doors = var.front_doors ip_groups = var.ip_groups + load_balancers = var.load_balancers local_network_gateways = var.local_network_gateways - networking_interface_asg_associations = var.networking_interface_asg_associations network_security_group_definition = var.network_security_group_definition network_watchers = var.network_watchers + networking_interface_asg_associations = var.networking_interface_asg_associations private_dns = var.private_dns private_endpoints = var.private_endpoints public_ip_addresses = var.public_ip_addresses - load_balancers = var.load_balancers route_tables = var.route_tables vhub_peerings = var.vhub_peerings + virtual_hub_connections = var.virtual_hub_connections + virtual_hub_route_tables = var.virtual_hub_route_tables virtual_network_gateway_connections = var.virtual_network_gateway_connections virtual_network_gateways = var.virtual_network_gateways virtual_wans = var.virtual_wans diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index 00f6595c8..dc68b1990 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -218,4 +218,10 @@ variable "diagnostic_event_hub_namespaces" { } variable "diagnostic_log_analytics" { default = {} +} +variable "virtual_hub_route_tables" { + default = {} +} +variable "virtual_hub_connections" { + default = {} } \ No newline at end of file From 5c0edca51712a9fac08a17715bf13c71e41921dd Mon Sep 17 00:00:00 2001 From: lolorol Date: Thu, 1 Apr 2021 05:51:24 +0000 Subject: [PATCH 18/38] Add virtual_hub_er_gateway_connections --- caf_solution/local.networking.tf | 1 + caf_solution/variables.networking.tf | 3 +++ 2 files changed, 4 insertions(+) diff --git a/caf_solution/local.networking.tf b/caf_solution/local.networking.tf index ea00c2282..299bc4b11 100644 --- a/caf_solution/local.networking.tf +++ b/caf_solution/local.networking.tf @@ -30,6 +30,7 @@ locals { route_tables = var.route_tables vhub_peerings = var.vhub_peerings virtual_hub_connections = var.virtual_hub_connections + virtual_hub_er_gateway_connections = var.virtual_hub_er_gateway_connections virtual_hub_route_tables = var.virtual_hub_route_tables virtual_network_gateway_connections = var.virtual_network_gateway_connections virtual_network_gateways = var.virtual_network_gateways diff --git a/caf_solution/variables.networking.tf b/caf_solution/variables.networking.tf index 4c44f41de..467bc6be2 100644 --- a/caf_solution/variables.networking.tf +++ b/caf_solution/variables.networking.tf @@ -98,4 +98,7 @@ variable "vhub_peerings" { } variable "vnet_peerings" { default = {} +} +variable "virtual_hub_er_gateway_connections" { + default = {} } \ No newline at end of file From 9df3cc1363d512a5ab3e2d79a40b5f4050ea4191 Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 6 Apr 2021 00:09:11 +0000 Subject: [PATCH 19/38] Update missing variables for ci examples --- .gitignore | 3 ++- caf_solution/variables.tf | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 27e8f9be5..9b5e12b23 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ **/*.log **/backend.azurerm.tf public -**/.terraform.lock.hcl \ No newline at end of file +**/.terraform.lock.hcl +aztfmod \ No newline at end of file diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index dc68b1990..111c1fc6d 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -11,7 +11,20 @@ variable "tfstate_container_name" {} variable "tfstate_key" {} variable "tfstate_resource_group_name" {} -variable "landingzone" {} +variable "landingzone" { + default = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "caf_examples" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } + } +} variable "global_settings" { default = {} @@ -224,4 +237,7 @@ variable "virtual_hub_route_tables" { } variable "virtual_hub_connections" { default = {} +} +variable "var_folder_path" { + default = null } \ No newline at end of file From e8b5eafc171dbc92a5fc3a4ac35b2e35f831b7c0 Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 6 Apr 2021 00:34:03 +0000 Subject: [PATCH 20/38] Add option to overwrite global_settings --- caf_solution/locals.remote_tfstates.tf | 2 +- caf_solution/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/caf_solution/locals.remote_tfstates.tf b/caf_solution/locals.remote_tfstates.tf index bc1eda611..d8266037e 100644 --- a/caf_solution/locals.remote_tfstates.tf +++ b/caf_solution/locals.remote_tfstates.tf @@ -32,7 +32,7 @@ locals { } tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings + global_settings = try(var.global_settings, data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings) diagnostics = { # Get the diagnostics settings of services to create diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index 111c1fc6d..ba0beb5dd 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -27,7 +27,7 @@ variable "landingzone" { } variable "global_settings" { - default = {} + default = null } variable "provider_azurerm_features_keyvault" { From 6c01897d7a372b5c1a83cfb4322f18c3255cdedb Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 6 Apr 2021 00:52:26 +0000 Subject: [PATCH 21/38] Update base tags optional attributes --- caf_solution/locals.remote_tfstates.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/caf_solution/locals.remote_tfstates.tf b/caf_solution/locals.remote_tfstates.tf index d8266037e..2530c0438 100644 --- a/caf_solution/locals.remote_tfstates.tf +++ b/caf_solution/locals.remote_tfstates.tf @@ -31,7 +31,7 @@ locals { "landingzone" = var.landingzone.key } - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + tags = merge(try(local.global_settings.tags, {}), local.landingzone_tag, { "level" = var.landingzone.level }, try({ "environment" = local.global_settings.environment }, {}), { "rover_version" = var.rover_version }, var.tags) global_settings = try(var.global_settings, data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings) diagnostics = { From 688de7bf853955f114d4d78c6b671af4a1191b7e Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 6 Apr 2021 01:22:08 +0000 Subject: [PATCH 22/38] Fix regression --- caf_solution/locals.remote_tfstates.tf | 2 +- caf_solution/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/caf_solution/locals.remote_tfstates.tf b/caf_solution/locals.remote_tfstates.tf index 2530c0438..600324103 100644 --- a/caf_solution/locals.remote_tfstates.tf +++ b/caf_solution/locals.remote_tfstates.tf @@ -32,7 +32,7 @@ locals { } tags = merge(try(local.global_settings.tags, {}), local.landingzone_tag, { "level" = var.landingzone.level }, try({ "environment" = local.global_settings.environment }, {}), { "rover_version" = var.rover_version }, var.tags) - global_settings = try(var.global_settings, data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings) + global_settings = var.global_settings == {} ? data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings : {} diagnostics = { # Get the diagnostics settings of services to create diff --git a/caf_solution/variables.tf b/caf_solution/variables.tf index ba0beb5dd..111c1fc6d 100644 --- a/caf_solution/variables.tf +++ b/caf_solution/variables.tf @@ -27,7 +27,7 @@ variable "landingzone" { } variable "global_settings" { - default = null + default = {} } variable "provider_azurerm_features_keyvault" { From 0170750ca1c18cb6dff9ea0a121e2e5780eb95a4 Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 6 Apr 2021 01:26:26 +0000 Subject: [PATCH 23/38] Fix global_settings overrite --- caf_solution/locals.remote_tfstates.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/caf_solution/locals.remote_tfstates.tf b/caf_solution/locals.remote_tfstates.tf index 600324103..6ccd34e65 100644 --- a/caf_solution/locals.remote_tfstates.tf +++ b/caf_solution/locals.remote_tfstates.tf @@ -32,7 +32,7 @@ locals { } tags = merge(try(local.global_settings.tags, {}), local.landingzone_tag, { "level" = var.landingzone.level }, try({ "environment" = local.global_settings.environment }, {}), { "rover_version" = var.rover_version }, var.tags) - global_settings = var.global_settings == {} ? data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings : {} + global_settings = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings : var.global_settings) diagnostics = { # Get the diagnostics settings of services to create From 4980a65ea12ee7066081ef4a2236694d1c6adc21 Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 6 Apr 2021 01:29:27 +0000 Subject: [PATCH 24/38] Update fix --- caf_solution/locals.remote_tfstates.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/caf_solution/locals.remote_tfstates.tf b/caf_solution/locals.remote_tfstates.tf index 6ccd34e65..71fc5d830 100644 --- a/caf_solution/locals.remote_tfstates.tf +++ b/caf_solution/locals.remote_tfstates.tf @@ -32,7 +32,7 @@ locals { } tags = merge(try(local.global_settings.tags, {}), local.landingzone_tag, { "level" = var.landingzone.level }, try({ "environment" = local.global_settings.environment }, {}), { "rover_version" = var.rover_version }, var.tags) - global_settings = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings : var.global_settings) + global_settings = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings, var.global_settings) diagnostics = { # Get the diagnostics settings of services to create From c466a37a195488f540aee80b6f0c4576635237ac Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 6 Apr 2021 01:38:16 +0000 Subject: [PATCH 25/38] Add remote network_security_groups --- caf_solution/local.remote.tf | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/caf_solution/local.remote.tf b/caf_solution/local.remote.tf index 6d76fb1ff..cb9e258f7 100644 --- a/caf_solution/local.remote.tf +++ b/caf_solution/local.remote.tf @@ -66,6 +66,9 @@ locals { mysql_servers = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].mysql_servers, {})) } + network_security_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].network_security_groups, {})) + } network_watchers = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].network_watchers, {})) } @@ -93,6 +96,12 @@ locals { synapse_workspaces = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].synapse_workspaces, {})) } + virtual_hub_route_tables = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].virtual_hub_route_tables, {})) + } + virtual_wans = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].virtual_wans, {})) + } vnets = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].vnets, {})) } From 91a1ea00073d9dcf53b1de70387ed06f44a5b419 Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 6 Apr 2021 01:57:35 +0000 Subject: [PATCH 26/38] Fix missing remote objects --- caf_solution/landingzone.tf | 2 +- caf_solution/local.remote.tf | 30 ++++++++++++ caf_solution/local.remote_objects.tf | 72 ++++++++++++++-------------- 3 files changed, 67 insertions(+), 37 deletions(-) diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf index cde94d6bd..5ab9912db 100644 --- a/caf_solution/landingzone.tf +++ b/caf_solution/landingzone.tf @@ -25,7 +25,7 @@ module "solution" { logic_app = var.logic_app managed_identities = var.managed_identities networking = local.networking - remote_objects = local.remote_objects + remote_objects = local.remote resource_groups = var.resource_groups role_mapping = var.role_mapping security = local.security diff --git a/caf_solution/local.remote.tf b/caf_solution/local.remote.tf index cb9e258f7..b369b0f5d 100644 --- a/caf_solution/local.remote.tf +++ b/caf_solution/local.remote.tf @@ -3,6 +3,9 @@ locals { aks_clusters = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].aks_clusters, {})) } + app_config = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_config, {})) + } app_service_environments = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_service_environments, {})) } @@ -12,6 +15,9 @@ locals { app_services = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].app_services, {})) } + application_security_groups = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].application_security_groups, {})) + } application_gateway_applications = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].application_gateway_applications, {})) } @@ -36,15 +42,39 @@ locals { container_registry = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].container_registry, {})) } + disk_encryption_sets = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].disk_encryption_sets, {})) + } + dns_zones = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].dns_zones, {})) + } event_hub_namespaces = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].event_hub_namespaces, {})) } front_door_waf_policies = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].front_door_waf_policies, {})) } + integration_service_environment = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].integration_service_environment, {})) + } + keyvault_certificate_requests = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].keyvault_certificate_requests, {})) + } + keyvault_keys = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].keyvault_keys, {})) + } keyvaults = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].keyvaults, {})) } + logic_app_integration_account = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].logic_app_integration_account, {})) + } + logic_app_workflow = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].logic_app_workflow, {})) + } + machine_learning_workspaces = { + for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].machine_learning_workspaces, {})) + } managed_identities = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].managed_identities, {})) } diff --git a/caf_solution/local.remote_objects.tf b/caf_solution/local.remote_objects.tf index 8863c7ff0..602dc1229 100644 --- a/caf_solution/local.remote_objects.tf +++ b/caf_solution/local.remote_objects.tf @@ -1,36 +1,36 @@ -locals { - remote_objects = { - aks_clusters = local.remote.aks_clusters - app_service_environments = local.remote.app_service_environments - app_service_plans = local.remote.app_service_plans - app_services = local.remote.app_services - application_gateway_applications = local.remote.application_gateway_applications - application_gateways = local.remote.application_gateways - availability_sets = local.remote.availability_sets - azuread_applications = local.remote.azuread_applications - azuread_groups = local.remote.azuread_groups - azuread_users = local.remote.azuread_users - azurerm_firewalls = local.remote.azurerm_firewalls - container_registry = local.remote.container_registry - event_hub_namespaces = local.remote.event_hub_namespaces - front_door_waf_policies = local.remote.front_door_waf_policies - keyvaults = local.remote.keyvaults - managed_identities = local.remote.managed_identities - mssql_databases = local.remote.mssql_databases - mssql_elastic_pools = local.remote.mssql_elastic_pools - mssql_managed_databases = local.remote.mssql_managed_databases - mssql_managed_instances = local.remote.mssql_managed_instances - mssql_servers = local.remote.mssql_servers - mysql_servers = local.remote.mysql_servers - network_watchers = local.remote.network_watchers - postgresql_servers = local.remote.postgresql_servers - private_dns = local.remote.private_dns - proximity_placement_groups = local.remote.proximity_placement_groups - public_ip_addresses = local.remote.public_ip_addresses - recovery_vaults = local.remote.recovery_vaults - resource_groups = local.remote.resource_groups - storage_accounts = local.remote.storage_accounts - synapse_workspaces = local.remote.synapse_workspaces - vnets = local.remote.vnets - } -} \ No newline at end of file +# locals { +# remote_objects = { +# aks_clusters = local.remote.aks_clusters +# app_service_environments = local.remote.app_service_environments +# app_service_plans = local.remote.app_service_plans +# app_services = local.remote.app_services +# application_gateway_applications = local.remote.application_gateway_applications +# application_gateways = local.remote.application_gateways +# availability_sets = local.remote.availability_sets +# azuread_applications = local.remote.azuread_applications +# azuread_groups = local.remote.azuread_groups +# azuread_users = local.remote.azuread_users +# azurerm_firewalls = local.remote.azurerm_firewalls +# container_registry = local.remote.container_registry +# event_hub_namespaces = local.remote.event_hub_namespaces +# front_door_waf_policies = local.remote.front_door_waf_policies +# keyvaults = local.remote.keyvaults +# managed_identities = local.remote.managed_identities +# mssql_databases = local.remote.mssql_databases +# mssql_elastic_pools = local.remote.mssql_elastic_pools +# mssql_managed_databases = local.remote.mssql_managed_databases +# mssql_managed_instances = local.remote.mssql_managed_instances +# mssql_servers = local.remote.mssql_servers +# mysql_servers = local.remote.mysql_servers +# network_watchers = local.remote.network_watchers +# postgresql_servers = local.remote.postgresql_servers +# private_dns = local.remote.private_dns +# proximity_placement_groups = local.remote.proximity_placement_groups +# public_ip_addresses = local.remote.public_ip_addresses +# recovery_vaults = local.remote.recovery_vaults +# resource_groups = local.remote.resource_groups +# storage_accounts = local.remote.storage_accounts +# synapse_workspaces = local.remote.synapse_workspaces +# vnets = local.remote.vnets +# } +# } \ No newline at end of file From 83b0367c9fa8470b711fcea6a1b48d1db6a9d960 Mon Sep 17 00:00:00 2001 From: lolorol Date: Tue, 6 Apr 2021 06:11:26 +0000 Subject: [PATCH 27/38] fmt --- .../caf_eslz/archetype_config_overrides.tf | 18 +++++------ .../caf_eslz/locals.remote_tfstates.tf | 2 +- .../contoso/archetype_config_overrides.tfvars | 8 ++--- .../contoso/custom_landing_zones.tfvars | 2 +- .../scenario/contoso/enterprise_scale.tfvars | 2 +- caf_solution/local.data_factory.tf | 30 +++++++++---------- caf_solution/locals.remote_tfstates.tf | 8 ++--- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/caf_solution/add-ons/caf_eslz/archetype_config_overrides.tf b/caf_solution/add-ons/caf_eslz/archetype_config_overrides.tf index 583ead684..ead14f952 100644 --- a/caf_solution/add-ons/caf_eslz/archetype_config_overrides.tf +++ b/caf_solution/add-ons/caf_eslz/archetype_config_overrides.tf @@ -1,12 +1,12 @@ locals { - archetype_config_overrides = { - for mg_id , mg_value in try(var.archetype_config_overrides, {}) : mg_id => { + archetype_config_overrides = { + for mg_id, mg_value in try(var.archetype_config_overrides, {}) : mg_id => { + + archetype_id = mg_value.archetype_id - archetype_id = mg_value.archetype_id - access_control = { - for mapping in + for mapping in flatten( [ for role, roles in try(mg_value.access_control, {}) : { @@ -21,7 +21,7 @@ locals { ] ] ) //flatten - , + , flatten( [ for resource_type, value in roles : [ @@ -31,15 +31,15 @@ locals { ] ] ) //flatten - ) //coalescelist (ids) + ) //coalescelist (ids) } ] ) : mapping.role => mapping.ids } - parameters = { + parameters = { for param_key, param_value in try(mg_value.parameters, {}) : param_key => { - for key, value in param_value : key => jsonencode(try(local.caf[value.output_key][value.lz_key][value.resource_type][value.resource_key][value.attribute_key], value.value)) + for key, value in param_value : key => jsonencode(try(local.caf[value.output_key][value.lz_key][value.resource_type][value.resource_key][value.attribute_key], value.value)) } } diff --git a/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf b/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf index 6a6ae17a0..48fc5bc32 100644 --- a/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf +++ b/caf_solution/add-ons/caf_eslz/locals.remote_tfstates.tf @@ -35,7 +35,7 @@ locals { diagnostics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics caf = { - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) + tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) global_settings = { for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.objects[key].global_settings, {})) diff --git a/caf_solution/add-ons/caf_eslz/scenario/contoso/archetype_config_overrides.tfvars b/caf_solution/add-ons/caf_eslz/scenario/contoso/archetype_config_overrides.tfvars index 5ce8c38e7..781917ec1 100644 --- a/caf_solution/add-ons/caf_eslz/scenario/contoso/archetype_config_overrides.tfvars +++ b/caf_solution/add-ons/caf_eslz/scenario/contoso/archetype_config_overrides.tfvars @@ -1,8 +1,8 @@ archetype_config_overrides = { root = { - archetype_id = "es_root" - parameters = { + archetype_id = "es_root" + parameters = { "Deploy-Resource-Diag" = { "logAnalytics" = { # value = "resource_id" @@ -41,8 +41,8 @@ archetype_config_overrides = { # } landing-zones = { - archetype_id = "es_landing_zones" - parameters = {} + archetype_id = "es_landing_zones" + parameters = {} access_control = { "Contributor" = { "managed_identities" = { diff --git a/caf_solution/add-ons/caf_eslz/scenario/contoso/custom_landing_zones.tfvars b/caf_solution/add-ons/caf_eslz/scenario/contoso/custom_landing_zones.tfvars index 0d1d97cae..48dc2d807 100644 --- a/caf_solution/add-ons/caf_eslz/scenario/contoso/custom_landing_zones.tfvars +++ b/caf_solution/add-ons/caf_eslz/scenario/contoso/custom_landing_zones.tfvars @@ -10,7 +10,7 @@ custom_landing_zones = { access_control = {} } } - + contoso-staging = { display_name = "Staging" parent_management_group_id = "contoso-landing-zones" diff --git a/caf_solution/add-ons/caf_eslz/scenario/contoso/enterprise_scale.tfvars b/caf_solution/add-ons/caf_eslz/scenario/contoso/enterprise_scale.tfvars index 1bb11770b..8aa30df26 100644 --- a/caf_solution/add-ons/caf_eslz/scenario/contoso/enterprise_scale.tfvars +++ b/caf_solution/add-ons/caf_eslz/scenario/contoso/enterprise_scale.tfvars @@ -1,4 +1,4 @@ -library_path = "landingzones/caf_solution/add-ons/caf_eslz/scenario/contoso" // Adjust the path as needed +library_path = "landingzones/caf_solution/add-ons/caf_eslz/scenario/contoso" // Adjust the path as needed root_id = "contoso" root_name = "Contoso" deploy_core_landing_zones = true \ No newline at end of file diff --git a/caf_solution/local.data_factory.tf b/caf_solution/local.data_factory.tf index 557defcf3..14861c1c7 100644 --- a/caf_solution/local.data_factory.tf +++ b/caf_solution/local.data_factory.tf @@ -2,21 +2,21 @@ locals { data_factory = merge( var.data_factory, { - data_factory_pipeline = var.data_factory_pipeline - data_factory_trigger_schedule = var.data_factory_trigger_schedule - datasets = { - azure_blob = try(var.datasets.azure_blob, {}) - cosmosdb_sqlapi = try(var.datasets.cosmosdb_sqlapi, {}) - delimited_text = try(var.datasets.delimited_text, {}) - http = try(var.datasets.http, {}) - json = try(var.datasets.json, {}) - mysql = try(var.datasets.mysql, {}) - postgresql = try(var.datasets.postgresql, {}) - sql_server_table = try(var.datasets.sql_server_table, {}) - } - linked_services = { - azure_blob_storage = try(var.linked_services.azure_blob_storage, {}) - } + data_factory_pipeline = var.data_factory_pipeline + data_factory_trigger_schedule = var.data_factory_trigger_schedule + datasets = { + azure_blob = try(var.datasets.azure_blob, {}) + cosmosdb_sqlapi = try(var.datasets.cosmosdb_sqlapi, {}) + delimited_text = try(var.datasets.delimited_text, {}) + http = try(var.datasets.http, {}) + json = try(var.datasets.json, {}) + mysql = try(var.datasets.mysql, {}) + postgresql = try(var.datasets.postgresql, {}) + sql_server_table = try(var.datasets.sql_server_table, {}) + } + linked_services = { + azure_blob_storage = try(var.linked_services.azure_blob_storage, {}) + } } ) } diff --git a/caf_solution/locals.remote_tfstates.tf b/caf_solution/locals.remote_tfstates.tf index 71fc5d830..ca11e499e 100644 --- a/caf_solution/locals.remote_tfstates.tf +++ b/caf_solution/locals.remote_tfstates.tf @@ -33,7 +33,7 @@ locals { tags = merge(try(local.global_settings.tags, {}), local.landingzone_tag, { "level" = var.landingzone.level }, try({ "environment" = local.global_settings.environment }, {}), { "rover_version" = var.rover_version }, var.tags) global_settings = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].global_settings, var.global_settings) - + diagnostics = { # Get the diagnostics settings of services to create diagnostic_event_hub_namespaces = var.diagnostic_event_hub_namespaces @@ -57,9 +57,9 @@ locals { ) } # Get the remote existing diagnostics objects - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.log_analytics - event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.event_hub_namespaces + storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.storage_accounts + log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.log_analytics + event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.objects[var.landingzone.global_settings_key].diagnostics.event_hub_namespaces } } From bff5453fb3805755952d1873afe59b6ab87499e3 Mon Sep 17 00:00:00 2001 From: lolorol Date: Wed, 7 Apr 2021 03:45:23 +0000 Subject: [PATCH 28/38] Add dynamic keyvault secrets in security --- caf_solution/local.security.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/caf_solution/local.security.tf b/caf_solution/local.security.tf index 8ae7b7e2d..3d5daf9e9 100644 --- a/caf_solution/local.security.tf +++ b/caf_solution/local.security.tf @@ -3,6 +3,7 @@ locals { var.security, { disk_encryption_sets = var.disk_encryption_sets + dynamic_keyvault_secrets = var.dynamic_keyvault_secrets keyvault_certificate_issuers = var.keyvault_certificate_issuers keyvault_certificate_requests = var.keyvault_certificate_requests keyvault_certificates = var.keyvault_certificates From 2de67b0a4156ff561807b0f179431d94c4047a4c Mon Sep 17 00:00:00 2001 From: lolorol Date: Wed, 7 Apr 2021 14:46:48 +0000 Subject: [PATCH 29/38] Update for dynamic keyvault secrets --- caf_solution/dynamic_secrets.tf | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/caf_solution/dynamic_secrets.tf b/caf_solution/dynamic_secrets.tf index fde3df0e0..e5be79320 100644 --- a/caf_solution/dynamic_secrets.tf +++ b/caf_solution/dynamic_secrets.tf @@ -1,7 +1,12 @@ module "dynamic_keyvault_secrets" { source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=5.3.0_preview" - for_each = try(var.dynamic_keyvault_secrets, {}) + for_each = { + for keyvault_key, secrets in try(var.dynamic_keyvault_secrets, {}) : keyvault_key => { + for key, value in secrets : key => value + if try(value.value, null) == null + } + } settings = each.value keyvault = module.solution.keyvaults[each.key] From e98dda38fb1b7d6fe91a2cdbd2c7b8bfdb29735f Mon Sep 17 00:00:00 2001 From: Arnaud Lheureux Date: Thu, 8 Apr 2021 04:50:48 +0000 Subject: [PATCH 30/38] Rover update --- .devcontainer/docker-compose.yml | 2 +- ...landingzones.yml => landingzones-tf13.yml} | 26 +++++------------- .github/workflows/landingzones-tf14.yml | 27 +++++++++++++++---- .github/workflows/landingzones-tf15.yml | 10 +++---- 4 files changed, 35 insertions(+), 30 deletions(-) rename .github/workflows/{landingzones.yml => landingzones-tf13.yml} (94%) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 95d2821c0..6e46e45b0 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -6,7 +6,7 @@ version: '3.7' services: rover: - image: aztfmod/rover-preview:0.14.8-2103.181107 + image: aztfmod/rover:0.14.10-2104.0803 user: vscode labels: diff --git a/.github/workflows/landingzones.yml b/.github/workflows/landingzones-tf13.yml similarity index 94% rename from .github/workflows/landingzones.yml rename to .github/workflows/landingzones-tf13.yml index 32d1685fd..8feeef155 100644 --- a/.github/workflows/landingzones.yml +++ b/.github/workflows/landingzones-tf13.yml @@ -3,23 +3,11 @@ # Licensed under the MIT License. # -name: landingzones +name: landingzones-tf13 on: - pull_request: - paths-ignore: - - 'documentation/**' - - '_pictures/**' - - 'README.md' - - 'CHANGELOG.md' - push: - paths-ignore: - - 'documentation/**' - - '_pictures/**' - - 'README.md' - - 'CHANGELOG.md' schedule: - - cron: '0 4 * * *' + - cron: '0 1 * * *' env: TF_CLI_ARGS: '-no-color' @@ -42,7 +30,7 @@ jobs: random_length: ['5'] container: - image: aztfmod/rover:0.13.6-2103.0304 + image: aztfmod/rover:0.13.6-2104.0803 options: --user 0 steps: @@ -91,7 +79,7 @@ jobs: ] container: - image: aztfmod/rover:0.13.6-2103.0304 + image: aztfmod/rover:0.13.6-2104.0803 options: --user 0 steps: @@ -135,7 +123,7 @@ jobs: random_length: ['5'] container: - image: aztfmod/rover:0.13.6-2103.0304 + image: aztfmod/rover:0.13.6-2104.0803 options: --user 0 steps: @@ -182,7 +170,7 @@ jobs: ] container: - image: aztfmod/rover:0.13.6-2103.0304 + image: aztfmod/rover:0.13.6-2104.0803 options: --user 0 steps: @@ -225,7 +213,7 @@ jobs: random_length: ['5'] container: - image: aztfmod/rover:0.13.6-2103.0304 + image: aztfmod/rover:0.13.6-2104.0803 options: --user 0 steps: diff --git a/.github/workflows/landingzones-tf14.yml b/.github/workflows/landingzones-tf14.yml index 252c3e8d9..e3530048e 100644 --- a/.github/workflows/landingzones-tf14.yml +++ b/.github/workflows/landingzones-tf14.yml @@ -9,6 +9,23 @@ on: schedule: - cron: '0 1 * * *' + +on: + pull_request: + paths-ignore: + - 'documentation/**' + - '_pictures/**' + - 'README.md' + - 'CHANGELOG.md' + push: + paths-ignore: + - 'documentation/**' + - '_pictures/**' + - 'README.md' + - 'CHANGELOG.md' + schedule: + - cron: '0 4 * * *' + env: TF_CLI_ARGS: '-no-color' TF_CLI_ARGS_destroy: '-auto-approve -refresh=false' @@ -30,7 +47,7 @@ jobs: random_length: ['5'] container: - image: aztfmod/rover:0.14.7-2103.0304 + image: aztfmod/rover:0.14.10-2104.0803 options: --user 0 steps: @@ -79,7 +96,7 @@ jobs: ] container: - image: aztfmod/rover:0.14.7-2103.0304 + image: aztfmod/rover:0.14.10-2104.0803 options: --user 0 steps: @@ -123,7 +140,7 @@ jobs: random_length: ['5'] container: - image: aztfmod/rover:0.14.7-2103.0304 + image: aztfmod/rover:0.14.10-2104.0803 options: --user 0 steps: @@ -170,7 +187,7 @@ jobs: ] container: - image: aztfmod/rover:0.14.7-2103.0304 + image: aztfmod/rover:0.14.10-2104.0803 options: --user 0 steps: @@ -213,7 +230,7 @@ jobs: random_length: ['5'] container: - image: aztfmod/rover:0.14.7-2103.0304 + image: aztfmod/rover:0.14.10-2104.0803 options: --user 0 steps: diff --git a/.github/workflows/landingzones-tf15.yml b/.github/workflows/landingzones-tf15.yml index 79276e89e..ae7b915b6 100644 --- a/.github/workflows/landingzones-tf15.yml +++ b/.github/workflows/landingzones-tf15.yml @@ -30,7 +30,7 @@ jobs: random_length: ['5'] container: - image: aztfmod/rover:0.15.0-alpha20210210-2103.0304 + image: aztfmod/rover:0.15.0-rc2-2104.0803 options: --user 0 steps: @@ -79,7 +79,7 @@ jobs: ] container: - image: aztfmod/rover:0.15.0-alpha20210210-2103.0304 + image: aztfmod/rover:0.15.0-rc2-2104.0803 options: --user 0 steps: @@ -123,7 +123,7 @@ jobs: random_length: ['5'] container: - image: aztfmod/rover:0.15.0-alpha20210210-2103.0304 + image: aztfmod/rover:0.15.0-rc2-2104.0803 options: --user 0 steps: @@ -170,7 +170,7 @@ jobs: ] container: - image: aztfmod/rover:0.15.0-alpha20210210-2103.0304 + image: aztfmod/rover:0.15.0-rc2-2104.0803 options: --user 0 steps: @@ -213,7 +213,7 @@ jobs: random_length: ['5'] container: - image: aztfmod/rover:0.15.0-alpha20210210-2103.0304 + image: aztfmod/rover:0.15.0-rc2-2104.0803 options: --user 0 steps: From be9135bca7aa8dbc045ece3e83df99b4c06ce578 Mon Sep 17 00:00:00 2001 From: Arnaud Lheureux Date: Thu, 8 Apr 2021 08:00:17 +0000 Subject: [PATCH 31/38] Update workflow --- .github/workflows/landingzones-tf14.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/landingzones-tf14.yml b/.github/workflows/landingzones-tf14.yml index e3530048e..aa65cb1a8 100644 --- a/.github/workflows/landingzones-tf14.yml +++ b/.github/workflows/landingzones-tf14.yml @@ -4,12 +4,7 @@ # name: landingzones-tf14 - -on: - schedule: - - cron: '0 1 * * *' - - + on: pull_request: paths-ignore: From 924f478cfe33d18a4834c3b2f1c162554ec57310 Mon Sep 17 00:00:00 2001 From: Arnaud Lheureux Date: Thu, 8 Apr 2021 10:06:22 +0000 Subject: [PATCH 32/38] March 2021 Update --- .github/workflows/landingzones-tf13.yml | 74 +++++++++++-------- .github/workflows/landingzones-tf14.yml | 72 +++++++++++------- .github/workflows/landingzones-tf15.yml | 74 +++++++++++-------- README.md | 33 +-------- caf_launchpad/dynamic_secrets.tf | 3 +- caf_launchpad/landingzone.tf | 3 +- caf_solution/dynamic_secrets.tf | 3 +- caf_solution/landingzone.tf | 3 +- .../configuration.tfvars | 4 - .../101-multi-region-hub/configuration.tfvars | 4 - .../105-hub-and-spoke/configuration.tfvars | 4 - .../configuration.tfvars | 4 - .../configuration.tfvars | 4 - .../201-multi-region-hub/configuration.tfvars | 4 - .../210-aks-private/configuration.tfvars | 4 - .../shared_services/100/configuration.tfvars | 4 - .../shared_services/200/configuration.tfvars | 4 - 17 files changed, 146 insertions(+), 155 deletions(-) diff --git a/.github/workflows/landingzones-tf13.yml b/.github/workflows/landingzones-tf13.yml index 8feeef155..a5144bb8f 100644 --- a/.github/workflows/landingzones-tf13.yml +++ b/.github/workflows/landingzones-tf13.yml @@ -4,10 +4,10 @@ # name: landingzones-tf13 - + on: schedule: - - cron: '0 1 * * *' + - cron: '0 2 * * *' env: TF_CLI_ARGS: '-no-color' @@ -45,8 +45,8 @@ jobs: - name: launchpad run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a apply \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/100 \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_launchpad -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_launchpad/scenario/100 \ -level level0 \ -launchpad \ -parallelism=30 \ @@ -57,10 +57,15 @@ jobs: - name: foundations run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a apply \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ - --environment ${{ github.run_id }} + --environment ${{ github.run_id }} \ + '-var random_length=${{ matrix.random_length }}' \ + '-var prefix=g${{ github.run_id }}' \ + '-var tags={testing_job_id="${{ github.run_id }}"}' networking100: name: networking-100 @@ -72,10 +77,10 @@ jobs: fail-fast: false matrix: config_files: [ - "caf_networking/scenario/100-single-region-hub", - "caf_networking/scenario/101-multi-region-hub", - "caf_networking/scenario/105-hub-and-spoke", - "caf_networking/scenario/106-hub-virtual-wan-firewall" + "caf_solution/scenario/networking/100-single-region-hub", + "caf_solution/scenario/networking/101-multi-region-hub", + "caf_solution/scenario/networking/105-hub-and-spoke", + "caf_solution/scenario/networking/106-hub-virtual-wan-firewall" ] container: @@ -92,20 +97,20 @@ jobs: - name: deploy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a apply \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a apply \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} - name: destroy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a destroy \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a destroy \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} \ -refresh=false \ -auto-approve @@ -138,8 +143,8 @@ jobs: - name: launchpad-200-upgrade run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a apply \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/200 \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_launchpad -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_launchpad/scenario/200 \ -level level0 \ -launchpad \ -parallelism=30 \ @@ -150,9 +155,15 @@ jobs: - name: foundations-200-upgrade run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a apply \ - -level level1 \ - --environment ${{ github.run_id }} + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -tfstate caf_foundations.tfstate \ + -level level1 \ + -parallelism=30 \ + --environment ${{ github.run_id }} \ + '-var random_length=${{ matrix.random_length }}' \ + '-var prefix=g${{ github.run_id }}' \ + '-var tags={testing_job_id="${{ github.run_id }}"}' networking200: name: networking-200 @@ -164,9 +175,9 @@ jobs: fail-fast: false matrix: config_files: [ - "caf_networking/scenario/200-single-region-hub", - "caf_networking/scenario/201-multi-region-hub", - "caf_networking/scenario/210-aks-private" + "caf_solution/scenario/networking/200-single-region-hub", + "caf_solution/scenario/networking/201-multi-region-hub", + "caf_solution/scenario/networking/210-aks-private" ] container: @@ -183,20 +194,20 @@ jobs: - name: deploy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a apply \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a apply \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} - name: destroy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a destroy \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a destroy \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} \ -refresh=false \ -auto-approve @@ -228,16 +239,21 @@ jobs: - name: foundations run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a destroy \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a destroy \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ + '-var random_length=${{ matrix.random_length }}' \ + '-var prefix=g${{ github.run_id }}' \ + '-var tags={testing_job_id="${{ github.run_id }}"}' \ -auto-approve - name: Remove launchpad run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a destroy \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/200 \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_launchpad -a destroy \ + -var-folder ${GITHUB_WORKSPACE}/caf_launchpad/scenario/200 \ -level level0 \ -launchpad \ -parallelism=30 \ diff --git a/.github/workflows/landingzones-tf14.yml b/.github/workflows/landingzones-tf14.yml index aa65cb1a8..1228a2c10 100644 --- a/.github/workflows/landingzones-tf14.yml +++ b/.github/workflows/landingzones-tf14.yml @@ -19,7 +19,7 @@ on: - 'README.md' - 'CHANGELOG.md' schedule: - - cron: '0 4 * * *' + - cron: '0 0 * * *' env: TF_CLI_ARGS: '-no-color' @@ -57,8 +57,8 @@ jobs: - name: launchpad run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a apply \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/100 \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_launchpad -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_launchpad/scenario/100 \ -level level0 \ -launchpad \ -parallelism=30 \ @@ -69,10 +69,15 @@ jobs: - name: foundations run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a apply \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ - --environment ${{ github.run_id }} + --environment ${{ github.run_id }} \ + '-var random_length=${{ matrix.random_length }}' \ + '-var prefix=g${{ github.run_id }}' \ + '-var tags={testing_job_id="${{ github.run_id }}"}' networking100: name: networking-100 @@ -84,10 +89,10 @@ jobs: fail-fast: false matrix: config_files: [ - "caf_networking/scenario/100-single-region-hub", - "caf_networking/scenario/101-multi-region-hub", - "caf_networking/scenario/105-hub-and-spoke", - "caf_networking/scenario/106-hub-virtual-wan-firewall" + "caf_solution/scenario/networking/100-single-region-hub", + "caf_solution/scenario/networking/101-multi-region-hub", + "caf_solution/scenario/networking/105-hub-and-spoke", + "caf_solution/scenario/networking/106-hub-virtual-wan-firewall" ] container: @@ -104,20 +109,20 @@ jobs: - name: deploy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a apply \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a apply \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} - name: destroy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a destroy \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a destroy \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} \ -refresh=false \ -auto-approve @@ -150,8 +155,8 @@ jobs: - name: launchpad-200-upgrade run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a apply \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/200 \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_launchpad -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_launchpad/scenario/200 \ -level level0 \ -launchpad \ -parallelism=30 \ @@ -162,9 +167,15 @@ jobs: - name: foundations-200-upgrade run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a apply \ - -level level1 \ - --environment ${{ github.run_id }} + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -tfstate caf_foundations.tfstate \ + -level level1 \ + -parallelism=30 \ + --environment ${{ github.run_id }} \ + '-var random_length=${{ matrix.random_length }}' \ + '-var prefix=g${{ github.run_id }}' \ + '-var tags={testing_job_id="${{ github.run_id }}"}' networking200: name: networking-200 @@ -176,9 +187,9 @@ jobs: fail-fast: false matrix: config_files: [ - "caf_networking/scenario/200-single-region-hub", - "caf_networking/scenario/201-multi-region-hub", - "caf_networking/scenario/210-aks-private" + "caf_solution/scenario/networking/200-single-region-hub", + "caf_solution/scenario/networking/201-multi-region-hub", + "caf_solution/scenario/networking/210-aks-private" ] container: @@ -195,20 +206,20 @@ jobs: - name: deploy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a apply \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a apply \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} - name: destroy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a destroy \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a destroy \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} \ -refresh=false \ -auto-approve @@ -240,16 +251,21 @@ jobs: - name: foundations run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a destroy \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a destroy \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ + '-var random_length=${{ matrix.random_length }}' \ + '-var prefix=g${{ github.run_id }}' \ + '-var tags={testing_job_id="${{ github.run_id }}"}' \ -auto-approve - name: Remove launchpad run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a destroy \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/200 \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_launchpad -a destroy \ + -var-folder ${GITHUB_WORKSPACE}/caf_launchpad/scenario/200 \ -level level0 \ -launchpad \ -parallelism=30 \ diff --git a/.github/workflows/landingzones-tf15.yml b/.github/workflows/landingzones-tf15.yml index ae7b915b6..8ac7dba27 100644 --- a/.github/workflows/landingzones-tf15.yml +++ b/.github/workflows/landingzones-tf15.yml @@ -4,10 +4,10 @@ # name: landingzones-tf15 - + on: schedule: - - cron: '0 0 * * *' + - cron: '0 3 * * *' env: TF_CLI_ARGS: '-no-color' @@ -45,8 +45,8 @@ jobs: - name: launchpad run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a apply \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/100 \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_launchpad -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_launchpad/scenario/100 \ -level level0 \ -launchpad \ -parallelism=30 \ @@ -57,10 +57,15 @@ jobs: - name: foundations run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a apply \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ - --environment ${{ github.run_id }} + --environment ${{ github.run_id }} \ + '-var random_length=${{ matrix.random_length }}' \ + '-var prefix=g${{ github.run_id }}' \ + '-var tags={testing_job_id="${{ github.run_id }}"}' networking100: name: networking-100 @@ -72,10 +77,10 @@ jobs: fail-fast: false matrix: config_files: [ - "caf_networking/scenario/100-single-region-hub", - "caf_networking/scenario/101-multi-region-hub", - "caf_networking/scenario/105-hub-and-spoke", - "caf_networking/scenario/106-hub-virtual-wan-firewall" + "caf_solution/scenario/networking/100-single-region-hub", + "caf_solution/scenario/networking/101-multi-region-hub", + "caf_solution/scenario/networking/105-hub-and-spoke", + "caf_solution/scenario/networking/106-hub-virtual-wan-firewall" ] container: @@ -92,20 +97,20 @@ jobs: - name: deploy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a apply \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a apply \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} - name: destroy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a destroy \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a destroy \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} \ -refresh=false \ -auto-approve @@ -138,8 +143,8 @@ jobs: - name: launchpad-200-upgrade run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a apply \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/200 \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_launchpad -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_launchpad/scenario/200 \ -level level0 \ -launchpad \ -parallelism=30 \ @@ -150,9 +155,15 @@ jobs: - name: foundations-200-upgrade run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a apply \ - -level level1 \ - --environment ${{ github.run_id }} + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -tfstate caf_foundations.tfstate \ + -level level1 \ + -parallelism=30 \ + --environment ${{ github.run_id }} \ + '-var random_length=${{ matrix.random_length }}' \ + '-var prefix=g${{ github.run_id }}' \ + '-var tags={testing_job_id="${{ github.run_id }}"}' networking200: name: networking-200 @@ -164,9 +175,9 @@ jobs: fail-fast: false matrix: config_files: [ - "caf_networking/scenario/200-single-region-hub", - "caf_networking/scenario/201-multi-region-hub", - "caf_networking/scenario/210-aks-private" + "caf_solution/scenario/networking/200-single-region-hub", + "caf_solution/scenario/networking/201-multi-region-hub", + "caf_solution/scenario/networking/210-aks-private" ] container: @@ -183,20 +194,20 @@ jobs: - name: deploy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a apply \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a apply \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} - name: destroy example run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_networking/ -a destroy \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution/ -a destroy \ -tfstate $(basename ${{ matrix.config_files }}).tfstate \ -level level2 \ -parallelism=30 \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/${{ matrix.config_files }} \ + -var-folder ${GITHUB_WORKSPACE}/${{ matrix.config_files }} \ --environment ${{ github.run_id }} \ -refresh=false \ -auto-approve @@ -228,16 +239,21 @@ jobs: - name: foundations run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_foundations -a destroy \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a destroy \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ + '-var random_length=${{ matrix.random_length }}' \ + '-var prefix=g${{ github.run_id }}' \ + '-var tags={testing_job_id="${{ github.run_id }}"}' \ -auto-approve - name: Remove launchpad run: | - /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/landingzones/caf_launchpad -a destroy \ - -var-folder ${GITHUB_WORKSPACE}/landingzones/caf_launchpad/scenario/200 \ + /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_launchpad -a destroy \ + -var-folder ${GITHUB_WORKSPACE}/caf_launchpad/scenario/200 \ -level level0 \ -launchpad \ -parallelism=30 \ diff --git a/README.md b/README.md index c77598245..92c17f5f7 100644 --- a/README.md +++ b/README.md @@ -22,29 +22,6 @@ Cloud Adoption Framework for Azure Terraform landing zones is an Open Source pro * Propose a prescriptive guidance on how to enable DevOps for infrastructure as code on Microsoft Azure. * Foster a community of Azure *Terraformers* using a common set of practices and sharing best practices. -## What's new in this release - -This release is relying extensively on Terraform 0.13 capabilities (module iterations, conditional modules, variables validation, etc.). - -Those new features allow more complex and more dynamic code composition. The following concepts are used: - -* **Multi-subscription deployment**: initial support to deploy landing zones in any subscription from the launchpad subscription. -* **Autonomous module consumption**: consumption of the CAF module outside of landing zones. -* **Starter kit extension**: added new scenarios for sandpit environment, added support for AKS. -* **Verified by Hashicorp status**: status achieved for new CAF module and provider. -* **No-code environment composition**: a landing zone environment can be composed customizing variable files and code must be robust enough to accommodate combinations and composition. -* **Flexible foundations to meet customer needs**: everything is customizable at all layers. -* **Key-based configuration and customization**: all configuration objects will call each other based on the object keys. -* **Iteration-based objects deployment**: a landing zone calls all its modules, iterating on complex objects for technical resources deployment. -* **Enterprise-scale support**: added support for foundations landing zones to optionally leverage Azure Enterprise-scale module. -* **Terraform Cloud/Enterprise bootstrap**: added initial support for Hashicorp Terraform Cloud/Enterprise to support environment bootstrap. - - - ## Getting started When starting an enterprise deployment, we recommend you start creating a configuration repository where you craft the configuration files for your environments. @@ -61,21 +38,19 @@ Currently we provide you with the following core sample landing zones: | Name | Level | Purpose | |--|--|--| -| [caf_launchpad](./landingzones/caf_launchpad) | 0 | provides the state management capabilities and security features leveraging Azure storage for the backend, provides secret management and modular approach to support plugin for Azure DevOps automated pipeline creation (and others) | -| [caf_foundations](./landingzones/caf_foundations) | 1 | setup all the fundamentals for a subscription (logging, accounting, security.). You can find all details of the caf_foundations landing zone [Here](./landingzones/caf_foundations/README.md) | -| [caf_shared_services](./landingzones/caf_shared_services) | 2 | provides shared services like monitoring, Azure Backup, Azure Site Recovery etc. | -| [caf_networking](./landingzones/caf_networking) | 2 | enables creation of any Azure networking combination of Virtual Networks-based hub-and-spoke topologies or Azure Virtual WAN based topologies. | -| [caf_solutions](./landingzones/caf_solutions) | 3 | "universal" landing zone that allow you to compose with any object from the CAF module and beyond. | +| [caf_launchpad](./caf_launchpad) | 0 | provides the state management capabilities and security features leveraging Azure storage for the backend, provides secret management and modular approach to support plugin for Azure DevOps automated pipeline creation (and others) | +| [caf_solution](./caf_solution) | 1-4 | "universal" landing zone that allow you to compose with any object from the CAF module and beyond. | ## Repositories | Repo | Description | |---------------------------------------------------------------------------------------------------|------------------------------------------------------------| +| [starter kit](https://github.com/azure/caf-terraform-landingzones-starter) | landing zones configuration repository | | [caf-terraform-landingzones](https://github.com/azure/caf-terraform-landingzones) (You are here!) | landing zones repo with sample and core documentations | | [rover](https://github.com/aztfmod/rover) | devops toolset for operating landing zones | | [azure_caf_provider](https://github.com/aztfmod/terraform-provider-azurecaf) | custom provider for naming conventions | -| [modules](https://registry.terraform.io/modules/aztfmod) | set of curated modules available in the Terraform registry | +| [module](https://github.com/aztfmod/terraform-azurerm-caf) | CAF universal module available in the Terraform registry | ## Community diff --git a/caf_launchpad/dynamic_secrets.tf b/caf_launchpad/dynamic_secrets.tf index 3b78eb1c8..a6f773359 100644 --- a/caf_launchpad/dynamic_secrets.tf +++ b/caf_launchpad/dynamic_secrets.tf @@ -1,6 +1,7 @@ module "dynamic_keyvault_secrets" { - source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=5.3.0_preview" + source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" + version = "~>5.3.0" for_each = try(var.dynamic_keyvault_secrets, {}) diff --git a/caf_launchpad/landingzone.tf b/caf_launchpad/landingzone.tf index fe36988d8..8c243a0ee 100644 --- a/caf_launchpad/landingzone.tf +++ b/caf_launchpad/landingzone.tf @@ -1,5 +1,6 @@ module "launchpad" { - source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git?ref=5.3.0_preview" + source = "aztfmod/caf/azurerm" + version = "~>5.3.0" azuread_api_permissions = var.azuread_api_permissions azuread_apps = var.azuread_apps diff --git a/caf_solution/dynamic_secrets.tf b/caf_solution/dynamic_secrets.tf index e5be79320..e429a40ce 100644 --- a/caf_solution/dynamic_secrets.tf +++ b/caf_solution/dynamic_secrets.tf @@ -1,5 +1,6 @@ module "dynamic_keyvault_secrets" { - source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git//modules/security/dynamic_keyvault_secrets?ref=5.3.0_preview" + source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" + version = "~>5.3.0" for_each = { for keyvault_key, secrets in try(var.dynamic_keyvault_secrets, {}) : keyvault_key => { diff --git a/caf_solution/landingzone.tf b/caf_solution/landingzone.tf index 5ab9912db..0763302b2 100644 --- a/caf_solution/landingzone.tf +++ b/caf_solution/landingzone.tf @@ -1,5 +1,6 @@ module "solution" { - source = "git::https://github.com/aztfmod/terraform-azurerm-caf.git?ref=5.3.0_preview" + source = "aztfmod/caf/azurerm" + version = "~>5.3.0" azuread_api_permissions = var.azuread_api_permissions azuread_apps = var.azuread_apps diff --git a/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars b/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars index 7269553e2..246be801c 100644 --- a/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars @@ -8,10 +8,6 @@ landingzone = { level = "lower" tfstate = "caf_foundations.tfstate" } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } } } diff --git a/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars b/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars index 26f860340..660ce5998 100644 --- a/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars @@ -8,10 +8,6 @@ landingzone = { level = "lower" tfstate = "caf_foundations.tfstate" } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } } } diff --git a/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars b/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars index b32be7ef7..dbf4f41ad 100644 --- a/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars +++ b/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars @@ -8,10 +8,6 @@ landingzone = { level = "lower" tfstate = "caf_foundations.tfstate" } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } } } diff --git a/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars index ea7eb6d12..0a7bd19f7 100644 --- a/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars +++ b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars @@ -8,10 +8,6 @@ landingzone = { level = "lower" tfstate = "caf_foundations.tfstate" } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } } } diff --git a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars index c06ac4c4b..13ebd6e9e 100644 --- a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars @@ -8,10 +8,6 @@ landingzone = { level = "lower" tfstate = "caf_foundations.tfstate" } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } } } diff --git a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars index 1e23636ed..c4ff585f5 100644 --- a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars @@ -8,10 +8,6 @@ landingzone = { level = "lower" tfstate = "caf_foundations.tfstate" } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } } } diff --git a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars index b264d5adc..1f7f2f2fb 100644 --- a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars +++ b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars @@ -8,10 +8,6 @@ landingzone = { level = "lower" tfstate = "caf_foundations.tfstate" } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } } } diff --git a/caf_solution/scenario/shared_services/100/configuration.tfvars b/caf_solution/scenario/shared_services/100/configuration.tfvars index 25489ff12..180c1175e 100644 --- a/caf_solution/scenario/shared_services/100/configuration.tfvars +++ b/caf_solution/scenario/shared_services/100/configuration.tfvars @@ -8,10 +8,6 @@ landingzone = { level = "lower" tfstate = "caf_foundations.tfstate" } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } } } diff --git a/caf_solution/scenario/shared_services/200/configuration.tfvars b/caf_solution/scenario/shared_services/200/configuration.tfvars index 0f8c8559c..dffaccf14 100644 --- a/caf_solution/scenario/shared_services/200/configuration.tfvars +++ b/caf_solution/scenario/shared_services/200/configuration.tfvars @@ -8,10 +8,6 @@ landingzone = { level = "lower" tfstate = "caf_foundations.tfstate" } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } } } From d2a6d6e6b19f38e0489473de10b80ebf94ca867e Mon Sep 17 00:00:00 2001 From: Arnaud Lheureux Date: Thu, 8 Apr 2021 10:18:55 +0000 Subject: [PATCH 33/38] Update pipelines --- .github/workflows/landingzones-tf13.yml | 6 ------ .github/workflows/landingzones-tf14.yml | 6 ------ .github/workflows/landingzones-tf15.yml | 8 +------- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/.github/workflows/landingzones-tf13.yml b/.github/workflows/landingzones-tf13.yml index a5144bb8f..fddcc5d97 100644 --- a/.github/workflows/landingzones-tf13.yml +++ b/.github/workflows/landingzones-tf13.yml @@ -63,8 +63,6 @@ jobs: -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ - '-var random_length=${{ matrix.random_length }}' \ - '-var prefix=g${{ github.run_id }}' \ '-var tags={testing_job_id="${{ github.run_id }}"}' networking100: @@ -161,8 +159,6 @@ jobs: -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ - '-var random_length=${{ matrix.random_length }}' \ - '-var prefix=g${{ github.run_id }}' \ '-var tags={testing_job_id="${{ github.run_id }}"}' networking200: @@ -245,8 +241,6 @@ jobs: -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ - '-var random_length=${{ matrix.random_length }}' \ - '-var prefix=g${{ github.run_id }}' \ '-var tags={testing_job_id="${{ github.run_id }}"}' \ -auto-approve diff --git a/.github/workflows/landingzones-tf14.yml b/.github/workflows/landingzones-tf14.yml index 1228a2c10..a30f60f08 100644 --- a/.github/workflows/landingzones-tf14.yml +++ b/.github/workflows/landingzones-tf14.yml @@ -75,8 +75,6 @@ jobs: -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ - '-var random_length=${{ matrix.random_length }}' \ - '-var prefix=g${{ github.run_id }}' \ '-var tags={testing_job_id="${{ github.run_id }}"}' networking100: @@ -173,8 +171,6 @@ jobs: -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ - '-var random_length=${{ matrix.random_length }}' \ - '-var prefix=g${{ github.run_id }}' \ '-var tags={testing_job_id="${{ github.run_id }}"}' networking200: @@ -257,8 +253,6 @@ jobs: -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ - '-var random_length=${{ matrix.random_length }}' \ - '-var prefix=g${{ github.run_id }}' \ '-var tags={testing_job_id="${{ github.run_id }}"}' \ -auto-approve diff --git a/.github/workflows/landingzones-tf15.yml b/.github/workflows/landingzones-tf15.yml index 8ac7dba27..e7a17f928 100644 --- a/.github/workflows/landingzones-tf15.yml +++ b/.github/workflows/landingzones-tf15.yml @@ -63,8 +63,6 @@ jobs: -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ - '-var random_length=${{ matrix.random_length }}' \ - '-var prefix=g${{ github.run_id }}' \ '-var tags={testing_job_id="${{ github.run_id }}"}' networking100: @@ -161,9 +159,7 @@ jobs: -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ - '-var random_length=${{ matrix.random_length }}' \ - '-var prefix=g${{ github.run_id }}' \ - '-var tags={testing_job_id="${{ github.run_id }}"}' + '-var tags={testing_job_id="${{ github.run_id }}"}' networking200: name: networking-200 @@ -245,8 +241,6 @@ jobs: -level level1 \ -parallelism=30 \ --environment ${{ github.run_id }} \ - '-var random_length=${{ matrix.random_length }}' \ - '-var prefix=g${{ github.run_id }}' \ '-var tags={testing_job_id="${{ github.run_id }}"}' \ -auto-approve From 40770b35383701cad06352589a8c773e60519779 Mon Sep 17 00:00:00 2001 From: Arnaud Lheureux Date: Thu, 8 Apr 2021 10:45:16 +0000 Subject: [PATCH 34/38] Update --- caf_solution/dynamic_secrets.tf | 2 +- .../configuration.tfvars | 4 +- .../101-multi-region-hub/configuration.tfvars | 4 +- .../105-hub-and-spoke/configuration.tfvars | 4 +- .../configuration.tfvars | 4 +- .../configuration.tfvars | 4 +- .../201-multi-region-hub/configuration.tfvars | 4 +- .../210-aks-private/configuration.tfvars | 4 +- .../shared_services/100/configuration.tfvars | 4 +- .../shared_services/200/configuration.tfvars | 4 +- landingzones.old/caf_eslz/README.md | 44 - landingzones.old/caf_eslz/backend.azurerm | 4 - landingzones.old/caf_eslz/es_main.tf | 25 - landingzones.old/caf_eslz/landingzone.tf | 21 - .../caf_eslz/locals.remote_tfstates.tf | 78 -- landingzones.old/caf_eslz/main.tf | 63 -- landingzones.old/caf_eslz/output.tf | 30 - .../100/enterprise_scale_contoso_com.tfvars | 25 - .../200/enterprise_scale_contoso_com.tfvars | 45 - ...chetype_definition_es_management.tmpl.json | 12 - .../200/lib/archetype_definition_es_root.json | 13 - ...nt_es_allowed_resource-locations.tmpl.json | 28 - ..._allowed_resourcegroup-locations.tmpl.json | 28 - ...licy_assignment_es_deploy_asc_ce.tmpl.json | 28 - ...ignment_es_deploy_asc_monitoring.tmpl.json | 88 -- ...ssignment_es_deploy_asc_standard.tmpl.json | 21 - ...nment_es_deploy_diag_activitylog.tmpl.json | 25 - ...ment_es_deploy_diag_loganalytics.tmpl.json | 25 - ...icy_definition_es_deploy_asc_standard.json | 284 ------- landingzones.old/caf_eslz/variables.tf | 83 -- landingzones.old/caf_foundations/README.md | 32 - .../caf_foundations/backend.azurerm | 4 - .../caf_foundations/dynamic_secrets.tf | 11 - .../caf_foundations/landingzone.tf | 30 - .../caf_foundations/locals.remote_tfstates.tf | 92 --- landingzones.old/caf_foundations/main.tf | 63 -- landingzones.old/caf_foundations/output.tf | 39 - landingzones.old/caf_foundations/variables.tf | 112 --- .../add-ons/azure_devops/azdo.tf | 15 - .../add-ons/azure_devops/azdo_agent_pools.tf | 52 -- .../add-ons/azure_devops/azdo_pipelines.tf | 43 - .../azure_devops/azdo_service_endpoint.tf | 36 - .../azure_devops/azdo_variable_groups.tf | 39 - .../add-ons/azure_devops/backend.azurerm | 4 - .../documentation/images/pat_token.png | Bin 78143 -> 0 bytes .../azure_devops/locals.remote_tfstates.tf | 76 -- .../add-ons/azure_devops/main.tf | 69 -- .../add-ons/azure_devops/output.tf | 6 - .../add-ons/azure_devops/readme.md | 60 -- .../200-contoso_demo/azure_devops.tfvars | 232 ------ .../200-contoso_demo/configurations.tfvars | 123 --- .../200-contoso_demo/pipeline/rover.yaml | 70 -- .../add-ons/azure_devops/solution.tf | 36 - .../add-ons/azure_devops/variables.tf | 102 --- .../azure_devops_agent/backend.azurerm | 4 - .../azure_devops_agent/dynamic_secrets.tf | 11 - .../extensions/devops_selfhosted_agent.tf | 44 - .../extensions/variables.tf | 3 - .../locals.current_tfstates.tf | 74 -- .../add-ons/azure_devops_agent/main.tf | 69 -- .../add-ons/azure_devops_agent/output.tf | 34 - .../add-ons/azure_devops_agent/readme.md | 54 -- .../level0/configuration.tfvars | 64 -- .../200-contoso_demo/level0/keyvaults.tfvars | 28 - .../level0/storage_accounts.tfvars | 42 - .../level0/virtual_machines.tfvars | 79 -- .../level1/configuration.tfvars | 68 -- .../200-contoso_demo/level1/keyvaults.tfvars | 32 - .../level1/storage_accounts.tfvars | 42 - .../level1/virtual_machines.tfvars | 77 -- .../cloud-init-install-rover-tools.config | 117 --- .../scripts/devops_runtime_baremetal.sh | 109 --- .../scripts/devops_runtime_docker.sh | 29 - .../add-ons/azure_devops_agent/solution.tf | 37 - .../add-ons/azure_devops_agent/variables.tf | 102 --- .../vm_extention_devops_agent.tf | 37 - .../terraform_cloud/example/tfc.tfvars | 25 - .../add-ons/terraform_cloud/main.tf | 51 -- .../add-ons/terraform_cloud/readme.md | 44 - .../terraform_cloud/terraform_cloud.tf | 83 -- .../add-ons/terraform_cloud/variables.tf | 85 -- .../caf_launchpad/backend.azurerm | 4 - .../documentation/img/launchpad-100.PNG | Bin 143702 -> 0 bytes .../documentation/img/launchpad-200.png | Bin 232335 -> 0 bytes .../documentation/img/launchpad_workflow.png | Bin 40149 -> 0 bytes .../caf_launchpad/documentation/variables.md | 41 - .../caf_launchpad/dynamic_secrets.tf | 11 - landingzones.old/caf_launchpad/landingzone.tf | 48 -- landingzones.old/caf_launchpad/main.tf | 99 --- landingzones.old/caf_launchpad/output.tf | 66 -- landingzones.old/caf_launchpad/readme.md | 206 ----- .../caf_launchpad/scenario/100/README.md | 44 - .../scenario/100/configuration.tfvars | 68 -- .../scenario/100/dynamic_secrets.tfvars | 114 --- .../scenario/100/iam_role_mapping.tfvars | 47 -- .../scenario/100/keyvaults.tfvars | 99 --- .../scenario/100/storage_accounts.tfvars | 102 --- .../caf_launchpad/scenario/200/compute.tfvars | 100 --- .../scenario/200/configuration.tfvars | 100 --- .../diagnostic_event_hub_namespaces.tfvars | 20 - .../200/diagnostic_log_analytics.tfvars | 48 -- .../200/diagnostic_storage_accounts.tfvars | 64 -- .../200/diagnostics_definition.tfvars | 274 ------- .../200/diagnostics_destinations.tfvars | 31 - .../scenario/200/dynamic_secrets.tfvars | 152 ---- .../scenario/200/iam_azuread.tfvars | 184 ----- .../200/iam_azuread_api_permissions.tfvars | 43 - .../scenario/200/iam_custom_roles.tfvars | 76 -- .../scenario/200/iam_keyvault_policies.tfvars | 114 --- .../200/iam_managed_identities.tfvars | 32 - .../scenario/200/iam_role_mapping.tfvars | 154 ---- .../scenario/200/keyvaults.tfvars | 204 ----- .../scenario/200/networking.tfvars | 110 --- .../200/networking_nsg_definition.tfvars | 141 ---- .../caf_launchpad/scenario/200/readme.md | 56 -- .../scenario/200/storage_accounts.tfvars | 101 --- .../scenario/200/subscriptions.tfvars | 20 - .../cloud-init-install-rover-tools.config | 49 -- .../caf_launchpad/scripts/grant_consent.sh | 28 - landingzones.old/caf_launchpad/variables.tf | 191 ----- .../caf_networking/backend.azurerm | 4 - .../img/100-single-region-hub.png | Bin 17963 -> 0 bytes .../img/101-multi-region-hub.png | Bin 42683 -> 0 bytes .../documentation/img/105-hub-and-spoke.png | Bin 27518 -> 0 bytes .../img/106-hub-virtual-wan-firewall.png | Bin 49613 -> 0 bytes .../caf_networking/landingzone.tf | 62 -- .../caf_networking/locals.remote_tfstates.tf | 91 --- landingzones.old/caf_networking/main.tf | 66 -- landingzones.old/caf_networking/output.tf | 58 -- landingzones.old/caf_networking/readme.md | 45 - .../configuration.tfvars | 62 -- .../network_security_group_definition.tfvars | 327 -------- .../scenario/100-single-region-hub/readme.md | 45 - .../101-multi-region-hub/configuration.tfvars | 27 - .../network_security_group_definition.tfvars | 344 -------- .../101-multi-region-hub/peering.tfvars | 31 - .../scenario/101-multi-region-hub/readme.md | 50 -- .../virtual_networks.tfvars | 78 -- .../105-hub-and-spoke/configuration.tfvars | 155 ---- .../network_security_group_definition.tfvars | 122 --- .../scenario/105-hub-and-spoke/readme.md | 52 -- .../configuration.tfvars | 71 -- .../network_security_group_definition.tfvars | 104 --- .../106-hub-virtual-wan-firewall/readme.md | 47 -- .../virtual_wan.tfvars | 84 -- .../configuration.tfvars | 612 -------------- .../201-multi-region-hub/configuration.tfvars | 767 ----------------- .../210-aks-private/configuration.tfvars | 772 ------------------ .../peerings/launchpad/configuration.tfvars | 41 - landingzones.old/caf_networking/variables.tf | 147 ---- .../caf_shared_services/backend.azurerm | 4 - .../caf_shared_services/landingzone.tf | 30 - .../locals.remote_tfstates.tf | 65 -- landingzones.old/caf_shared_services/main.tf | 66 -- .../caf_shared_services/output.tf | 29 - .../caf_shared_services/readme.md | 40 - .../scenario/100/configuration.tfvars | 140 ---- .../scenario/200/configuration.tfvars | 156 ---- .../caf_shared_services/variables.tf | 71 -- .../caf_shared_services/vm_extensions.tf | 42 - .../add-ons/aks_applications/app/main.tf | 7 - .../add-ons/aks_applications/app/module.tf | 48 -- .../add-ons/aks_applications/app/output.tf | 0 .../add-ons/aks_applications/app/variables.tf | 5 - .../add-ons/aks_applications/applications.tf | 27 - .../add-ons/aks_applications/backend.azurerm | 4 - .../locals.remote_tfstates.tf | 54 -- .../add-ons/aks_applications/main.tf | 75 -- .../add-ons/aks_applications/output.tf | 0 .../add-ons/aks_applications/variables.tf | 36 - .../add-ons/databricks/backend.azurerm | 4 - .../add-ons/databricks/databricks.tf | 21 - .../databricks/locals.remote_tfstates.tf | 43 - .../caf_solutions/add-ons/databricks/main.tf | 63 -- .../add-ons/databricks/variables.tf | 115 --- .../caf_solutions/backend.azurerm | 4 - .../caf_solutions/dynamic_secrets.tf | 10 - landingzones.old/caf_solutions/landingzone.tf | 139 ---- .../caf_solutions/locals.remote_tfstates.tf | 158 ---- landingzones.old/caf_solutions/main.tf | 70 -- .../modules/databricks/cluster.tf | 26 - .../modules/databricks/instance_pool.tf | 0 .../caf_solutions/modules/databricks/main.tf | 9 - .../modules/databricks/output.tf | 9 - .../modules/databricks/variables.tf | 4 - landingzones.old/caf_solutions/output.tf | 114 --- landingzones.old/caf_solutions/readme.md | 22 - .../cloud-init-install-rover-tools.config | 119 --- landingzones.old/caf_solutions/variables.tf | 272 ------ 189 files changed, 19 insertions(+), 13385 deletions(-) delete mode 100644 landingzones.old/caf_eslz/README.md delete mode 100644 landingzones.old/caf_eslz/backend.azurerm delete mode 100644 landingzones.old/caf_eslz/es_main.tf delete mode 100644 landingzones.old/caf_eslz/landingzone.tf delete mode 100644 landingzones.old/caf_eslz/locals.remote_tfstates.tf delete mode 100644 landingzones.old/caf_eslz/main.tf delete mode 100644 landingzones.old/caf_eslz/output.tf delete mode 100644 landingzones.old/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars delete mode 100644 landingzones.old/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_root.json delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json delete mode 100644 landingzones.old/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json delete mode 100644 landingzones.old/caf_eslz/variables.tf delete mode 100644 landingzones.old/caf_foundations/README.md delete mode 100644 landingzones.old/caf_foundations/backend.azurerm delete mode 100644 landingzones.old/caf_foundations/dynamic_secrets.tf delete mode 100644 landingzones.old/caf_foundations/landingzone.tf delete mode 100644 landingzones.old/caf_foundations/locals.remote_tfstates.tf delete mode 100644 landingzones.old/caf_foundations/main.tf delete mode 100644 landingzones.old/caf_foundations/output.tf delete mode 100644 landingzones.old/caf_foundations/variables.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/azdo.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_agent_pools.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_pipelines.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_service_endpoint.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_variable_groups.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/backend.azurerm delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/documentation/images/pat_token.png delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/locals.remote_tfstates.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/readme.md delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/solution.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/backend.azurerm delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/locals.current_tfstates.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/readme.md delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/solution.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars delete mode 100644 landingzones.old/caf_launchpad/add-ons/terraform_cloud/main.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/terraform_cloud/readme.md delete mode 100644 landingzones.old/caf_launchpad/add-ons/terraform_cloud/terraform_cloud.tf delete mode 100644 landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf delete mode 100644 landingzones.old/caf_launchpad/backend.azurerm delete mode 100644 landingzones.old/caf_launchpad/documentation/img/launchpad-100.PNG delete mode 100644 landingzones.old/caf_launchpad/documentation/img/launchpad-200.png delete mode 100644 landingzones.old/caf_launchpad/documentation/img/launchpad_workflow.png delete mode 100644 landingzones.old/caf_launchpad/documentation/variables.md delete mode 100644 landingzones.old/caf_launchpad/dynamic_secrets.tf delete mode 100644 landingzones.old/caf_launchpad/landingzone.tf delete mode 100644 landingzones.old/caf_launchpad/main.tf delete mode 100644 landingzones.old/caf_launchpad/output.tf delete mode 100644 landingzones.old/caf_launchpad/readme.md delete mode 100644 landingzones.old/caf_launchpad/scenario/100/README.md delete mode 100644 landingzones.old/caf_launchpad/scenario/100/configuration.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/100/dynamic_secrets.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/100/iam_role_mapping.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/100/keyvaults.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/100/storage_accounts.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/compute.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/configuration.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostics_definition.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/diagnostics_destinations.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/dynamic_secrets.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_azuread.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_custom_roles.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_managed_identities.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/iam_role_mapping.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/keyvaults.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/networking.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/networking_nsg_definition.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/readme.md delete mode 100644 landingzones.old/caf_launchpad/scenario/200/storage_accounts.tfvars delete mode 100644 landingzones.old/caf_launchpad/scenario/200/subscriptions.tfvars delete mode 100644 landingzones.old/caf_launchpad/scripts/cloud-init-install-rover-tools.config delete mode 100644 landingzones.old/caf_launchpad/scripts/grant_consent.sh delete mode 100644 landingzones.old/caf_launchpad/variables.tf delete mode 100644 landingzones.old/caf_networking/backend.azurerm delete mode 100644 landingzones.old/caf_networking/documentation/img/100-single-region-hub.png delete mode 100644 landingzones.old/caf_networking/documentation/img/101-multi-region-hub.png delete mode 100644 landingzones.old/caf_networking/documentation/img/105-hub-and-spoke.png delete mode 100644 landingzones.old/caf_networking/documentation/img/106-hub-virtual-wan-firewall.png delete mode 100644 landingzones.old/caf_networking/landingzone.tf delete mode 100644 landingzones.old/caf_networking/locals.remote_tfstates.tf delete mode 100644 landingzones.old/caf_networking/main.tf delete mode 100644 landingzones.old/caf_networking/output.tf delete mode 100644 landingzones.old/caf_networking/readme.md delete mode 100644 landingzones.old/caf_networking/scenario/100-single-region-hub/configuration.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/100-single-region-hub/network_security_group_definition.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/100-single-region-hub/readme.md delete mode 100644 landingzones.old/caf_networking/scenario/101-multi-region-hub/configuration.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/101-multi-region-hub/network_security_group_definition.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/101-multi-region-hub/peering.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/101-multi-region-hub/readme.md delete mode 100644 landingzones.old/caf_networking/scenario/101-multi-region-hub/virtual_networks.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/105-hub-and-spoke/configuration.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/105-hub-and-spoke/network_security_group_definition.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/105-hub-and-spoke/readme.md delete mode 100644 landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/readme.md delete mode 100644 landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/virtual_wan.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/200-single-region-hub/configuration.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/201-multi-region-hub/configuration.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/210-aks-private/configuration.tfvars delete mode 100644 landingzones.old/caf_networking/scenario/210-aks-private/peerings/launchpad/configuration.tfvars delete mode 100644 landingzones.old/caf_networking/variables.tf delete mode 100644 landingzones.old/caf_shared_services/backend.azurerm delete mode 100644 landingzones.old/caf_shared_services/landingzone.tf delete mode 100644 landingzones.old/caf_shared_services/locals.remote_tfstates.tf delete mode 100644 landingzones.old/caf_shared_services/main.tf delete mode 100644 landingzones.old/caf_shared_services/output.tf delete mode 100644 landingzones.old/caf_shared_services/readme.md delete mode 100644 landingzones.old/caf_shared_services/scenario/100/configuration.tfvars delete mode 100644 landingzones.old/caf_shared_services/scenario/200/configuration.tfvars delete mode 100644 landingzones.old/caf_shared_services/variables.tf delete mode 100644 landingzones.old/caf_shared_services/vm_extensions.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/app/main.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/app/module.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/app/output.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/applications.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/backend.azurerm delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/locals.remote_tfstates.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/main.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/output.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/databricks/backend.azurerm delete mode 100644 landingzones.old/caf_solutions/add-ons/databricks/databricks.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/databricks/locals.remote_tfstates.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/databricks/main.tf delete mode 100644 landingzones.old/caf_solutions/add-ons/databricks/variables.tf delete mode 100644 landingzones.old/caf_solutions/backend.azurerm delete mode 100644 landingzones.old/caf_solutions/dynamic_secrets.tf delete mode 100644 landingzones.old/caf_solutions/landingzone.tf delete mode 100644 landingzones.old/caf_solutions/locals.remote_tfstates.tf delete mode 100644 landingzones.old/caf_solutions/main.tf delete mode 100644 landingzones.old/caf_solutions/modules/databricks/cluster.tf delete mode 100644 landingzones.old/caf_solutions/modules/databricks/instance_pool.tf delete mode 100644 landingzones.old/caf_solutions/modules/databricks/main.tf delete mode 100644 landingzones.old/caf_solutions/modules/databricks/output.tf delete mode 100644 landingzones.old/caf_solutions/modules/databricks/variables.tf delete mode 100644 landingzones.old/caf_solutions/output.tf delete mode 100644 landingzones.old/caf_solutions/readme.md delete mode 100644 landingzones.old/caf_solutions/scripts/cloud-init-install-rover-tools.config delete mode 100644 landingzones.old/caf_solutions/variables.tf diff --git a/caf_solution/dynamic_secrets.tf b/caf_solution/dynamic_secrets.tf index e429a40ce..54558fa00 100644 --- a/caf_solution/dynamic_secrets.tf +++ b/caf_solution/dynamic_secrets.tf @@ -2,7 +2,7 @@ module "dynamic_keyvault_secrets" { source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" version = "~>5.3.0" - for_each = { + for_each = { for keyvault_key, secrets in try(var.dynamic_keyvault_secrets, {}) : keyvault_key => { for key, value in secrets : key => value if try(value.value, null) == null diff --git a/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars b/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars index 246be801c..b20b85509 100644 --- a/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/100-single-region-hub/configuration.tfvars @@ -1,10 +1,10 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "foundations" + global_settings_key = "caf_foundations" level = "level2" key = "networking_hub" tfstates = { - foundations = { + caf_foundations = { level = "lower" tfstate = "caf_foundations.tfstate" } diff --git a/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars b/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars index 660ce5998..654a1bfe1 100644 --- a/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/101-multi-region-hub/configuration.tfvars @@ -1,10 +1,10 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "foundations" + global_settings_key = "caf_foundations" level = "level2" key = "networking_hub" tfstates = { - foundations = { + caf_foundations = { level = "lower" tfstate = "caf_foundations.tfstate" } diff --git a/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars b/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars index dbf4f41ad..fdb98ad03 100644 --- a/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars +++ b/caf_solution/scenario/networking/105-hub-and-spoke/configuration.tfvars @@ -1,10 +1,10 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "foundations" + global_settings_key = "caf_foundations" level = "level2" key = "networking_hub" tfstates = { - foundations = { + caf_foundations = { level = "lower" tfstate = "caf_foundations.tfstate" } diff --git a/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars index 0a7bd19f7..6383a2dde 100644 --- a/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars +++ b/caf_solution/scenario/networking/106-hub-virtual-wan-firewall/configuration.tfvars @@ -1,10 +1,10 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "foundations" + global_settings_key = "caf_foundations" level = "level2" key = "networking_hub" tfstates = { - foundations = { + caf_foundations = { level = "lower" tfstate = "caf_foundations.tfstate" } diff --git a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars index 13ebd6e9e..4b1e28f4b 100644 --- a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars @@ -1,10 +1,10 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "foundations" + global_settings_key = "caf_foundations" level = "level2" key = "networking_hub" tfstates = { - foundations = { + caf_foundations = { level = "lower" tfstate = "caf_foundations.tfstate" } diff --git a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars index c4ff585f5..434bb720c 100644 --- a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars @@ -1,10 +1,10 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "foundations" + global_settings_key = "caf_foundations" level = "level2" key = "networking_hub" tfstates = { - foundations = { + caf_foundations = { level = "lower" tfstate = "caf_foundations.tfstate" } diff --git a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars index 1f7f2f2fb..140f47831 100644 --- a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars +++ b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars @@ -1,10 +1,10 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "foundations" + global_settings_key = "caf_foundations" level = "level2" key = "networking_hub" tfstates = { - foundations = { + caf_foundations = { level = "lower" tfstate = "caf_foundations.tfstate" } diff --git a/caf_solution/scenario/shared_services/100/configuration.tfvars b/caf_solution/scenario/shared_services/100/configuration.tfvars index 180c1175e..c99d0e73a 100644 --- a/caf_solution/scenario/shared_services/100/configuration.tfvars +++ b/caf_solution/scenario/shared_services/100/configuration.tfvars @@ -1,10 +1,10 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "foundations" + global_settings_key = "caf_foundations" level = "level2" key = "shared_services" tfstates = { - foundations = { + caf_foundations = { level = "lower" tfstate = "caf_foundations.tfstate" } diff --git a/caf_solution/scenario/shared_services/200/configuration.tfvars b/caf_solution/scenario/shared_services/200/configuration.tfvars index dffaccf14..83b977838 100644 --- a/caf_solution/scenario/shared_services/200/configuration.tfvars +++ b/caf_solution/scenario/shared_services/200/configuration.tfvars @@ -1,10 +1,10 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "foundations" + global_settings_key = "caf_foundations" level = "level2" key = "shared_services" tfstates = { - foundations = { + caf_foundations = { level = "lower" tfstate = "caf_foundations.tfstate" } diff --git a/landingzones.old/caf_eslz/README.md b/landingzones.old/caf_eslz/README.md deleted file mode 100644 index afef4f046..000000000 --- a/landingzones.old/caf_eslz/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Enterprise-Scale - -The foundations landing zone allows you to manage the core components of an environment: - -* Management groups -* Policies - -Foundations landing zone operates at **level 1**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -
- -## Components - -CAF eslz leverages the enterprise-scale module in order to deploy its core components. - -For full description on enterprise_scale module usage, please [refer to the repository](https://github.com/Azure/terraform-azurerm-caf-enterprise-scale) - -This is currently work in progress. -Use the following configuration file in order to get started with the enterprise-scale module integration: - -```bash -# This example will setup the complete enterprise-scale fundamentals management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription - -rover -lz /tf/caf/public/landingzones/caf_eslz \ - -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/100 \ - -level level1 \ - -a [plan|apply|destroy] - -# This example will setup custom enterprise-scale management groups and policies. Please make sure you have appropriate privileges on the tenant and subscription - -rover -lz /tf/caf/public/landingzones/caf_eslz \ - -var-folder /tf/caf/public/landingzones/caf_eslz/scenario/200 \ - -level level1 \ - -a [plan|apply|destroy] - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/public/landingzones/caf_eslz \ - -tfstate_subscription_id \ - -var-folder /tf/caf/public/landingzones/caf_foundations/scenario/200 \ - -level level1 \ - -a apply -``` diff --git a/landingzones.old/caf_eslz/backend.azurerm b/landingzones.old/caf_eslz/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones.old/caf_eslz/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones.old/caf_eslz/es_main.tf b/landingzones.old/caf_eslz/es_main.tf deleted file mode 100644 index 45ced3fc9..000000000 --- a/landingzones.old/caf_eslz/es_main.tf +++ /dev/null @@ -1,25 +0,0 @@ -# For full description on enterprise_scale module usage, please refer to https://github.com/Azure/terraform-azurerm-caf-enterprise-scale - -module "enterprise_scale" { - source = "Azure/caf-enterprise-scale/azurerm" - version = "0.0.8" - - root_parent_id = data.azurerm_client_config.current.tenant_id - - root_id = try(var.enterprise_scale.root_id, "es") - root_name = try(var.enterprise_scale.root_name, "Enterprise-Scale") - deploy_core_landing_zones = try(var.enterprise_scale.deploy_core_landing_zones, false) - - # Control whether to deploy the demo landing zones // default = false - deploy_demo_landing_zones = try(var.enterprise_scale.deploy_demo_landing_zones, false) - - # Set a path for the custom archetype library path - library_path = try(format("%s", var.enterprise_scale.library_path), "") - - # Deploys the custom landing zone configuration as defined in config file - custom_landing_zones = try(var.enterprise_scale.custom_landing_zones, {}) - subscription_id_overrides = try(var.enterprise_scale.subscription_id_overrides, {}) - archetype_config_overrides = try(var.enterprise_scale.archetype_config_overrides, {}) - - default_location = local.global_settings.regions[local.global_settings.default_region] -} \ No newline at end of file diff --git a/landingzones.old/caf_eslz/landingzone.tf b/landingzones.old/caf_eslz/landingzone.tf deleted file mode 100644 index b12b48a6c..000000000 --- a/landingzones.old/caf_eslz/landingzone.tf +++ /dev/null @@ -1,21 +0,0 @@ -module "foundations" { - # source = "/tf/caf/aztfmod" - source = "aztfmod/caf/azurerm" - version = "~>5.2.0" - - current_landingzone_key = var.landingzone.key - tenant_id = var.tenant_id - tags = local.tags - diagnostics = local.remote.diagnostics - global_settings = local.global_settings - tfstates = local.tfstates - diagnostics_definition = var.diagnostics_definition - diagnostics_destinations = var.diagnostics_destinations - diagnostic_storage_accounts = var.diagnostic_storage_accounts - logged_user_objectId = var.logged_user_objectId - logged_aad_app_objectId = var.logged_aad_app_objectId - resource_groups = var.resource_groups - keyvaults = var.keyvaults - log_analytics = var.log_analytics - event_hub_namespaces = var.event_hub_namespaces -} diff --git a/landingzones.old/caf_eslz/locals.remote_tfstates.tf b/landingzones.old/caf_eslz/locals.remote_tfstates.tf deleted file mode 100644 index 27fa9da3c..000000000 --- a/landingzones.old/caf_eslz/locals.remote_tfstates.tf +++ /dev/null @@ -1,78 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(var.tags, local.landingzone_tag, local.global_settings.tags, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - - remote = { - diagnostics = { - # Get the diagnostics settings of services to create - diagnostic_event_hub_namespaces = var.diagnostic_event_hub_namespaces - diagnostic_log_analytics = var.diagnostic_log_analytics - diagnostic_storage_accounts = var.diagnostic_storage_accounts - - # Combine the diagnostics definitions - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = { - event_hub_namespaces = merge( - try(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations.event_hub_namespaces, {}), - try(var.diagnostics_destinations.event_hub_namespaces, {}) - ) - log_analytics = merge( - try(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations.log_analytics, {}), - try(var.diagnostics_destinations.log_analytics, {}) - ) - storage = merge( - try(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations.storage, {}), - try(var.diagnostics_destinations.storage, {}) - ) - } - # Get the remote existing diagnostics objects - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.event_hub_namespaces - } - - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) - } - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) - } - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) - } - } -} diff --git a/landingzones.old/caf_eslz/main.tf b/landingzones.old/caf_eslz/main.tf deleted file mode 100644 index b3f105bee..000000000 --- a/landingzones.old/caf_eslz/main.tf +++ /dev/null @@ -1,63 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} -data "azurerm_subscription" "current" {} - -locals { - - # Update the tfstates map - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} - diff --git a/landingzones.old/caf_eslz/output.tf b/landingzones.old/caf_eslz/output.tf deleted file mode 100644 index 915837487..000000000 --- a/landingzones.old/caf_eslz/output.tf +++ /dev/null @@ -1,30 +0,0 @@ -output "global_settings" { - value = local.global_settings - sensitive = true -} -output "diagnostics" { - value = module.foundations.diagnostics - sensitive = true -} -output "vnets" { - value = local.remote.vnets - sensitive = true -} -output "managed_identities" { - value = local.remote.managed_identities - sensitive = true -} -output "azuread_groups" { - value = local.remote.azuread_groups - sensitive = true -} -output "tfstates" { - value = local.tfstates - sensitive = true -} -output "keyvaults" { - value = tomap({ - (var.landingzone.key) = try(module.foundations.keyvaults, {}) - }) - sensitive = true -} diff --git a/landingzones.old/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars b/landingzones.old/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars deleted file mode 100644 index 89e2ea1fd..000000000 --- a/landingzones.old/caf_eslz/scenario/100/enterprise_scale_contoso_com.tfvars +++ /dev/null @@ -1,25 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "caf_eslz" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } -} - -enterprise_scale = { - # Define a custom ID to use for the root Management Group - # Also used as a prefix for all core Management Group IDs - # root_id = "caf" - # root_name = "CAF-RootManagementGroup" - - # Control whether to deploy the default core landing zones // default = true - deploy_core_landing_zones = true - - # Control whether to deploy the demo landing zones // default = false - deploy_demo_landing_zones = false -} \ No newline at end of file diff --git a/landingzones.old/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars b/landingzones.old/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars deleted file mode 100644 index 73c92cb7f..000000000 --- a/landingzones.old/caf_eslz/scenario/200/enterprise_scale_contoso_com.tfvars +++ /dev/null @@ -1,45 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "caf_foundations" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } -} - -enterprise_scale = { - #path to the policies definition and assignment repo - library_path = "/tf/caf/public/landingzones/caf_eslz/scenario/200/lib" - - #management groups hierarchy configuration - custom_landing_zones = { - caf = { - display_name = "CAF-RootManagementGroup" - parent_management_group_id = "" - subscription_ids = [] - archetype_config = { - archetype_id = "es_root" - parameters = {} - access_control = {} - } - } - child-caf = { - display_name = "CAF-ChildManagementGroup" - parent_management_group_id = "caf" - subscription_ids = [] - archetype_config = { - archetype_id = "es_management" - parameters = { - ES-Deploy-ForwardDiagLog = { - logAnalytics = "central_logs_region1" - } - } - access_control = {} - } - } - } -} \ No newline at end of file diff --git a/landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json deleted file mode 100644 index e6d18b5db..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_management.tmpl.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "es_management": { - "policy_assignments": [ - "ES-Deploy-ASC-Standard" - ], - "policy_definitions": [ - ], - "policy_set_definitions": [], - "role_assignments": [], - "role_definitions": [] - } -} \ No newline at end of file diff --git a/landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_root.json b/landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_root.json deleted file mode 100644 index e41b04f6f..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/archetype_definition_es_root.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "es_root": { - "policy_assignments": [ - "ES-Deploy-ASC-Standard" - ], - "policy_definitions": [ - "ES-Deploy-ASC-Standard" - ], - "policy_set_definitions": [], - "role_assignments": [], - "role_definitions": [] - } -} \ No newline at end of file diff --git a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json deleted file mode 100644 index ae28ea455..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resource-locations.tmpl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "ES-Allowed-Locations", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Specifies the allowed locations (regions) where resources can be deployed", - "displayName": "ES-Allowed-Resource-Locations", - "notScopes": [], - "parameters": { - "listOfAllowedLocations": { - "value": [ - "uksouth", - "ukwest" - ] - } - }, - "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "None" - } -} diff --git a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json deleted file mode 100644 index b00174588..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_allowed_resourcegroup-locations.tmpl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "ES-Allowed-RSG-Locations", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Specifies the allowed locations (regions) where Resource Groups can be deployed", - "displayName": "ES-Allowed-ResourceGroup-Locations", - "notScopes": [], - "parameters": { - "listOfAllowedLocations": { - "value": [ - "uksouth", - "ukwest" - ] - } - }, - "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "None" - } -} diff --git a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json deleted file mode 100644 index 4417b6a01..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_ce.tmpl.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "ES-Deploy-ASC-ContExport", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Deploy ASC Continuous Export To Log Analytics Workspace.", - "displayName": "ES-Deploy-ASC-ContinuousExportToWorkspace", - "notScopes": [], - "parameters": { - "resourceGroupLocation": { - "value": null - }, - "workspaceResourceId": { - "value": null - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-ContinuousExportToWorkspace", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json deleted file mode 100644 index ba6d2186f..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_monitoring.tmpl.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "name": "ES-Deploy-ASC-Monitoring", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Enable Monitoring in Azure Security Center.", - "displayName": "ES-Deploy-ASC-Monitoring", - "notScopes": [], - "parameters": { - "aadAuthenticationInSqlServerMonitoringEffect": { - "value": "Disabled" - }, - "diskEncryptionMonitoringEffect": { - "value": "Disabled" - }, - "encryptionOfAutomationAccountMonitoringEffect": { - "value": "Disabled" - }, - "identityDesignateLessThanOwnersMonitoringEffect": { - "value": "Disabled" - }, - "identityDesignateMoreThanOneOwnerMonitoringEffect": { - "value": "Disabled" - }, - "identityEnableMFAForWritePermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveDeprecatedAccountMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveDeprecatedAccountWithOwnerPermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveExternalAccountWithOwnerPermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveExternalAccountWithReadPermissionsMonitoringEffect": { - "value": "Disabled" - }, - "identityRemoveExternalAccountWithWritePermissionsMonitoringEffect": { - "value": "Disabled" - }, - "jitNetworkAccessMonitoringEffect": { - "value": "Disabled" - }, - "networkSecurityGroupsOnSubnetsMonitoringEffect": { - "value": "AuditIfNotExists" - }, - "sqlDbEncryptionMonitoringEffect": { - "value": "Disabled" - }, - "sqlManagedInstanceAdvancedDataSecurityEmailAdminsMonitoringEffect": { - "value": "Disabled" - }, - "sqlManagedInstanceAdvancedDataSecurityEmailsMonitoringEffect": { - "value": "Disabled" - }, - "sqlServerAdvancedDataSecurityEmailAdminsMonitoringEffect": { - "value": "Disabled" - }, - "sqlServerAdvancedDataSecurityMonitoringEffect": { - "value": "Disabled" - }, - "systemUpdatesMonitoringEffect": { - "value": "Disabled" - }, - "useRbacRulesMonitoringEffect": { - "value": "Disabled" - }, - "vmssSystemUpdatesMonitoringEffect": { - "value": "Disabled" - }, - "windowsDefenderExploitGuardMonitoringEffect": { - "value": "Disabled" - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json deleted file mode 100644 index 1786a9c39..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_asc_standard.tmpl.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "ES-Deploy-ASC-Standard", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Deploy Azure Security Center Standard Tier.", - "displayName": "ES-Deploy-ASC-Standard", - "notScopes": [], - "parameters": {}, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-ASC-Standard", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json deleted file mode 100644 index 7bf367af8..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_activitylog.tmpl.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "ES-Deploy-ForwardActLogs", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Ensures that Activity Log Diagnostics settings are set to push logs into Log Analytics workspace.", - "displayName": "ES-Deploy-Diagnostics-ForwardActivityLogs", - "notScopes": [], - "parameters": { - "logAnalytics": { - "value": null - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/ES-Deploy-Diagnostics-LogAnalytics", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json deleted file mode 100644 index 6cae95354..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/policy_assignment_es_deploy_diag_loganalytics.tmpl.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "ES-Deploy-ForwardDiagLog", - "type": "Microsoft.Authorization/policyAssignments", - "apiVersion": "2019-09-01", - "properties": { - "description": "Ensures that Azure resources are configured to forward diagnostic logs and metrics to an Azure Log Analytics workspace.", - "displayName": "ES-Deploy-Diagnostics-ForwardDiagnosticLogs", - "notScopes": [], - "parameters": { - "logAnalytics": { - "value": null - } - }, - "policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/ES-Deploy-Diagnostics-LogAnalytics", - "scope": "${current_scope_resource_id}" - }, - "sku": { - "name": "A0", - "tier": "Free" - }, - "location": "${default_location}", - "identity": { - "type": "SystemAssigned" - } -} diff --git a/landingzones.old/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json b/landingzones.old/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json deleted file mode 100644 index d75c1298a..000000000 --- a/landingzones.old/caf_eslz/scenario/200/lib/policy_definition_es_deploy_asc_standard.json +++ /dev/null @@ -1,284 +0,0 @@ -{ - "name": "ES-Deploy-ASC-Standard", - "type": "Microsoft.Authorization/policyDefinitions", - "apiVersion": "2019-09-01", - "properties": { - "description": "Ensures that subscriptions have Security Center Standard enabled.", - "displayName": "ES-Deploy-ASC-Standard", - "mode": "All", - "parameters": { - "pricingTierVMs": { - "type": "String", - "metadata": { - "displayName": "pricingTierVMs", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierSqlServers": { - "type": "String", - "metadata": { - "displayName": "pricingTierSqlServers", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierAppServices": { - "type": "String", - "metadata": { - "displayName": "pricingTierAppServices", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierStorageAccounts": { - "type": "String", - "metadata": { - "displayName": "pricingTierStorageAccounts", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierContainerRegistry": { - "type": "String", - "metadata": { - "displayName": "pricingTierContainerRegistry", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierKeyVaults": { - "type": "String", - "metadata": { - "displayName": "pricingTierKeyVaults", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - }, - "pricingTierKubernetesService": { - "type": "String", - "metadata": { - "displayName": "pricingTierKubernetesService", - "description": "" - }, - "allowedValues": [ - "Standard", - "Free" - ], - "defaultValue": "Standard" - } - }, - "policyRule": { - "if": { - "allOf": [ - { - "field": "type", - "equals": "Microsoft.Resources/subscriptions" - } - ] - }, - "then": { - "effect": "deployIfNotExists", - "details": { - "type": "Microsoft.Security/pricings", - "deploymentScope": "subscription", - "existenceScope": "subscription", - "roleDefinitionIds": [ - "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635" - ], - "existenceCondition": { - "allOf": [ - { - "field": "Microsoft.Security/pricings/pricingTier", - "equals": "Standard" - }, - { - "field": "type", - "equals": "Microsoft.Security/pricings" - } - ] - }, - "deployment": { - "location": "northeurope", - "properties": { - "mode": "incremental", - "parameters": { - "pricingTierVMs": { - "value": "[parameters('pricingTierVMs')]" - }, - "pricingTierSqlServers": { - "value": "[parameters('pricingTierSqlServers')]" - }, - "pricingTierAppServices": { - "value": "[parameters('pricingTierAppServices')]" - }, - "pricingTierStorageAccounts": { - "value": "[parameters('pricingTierStorageAccounts')]" - }, - "pricingTierContainerRegistry": { - "value": "[parameters('pricingTierContainerRegistry')]" - }, - "pricingTierKeyVaults": { - "value": "[parameters('pricingTierKeyVaults')]" - }, - "pricingTierKubernetesService": { - "value": "[parameters('pricingTierKubernetesService')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "pricingTierVMs": { - "type": "string", - "metadata": { - "description": "pricingTierVMs" - } - }, - "pricingTierSqlServers": { - "type": "string", - "metadata": { - "description": "pricingTierSqlServers" - } - }, - "pricingTierAppServices": { - "type": "string", - "metadata": { - "description": "pricingTierAppServices" - } - }, - "pricingTierStorageAccounts": { - "type": "string", - "metadata": { - "description": "pricingTierStorageAccounts" - } - }, - "pricingTierContainerRegistry": { - "type": "string", - "metadata": { - "description": "ContainerRegistry" - } - }, - "pricingTierKeyVaults": { - "type": "string", - "metadata": { - "description": "KeyVaults" - } - }, - "pricingTierKubernetesService": { - "type": "string", - "metadata": { - "description": "KubernetesService" - } - } - }, - "variables": {}, - "resources": [ - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "VirtualMachines", - "properties": { - "pricingTier": "[parameters('pricingTierVMs')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "StorageAccounts", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/VirtualMachines')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierStorageAccounts')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "AppServices", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/StorageAccounts')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierAppServices')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "SqlServers", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/AppServices')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierSqlServers')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "KeyVaults", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/SqlServers')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierKeyVaults')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "KubernetesService", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/KeyVaults')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierKubernetesService')]" - } - }, - { - "type": "Microsoft.Security/pricings", - "apiVersion": "2018-06-01", - "name": "ContainerRegistry", - "dependsOn": [ - "[concat('Microsoft.Security/pricings/KubernetesService')]" - ], - "properties": { - "pricingTier": "[parameters('pricingTierContainerRegistry')]" - } - } - ], - "outputs": {} - } - } - } - } - } - } - } -} diff --git a/landingzones.old/caf_eslz/variables.tf b/landingzones.old/caf_eslz/variables.tf deleted file mode 100644 index 0c1e834c0..000000000 --- a/landingzones.old/caf_eslz/variables.tf +++ /dev/null @@ -1,83 +0,0 @@ -# Map of the remote data state -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} -variable "tfstate_storage_account_name" { - description = "This value is propulated by the rover" -} -variable "tfstate_container_name" { - description = "This value is propulated by the rover" -} -variable "tfstate_key" { - description = "This value is propulated by the rover" -} -variable "tfstate_resource_group_name" { - description = "This value is propulated by the rover" -} - -variable "landingzone" { - default = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "foundations" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } - } -} - -variable "tenant_id" {} -variable "rover_version" {} -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - type = map(any) - default = {} -} - -variable "enterprise_scale" { - default = {} -} - -variable "diagnostics_definition" { - default = {} -} -variable "keyvaults" { - default = {} -} -variable "resource_groups" { - default = {} -} -variable "log_analytics" { - default = {} -} -variable "event_hub_namespaces" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "diagnostic_event_hub_namespaces" { - default = {} -} -variable "diagnostic_log_analytics" { - default = {} -} -variable "diagnostics_destinations" { - default = {} -} -variable "dynamic_keyvault_secrets" { - default = {} -} \ No newline at end of file diff --git a/landingzones.old/caf_foundations/README.md b/landingzones.old/caf_foundations/README.md deleted file mode 100644 index d9e449911..000000000 --- a/landingzones.old/caf_foundations/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Foundations - -The foundations landing zone allows you to manage the core components of an environment: - -* Auditing and Accounting, deployment or connection to existing ones. - -Foundations landing zone operates at **level 1**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -
- -## Components - -CAF foundations landing zone leverages the enterprise-scale module in order to deploy its core components. - -## Deploying CAF foundations - -By default, the content of this landing zone is empty unless you specify a configuration file to enable it. - -```bash -# To deploy the CAF foundations in passthrough mode -rover -lz /tf/caf/public/landingzones/caf_foundations \ - -level level1 \ - -a apply - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/public/landingzones/caf_foundations \ - -tfstate_subscription_id \ - -level level1 \ - -a apply -``` diff --git a/landingzones.old/caf_foundations/backend.azurerm b/landingzones.old/caf_foundations/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones.old/caf_foundations/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones.old/caf_foundations/dynamic_secrets.tf b/landingzones.old/caf_foundations/dynamic_secrets.tf deleted file mode 100644 index ae28233b0..000000000 --- a/landingzones.old/caf_foundations/dynamic_secrets.tf +++ /dev/null @@ -1,11 +0,0 @@ - -module "dynamic_keyvault_secrets" { - source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" - version = "~>5.2.0" - - for_each = try(var.dynamic_keyvault_secrets, {}) - - settings = each.value - keyvault = module.foundations.keyvaults[each.key] - objects = module.foundations -} diff --git a/landingzones.old/caf_foundations/landingzone.tf b/landingzones.old/caf_foundations/landingzone.tf deleted file mode 100644 index 8bda58b4c..000000000 --- a/landingzones.old/caf_foundations/landingzone.tf +++ /dev/null @@ -1,30 +0,0 @@ -module "foundations" { - source = "aztfmod/caf/azurerm" - version = "~>5.2.0" - - current_landingzone_key = var.landingzone.key - tenant_id = var.tenant_id - tags = local.tags - diagnostics = local.remote.diagnostics - global_settings = local.global_settings - tfstates = local.tfstates - diagnostics_definition = var.diagnostics_definition - diagnostics_destinations = var.diagnostics_destinations - diagnostic_storage_accounts = var.diagnostic_storage_accounts - logged_user_objectId = var.logged_user_objectId - logged_aad_app_objectId = var.logged_aad_app_objectId - resource_groups = var.resource_groups - keyvaults = var.keyvaults - log_analytics = var.log_analytics - event_hub_namespaces = var.event_hub_namespaces - - ## Azure Active Directory - azuread_apps = var.azuread_apps - azuread_api_permissions = var.azuread_api_permissions - azuread_groups = var.azuread_groups - azuread_roles = var.azuread_roles - azuread_users = var.azuread_users - managed_identities = var.managed_identities - custom_role_definitions = var.custom_role_definitions - role_mapping = var.role_mapping -} diff --git a/landingzones.old/caf_foundations/locals.remote_tfstates.tf b/landingzones.old/caf_foundations/locals.remote_tfstates.tf deleted file mode 100644 index b2c4c2d2b..000000000 --- a/landingzones.old/caf_foundations/locals.remote_tfstates.tf +++ /dev/null @@ -1,92 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - - remote = { - diagnostics = { - # Get the diagnostics settings of services to create - diagnostic_event_hub_namespaces = var.diagnostic_event_hub_namespaces - diagnostic_log_analytics = var.diagnostic_log_analytics - diagnostic_storage_accounts = var.diagnostic_storage_accounts - - # Combine the diagnostics definitions - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = { - event_hub_namespaces = merge( - try(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations.event_hub_namespaces, {}), - try(var.diagnostics_destinations.event_hub_namespaces, {}) - ) - log_analytics = merge( - try(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations.log_analytics, {}), - try(var.diagnostics_destinations.log_analytics, {}) - ) - storage = merge( - try(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations.storage, {}), - try(var.diagnostics_destinations.storage, {}) - ) - } - # Get the remote existing diagnostics objects - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.event_hub_namespaces - } - - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) - } - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) - } - azuread_applications = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {})) - } - azuread_users = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_users[key], {})) - } - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) - } - } - - combined = { - managed_identities = merge(local.remote.managed_identities, tomap({ (var.landingzone.key) = module.foundations.managed_identities })) - azuread_groups = merge(local.remote.azuread_groups, tomap({ (var.landingzone.key) = module.foundations.azuread_groups })) - aad_apps = merge(local.remote.azuread_applications, tomap({ (var.landingzone.key) = module.foundations.aad_apps })) - azuread_users = merge(local.remote.azuread_users, tomap({ (var.landingzone.key) = module.foundations.azuread_users })) - } - -} diff --git a/landingzones.old/caf_foundations/main.tf b/landingzones.old/caf_foundations/main.tf deleted file mode 100644 index b3f105bee..000000000 --- a/landingzones.old/caf_foundations/main.tf +++ /dev/null @@ -1,63 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} -data "azurerm_subscription" "current" {} - -locals { - - # Update the tfstates map - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} - diff --git a/landingzones.old/caf_foundations/output.tf b/landingzones.old/caf_foundations/output.tf deleted file mode 100644 index a66bb9edd..000000000 --- a/landingzones.old/caf_foundations/output.tf +++ /dev/null @@ -1,39 +0,0 @@ -output "global_settings" { - value = local.global_settings - sensitive = true -} -output "diagnostics" { - value = module.foundations.diagnostics - sensitive = true -} -output "vnets" { - value = local.remote.vnets - sensitive = true -} -output "tfstates" { - value = local.tfstates - sensitive = true -} -output "keyvaults" { - value = tomap({ - (var.landingzone.key) = try(module.foundations.keyvaults, {}) - }) - sensitive = true -} -# Active Directory -output "managed_identities" { - value = local.combined.managed_identities - sensitive = true -} -output "azuread_groups" { - value = local.combined.azuread_groups - sensitive = true -} -output "aad_apps" { - value = local.combined.aad_apps - sensitive = true -} -output "azuread_users" { - value = local.combined.managed_identities - sensitive = true -} diff --git a/landingzones.old/caf_foundations/variables.tf b/landingzones.old/caf_foundations/variables.tf deleted file mode 100644 index fa721b4e2..000000000 --- a/landingzones.old/caf_foundations/variables.tf +++ /dev/null @@ -1,112 +0,0 @@ -# Map of the remote data state -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} -variable "tfstate_storage_account_name" { - description = "This value is propulated by the rover" -} -variable "tfstate_container_name" { - description = "This value is propulated by the rover" -} -variable "tfstate_key" { - description = "This value is propulated by the rover" -} -variable "tfstate_resource_group_name" { - description = "This value is propulated by the rover" -} - -variable "landingzone" { - default = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level1" - key = "foundations" - tfstates = { - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - } - } -} - -variable "tenant_id" {} -variable "rover_version" {} -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - type = map(any) - default = {} -} - -variable "enterprise_scale" { - default = {} -} - -variable "diagnostics_definition" { - default = {} -} -variable "keyvaults" { - default = {} -} -variable "resource_groups" { - default = {} -} -variable "log_analytics" { - default = {} -} -variable "event_hub_namespaces" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "diagnostic_event_hub_namespaces" { - default = {} -} -variable "diagnostic_log_analytics" { - default = {} -} -variable "diagnostics_destinations" { - default = {} -} -variable "dynamic_keyvault_secrets" { - default = {} -} - -## Azure Active Directory -variable "azuread_apps" { - default = {} -} -variable "azuread_api_permissions" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "azuread_users" { - default = {} -} -variable "azuread_roles" { - default = {} -} -variable "managed_identities" { - default = {} -} -variable "custom_role_definitions" { - default = {} -} -variable "role_mapping" { - default = { - built_in_role_mapping = {} - custom_role_mapping = {} - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo.tf deleted file mode 100644 index 9d2b42c02..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo.tf +++ /dev/null @@ -1,15 +0,0 @@ -# The PAT token must be provisioned in a different deployment -provider "azuredevops" { - org_service_url = var.azure_devops.url - personal_access_token = data.azurerm_key_vault_secret.pat.value -} - -data "azurerm_key_vault_secret" "pat" { - name = var.azure_devops.pats["admin"].secret_name - key_vault_id = local.remote.keyvaults[var.azure_devops.pats["admin"].lz_key][var.azure_devops.pats["admin"].keyvault_key].id - -} - -data "azuredevops_project" "project" { - name = var.azure_devops.project -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_agent_pools.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_agent_pools.tf deleted file mode 100644 index 7832ba6e9..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_agent_pools.tf +++ /dev/null @@ -1,52 +0,0 @@ - -locals { - organization_agent_pools = try(var.azure_devops.organization_agent_pools, {}) - project_agent_pools = try(var.azure_devops.project_agent_pools, {}) -} - - -## Agent pools -## Those pools are created in the organization, not the project -resource "azuredevops_agent_pool" "pool" { - for_each = try(var.azure_devops.organization_agent_pools, {}) - - name = each.value.name - auto_provision = lookup(each.value, "auto_provision", false) -} - -# -# add the agent pools into the project -# - -data "azuredevops_agent_pool" "pool" { - depends_on = [azuredevops_agent_pool.pool] - for_each = try(var.azure_devops.project_agent_pools, {}) - - name = each.value.name -} - -resource "azuredevops_agent_queue" "agent_queue" { - for_each = data.azuredevops_agent_pool.pool - - project_id = data.azuredevops_project.project.id - agent_pool_id = each.value.id - - lifecycle { - ignore_changes = [ - agent_pool_id - ] - } -} - -# -# Grant acccess to queue to all pipelines in the project -# - -resource "azuredevops_resource_authorization" "queue" { - for_each = data.azuredevops_agent_pool.pool - - project_id = data.azuredevops_project.project.id - resource_id = azuredevops_agent_queue.agent_queue[each.key].id - type = "queue" - authorized = true -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_pipelines.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_pipelines.tf deleted file mode 100644 index 6fe4fdcbb..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_pipelines.tf +++ /dev/null @@ -1,43 +0,0 @@ -data "azuredevops_git_repositories" "repos" { - project_id = data.azuredevops_project.project.id -} - - -locals { - repositories = zipmap(tolist(data.azuredevops_git_repositories.repos.repositories.*.name), tolist(data.azuredevops_git_repositories.repos.repositories)) -} - -resource "azuredevops_build_definition" "build_definition" { - - for_each = try(var.azure_devops.pipelines, {}) - project_id = data.azuredevops_project.project.id - name = each.value.name - path = each.value.folder - - variable_groups = lookup(each.value, "variable_group_keys", null) == null ? null : [ - for key in each.value.variable_group_keys : - azuredevops_variable_group.variable_group[key].id - ] - - repository { - repo_id = local.repositories[each.value.git_repo_name].id - repo_type = each.value.repo_type - yml_path = each.value.yaml - branch_name = lookup(each.value, "branch_name", null) - # service_connection_id = lookup(each.value, "repo_type", null) == "github" ? null : azuredevops_serviceendpoint_azurerm.github[each.value.service_connection_key].id - } - - ci_trigger { - use_yaml = true - } - - dynamic "variable" { - for_each = try(each.value.variables, {}) - - content { - name = variable.key - value = variable.value - } - } - -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_service_endpoint.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_service_endpoint.tf deleted file mode 100644 index 760919a25..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_service_endpoint.tf +++ /dev/null @@ -1,36 +0,0 @@ - -data "azurerm_key_vault_secret" "client_secret" { - depends_on = [module.caf] - for_each = try(var.azure_devops.service_endpoints, {}) - - name = format("%s-client-secret", local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].secret_name_client_secret) - key_vault_id = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].keyvaults[each.value.secret_keyvault_key].id -} - -resource "azuredevops_serviceendpoint_azurerm" "azure" { - depends_on = [module.caf] - for_each = try(var.azure_devops.service_endpoints, {}) - - project_id = data.azuredevops_project.project.id - service_endpoint_name = each.value.endpoint_name - credentials { - serviceprincipalid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].azuread_application.application_id - serviceprincipalkey = data.azurerm_key_vault_secret.client_secret[each.key].value - } - azurerm_spn_tenantid = local.combined.aad_apps[var.landingzone.key][each.value.aad_app_key].tenant_id - azurerm_subscription_id = each.value.subscription_id - azurerm_subscription_name = each.value.subscription_name -} - -# -# Grant acccess to service endpoint to all pipelines in the project -# - -resource "azuredevops_resource_authorization" "endpoint" { - for_each = azuredevops_serviceendpoint_azurerm.azure - - project_id = data.azuredevops_project.project.id - resource_id = each.value.id - type = "endpoint" - authorized = true -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_variable_groups.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_variable_groups.tf deleted file mode 100644 index 7cd1ed1c2..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/azdo_variable_groups.tf +++ /dev/null @@ -1,39 +0,0 @@ -# -# permissions required: -# - vso.variablegroups_manage (create) -# + vso.buid (update) -# + vso.build_execute (destroy) -# -resource "azuredevops_variable_group" "variable_group" { - for_each = try(var.azure_devops.variable_groups, {}) - - project_id = data.azuredevops_project.project.id - name = each.value.name - description = try(each.value.description, null) - allow_access = try(each.value.allow_access, false) - - dynamic "key_vault" { - for_each = lookup(each.value, "keyvault", null) == null ? [] : [1] - - content { - name = try(each.value.keyvault.lz_key, null) == null ? local.combined.keyvaults[var.landingzone.key][each.value.keyvault.keyvault_key].name : local.combined.keyvaults[each.value.keyvault.lz_key][each.value.keyvault.keyvault_key].name - service_endpoint_id = azuredevops_serviceendpoint_azurerm.azure[each.value.keyvault.serviceendpoint_key].id - } - } - - dynamic "variable" { - for_each = { - for key, variable in each.value.variables : key => { - name = key == "name" ? variable : key - value = key == "name" ? null : variable - } - } - - content { - # When used with Keyvault, the name must be the keyvault secret name and value must not be set - name = variable.value.name - value = variable.value.value - } - } - -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/backend.azurerm b/landingzones.old/caf_launchpad/add-ons/azure_devops/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/documentation/images/pat_token.png b/landingzones.old/caf_launchpad/add-ons/azure_devops/documentation/images/pat_token.png deleted file mode 100644 index 84fc549c5baa26167b2a975c5ae917e5a46b162e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78143 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 diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/locals.remote_tfstates.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/locals.remote_tfstates.tf deleted file mode 100644 index 4295ebf43..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/locals.remote_tfstates.tf +++ /dev/null @@ -1,76 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - } - - - combined = { - aad_apps = merge(local.remote.aad_apps, map(var.landingzone.key, module.caf.aad_apps)) - azuread_groups = merge(local.remote.azuread_groups, map(var.landingzone.key, module.caf.azuread_groups)) - keyvaults = merge(local.remote.keyvaults, map(var.landingzone.key, module.caf.keyvaults)) - managed_identities = merge(local.remote.managed_identities, map(var.landingzone.key, module.caf.managed_identities)) - } - - remote = { - aad_apps = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {})) - } - - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) - } - - keyvaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) - } - - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) - } - - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) - } - } - - -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf deleted file mode 100644 index a85b06a80..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/main.tf +++ /dev/null @@ -1,69 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - azuredevops = { - source = "microsoft/azuredevops" - version = "~> 0.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - - -locals { - - - tfstates = merge( - map(var.landingzone.backend_type, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf deleted file mode 100644 index a46105168..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/output.tf +++ /dev/null @@ -1,6 +0,0 @@ -output "keyvaults" { - value = map( - var.landingzone.key, module.caf.keyvaults - ) - sensitive = true -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/readme.md b/landingzones.old/caf_launchpad/add-ons/azure_devops/readme.md deleted file mode 100644 index 1ebbb675f..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/readme.md +++ /dev/null @@ -1,60 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Azure Devops add-on - -The Azure Devops add-ons allow you to setup you Azure Devops environment as a platform to automate all your subsequent landing zone deployment from level 0 until level 4 through Azure pipelines with self hosted agents. - -* Azure Devops: - - Agent Pools (Organization and Project Level) - - Service Endpoint - - Variables and Variable Groups - - Pipelines - -* Azure (Connection with Azure Devops): - - Azure AD Application - - Custom Role - - Keyvault and access policies for Azure AD App - -Azure Devops add-on landing zone operates at **level 0** - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -## Dependencies - -Landing zone: -* CAF Launchpad (Scenario 200 or above) - -Azure Devops (example): -* Organization: https://dev.azure.com/azure-terraform -* Project : contoso_demo (https://dev.azure.com/azure-terraform/contoso_demo) -* Repo : caf-configuration (https://dev.azure.com/azure-terraform/contoso_demo/_git/caf-configuration) - - In order for pipeline to work properly, YAML file should be in this repo and referred accordingly under pipeline section in azure_devops.tfvars - - sample yaml attached [here](./scenario/200-contoso_demo/pipeline/rover.yaml). - -Azure: -* PAT Token : PAT Token should be updated in keyvault secret that deployed by launchpad LZ as below - -![](./documentation/images/pat_token.png) - -## Deployment - -```bash -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops \ - -tfstate azure_devops-contoso_demo.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo \ - -parallelism 30 \ - -level level0 \ - -env sandpit \ - -a apply - - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops \ - -tfstate_subscription_id \ - -tfstate azure_devops-contoso_demo.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo \ - -parallelism 30 \ - -level level0 \ - -env sandpit \ - -a apply -``` - -We are planning to release more examples on how to deploy the Azure Devops Agents. diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars deleted file mode 100644 index bf0bd6c1f..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/azure_devops.tfvars +++ /dev/null @@ -1,232 +0,0 @@ - - -azure_devops = { - - url = "https://dev.azure.com/azure-terraform/" - project = "contoso_demo" - - # PAT Token should be updated manually to the keyvault after running launchpad - pats = { - admin = { - secret_name = "azdo-pat-admin" - lz_key = "launchpad" - keyvault_key = "secrets" - } - } - - organization_agent_pools = { - level0 = { - name = "caf-sandpit-level0" - auto_provision = false # When set to false the agent pool is not populated automatically into the devops projects (recommended) - } - level1 = { - name = "caf-sandpit-level1" - auto_provision = false - } - level2 = { - name = "caf-sandpit-level2" - auto_provision = false - } - level3 = { - name = "caf-sandpit-level3" - auto_provision = false - } - level4 = { - name = "caf-sandpit-level4" - auto_provision = false - } - } - - project_agent_pools = { - level0 = { - name = "caf-sandpit-level0" - } - level1 = { - name = "caf-sandpit-level1" - } - level2 = { - name = "caf-sandpit-level2" - } - level3 = { - name = "caf-sandpit-level3" - } - level4 = { - name = "caf-sandpit-level4" - } - } - - service_endpoints = { - contoso_demo = { - endpoint_name = "terraformdev (terraformdev.onmicrosoft.com) - contoso_demo" - subscription_name = "ase-landingzone" - subscription_id = "1d53e782-9f46-4720-b6b3-cff29106e9f6" - aad_app_key = "contoso_demo" - secret_keyvault_key = "devops" - } - } - - variable_groups = { - global = { - name = "release-global" # changing that name requires to change it in the devops agents yaml variables group - allow_access = true - variables = { - HOME_FOLDER_USER = "vsts_azpcontainer" - ROVER_IMAGE = "aztfmod/rover:2010.2808" - TF_CLI_ARGS = "'-no-color'" - TF_CLI_ARGS_init = "" - TF_CLI_ARGS_plan = "'-input=false'" - TF_VAR_ARGS_destroy = "'-auto-approve -refresh=false'" - ENVIRONMENT = "sandpit" - LANDINGZONE_BRANCH = "2010.0.0" - } - } - - level0 = { - name = "release-level0" - allow_access = true - variables = { - TF_VAR_pipeline_level = "level0" - ARM_USE_MSI = "true" - AGENT_POOL = "caf-sandpit-level0" - } - } - - level0_kv = { - name = "release-level0-msi" - allow_access = true - keyvault = { - lz_key = "launchpad" - keyvault_key = "level0" - serviceendpoint_key = "contoso_demo" - } - variables = { - name = "msi-resource-id" - } - } - - level1 = { - name = "release-level1" - allow_access = true - variables = { - TF_VAR_pipeline_level = "level1" - ARM_USE_MSI = "true" - AGENT_POOL = "caf-sandpit-level1" - } - } - - level1_kv = { - name = "release-level1-msi" - allow_access = true - keyvault = { - lz_key = "launchpad" - keyvault_key = "level1" - serviceendpoint_key = "contoso_demo" - } - variables = { - name = "msi-resource-id" - } - } - - level2 = { - name = "release-level2" - allow_access = true - variables = { - TF_VAR_pipeline_level = "level2" - ARM_USE_MSI = "true" - AGENT_POOL = "caf-sandpit-level2" - } - } - - level2_kv = { - name = "release-level2-msi" - allow_access = true - keyvault = { - lz_key = "launchpad" - keyvault_key = "level2" - serviceendpoint_key = "contoso_demo" - } - variables = { - name = "msi-resource-id" - } - } - - level3 = { - name = "release-level3" - allow_access = true - variables = { - TF_VAR_pipeline_level = "level3" - ARM_USE_MSI = "true" - AGENT_POOL = "caf-sandpit-level3" - } - } - - level3_kv = { - name = "release-level3-msi" - allow_access = true - keyvault = { - lz_key = "launchpad" - keyvault_key = "level3" - serviceendpoint_key = "contoso_demo" - } - variables = { - name = "msi-resource-id" - } - } - } - - pipelines = { - - # - # Agent pools - # - - devops_agent_level1_plan = { - name = "devops_agent_level1_plan" - folder = "\\configuration\\level1" - yaml = "configuration/pipeline/rover.yaml" - repo_type = "TfsGit" - git_repo_name = "caf-configuration" - variables = { - landingZoneName = "azdo-agent-level1", - terraformAction = "plan", - tfstateName = "azdo-agent-level1.tfstate" - configPath = "/configuration/level1/azuredevops/agent" - landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" - level = "level1" - } - variable_group_keys = ["global", "level0", "level0_kv"] - } - devops_agent_level1_apply = { - name = "devops_agent_level1_apply" - folder = "\\configuration\\level1" - yaml = "configuration/pipeline/rover.yaml" - repo_type = "TfsGit" - git_repo_name = "caf-configuration" - variables = { - landingZoneName = "azdo-agent-level1", - terraformAction = "apply", - tfstateName = "azdo-agent-level1.tfstate" - configPath = "/configuration/level1/azuredevops/agent" - landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" - level = "level1" - } - variable_group_keys = ["global", "level0", "level0_kv"] - } - devops_agent_level1_destroy = { - name = "devops_agent_level1_destroy" - folder = "\\configuration\\level1" - yaml = "configuration/pipeline/rover.yaml" - repo_type = "TfsGit" - git_repo_name = "caf-configuration" - variables = { - landingZoneName = "azdo-agent-level1", - terraformAction = "destroy", - tfstateName = "azdo-agent-level1.tfstate" - configPath = "/configuration/level1/azuredevops/agent" - landingZonePath = "/public/landingzones/caf_launchpad/add-ons/azure_devops_agent" - level = "level1" - } - variable_group_keys = ["global", "level0", "level0_kv"] - } - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars deleted file mode 100644 index e4d8208f3..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/configurations.tfvars +++ /dev/null @@ -1,123 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level0" - key = "azdo-contoso_demo" - tfstates = { - launchpad = { - level = "current" - tfstate = "caf_launchpad.tfstate" - } - } -} - -resource_groups = { - rg1 = { - name = "devops-agents-security" - } -} - - -keyvaults = { - devops = { - name = "devops" - resource_group_key = "rg1" - sku_name = "standard" - - creation_policies = { - keyvault_level0_rw = { - # Reference a key to an azure ad group - lz_key = "launchpad" - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - } -} - -keyvault_access_policies_azuread_apps = { - level0 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } - level1 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } - level2 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } - level3 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } - level4 = { - contoso_demo = { - lz_key = "launchpad" - azuread_app_key = "contoso_demo" - secret_permissions = ["Get", "List"] - } - } -} - - -azuread_apps = { - - contoso_demo = { - useprefix = true - application_name = "caf-level4-contoso_demo" - password_expire_in_days = 60 - tenant_name = "terraformdev.onmicrosoft.com" - reply_urls = ["https://localhost"] - keyvaults = { - devops = { - secret_prefix = "aadapp-caf-level4-azdo-contoso_demo" - } - } - } - -} - -custom_role_definitions = { - - caf-azdo-to-azure-subscription = { - name = "caf-azure-devops-azure-app-service-improvement-program-TO-azure-subscription" - useprefix = true - description = "CAF Custom role for service principal in Azure Devops to access resources" - permissions = { - actions = [ - "Microsoft.Resources/subscriptions/read", - "Microsoft.KeyVault/vaults/read" - ] - } - } - -} - - -role_mapping = { - custom_role_mapping = { - subscriptions = { - logged_in_subscription = { - "caf-azdo-to-azure-subscription" = { - azuread_apps = { - keys = ["contoso_demo"] - } - } - } - } - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml b/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml deleted file mode 100644 index 156fb9983..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/scenario/200-contoso_demo/pipeline/rover.yaml +++ /dev/null @@ -1,70 +0,0 @@ -parameters: - - name: timeoutInMinutes - displayName: 'Timeout in minutes' - type: number - default: 60 - - variables: - - group: release-global - - resources: - containers: - - container: rover - image: $(ROVER_IMAGE) - options: --user 0:0 -e TF_PLUGIN_CACHE_DIR="/home/$(HOME_FOLDER_USER)/plugin-cache" -e TF_DATA_DIR="/home/$(HOME_FOLDER_USER)" - - trigger: none - - jobs: - - job: CAF_Rover - - displayName: Azure Landing Zone - - pool: $(AGENT_POOL) - - continueOnError: false - - workspace: - clean: all - - container: rover - - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - - steps: - - checkout: self - - - bash: | - git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null - - az login --identity -u $(msi-resource-id) - - /tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \ - -tfstate $(tfstateName) \ - -var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \ - -parallelism=30 \ - -level $(level) \ - -a $(terraformAction) \ - -env $(ENVIRONMENT) - - condition: ne(variables['terraformAction'], 'destroy') - failOnStderr: true - displayName: 'Terraform $(terraformAction)' - - - bash: | - git clone --branch $(LANDINGZONE_BRANCH) https://github.com/Azure/caf-terraform-landingzones.git ${BUILD_REPOSITORY_LOCALPATH}/public 2>/dev/null - - az login --identity -u $(msi-resource-id) - - /tf/rover/rover.sh -lz ${BUILD_REPOSITORY_LOCALPATH}$(landingZonePath) \ - -tfstate $(tfstateName) \ - -var-folder ${BUILD_REPOSITORY_LOCALPATH}$(configPath) \ - -parallelism=30 \ - -level $(level) \ - -a $(terraformAction) \ - -auto-approve \ - -env $(ENVIRONMENT) - - condition: eq(variables['terraformAction'], 'destroy') - failOnStderr: true - displayName: 'Terraform destroy' diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/solution.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/solution.tf deleted file mode 100644 index e519166e8..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/solution.tf +++ /dev/null @@ -1,36 +0,0 @@ -module "caf" { - source = "aztfmod/caf/azurerm" - version = "~>5.2.0" - - current_landingzone_key = var.landingzone.key - tenant_id = var.tenant_id - tfstates = local.tfstates - tags = local.tags - global_settings = local.global_settings - diagnostics = local.diagnostics - diagnostic_storage_accounts = var.diagnostic_storage_accounts - logged_user_objectId = var.logged_user_objectId - logged_aad_app_objectId = var.logged_aad_app_objectId - resource_groups = var.resource_groups - storage_accounts = var.storage_accounts - azuread_groups = var.azuread_groups - keyvaults = var.keyvaults - keyvault_access_policies = var.keyvault_access_policies - keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps - role_mapping = var.role_mapping - custom_role_definitions = var.custom_role_definitions - azuread_apps = var.azuread_apps - compute = { - virtual_machines = var.virtual_machines - } - storage = { - storage_account_blobs = var.storage_account_blobs - } - - remote_objects = { - keyvaults = local.remote.keyvaults - vnets = local.remote.vnets - managed_identities = local.remote.managed_identities - azuread_groups = local.remote.azuread_groups - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf deleted file mode 100644 index 87dcc831a..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops/variables.tf +++ /dev/null @@ -1,102 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} - -variable "global_settings" { - default = {} -} -variable "tenant_id" {} -variable "landingzone" { -} -variable "rover_version" { - default = null -} - -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - default = null -} -variable "app_service_environments" { - default = {} -} -variable "app_service_plans" { - default = {} -} -variable "app_services" { - default = {} -} -variable "diagnostics_definition" { - default = {} -} -variable "resource_groups" { - default = {} -} -variable "network_security_group_definition" { - default = {} -} -variable "vnets" { - default = {} -} -variable "azurerm_redis_caches" { - default = {} -} -variable "mssql_servers" { - default = {} -} -variable "storage_accounts" { - default = {} -} -variable "storage_account_blobs" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "keyvaults" { - default = {} -} -variable "keyvault_access_policies" { - default = {} -} -variable "keyvault_access_policies_azuread_apps" { - default = {} -} -variable "virtual_machines" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "virtual_machine_extension_scripts" { - default = {} -} -variable "azure_devops" { - default = {} -} -variable "role_mapping" { - default = {} -} -variable "custom_role_definitions" { - default = {} -} -variable "azuread_apps" { - default = {} -} -variable "dynamic_keyvault_secrets" { - default = {} -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/backend.azurerm b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf deleted file mode 100644 index 48c0cd240..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/dynamic_secrets.tf +++ /dev/null @@ -1,11 +0,0 @@ - -module "dynamic_keyvault_secrets" { - source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" - version = "~>5.2.0" - - for_each = try(var.dynamic_keyvault_secrets, {}) - - settings = each.value - keyvault = module.caf.keyvaults[each.key] - objects = module.caf -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf deleted file mode 100644 index 5372db558..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/devops_selfhosted_agent.tf +++ /dev/null @@ -1,44 +0,0 @@ - -resource "azurerm_virtual_machine_extension" "devops_selfhosted_agent" { - for_each = { - for key, value in var.extensions : key => value - if key == "devops_selfhosted_agent" - } - - name = "install_azure_devops_agent" - - virtual_machine_id = var.virtual_machine_id - publisher = "Microsoft.Azure.Extensions" - type = "CustomScript" - type_handler_version = "2.1" - - #timestamp: use this field only to trigger a re-run of the script by changing value of this field. - # Any integer value is acceptable; it must only be different than the previous value. - settings = jsonencode( - { - "timestamp" : each.value.version, - "fileUris" : concat(local.devops_selfhosted_agent.file_uris, local.devops_selfhosted_agent.storage_account_blobs_urls), - - } - ) - protected_settings = jsonencode( - { - "commandToExecute" : format("bash %s '%s' '%s' '%s' '%s' '%s' '%s' '%s'", var.extensions[each.key].agent_init_script, var.settings[each.key].azure_devops.url, var.settings[each.key].agent_pat, var.settings[each.key].azure_devops.agent_pool.name, var.settings[each.key].azure_devops.agent_pool.agent_name_prefix, var.settings[each.key].azure_devops.agent_pool.num_agents, var.settings[each.key].admin_username, var.settings[each.key].azure_devops.rover_version) - } - ) - -} - -locals { - devops_selfhosted_agent = { - file_uris = flatten( - [ - for file_uris_key, file in try(var.extensions.devops_selfhosted_agent.fileUris, {}) : [ - for file_uri_key in file.storage_blob_keys : var.settings.devops_selfhosted_agent.storage_accounts[file.storage_account_key].containers[file.container_key].blobs[file_uri_key].url - ] - ] - ) - - storage_account_blobs_urls = try(var.settings.devops_selfhosted_agent.storage_account_blobs_urls, []) - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf deleted file mode 100644 index 9b8d2f8c3..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/extensions/variables.tf +++ /dev/null @@ -1,3 +0,0 @@ -variable "virtual_machine_id" {} -variable "extensions" {} -variable "settings" {} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/locals.current_tfstates.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/locals.current_tfstates.tf deleted file mode 100644 index fcc2fc189..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/locals.current_tfstates.tf +++ /dev/null @@ -1,74 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - } - - - combined = { - aad_apps = merge(local.remote.aad_apps, map(var.landingzone.key, module.caf.aad_apps)) - azuread_groups = merge(local.remote.azuread_groups, map(var.landingzone.key, module.caf.azuread_groups)) - keyvaults = merge(local.remote.keyvaults, map(var.landingzone.key, module.caf.keyvaults)) - managed_identities = merge(local.remote.managed_identities, map(var.landingzone.key, module.caf.managed_identities)) - } - - remote = { - aad_apps = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aad_apps[key], {})) - } - - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) - } - - keyvaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) - } - - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) - } - - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) - } - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf deleted file mode 100644 index 4ae9c573e..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/main.tf +++ /dev/null @@ -1,69 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - azuredevops = { - source = "microsoft/azuredevops" - version = "~> 0.1.1" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - - -locals { - - - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf deleted file mode 100644 index e19cb88aa..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/output.tf +++ /dev/null @@ -1,34 +0,0 @@ -output "managed_identities" { - value = local.combined.managed_identities - sensitive = false -} - -output "azuread_groups" { - value = local.combined.azuread_groups - sensitive = true -} - -output "keyvaults" { - value = local.combined.keyvaults - sensitive = false -} - -output "vnets" { - value = local.remote.vnets - sensitive = false -} - -output "global_settings" { - value = local.global_settings - sensitive = true -} - -output "diagnostics" { - value = local.diagnostics - sensitive = true -} - -output "tfstates" { - value = local.tfstates - sensitive = true -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/readme.md b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/readme.md deleted file mode 100644 index dd7b29571..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/readme.md +++ /dev/null @@ -1,54 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Azure Devops Agent add-on - -The Azure Devops Agent add-ons is the continuation of Self Hosted Agent implementation for Azure Devops environment that deployed in Azure Devops add on LZ. This will set up the underlying resources required for Agent in Azure. - -* Azure Virtual Machine to host the Agent -* Azure VM Extension to connect the VM to Azure Devops self hosted agent -* Storage account to put the script for VM Extension -* Key Vault to store the SSH key of the VM - -Azure Devops (Self Hosted Agent) add-on landing zone operates base on agent level for example for agent level0 will operates at **level 0** and agent level1 will operates at **level 1** - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -## Dependencies - -Landing zone: -* CAF Launchpad -* Azure DevOps add on (example: scenario 200-contoso_demo) - -## Deployment - -### Deploy the Azure Devops agent for level0 -```bash -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ - -tfstate level0_azure_devops_agents.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0 \ - -parallelism 30 \ - -level level0 \ - -env sandpit \ - -a apply -``` - -### Deploy the Azure Devops agent for level1 -```bash -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ - -tfstate azdo-agent-level1.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1 \ - -parallelism 30 \ - -level level1 \ - -env sandpit \ - -a apply - - -# If the tfstates are stored in a different subscription you need to execute the following command - -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent \ - -tfstate_subscription_id \ - -tfstate azdo-agent-level1.tfstate \ - -var-folder /tf/caf/landingzones/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1 \ - -parallelism 30 \ - -level level1 \ - -env sandpit \ - -a apply -``` \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars deleted file mode 100644 index 0141decf0..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/configuration.tfvars +++ /dev/null @@ -1,64 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "launchpad" - level = "level0" - key = "azdo-agent-level0" - tfstates = { - launchpad = { - level = "current" - tfstate = "caf_launchpad.tfstate" - } - azdo-contoso_demo = { - level = "current" - tfstate = "azure_devops-contoso_demo" - } - } -} - -resource_groups = { - rg1 = { - name = "devops-agents-level0" - } -} - -azure_devops = { - - # Rover version to apply to the devops self-hosted agents during the setup. - rover_version = "aztfmod/rover:2010.2808" - url = "https://dev.azure.com/azure-terraform/" - - pats = { - agent = { - secret_name = "azdo-pat-agent" - keyvault_key = "secrets" - lz_key = "launchpad" - } - } - - agent_pool = { - name = "caf-sandpit-level0" - auto_provision = true - num_agents = 4 - agent_name_prefix = "agent" - } - -} - -role_mapping = { - built_in_role_mapping = { - storage_accounts = { - scripts_region1 = { - "Storage Blob Data Contributor" = { - azuread_groups = { - lz_key = "launchpad" - keys = ["keyvault_level0_rw"] - } - managed_identities = { - lz_key = "launchpad" - keys = ["level0"] - } - } - } - } - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars deleted file mode 100644 index 35f188ba7..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/keyvaults.tfvars +++ /dev/null @@ -1,28 +0,0 @@ - -keyvaults = { - ssh = { - name = "sshl0" - resource_group_key = "rg1" - sku_name = "premium" - soft_delete_enabled = true - - creation_policies = { - keyvault_level0_rw = { - # Reference a key to an azure ad group - lz_key = "launchpad" - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } - -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars deleted file mode 100644 index 0af2a98f2..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/storage_accounts.tfvars +++ /dev/null @@ -1,42 +0,0 @@ - -storage_accounts = { - # Is used to store the azure devops deployment script to setup the Azure Devops Selfhosted agents - scripts_region1 = { - name = "scriptsl0" - resource_group_key = "rg1" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - allow_blob_public_access = true - - containers = { - scripts = { - name = "deployment-scripts" - container_access_type = "blob" - } - } - } -} - -# Attributes available https://www.terraform.io/docs/providers/azurerm/r/storage_blob.html -storage_account_blobs = { - devops_runtime_baremetal = { - storage_account_key = "scripts_region1" - storage_container_name = "deployment-scripts" - name = "devops_runtime_baremetal.sh" - source = "scripts/devops_runtime_baremetal.sh" - } -} - -diagnostic_storage_accounts = { - # Stores boot diagnostic for region1 - bootdiag_region1 = { - name = "bootl4" - resource_group_key = "rg1" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } -} - diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars deleted file mode 100644 index 3140b94e1..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level0/virtual_machines.tfvars +++ /dev/null @@ -1,79 +0,0 @@ - -# Virtual machines -virtual_machines = { - - # Configuration to deploy a bastion host linux virtual machine - level0 = { - resource_group_key = "rg1" - provision_vm_agent = true - boot_diagnostics_storage_account_key = "bootdiag_region1" - - os_type = "linux" - - keyvault_key = "ssh" - - # Define the number of networking cards to attach the virtual machine - networking_interfaces = { - nic0 = { - # Value of the keys from networking.tfvars - lz_key = "launchpad" - vnet_key = "devops_region1" - subnet_key = "release_agent_level0" - name = "0-release-agent-level0" - enable_ip_forwarding = false - internal_dns_name_label = "release-agent-level0" - } - } - - virtual_machine_settings = { - linux = { - name = "release-agent-level0" - size = "Standard_F2s_v2" - admin_username = "adminuser" - disable_password_authentication = true - - # Value of the nic keys to attach the VM. The first one in the list is the default nic - network_interface_keys = ["nic0"] - - os_disk = { - name = "release-agent-level0-os" - caching = "ReadWrite" - storage_account_type = "Standard_LRS" - } - - source_image_reference = { - publisher = "canonical" - offer = "0001-com-ubuntu-server-focal" - sku = "20_04-lts" - version = "latest" - } - - identity = { - type = "UserAssigned" - - remote = { - launchpad = { - managed_identity_keys = [ - "level0", - ] - } - } - } - - - } - } - - virtual_machine_extensions = { - devops_selfhosted_agent = { - version = 1 - virtual_machine_key = "vm_devops_level0" - agent_init_script = "devops_runtime_baremetal.sh" - storage_account_blobs = [ - "devops_runtime_baremetal" - ] - } - } - - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars deleted file mode 100644 index 7197d9c73..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/configuration.tfvars +++ /dev/null @@ -1,68 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "azdo-agent-level0" - level = "level1" - key = "azdo-agent-level1" - tfstates = { - azdo-agent-level0 = { - level = "lower" - tfstate = "level0_azure_devops_agents.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_launchpad.tfstate" - } - azdo-contoso_demo = { - level = "lower" - tfstate = "azure_devops-contoso_demo" - } - } -} - -resource_groups = { - rg1 = { - name = "devops-agents-level0" - } -} - -azure_devops = { - - # Rover version to apply to the devops self-hosted agents during the setup. - rover_version = "aztfmod/rover:2010.2808" - url = "https://dev.azure.com/azure-terraform/" - - pats = { - agent = { - secret_name = "azdo-pat-agent" - keyvault_key = "secrets" - lz_key = "launchpad" - } - } - - agent_pool = { - name = "caf-sandpit-level1" - auto_provision = true - num_agents = 4 - agent_name_prefix = "agent" - } - -} - -role_mapping = { - built_in_role_mapping = { - storage_accounts = { - scripts_region1 = { - "Storage Blob Data Contributor" = { - azuread_groups = { - lz_key = "launchpad" - keys = ["keyvault_level0_rw"] - } - managed_identities = { - lz_key = "launchpad" - keys = ["level0", "level1"] - } - } - } - } - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars deleted file mode 100644 index f25881503..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/keyvaults.tfvars +++ /dev/null @@ -1,32 +0,0 @@ - -keyvaults = { - ssh = { - name = "sshl1" - resource_group_key = "rg1" - sku_name = "premium" - soft_delete_enabled = true - - creation_policies = { - keyvault_level0_rw = { - # Reference a key to an azure ad group - lz_key = "launchpad" - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - msi_level0 = { - lz_key = "launchpad" - managed_identity_key = "level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars deleted file mode 100644 index 5ee9634cf..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/storage_accounts.tfvars +++ /dev/null @@ -1,42 +0,0 @@ - -storage_accounts = { - # Is used to store the azure devops deployment script to setup the Azure Devops Selfhosted agents - scripts_region1 = { - name = "scriptsl1" - resource_group_key = "rg1" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - allow_blob_public_access = true - - containers = { - scripts = { - name = "deployment-scripts" - container_access_type = "blob" - } - } - } -} - -# Attributes available https://www.terraform.io/docs/providers/azurerm/r/storage_blob.html -storage_account_blobs = { - devops_runtime_baremetal = { - storage_account_key = "scripts_region1" - storage_container_name = "deployment-scripts" - name = "devops_runtime_baremetal.sh" - source = "scripts/devops_runtime_baremetal.sh" - } -} - -diagnostic_storage_accounts = { - # Stores boot diagnostic for region1 - bootdiag_region1 = { - name = "bootl1" - resource_group_key = "rg1" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } -} - diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars deleted file mode 100644 index 41a40da84..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scenario/200-contoso_demo/level1/virtual_machines.tfvars +++ /dev/null @@ -1,77 +0,0 @@ - -# Virtual machines -virtual_machines = { - - # Configuration to deploy a bastion host linux virtual machine - level1 = { - resource_group_key = "rg1" - provision_vm_agent = true - boot_diagnostics_storage_account_key = "bootdiag_region1" - - os_type = "linux" - - keyvault_key = "ssh" - - # Define the number of networking cards to attach the virtual machine - networking_interfaces = { - nic0 = { - # Value of the keys from networking.tfvars - lz_key = "launchpad" - vnet_key = "devops_region1" - subnet_key = "release_agent_level1" - name = "0-release-agent-level1" - enable_ip_forwarding = false - internal_dns_name_label = "release-agent-level1" - } - } - - virtual_machine_settings = { - linux = { - name = "release-agent-level1" - size = "Standard_F2s_v2" - admin_username = "adminuser" - disable_password_authentication = true - - # Value of the nic keys to attach the VM. The first one in the list is the default nic - network_interface_keys = ["nic0"] - - os_disk = { - name = "release-agent-level1-os" - caching = "ReadWrite" - storage_account_type = "Standard_LRS" - } - - source_image_reference = { - publisher = "canonical" - offer = "0001-com-ubuntu-server-focal" - sku = "20_04-lts" - version = "latest" - } - - identity = { - type = "UserAssigned" - - remote = { - lz_key = "launchpad" - managed_identity_keys = [ - "level1", - ] - } - } - - - } - } - - virtual_machine_extensions = { - devops_selfhosted_agent = { - version = 1 - agent_init_script = "devops_runtime_baremetal.sh" - storage_account_blobs = [ - "devops_runtime_baremetal" - ] - } - } - - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config deleted file mode 100644 index 5bed7c472..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/cloud-init-install-rover-tools.config +++ /dev/null @@ -1,117 +0,0 @@ -#cloud-config -apt: - preserve_sources_list: true - sources: - azure-cli.list: - source: "deb https://packages.microsoft.com/repos/azure-cli/ bionic main" - key: | - -----BEGIN PGP PUBLIC KEY BLOCK----- - Version: GnuPG v1.4.7 (GNU/Linux) - - mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT - LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV - 7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag - OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j - H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr - M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs - ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC - AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH - /32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe - MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy - 7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV - KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ - XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+ - NdCFTW7wY0Fb1fWJ+/KTsC4= - =J6gs - -----END PGP PUBLIC KEY BLOCK----- - docker.list: - source: "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" - key: | - -----BEGIN PGP PUBLIC KEY BLOCK----- - - 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 - YT90qFF93M3v01BbxP+EIY2/9tiIPbrd - =0YYh - -----END PGP PUBLIC KEY BLOCK----- -package_update: true - -packages: - - docker-ce - - azure-cli - - ca-certificates - - curl - - apt-transport-https - - lsb-release - - jq - -snap: - commands: - - snap install kubectl --classic - -apt_upgrade: true - - # Install docker-compose -runcmd: - - [ sh, -c, 'curl -L https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep "tag_name" | cut -d \" -f4)/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose' ] - - [ sh, -c, 'sudo chmod +x /usr/local/bin/docker-compose' ] - -# Add default auto created user to docker group -system_info: - default_user: - groups: [docker] \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh deleted file mode 100644 index 7abc06a08..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_baremetal.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/sh - -url=${1} -pat_token=${2} -agent_pool=${3} -agent_prefix=${4} -num_agent=${5} -admin_user=${6} -rover_version="${7}" - -error() { - local parent_lineno="$1" - local message="$2" - local code="${3:-1}" - if [[ -n "$message" ]] ; then - >&2 echo -e "\e[41mError on or near line ${parent_lineno}: ${message}; exiting with status ${code}\e[0m" - else - >&2 echo -e "\e[41mError on or near line ${parent_lineno}; exiting with status ${code}\e[0m" - fi - echo "" - exit "${code}" -} - -function cleanup { - echo "calling cleanup" - - echo "stopping the service" - sudo ./svc.sh stop || true - echo "uninstall the service" - sudo ./svc.sh uninstall || true - echo "un-register from AZDO" - sudo -u ${admin_user} ./config.sh remove --unattended --auth pat --token ${pat_token} || true -} - -set -ETe -trap 'error ${LINENO}' ERR 1 2 3 6 - -#strict mode, fail on error -# set -euo pipefail - -echo "start" - -echo "install Ubuntu packages" - -# To make it easier for build and release pipelines to run apt-get, -# configure apt to not require confirmation (assume the -y argument by default) -export DEBIAN_FRONTEND=noninteractive -echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes - -apt-get update -apt-get install -y --no-install-recommends \ - ca-certificates \ - jq \ - apt-transport-https \ - docker.io \ - sudo - -echo "Allowing agent to run docker" - -usermod -aG docker ${admin_user} -systemctl daemon-reload -systemctl enable docker -service docker start -docker --version - -# Pull rover base image -echo "Rover docker image ${rover_version}" -docker pull "${rover_version}" 2>/dev/null - -echo "Installing Azure CLI" - -curl -sL https://aka.ms/InstallAzureCLIDeb | bash - -echo "install VSTS Agent" - -cd /home/${admin_user} -mkdir -p agent -cd agent - -AGENTRELEASE="$(curl -s https://api.github.com/repos/Microsoft/azure-pipelines-agent/releases/latest | grep -oP '"tag_name": "v\K(.*)(?=")')" -AGENTURL="https://vstsagentpackage.azureedge.net/agent/${AGENTRELEASE}/vsts-agent-linux-x64-${AGENTRELEASE}.tar.gz" -echo "Release "${AGENTRELEASE}" appears to be latest" -echo "Downloading..." -curl -s ${AGENTURL} -o agent_package.tar.gz - -for agent_num in $(seq 1 ${num_agent}); do - agent_dir="agent-$agent_num" - mkdir -p "$agent_dir" - cd "$agent_dir" - echo "moving to $agent_dir" - - cleanup - - name="${agent_prefix}-${agent_num}" - echo "installing agent $name" - tar zxvf ../agent_package.tar.gz - chmod -R 777 . - echo "extracted" - ./bin/installdependencies.sh || true - echo "dependencies installed" - sudo -u ${admin_user} ./config.sh --unattended --url "${url}" --auth pat --token "${pat_token}" --pool "${agent_pool}" --agent "${name}" --acceptTeeEula --replace --work ./_work --runAsService - echo "configuration done" - ./svc.sh install - echo "service installed" - ./svc.sh start - echo "service started" - echo "config done" - cd .. -done diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh deleted file mode 100644 index eb0b8cc2a..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/scripts/devops_runtime_docker.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc -sudo sh -c 'echo -e "[azure-cli] -name=Azure CLI -baseurl=https://packages.microsoft.com/yumrepos/azure-cli -enabled=1 -gpgcheck=1 -gpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/azure-cli.repo' -sudo yum -y install azure-cli - -sudo yum install -y yum-utils device-mapper-persistent-data lvm2 -sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo -sudo yum makecache fast -sudo yum install -y docker-ce -sudo systemctl daemon-reload -sudo systemctl enable docker -sudo service docker start -sudo docker --version - -sudo az login --identity - -az acr login --name ${7} -sudo docker pull "${7}/${5}" - -for agent_num in $(seq 1 ${6}); do - name="${4}-${agent_num}" - sudo docker run -d -v /var/run/docker.sock:/var/run/docker.sock --name ${name} -e AZP_URL=${1} -e AZP_TOKEN=${2} -e AZP_POOL="${3}" -e AZP_AGENT_NAME="${name}" "${7}/${5}" -done \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/solution.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/solution.tf deleted file mode 100644 index fb687582d..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/solution.tf +++ /dev/null @@ -1,37 +0,0 @@ -module "caf" { - source = "aztfmod/caf/azurerm" - version = "~>5.2.0" - - current_landingzone_key = var.landingzone.key - tenant_id = var.tenant_id - tfstates = local.tfstates - tags = local.tags - global_settings = local.global_settings - diagnostics = local.diagnostics - diagnostic_storage_accounts = var.diagnostic_storage_accounts - logged_user_objectId = var.logged_user_objectId - logged_aad_app_objectId = var.logged_aad_app_objectId - resource_groups = var.resource_groups - storage_accounts = var.storage_accounts - azuread_groups = var.azuread_groups - keyvaults = var.keyvaults - keyvault_access_policies = var.keyvault_access_policies - managed_identities = var.managed_identities - role_mapping = var.role_mapping - custom_role_definitions = var.custom_role_definitions - azuread_apps = var.azuread_apps - compute = { - virtual_machines = var.virtual_machines - } - storage = { - storage_account_blobs = var.storage_account_blobs - } - - # Pass the remote objects you need to connect to. - remote_objects = { - keyvaults = local.remote.keyvaults - vnets = local.remote.vnets - managed_identities = local.remote.managed_identities - azuread_groups = local.remote.azuread_groups - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf deleted file mode 100644 index 45c344a59..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/variables.tf +++ /dev/null @@ -1,102 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} - -variable "global_settings" { - default = {} -} -variable "tenant_id" {} -variable "landingzone" { -} -variable "rover_version" { - default = null -} - -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - default = null -} -variable "app_service_environments" { - default = {} -} -variable "app_service_plans" { - default = {} -} -variable "app_services" { - default = {} -} -variable "diagnostics_definition" { - default = {} -} -variable "resource_groups" { - default = {} -} -variable "network_security_group_definition" { - default = {} -} -variable "vnets" { - default = {} -} -variable "azurerm_redis_caches" { - default = {} -} -variable "mssql_servers" { - default = {} -} -variable "storage_accounts" { - default = {} -} -variable "storage_account_blobs" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "keyvaults" { - default = {} -} -variable "keyvault_access_policies" { - default = {} -} -variable "virtual_machines" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "virtual_machine_extension_scripts" { - default = {} -} -variable "azure_devops" { - default = {} -} -variable "role_mapping" { - default = {} -} -variable "custom_role_definitions" { - default = {} -} -variable "azuread_apps" { - default = {} -} -variable "dynamic_keyvault_secrets" { - default = {} -} -variable "managed_identities" { - default = {} -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf b/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf deleted file mode 100644 index 898d03288..000000000 --- a/landingzones.old/caf_launchpad/add-ons/azure_devops_agent/vm_extention_devops_agent.tf +++ /dev/null @@ -1,37 +0,0 @@ - - -# Get PAT token from keyvault -data "azurerm_key_vault_secret" "agent_pat" { - depends_on = [module.caf] - for_each = { - for key, value in try(var.virtual_machines, {}) : key => value - if try(value.virtual_machine_extensions, null) != null - } - - name = var.azure_devops.pats.agent.secret_name - key_vault_id = try(var.azure_devops.pats["agent"].lz_key, null) == null ? local.combined.keyvaults[var.landingzone.key][var.azure_devops.pats["agent"].keyvault_key].id : local.combined.keyvaults[var.azure_devops.pats["agent"].lz_key][var.azure_devops.pats["agent"].keyvault_key].id -} - - -module "vm_extensions" { - source = "./extensions" - depends_on = [module.caf] - for_each = { - for key, value in try(var.virtual_machines, {}) : key => value - if try(value.virtual_machine_extensions, null) != null - } - - virtual_machine_id = module.caf.virtual_machines[each.key].id - extensions = each.value.virtual_machine_extensions - settings = { - devops_selfhosted_agent = { - storage_accounts = module.caf.storage_accounts - agent_pat = data.azurerm_key_vault_secret.agent_pat[each.key].value - admin_username = each.value.virtual_machine_settings[each.value.os_type].admin_username - azure_devops = var.azure_devops - storage_account_blobs_urls = [ - for key, value in try(var.storage_account_blobs, []) : module.caf.storage_account_blobs[key].url - ] - } - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars deleted file mode 100644 index 1ce04bf0f..000000000 --- a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars +++ /dev/null @@ -1,25 +0,0 @@ -landingzone = { - backend_type = "remote" - level = "level0" - key = "launchpad" -} - -# Create the TFC organization -tfe_organizations = { - caf_lz = { - name = "caf-landingzones-test3" - email = "admin@your-company.com" - - } -} - -# Create the required TFE workspaces -tfe_workspaces = { - caf_launchpad = { - # specifies the object key for the organization where to create the workspace - organization_key = "caf_lz" - name = "caf_launchpad" - # path to place the backend file for the corresponding landing zone - backend_file = "/backend.hcl" - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/main.tf b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/main.tf deleted file mode 100644 index 413e570f5..000000000 --- a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/main.tf +++ /dev/null @@ -1,51 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.40" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - tfe = { - source = "hashicorp/tfe" - version = "~> 0.22.0" - } - } - required_version = ">= 0.13" -} - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - -locals { - tfstates = merge( - map(var.landingzone.backend_type, - map( - "level", var.landingzone.level, - "tenant_id", data.azurerm_client_config.current.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - ) -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/readme.md b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/readme.md deleted file mode 100644 index 7bfe4e7a6..000000000 --- a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/readme.md +++ /dev/null @@ -1,44 +0,0 @@ -# Add-on to deploy a Terraform Cloud / Terraform Enterprise configuration for Azure CAF landing zones - -Supported scenario in this release: - -1. Create the TFE/TFC environment (organization, variables, workspaces) - -Future scenarios: - -1. Use TFE/TFC as remote backend (local execution, backend in TFC) -2. Deploy Terraform Enterprise Server and remote agents -3. Use TFE/TFC in online mode (execution in TFE with remote agents) - -## Authenticating to Terraform Cloud - -First step is to authenticate to TFC using the following commands: - -```bash -terraform login -export TERRAFORM_CONFIG="$HOME/.terraform.d/credentials.tfrc.json" -``` - -## Creating the TFC environment - -This will setup TFC organization, workspaces and variables to host landing zones. - -```bash -# Deploy -rover -lz /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/ \ --var-folder /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/ \ --a plan -launchpad - -or -cd /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/ -terraform init -terraform plan \ --var-file /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars -``` - -Once ready, you can create your configuration: - -```bash -terraform apply \ --var-file /tf/caf/landingzones/caf_launchpad/add-ons/terraform_cloud/example/tfc.tfvars -``` \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/terraform_cloud.tf b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/terraform_cloud.tf deleted file mode 100644 index db9218fc0..000000000 --- a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/terraform_cloud.tf +++ /dev/null @@ -1,83 +0,0 @@ - -resource "tfe_organization" "tfe_org" { - for_each = try(var.tfe_organizations, {}) - - name = each.value.name - email = each.value.email - session_timeout_minutes = try(each.value.session_timeout_minutes, 20160) - session_remember_minutes = try(each.value.session_remember_minutes, 20160) - collaborator_auth_policy = try(each.value.collaborator_auth_policy, "password") - owners_team_saml_role_id = try(each.value.owners_team_saml_role_id, null) -} - -resource "tfe_workspace" "tfe_wks" { - for_each = try(var.tfe_workspaces, {}) - - name = each.value.name - organization = tfe_organization.tfe_org[each.value.organization_key].name - auto_apply = try(each.value.auto_apply, false) - file_triggers_enabled = try(each.value.file_triggers_enabled, true) - operations = try(each.value.operations, true) - queue_all_runs = try(each.value.queue_all_runs, true) - speculative_enabled = try(each.value.speculative_enabled, true) - ssh_key_id = try(each.value.ssh_key_id, null) - terraform_version = try(each.value.terraform_version, null) - trigger_prefixes = try(each.value.trigger_prefixes, null) - working_directory = try(each.value.working_directory, null) - - dynamic "vcs_repo" { - for_each = lookup(each.value, "vcs_repo", null) == null ? [] : [1] - - content { - identifier = each.value.vcs_repo.identifier - branch = try(each.value.vcs_repo.branch, null) - ingress_submodules = try(each.value.vcs_repo.ingress_submodules, false) - oauth_token_id = each.value.vcs_repo.oauth_token_id - } - } -} - -resource "tfe_variable" "variable" { - for_each = try(var.tfe_variables, {}) - - key = each.value.key_name - value = each.value.value - category = each.value.category - workspace_id = tfe_workspace.tfe_wks[each.value.workspace_key].id - description = each.value.description - hcl = try(each.value.hcl, false) - sensitive = try(each.value.sensitive, false) -} - -resource "null_resource" "backend_file" { - depends_on = [tfe_workspace.tfe_wks] - for_each = try(var.tfe_workspaces, {}) - - provisioner "local-exec" { - working_dir = "./" - command = "echo workspaces '{' name = \\\"${each.value.name}\\\" '}' >> ${path.cwd}${each.value.backend_file}" - } - provisioner "local-exec" { - working_dir = "./" - command = "echo hostname = \\\"app.terraform.io\\\" >> ${path.cwd}${each.value.backend_file}" - } - provisioner "local-exec" { - working_dir = "./" - command = "echo organization = \\\"${tfe_organization.tfe_org[each.value.organization_key].name}\\\" >> ${path.cwd}${each.value.backend_file}" - } -} - -resource "null_resource" "backend_file_destroy" { - depends_on = [tfe_workspace.tfe_wks] - for_each = try(var.tfe_workspaces, {}) - - triggers = { - backend_file = lookup(each.value, "backend_file") - } - - provisioner "local-exec" { - command = format("rm %s%s", path.cwd, self.triggers.backend_file) - when = destroy - on_failure = fail - } -} diff --git a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf b/landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf deleted file mode 100644 index 499b0aba5..000000000 --- a/landingzones.old/caf_launchpad/add-ons/terraform_cloud/variables.tf +++ /dev/null @@ -1,85 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" { - default = {} -} -variable "lower_container_name" { - default = {} -} -variable "lower_resource_group_name" { - default = {} -} - -variable "tfstate_storage_account_name" { - default = {} -} -variable "tfstate_container_name" { - default = {} -} -variable "tfstate_key" { - default = {} -} -variable "tfstate_resource_group_name" { - default = {} -} - -variable "global_settings" { - default = {} -} -variable "tenant_id" { - default = {} -} -variable "landingzone" { - default = {} -} - -variable "rover_version" { - default = null -} - -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - default = null -} -variable "keyvaults" { - default = {} -} -variable "keyvault_access_policies" { - default = {} -} -variable "role_mapping" { - default = {} -} -variable "secrets_from_keys" { - default = {} -} -variable "custom_role_definitions" { - default = {} -} -variable "azuread_apps" { - default = {} -} - -variable "tfe_organizations" { - default = {} -} - -variable "tfe_workspaces" { - default = {} -} - -variable "tfe_variables" { - default = {} -} - -variable "tfe_servers" { - default = {} -} - -variable "tfe_agents" { - default = {} -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/backend.azurerm b/landingzones.old/caf_launchpad/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones.old/caf_launchpad/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/documentation/img/launchpad-100.PNG b/landingzones.old/caf_launchpad/documentation/img/launchpad-100.PNG deleted file mode 100644 index c93a36c46bafe2b787394e8729e469a1c98bc6db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143702 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%0A}!)1#qO;^}XKhld?yny=?0OQ;f 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ȿ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

8x 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⪙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 z%0D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

eWxqjS32AL3iKBq8=c>e-zj+ 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 HA13EtOFTXU diff --git a/landingzones.old/caf_launchpad/documentation/variables.md b/landingzones.old/caf_launchpad/documentation/variables.md deleted file mode 100644 index ce3e5b190..000000000 --- a/landingzones.old/caf_launchpad/documentation/variables.md +++ /dev/null @@ -1,41 +0,0 @@ -# Variables of the landing zone launchpad - -The launchpad landing zone leverage object variables to provide better understanding of the variables to set in the configuration files. - -## launchpad_mode - -There are two launchpad versions that can be deployed in an Azure subscription. When set to launchpad_light it not impersonating the rover to the launchpad aad application and keep the execution under the logged-in user. It is designed to provide a way to experience the landing zone when the logged-in user has limited privileges in the Azure AD tenant. - -| Variable | Default | Allowed value | Type | Example | -|---|---|---|---|---| -| launchpad_mode | "launchpad_light" | ["launchpad_light", "launchpad"] | string | | - -## level - -| Variable | Description | -|---|---| -| level | The Cloud Adoption Framework for the Terraform Edition proposes to group landing zones into different levels to group per function and more importantly to secure the levels and prevent a level to access to an un-authorized level. More details on this link | - - -"level0" | ["level0", "level1", "level2", "level3", "level4"] | string | | - -## global_settings - -| Variable | Description | -|---|---| -| global_settings | The global_settings is an object containing the default settings the landing zones from a higher level can hinerit. | - -| Default | -|---| -```hcl -default = { - default_location = "southeastasia" - prefix = null -} -``` -### Attributes - -| Attribute | Allowed values -|---| -* prefix is not set or null it generates a random 4 alpha char -* prefix = "" disable the prefix in the naming conventions diff --git a/landingzones.old/caf_launchpad/dynamic_secrets.tf b/landingzones.old/caf_launchpad/dynamic_secrets.tf deleted file mode 100644 index 17d72202d..000000000 --- a/landingzones.old/caf_launchpad/dynamic_secrets.tf +++ /dev/null @@ -1,11 +0,0 @@ - -module "dynamic_keyvault_secrets" { - source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" - version = "~>5.2.0" - - for_each = try(var.dynamic_keyvault_secrets, {}) - - settings = each.value - keyvault = module.launchpad.keyvaults[each.key] - objects = module.launchpad -} diff --git a/landingzones.old/caf_launchpad/landingzone.tf b/landingzones.old/caf_launchpad/landingzone.tf deleted file mode 100644 index 762a46947..000000000 --- a/landingzones.old/caf_launchpad/landingzone.tf +++ /dev/null @@ -1,48 +0,0 @@ -module "launchpad" { - source = "aztfmod/caf/azurerm" - version = "~>5.2.0" - - current_landingzone_key = var.landingzone.key - tenant_id = var.tenant_id - tags = local.tags - global_settings = local.global_settings - enable = var.enable - logged_user_objectId = var.logged_user_objectId - logged_aad_app_objectId = var.logged_aad_app_objectId - user_type = var.user_type - log_analytics = var.log_analytics - diagnostics = { - diagnostics_definition = var.diagnostics_definition - diagnostics_destinations = var.diagnostics_destinations - diagnostic_event_hub_namespaces = var.diagnostic_event_hub_namespaces - diagnostic_log_analytics = var.diagnostic_log_analytics - diagnostic_storage_accounts = var.diagnostic_storage_accounts - } - event_hub_namespaces = var.event_hub_namespaces - resource_groups = var.resource_groups - keyvaults = var.keyvaults - keyvault_access_policies = var.keyvault_access_policies - keyvault_access_policies_azuread_apps = var.keyvault_access_policies_azuread_apps - subscriptions = var.subscriptions - compute = { - virtual_machines = var.virtual_machines - bastion_hosts = var.bastion_hosts - } - networking = { - vnets = var.vnets - network_security_group_definition = var.network_security_group_definition - public_ip_addresses = var.public_ip_addresses - azurerm_routes = var.azurerm_routes - route_tables = var.route_tables - } - storage_accounts = var.storage_accounts - # diagnostic_storage_accounts = var.diagnostic_storage_accounts - azuread_apps = var.azuread_apps - azuread_api_permissions = var.azuread_api_permissions - azuread_groups = var.azuread_groups - azuread_roles = var.azuread_roles - azuread_users = var.azuread_users - managed_identities = var.managed_identities - custom_role_definitions = var.custom_role_definitions - role_mapping = var.role_mapping -} diff --git a/landingzones.old/caf_launchpad/main.tf b/landingzones.old/caf_launchpad/main.tf deleted file mode 100644 index f5180c8bc..000000000 --- a/landingzones.old/caf_launchpad/main.tf +++ /dev/null @@ -1,99 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.4.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -resource "random_string" "prefix" { - count = var.prefix == null ? 1 : 0 - length = 4 - special = false - upper = false - number = false -} - -resource "random_string" "alpha1" { - count = var.prefix == null ? 1 : 0 - length = 1 - special = false - upper = false - number = false -} - -locals { - landingzone_tag = { - landingzone = var.landingzone.key - } - tags = merge(local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = var.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = { - default_region = var.default_region - environment = var.environment - inherit_tags = var.inherit_tags - passthrough = var.passthrough - prefix = var.prefix - prefixes = var.prefix == "" ? null : [try(var.prefix, random_string.prefix.0.result)] - prefix_with_hyphen = var.prefix == "" ? "" : try(format("%s-", var.prefix), format("%s-", random_string.prefix.0.result)) - random_length = var.random_length - regions = var.regions - tags = var.tags - use_slug = var.use_slug - } - - tfstates = map( - var.landingzone.key, - local.backend[var.landingzone.backend_type] - ) - - backend = { - azurerm = { - storage_account_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].name - container_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].containers["tfstate"].name - resource_group_name = module.launchpad.storage_accounts[var.launchpad_key_names.tfstates[0]].resource_group_name - key = var.tf_name - level = var.landingzone.level - tenant_id = data.azurerm_client_config.current.tenant_id - subscription_id = data.azurerm_client_config.current.subscription_id - } - } - -} - -data "azurerm_client_config" "current" {} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/output.tf b/landingzones.old/caf_launchpad/output.tf deleted file mode 100644 index 01d7898d6..000000000 --- a/landingzones.old/caf_launchpad/output.tf +++ /dev/null @@ -1,66 +0,0 @@ -output "global_settings" { - value = local.global_settings - sensitive = true -} - -output "diagnostics" { - value = module.launchpad.diagnostics - sensitive = true -} - -# TODO: candidate to deprecation in 2101 -# output networking { -# value = map( -# var.landingzone.key, -# map( -# "vnets", module.launchpad.vnets -# ) -# ) -# sensitive = true -# description = "[WARNING] deprecated. Use vnets from 0.4" -# } - -output "vnets" { - value = tomap({ - (var.landingzone.key) = module.launchpad.vnets - }) - sensitive = true -} - -output "tfstates" { - value = local.tfstates - sensitive = true -} - -output "backend_type" { - value = var.landingzone.backend_type - sensitive = true -} - -output "keyvaults" { - value = tomap({ - (var.landingzone.key) = module.launchpad.keyvaults - }) - sensitive = true -} - -output "managed_identities" { - value = tomap({ - (var.landingzone.key) = module.launchpad.managed_identities - }) - sensitive = true -} - -output "aad_apps" { - value = tomap({ - (var.landingzone.key) = module.launchpad.aad_apps - }) - sensitive = true -} - -output "azuread_groups" { - value = tomap({ - (var.landingzone.key) = module.launchpad.azuread_groups - }) - sensitive = true -} diff --git a/landingzones.old/caf_launchpad/readme.md b/landingzones.old/caf_launchpad/readme.md deleted file mode 100644 index 9bc5aa947..000000000 --- a/landingzones.old/caf_launchpad/readme.md +++ /dev/null @@ -1,206 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Launchpad - -The launchpad allows you to manage the foundations of landing zone environments by: - -* Securing remote Terraform state storage for multiple subscriptions. -* Managing the transition from manual to automated environments. -* Bring up the DevOps foundations using Azure DevOps, Terraform Cloud and GitHub actions (more to come). - -Launchpad operates at **level 0**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -
- -## Getting started with launchpad - -Depending on what you are trying to achieve, we provide you with different levels of launchpads to cover different scenario: - -| level | scenario | supported environments | -|-----------------------|------------------------------------------------------------------------------------------------------------------|--------------------------------------------| -| [100](./scenario/100) | Start with this one! basic functionalities and features, no RBAC or security hardening - for demo and simple POC | working on AIRS subscriptions | -| [200](./scenario/200) | intermediate functionalities includes diagnostics features | may not work in AIRS, need AAD permissions | -| [300](./scenario/300) | advanced functionalities, includes RBAC features | not working in AIRS, need AAD permissions | -| [400](./scenario/400) | advanced functionalities, includes RBAC features and security hardening | not working in AIRS, need AAD permissions | - -You can pick your scenario and use one of the following commands: - -```bash -# Simple scenario for learning and demonstration -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \ - -parallelism=30 \ - -a apply - -# Advanced scenario - Requires Azure AD privileges -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ - -parallelism=30 \ - -a apply - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/landingzones/caf_launchpad \ - -tfstate_subscription_id \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ - -parallelism=30 \ - -a apply -``` - -
- -## Overview of launchpad initialization - -![Launchpad Worklow](./documentation/img/launchpad_workflow.png) - -The rover executed in launchpad mode performs the following option to bootstrap your environment: - -1. **Initialize a terraform state**: - * The launchpad tries to retrieve an existing terraform state on Azure using the name of the tfstate file and the name of the workspace (level0 by default) - * Creates a tfstates folder if no remote state have been retrieved, this happens when your environment does not contain a storage account containing a tfstate matching the input parameters - - The Launchpad deployment relies on the following providers: - - * hashicorp/azurerm - * hashicorp/azuread - * hashicorp/random - * aztfmod/azurecaf - * hashicorp/null - - The latest version of the Launchpad relies on the new capabilities of **Terraform 0.13** - -2. **Call Terraform init**: - - * The launchpad then call terraform init to retrieve the provides and modules associated with the deployment - -3. **Call terraform apply**: - * deploy the resources as specified in the launchpad configuration files (see description below) - -```bash -Outputs: - -aad_apps = -azure_subscriptions = -diagnostics_map = -github_token_keyvault = -global_settings = -keyvaults = -log_analytics = -networking = -resource_groups = -``` - -4. **Create a workspace to host the local tfsate** - the launchpad will create two containers in the newly created storage account (in step 3): - * "sandpit" workspace - * "level0" (by default) workspace - -5. **Upload the launchpad state (tfstate) to the storage level0 workspace** - the state contains the default settings, keyvault id, and service principal id created during the launchpad deployment - -```bash -Moving launchpad to the cloud - - storage_account_name: storageaccname - - resource_group: hrjx-rg-launchpad-tfstates-rVb7GtKPXxHMa - - storage_key: retrieved -{ - "etag": "\"0x8D833A974C32C5F\"", - "lastModified": "2020-07-29T10:23:37+00:00" -} -``` - -
- -## Launchpad architecture - -Each resource deployed with the launchpad is leveraging the [azurecaf provider](https://github.com/aztfmod/terraform-provider-azurecaf) to enforce naming convention. - -The launchpad deploys the following Azure components: - -1. Resource groups - By default the launchpad light auto variables will create three resources groups : launchpad-tfstates to host a the tfstate storage account, launchpad-security to host a keyvault, launchpad-devops-agents to host deployment agents should you choose to deploy VMs to automate subsequent deployment using Azure DevOps or GitHub - -2. Storage Accounts - a storage account in the launchpad-tfstates reosource group. The storage account contains the tfstate of the launchpad deployment and will be automatically configured as the Terraform remote backend when deploying landing zones with the rover - -3. KeyVaults - a keyvault resource to store with Get,List,Set,Delete access to for the logged in user (using the Azure CLI) - the keyvault will contain secrets of service principal accounts and managed identities - -4. A Log Analytics workspace and a KeyVault analytics solution deployed in the launchpad-devops-agent resource group. The Log Analytics workspace will gather the monitoring information and logs of both the DevOps agents and of the Keyvault - -5. Diagnostic settings - Creates Storage Account and Event Hubs (optional) to be used for diagnostics and operations logs. The resources are created in the launchpad-devops-agent resource group - -6. Virtual Network: The Launchpad can create Virtual Networks and subnets to deploy additional workloads during the bootstrap process - typically CI/CD agents - -7. Azure Active Directory Applications and role assignment - - This a critical aspect of the launchpad bootstrap process. The deployment creates an Azure AD Application named "caf_launchpad_level0" by default. The launchpad can be configured to create additional Azure AD Applications - - * The user deploying the launchpad is set to be the application owner - * A Service Principal + random password is created for each Application - the data is then stored in the referenced keyvault as multiple secrets - * Resource Access is assigned based on the aad_api_permissions object - * Each application can be assigned one or multiple Azure AD roles through the aad_roles object - empty by default - - By default the underlying service principal will be granted **owner** access to the subscription targeted by the launchpad deployment. This Azure AD Application + Service Principal will be used in subsequent deployments using the Rover. - - API permissions and admin consent are also granted during the bootstrap process. The grant_consent.sh scripts is called for to enable API access for a given Application - * The variable `aad_api_permissions` object can contains multiple entries - * each key references one of the Application defined in the `aad_apps` variable. The content of each entry is an api permission definition. - - The objectId, ApplicationId, ServicePrincipalID, client_secret are each stored in a keyvault using the secret_prefix value as defined in the code example - - The example below shows an App Definition, a role assignment and an API permission assignment. using three terraform variables with define an app called "caf_launchpad_github_terraformdev_github-integration-landingzones", we assign the Application Developer role to this application, finally we grand admin consent to the Active Directory Graph APIs. - - ```terraform - aad_apps = { - azure_caf-terraform-landingzones = { - application_name = "caf_launchpad_github_terraformdev_github-integration-landingzones" - password_expire_in_days = 60 - tenant_name = "terraformdev.onmicrosoft.com" - keyvault = { - keyvault_key = "launchpad" - secret_prefix = "caf-launchpad-github-terraformdev-github-integration-landingzones" - } - } - } - aad_roles = { - azure_caf-terraform-landingzones = { - roles = [ - "Application Developer" - ] - } - } - - aad_api_permissions = { - azure_caf-terraform-landingzones = { - active_directory_graph = { - resource_app_id = "00000002-0000-0000-c000-000000000000" - resource_access = { - active_directory_graph_resource_access_id_Application_ReadWrite_OwnedBy = { - id = "824c81eb-e3f8-4ee6-8f6d-de7f50d565b7" - type = "Role" - } - active_directory_graph_resource_access_id_Directory_ReadWrite_All = { - id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175" - type = "Role" - } - } - } - } - } - ``` - - The Azure Active Directory Application creation, Role assignment and Admin Consent delegation plays a critical role in the launchpad bootstrapping process. Make sure to work with your Tenant administrators to define the scope and the roles assigned the Application created by the launchpad. - -8. Release Agents (Optional): - * Deploys Virtual machines in the targeted Virtual Network. You may choose to leverage an existing Azure DevOps organization and deploy CI/CD agents and pipelines. The Agents will then be in charge of subsequent rover deployments to automate the IaC provisioning with Terraform - -## Launchpad add-ons - -Add-ons are additional capabilities to enhance the launchpad, that are deployed separately and managed by a different state. - -Current add-ons: - -* Azure DevOps Self Hosted Agents and Pipeline - -In-development add-ons: - -* Terrform Cloud Enterprise -* GitHub Actions diff --git a/landingzones.old/caf_launchpad/scenario/100/README.md b/landingzones.old/caf_launchpad/scenario/100/README.md deleted file mode 100644 index dfa8197a7..000000000 --- a/landingzones.old/caf_launchpad/scenario/100/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Launchpad - scenario 100 - -The 100 scenario is designed to demonstrate a basic functional foundations to store Terraform state on Azure storage and use it centrally. -The focus of this scenario is to be able to deploy a basic launchpad from a remote machine and use the portal to review the settings in a non-constrained environment. -For example in this scenario you can go to the Key Vaults and view the secrets from the portal, a feature that is disabled in the 300+ scenarios. -We recommend using the 100 scenario for demonstration purposes. - -An estimated time of 5 minutes is required to deploy this scenario. - -## Pre-requisites - -This scenario require the following privileges: - -| Component | Privileges | -|--------------------|--------------------| -| Active Directory | None | -| Azure subscription | Subscription owner | - -## Deployment - -```bash -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad -var-folder \ - /tf/caf/landingzones/caf_launchpad/scenario/100 \ - -a apply - -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/100 \ - -a destroy -``` - -## Architecture diagram -![Launchpad 100](../../documentation/img/launchpad-100.PNG) - -## Services deployed in this scenario - -| Component | Purpose | -|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Resource group | Multiple resource groups are created to isolate the services. | -| Storage account | A storage account for remote tfstate management is provided for each level of the framework. Additional storage accounts are created for diagnostic logs. | -| Key Vault | The launchpad Key Vault hosts all secrets required by the rover to access the remote states, the Key Vault policies are created allowing the logged-in user to see secrets created and stored. | -| Virtual network | To secure the communication between the services a dedicated virtual network is deployed with a gateway subnet, bastion service, jumpbox and azure devops release agents. Service endpoints is enabled but not configured. | -| Azure AD Applications | An Azure AD application is created. This account is mainly use to bootstrap the services during the initialization. It is also considered as a breakglass account for the launchpad landing zones | diff --git a/landingzones.old/caf_launchpad/scenario/100/configuration.tfvars b/landingzones.old/caf_launchpad/scenario/100/configuration.tfvars deleted file mode 100644 index ad53a6ba0..000000000 --- a/landingzones.old/caf_launchpad/scenario/100/configuration.tfvars +++ /dev/null @@ -1,68 +0,0 @@ -landingzone = { - backend_type = "azurerm" - level = "level0" - key = "launchpad" -} - - -# Default region. When not set to a resource it will use that value -default_region = "region1" - -# naming convention settings -# for more settings on naming convention, please refer to the provider documentation: https://github.com/aztfmod/terraform-provider-azurecaf -# -# passthrough means the default CAF naming convention is not applied and you are responsible -# of the unicity of the names you are giving. the CAF provider will clear out -# passthrough = false -# adds random chars at the end of the names produced by the provider -# random_length = 3 - -# Inherit_tags defines if a resource will inherit it's resource group tags -inherit_tags = true - -regions = { - region1 = "southeastasia" - region2 = "eastasia" -} - -launchpad_key_names = { - azuread_app = "caf_launchpad_level0" - keyvault_client_secret = "aadapp-caf-launchpad-level0" - tfstates = [ - "level0", - ] -} - -resource_groups = { - level0 = { - name = "launchpad-level0" - tags = { - level = "level0" - } - } - level1 = { - name = "launchpad-level1" - tags = { - level = "level1" - } - } - level2 = { - name = "launchpad-level2" - tags = { - level = "level2" - } - } - level3 = { - name = "launchpad-level3" - tags = { - level = "level3" - } - } - level4 = { - name = "launchpad-level4" - tags = { - level = "level4" - } - } -} - diff --git a/landingzones.old/caf_launchpad/scenario/100/dynamic_secrets.tfvars b/landingzones.old/caf_launchpad/scenario/100/dynamic_secrets.tfvars deleted file mode 100644 index 23a0258d4..000000000 --- a/landingzones.old/caf_launchpad/scenario/100/dynamic_secrets.tfvars +++ /dev/null @@ -1,114 +0,0 @@ - -# Store output attributes into keyvault secret -# Those values are used by the rover to connect the current remote state and -# identity the lower level -dynamic_keyvault_secrets = { - level0 = { - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level1 = { - lower_stg = { - output_key = "storage_accounts" - resource_key = "level0" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level0" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level2 = { - lower_stg = { - output_key = "storage_accounts" - resource_key = "level1" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level1" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level3 = { - lower_stg = { - output_key = "storage_accounts" - resource_key = "level2" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level2" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level4 = { - lower_stg = { - output_key = "storage_accounts" - resource_key = "level3" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level3" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/100/iam_role_mapping.tfvars b/landingzones.old/caf_launchpad/scenario/100/iam_role_mapping.tfvars deleted file mode 100644 index 87a218b80..000000000 --- a/landingzones.old/caf_launchpad/scenario/100/iam_role_mapping.tfvars +++ /dev/null @@ -1,47 +0,0 @@ - -# -# Services supported: subscriptions, storage accounts and resource groups -# Can assign roles to: AD groups, AD object ID, AD applications, Managed identities -# -role_mapping = { - built_in_role_mapping = { - storage_accounts = { - level0 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - level1 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - level2 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - level3 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - level4 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - } - } - } - } - -} diff --git a/landingzones.old/caf_launchpad/scenario/100/keyvaults.tfvars b/landingzones.old/caf_launchpad/scenario/100/keyvaults.tfvars deleted file mode 100644 index 00de22b41..000000000 --- a/landingzones.old/caf_launchpad/scenario/100/keyvaults.tfvars +++ /dev/null @@ -1,99 +0,0 @@ - -keyvaults = { - level0 = { - name = "level0" - resource_group_key = "level0" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level0" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - } - - level1 = { - name = "level1" - resource_group_key = "level1" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level1" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - } - - level2 = { - name = "level2" - resource_group_key = "level2" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level2" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - } - - level3 = { - name = "level3" - resource_group_key = "level3" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level3" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - } - - level4 = { - name = "level4" - resource_group_key = "level4" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level4" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - } -} diff --git a/landingzones.old/caf_launchpad/scenario/100/storage_accounts.tfvars b/landingzones.old/caf_launchpad/scenario/100/storage_accounts.tfvars deleted file mode 100644 index bb2834b9c..000000000 --- a/landingzones.old/caf_launchpad/scenario/100/storage_accounts.tfvars +++ /dev/null @@ -1,102 +0,0 @@ - -storage_accounts = { - level0 = { - name = "level0" - resource_group_key = "level0" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - ## Those tags must never be changed after being set as they are used by the rover to locate the launchpad and the tfstates. - # Only adjust the environment value at creation time - tfstate = "level0" - environment = "sandpit" - launchpad = "launchpad" - ## - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - - level1 = { - name = "level1" - resource_group_key = "level1" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level1" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level2 = { - name = "level2" - resource_group_key = "level2" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level2" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level3 = { - name = "level3" - resource_group_key = "level3" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level3" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level4 = { - name = "level4" - resource_group_key = "level4" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level4" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - - } - -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/compute.tfvars b/landingzones.old/caf_launchpad/scenario/200/compute.tfvars deleted file mode 100644 index 88164c5a4..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/compute.tfvars +++ /dev/null @@ -1,100 +0,0 @@ -################################################## -# -# Compute resources -# -################################################## - -bastion_hosts = { - launchpad_host = { - name = "bastion" - resource_group_key = "bastion_launchpad" - vnet_key = "devops_region1" - subnet_key = "AzureBastionSubnet" - public_ip_key = "bastion_host_rg1" - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "bastion_host" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - } -} - -# Virtual machines -virtual_machines = { - - # Configuration to deploy a bastion host linux virtual machine - bastion_host = { - resource_group_key = "bastion_launchpad" - region = "region1" - boot_diagnostics_storage_account_key = "bootdiag_region1" - provision_vm_agent = true - - os_type = "linux" - - # the auto-generated ssh key in keyvault secret. Secret name being {VM name}-ssh-public and {VM name}-ssh-private - keyvault_key = "secrets" - - # Define the number of networking cards to attach the virtual machine - networking_interfaces = { - nic0 = { - # Value of the keys from networking.tfvars - vnet_key = "devops_region1" - subnet_key = "jumpbox" - name = "0" - enable_ip_forwarding = false - internal_dns_name_label = "nic0" - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "network_interface_card" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - } - - virtual_machine_settings = { - linux = { - name = "bastion" - size = "Standard_F2" - admin_username = "adminuser" - disable_password_authentication = true - custom_data = "scripts/cloud-init-install-rover-tools.config" - - # Value of the nic keys to attach the VM. The first one in the list is the default nic - network_interface_keys = ["nic0"] - - os_disk = { - name = "bastion-os" - caching = "ReadWrite" - storage_account_type = "Standard_LRS" - } - - source_image_reference = { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "18.04-LTS" - version = "latest" - } - - identity = { - type = "UserAssigned" - managed_identity_keys = [ - "level0", "level1", "level2", "level3", "level4" - ] - } - - } - } - - } -} - diff --git a/landingzones.old/caf_launchpad/scenario/200/configuration.tfvars b/landingzones.old/caf_launchpad/scenario/200/configuration.tfvars deleted file mode 100644 index 36645019e..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/configuration.tfvars +++ /dev/null @@ -1,100 +0,0 @@ -landingzone = { - backend_type = "azurerm" - level = "level0" - key = "launchpad" -} - -enable = { - bastion_hosts = false - virtual_machines = false -} - -# Default region. When not set to a resource it will use that value -default_region = "region1" - -regions = { - region1 = "southeastasia" - region2 = "eastasia" -} - -# core tags to be applied accross this landing zone -tags = { - owner = "CAF" - deploymentType = "Terraform" - costCenter = "0" - BusinessUnit = "SHARED" - DR = "NON-DR-ENABLED" -} - -# naming convention settings -# for more settings on naming convention, please refer to the provider documentation: https://github.com/aztfmod/terraform-provider-azurecaf -# -# passthrough means the default CAF naming convention is not applied and you are responsible -# of the unicity of the names you are giving. the CAF provider will clear out -# passthrough = false -# adds random chars at the end of the names produced by the provider -# random_length = 3 - -# all resources deployed will inherit tags from the parent resource group -inherit_tags = true - -launchpad_key_names = { - azuread_app = "caf_launchpad_level0" - keyvault_client_secret = "aadapp-caf-launchpad-level0" - tfstates = [ - "level0", - "level1", - "level2", - "level3", - "level4" - ] -} - -resource_groups = { - level0 = { - name = "launchpad-level0" - tags = { - level = "level0" - } - } - level1 = { - name = "launchpad-level1" - tags = { - level = "level1" - } - } - level2 = { - name = "launchpad-level2" - tags = { - level = "level2" - } - } - level3 = { - name = "launchpad-level3" - tags = { - level = "level3" - } - } - level4 = { - name = "launchpad-level4" - tags = { - level = "level4" - } - } - security = { - name = "launchpad-security" - } - networking = { - name = "launchpad-networking" - } - ops = { - name = "operations" - } - siem = { - name = "siem-logs" - } - bastion_launchpad = { - name = "launchpad-bastion" - } -} - diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars deleted file mode 100644 index 75c3e3e90..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/diagnostic_event_hub_namespaces.tfvars +++ /dev/null @@ -1,20 +0,0 @@ - -# Event hub diagnostics -diagnostic_event_hub_namespaces = { - central_logs_region1 = { - name = "logs" - resource_group_key = "ops" - sku = "Standard" - region = "region1" - - diagnostic_profiles = { - central_logs_region1 = { - definition_key = "event_hub_namespace" - destination_type = "storage" - destination_key = "all_regions" - } - } - } -} - - diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars deleted file mode 100644 index fd2cb048f..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/diagnostic_log_analytics.tfvars +++ /dev/null @@ -1,48 +0,0 @@ -# -# Define the settings for log analytics workspace and solution map -# -diagnostic_log_analytics = { - central_logs_region1 = { - region = "region1" - name = "logs" - resource_group_key = "ops" - # you can setup up to 5 key - diagnostic_profiles = { - central_logs_region1 = { - definition_key = "log_analytics" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - solutions_maps = { - NetworkMonitoring = { - "publisher" = "Microsoft" - "product" = "OMSGallery/NetworkMonitoring" - }, - ADAssessment = { - "publisher" = "Microsoft" - "product" = "OMSGallery/ADAssessment" - }, - ADReplication = { - "publisher" = "Microsoft" - "product" = "OMSGallery/ADReplication" - }, - AgentHealthAssessment = { - "publisher" = "Microsoft" - "product" = "OMSGallery/AgentHealthAssessment" - }, - DnsAnalytics = { - "publisher" = "Microsoft" - "product" = "OMSGallery/DnsAnalytics" - }, - ContainerInsights = { - "publisher" = "Microsoft" - "product" = "OMSGallery/ContainerInsights" - }, - KeyVaultAnalytics = { - "publisher" = "Microsoft" - "product" = "OMSGallery/KeyVaultAnalytics" - } - } - } -} diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars deleted file mode 100644 index a58c5eee8..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/diagnostic_storage_accounts.tfvars +++ /dev/null @@ -1,64 +0,0 @@ -# Defines different repositories for the diagnostics logs -# Storage accounts, log analytics, event hubs - -diagnostic_storage_accounts = { - # Stores diagnostic logging for region1 - diaglogs_region1 = { - name = "diaglogsrg1" - region = "region1" - resource_group_key = "ops" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores diagnostic logging for region2 - diaglogs_region2 = { - name = "diaglogrg2" - region = "region2" - resource_group_key = "ops" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores security logs for siem default region" - diagsiem_region1 = { - name = "siemsg1" - resource_group_key = "siem" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores diagnostic logging for region2 - diagsiem_region2 = { - name = "siemrg2" - region = "region2" - resource_group_key = "siem" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores boot diagnostic for region1 - bootdiag_region1 = { - name = "bootrg1" - region = "region1" - resource_group_key = "ops" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } - # Stores boot diagnostic for region2 - bootdiag_region2 = { - name = "bootrg2" - region = "region2" - resource_group_key = "ops" - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - access_tier = "Cool" - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostics_definition.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostics_definition.tfvars deleted file mode 100644 index 10a20c4dd..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/diagnostics_definition.tfvars +++ /dev/null @@ -1,274 +0,0 @@ - -# -# Define a set of settings for the various type of Azure resources -# - -diagnostics_definition = { - log_analytics = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["Audit", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - default_all = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AuditEvent", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - bastion_host = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["BastionAuditLogs", true, false, 7], - ] - } - - } - - networking_all = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["VMProtectionAlerts", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - public_ip_address = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["DDoSProtectionNotifications", true, false, 7], - ["DDoSMitigationFlowLogs", true, false, 7], - ["DDoSMitigationReports", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - network_security_group = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["NetworkSecurityGroupEvent", true, false, 7], - ["NetworkSecurityGroupRuleCounter", true, false, 7], - ] - } - - } - - network_interface_card = { - name = "operational_logs_and_metrics" - categories = { - # log = [ - # # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - # ["AuditEvent", true, false, 7], - # ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - azure_container_registry = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["ContainerRegistryRepositoryEvents", true, false, 7], - ["ContainerRegistryLoginEvents", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - } - - azure_kubernetes_cluster = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["kube-apiserver", true, false, 7], - ["kube-audit", true, false, 7], - ["kube-audit-admin", true, false, 7], - ["kube-controller-manager", true, false, 7], - ["kube-scheduler", true, false, 7], - ["cluster-autoscaler", true, false, 7], - ["guard", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - } - - azure_site_recovery = { - name = "operational_logs_and_metrics" - log_analytics_destination_type = "Dedicated" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AzureBackupReport", true, true, 7], - ["CoreAzureBackup", true, true, 7], - ["AddonAzureBackupAlerts", true, true, 7], - ["AddonAzureBackupJobs", true, true, 7], - ["AddonAzureBackupPolicy", true, true, 7], - ["AddonAzureBackupProtectedInstance", true, true, 7], - ["AddonAzureBackupStorage", true, true, 7], - ["AzureSiteRecoveryJobs", true, true, 7], - ["AzureSiteRecoveryEvents", true, true, 7], - ["AzureSiteRecoveryReplicatedItems", true, true, 7], - ["AzureSiteRecoveryReplicationStats", true, true, 7], - ["AzureSiteRecoveryRecoveryPoints", true, true, 7], - ["AzureSiteRecoveryReplicationDataUploadRate", true, true, 7], - ["AzureSiteRecoveryProtectedDiskDataChurn", true, true, 30], - ] - metric = [ - #["AllMetrics", 60, True], - ] - } - - } - - azure_automation = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["JobLogs", true, true, 30], - ["JobStreams", true, true, 30], - ["DscNodeStatus", true, true, 30], - ] - metric = [ - # ["Category name", "Metric Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, true, 30], - ] - } - - } - - event_hub_namespace = { - name = "operational_logs_and_metrics" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["ArchiveLogs", true, false, 7], - ["OperationalLogs", true, false, 7], - ["AutoScaleLogs", true, false, 7], - ["KafkaCoordinatorLogs", true, false, 7], - ["KafkaUserErrorLogs", true, false, 7], - ["EventHubVNetConnectionEvent", true, false, 7], - ["CustomerManagedKeyUserLogs", true, false, 7], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", true, false, 7], - ] - } - - } - - compliance_all = { - name = "compliance_logs" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AuditEvent", true, true, 365], - ] - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", false, false, 7], - ] - } - - } - - siem_all = { - name = "siem" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AuditEvent", true, true, 0], - ] - - metric = [ - #["Category name", "Diagnostics Enabled(true/false)", "Retention Enabled(true/false)", Retention_period] - ["AllMetrics", false, false, 0], - ] - } - - } - - subscription_operations = { - name = "subscription_operations" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)"] - ["Administrative", true], - ["Security", true], - ["ServiceHealth", true], - ["Alert", true], - ["Policy", true], - ["Autoscale", true], - ["ResourceHealth", true], - ["Recommendation", true], - ] - } - } - - subscription_siem = { - name = "activity_logs_for_siem" - categories = { - log = [ - # ["Category name", "Diagnostics Enabled(true/false)"] - ["Administrative", false], - ["Security", true], - ["ServiceHealth", false], - ["Alert", false], - ["Policy", true], - ["Autoscale", false], - ["ResourceHealth", false], - ["Recommendation", false], - ] - } - - } - -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/diagnostics_destinations.tfvars b/landingzones.old/caf_launchpad/scenario/200/diagnostics_destinations.tfvars deleted file mode 100644 index 95ede1c24..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/diagnostics_destinations.tfvars +++ /dev/null @@ -1,31 +0,0 @@ -# Defines the different destination for the different log profiles -# Different profiles to target different operational teams - -diagnostics_destinations = { - # Storage keys must reference the azure region name - # For storage, reference "all_regions" and we will send the logs to the storage account - # in the region of the deployment - storage = { - all_regions = { - southeastasia = { - storage_account_key = "diagsiem_region1" - } - eastasia = { - storage_account_key = "diagsiem_region2" - } - } - } - - log_analytics = { - central_logs = { - log_analytics_key = "central_logs_region1" - log_analytics_destination_type = "Dedicated" - } - } - - event_hub_namespaces = { - central_logs = { - event_hub_namespace_key = "central_logs_region1" - } - } -} diff --git a/landingzones.old/caf_launchpad/scenario/200/dynamic_secrets.tfvars b/landingzones.old/caf_launchpad/scenario/200/dynamic_secrets.tfvars deleted file mode 100644 index 94042fd05..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/dynamic_secrets.tfvars +++ /dev/null @@ -1,152 +0,0 @@ - -# Store output attributes into keyvault secret -# Those values are used by the rover to connect the current remote state and -# identity the lower level -dynamic_keyvault_secrets = { - level0 = { - msi = { - output_key = "managed_identities" - resource_key = "level0" - attribute_key = "id" - secret_name = "msi-resource-id" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - admin = { - secret_name = "azdo-pat-admin" - value = "" - } - agent = { - secret_name = "azdo-pat-agent" - value = "" - } - } - level1 = { - msi = { - output_key = "managed_identities" - resource_key = "level1" - attribute_key = "id" - secret_name = "msi-resource-id" - } - lower_stg = { - output_key = "storage_accounts" - resource_key = "level0" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level0" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level2 = { - msi = { - output_key = "managed_identities" - resource_key = "level2" - attribute_key = "id" - secret_name = "msi-resource-id" - } - lower_stg = { - output_key = "storage_accounts" - resource_key = "level1" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level1" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level3 = { - msi = { - output_key = "managed_identities" - resource_key = "level3" - attribute_key = "id" - secret_name = "msi-resource-id" - } - lower_stg = { - output_key = "storage_accounts" - resource_key = "level2" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level2" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } - level4 = { - msi = { - output_key = "managed_identities" - resource_key = "level4" - attribute_key = "id" - secret_name = "msi-resource-id" - } - lower_stg = { - output_key = "storage_accounts" - resource_key = "level3" - attribute_key = "name" - secret_name = "lower-storage-account-name" - } - lower_rg = { - output_key = "resource_groups" - resource_key = "level3" - attribute_key = "name" - secret_name = "lower-resource-group-name" - } - subscription_id = { - output_key = "client_config" - attribute_key = "subscription_id" - secret_name = "subscription-id" - } - tenant_id = { - output_key = "client_config" - attribute_key = "tenant_id" - secret_name = "tenant-id" - } - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_azuread.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_azuread.tfvars deleted file mode 100644 index 4a4856f72..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/iam_azuread.tfvars +++ /dev/null @@ -1,184 +0,0 @@ - -azuread_groups = { - keyvault_level0_rw = { - name = "caf-level0-keyvault-rw" - description = "Provide read and write access to the keyvault secrets / level0." - members = { - user_principal_names = [ - ] - group_names = [] - object_ids = [] - group_keys = [] - - service_principal_keys = [ - "caf_launchpad_level0" - ] - - } - owners = { - user_principal_names = [ - ] - service_principal_keys = [ - "caf_launchpad_level0" - ] - } - prevent_duplicate_name = false - } - - keyvault_level1_rw = { - name = "caf-level1-landingzones-rw" - description = "Provide read and write access to manage landingzones / level1." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - keyvault_level2_rw = { - name = "caf-level2-landingzones-rw" - description = "Provide read and write access to manage landingzones / level2." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - keyvault_level3_rw = { - name = "caf-level3-landingzones-rw" - description = "Provide read and write access to manage landingzones / level3." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - keyvault_level4_rw = { - name = "caf-level4-applications" - description = "Provide read access to the applications who need to deploy on the level4." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - caf_launchpad_Reader = { - name = "caf-launchpad-Reader" - description = "Provide Reader role to the caf launchpad landing zone resource groups." - members = { - } - owners = { - - } - prevent_duplicate_name = false - } - - keyvault_password_rotation = { - name = "caf-level0-password-rotation-rw" - description = "Provide read and write access to the keyvault secrets / level0." - members = { - user_principal_names = [ - ] - group_names = [] - object_ids = [] - group_keys = [] - - service_principal_keys = [ - "caf_launchpad_level0" - ] - - } - owners = { - user_principal_names = [ - ] - service_principal_keys = [ - "caf_launchpad_level0" - ] - } - prevent_duplicate_name = false - } -} - -azuread_users = { - - # don't change that key - aad-user-devops-user-admin = { - useprefix = true - user_name = "caf-level0-security-devops-pat-rotation" - password_expire_in_days = 180 - - # Value must match with var.keyvaults[keyname] to store username and password for password rotation - keyvault_key = "secrets" - } - -} - -azuread_apps = { - # Do not rename the key "launchpad" to be able to upgrade to the standard launchpad - caf_launchpad_level0 = { - useprefix = true - application_name = "caf_launchpad_level0" - password_expire_in_days = 180 - - # Store the ${secret_prefix}-client-id, ${secret_prefix}-client-secret... - # Set the policy during the creation process of the launchpad - keyvaults = { - level0 = { - secret_prefix = "aadapp-caf-launchpad-level0" - } - } - } - -} - -# -# Available roles: -# az rest --method Get --uri https://graph.microsoft.com/v1.0/directoryRoleTemplates -o json | jq -r .value[].displayName -# -azuread_roles = { - azuread_apps = { - caf_launchpad_level0 = { - roles = [ - "Application Administrator", - "Application Developer", - "User Administrator" - ] - } - } - managed_identities = { - level0 = { - roles = [ - "Directory Readers", - "Application Developer", - "User Administrator" - ] - } - level1 = { - roles = [ - "Directory Readers" - ] - } - level2 = { - roles = [ - "Directory Readers" - ] - } - level3 = { - roles = [ - "Directory Readers" - ] - } - level4 = { - roles = [ - "Directory Readers" - ] - } - } -} diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars deleted file mode 100644 index f73f3b73d..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/iam_azuread_api_permissions.tfvars +++ /dev/null @@ -1,43 +0,0 @@ - - -azuread_api_permissions = { - - caf_launchpad_level0 = { - active_directory_graph = { - resource_app_id = "00000002-0000-0000-c000-000000000000" - resource_access = { - Application_ReadWrite_OwnedBy = { - id = "824c81eb-e3f8-4ee6-8f6d-de7f50d565b7" - type = "Role" - } - Directory_ReadWrite_All = { - id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175" - type = "Role" - } - } - } - - microsoft_graph = { - resource_app_id = "00000003-0000-0000-c000-000000000000" - resource_access = { - AppRoleAssignment_ReadWrite_All = { - id = "06b708a9-e830-4db3-a914-8e69da51d44f" - type = "Role" - } - DelegatedPermissionGrant_ReadWrite_All = { - id = "8e8e4742-1d95-4f68-9d56-6ee75648c72a" - type = "Role" - } - GroupReadWriteAll = { - id = "62a82d76-70ea-41e2-9197-370581804d09" - type = "Role" - } - RoleManagement_ReadWrite_Directory = { - id = "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8" - type = "Role" - } - } - } - } - -} diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_custom_roles.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_custom_roles.tfvars deleted file mode 100644 index f314abf3a..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/iam_custom_roles.tfvars +++ /dev/null @@ -1,76 +0,0 @@ - -custom_role_definitions = { - caf-launchpad = { - name = "caf-launchpad" - useprefix = true - description = "Provide addition permissions on top of built-in Contributor role to manage landing zones deployment" - permissions = { - actions = [ - "Microsoft.Authorization/roleAssignments/delete", - "Microsoft.Authorization/roleAssignments/read", - "Microsoft.Authorization/roleAssignments/write", - "Microsoft.Authorization/roleDefinitions/delete", - "Microsoft.Authorization/roleDefinitions/read", - "Microsoft.Authorization/roleDefinitions/write", - "microsoft.insights/diagnosticSettings/delete", - "microsoft.insights/diagnosticSettings/read", - "microsoft.insights/diagnosticSettings/write", - "Microsoft.KeyVault/vaults/delete", - "Microsoft.KeyVault/vaults/read", - "Microsoft.KeyVault/vaults/write", - "Microsoft.KeyVault/vaults/accessPolicies/write", - "Microsoft.Network/networkSecurityGroups/delete", - "Microsoft.Network/networkSecurityGroups/read", - "Microsoft.Network/networkSecurityGroups/write", - "Microsoft.Network/networkSecurityGroups/join/action", - "Microsoft.Network/virtualNetworks/subnets/delete", - "Microsoft.Network/virtualNetworks/subnets/read", - "Microsoft.Network/virtualNetworks/subnets/write", - "Microsoft.OperationalInsights/workspaces/delete", - "Microsoft.OperationalInsights/workspaces/read", - "Microsoft.OperationalInsights/workspaces/write", - "Microsoft.OperationalInsights/workspaces/sharedKeys/action", - "Microsoft.OperationsManagement/solutions/delete", - "Microsoft.OperationsManagement/solutions/read", - "Microsoft.OperationsManagement/solutions/write", - "Microsoft.Storage/storageAccounts/delete", - "Microsoft.Storage/storageAccounts/read", - "Microsoft.Storage/storageAccounts/write", - "Microsoft.Storage/storageAccounts/blobServices/containers/delete", - "Microsoft.Storage/storageAccounts/blobServices/containers/read", - "Microsoft.Storage/storageAccounts/blobServices/containers/write", - "Microsoft.Storage/storageAccounts/blobServices/containers/lease/action", - "Microsoft.Storage/storageAccounts/blobServices/read", - "Microsoft.Storage/storageAccounts/listKeys/action", - "Microsoft.Resources/subscriptions/providers/read", - "Microsoft.Resources/subscriptions/read", - "Microsoft.Resources/subscriptions/resourcegroups/delete", - "Microsoft.Resources/subscriptions/resourcegroups/read", - "Microsoft.Resources/subscriptions/resourcegroups/write", - "Microsoft.Network/virtualNetworks/delete", - "Microsoft.Network/virtualNetworks/read", - "Microsoft.Network/virtualNetworks/write", - ] - } - - } - - caf-launchpad-contributor = { - name = "caf-launchpad-contributor" - useprefix = true - description = "Provide addition permissions on top of built-in Contributor role to manage landing zones deployment" - permissions = { - actions = [ - "Microsoft.Authorization/roleAssignments/delete", - "Microsoft.Authorization/roleAssignments/read", - "Microsoft.Authorization/roleAssignments/write", - "Microsoft.Authorization/roleDefinitions/delete", - "Microsoft.Authorization/roleDefinitions/read", - "Microsoft.Authorization/roleDefinitions/write", - "Microsoft.Resources/subscriptions/providers/read" - ] - } - } - -} - diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars deleted file mode 100644 index e755b1ebd..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars +++ /dev/null @@ -1,114 +0,0 @@ -keyvault_access_policies_azuread_apps = { - level0 = { - caf_launchpad_level0 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - # A maximum of 16 access policies per keyvault - level1 = { - caf_launchpad_level0 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # A maximum of 16 access policies per keyvault - level2 = { - caf_launchpad_level0 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - - # A maximum of 16 access policies per keyvault - level3 = { - caf_launchpad_level0 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - - # A maximum of 16 access policies per keyvault - level4 = { - caf_launchpad_level1 = { - # Reference a key to an azure ad applications - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - - secrets = { - caf_launchpad_level0 = { - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } -} - -keyvault_access_policies = { - # A maximum of 16 access policies per keyvault - level0 = { - keyvault_level0_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - # A maximum of 16 access policies per keyvault - level1 = { - keyvault_level1_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level1_rw" - secret_permissions = ["Get", "List"] - } - } - - # A maximum of 16 access policies per keyvault - level2 = { - keyvault_level2_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level2_rw" - secret_permissions = ["Get", "List"] - } - } - - - # A maximum of 16 access policies per keyvault - level3 = { - keyvault_level3_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level3_rw" - secret_permissions = ["Get", "List"] - } - } - - - # A maximum of 16 access policies per keyvault - level4 = { - keyvault_level4_rw = { - # Reference a key to an azure ad group - azuread_group_key = "keyvault_level4_rw" - secret_permissions = ["Get", "List"] - } - } - - - secrets = { - keyvault_level0_rw = { - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - keyvault_password_rotation = { - azuread_group_key = "keyvault_password_rotation" - secret_permissions = ["Set", "Get", "List", "Delete", ] - } - } -} diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_managed_identities.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_managed_identities.tfvars deleted file mode 100644 index a5e76137c..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/iam_managed_identities.tfvars +++ /dev/null @@ -1,32 +0,0 @@ - -managed_identities = { - level0 = { - # Used by the release agent to access the level0 keyvault and storage account with the tfstates in read / write - name = "landingzone-level0-msi" - resource_group_key = "security" - } - level1 = { - # Used by the release agent to access the level1 keyvault and storage account with the tfstates in read / write - # Has read access to level0 - name = "landingzone-level1-msi" - resource_group_key = "security" - } - level2 = { - # Used by the release agent to access the level2 keyvault and storage account with the tfstates in read / write - # Has read access to level1 - name = "landingzone-level2-msi" - resource_group_key = "security" - } - level3 = { - # Used by the release agent to access the level3 keyvault and storage account with the tfstates in read / write - # Has read access to level2 - name = "landingzone-level3-msi" - resource_group_key = "security" - } - level4 = { - # Used by the release agent to access the level4 keyvault and storage account with the tfstates in read / write - # Has read access to level3 - name = "landingzone-level4-msi" - resource_group_key = "security" - } -} diff --git a/landingzones.old/caf_launchpad/scenario/200/iam_role_mapping.tfvars b/landingzones.old/caf_launchpad/scenario/200/iam_role_mapping.tfvars deleted file mode 100644 index 23a919f2a..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/iam_role_mapping.tfvars +++ /dev/null @@ -1,154 +0,0 @@ - -# -# Services supported: subscriptions, storage accounts and resource groups -# Can assign roles to: AD groups, AD object ID, AD applications, Managed identities -# -role_mapping = { - custom_role_mapping = { - subscriptions = { - logged_in_subscription = { - "caf-launchpad-contributor" = { - azuread_groups = { - keys = ["keyvault_level0_rw", "keyvault_level1_rw", "keyvault_level2_rw", "keyvault_level3_rw", "keyvault_level4_rw", ] - } - managed_identities = { - keys = ["level0", "level1", "level2", "level3", "level4"] - } - azuread_apps = { - keys = ["caf_launchpad_level0"] - } - } - } - } - } - - built_in_role_mapping = { - subscriptions = { - logged_in_subscription = { - "Contributor" = { - azuread_apps = { - keys = ["caf_launchpad_level0"] - } - managed_identities = { - keys = ["level0", "level1", "level2", "level3", "level4"] - } - } - } - } - resource_groups = { - level0 = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - security = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - networking = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - ops = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - siem = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } - } - storage_accounts = { - level0 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - azuread_groups = { - keys = ["keyvault_level0_rw"] - } - azuread_apps = { - keys = ["caf_launchpad_level0"] - } - managed_identities = { - keys = ["level0"] - } - } - "Storage Blob Data Reader" = { - azuread_groups = { - keys = ["keyvault_level1_rw"] - } - } - } - level1 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - azuread_groups = { - keys = ["keyvault_level1_rw"] - } - managed_identities = { - keys = ["level1"] - } - } - "Storage Blob Data Reader" = { - azuread_groups = { - keys = ["keyvault_level2_rw"] - } - } - } - level2 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - azuread_groups = { - keys = ["keyvault_level2_rw"] - } - managed_identities = { - keys = ["level2"] - } - } - "Storage Blob Data Reader" = { - azuread_groups = { - keys = ["keyvault_level3_rw"] - } - } - } - level3 = { - "Storage Blob Data Contributor" = { - logged_in = { - keys = ["user"] - } - azuread_groups = { - keys = ["keyvault_level3_rw"] - } - managed_identities = { - keys = ["level3"] - } - } - "Storage Blob Data Reader" = { - azuread_groups = { - keys = ["keyvault_level4_rw"] - } - } - } - } - } - -} diff --git a/landingzones.old/caf_launchpad/scenario/200/keyvaults.tfvars b/landingzones.old/caf_launchpad/scenario/200/keyvaults.tfvars deleted file mode 100644 index 9b407a31d..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/keyvaults.tfvars +++ /dev/null @@ -1,204 +0,0 @@ - -keyvaults = { - level0 = { - name = "level0" - resource_group_key = "level0" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level0" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - level1 = { - name = "level1" - resource_group_key = "level1" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level1" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - level2 = { - name = "level2" - resource_group_key = "level2" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level2" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - level3 = { - name = "level3" - resource_group_key = "level3" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level3" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - level4 = { - name = "level4" - resource_group_key = "level4" - sku_name = "standard" - soft_delete_enabled = true - tags = { - tfstate = "level4" - environment = "sandpit" - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } - - secrets = { - name = "secrets" - resource_group_key = "security" - region = "region1" - sku_name = "premium" - soft_delete_enabled = true - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - - } -} diff --git a/landingzones.old/caf_launchpad/scenario/200/networking.tfvars b/landingzones.old/caf_launchpad/scenario/200/networking.tfvars deleted file mode 100644 index e21c316fe..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/networking.tfvars +++ /dev/null @@ -1,110 +0,0 @@ - -################################################## -# -# Networking resources -# -################################################## - - -public_ip_addresses = { - bastion_host_rg1 = { - name = "pip1" - resource_group_key = "networking" - sku = "Standard" - allocation_method = "Static" - ip_version = "IPv4" - idle_timeout_in_minutes = "4" - - # you can setup up to 5 key - diagnostic_profiles = { - bastion_host_rg1 = { - definition_key = "public_ip_address" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - } -} - -vnets = { - devops_region1 = { - resource_group_key = "networking" - region = "region1" - vnet = { - name = "devops" - address_space = ["10.100.100.0/24"] - } - specialsubnets = {} - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["10.100.100.24/29"] - nsg_key = "azure_bastion_nsg" - } - jumpbox = { - name = "jumpbox" - cidr = ["10.100.100.32/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level0 = { - name = "level0" - cidr = ["10.100.100.40/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level1 = { - name = "level1" - cidr = ["10.100.100.48/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level2 = { - name = "level2" - cidr = ["10.100.100.56/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level3 = { - name = "level3" - cidr = ["10.100.100.64/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - release_agent_level4 = { - name = "level4" - cidr = ["10.100.100.72/29"] - service_endpoints = ["Microsoft.KeyVault"] - } - private_endpoints = { - name = "private_endpoints" - cidr = ["10.100.100.128/25"] - enforce_private_link_endpoint_network_policies = true - } - } - - # you can setup up to 5 keys - vnet diganostic - diagnostic_profiles = { - vnet = { - definition_key = "networking_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - } -} - - -route_tables = { - default_no_internet = { - name = "default_no_internet" - resource_group_key = "networking" - } -} - -azurerm_routes = { - no_internet = { - name = "no_internet" - resource_group_key = "networking" - route_table_key = "default_no_internet" - address_prefix = "0.0.0.0/0" - next_hop_type = "None" - } -} diff --git a/landingzones.old/caf_launchpad/scenario/200/networking_nsg_definition.tfvars b/landingzones.old/caf_launchpad/scenario/200/networking_nsg_definition.tfvars deleted file mode 100644 index 8b558b104..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/networking_nsg_definition.tfvars +++ /dev/null @@ -1,141 +0,0 @@ - -# -# Definition of the networking security groups -# -network_security_group_definition = { - # This entry is applied to all subnets with no NSG defined - empty_nsg = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } - - azure_bastion_nsg = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } - - jumphost = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "ssh-inbound-22", - priority = "200" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - -} diff --git a/landingzones.old/caf_launchpad/scenario/200/readme.md b/landingzones.old/caf_launchpad/scenario/200/readme.md deleted file mode 100644 index 82f7b4440..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/readme.md +++ /dev/null @@ -1,56 +0,0 @@ -# Launchpad - scenario 200 - -The 200 scenario is an extension of the 100 scenario, meaning you can upgrade a 100 scenario to a 200. -The 200 scenario is designed to demonstrate a more secure environment but is not recommended for production use. -The focus of this scenario is to be able to deploy a more advanced launchpad from a remote machine and use the portal to review the settings in a non-constrained environment. -For example in this scenario you can go to the Key Vaults and view the secrets from the portal. A feature that is disabled in the 300+ scenarios. We recommend using the 200 scenario for demonstration or building new capabilities. - -An estimated time of 20 minutes is required to deploy this scenario. - -## Pre-requisites - -This scenario require the following privileges: - -| Component | Privileges | -|--------------------|--------------------------------| -| Active Directory | Application Administrator role | -| Azure subscription | Subscription owner | - -## Deployment - -```bash -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ - -level level0 \ - -a apply - -rover -lz /tf/caf/landingzones/caf_launchpad \ - -launchpad \ - -var-folder /tf/caf/landingzones/caf_launchpad/scenario/200 \ - -level level0 \ - -a destroy -``` - -## Architecture diagram - -![Launchpad 200](../../documentation/img/launchpad-200.png) - -## Services deployed in this scenario - -| Component | Purpose | -|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Resource group | Multiple resource groups are created to isolate the services | -| Storage account | A storage account for remote tfstate management is provided for each level of the framework. Additional storage accounts are created for diagnostic logs. | -| Keyvault | The launchpad keyvault hosts all secrets required by the rover to access the remote states. The secret keyvault is used to host all Azure AD users, applications and virtual machines's ssh key. | -| Virtual network | To secure the communication between the services a dedicated virtual network is deployed with a gateway subnet, bastion service, jumpbox and azure DevOps release agents. Service endpoints is enabled but not configured. | -| Bastion host service | Is use to support the access to the rover in scenario 300 and 400. | -| Jumpbox | A Linux server with the docker engine to run the rover and perform the deployment of the scenario 300 and 400. | -| Log analytics | A central log analytics workspace is created to collect all diagnostics and metrics information. Solutions are also deployed. | -| Diagnostic profiles | Default settings with 7 days retention of diagnostic profile is provided for all services. | -| Diagnostic destination | Operation sends the logs to a log analytics workspace and SIEM send all security logs to a storage account. | -| Diagnostic | Is enabled by default on all services. | -| Azure AD Users | An Azure AD user is created. This user is used in scenario 300 and 400 to own the Azure DevOps Personal Access Token (PAT) rotation. | -| Azure AD Applications | An Azure AD application is created. This account is mainly use to bootstrap the services during the initialization. It is also considered as a breakglass account for the launchpad landing zones. | -| Azure AD API permissions | A set of API permissions assigned to the Azure AD application to support management of the landing zones in a pipeline. | -| Managed Identities | A user managed Identity account is created for each Azure DevOps agent. This account is configured to get access to the keyvaults and Azure storage accounts | \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/storage_accounts.tfvars b/landingzones.old/caf_launchpad/scenario/200/storage_accounts.tfvars deleted file mode 100644 index bd60a50f5..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/storage_accounts.tfvars +++ /dev/null @@ -1,101 +0,0 @@ - -storage_accounts = { - level0 = { - name = "level0" - resource_group_key = "level0" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - ## Those tags must never be changed after being set as they are used by the rover to locate the launchpad and the tfstates. - # Only adjust the environment value at creation time - tfstate = "level0" - environment = "sandpit" - launchpad = "launchpad" - ## - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level1 = { - name = "level1" - resource_group_key = "level1" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level1" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level2 = { - name = "level2" - resource_group_key = "level2" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level2" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level3 = { - name = "level3" - resource_group_key = "level3" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level3" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - } - - level4 = { - name = "level4" - resource_group_key = "level4" - account_kind = "BlobStorage" - account_tier = "Standard" - account_replication_type = "RAGRS" - tags = { - # Those tags must never be changed while set as they are used by the rover to locate the launchpad and the tfstates. - tfstate = "level4" - environment = "sandpit" - launchpad = "launchpad" - } - containers = { - tfstate = { - name = "tfstate" - } - } - - } - -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scenario/200/subscriptions.tfvars b/landingzones.old/caf_launchpad/scenario/200/subscriptions.tfvars deleted file mode 100644 index 9e98ae770..000000000 --- a/landingzones.old/caf_launchpad/scenario/200/subscriptions.tfvars +++ /dev/null @@ -1,20 +0,0 @@ - -subscriptions = { - logged_in_subscription = { - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "subscription_operations" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "subscription_siem" - destination_type = "storage" - destination_key = "all_regions" - } - } - - } -} \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scripts/cloud-init-install-rover-tools.config b/landingzones.old/caf_launchpad/scripts/cloud-init-install-rover-tools.config deleted file mode 100644 index 53cd432e8..000000000 --- a/landingzones.old/caf_launchpad/scripts/cloud-init-install-rover-tools.config +++ /dev/null @@ -1,49 +0,0 @@ -#cloud-config - -apt: - preserve_sources_list: true - sources: - azure-cli.list: - source: "deb https://packages.microsoft.com/repos/azure-cli/ bionic main" - key: | - -----BEGIN PGP PUBLIC KEY BLOCK----- - Version: GnuPG v1.4.7 (GNU/Linux) - - mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT - LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV - 7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag - OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j - H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr - M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs - ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC - AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH - /32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe - MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy - 7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV - KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ - XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+ - NdCFTW7wY0Fb1fWJ+/KTsC4= - =J6gs - -----END PGP PUBLIC KEY BLOCK----- -package_update: true - -packages: - - ca-certificates - - curl - - apt-transport-https - - lsb-release - - azure-cli - -snap: - commands: - - snap install kubectl --classic -# Install docker and docker-compose -runcmd: - - [ sh, -c, 'curl -sSL https://get.docker.com/ | sh' ] - - [ sh, -c, 'curl -L https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep "tag_name" | cut -d \" -f4)/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose' ] - - [ sh, -c, 'sudo chmod +x /usr/local/bin/docker-compose' ] - -# Add default auto created user to docker group -system_info: - default_user: - groups: [docker] \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/scripts/grant_consent.sh b/landingzones.old/caf_launchpad/scripts/grant_consent.sh deleted file mode 100644 index 620e18488..000000000 --- a/landingzones.old/caf_launchpad/scripts/grant_consent.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -set -e - - -user_type=$(az account show --query user.type -o tsv) - -if [ ${user_type} == "user" ]; then - - az ad app permission admin-consent --id ${applicationId} - -else - - resourceId=$(az ad sp show --id "${resourceAppId}" --query "objectId" -o tsv) - echo " -resourceId: ${resourceId}" - - URI=$(echo "https://graph.microsoft.com/beta/servicePrincipals/${resourceId}/appRoleAssignments") && echo " - uri: $URI" - - # grant consent (Application.ReadWrite.OwnedBy) - JSON=$( jq -n \ - --arg principalId "${principalId}" \ - --arg resourceId "${resourceId}" \ - --arg appRoleId "${appRoleId}" \ - '{principalId: $principalId, resourceId: $resourceId, appRoleId: $appRoleId}' ) && echo " - body: $JSON" - - az rest --method POST --uri $URI --header Content-Type=application/json --body "$JSON" - -fi \ No newline at end of file diff --git a/landingzones.old/caf_launchpad/variables.tf b/landingzones.old/caf_launchpad/variables.tf deleted file mode 100644 index 4836eda20..000000000 --- a/landingzones.old/caf_launchpad/variables.tf +++ /dev/null @@ -1,191 +0,0 @@ -# Map of the current tfstate -variable "tfstate_storage_account_name" { - default = null -} -variable "tfstate_container_name" { - default = null -} -variable "tfstate_key" { - default = null -} -variable "tfstate_resource_group_name" { - default = null -} - -variable "tenant_id" {} -variable "landingzone" { - description = "The landing zone name is used to reference the tfstate in configuration files. Therefore while set it is recommended not to change" -} - -variable "passthrough" { - default = false -} -variable "random_length" { - default = null -} - -variable "inherit_tags" { - default = false -} - -variable "default_region" { - description = "Define the default region where services are deployed if the location is not set at the resource level" - default = "region1" -} - -variable "regions" { - type = map(any) - description = "List of the regions where services can be deployed. This impact the diagnostics logs settings" - default = { - region1 = "southeastasia" - } -} - -variable "enable" { - description = "Map of services defined in the configuration file you want to disable during a deployment" - default = {} -} - -variable "prefix" { - default = null -} - -variable "use_slug" { - default = true -} - -variable "log_analytics" { - default = {} -} - -variable "event_hub_namespaces" { - default = {} -} - -# Do not change the default value to be able to upgrade to the standard launchpad -variable "tf_name" { - description = "Name of the terraform state in the blob storage (Does not include the extension .tfstate). Setup by the rover. Leave empty in the configuration file" - default = "" -} - -variable "resource_groups" {} - -variable "storage_accounts" {} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "diagnostic_event_hub_namespaces" { - default = {} -} -variable "diagnostic_log_analytics" { - default = {} -} -variable "keyvaults" {} -variable "keyvault_access_policies" { - default = {} -} -variable "dynamic_keyvault_secrets" {} - -variable "subscriptions" { - default = {} -} - -## Azure Active Directory -variable "azuread_apps" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "azuread_users" { - default = {} -} -variable "azuread_roles" { - default = {} -} -variable "managed_identities" { - default = {} -} - -variable "virtual_machines" { - description = "Virtual machine object" - default = {} -} - -variable "bastion_hosts" { - default = {} -} - -variable "launchpad_key_names" {} - -variable "custom_role_definitions" { - default = {} -} -variable "role_mapping" { - default = { - built_in_role_mapping = {} - custom_role_mapping = {} - } -} - -variable "tags" { - type = map(any) - default = {} -} - -variable "rover_version" {} - -variable "user_type" {} - -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} - -variable "aad_users" { - default = {} -} - -variable "aad_roles" { - default = {} -} - -variable "azuread_api_permissions" { - default = {} -} - -variable "environment" { - type = string - description = "This variable is set by the rover during the deployment based on the -env or -environment flags. Default to sandpit" -} - -variable "diagnostics_definition" { - default = {} -} -variable "diagnostics_destinations" { - default = {} -} - -variable "vnets" { - default = {} -} - -variable "network_security_group_definition" { - default = {} -} - -variable "public_ip_addresses" { - default = {} -} -variable "route_tables" { - default = {} -} -variable "azurerm_routes" { - default = {} -} - -variable "keyvault_access_policies_azuread_apps" { - default = {} -} diff --git a/landingzones.old/caf_networking/backend.azurerm b/landingzones.old/caf_networking/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones.old/caf_networking/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones.old/caf_networking/documentation/img/100-single-region-hub.png b/landingzones.old/caf_networking/documentation/img/100-single-region-hub.png deleted file mode 100644 index 48aac6a450d95538c053352826e83e21ca30bfce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17963 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 diff --git a/landingzones.old/caf_networking/documentation/img/101-multi-region-hub.png b/landingzones.old/caf_networking/documentation/img/101-multi-region-hub.png deleted file mode 100644 index 48f2cd59d88f0a352679461b5e709591c2b27184..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42683 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 G3HTp~PdelP diff --git a/landingzones.old/caf_networking/documentation/img/106-hub-virtual-wan-firewall.png b/landingzones.old/caf_networking/documentation/img/106-hub-virtual-wan-firewall.png deleted file mode 100644 index 021a80d9daad9106a138d83320c26eadfc5f86e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49613 zcmXV11yoe;)26$mJC`m6q&uXfyQKsck?!tLkmg4>EZtp7cQ;6PcgJ_}|8WjyP}ojy|IjO6Dcqo-{+P&0imAI99zP@gN7j>k`s>l% z=hd^qwe8mMn`z*mUccY79F#j(YV<7uNs zp=B9zxoE7oQqmkp`7FP3<%)Ga_$qZcA58D#(4{T!KDr+y@2eRY{55#iY+EfZKk-?G z7e}HB!iv39o_Y87ju*O^A9zLX&4kTW#fpvp_jS0CT)Y%nou@b{v<4YfP&6dxDqdtI zm2fvO2Rkx!F<)fbA3N6af2UH)F}UXjCGg0_>!fkI@tCQ9`aUhpGTn|oP34iR7!rLK zQXGXPF7uy?YQHEW9cq3d+I~UzT+3-x6QA{mgOM;y3pDk3|Ha|REo3tSa8k&QTIe>- z^)w$Lg7XQSP-B~(I@ zQ|80Qc844Q+XN?xjDtGCOl>4N03AjmLps3|Ce2ZoU-SF^z*vw$P$rw(KFM)U%NW=J$T3%j!h`KHX{6fuCGejc@AS_786#pa$ zdML(+=5M!llj39Ls^U;6TPiz9NJvDxa`@55oiUusaAgB~7`-JmfPxxBT<{+btM~^V z9c9aCr*RkHlv@kf0RfGNX%`Ub8?-VUIeBnB`XI3w@fES9`$2)!de{RG<&_w$H%o}# z61NJ4@`y5F!xkMtM?<^1xj9I!*~!HtZKhcdc(b!u_ESQIZyOQgl} ziVF6-@pOHKHxC#jgJwHEt>?w{l=hoAx{j=G$ zpOf&y9vG-$>ftghzqii>oah%7G5-#1!-6@*VI~Ep|5~#0k9A~KVsEO3N8CA-?NaVQ`4rD|Gp;d7 zj5)iwh%W&sqM@S?JRaLM)z#yeDw9N;1-}7_jcLDLu0p(-$c#S?-jKBO_Vo13K0dp> z+Mjy(+tc_!edI?Nvgil;X9Tfd!gle6=o|FUwaRD|Eu5TiJIhN-=yCOA1c^`q-N z2eBX?$Kt<*ws7li<}RTjEHYB=#2J2Z7S#RIQ(IeGp3LZLvRbvG@Z5jq$t#ssW!>8I zoW-2wN$2Aq8(7JSczoyf4O{#TyYsNSFXw%`cUjEIP*`?=${yov^7KWR>DbJ^AHIcr_kx|8-{QJ?V{n(FK8qoOb_ z&$X*)=ke;&1OKVuCgxRkXV7$rVq7@;j)UlnczSyJxC;Qz1rq#eFCFYZNd#d@!7ag4 z!H3>Sn4hAf-_~Md6WqG_cOK;bCdTB~omPyKU30t>NME!!+11o$tT$r4C=Yc0PX-}P zhK4-9Vjj&pd;z>h;c4$;!9w^waQM%^!`jpy7$x@XCTF4bJMXWq?wVFDi&sD zaGi=7nbC8&YV&-s|Mrr6gPn0-W|)YC#QOX9?>07dLWJ_hN#p;lKORe|h?eZ77%!+B z#)(OnW$TYNiU8ujxIZE41)?PjXZ{j8GBSee67>%%>L@p9IezTWuu50}=?4uLTo+`N zw>3!OpZ@^#|L(8A&CRVk&j=k1O`tj%6ZD(z zh_{dJ-M zRh&ihX{z4haV#WEfQVp1&sc1G4^}hXwIc;XWaj+c2Ib=7BG}qmPgnPfrpn8K8slxb zAgB%QCzAnI5z(*k&?}bu>Z-o~gj|uPk@^(V&~@wlt|uWTJ~%j_JoWJK*cw1y3611= zQ|LU5ft!R4-JH@vPFZ}In6(DF%6#)ENQHzD^0`e+5ZhFYOo&Pm&c#qot&5)iA8scHlM0(!Z93xeMO?gu#@!=Cw$lf{zr?NohUkx`#SHtepu}h^7m9^Bib+9=i@{*< z!O>BCMR(3Yws1~}T%E?g%+I$J*NuG+NBqt%Akm(B%}?RCnBqWn>C8TSU7+2Uugr*) zau{sKwLNQVlo*EjblnrR4GnYC)BSzjynonM-Y%CUv3mHJv+l<@B-s`I69+vM{%QI^ zVH*!|4R_ktGYg$yMmB-GW_wPKR|6W#fff$xhIpNNTKJSjE= z9U!4HMn*>N?oI9#n&1WqzvkJ0Z{CZHIT;1}&haK&*aQYu;aVs|O2VBli%RMCXO${)ype?~J>%VC852V0O4muNss8^jyGvSR2? zUZ0yQu^Kwl^=4cuZ_$9mDz6Hm-6V>}F$hEg=m>xWgo+EpjhL8sR)~`GMUo(sx<$;)qdz3$u^Pf*G@W>3cSzwv@(tVw=Y`BC@CF=Oa+CNe6} zJ*1+dqO|new{P*MT^Cj1+HVPt2vL5hY1|`ZqC`s>FV}&i9A&~TqfvkNACJ6GB!sv#lwuoC2qZvc`N6+MLR~6guG8VPt?ZBbjmMeDy;?(Ui5dweblFGjnsPMyYFd2LA|}Tjf?7 zg-~cF6FfjRMMDmYi;H>n37FqJf=zM^x@>nGANGJxyuaH&W7Ez6ExQ<%bA!PDK|zL^ z^3#v61YsGQmt_FjezUm{NLZJ1RY39g$*@;c_=I;<_I@04w^-@cPEke=)ImW|p@$|& z8h?YZ8Vc>vE$?94m2-2vlywLp-dNbq-7v<9mD)r(T}E|4j46QAjTP;3p4@>rfnbzp z;3a=5(WIbhr;NZqWv&q~BSpx$o}_()a8xTd=|RYFu-&`2x{-|IDkrO|KCqO`0GSzv zwEPF2y0Z^fC?ZSJuJ|+|i>f;D6NO)7RI`|LH#_)xj{zI@8!ewU@fhvJGzLIdao=$U z&V*}pvAl7apy+5m$DN;i`h7|Yk^qvJCSXxB{7Oc?7<=8cb@phk_Ahv829stoy z$Meg~xp5Mf`T5!JNSzEWGD8yT18Wu6e`)56UZ{W-JgIAHCMG4#&CLxJ(ycvqn?|In zh08Q%7dsle^AjvCiCO(w3g?(wL@k*{h(lbWrciM!RLbl%Qd?J9iD97Jft#AdkLmye zDJm!d$j>=BIR^*er6l8?7Qj50K`q5NB8V(x+vhG=j(0yYnGCf5M15HXxcFYX==#9> zjEdGc3Dv$neo=9WQY3u%senjmVmvC4LslIl0|Ns)yY07cL7gOogn&ul${1=`-18E! z?Qgj_zvr#u>n?GMfqM)Fc+uhEA&xs@uJlh!IU}1wZW=R=u=6k~*+O`i{8@m%cLSEr z&d69)RtDsa0y8-OoM&NN zU0v;E3mDnZ_f>FHf*4F#7pI{kL$ROEKolz_8v>lL-W0>gQj}HqVcZ_%L^LZm2&59SdvQ?U!zbc&BcK-LjgsY z@GmjI#v20b<184l*cTN?Wq=?|G9RKXfQC?jk*dOsO;P2AQx|}R?VI%+V?jquOuUth z?2V&Ink*;XDX9wKw|X!ZeNV&7XPGN$@1X1eLHHl}-P-{2V=rlK+@-24aursI9ddI} zx(t0G7MprO5C~=v?5$ja69??J``4VZva*H-*Z)?N!$6~2&Z@Lugp|e4>?o^-kqTCU zur)D}ZQFk!CXlpRP)~zkf@X3|y^r0=y;Z5uUGM$J{a&iJIr2`UqMR z+B(!7f@dF2T80o>W%0)aiRm3E#;7+*Zj&(FdoL)s3?%Y}1?1qqHz|ZrEYLTUn%SD& zI1bUoTHCe1Cty@e*{pVa96>CkS$de`aUcAjVXwQyW1$!19HN&&77ITX^BV-z`=n*= zlr?HG%Z(G9x&1i1{#|3{JW+-le0;=Vmy04Qj*^)$jzEC=inKI=cOp_ z_S(7w%nIBUe$Gb`a$ft}r&dHmR^5gUmCo>ujDQsA4yuw?C3;V;{Hul^D3$k^nS()V zo<61v){oXGO#EviwbM8qdnISne}Di~lymeI<{6*RIP4kUW-RAEy3nWu;Xrxgccp!8 zQ&ZCe9ZLr}K3`hV!57*}ybs^;4q3+MtgNgirjC^Jx6Pc7HTJ`%Vus4l$x*>lr7^Iu zydXY7d)tjAlwyw+-f1Wcm#NLd6E`-CiP;nzt1@LPvNnsE8>(>u-jGt4{08;~6-58L z$WXQamha2I&%v^y{#np&aqrS9&{bhAG<5iBC^Y8yhCV z$Rt*21qWY9-@iMzdryFOD7m<_l$x3|F+PVl(>? zLE~-^tpg6!hGM+$EI1&c7;*!fPmIuzbe2i+`R3I-_m;nWcz{3tCTNw#ur0d*w&=?KE?Ux>e-@-VpT zFxy+p9zvDOg{xb)L^UmNmzTQzX@c6*+On}PzRxbkc1CDUQ#KN*=ZLZ?kE#F?F+V_2 z-eeu8Jtrau2z|A%NQ#f2Z$~a6OO%rq@1iPJ{E3}NHN)b51WW(J2Qw($of$u-lpdp( zEVmtjib4<_gFb=i}Tl;`r6r*KOYjf*!*XMHl7yJju4Folt!%f_V;5>8^ciZ z>S+S>U8|sNcEcxalbZ^76(3ju41}2 zAZ290-Bq1}?NJV90>-3q9=^b)p zx3aT|g&4r!+4_2WD@*HT>6H1T=Cd=hctQ@qE`G5!pGm{@74&C$W1M)QD1F%4AUGx` zMH=StA7PnPU{t3#o`9{@%NX%El)(eX0ol!hl{Sl;Mp2TjO8@(fUMI|S-sz)4rS%by zxaVi_4f&Y?=X74xRljK-?T|r+d(msZN^2`CF=r_QDGmQ#JWP;zK2W1dmD8|6WSX^g zT7=QOK_g@mO64rxX70$K7`ga0r>l(gw(JYnAD0}cBnmc#yP)-M`v+BAQJYVsLHar$ z9M0LJjvB6-McB#feB>1sqkKA$!T2sCMb7KAH^qvdrD<-=V3P!~R9EwgH2CP4BO@c7 zot+^}Kxb_aJ3BGu1h9MLAJZ86%2w_g-<+xrAbm5}7->2$F2`hJ+i46ZDvYFXX}3bC z7rUkGOcnNRVPYqG18JZpxMm0FI&@jDt$>Zei1ba}IWA1W*3xLV#fsmgunwUsLC|xAzv}~_HgUd$LES@2I7WZNh<99{AveFiK>QlPtKwxt>olbe&hdT~(?o_E)D&y-uI93)0K)ziP* ziV(ljlU&;OK^-P3q(Ht5$=IB34#T$5pueG7V}hBFoTkv%`m)b;ZH@aU9rEn+~if*h#LQOZjRzu0 zgJ5diQ<>_0XX8l&&^N;kjt`IjwMYk-lA3A`Hjt1A{9M-6ZYI6HC>4t%q(M)B78c%^ zmuCN}ZbteNK}%&giy+1=wuF+Z{3zq0TnW&Rj~_pJ1f-Y0*ADIk3dW5rYxHmANgNLZ zDilzqNQlbXe?5UD1gnz{cAkvZSaE$kDi!KuT7Ob*8Wt1KCpPHu1A2-W4(r|h_8$d2 zLMaS2pPqV)8$EPnw+IDpR|bX9Z%4-l*ose&j;7;|*NnTquk7I_+m^*mARYxPGU-c7 z%!D&S>2p%feEPxnfw;S58pO3`H8?Z`&{h>=WxjK@Pq@mR4tVPPu}J;2ak_yi*v~^2 zU6CEw#swNZfk8F7oOL=iv8*G)A!`$WGN{r00e-g*{MeVf{0PWiVvsx^%wJ3K~drX zN>yP?0{OfY=#1?@R>IEaZZg=-CQC}rrSHuVlx#HLV0;lIYwH?!JiOs4o{=3czq-jB z8yaPDisX8ux+>`UGzLR{ata%SO{$CikBYy5ys#0oO)JYGxjO_TCc}Ak);RR5EQ9$+ z)`f+Ihrmj&FVshpax(+Lh>eN`88|~g)o3P4rKPSuJv*C2AH>hO_YziJ9tZSnY@M#d zeafm1%KMfQ=58e>vzaS2>4g;1X>M8B1fvbZndowfcaE7Dd2q7;1+Y_N=IYZzV(8bW zVT`H=AAQcfMkj{BLQ|s^?yz-#K#Xi`qeDZ1ao}%G3hKdj(>(DYi-f4p;b9Q|rWJ?a z+Keuk3e9Oz4YBl?eaMExJdqqrDgRcnWFuI#=M#LJ_5QDI^((?gG30{uI`3wCz)q_N}ks&GlkgLelQ<+@xINhL5X zZDcNOyJprLtI;T<0H$AUA^OdAjZIBNqeTr3S}Qn=8NZxazh}oN!A-Spe=jw^Qgu{RwF} zJxIIQ$qr1Rq4;XmU})60-V7%`N25;70-5hOo%u3Wp44IR_|(f}(GkVwqo zYMLvUnYT-ooS{TZYY!Far5ffwH@h@KB2_p-0-45vO*Z@bb+9FjipYE!dSOt(a0^Y@ zn`=JC@9#o%TPnmG^ubuoSv8Bn9JftBA&AWgQZ-igz1>aaxi&viP5EnN;aG6ByY_Ed z1~xYCl1TFMxF103;FT!HD8^>P*X6<^ali7(N9kHRUkF2Xpe(`3P%?yK8&guA@1ZY< z!Tgn$-c;_j`G>A93Jz-L`7HJ+r5WMgPGzqXa=hDJoBqqS8Z9J$xCzHYpQCIat{ zScwX)s#GGhhV6kr-$Ls5DXLrYm?Ie}usE(djzdZ;cU)y0Y+#b}F&U15v(Cf>EzSG1 zq@p1uwNGyTBR980BU{yYoosPzL?lYJk-FiL>vaadT(d0n7>}uxuzvi=W%#Lal@`A)f>(-tVk|D;|`PXptjh7K%9^F6jwDb zA}$`@{(|#^v9^A0UiAf>I2dQKfI*Aav7>^_QoE^8tc()ptDf$m4?&F;IViQAE^wD zWBvXa0`>M$T95|4c@VY4c{Y|xO1Pn!5AEOSliwy?b|Yz#E<1cMk5JmjI@ z3%8xTz4-K<jj5cc>k5_%>Itk2^xoawO+EDtx*np9`vIAZ(KgkDKnw_m;NtU`OHaJlW~hbH z2>CfRlWc{R^9ubjiBAK^+a+mfW29O1!T9t)L!v%Y&2(Z2OQE*7y|>l34C7O828N$y zXJ%-ah{z;R1+8(g`0Dt`qw4DEX(AC42gtz40r`iKY(wGBPhB#Yal7`;@6|O|;&~7V zq_$RFIG<(g^Y1@l3Ie@RIAjKec|9ss?>?R4_Kr^ocmcU^J=#*n=ObYB8Q$uS%osQ3{vUx)Y)JvJoV9rO96D0*cMr9h7YeP^@XBM zX60wynE|U@BxQUCT%dQ4EWZUxUt>NJZfNF9=`63W*A(IOCk|^z9oE$nNeJu4EmCV_ zfT%GsUF<~&3Od}ZoA&_B6AX_`bf2d!R%QLOH8&U5N9usAoITiJT9oQXOzzhKty5lH zGB$Dr#=kxg?J=%#*vZ9Ke>q}nJCOfY`f{4{fAy&m#a+n)vXg(?OQz!W*Atvzg3_B% zgDg>6fH@M-Td)}B5AI;%?)*={+g%iy6_rfa}9R8k9 zBQ&miVWT#8--lY->EHU>A3Us`g2+B|)6+|@25rYx+6T`#H5O}dAs!5;laE;Yf;EzL z#X1LL$(-dIwt!AL&>58pWx}vk=fkVAJJ^_6LAAz0b(>OCDx@=nT?CR>)lF zdz1P?lx3^VIq9g%vYVKsBuu8hz9L>ZwNbN>3(KV^Kinyo zX`%|8P^`&^CxqFmo2MC#bOzKd9|bO~t*y5WZaKR8NTW6PHwZ~tF-V-%$Wvz;%vEG@ zRF)KEW(Ee`~%JfjiHqL9NLdm(0hVYBtU%H|GXj z3;W$ep;i6aeT;HAvcQb<*7z$b(=z5GhO5C-CUw+a{oy||g!FVY40LpaIQWZc;*zUF{cN_W_opnR`4Tc3FGit8n{@ zX=_etsh8XQHlN$E=;_*gx}&4xg+W8$RiIe7urF@LJ9-$K!qb6`pWRwu_VCMy1~n3+ znf1neM+)0ea+KHhC1)H>P&!;{Wy|JBy?jQIL$HN`@jWB^OkIPQOj%v$sf&jLPA1- zO1y8FBG}@n{x?zf=%8}gKK17DbU+b5pJowAw1+rLOlfmk3{wg@K|MpgJ|Rz3`|U*{LK!fjN!gH@uWBJ z0n6|Q#V3@woUY_*x=l?i=x7-sda8BgB3+Sor!h2%{<*pG(Doa3b62Zh4z+RhZ69;; zWFkw(Hd(hU4H^9j^lUv*GCLeKV$aJv!>{7@O2XVt*YD18z*0}|wte1ey>VOFF{b#( zN{%ta*na3|d{RDrP#zP%sWu@o@g$Gg_Vm`##ui+kiZib!DHn!;6yJ~ChgLZJ0EPKr z0wdYm$=|{2|1t6lG!9aq`Z1nfjp%?|?EEL=Qi7`^6=hRA(=J5Q#}^kLdP!_qj54ah z*9Xh`BA1D(Q&Fr2_2SDblje+}zerV>m)E{i7CFuG}_=OU|OtKdDrm z7$oB9m8)VTPv0f6cN019j%F@ZIqp_(vrW`H%q%99Xf`x7lsJC}9+jA_@Ksn|NvR_l zZ!E$4o|3AURQP48PNvdKXR!RQ=lCeZ`CUQj^D-Q5I>tJli!uqjjr#YoQ#&$c*#Wb0 zeBo_>{_Og4m%q)|Ly4>s9ou)|IQ?p6cBUjH^6~-&nvMP+D1=g)xoFJ?96)-jt5l;9a15OQJI5pQ)4iggCf=LQwMzCD$ohyR#=UW>=JAFQjF0TDu+$hha-_gc@&+k zFlk(P&bZIjcv7kBq}Su(+yN>d=6M&B63iiKY$De43ES}(6~^@S^=+9!$M@?L=Z%>} zRwYKJ3y+?XdDw@Vp~U>WQtgG66AMx{0eU4TDwx{8))j5Sf~1l3Omrv5!+r{#ZY^>l zhYlAgTi4E{<*29(Tz-=hA3`{CPmbp26U+1_w(WFwQk>s^(Wj{!9r-Q#n#iixq-Ezi>5&w#)g9O!1(hKZ`7EOibXl zSTRbL2^mAZho8X6*mdw)Jmf4oELIWLv~DMyZdh{SP8y7lf>q`h5%J#RSGLH5$IkHC zAqh{pejNh2^~mCN$z18RvuEdUGH0ge3Ey>B>cK%uLdjgY&f&!mX00;s&BzgpGJ-70 zl!eET?|M@r!G7o(`0K#rd#h#G&NIz`fPb-5f)sLie5ltlI%TEP?iIYMI5d8CHdN8t zY_`wQG3IJvu^YiAsa@wm#?Pwai6%(?04&9og=Xy5-j@Da&kmo%GBk<^-^*f=O00C0 zE33H6czrEr$IT?FqLNv-L^D`iT%I5OGkyZ+xa0(3ifw1Mbz*!5kXv@hyDlOxhlg42 zYU1&jwMwOd%JN$$<&4i0;!J8-{#}LmQ549`wjnfIbUqsyP-QaD(1_3*{Sl130W3O z3z-}e1s3s>k}9jnip~e8bAr;LyfK$%aHNdeab46z!J3~D4pJ5oZPSy>OeCPRNF&U~ zGK7E@87e-@-GGu$KxSA2k!V&`b8BlW#j4lk)BUAVI)9z(=?XBX6X_t(86qNobo|;i zU$L_H`ZAcoi1@9%8WjsB1c7uA-i}Hd3&9bof=To*s#C*58L^=yi((E z#C5KUNdZ3|4+R~Msic&dh2kPKbaY^#sG`F6`FhT_^}Lr%zy*Sb;IIC--e#%&GX3=1 zd}VffIU5fTfsk<>b!@kB$9Ay7%n*-7O3fkZvhAOJCuirn+S)aC4@(CDdBI%GstLhu zzhVr;pe|LF0ZHwk^h;n%m;6NVFK6PAzdd6o#NSbVlz)()U}UIadp#=}W*p-|5qGsc zJw54o&G0<60iQp-3=S{UWTpxzJy%*2~; z88f$4Ii5aSe$sp>(!ZZY^%4QcUG9)eK^qiOhV8a%LN}Fa2ElH%n)F1ZesA9Y?GMW| z7-^)@0NBT=*W;3WBFmq12*V-Lj4E8%l8?OD$nQY;2vii5tFFo&F4%Zk$se?Iz%z(h zpE0$@1diNtr!O3A{>fSCDS2T9tzbU^_0{>+?>I!S@FX=r7SaLVFn0fhGl`q#WkmL6KJ_IaWB`_yFNX*c6gp;hc2}U zQY5DHS&TZ4d8!-8>ph-QxSg%6zSLLsyh`T3pZwtVGMDQ4YAq}6))hcg7&;m zoacowVDf*#FY$k#M6T4j`u(N7y^{@G&#YZNifbQ-=Zs#Yv~t9X zN)u47qdK7R4fNsm?r5>P(s#%=tIYdy%(v=cX?4Nr&}Pi{{=rk^C7jRbY4T9yX`-3L zR^M~emHaie!+qlv80;u$x7%<2^5r;0HEO-R_%-%;k;L=Y;jq}&*J7#d7VX-pHd*#z;%ZhjLstO^0M&M@^b_ z^_Y^vKRBo>Ka}zG_te*A%5}>1bib(hgoX8(fi?a7aaHK?H%0T{;G(>oM@h+)%hA(* zL&xQv?Wr{r(+Nw(o-Oi{I${S%vcr5Tdq<~45f2YfLrZH(IEMbac)lY(Z%chW_tn&} zyPRrK?hfg534f!-6|si8stHO9V{1DG)A*lQMZcL&k{B9PDoL+i<2#X8i?L8P{;MkaUp^a~p=|g47nojOE?1v7&wU?H zOJ5)GJF9#j#~NN=pa)V!w<*C|6n zEQ1ertVrR0jg>cSJ}8#bGUU7LqR4n&|6$a4baAic<#0YT*J{^;hxDUBLC!TQ!Y|8)^j2-rqy;cG|c$SX?MekL&y6OqMfzN z7+(1!#qmnjxmqNiHwx-nvWJdY*_0jqv(zLqmdn^RpXMa;dwnBgf)T~=FDQIt)k7Bg zw_C(>t7ASlH9RdijUhXw{~hY9luK&Y`-Cj@5y@C(X)D+G{Vz3s{IUG$Uf{I#%)jHH z_2FRMx`M3nCgsJtAX48^;h@$Ey`%NDb2y1j@Vu2-u%&TR3$x=oTnWuczy@kP#j3C( zncMBSaL&kC!C8}#yua>)(@oo}?(9o`Pnimm$P(ef{4Q#0aZ-DXF~--RGng+rnf zz4BmUK0WyR8wriyrivs!t&Lt&wB@}JYXuxwX=xa`n{Ur(vA*u*YY@HLul0jFXjrbH zd_8t;U6J|eBhT@f(+}rcyO^F86`4mh*hRlXs;jp1cgy7bf7rTr3yhN%Tb* zDw^6#wSDSH=|Lixv29L$k+qMdQbWFtiKPrIMR`<@iO5*bDfzcyLsekcef#=Xd#aH{U6H2E#o(p|3 zS>OjJt?H7B@(h>jLFRJE2u4S-d>PUGt`w^ZYU+i!$IzUA>8P|JUqVt6K~!p`3nzJB zDZSZsTp4i;Z-}4F{qKGi{p=3IrKAW6#0jhY#*5-V))i8}@@*GuIj0Kp4ZSs<*?oVt z4+i%cHJ){&5@fg+J+Fk;dp~VT%qbqWd?k)W|J>rSmts9<^s$T%W(OU+WVIS7w0|5b z;o~;8=fQ->sgHT&qU4r*MQMTj9lgjssMLa3u|TxNVPMsY%FDll!2!oNx3}_IpP5+0 z($+mT@f~*{=|dKczKu!eMxS=zh6;mr^yor#YI4-*021coCjY0$UyF?6ir;i|CS>!zkc;Wbr*;F{OhafkIlhN0FMvqZ(4xh1&p*MDPoT*tEaKzF4y--(Q-^n)!k)GaRyw`G8 zo??oKJ{Oe=u9PUu8@fw$%tN0Gq1~Nr3|(c>7w-C1eCZ&-_S6$hQlw)!q|Cv@1hlp6 z@u=+qEP37RRuEr`PX?{XrV83z7R(iH1@Bg999JHvYIZ5S9@?ZchVEBJ1lV4_^v!5} zRBCCyR-3Cg@U)rOPO`aMdUZXCY1)0gI%@8C{HD+=o1k*n=qr8un!1WRQb|P*YVsNj zcp`fg;vAH4!=5$oO+>iN8s^W+aTpP^W7TaQ%q-w24oNWVCfy?Az>GI^DMP*|gvntg z?QuRFK8jj-ucQ@RocipKN!ogFU^-`bIk=rf_Hu)X^1Uf{Ewo|B`?e2Wq|tjRsoco@ zT&gIub)%nNB$@m8VA{I;uX7I`yYIo2JI|}&X=prM= z)XL^n4tG=~8M^@8c_|y1X6cy$jI6A6Ph}-_7Al;q@^VFC3>qb;zAT=v?!;^MXd9ue z8tEXlhA(P!rS@gcWvNHJfAU0;vq;U9p?h*nXu>rTGz^4em+)^=)x>+U1IK)USx80e z#np_~_m?|7vJTIy&Ny~MH>Z_g=^X<%590w=*OTXdX+@=$>c@i;kAkMJ(;5aY3pQ1FdG@#o0;;c-#mG!yEh}!=?z9y2-j;pujg>hVsBzVu)n0)%H)Q@y#b?}n<*$~3 z5dU#;S!QF-E2ffx+s-zs601`%pFFeg!;mXm)7DYlTv~l+vUNpK%Tsk(=3^*ojbZzH z)Aio5XVdF}vs50LMxUWv#(WYNvwqYD^9#swkOH;_qFvP4PYxwU{?1YP8LL&`0c<+> z;aZ@kXm2;nNE^pFqBg60vAaj9SZUvOn6@=-GLGD}Lbj*Ywt7zcDW8m{S_9yT%ETSp zPoB@#QCkPr)0H%Qr{%r3R^xl`Kgag6mzrc)eMdv#z3KScdU*NTd`aA2nf$6zskoT@W9&dpOsbIwJ#XCa|T+uA+ZcMW=4 zn&(6wjE_MV$8)0UWc<9lu)YaC_uKB7cXtu;>;l(aOC%>xHk-#C<&OjGhu=FaRy&?| zn_n+G9NF(>X8YJiIyNGnn1$W9V&zqZujlGSUKO5?J9LDfIqPEFy9L%CSS`K2vW!L3 z8{5Q5=kAf2ppCxsuBXHq@6tnh(I8W<3i^z82fEj7`kYbuH&i1$7Q09%=RjRO2;hd} zlR2dq!a&PTot*z_8S#bVx%!v6k-gLjeMSGnJS|_6m)T|yh43B4YH8bXlC#LYd)JuH zjNP0!{r9JVh+hUFa54yp$?gNvO5R%=TI@}E!t_s@%)X0%ooCV(EkoGZtyCW~uz|-A zTt`Pn1}_|c$Ti$C?eoHEs+ZH!=9ZTKVrizHn26D~hSIC&thzWu>ymXC=&69ZJW@M* zs^`v}{BYNIrFppunNL_L*9`h~AQAfYW!va`>m7})p~pT+l40|GtbBvv#e_M*12o9S1(Q_f4i@`yGv*J~Es86pF3>)A~Ju(ei&JK9>l{bGBlemzHux zeC}L)BDn#xglwu~RX-q=H6{G#aCapp$jO8d$VT#(aH-EMvL=aPoC3?%vI-JI1jIS9 zQo3lU5$@fCGGQe-_LJz`j24FP!{XFjbLU=NCcn$|47%&u2+IyDNRsATbpoky7_m+L1(Z!QDlg?=cH%aFmZ!R4+%*MWdeC`$eFlF!Y|rW zudx0PcT#%1C`{s*usS$s!s8w@^p6#71-B{I9t8>lLdOSPT0YeWQARD_9;=!N$X!Rc zESqlslxZ0*ycSt|M(+UURkSzn9$1x#kjF^3igjM=ZN*T2@%cn6yJBksTlV287tKp% zcZ3e;?nj>ksha-iQx7(W@i<-y1QJamdm(t#9eTKO`0Fk-k6Jo9FbN!tLhG%DM`CPN zXvwaKneK0?T(w@{wd!xNa@%f7@$hA*hrq(XL-u4lY1hDEfP~^{ZT+yr@V;xQ#P>`s zDB|>Q;zONndFx)z(=Tt9*NdSV_O`3(P?5CrY)tlt)mI+u28iOXcAn?p#i6g7OP!hJ zcZbdt&wF%-E|nM+hF<3vR&ys$h3v`3e~n&QH*6TIj%x@E%!brDpK1;3PKz9NmzNDr z&Gw3%AC55xb}s3H_shO}JgLvGR-!ZAQ2h7U@uKw?kHWU&p;%L^u^9-!t4$jb)p|bm zFEIOf%h+D^o|xC!m;{ls-!A1=*AW^bzNW<9qLlvYKWK?x6W^cGLs zMl5$muZQ^^5357MSK0Xl-gXm4Pd&>WcS8j1FMF{=!WkFgN^Gy)2^Bs^7w{BKPB%tR z@S3dm9R#eeGg>Z#h!R#q#AbJUl(A zj@GER6W-Mu4^_s87|dj6sVoDtz@X0|i;KGMA7jww;4?+2Jj!ne#;8Eez&N(jN}wdR z7>u{QRKehQWN-B85_m)pETw&a87z_;N%)8M3=T35_*ZL0`&2~?AY;|%EL_`b2#`m#y&xulc*7#+v|NMMO?{EuToHrom z>DlsGsws#Oe;B!MOE)Y#Y{bv87P_P24=3{gO(q$6rPn_r zJRPl0MGs`M?X`I?z9JgguwE+>zq}-WeU=gZxf=76K;()_PmXBdJ*VVvHiS=Ic1oKv zhI2>g2@n3r?gUk~t}?}+#kJy!{82tW&7!F-CF8g6fAI#9`+ekd*y#Rc+u^-!P4d~| z@oA&S5uZg_gi?rIU%TDq_?OSaR4zTu$Mrv;st4AkN!?8Sl#KLrbX27sM7qx@DJkQ@ zz$_exz35|k{HHK@aSZ}fNQtiHDxys2Yj5ZdW8jqskuhjun1bOs?>G1 z5_;?(kUlJH+L|M5y-#U@wO~C#H2AQb4nq+Ikrk z;c)qMIX0HeDgA6$W4qc;(s7xtQKDJ28e=xQUf$uBqu*(oQN_YTYl*vGCtcm+ao%b_g1yBy&F97+ih${U(uGw6usp z842tLJ|llCq=yWAnhRfCVGliDKjo$No<1Eq3mC2lOB+m8Sy@_KPm)3N_3Pj7$)5+G zgwrnj%$uJWvHS8bzx(%azWc*al1loq>+^K(?ee~vo7d`nNPtFIsvflr-rwANLVp2gtA=l-WQ_Uk!( ze5P7?)V(WxEw&YYlKhH;^b>|pX>u&IO}ES}u@^4XIBE+-B$gWUQwz9w{dqNM5f^{I zwTw6LNv=Kl@@i;tNp!-US~B?lZuRbO7%J8p=`2Jjc#M+Yex<|T9esa)Uskpsyy|1L z4;Z9uE=>peF2h%vZtU0{`T2x}V{W;19WPUf+N5Nj5h<2KjK1p|n)`s-Z^bIX%b^5n zARb}a9V|{t6MVg%X&G!>^$~kq*9Y2wii#S%nx44h=dgrr`rH*Qx*U?r*}yqY&5Wby%L)|5Q|nq!(gGM*>8UOU_NUkxfdV?B^`D?TzOv6rP4 zhJ2Ea&&7uC@5x|Bba)Si*nN1*EKw&VfDEd-=C5B@$Hg)2rG73cfzs*@`onO8aI>Cr z=ynH{X%zrO#nPM_Bihm5Pl~gFWl3m~1mgn!G|Zy&2K32B9DMI2gjoJNmZI$E-bo8S z^{+#jDHRaC%0O-AIA65c_0II0u0geVvo+|hotQd&oPoHl;R19Io*M;4jzN`0GaAhO z7aFubPjofmLTcyy(>+t}+%jG;J|fnMdsD&uVwlEz)O5oZ0{u5_scpE=8RZzx@M z?67JfKLtnO>;_9{Pr{Eo2raM_u^I!9^O-?E&G?}H2sDY%vT2A0Iu78J2B2N!bZO!p zoHQGXd|V&_^GT+szvZfR@9G*t8>fb8{C2*{vnrcXC)|ZXFy8Hnq!C2?>c^AhOnwv` zuwYT*wf%~H&dtS;jE%+9eSenY)`j`uv+c>b>FVv=uH-*|JHOitM~>F$_TOz-*=i5& zj9F{P^IU3!QF#ozfOx)HBY~hhyWVpVVtHadBmzhon_XUnRZZnb-p=_k4vLX<0l3M+ zy16`XVqz{0OC1HopFHgR6fpqx;t0pSBoIuU4lkQ`b>A1k;E&jT#xe2F-~fBVqWcV9 z!TXXbJdR&DJqw4ARix*p^Y1N-Q49cW6u<{|v#jgAM)WP#Umh+8uKMlS1q8GOw<^DJ z_4t>Q=oo*7qvx}5rFLanTYb_Mc6~9ib~`V&lUHxUyvWx$j-c-X!WI@;SIm`~Jo(nv z7LTU!HsA4woblY)O8;;_fQ^rjv0i`M8p{LdlxHc1{%Y);U~{d8s>|s&yRAw<**MeE z(#(8j^*0nx$;?sK=S%~Zq$F{PQ@jklTng3q308ni<-B5C%#1n@HVRi z0vK{iFC0Vn94bkYoIr#44oi^L%9zyi9-v3+NW5+XatPL** z>8N_HwRbz%`7S}gS*X&y-TI*E2w5U1Wvc!R>>|_G$BkgFn>!n+6)WcCqx=kf)&OG+ zQEqm`R-yV2b;CUF>mZ$jrT!^J4nQyIe}ubnv%_eA_Lo)MBJymXo_RR>+wP>;Tl zOfJ>XA^n48y0PByXsdgSJ3J~X@;bbJGGfy9G0Hag%bhXPVy%bG)xNP{Ed4yp3#zxw zZ^hYzjehsv8v1B^$ylSnRq(u}3A5U8q)en;VqZQff+s03AQISn0BlNWqV zLjJ3=)1+2FfJo}Hfj#2hQy=1opbQ(@VyQpyEB*Xg{@u8-8S#4+L#u+R*5oLQhuV|3 z;s4rl=GCqblGcmqea4t1tn309aWsf_<3}<3V@!mU;|vYAl-_bzR#sB!xcodLaW@aV z`c3pjXk>WUsNOrvPoPA^gTcJY{W&DScXz2hliR$@+gN2Z4%A_0o#Y2Xek?uIC2m`I zM3S$xT}>HbyILXOr?(5K2v|5jp4_3JA z(%DOUKRhZDoaF;#1X16^B)^g& zq&X*Lbe67zYn0Ngygc#kA0no-xg9qn0_9Nf-g_vHy)I zI$mknrx#0h9~@VVPMlXBkdaxZrdR!U^8lEUgv6Qu;&@qtKng(*}iZ0>xn%AjZPZvs0vN$Yai5P*3J`X zC28bll?iTe9nl%;qT0fXFLUWW6UbsozGc$S`BT5mflCc3F=$DSC$T4NUJX-yHm}F5 zZlJ{}{ktC~MN&8StBDguGo z*?dvO1+0>%q)C`tdERFyhO4T1e6~@;!tPgxKS5jhfRIO2US(jo(}eeT^(NKFq}4xe z>H`YMjvVt!*-P5ujtS5zj|X}1E<|}y$j%8YGON}ce9|eaXdjRZceWbz-Mt97>Mb{UmnR$=dnR8&;xQY8M}{E)@iV3pIS(?_3- zdNGWGg!OJrA8Ag7WtcXQz&KW|V8pIse{Qpy{}cm>>WStMW7fby-l+D-Sxb9@mz7e} zA2(EgtG+0DD0W(sr+j~)lxpkSC=$%$P$TEbMNX>{lE}}jgX<+5-J)5ePh+v0w?@GF|_C>SI_eNNkuM#ZJ}@}#aHtH*~O}n>v9~kmdTYX?XJ&yi3*+BWFS4z){BMA zP-8s%umGODrh$ufn~sh{rY1{z#F%P;+oJ*aj`I1LGB?*9k$Rg_1lw zN2Bn**5Hcd?ffZTf?2-p(9eC={L)Hz2jj19HT2TV2l)+2l&r6fb*eLttI+{lw-xmQ zq#xK!D}MxcCNC0u>HqnjJq6&XPSmlg|Kq(qeQS}Y0zvHHn(LQ~&VAe+iuO=Z3_+}S z4vyM@AZMbuky1LI40_jRxQ8tTFA8wzFlFAl^i{(L@T8d-L>t4@(3V0hr}!^-7cP@N zhOV=`x7?s%`fPDUw!hNTqdJSJ!2YM`Pt?oDAxt)6rf?g;aP|GhZ|h@%(K8}6LNCRc z#WShIu~%ES*!NLRnv8^OJ{w#J%Z?*5RE7f}8Z@LA}Tp0J?Nf<8a zxKIuXI;xI|345aYutQ85VZ_e?tWnij#9!!PY57*919q!jL99WqJ6I@z&Q9U1wI9y5 z66gMQ!c?;-XV&(rILZn6+yjG8ztRo)d1;EMoQzhxE1DtV!R}?||=yvlu@y%4# zmJPFiGpq;=T_7_Zo|>`?E0gdTFpz>5YFL(E+9^Jl%_XKihHcPLQ4NHdNDtcqIHJl~ewH4yp1j^?qjJb0q`l#xIsX3bWc&c$ z7a_f_GZUCA4Se7e_gOEYiUHn$ybZ1ox}vFYcG?^MoO~1gQiG%xyOD%8|B9*W!CK5P zq)=EY-j0TA%XlIz6%kE%$F2+W;BHIq9{OF^`>KC8a62{#EPiQW9dGv8lxKi_QH zk^|(rDgb-`+Zk_oCi(m~-uyMc_tV;vOi^|Z5Mn`b$=G%Nu~|XF#O?p$v-fsRbud=< zZ%JtrQ&U;;>hof_of9=b{P;LAbt6iG*OHNwPRD|U-}dYKyP&RmT87}Vq4cygI>I8A zho+dnT=UnT+U8eQ^0zjRbkYY-2jpgB3*@FT^@U!f_Z-G zMlkQyX33@eyGz>?6dj)=@8M}GVeINU8IdTdfo_;AE91z}(q|gwV~kf-HpO9wCW$S8 z0Of5M&~74Rzs$p`+q|IX62bR+EAqXw!Ti?orF?GXSr;H?g3>}pdU|9RN4BTqzz?;Z z_K}e&U!4=L+LNISvOGW}J}6b_%Mpsv#fo0*dL`XuWW*rwxW-XXaYsxW>>+U+=-slx! z&$c~VLpVn}by^3ovB|$wlEGr4qLdG$z8%!8Y?o{xc<-^B{hA0m_>LJwC_z`P9bzOL zf6^+R`7KrX-ec#2#!RQ<f8!g?0T!041p-a>WNo_c(sE}v~F)2b)u@{ z>S4$W?bUs?Nr2lA-@}o=ZNJYCj?mup?;xnqOS>U?_H+EG`J%q@q{LZw-k>XMcr(L* zf-_?9DE1qXB<#<|!%K5H&3y-1Yw*Yw5)Xz?5X{SYN&sb#O8EA^fX|<+M@$|*4W_5L z?L6vbQ^NqCTS%vg@nBYDIPKW*V&gxydpb*Jeq${OP!nqV@(Onyou?T9{#@hUyY({{ zr)wYBJdvBdoVQFw#h{o3wHqp9-c430ynvvN#E!xHsZ-9l3aMHH3>lREq-~7KG-9ce z$}kyRheFbxzx*EZR*tDDPa+7yK>sU=lJsQy?IAKudwkxVIM0Xde-|NJFgXtp_U(ODFSEb;tlctt(!!BB1~L6!y}AlJK}xYiE*Y~ z*Ok>`qeoL-E&peyFvL9Y=trD)F|G-h`k8~QY!~~wXmV~MdP4kIpKP8<=EM$8?VB2N zljPSk9u=RJY1|!#OWJ1i<{4M`>7x_*-KqLe9Zu^G#PL(U9r6R&8;r8YhBxg`r9q{0t4bPzjY z5-!FDw&BaBMiL7DK0*N5G&FL*!Ypv2{p0;)l%IpD@64EaR>1wW#{(3FHANGDx{sbf z@UTL`8s?+R!Z$`~^~s5r^wf5JPi>=Z&s1oKaizsw&u24iuIDO_$m{)ctx13tL?~CU z38}ohyL&tt)W{xD*=50|4wJUJl57~~3RUGJNoso3b8$LyOeHiK4=^(`B82jYcR$t$f2axBWv{7?PdW0q;aHyQ1b|~7#X;%6nyZQAsbf6^Uco@hNy<)jAukncI z{s`;Oa4@rL!G%nwvD6{iU^uyq=Ze6a<-yCLAh4icj#Anx=J*=B9~=nXSX|))`Y3{<&%#S?7@kM^npqN$UZDbd7$K46|Ac8Y}R?U zvh`Ni7s)kB)PY0gnM1*mWO_Lw2?syoftvkpT6#qE{?<*~hoszcL zH$$mZ&&XZZllpW&iDiSMVn#k#9QmzbGCcZ04VD^=#r2jUEi*HxKbNT0|Hu+V%8;>I zzWNYDg-0>cQ+Grw241Yoek4zoi!2LX>41R>+KeP5BdHDtmJpP)=Y9rSKxmH{9!=>2 z)!pbh(XCH;ipY2S)FsO*{m8o#TO-@i1>N?q+-oJ5CG$!tS_ZDM%TCEOUKfI@k|P0} zk#e{er;|K!FQU>zdaR;bhwk&sANT#_ek(iMf34Cu7Jd3hIi}honfWrDLx#M6O@}V| zohdh;pIixaWzpd^j!+2GYmSz$Z~m-&%Hez{U%b4wmFPP=T{phK}_q&)$LbppOQ4FNzTS+%%R`@?9C zZff7lb^HNQ9cLhmpjV-+W(>NH07NULIli7U*~f}|kt>EN+RKk!3J=kvY~Y`w4NHxx zcE{b8PgU?i}q;d4>Cgl^P*?AHWGi`t6kMefR zanMyO9)9;^E<8eJ*VmM+Y8 zD_ut@&oZvk{YRk~XROS5=L1YMFj5BmUK1+Kk~^UU7;@WAjGNRn_+ez^V@J)xekk63 zMRk}~TjS|)v8=~QNx9PDsDk$vm9F^oduiA+4dqb20;B_SAAT)##yTA0JBm-?$tK}m zikLkBxB|7MLE}~oeD#Ox$IDAxg}wa`*B*gqW}ogzEMnY`RP&LrX>YGty%=nFSK3_- z60mI-EXLv_o=5YsL{_NtaZ+`aw-r*8(qxr|9cKFHev=@t_$YSjyuOx?dPBJi*%0jw zX|^m=D~uG;XH+ufqt{0V2Yv!*T7GeP{aRs;ogj<%GU&MLIGIqXO|+@O0@99D*x@{N zUR^sf1;hzwho2}iM3)q?AiqaU(O|D#zT1_ep3rBZ(aW1L^FE#!F>P;Wu<7@?YI;Xy z$*XM0N8YhIhfiO+b#7NMF8H4B^iMn?1{QC2Oe zj6LL@SCKW(i2NGQ*6mKbTb;Hf)4uU?WBw7BY<>H&Wo`5PqR_}0Dd^jBqYiGru;hGE zy6@On^_w8$Xeaxs^BJs7dSoBbE2XGT z;4JXFy{5m_Ll|~&zMGru71zxTjP`|M&+P9qeJ88(2kFaBJ{W%S=C}2 zP`Xa~9*5SGRgvc<;YbjX@*nN|>3)W!9r0}>qL5jNc?DiJ))%=$)U*hBAD*)@Z z$QxB-CltM$hd(0ZNf^M}!#^rAgp;p>7vD8{=a$pmAcsR54{uPCg)j4)8;bd&?R%zn z_qD}n2-1A}8BViZr?@3`9EVP)l4X~DwXQYdNG0;wfU!^;Q(x29PF|XTg7ITsG;aK8 zzS58;cMrAN6EX`PT%Q*1>M_cJ^2mcw$P!1jySBr6Awmti?m@{QhD3v;wmy2vSxjyC z4~1RA%qOBDTvpP|44c+42uA%r7Hr#sJ%cBplA%j_nsm0TR#G8hpjx=zFf09R6%Lh;ZbOOKB*8|r6_DaRF zYQ4Ty&KNVYj&VbVOu9BlQ36$Lb<^Hfq+`qY(NV*^u50&Sy3gC+2FOsn0~htx7TnY@ zenvwG4I{=^gb4?XCA8P$d|74L=fB;|7L^R`i}`;ErYSJ7Rx^avYJr^RF$CNRSR=T%wa?-lF^fZ93G;SV|%7~!a$Ar=n~;n(J{K}

  • +7GQPaikKyzdJ#1+ihk4T>&l`YGxEE%@cOg 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 DCI#~x diff --git a/landingzones.old/caf_networking/landingzone.tf b/landingzones.old/caf_networking/landingzone.tf deleted file mode 100644 index 98de51c99..000000000 --- a/landingzones.old/caf_networking/landingzone.tf +++ /dev/null @@ -1,62 +0,0 @@ -module "networking" { - source = "aztfmod/caf/azurerm" - version = "~>5.2.0" - - current_landingzone_key = var.landingzone.key - tags = local.tags - diagnostics = local.diagnostics - global_settings = local.global_settings - tfstates = local.tfstates - tenant_id = var.tenant_id - logged_user_objectId = var.logged_user_objectId - logged_aad_app_objectId = var.logged_aad_app_objectId - resource_groups = var.resource_groups - keyvaults = var.keyvaults - keyvault_access_policies = var.keyvault_access_policies - networking = { - application_gateway_applications = var.application_gateway_applications - application_gateways = var.application_gateways - azurerm_firewall_application_rule_collection_definition = var.azurerm_firewall_application_rule_collection_definition - azurerm_firewall_nat_rule_collection_definition = var.azurerm_firewall_nat_rule_collection_definition - azurerm_firewall_network_rule_collection_definition = var.azurerm_firewall_network_rule_collection_definition - azurerm_firewalls = var.azurerm_firewalls - azurerm_routes = var.azurerm_routes - ddos_services = var.ddos_services - dns_zone_records = var.dns_zone_records - dns_zones = var.dns_zones - express_route_circuit_authorizations = var.express_route_circuit_authorizations - express_route_circuits = var.express_route_circuits - network_security_group_definition = var.network_security_group_definition - private_dns = var.private_dns - private_endpoints = var.private_endpoints - public_ip_addresses = var.public_ip_addresses - load_balancers = var.load_balancers - route_tables = var.route_tables - vhub_peerings = var.vhub_peerings - virtual_network_gateways = var.virtual_network_gateways - virtual_wans = var.virtual_wans - vnet_peerings = var.vnet_peerings - vnets = var.vnets - } - compute = { - azure_container_registries = var.azure_container_registries - bastion_hosts = var.bastion_hosts - virtual_machines = var.virtual_machines - } - storage_accounts = var.storage_accounts - managed_identities = var.managed_identities - - remote_objects = { - application_gateway_applications = local.remote.application_gateway_applications - application_gateways = local.remote.application_gateways - azuread_groups = local.remote.azuread_groups - azurerm_firewalls = local.remote.azurerm_firewalls - keyvaults = local.remote.keyvaults - managed_identities = local.remote.managed_identities - private_dns = local.remote.private_dns - public_ip_addresses = local.remote.public_ip_addresses - virtual_wans = local.remote.virtual_wans - vnets = local.remote.vnets - } - -} diff --git a/landingzones.old/caf_networking/locals.remote_tfstates.tf b/landingzones.old/caf_networking/locals.remote_tfstates.tf deleted file mode 100644 index 9f3734742..000000000 --- a/landingzones.old/caf_networking/locals.remote_tfstates.tf +++ /dev/null @@ -1,91 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.event_hub_namespaces - } - - - remote = { - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) - } - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) - } - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) - } - azurerm_firewalls = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azurerm_firewalls[key], {})) - } - virtual_wans = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.virtual_wans[key], {})) - } - private_dns = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.private_dns[key], {})) - } - application_gateways = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.application_gateways[key], {})) - } - application_gateway_applications = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.application_gateway_applications[key], {})) - } - public_ip_addresses = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.public_ip_addresses[key], {})) - } - keyvaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) - } - } - - - combined = { - vnets = merge(local.remote.vnets, map(var.landingzone.key, module.networking.vnets)) - azurerm_firewalls = merge(local.remote.azurerm_firewalls, map(var.landingzone.key, module.networking.azurerm_firewalls)) - public_ip_addresses = merge(local.remote.public_ip_addresses, map(var.landingzone.key, module.networking.public_ip_addresses)) - virtual_wans = merge(local.remote.virtual_wans, map(var.landingzone.key, module.networking.virtual_wans)) - private_dns = merge(local.remote.private_dns, map(var.landingzone.key, module.networking.private_dns)) - application_gateways = merge(local.remote.application_gateways, map(var.landingzone.key, module.networking.application_gateways)) - application_gateway_applications = merge(local.remote.application_gateway_applications, map(var.landingzone.key, module.networking.application_gateway_applications)) - } - -} diff --git a/landingzones.old/caf_networking/main.tf b/landingzones.old/caf_networking/main.tf deleted file mode 100644 index 8eb1f3590..000000000 --- a/landingzones.old/caf_networking/main.tf +++ /dev/null @@ -1,66 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - - -locals { - - # Update the tfstates map - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} \ No newline at end of file diff --git a/landingzones.old/caf_networking/output.tf b/landingzones.old/caf_networking/output.tf deleted file mode 100644 index 500b278c8..000000000 --- a/landingzones.old/caf_networking/output.tf +++ /dev/null @@ -1,58 +0,0 @@ -output "diagnostics" { - value = module.networking.diagnostics - sensitive = true -} - -output "tfstates" { - value = local.tfstates - sensitive = true -} - -output "vnets" { - value = local.combined.vnets - sensitive = true -} - -output "azurerm_firewalls" { - value = local.combined.azurerm_firewalls - sensitive = true -} - -output "virtual_wans" { - value = local.combined.virtual_wans - sensitive = true - description = "Virtual WAN output" -} - -output "private_dns" { - value = local.combined.private_dns - sensitive = true -} - -output "application_gateways" { - value = local.combined.application_gateways - sensitive = true -} - -output "application_gateway_applications" { - value = local.combined.application_gateway_applications - sensitive = true -} - -output "public_ip_addresses" { - value = local.combined.public_ip_addresses - sensitive = true -} - -output "managed_identities" { - value = local.remote.managed_identities - sensitive = true -} -output "azuread_groups" { - value = local.remote.azuread_groups - sensitive = true -} -output "express_route_circuits" { - value = module.networking.express_route_circuits - sensitive = false -} diff --git a/landingzones.old/caf_networking/readme.md b/landingzones.old/caf_networking/readme.md deleted file mode 100644 index cccb1a695..000000000 --- a/landingzones.old/caf_networking/readme.md +++ /dev/null @@ -1,45 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Networking - -The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. - -* Hub and spoke -* Virtual WAN -* Application DMZ scenario -* Any custom network topology based on virtual networks or virtual WAN -* Library of network security groups definition - -Networking landing zone operates at **level 2**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -## Getting started with networking examples - -Depending on the networking scenario and topology, we provide you with different examples ready to use: - -| level | scenario | -|-------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| -| [100-single-region-hub](./scenario/100-single-region-hub) | Simple hub in one region | -| [101-multi-region-hub](./scenario/101-multi-region-hub) | Two hubs in different regions with peering | -| [105-hub-and-spoke](./scenario/105-hub-and-spoke) | Hub and spoke topology in one region | -| [106-hub-virtual-wan-firewall](./scenario/106-hub-virtual-wan-firewall) | Azure Virtual WAN topology with virtual hub in multiple regions, optional support for Azure Firewall manager | -| [200-single-region-hub](./scenario/200-single-region-hub) | Simple hub in one region, with diagnostics | -| [201-multi-region-hub](./scenario/201-multi-region-hub) | Two hubs in different regions with peering, with diagnostics | -| [210-aks-private](./scenario/210-aks-private) | Hub and spoke topology in one region, with diagnostics | - -## Deploying CAF networking - -Once you have picked a scenario for test, you can deploy it using: - -```bash -rover -lz /tf/caf/public/landingzones/caf_networking \ - -level level2 \ - -var-folder /tf/caf/public/landingzones/caf_networking/scenario/100-single-region-hub \ - -a apply - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/public/landingzones/caf_networking \ - -tfstate_subscription_id \ - -level level2 \ - -var-folder /tf/caf/public/landingzones/caf_networking/scenario/100-single-region-hub \ - -a apply -``` diff --git a/landingzones.old/caf_networking/scenario/100-single-region-hub/configuration.tfvars b/landingzones.old/caf_networking/scenario/100-single-region-hub/configuration.tfvars deleted file mode 100644 index 7269553e2..000000000 --- a/landingzones.old/caf_networking/scenario/100-single-region-hub/configuration.tfvars +++ /dev/null @@ -1,62 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "networking_hub" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - vnet_hub_re1 = { - name = "vnet-hub-re1" - region = "region1" - } -} - -vnets = { - hub_re1 = { - resource_group_key = "vnet_hub_re1" - region = "region1" - vnet = { - name = "hub-re1" - address_space = ["100.64.100.0/22"] - } - specialsubnets = { - GatewaySubnet = { - name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway - cidr = ["100.64.100.0/27"] - } - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["100.64.101.0/26"] - } - } - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["100.64.101.64/26"] - nsg_key = "azure_bastion_nsg" - } - jumpbox = { - name = "jumpbox" - cidr = ["100.64.102.0/27"] - nsg_key = "jumpbox" - } - private_endpoints = { - name = "private_endpoints" - cidr = ["100.64.103.128/25"] - enforce_private_link_endpoint_network_policies = true - } - } - } - -} diff --git a/landingzones.old/caf_networking/scenario/100-single-region-hub/network_security_group_definition.tfvars b/landingzones.old/caf_networking/scenario/100-single-region-hub/network_security_group_definition.tfvars deleted file mode 100644 index 232a5432d..000000000 --- a/landingzones.old/caf_networking/scenario/100-single-region-hub/network_security_group_definition.tfvars +++ /dev/null @@ -1,327 +0,0 @@ -# -# Definition of the networking security groups -# -network_security_group_definition = { - # This entry is applied to all subnets with no NSG defined - empty_nsg = { - } - - azure_bastion_nsg = { - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } - - application_gateway = { - nsg = [ - { - name = "Inbound-HTTP", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "80-82" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "Inbound-HTTPs", - priority = "130" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "Inbound-AGW", - priority = "140" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "65200-65535" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - ] - } - - api_management = { - nsg = [ - { - name = "Inbound-APIM", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3443" - source_address_prefix = "ApiManagement" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Inbound-Redis", - priority = "110" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "6381-6383" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Inbound-LoadBalancer", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "AzureLoadBalancer" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Outbound-StorageHttp", - priority = "100" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "80" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-StorageHttps", - priority = "110" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-AADHttp", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "80" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureActiveDirectory" - }, - { - name = "Outbound-AADHttps", - priority = "130" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureActiveDirectory" - }, - { - name = "Outbound-SQL", - priority = "140" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "1433" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "SQL" - }, - { - name = "Outbound-EventHub", - priority = "150" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "5671-5672" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "EventHub" - }, - { - name = "Outbound-EventHubHttps", - priority = "160" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "EventHub" - }, - { - name = "Outbound-FileShareGit", - priority = "170" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "445" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-Health", - priority = "180" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "1886" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-Monitor", - priority = "190" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureMonitor" - }, - { - name = "Outbound-MoSMTP1itor", - priority = "200" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "25" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-SMTP2", - priority = "210" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "587" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-SMTP3", - priority = "220" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "25028" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-Redis", - priority = "230" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "6381-6383" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - - jumpbox = { - nsg = [ - { - name = "ssh-inbound-22", - priority = "200" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - -} - diff --git a/landingzones.old/caf_networking/scenario/100-single-region-hub/readme.md b/landingzones.old/caf_networking/scenario/100-single-region-hub/readme.md deleted file mode 100644 index 624dfff6b..000000000 --- a/landingzones.old/caf_networking/scenario/100-single-region-hub/readme.md +++ /dev/null @@ -1,45 +0,0 @@ -# CAF landing zones for Terraform - Single region hub virtual network - -The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. - -* Hub and spoke -* Virtual WAN -* Application DMZ scenario -* Any custom network topology based on virtual networks or virtual WAN -* Library of network security groups definition - -Networking landing zone operates at **level 2**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). - -## Architecture diagram - -This example allows you to deploy the following topology: - -![100-example](../../documentation/img/100-single-region-hub.png) - - -## Components deployed by this example - -| Component | Type of resource | Purpose | -|----------------------------------------------------------------------------------|-------------------------|------------------------------------------------------------------| -| vnet-hub-re1 | Resource group | resource group to host the virtual network | -| vnet_hub_re1 | Virtual network | virtual network used as a hub | -| GatewaySubnet,AzureFirewallSubnet,AzureBastionSubnet, jumpbox, private_endpoints | Virtual Subnets | virtual subnets | -| azure_bastion_nsg, empty_nsg, application_gateway, api_management, jumpbox | Network security groups | network security groups that can be attached to virtual subnets. | - - -## Customizing this example - -Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. - -## Deploying this example - -Once you have picked a scenario for test, you can deploy it using: - -```bash -rover -lz /tf/caf/landingzones/caf_networking \ --level level2 \ --var-folder /tf/caf/landingzones/caf_networking/scenario/100-single-region-hub \ --a apply -``` diff --git a/landingzones.old/caf_networking/scenario/101-multi-region-hub/configuration.tfvars b/landingzones.old/caf_networking/scenario/101-multi-region-hub/configuration.tfvars deleted file mode 100644 index 26f860340..000000000 --- a/landingzones.old/caf_networking/scenario/101-multi-region-hub/configuration.tfvars +++ /dev/null @@ -1,27 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "networking_hub" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - vnet_hub_re1 = { - name = "vnet-hub-re1" - region = "region1" - } - vnet_hub_re2 = { - name = "vnet-hub-re2" - region = "region2" - } -} diff --git a/landingzones.old/caf_networking/scenario/101-multi-region-hub/network_security_group_definition.tfvars b/landingzones.old/caf_networking/scenario/101-multi-region-hub/network_security_group_definition.tfvars deleted file mode 100644 index 6352fec33..000000000 --- a/landingzones.old/caf_networking/scenario/101-multi-region-hub/network_security_group_definition.tfvars +++ /dev/null @@ -1,344 +0,0 @@ -# -# Definition of the networking security groups -# -network_security_group_definition = { - # This entry is applied to all subnets with no NSG defined - empty_nsg = { - } - - azure_bastion_nsg = { - - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } - - application_gateway = { - - nsg = [ - { - name = "Inbound-HTTP", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "80-82" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "Inbound-HTTPs", - priority = "130" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "Inbound-AGW", - priority = "140" - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "65200-65535" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - ] - } - - api_management = { - - nsg = [ - { - name = "Inbound-APIM", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3443" - source_address_prefix = "ApiManagement" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Inbound-Redis", - priority = "110" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "6381-6383" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Inbound-LoadBalancer", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "AzureLoadBalancer" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "Outbound-StorageHttp", - priority = "100" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "80" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-StorageHttps", - priority = "110" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-AADHttp", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "80" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureActiveDirectory" - }, - { - name = "Outbound-AADHttps", - priority = "130" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureActiveDirectory" - }, - { - name = "Outbound-SQL", - priority = "140" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "1433" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "SQL" - }, - { - name = "Outbound-EventHub", - priority = "150" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "5671-5672" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "EventHub" - }, - { - name = "Outbound-EventHubHttps", - priority = "160" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "EventHub" - }, - { - name = "Outbound-FileShareGit", - priority = "170" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "445" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "Storage" - }, - { - name = "Outbound-Health", - priority = "180" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "1886" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-Monitor", - priority = "190" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "AzureMonitor" - }, - { - name = "Outbound-MoSMTP1itor", - priority = "200" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "25" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-SMTP2", - priority = "210" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "587" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-SMTP3", - priority = "220" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "25028" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "INTERNET" - }, - { - name = "Outbound-Redis", - priority = "230" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "6381-6383" - source_address_prefix = "VirtualNetwork" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - - jumpbox = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "ssh-inbound-22", - priority = "200" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - -} diff --git a/landingzones.old/caf_networking/scenario/101-multi-region-hub/peering.tfvars b/landingzones.old/caf_networking/scenario/101-multi-region-hub/peering.tfvars deleted file mode 100644 index 40a1eb491..000000000 --- a/landingzones.old/caf_networking/scenario/101-multi-region-hub/peering.tfvars +++ /dev/null @@ -1,31 +0,0 @@ - -vnet_peerings = { - hub_re1_TO_hub_re2 = { - name = "hub_re1_TO_hub_re2" - from = { - vnet_key = "hub_re1" - } - to = { - vnet_key = "hub_re2" - } - allow_virtual_network_access = true - allow_forwarded_traffic = false - allow_gateway_transit = false - use_remote_gateways = false - } - - hub_re2_TO_hub_re1 = { - name = "hub_re2_TO_hub_re1" - from = { - vnet_key = "hub_re2" - } - to = { - vnet_key = "hub_re1" - } - allow_virtual_network_access = true - allow_forwarded_traffic = false - allow_gateway_transit = false - use_remote_gateways = false - } - -} diff --git a/landingzones.old/caf_networking/scenario/101-multi-region-hub/readme.md b/landingzones.old/caf_networking/scenario/101-multi-region-hub/readme.md deleted file mode 100644 index 8d7ad2ac7..000000000 --- a/landingzones.old/caf_networking/scenario/101-multi-region-hub/readme.md +++ /dev/null @@ -1,50 +0,0 @@ -# CAF landing zones for Terraform - Multi-region hub with global peering - -This scenario deploys the networking hub across multiple regions - -The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. - -* Hub and spoke -* Virtual WAN -* Application DMZ scenario -* Any custom network topology based on virtual networks or virtual WAN -* Library of network security groups definition - -Networking landing zone operates at **level 2**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). - -## Architecture diagram - -This example allows you to deploy the following topology: - -![101-example](../../documentation/img/101-multi-region-hub.png) - - -## Components deployed by this example - -| Component | Type of resource | Purpose | -|----------------------------------------------------------------------------------|-------------------------|--------------------------------------------------------------------------------------------| -| vnet-hub-re1, vnet-hub-re2 | Resource group | resource group to host the virtual network | -| vnet_hub_re1, vnet-hub-re2 | Virtual network | virtual network used as a hub | -| GatewaySubnet,AzureFirewallSubnet,AzureBastionSubnet, jumpbox, private_endpoints | Virtual Subnets | virtual subnets | -| azure_bastion_nsg, empty_nsg, application_gateway, api_management, jumpbox | Network security groups | network security groups that can be attached to virtual subnets. | -| hub_re1_TO_hub_re2, and hub_re2_TO_hub_re1 | Virtual network peering | Peering between vnet_hub_re1 and vnet-hub-re2 | -| bastion-re1-pip1, bastion-re2-pip1 | Public IP address | Public IP address to be used in vnet_hub_re1 and vnet-hub-re2, to be used by Azure Bastion | -| bastion-re1, bastion-re2 | Azure Bastion | Azure Bastion host in order to access the virtual network. | - - -## Customizing this example - -Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. - -## Deploying this example - -Once you have picked a scenario for test, you can deploy it using: - -```bash -rover -lz /tf/caf/landingzones/caf_networking \ --level level2 \ --var-folder /tf/caf/landingzones/caf_networking/scenario/101-multi-region-hub \ --a apply -``` diff --git a/landingzones.old/caf_networking/scenario/101-multi-region-hub/virtual_networks.tfvars b/landingzones.old/caf_networking/scenario/101-multi-region-hub/virtual_networks.tfvars deleted file mode 100644 index 67af89832..000000000 --- a/landingzones.old/caf_networking/scenario/101-multi-region-hub/virtual_networks.tfvars +++ /dev/null @@ -1,78 +0,0 @@ - -vnets = { - hub_re1 = { - resource_group_key = "vnet_hub_re1" - region = "region1" - vnet = { - name = "hub-re1" - address_space = ["100.64.100.0/22"] - } - specialsubnets = { - GatewaySubnet = { - name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway - cidr = ["100.64.100.0/27"] - } - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["100.64.101.0/26"] - } - } - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["100.64.101.64/26"] - nsg_key = "azure_bastion_nsg" - } - jumpbox = { - name = "jumpbox" - cidr = ["100.64.102.0/27"] - nsg_key = "jumpbox" - } - private_endpoints = { - name = "private_endpoints" - cidr = ["100.64.103.128/25"] - enforce_private_link_endpoint_network_policies = true - } - } - - } - - hub_re2 = { - resource_group_key = "vnet_hub_re2" - region = "region2" - vnet = { - name = "hub-re2" - address_space = ["100.65.100.0/22"] - } - specialsubnets = { - GatewaySubnet = { - name = "GatewaySubnet" #Must be called GateWaySubnet in order to host a Virtual Network Gateway - cidr = ["100.65.100.0/27"] - } - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["100.65.101.0/26"] - } - } - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["100.65.101.64/26"] - nsg_key = "azure_bastion_nsg" - } - jumpbox = { - name = "jumpbox" - cidr = ["100.65.102.0/27"] - nsg_key = "jumpbox" - } - private_endpoints = { - name = "private_endpoints" - cidr = ["100.65.103.128/25"] - enforce_private_link_endpoint_network_policies = true - } - } - - } - - -} diff --git a/landingzones.old/caf_networking/scenario/105-hub-and-spoke/configuration.tfvars b/landingzones.old/caf_networking/scenario/105-hub-and-spoke/configuration.tfvars deleted file mode 100644 index b32be7ef7..000000000 --- a/landingzones.old/caf_networking/scenario/105-hub-and-spoke/configuration.tfvars +++ /dev/null @@ -1,155 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "networking_hub" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - vnet_hub_region1 = { - name = "vnet-hub-re1" - } - vnet_spoke_region1 = { - name = "vnet-spoke-re1" - } -} - -vnets = { - hub_re1 = { - resource_group_key = "vnet_hub_region1" - vnet = { - name = "hub-re1" - address_space = ["10.10.100.0/24"] - } - specialsubnets = { - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["10.10.100.192/26"] - } - } - subnets = { - jumphost = { - name = "jumphost" - cidr = ["10.10.100.0/25"] - nsg_key = "jumphost" - } - } - } - - spoke_re1 = { - resource_group_key = "vnet_spoke_region1" - vnet = { - name = "spoke-re1" - address_space = ["10.11.100.0/24"] - } - specialsubnets = {} - subnets = { - jumphost = { - name = "jumphost" - cidr = ["10.11.100.0/25"] - nsg_key = "jumphost" - } - webapp1 = { - name = "webapp-presentation-tier" - cidr = ["10.11.100.128/25"] - } - } - } -} - -azurerm_firewalls = { - # Southeastasia firewall (do not change the key when created) - fw_re1 = { - region = "region1" - name = "azfwre1" - resource_group_key = "vnet_hub_region1" - vnet_key = "hub_re1" - public_ip_key = "az_fw_pip" - - } - -} - -public_ip_addresses = { - - az_fw_pip = { - name = "az_fw_re1_pip1" - region = "region1" - resource_group_key = "vnet_hub_region1" - sku = "Standard" - allocation_method = "Static" - ip_version = "IPv4" - idle_timeout_in_minutes = "4" - - } -} - -route_tables = { - default_to_firewall_re1 = { - name = "default_to_firewall_re1" - resource_group_key = "vnet_spoke_region1" - } -} - -azurerm_routes = { - default_to_firewall_rg1 = { - name = "0-0-0-0-through-firewall-re1" - resource_group_key = "vnet_spoke_region1" - route_table_key = "default_to_firewall_re1" - address_prefix = "0.0.0.0/0" - next_hop_type = "VirtualAppliance" - - # To be set when next_hop_type = "VirtualAppliance" - private_ip_keys = { - azurerm_firewall = { - key = "fw_re1" - interface_index = 0 - } - # virtual_machine = { - # key = "" - # nic_key = "" - # } - } - } -} - -vnet_peerings = { - hub-re1_TO_spoke-re1 = { - name = "hub-re1_TO_spoke-re1" - from = { - vnet_key = "hub_re1" - } - to = { - vnet_key = "spoke_re1" - } - allow_virtual_network_access = true - allow_forwarded_traffic = true - allow_gateway_transit = false - use_remote_gateways = false - } - - spoke-re1_TO_hub-re1 = { - name = "hub_re2_TO_hub_re1" - from = { - vnet_key = "spoke_re1" - } - to = { - vnet_key = "hub_re1" - } - allow_virtual_network_access = true - allow_forwarded_traffic = false - allow_gateway_transit = false - use_remote_gateways = false - } - -} diff --git a/landingzones.old/caf_networking/scenario/105-hub-and-spoke/network_security_group_definition.tfvars b/landingzones.old/caf_networking/scenario/105-hub-and-spoke/network_security_group_definition.tfvars deleted file mode 100644 index 40dfc522a..000000000 --- a/landingzones.old/caf_networking/scenario/105-hub-and-spoke/network_security_group_definition.tfvars +++ /dev/null @@ -1,122 +0,0 @@ -# -# Definition of the networking security groups -# -network_security_group_definition = { - azure_bastion_nsg = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } - - jumphost = { - - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "ssh-inbound-22", - priority = "200" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - ] - } - -} diff --git a/landingzones.old/caf_networking/scenario/105-hub-and-spoke/readme.md b/landingzones.old/caf_networking/scenario/105-hub-and-spoke/readme.md deleted file mode 100644 index b2820fb78..000000000 --- a/landingzones.old/caf_networking/scenario/105-hub-and-spoke/readme.md +++ /dev/null @@ -1,52 +0,0 @@ -# CAF landing zones for Terraform - Secure Hub and Spoke with Azure Firewall - -This scenario deploys the networking hub across multiple regions - -The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. - -* Hub and spoke -* Virtual WAN -* Application DMZ scenario -* Any custom network topology based on virtual networks or virtual WAN -* Library of network security groups definition - -Networking landing zone operates at **level 2**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). - -## Architecture diagram - -This example allows you to deploy the following topology: - -![101-example](../../documentation/img/105-hub-and-spoke.png) - - -## Components deployed by this example - -| Component | Type of resource | Purpose | -|--|--|--| -| vnet-hub-re1, vnet-spoke-re2 | Resource group | resource group to host the virtual network | -| hub-re1, spoke-re1 | Virtual network | virtual networks for hub and spokeshub | -| AzureFirewallSubnet,jumphost, webapp-presentation-tier | Virtual Subnets | virtual subnets | -| azure_bastion_nsg, , jumphost_nsg | Network security groups | network security groups that can be attached to virtual subnets. | -| hub_re1_TO_spoke_re1, and spoke_re1_TO_hub_re1 | Virtual network peering | Peering between hub-re1 and spoke-re1 | -| azfwre1 | Azure Firewall | Azure Firewall in Hub network | -| az_fw_re1_pip1 | Public IP address | Public IP address used by Azure Firewall | -| default_to_firewall_re1 | Route table | Route table to host route entries | -| 0-0-0-0-through-firewall-re1 | Route table entry | Route all traffic to Azure Firewall in hub | - - -## Customizing this example - -Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. - -## Deploying this example - -Once you have picked a scenario for test, you can deploy it using: - -```bash -rover -lz /tf/caf/landingzones/caf_networking \ --level level2 \ --var-folder /tf/caf/landingzones/caf_networking/scenario/105-hub-and-spoke \ --a apply -``` diff --git a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars deleted file mode 100644 index ea7eb6d12..000000000 --- a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/configuration.tfvars +++ /dev/null @@ -1,71 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "networking_hub" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - vnet_re1 = { - name = "vnet-spoke-re1" - region = "region1" - } - hub_re1 = { - name = "vnet-hub-re1" - region = "region1" - } -} - -vnets = { - vnet_re1 = { - resource_group_key = "vnet_re1" - region = "region1" - vnet = { - name = "hub-re1" - address_space = ["10.10.100.0/24"] - } - specialsubnets = { - AzureFirewallSubnet = { - name = "AzureFirewallSubnet" #Must be called AzureFirewallSubnet - cidr = ["10.10.100.192/26"] - } - } - subnets = { - AzureBastionSubnet = { - name = "AzureBastionSubnet" #Must be called AzureBastionSubnet - cidr = ["10.10.100.160/27"] - nsg_key = "azure_bastion_nsg" - } - } - } -} - -vhub_peerings = { - # Establish the peering with Virtual Hubs - hub_rg1-TO-vnet_rg1 = { - vhub = { - virtual_wan_key = "vwan_re1" - virtual_hub_key = "hub_re1" - } - vnet = { - # If the virtual network is stored in another another landing zone, use the following attributes to refer the state file: - # lz_key = "networking" - # output_key = "vnets" - vnet_key = "vnet_re1" - } - name = "vhub_peering_hub_sg" - hub_to_virtual_network_traffic_allowed = true - virtual_network_to_hub_gateways_traffic_allowed = true - internet_security_enabled = true - } -} diff --git a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars deleted file mode 100644 index 3d3d06e3a..000000000 --- a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/network_security_group_definition.tfvars +++ /dev/null @@ -1,104 +0,0 @@ -network_security_group_definition = { - empty_nsg = { - - nsg = [] - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } - - azure_bastion_nsg = { - diagnostic_profiles = { - nsg = { - definition_key = "network_security_group" - destination_type = "storage" - destination_key = "all_regions" - } - operations = { - name = "operations" - definition_key = "network_security_group" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - nsg = [ - { - name = "bastion-in-allow", - priority = "100" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "*" - }, - { - name = "bastion-control-in-allow-443", - priority = "120" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "135" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "Kerberos-password-change", - priority = "121" - direction = "Inbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "4443" - source_address_prefix = "GatewayManager" - destination_address_prefix = "*" - }, - { - name = "bastion-vnet-out-allow-22", - priority = "103" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "22" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-vnet-out-allow-3389", - priority = "101" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "3389" - source_address_prefix = "*" - destination_address_prefix = "VirtualNetwork" - }, - { - name = "bastion-azure-out-allow", - priority = "120" - direction = "Outbound" - access = "Allow" - protocol = "tcp" - source_port_range = "*" - destination_port_range = "443" - source_address_prefix = "*" - destination_address_prefix = "AzureCloud" - } - ] - } -} \ No newline at end of file diff --git a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/readme.md b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/readme.md deleted file mode 100644 index eb0b2487b..000000000 --- a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/readme.md +++ /dev/null @@ -1,47 +0,0 @@ -# CAF landing zones for Terraform - Azure Virtual WAN with Firewall manager - -The networking landing zone allows you to deploy most networking topologies on Microsoft Azure. The same landing zone used with different parameters should allow you to deploy most network configurations. - -* Hub and spoke -* Virtual WAN -* Application DMZ scenario -* Any custom network topology based on virtual networks or virtual WAN -* Library of network security groups definition - -Networking landing zone operates at **level 2**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../../../documentation/code_architecture/hierarchy.md). - -## Architecture diagram - -This example allows you to deploy the following topology: - -![virtual_wan_lz](../../documentation/img/106-hub-virtual-wan-firewall.png) - - -## Components deployed by this example - -| Component | Type of resource | Purpose | -|------------------------------|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| vnet-spoke-re1, vnet-hub-re1 | Resource group | resource group to host the virtual network and virtual WAN | -| vnet_re1 | Virtual network with subnets, network security groups | virtual network used as a spoke, attached to the virtual hub from Azure Virtual WAN | -| contosovWAN-re1 | Virtual WAN | virtual WAN infrastructure | -| hub-re1, hub-re2 | Virtual Hubs | virtual hubs to be deployed in region, the hubs can be configured to deploy point-to-site connectivity, site-to-site connectivity or Express Route connectivity. | -| hub_fw_re1, hub_fw_re2 | Azure Firewall | traffic filtering between hubs and outside | -| hub_rg1-TO-vnet_rg1 | Virtual network and Virtual Hubs peering objects | network peering between virtual hubs and virtual network | - - -## Customizing this example - -Please review the configuration files and make sure you are deploying in the expected region and with the expected settings. - -## Deploying this example - -Once you have picked a scenario for test, you can deploy it using: - -```bash -rover -lz /tf/caf/landingzones/caf_networking \ --level level2 \ --var-folder /tf/caf/landingzones/caf_networking/scenario/106-hub-virtual-wan-firewall \ --a apply -``` diff --git a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/virtual_wan.tfvars b/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/virtual_wan.tfvars deleted file mode 100644 index 547e62450..000000000 --- a/landingzones.old/caf_networking/scenario/106-hub-virtual-wan-firewall/virtual_wan.tfvars +++ /dev/null @@ -1,84 +0,0 @@ -virtual_wans = { - vwan_re1 = { - resource_group_key = "hub_re1" - name = "contosovWAN-re1" - region = "region1" - - hubs = { - hub_re1 = { - hub_name = "hub-re1" - region = "region1" - hub_address_prefix = "10.0.3.0/24" - deploy_firewall = true - firewall_name = "hub-fw-re1" - firewall_resource_group_key = "hub_re1" - deploy_p2s = false - p2s_config = { - name = "caf-sea-vpn-p2s" - scale_unit = 2 - connection_configuration = { - name = "client-connections" - vpn_client_address_pool = { - address_prefixes = ["192.168.0.0/24"] - } - } - server_config = { - vpn_authentication_types = ["Certificate"] - client_root_certificate = { - name = "DigiCert-Federated-ID-Root-CA" - public_cert_data = < merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) - } - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) - } - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) - } - keyvaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) - } - recovery_vaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.recovery_vaults[key], {})) - } - } -} diff --git a/landingzones.old/caf_shared_services/main.tf b/landingzones.old/caf_shared_services/main.tf deleted file mode 100644 index 8eb1f3590..000000000 --- a/landingzones.old/caf_shared_services/main.tf +++ /dev/null @@ -1,66 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - - -locals { - - # Update the tfstates map - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} \ No newline at end of file diff --git a/landingzones.old/caf_shared_services/output.tf b/landingzones.old/caf_shared_services/output.tf deleted file mode 100644 index 775534ced..000000000 --- a/landingzones.old/caf_shared_services/output.tf +++ /dev/null @@ -1,29 +0,0 @@ -output "global_settings" { - value = local.global_settings - sensitive = true -} - -output "diagnostics" { - value = local.diagnostics - sensitive = true -} - -output "tfstates" { - value = local.tfstates - sensitive = true -} - -output "managed_identities" { - value = local.remote.managed_identities - sensitive = true -} -output "azuread_groups" { - value = local.remote.azuread_groups - sensitive = true -} - -output "recovery_vaults" { - value = tomap({ - (var.landingzone.key) = module.landingzones_shared_services.recovery_vaults - }) -} \ No newline at end of file diff --git a/landingzones.old/caf_shared_services/readme.md b/landingzones.old/caf_shared_services/readme.md deleted file mode 100644 index c87bf6d35..000000000 --- a/landingzones.old/caf_shared_services/readme.md +++ /dev/null @@ -1,40 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Shared services - -The Shared services landing zone allows you to management components on Microsoft Azure, typically: - -* Monitoring -* Azure Site Recovery -* Azure Backup -* Azure Automation - -Shared services landing zone operates at **level 2**. - -It is **important** to deploy shared services landing zone, even in passthrough mode as it will export some shared parameters and settings from level1 landing zones. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -## Deploying shared services - -By default, the content of this landing zone is empty unless you specify a configuration file to enable it. - -```bash -rover -lz /tf/caf/public/landingzones/caf_shared_services \ --level level2 \ --a apply -``` - -You can deploy an example with Azure Site Recovery configuration and Automation: - -```bash -rover -lz /tf/caf/public/landingzones/caf_shared_services \ - -level level2 \ - -var-folder /tf/caf/public/landingzones/caf_shared_services/scenario/100 \ - -a apply - -# If the tfstates are stored in a different subscription you need to execute the following command -rover -lz /tf/caf/public/landingzones/caf_shared_services \ - -tfstate_subscription_id \ - -level level2 \ - -var-folder /tf/caf/public/landingzones/caf_shared_services/scenario/100 \ - -a apply -``` diff --git a/landingzones.old/caf_shared_services/scenario/100/configuration.tfvars b/landingzones.old/caf_shared_services/scenario/100/configuration.tfvars deleted file mode 100644 index 25489ff12..000000000 --- a/landingzones.old/caf_shared_services/scenario/100/configuration.tfvars +++ /dev/null @@ -1,140 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "shared_services" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - primary = { - name = "sharedsvc_re1" - } -} - -recovery_vaults = { - asr1 = { - name = "vault_re1" - resource_group_key = "primary" - - region = "region1" - - # replication_policies = { - # repl1 = { - # name = "policy1" - # resource_group_key = "primary" - - # recovery_point_retention_in_minutes = 24 * 60 - # application_consistent_snapshot_frequency_in_minutes = 4 * 60 - # } - # } - - # recovery_fabrics = { - # fabric1 = { - # name = "fabric-primary" - # resource_group_key = "primary" - # region = "region1" - # } - # fabric2 = { - # name = "fabric-secondary" - # resource_group_key = "secondary" - # region = "region2" - # } - # } - - # protection_containers = { - # container1 = { - # name = "protection_container1" - # resource_group_key = "primary" - # recovery_fabric_key = "fabric1" - # } - # container2 = { - # name = "protection_container2" - # resource_group_key = "secondary" - # recovery_fabric_key = "fabric2" - # } - # } - - # protection_container_mapping = { - # hk-sg = { - # name = "hk-sg-container-mapping" - # vault_key = "asr1" - # resource_group_key = "secondary" - # fabric_key = "fabric1" - # source_protection_container_key = "container1" - # target_protection_container_key = "container2" - # policy_key = "repl1" - # } - #} - backup_policies = { - vms = { - policy1 = { - name = "VMBackupPolicy1" - vault_key = "asr1" - rg_key = "primary" - timezone = "UTC" - backup = { - frequency = "Daily" - time = "23:00" - #if not desired daily, can pick weekdays as below: - #weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] - } - retention_daily = { - count = 10 - } - retention_weekly = { - count = 42 - weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"] - } - retention_monthly = { - count = 7 - weekdays = ["Sunday", "Wednesday"] - weeks = ["First", "Last"] - } - retention_yearly = { - count = 77 - weekdays = ["Sunday"] - weeks = ["Last"] - months = ["January"] - } - } - } - - fs = { - policy1 = { - name = "FSBackupPolicy1" - vault_key = "asr1" - rg_key = "primary" - timezone = "UTC" - backup = { - frequency = "Daily" - time = "23:00" - } - retention_daily = { - count = 10 - } - } - } - } - } - -} - -automations = { - auto1 = { - name = "autore1" - resource_group_key = "primary" - - region = "region1" - } - -} \ No newline at end of file diff --git a/landingzones.old/caf_shared_services/scenario/200/configuration.tfvars b/landingzones.old/caf_shared_services/scenario/200/configuration.tfvars deleted file mode 100644 index 0f8c8559c..000000000 --- a/landingzones.old/caf_shared_services/scenario/200/configuration.tfvars +++ /dev/null @@ -1,156 +0,0 @@ -landingzone = { - backend_type = "azurerm" - global_settings_key = "foundations" - level = "level2" - key = "shared_services" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - launchpad = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } -} - -resource_groups = { - primary = { - name = "sharedsvc_re1" - } -} - -recovery_vaults = { - asr1 = { - name = "vault_re1" - resource_group_key = "primary" - - region = "region1" - - diagnostic_profiles = { - asr1 = { - definition_key = "azure_site_recovery" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - - # replication_policies = { - # repl1 = { - # name = "policy1" - # resource_group_key = "primary" - - # recovery_point_retention_in_minutes = 24 * 60 - # application_consistent_snapshot_frequency_in_minutes = 4 * 60 - # } - # } - - # recovery_fabrics = { - # fabric1 = { - # name = "fabric-primary" - # resource_group_key = "primary" - # region = "region1" - # } - # fabric2 = { - # name = "fabric-secondary" - # resource_group_key = "secondary" - # region = "region2" - # } - # } - - # protection_containers = { - # container1 = { - # name = "protection_container1" - # resource_group_key = "primary" - # recovery_fabric_key = "fabric1" - # } - # container2 = { - # name = "protection_container2" - # resource_group_key = "secondary" - # recovery_fabric_key = "fabric2" - # } - # } - - # protection_container_mapping = { - # hk-sg = { - # name = "hk-sg-container-mapping" - # vault_key = "asr1" - # resource_group_key = "secondary" - # fabric_key = "fabric1" - # source_protection_container_key = "container1" - # target_protection_container_key = "container2" - # policy_key = "repl1" - # } - #} - backup_policies = { - vms = { - policy1 = { - name = "VMBackupPolicy1" - vault_key = "asr1" - rg_key = "primary" - timezone = "UTC" - backup = { - frequency = "Daily" - time = "23:00" - #if not desired daily, can pick weekdays as below: - #weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] - } - retention_daily = { - count = 10 - } - retention_weekly = { - count = 42 - weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"] - } - retention_monthly = { - count = 7 - weekdays = ["Sunday", "Wednesday"] - weeks = ["First", "Last"] - } - retention_yearly = { - count = 77 - weekdays = ["Sunday"] - weeks = ["Last"] - months = ["January"] - } - } - } - - fs = { - policy1 = { - name = "FSBackupPolicy1" - vault_key = "asr1" - rg_key = "primary" - timezone = "UTC" - backup = { - frequency = "Daily" - time = "23:00" - } - retention_daily = { - count = 10 - } - } - } - } - } - -} - -automations = { - auto1 = { - name = "autore1" - resource_group_key = "primary" - - region = "region1" - - diagnostic_profiles = { - asr1 = { - definition_key = "azure_automation" - destination_type = "log_analytics" - destination_key = "central_logs" - } - } - } - -} \ No newline at end of file diff --git a/landingzones.old/caf_shared_services/variables.tf b/landingzones.old/caf_shared_services/variables.tf deleted file mode 100644 index 9916a4178..000000000 --- a/landingzones.old/caf_shared_services/variables.tf +++ /dev/null @@ -1,71 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} - -variable "landingzone" { - default = { - backend_type = "azurerm" - level = "level2" - global_settings_key = "foundations" - key = "shared_services" - tfstates = { - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - foundations = { - level = "lower" - tfstate = "caf_foundations.tfstate" - } - } - } -} -variable "tenant_id" {} -variable "global_settings" { - default = {} -} -variable "rover_version" {} -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - type = map(any) - default = {} -} -variable "diagnostics_definition" { - default = {} -} -variable "resource_groups" { - default = {} -} -variable "automations" { - default = {} -} -variable "recovery_vaults" { - default = {} -} -variable "replicated_vms" { - default = {} -} -variable "network_mappings" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "virtual_machines" { - default = {} -} \ No newline at end of file diff --git a/landingzones.old/caf_shared_services/vm_extensions.tf b/landingzones.old/caf_shared_services/vm_extensions.tf deleted file mode 100644 index 838e39926..000000000 --- a/landingzones.old/caf_shared_services/vm_extensions.tf +++ /dev/null @@ -1,42 +0,0 @@ -# -# microsoft_enterprise_cloud_monitoring - Install the monitoring agent in the virtual machine -# - - -module "vm_extension_monitoring_agent" { - source = "aztfmod/caf/azurerm//modules/compute/virtual_machine_extensions" - version = "~>5.2.0" - - for_each = { - for key, value in try(var.virtual_machines, {}) : key => value - if try(value.virtual_machine_extensions.microsoft_enterprise_cloud_monitoring, null) != null - } - - client_config = module.landingzones_shared_services.client_config - virtual_machine_id = module.landingzones_shared_services.virtual_machines[each.key].id - extension = each.value.virtual_machine_extensions.microsoft_enterprise_cloud_monitoring - extension_name = "microsoft_enterprise_cloud_monitoring" - settings = { - diagnostics = local.diagnostics - } -} - -module "vm_extension_diagnostics" { - source = "aztfmod/caf/azurerm//modules/compute/virtual_machine_extensions" - version = "~>5.2.0" - - for_each = { - for key, value in try(var.virtual_machines, {}) : key => value - if try(value.virtual_machine_extensions.microsoft_azure_diagnostics, null) != null - } - - client_config = module.landingzones_shared_services.client_config - virtual_machine_id = module.landingzones_shared_services.virtual_machines[each.key].id - extension = each.value.virtual_machine_extensions.microsoft_azure_diagnostics - extension_name = "microsoft_azure_diagnostics" - settings = { - diagnostics = local.diagnostics - xml_diagnostics_file = try(each.value.virtual_machine_extensions.microsoft_azure_diagnostics.xml_diagnostics_file, null) - diagnostics_storage_account_keys = each.value.virtual_machine_extensions.microsoft_azure_diagnostics.diagnostics_storage_account_keys - } -} diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/app/main.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/app/main.tf deleted file mode 100644 index 1191eedce..000000000 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/app/main.tf +++ /dev/null @@ -1,7 +0,0 @@ -provider "kubernetes" { - alias = "k8s" -} - -provider "helm" { - alias = "helm" -} diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/app/module.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/app/module.tf deleted file mode 100644 index 2d4288893..000000000 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/app/module.tf +++ /dev/null @@ -1,48 +0,0 @@ -resource "kubernetes_namespace" "namespaces" { - for_each = var.namespaces - metadata { - annotations = try(each.value.annotations, null) - labels = try(each.value.labels, null) - name = each.value.name - } - - provider = kubernetes.k8s -} - -# https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release -resource "helm_release" "charts" { - for_each = var.helm_charts - - name = each.value.name - repository = each.value.repository - chart = each.value.chart - - namespace = each.value.namespace - wait = try(each.value.wait, true) - timeout = try(each.value.timeout, 900) - skip_crds = try(each.value.skip_crds, false) - create_namespace = try(each.value.create_namespace, false) - - dynamic "set" { - for_each = try(each.value.sets, {}) - content { - name = set.key - value = set.value - } - } - - dynamic "set_sensitive" { - for_each = try(each.value.sets_sensitive, {}) - content { - name = set_sensitive.key - value = set_sensitive.value - } - } - - provider = helm.helm - - depends_on = [kubernetes_namespace.namespaces] - # values = [ - # "${file("values.yaml")}" - # ] -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/app/output.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/app/output.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf deleted file mode 100644 index 4a0225192..000000000 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/app/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "cluster" {} - -variable "namespaces" {} - -variable "helm_charts" {} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/applications.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/applications.tf deleted file mode 100644 index b1f674491..000000000 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/applications.tf +++ /dev/null @@ -1,27 +0,0 @@ -module "app1" { - source = "./app" - for_each = try(local.clusters[var.cluster_re1_key], null) != null ? { (var.cluster_re1_key) = local.clusters[var.cluster_re1_key] } : {} - - cluster = each.value - namespaces = var.namespaces - helm_charts = var.helm_charts - - providers = { - kubernetes.k8s = kubernetes.k8s1 - helm.helm = helm.helm1 - } -} - -module "app2" { - source = "./app" - for_each = try(local.clusters[var.cluster_re2_key], null) != null ? { (var.cluster_re2_key) = local.clusters[var.cluster_re2_key] } : {} - - cluster = each.value - namespaces = var.namespaces - helm_charts = var.helm_charts - - providers = { - kubernetes.k8s = kubernetes.k8s2 - helm.helm = helm.helm2 - } -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/backend.azurerm b/landingzones.old/caf_solutions/add-ons/aks_applications/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/locals.remote_tfstates.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/locals.remote_tfstates.tf deleted file mode 100644 index 3d367287d..000000000 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/locals.remote_tfstates.tf +++ /dev/null @@ -1,54 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - remote = { - aks_clusters = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aks_clusters[key], {})) - } - } - - clusters = local.remote.aks_clusters[var.landingzone.global_settings_key] - k8sconfigs = { for key, value in values(local.clusters) : key => { - host = value.enable_rbac ? value.kube_config.0.host : value.kube_config.0.host - username = value.enable_rbac ? value.kube_config.0.username : value.kube_config.0.username - password = value.enable_rbac ? value.kube_config.0.password : value.kube_config.0.password - client_certificate = value.enable_rbac ? base64decode(value.kube_config.0.client_certificate) : base64decode(value.kube_config.0.client_certificate) - client_key = value.enable_rbac ? base64decode(value.kube_config.0.client_key) : base64decode(value.kube_config.0.client_key) - cluster_ca_certificate = value.enable_rbac ? base64decode(value.kube_config.0.cluster_ca_certificate) : base64decode(value.kube_config.0.cluster_ca_certificate) - } - } - -} diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/main.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/main.tf deleted file mode 100644 index 69ab5ac44..000000000 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/main.tf +++ /dev/null @@ -1,75 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.49" - } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 1.13.2" - } - helm = { - source = "hashicorp/helm" - version = "~> 1.3.0" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - - -provider "kubernetes" { - load_config_file = false - host = try(local.k8sconfigs[0].host, null) - username = try(local.k8sconfigs[0].username, null) - password = try(local.k8sconfigs[0].password, null) - client_certificate = try(local.k8sconfigs[0].client_certificate, null) - client_key = try(local.k8sconfigs[0].client_key, null) - cluster_ca_certificate = try(local.k8sconfigs[0].cluster_ca_certificate, null) - alias = "k8s1" -} - -provider "helm" { - kubernetes { - load_config_file = false - host = try(local.k8sconfigs[0].host, null) - username = try(local.k8sconfigs[0].username, null) - password = try(local.k8sconfigs[0].password, null) - client_certificate = try(local.k8sconfigs[0].client_certificate, null) - client_key = try(local.k8sconfigs[0].client_key, null) - cluster_ca_certificate = try(local.k8sconfigs[0].cluster_ca_certificate, null) - } - alias = "helm1" -} - -provider "kubernetes" { - load_config_file = false - host = try(local.k8sconfigs[1].host, null) - username = try(local.k8sconfigs[1].username, null) - password = try(local.k8sconfigs[1].password, null) - client_certificate = try(local.k8sconfigs[1].client_certificate, null) - client_key = try(local.k8sconfigs[1].client_key, null) - cluster_ca_certificate = try(local.k8sconfigs[1].cluster_ca_certificate, null) - alias = "k8s2" -} - -provider "helm" { - kubernetes { - load_config_file = false - host = try(local.k8sconfigs[1].host, null) - username = try(local.k8sconfigs[1].username, null) - password = try(local.k8sconfigs[1].password, null) - client_certificate = try(local.k8sconfigs[1].client_certificate, null) - client_key = try(local.k8sconfigs[1].client_key, null) - cluster_ca_certificate = try(local.k8sconfigs[1].cluster_ca_certificate, null) - } - alias = "helm2" -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/output.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/output.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf b/landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf deleted file mode 100644 index 7ad77ea93..000000000 --- a/landingzones.old/caf_solutions/add-ons/aks_applications/variables.tf +++ /dev/null @@ -1,36 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_resource_group_name" {} -# variable tfstate_key {} - -variable "global_settings" { - default = {} -} - -# variable tenant_id {} -variable "landingzone" {} - -variable "namespaces" {} - -variable "tags" { - default = null - type = map(any) -} - -variable "helm_charts" {} - -variable "rover_version" { - default = null -} - -variable "cluster_re1_key" { - default = null -} -variable "cluster_re2_key" { - default = null -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/databricks/backend.azurerm b/landingzones.old/caf_solutions/add-ons/databricks/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones.old/caf_solutions/add-ons/databricks/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/add-ons/databricks/databricks.tf b/landingzones.old/caf_solutions/add-ons/databricks/databricks.tf deleted file mode 100644 index 1c81174b7..000000000 --- a/landingzones.old/caf_solutions/add-ons/databricks/databricks.tf +++ /dev/null @@ -1,21 +0,0 @@ -locals { - azure_workspace_resource_id = local.remote.databricks_workspaces[var.databricks.lz_key][var.databricks.workspace_key].id -} - -provider "databricks" { - azure_workspace_resource_id = local.azure_workspace_resource_id - # azure_client_id = var.client_id - # azure_client_secret = var.client_secret - # azure_tenant_id = var.tenant_id -} - -module "databricks" { - source = "../../modules/databricks" - - settings = var.databricks -} - -output "databricks" { - value = module.databricks - sensitive = false -} diff --git a/landingzones.old/caf_solutions/add-ons/databricks/locals.remote_tfstates.tf b/landingzones.old/caf_solutions/add-ons/databricks/locals.remote_tfstates.tf deleted file mode 100644 index b813756c5..000000000 --- a/landingzones.old/caf_solutions/add-ons/databricks/locals.remote_tfstates.tf +++ /dev/null @@ -1,43 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - remote = { - databricks_workspaces = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.databricks_workspaces[key], {})) - } - } - -} diff --git a/landingzones.old/caf_solutions/add-ons/databricks/main.tf b/landingzones.old/caf_solutions/add-ons/databricks/main.tf deleted file mode 100644 index 743b254d2..000000000 --- a/landingzones.old/caf_solutions/add-ons/databricks/main.tf +++ /dev/null @@ -1,63 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.48" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - databricks = { - source = "databrickslabs/databricks" - version = "~> 0.3.1" - } - } - required_version = ">= 0.13" -} - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - -data "terraform_remote_state" "landingzone" { - backend = "azurerm" - config = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - key = var.tfstate_key - resource_group_name = var.tfstate_resource_group_name - } -} - -locals { - diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.landingzone.outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.landingzone.outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.landingzone.outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.landingzone.outputs.diagnostics.log_analytics - } - - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", data.azurerm_client_config.current.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.landingzone.outputs.tfstates - ) - -} diff --git a/landingzones.old/caf_solutions/add-ons/databricks/variables.tf b/landingzones.old/caf_solutions/add-ons/databricks/variables.tf deleted file mode 100644 index 848b0ece0..000000000 --- a/landingzones.old/caf_solutions/add-ons/databricks/variables.tf +++ /dev/null @@ -1,115 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "global_settings" { - default = {} -} - -variable "landingzone" { - default = "" -} - -variable "environment" { - default = "sandpit" -} -variable "rover_version" { - default = null -} -variable "max_length" { - default = 40 -} -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - default = null - type = map(any) -} -variable "app_service_environments" { - default = {} -} -variable "app_service_plans" { - default = {} -} -variable "app_services" { - default = {} -} -variable "diagnostics_definition" { - default = null -} -variable "resource_groups" { - default = null -} -variable "network_security_group_definition" { - default = null -} -variable "vnets" { - default = {} -} -variable "azurerm_redis_caches" { - default = {} -} -variable "mssql_servers" { - default = {} -} -variable "storage_accounts" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "keyvaults" { - default = {} -} -variable "keyvault_access_policies" { - default = {} -} -variable "virtual_machines" { - default = {} -} -variable "azure_container_registries" { - default = {} -} -variable "bastion_hosts" { - default = {} -} -variable "public_ip_addresses" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "managed_identities" { - default = {} -} -variable "private_dns" { - default = {} -} -variable "synapse_workspaces" { - default = {} -} -variable "azurerm_application_insights" { - default = {} -} -variable "role_mapping" { - default = {} -} -variable "aks_clusters" { - default = {} -} -variable "databricks_workspaces" { - default = {} -} -variable "databricks" { - default = {} -} diff --git a/landingzones.old/caf_solutions/backend.azurerm b/landingzones.old/caf_solutions/backend.azurerm deleted file mode 100644 index 5d026b233..000000000 --- a/landingzones.old/caf_solutions/backend.azurerm +++ /dev/null @@ -1,4 +0,0 @@ -terraform { - backend "azurerm" { - } -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/dynamic_secrets.tf b/landingzones.old/caf_solutions/dynamic_secrets.tf deleted file mode 100644 index 6515cd772..000000000 --- a/landingzones.old/caf_solutions/dynamic_secrets.tf +++ /dev/null @@ -1,10 +0,0 @@ -module "dynamic_keyvault_secrets" { - source = "aztfmod/caf/azurerm//modules/security/dynamic_keyvault_secrets" - version = "~>5.2.0" - - for_each = try(var.dynamic_keyvault_secrets, {}) - - settings = each.value - keyvault = module.caf.keyvaults[each.key] - objects = module.caf -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/landingzone.tf b/landingzones.old/caf_solutions/landingzone.tf deleted file mode 100644 index 06d1a28e5..000000000 --- a/landingzones.old/caf_solutions/landingzone.tf +++ /dev/null @@ -1,139 +0,0 @@ -module "caf" { - source = "aztfmod/caf/azurerm" - version = "~>5.2.0" - - azuread_api_permissions = var.azuread_api_permissions - azuread_apps = var.azuread_apps - azuread_groups = var.azuread_groups - azuread_roles = var.azuread_roles - azuread_users = var.azuread_users - current_landingzone_key = var.landingzone.key - custom_role_definitions = var.custom_role_definitions - diagnostics = local.diagnostics - event_hub_namespaces = var.event_hub_namespaces - global_settings = local.global_settings - keyvault_access_policies = var.keyvault_access_policies - keyvault_certificate_issuers = var.keyvault_certificate_issuers - keyvaults = var.keyvaults - log_analytics = var.log_analytics - logged_aad_app_objectId = var.logged_aad_app_objectId - logged_user_objectId = var.logged_user_objectId - managed_identities = var.managed_identities - resource_groups = var.resource_groups - role_mapping = var.role_mapping - storage_accounts = var.storage_accounts - tags = local.tags - tenant_id = var.tenant_id - tfstates = local.tfstates - user_type = var.user_type - - compute = { - aks_clusters = var.aks_clusters - availability_sets = var.availability_sets - azure_container_registries = var.azure_container_registries - bastion_hosts = var.bastion_hosts - proximity_placement_groups = var.proximity_placement_groups - virtual_machines = var.virtual_machines - } - - database = { - azurerm_redis_caches = var.azurerm_redis_caches - cosmos_dbs = var.cosmos_dbs - databricks_workspaces = var.databricks_workspaces - machine_learning_workspaces = var.machine_learning_workspaces - mariadb_servers = var.mariadb_servers - mssql_databases = var.mssql_databases - mssql_elastic_pools = var.mssql_elastic_pools - mssql_failover_groups = var.mssql_failover_groups - mssql_managed_databases = var.mssql_managed_databases - mssql_managed_databases_restore = var.mssql_managed_databases_restore - mssql_managed_instances = var.mssql_managed_instances - mssql_managed_instances_secondary = var.mssql_managed_instances_secondary - mssql_mi_administrators = var.mssql_mi_administrators - mssql_mi_failover_groups = var.mssql_mi_failover_groups - mssql_servers = var.mssql_servers - mysql_servers = var.mysql_servers - postgresql_servers = var.postgresql_servers - synapse_workspaces = var.synapse_workspaces - } - - networking = { - application_gateway_applications = var.application_gateway_applications - application_gateways = var.application_gateways - azurerm_routes = var.azurerm_routes - dns_zone_records = var.dns_zone_records - dns_zones = var.dns_zones - domain_name_registrations = var.domain_name_registrations - express_route_circuit_authorizations = var.express_route_circuit_authorizations - express_route_circuits = var.express_route_circuits - front_door_waf_policies = var.front_door_waf_policies - front_doors = var.front_doors - load_balancers = var.load_balancers - local_network_gateways = var.local_network_gateways - network_security_group_definition = var.network_security_group_definition - network_watchers = var.network_watchers - private_dns = var.private_dns - private_endpoints = var.private_endpoints - public_ip_addresses = var.public_ip_addresses - route_tables = var.route_tables - virtual_network_gateway_connections = var.virtual_network_gateway_connections - virtual_network_gateways = var.virtual_network_gateways - virtual_wans = var.virtual_wans - vnet_peerings = var.vnet_peerings - vnets = var.vnets - } - - remote_objects = { - aks_clusters = local.remote.aks_clusters - app_service_environments = local.remote.app_service_environments - app_service_plans = local.remote.app_service_plans - app_services = local.remote.app_services - application_gateway_applications = local.remote.application_gateway_applications - application_gateways = local.remote.application_gateways - availability_sets = local.remote.availability_sets - azuread_applications = local.remote.azuread_applications - azuread_groups = local.remote.azuread_groups - azuread_users = local.remote.azuread_users - azurerm_firewalls = local.remote.azurerm_firewalls - container_registry = local.remote.container_registry - event_hub_namespaces = local.remote.event_hub_namespaces - front_door_waf_policies = local.remote.front_door_waf_policies - keyvaults = local.remote.keyvaults - managed_identities = local.remote.managed_identities - mssql_databases = local.remote.mssql_databases - mssql_elastic_pools = local.remote.mssql_elastic_pools - mssql_managed_databases = local.remote.mssql_managed_databases - mssql_managed_instances = local.remote.mssql_managed_instances - mssql_servers = local.remote.mssql_servers - mysql_servers = local.remote.mysql_servers - network_watchers = local.remote.network_watchers - postgresql_servers = local.remote.postgresql_servers - private_dns = local.remote.private_dns - proximity_placement_groups = local.remote.proximity_placement_groups - public_ip_addresses = local.remote.public_ip_addresses - recovery_vaults = local.remote.recovery_vaults - resource_groups = local.remote.resource_groups - storage_accounts = local.remote.storage_accounts - synapse_workspaces = local.remote.synapse_workspaces - vnets = local.remote.vnets - } - - security = { - keyvault_certificate_issuers = var.keyvault_certificate_issuers - keyvault_certificate_requests = var.keyvault_certificate_requests - keyvault_certificates = var.keyvault_certificates - keyvault_keys = var.keyvault_keys - } - - shared_services = { - monitoring = var.monitoring - recovery_vaults = var.recovery_vaults - } - - webapp = { - app_service_environments = var.app_service_environments - app_service_plans = var.app_service_plans - app_services = var.app_services - azurerm_application_insights = var.azurerm_application_insights - } -} diff --git a/landingzones.old/caf_solutions/locals.remote_tfstates.tf b/landingzones.old/caf_solutions/locals.remote_tfstates.tf deleted file mode 100644 index 96de17801..000000000 --- a/landingzones.old/caf_solutions/locals.remote_tfstates.tf +++ /dev/null @@ -1,158 +0,0 @@ -locals { - landingzone = { - current = { - storage_account_name = var.tfstate_storage_account_name - container_name = var.tfstate_container_name - resource_group_name = var.tfstate_resource_group_name - } - lower = { - storage_account_name = var.lower_storage_account_name - container_name = var.lower_container_name - resource_group_name = var.lower_resource_group_name - } - } -} - -data "terraform_remote_state" "remote" { - for_each = try(var.landingzone.tfstates, {}) - - backend = var.landingzone.backend_type - config = { - storage_account_name = local.landingzone[try(each.value.level, "current")].storage_account_name - container_name = local.landingzone[try(each.value.level, "current")].container_name - resource_group_name = local.landingzone[try(each.value.level, "current")].resource_group_name - subscription_id = var.tfstate_subscription_id - key = each.value.tfstate - } -} - -locals { - landingzone_tag = { - "landingzone" = var.landingzone.key - } - - tags = merge(local.global_settings.tags, local.landingzone_tag, { "level" = var.landingzone.level }, { "environment" = local.global_settings.environment }, { "rover_version" = var.rover_version }, var.tags) - - global_settings = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.global_settings - - diagnostics = { - diagnostics_definition = merge(data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_definition, var.diagnostics_definition) - diagnostics_destinations = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.diagnostics_destinations - storage_accounts = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.storage_accounts - log_analytics = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.log_analytics - event_hub_namespaces = data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.diagnostics.event_hub_namespaces - } - - remote = { - aks_clusters = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.aks_clusters[key], {})) - } - app_service_environments = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.app_service_environments[key], {})) - } - app_service_plans = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.app_service_plans[key], {})) - } - app_services = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.app_services[key], {})) - } - application_gateway_applications = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.application_gateway_applications[key], {})) - } - application_gateways = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.application_gateways[key], {})) - } - availability_sets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.availability_sets[key], {})) - } - azuread_applications = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_applications[key], {})) - } - azuread_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_groups[key], {})) - } - azuread_users = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azuread_users[key], {})) - } - azurerm_firewalls = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.azurerm_firewalls[key], {})) - } - container_registry = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.container_registry[key], {})) - } - event_hub_namespaces = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.event_hub_namespaces[key], {})) - } - front_door_waf_policies = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.front_door_waf_policies[key], {})) - } - keyvaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.keyvaults[key], {})) - } - managed_identities = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.managed_identities[key], {})) - } - mssql_databases = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.mssql_databases[key], {})) - } - mssql_elastic_pools = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.mssql_elastic_pools[key], {})) - } - mssql_managed_databases = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.mssql_managed_databases[key], {})) - } - mssql_managed_instances = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.mssql_managed_instances[key], {})) - } - mssql_servers = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.mssql_servers[key], {})) - } - mysql_servers = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.mysql_servers[key], {})) - } - network_watchers = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.network_watchers[key], {})) - } - postgresql_servers = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.postgresql_servers[key], {})) - } - private_dns = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.private_dns[key], {})) - } - proximity_placement_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.proximity_placement_groups[key], {})) - } - public_ip_addresses = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.public_ip_addresses[key], {})) - } - recovery_vaults = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.recovery_vaults[key], {})) - } - resource_groups = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.resource_groups[key], {})) - } - storage_accounts = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.storage_accounts[key], {})) - } - synapse_workspaces = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.synapse_workspaces[key], {})) - } - vnets = { - for key, value in try(var.landingzone.tfstates, {}) : key => merge(try(data.terraform_remote_state.remote[key].outputs.vnets[key], {})) - } - } - - combined = { - app_service_environments = merge(local.remote.app_service_environments, tomap({ (var.landingzone.key) = module.caf.app_service_environments })) - app_service_plans = merge(local.remote.app_service_plans, tomap({ (var.landingzone.key) = module.caf.app_service_plans })) - app_services = merge(local.remote.app_services, tomap({ (var.landingzone.key) = module.caf.app_services })) - application_gateway_applications = merge(local.remote.application_gateway_applications, tomap({ (var.landingzone.key) = module.caf.application_gateway_applications })) - application_gateways = merge(local.remote.application_gateways, tomap({ (var.landingzone.key) = module.caf.application_gateways })) - managed_identities = merge(local.remote.managed_identities, tomap({ (var.landingzone.key) = module.caf.managed_identities })) - mssql_elastic_pools = merge(local.remote.mssql_elastic_pools, tomap({ (var.landingzone.key) = module.caf.mssql_elastic_pools })) - mssql_servers = merge(local.remote.mssql_servers, tomap({ (var.landingzone.key) = module.caf.mssql_servers })) - private_dns = merge(local.remote.private_dns, tomap({ (var.landingzone.key) = module.caf.private_dns })) - public_ip_addresses = merge(local.remote.public_ip_addresses, tomap({ (var.landingzone.key) = module.caf.public_ip_addresses })) - vnets = merge(local.remote.vnets, tomap({ (var.landingzone.key) = module.caf.vnets })) - } -} diff --git a/landingzones.old/caf_solutions/main.tf b/landingzones.old/caf_solutions/main.tf deleted file mode 100644 index 7710e1318..000000000 --- a/landingzones.old/caf_solutions/main.tf +++ /dev/null @@ -1,70 +0,0 @@ -terraform { - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 2.43" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 1.0.0" - } - random = { - source = "hashicorp/random" - version = "~> 2.2.1" - } - external = { - source = "hashicorp/external" - version = "~> 1.2.0" - } - null = { - source = "hashicorp/null" - version = "~> 2.1.0" - } - tls = { - source = "hashicorp/tls" - version = "~> 2.2.0" - } - azurecaf = { - source = "aztfmod/azurecaf" - version = "~> 1.2.0" - } - databricks = { - source = "databrickslabs/databricks" - version = "~> 0.2.5" - } - } - required_version = ">= 0.13" -} - - -provider "azurerm" { - features { - key_vault { - purge_soft_delete_on_destroy = true - } - } -} - -data "azurerm_client_config" "current" {} - - -locals { - - # Update the tfstates map - tfstates = merge( - map(var.landingzone.key, - map( - "storage_account_name", var.tfstate_storage_account_name, - "container_name", var.tfstate_container_name, - "resource_group_name", var.tfstate_resource_group_name, - "key", var.tfstate_key, - "level", var.landingzone.level, - "tenant_id", var.tenant_id, - "subscription_id", data.azurerm_client_config.current.subscription_id - ) - ) - , - data.terraform_remote_state.remote[var.landingzone.global_settings_key].outputs.tfstates - ) - -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/modules/databricks/cluster.tf b/landingzones.old/caf_solutions/modules/databricks/cluster.tf deleted file mode 100644 index 3a98fd219..000000000 --- a/landingzones.old/caf_solutions/modules/databricks/cluster.tf +++ /dev/null @@ -1,26 +0,0 @@ -resource "databricks_cluster" "cluster" { - cluster_name = var.settings.name - spark_version = data.databricks_spark_version.version.id - node_type_id = var.settings.node_type_id - autotermination_minutes = try(var.settings.autotermination_minutes, 120) - - dynamic "autoscale" { - for_each = try(var.settings.autoscale, null) == null ? [] : [1] - - content { - min_workers = try(var.settings.autoscale.min_workers, null) - max_workers = try(var.settings.autoscale.max_workers, null) - } - } - -} - -data "databricks_spark_version" "version" { - latest = try(var.settings.spark_version.latest, true) - long_term_support = try(var.settings.spark_version.long_term_support, false) - ml = try(var.settings.spark_version.ml, false) - genomics = try(var.settings.spark_version.mlgenomics, false) - gpu = try(var.settings.spark_version.gpu, false) - scala = try(var.settings.spark_version.scala, "2.12") - spark_version = try(var.settings.spark_version.spark_version, "3.0") -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/modules/databricks/instance_pool.tf b/landingzones.old/caf_solutions/modules/databricks/instance_pool.tf deleted file mode 100644 index e69de29bb..000000000 diff --git a/landingzones.old/caf_solutions/modules/databricks/main.tf b/landingzones.old/caf_solutions/modules/databricks/main.tf deleted file mode 100644 index 8993136bd..000000000 --- a/landingzones.old/caf_solutions/modules/databricks/main.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_providers { - databricks = { - source = "databrickslabs/databricks" - } - } - required_version = ">= 0.13" -} - diff --git a/landingzones.old/caf_solutions/modules/databricks/output.tf b/landingzones.old/caf_solutions/modules/databricks/output.tf deleted file mode 100644 index 5ac9d541c..000000000 --- a/landingzones.old/caf_solutions/modules/databricks/output.tf +++ /dev/null @@ -1,9 +0,0 @@ -output "cluster" { - value = { - id = databricks_cluster.cluster.id - default_tags = databricks_cluster.cluster.default_tags - state = databricks_cluster.cluster.state - spark_version = databricks_cluster.cluster.spark_version - - } -} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/modules/databricks/variables.tf b/landingzones.old/caf_solutions/modules/databricks/variables.tf deleted file mode 100644 index 719f36726..000000000 --- a/landingzones.old/caf_solutions/modules/databricks/variables.tf +++ /dev/null @@ -1,4 +0,0 @@ -variable "azure_workspace_resource_id" { - default = {} -} -variable "settings" {} \ No newline at end of file diff --git a/landingzones.old/caf_solutions/output.tf b/landingzones.old/caf_solutions/output.tf deleted file mode 100644 index adac00b3c..000000000 --- a/landingzones.old/caf_solutions/output.tf +++ /dev/null @@ -1,114 +0,0 @@ -#Core outputs -output "diagnostics" { - value = local.diagnostics - sensitive = true -} - -output "tfstates" { - value = local.tfstates - sensitive = true -} - -output "global_settings" { - value = local.global_settings - sensitive = true -} - -# ASE -output "app_service_environments" { - value = local.combined.app_service_environments - sensitive = true -} - -output "app_service_plans" { - value = local.combined.app_service_plans - sensitive = true -} - -output "app_services" { - value = local.combined.app_services - sensitive = true -} - -# DB -output "mssql_servers" { - value = local.combined.mssql_servers - sensitive = true -} - -output "mssql_elastic_pools" { - value = local.combined.mssql_elastic_pools - sensitive = true -} - -output "redis_caches" { - value = module.caf.redis_caches - sensitive = true -} - -output "managed_identities" { - value = local.combined.managed_identities - sensitive = true -} - -output "keyvaults" { - value = tomap({ (var.landingzone.key) = module.caf.keyvaults }) - sensitive = true -} - -# App Gateways -output "application_gateways" { - value = local.combined.application_gateways - sensitive = true -} - -output "application_gateway_applications" { - value = local.combined.application_gateway_applications - sensitive = true -} - -# DNS -output "private_dns" { - value = local.combined.private_dns - sensitive = true -} - -# Kubernetes related outputs -output "aks_clusters_kubeconfig" { - value = { - for key, aks_cluster in module.caf.aks_clusters : key => { - aks_kubeconfig_cmd = aks_cluster.aks_kubeconfig_cmd - aks_kubeconfig_admin_cmd = aks_cluster.aks_kubeconfig_admin_cmd - } - } - sensitive = false -} - -output "aks_clusters" { - value = tomap({ (var.landingzone.key) = module.caf.aks_clusters }) - sensitive = true -} - -output "virtual_machines" { - value = module.caf.virtual_machines - sensitive = false -} - -# Data and AI outputs -output "databricks_workspaces" { - value = tomap({ (var.landingzone.key) = module.caf.databricks_workspaces }) - sensitive = true -} - -output "machine_learning_workspaces" { - value = tomap({ (var.landingzone.key) = module.caf.machine_learning_workspaces }) - sensitive = true -} - -output "synapse_workspaces" { - value = tomap({ (var.landingzone.key) = module.caf.synapse_workspaces }) - sensitive = true -} - - - diff --git a/landingzones.old/caf_solutions/readme.md b/landingzones.old/caf_solutions/readme.md deleted file mode 100644 index 48f6c0333..000000000 --- a/landingzones.old/caf_solutions/readme.md +++ /dev/null @@ -1,22 +0,0 @@ -# Cloud Adoption Framework for Azure - Landing zones on Terraform - Solutions - -The landing zones solutions provide the underlying infrastructure to support your applications. The following are solutions accelerator ready to be deployed into your environment. They would require some review to match your operating model. - -* App Services (including App Service Environment) -* Azure Kubernetes Service (AKS) -* Azure Databricks -* Azure SQL Database -* Azure Application Gateway -* Azure Redis Cache -* Azure Keyvault -* Azure Virtual Machine -* Azure Machine Learning -* Azure Synapse - -Solutions landing zone operates at **level 3**. - -For a review of the hierarchy approach of Cloud Adoption Framework for Azure landing zones on Terraform, you can refer to [the following documentation](../../documentation/code_architecture/hierarchy.md). - -## Deploying solutions - -Solution examples are available in the CAF Landing zones Starter repo: https://github.com/Azure/caf-terraform-landingzones-starter diff --git a/landingzones.old/caf_solutions/scripts/cloud-init-install-rover-tools.config b/landingzones.old/caf_solutions/scripts/cloud-init-install-rover-tools.config deleted file mode 100644 index 29b30cbec..000000000 --- a/landingzones.old/caf_solutions/scripts/cloud-init-install-rover-tools.config +++ /dev/null @@ -1,119 +0,0 @@ -#cloud-config -apt: - preserve_sources_list: true - sources: - azure-cli.list: - source: "deb https://packages.microsoft.com/repos/azure-cli/ bionic main" - key: | - -----BEGIN PGP PUBLIC KEY BLOCK----- - Version: GnuPG v1.4.7 (GNU/Linux) - - mQENBFYxWIwBCADAKoZhZlJxGNGWzqV+1OG1xiQeoowKhssGAKvd+buXCGISZJwT - LXZqIcIiLP7pqdcZWtE9bSc7yBY2MalDp9Liu0KekywQ6VVX1T72NPf5Ev6x6DLV - 7aVWsCzUAF+eb7DC9fPuFLEdxmOEYoPjzrQ7cCnSV4JQxAqhU4T6OjbvRazGl3ag - OeizPXmRljMtUUttHQZnRhtlzkmwIrUivbfFPD+fEoHJ1+uIdfOzZX8/oKHKLe2j - H632kvsNzJFlROVvGLYAk2WRcLu+RjjggixhwiB+Mu/A8Tf4V6b+YppS44q8EvVr - M+QvY7LNSOffSO6Slsy9oisGTdfE39nC7pVRABEBAAG0N01pY3Jvc29mdCAoUmVs - ZWFzZSBzaWduaW5nKSA8Z3Bnc2VjdXJpdHlAbWljcm9zb2Z0LmNvbT6JATUEEwEC - AB8FAlYxWIwCGwMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJEOs+lK2+EinPGpsH - /32vKy29Hg51H9dfFJMx0/a/F+5vKeCeVqimvyTM04C+XENNuSbYZ3eRPHGHFLqe - MNGxsfb7C7ZxEeW7J/vSzRgHxm7ZvESisUYRFq2sgkJ+HFERNrqfci45bdhmrUsy - 7SWw9ybxdFOkuQoyKD3tBmiGfONQMlBaOMWdAsic965rvJsd5zYaZZFI1UwTkFXV - KJt3bp3Ngn1vEYXwijGTa+FXz6GLHueJwF0I7ug34DgUkAFvAs8Hacr2DRYxL5RJ - XdNgj4Jd2/g6T9InmWT0hASljur+dJnzNiNCkbn9KbX7J/qK1IbR8y560yRmFsU+ - NdCFTW7wY0Fb1fWJ+/KTsC4= - =J6gs - -----END PGP PUBLIC KEY BLOCK----- - docker.list: - source: "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" - key: | - -----BEGIN PGP PUBLIC KEY BLOCK----- - - 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 - YT90qFF93M3v01BbxP+EIY2/9tiIPbrd - =0YYh - -----END PGP PUBLIC KEY BLOCK----- -package_update: true - -packages: - - docker-ce - - azure-cli - - ca-certificates - - curl - - apt-transport-https - - lsb-release - - jq - - helm - -snap: - commands: - - snap install kubectl --classic - - snap install helm --classic - -apt_upgrade: true - - # Install docker-compose -runcmd: - - [ sh, -c, 'curl -L https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep "tag_name" | cut -d \" -f4)/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose' ] - - [ sh, -c, 'sudo chmod +x /usr/local/bin/docker-compose' ] - -# Add default auto created user to docker group -system_info: - default_user: - groups: [docker] \ No newline at end of file diff --git a/landingzones.old/caf_solutions/variables.tf b/landingzones.old/caf_solutions/variables.tf deleted file mode 100644 index cfafad2d5..000000000 --- a/landingzones.old/caf_solutions/variables.tf +++ /dev/null @@ -1,272 +0,0 @@ -# Map of the remote data state for lower level -variable "lower_storage_account_name" {} -variable "lower_container_name" {} -variable "lower_resource_group_name" {} - -variable "tfstate_subscription_id" { - description = "This value is propulated by the rover. subscription id hosting the remote tfstates" -} -variable "tfstate_storage_account_name" {} -variable "tfstate_container_name" {} -variable "tfstate_key" {} -variable "tfstate_resource_group_name" {} - -variable "landingzone" {} -variable "tenant_id" {} - -variable "global_settings" { - default = {} -} -variable "rover_version" { - default = null -} -variable "logged_user_objectId" { - default = null -} -variable "logged_aad_app_objectId" { - default = null -} -variable "tags" { - type = map(any) - default = {} -} -variable "resource_groups" { - default = {} -} -variable "azurerm_redis_caches" { - default = {} -} -variable "mssql_servers" { - default = {} -} -variable "mssql_databases" { - default = {} -} -variable "mssql_elastic_pools" { - default = {} -} -variable "storage_accounts" { - default = {} -} -variable "azuread_groups" { - default = {} -} -variable "keyvaults" { - default = {} -} -variable "keyvault_access_policies" { - default = {} -} -variable "keyvault_certificates" { - default = {} -} -variable "managed_identities" { - default = {} -} -variable "azurerm_application_insights" { - default = {} -} -variable "role_mapping" { - default = {} -} -variable "custom_role_definitions" { - default = {} -} -variable "dynamic_keyvault_secrets" { - default = {} -} -variable "app_service_environments" { - default = {} -} -variable "app_service_plans" { - default = {} -} -variable "app_services" { - default = {} -} -variable "diagnostics_definition" { - default = null -} -variable "network_security_group_definition" { - default = null -} -variable "route_tables" { - default = {} -} -variable "azurerm_routes" { - default = {} -} -variable "vnets" { - default = {} -} -variable "mssql_managed_instances" { - default = {} -} -variable "mssql_managed_instances_secondary" { - default = {} -} - -variable "mssql_managed_databases" { - default = {} -} -variable "mssql_managed_databases_restore" { - default = {} -} - -variable "mariadb_servers" { - default = {} -} -variable "mariadb_databases" { - default = {} -} -variable "mssql_failover_groups" { - default = {} -} -variable "mssql_mi_failover_groups" { - default = {} -} -variable "mssql_mi_administrators" { - default = {} -} -variable "azuread_roles" { - default = {} -} -variable "keyvault_certificate_issuers" { - default = {} -} -variable "keyvault_certificate_requests" { - default = {} -} -variable "virtual_machines" { - default = {} -} -variable "bastion_hosts" { - default = {} -} -variable "public_ip_addresses" { - default = {} -} -variable "diagnostic_storage_accounts" { - default = {} -} -variable "diagnostic_event_hub_namespaces" { - default = {} -} -variable "diagnostic_log_analytics" { - default = {} -} -variable "private_dns" { - default = {} -} -variable "synapse_workspaces" { - default = {} -} -variable "aks_clusters" { - default = {} -} -variable "databricks_workspaces" { - default = {} -} -variable "machine_learning_workspaces" { - default = {} -} -variable "monitoring" { - default = {} -} -variable "virtual_wans" { - default = {} -} -variable "event_hub_namespaces" { - default = {} -} -variable "application_gateways" { - default = {} -} -variable "application_gateway_applications" { - default = {} -} -variable "mysql_servers" { - default = {} -} -variable "postgresql_servers" { - default = {} -} -variable "cosmos_db" { - default = {} -} -variable "log_analytics" { - default = {} -} -variable "recovery_vaults" { - default = {} -} -variable "availability_sets" { - default = {} -} -variable "proximity_placement_groups" { - default = {} -} -variable "network_watchers" { - default = {} -} -variable "virtual_network_gateways" { - default = {} -} -variable "virtual_network_gateway_connections" { - default = {} -} -variable "express_route_circuits" { - default = {} -} -variable "express_route_circuit_authorizations" { - default = {} -} -variable "diagnostics_destinations" { - default = {} -} -variable "vnet_peerings" { - default = {} -} -variable "cosmos_dbs" { - default = {} -} -variable "front_doors" { - default = {} -} -variable "front_door_waf_policies" { - default = {} -} -variable "dns_zones" { - default = {} -} -variable "private_endpoints" { - default = {} -} -variable "local_network_gateways" { - default = {} -} -variable "azure_container_registries" { - default = {} -} -variable "azuread_api_permissions" { - default = {} -} -variable "azuread_apps" { - default = {} -} -variable "azuread_users" { - default = {} -} -variable "user_type" {} -variable "domain_name_registrations" { - default = {} -} -variable "dns_zone_records" { - default = {} -} -variable "keyvault_keys" { - default = {} -} -variable "load_balancers" { - default = {} -} \ No newline at end of file From a51cc3f02880f4507fafcc2ed8e70893ea2e9ff2 Mon Sep 17 00:00:00 2001 From: Arnaud Lheureux Date: Thu, 8 Apr 2021 23:44:52 +0000 Subject: [PATCH 35/38] Update level200 samples --- .../networking/200-single-region-hub/configuration.tfvars | 8 ++++---- .../networking/201-multi-region-hub/configuration.tfvars | 8 ++++---- .../networking/210-aks-private/configuration.tfvars | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars index 4b1e28f4b..4b2c7b19f 100644 --- a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars @@ -75,8 +75,8 @@ vnet_peerings = { vnet_key = "hub_rg1" } to = { - tfstate_key = "foundations" - lz_key = "launchpad" + tfstate_key = "caf_foundations" + lz_key = "caf_foundations" output_key = "vnets" vnet_key = "devops_region1" } @@ -90,8 +90,8 @@ vnet_peerings = { launchpad_devops-TO-hub_rg1 = { name = "launchpad_devops-TO-hub_rg1" from = { - tfstate_key = "foundations" - lz_key = "launchpad" + tfstate_key = "caf_foundations" + lz_key = "caf_foundations" output_key = "vnets" vnet_key = "devops_region1" } diff --git a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars index 434bb720c..03812f573 100644 --- a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars @@ -154,8 +154,8 @@ vnet_peerings = { vnet_key = "hub_rg1" } to = { - tfstate_key = "foundations" - lz_key = "launchpad" + tfstate_key = "caf_foundations" + lz_key = "caf_foundations" output_key = "vnets" vnet_key = "devops_region1" } @@ -169,8 +169,8 @@ vnet_peerings = { launchpad_devops-TO-hub_rg1 = { name = "launchpad_devops-TO-hub_rg1" from = { - tfstate_key = "foundations" - lz_key = "launchpad" + tfstate_key = "caf_foundations" + lz_key = "caf_foundations" output_key = "vnets" vnet_key = "devops_region1" } diff --git a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars index 140f47831..286db0a27 100644 --- a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars +++ b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars @@ -90,7 +90,7 @@ vnet_peerings = { vnet_key = "hub_rg1" } to = { - lz_key = "launchpad" + lz_key = "caf_foundations" output_key = "vnets" vnet_key = "devops_region1" } From 587dc0d962c7f7a985e828d9f400076ee2ecda52 Mon Sep 17 00:00:00 2001 From: lolorol Date: Fri, 9 Apr 2021 09:10:07 +0800 Subject: [PATCH 36/38] Delete .terraform.lock.hcl --- caf_launchpad/.terraform.lock.hcl | 72 ------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 caf_launchpad/.terraform.lock.hcl diff --git a/caf_launchpad/.terraform.lock.hcl b/caf_launchpad/.terraform.lock.hcl deleted file mode 100644 index bc50f2e74..000000000 --- a/caf_launchpad/.terraform.lock.hcl +++ /dev/null @@ -1,72 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/aztfmod/azurecaf" { - version = "1.2.2" - constraints = "~> 1.2.0" - hashes = [ - "h1:5GMOMtQg1/i6yigQ++Nol/lno2D67D5LhO3/VLPMq9A=", - ] -} - -provider "registry.terraform.io/hashicorp/azuread" { - version = "1.4.0" - constraints = "~> 1.4.0" - hashes = [ - "h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=", - ] -} - -provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.52.0" - constraints = "~> 2.50, ~> 2.52.0" - hashes = [ - "h1:bYwfAgIZFgbGVGYjnZ0OO+RumXn6UDNl2VmIm5gi8tI=", - ] -} - -provider "registry.terraform.io/hashicorp/external" { - version = "1.2.0" - constraints = "~> 1.2.0" - hashes = [ - "h1:wDfbBn+171g9/+aWqkicrN5l1S3kuqEX4J1zyPCDsoY=", - ] -} - -provider "registry.terraform.io/hashicorp/null" { - version = "2.1.2" - constraints = "~> 2.1.0" - hashes = [ - "h1:CFnENdqQu4g3LJNevA32aDxcUz2qGkRGQpFfkI8TCdE=", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "2.2.1" - constraints = "~> 2.2.1" - hashes = [ - "h1:Zg1Bpi6vr7b0H6no8kVDfEucn5pvNALivdrVKVHarGs=", - ] -} - -provider "registry.terraform.io/hashicorp/template" { - version = "2.2.0" - hashes = [ - "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", - ] -} - -provider "registry.terraform.io/hashicorp/time" { - version = "0.7.0" - hashes = [ - "h1:1VPBq+jeoCf0wVCxnzK6BNnOmNbXf3fRnDmS43Jw7Oo=", - ] -} - -provider "registry.terraform.io/hashicorp/tls" { - version = "2.2.0" - constraints = "~> 2.2.0" - hashes = [ - "h1:BRvNNW/32RAFXRcEAovtJWVbFt8zesIKkQm2N0GBCn8=", - ] -} From 8a70a131c444c31c17d41986072060476d362aaf Mon Sep 17 00:00:00 2001 From: Arnaud Lheureux Date: Fri, 9 Apr 2021 03:11:06 +0000 Subject: [PATCH 37/38] Refactoring level 1 gitops --- .github/workflows/landingzones-tf13.yml | 6 +- .github/workflows/landingzones-tf14.yml | 12 +--- .github/workflows/landingzones-tf15.yml | 6 +- .gitignore | 2 +- caf_launchpad/.terraform.lock.hcl | 72 ------------------- .../scenario/200/configuration.tfvars | 6 -- caf_launchpad/scenario/200/iam_azuread.tfvars | 2 +- .../scenario/200/iam_keyvault_policies.tfvars | 19 ----- .../scenario/200/iam_role_mapping.tfvars | 7 -- caf_launchpad/scenario/200/keyvaults.tfvars | 31 -------- .../foundations/gitops}/compute.tfvars | 13 ++-- .../gitops/iam_keyvault_policies.tfvars | 25 +++++++ .../gitops/iam_role_mapping.tfvars | 19 +++++ .../foundations/gitops/keyvaults.tfvars | 34 +++++++++ .../foundations/gitops/landingzone.tfvars | 21 ++++++ .../foundations/gitops}/networking.tfvars | 0 .../gitops}/networking_nsg_definition.tfvars | 0 .../configuration.tfvars | 12 ++-- .../201-multi-region-hub/configuration.tfvars | 18 ++--- .../210-aks-private/configuration.tfvars | 8 +-- 20 files changed, 133 insertions(+), 180 deletions(-) delete mode 100644 caf_launchpad/.terraform.lock.hcl rename {caf_launchpad/scenario/200 => caf_solution/scenario/foundations/gitops}/compute.tfvars (91%) create mode 100644 caf_solution/scenario/foundations/gitops/iam_keyvault_policies.tfvars create mode 100644 caf_solution/scenario/foundations/gitops/iam_role_mapping.tfvars create mode 100644 caf_solution/scenario/foundations/gitops/keyvaults.tfvars create mode 100644 caf_solution/scenario/foundations/gitops/landingzone.tfvars rename {caf_launchpad/scenario/200 => caf_solution/scenario/foundations/gitops}/networking.tfvars (100%) rename {caf_launchpad/scenario/200 => caf_solution/scenario/foundations/gitops}/networking_nsg_definition.tfvars (100%) diff --git a/.github/workflows/landingzones-tf13.yml b/.github/workflows/landingzones-tf13.yml index fddcc5d97..da21482ee 100644 --- a/.github/workflows/landingzones-tf13.yml +++ b/.github/workflows/landingzones-tf13.yml @@ -58,7 +58,7 @@ jobs: - name: foundations run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ @@ -154,7 +154,7 @@ jobs: - name: foundations-200-upgrade run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ @@ -236,7 +236,7 @@ jobs: - name: foundations run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a destroy \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ diff --git a/.github/workflows/landingzones-tf14.yml b/.github/workflows/landingzones-tf14.yml index a30f60f08..539aeafb0 100644 --- a/.github/workflows/landingzones-tf14.yml +++ b/.github/workflows/landingzones-tf14.yml @@ -12,12 +12,6 @@ on: - '_pictures/**' - 'README.md' - 'CHANGELOG.md' - push: - paths-ignore: - - 'documentation/**' - - '_pictures/**' - - 'README.md' - - 'CHANGELOG.md' schedule: - cron: '0 0 * * *' @@ -70,7 +64,7 @@ jobs: - name: foundations run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ @@ -166,7 +160,7 @@ jobs: - name: foundations-200-upgrade run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ @@ -248,7 +242,7 @@ jobs: - name: foundations run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a destroy \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ diff --git a/.github/workflows/landingzones-tf15.yml b/.github/workflows/landingzones-tf15.yml index e7a17f928..d5fa64fea 100644 --- a/.github/workflows/landingzones-tf15.yml +++ b/.github/workflows/landingzones-tf15.yml @@ -58,7 +58,7 @@ jobs: - name: foundations run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ @@ -154,7 +154,7 @@ jobs: - name: foundations-200-upgrade run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ @@ -236,7 +236,7 @@ jobs: - name: foundations run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a destroy \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ diff --git a/.gitignore b/.gitignore index 9b5e12b23..a043b16a3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,9 @@ **/terraform.tfstate.d **/terraform.tfstate.backup **/.terraform.tfstate.lock.info +**/.terraform.lock.hcl **/~*.* **/*.log **/backend.azurerm.tf public -**/.terraform.lock.hcl aztfmod \ No newline at end of file diff --git a/caf_launchpad/.terraform.lock.hcl b/caf_launchpad/.terraform.lock.hcl deleted file mode 100644 index bc50f2e74..000000000 --- a/caf_launchpad/.terraform.lock.hcl +++ /dev/null @@ -1,72 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/aztfmod/azurecaf" { - version = "1.2.2" - constraints = "~> 1.2.0" - hashes = [ - "h1:5GMOMtQg1/i6yigQ++Nol/lno2D67D5LhO3/VLPMq9A=", - ] -} - -provider "registry.terraform.io/hashicorp/azuread" { - version = "1.4.0" - constraints = "~> 1.4.0" - hashes = [ - "h1:lDsKRxDRXPEzA4AxkK4t+lJd3IQIP2UoaplJGjQSp2s=", - ] -} - -provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.52.0" - constraints = "~> 2.50, ~> 2.52.0" - hashes = [ - "h1:bYwfAgIZFgbGVGYjnZ0OO+RumXn6UDNl2VmIm5gi8tI=", - ] -} - -provider "registry.terraform.io/hashicorp/external" { - version = "1.2.0" - constraints = "~> 1.2.0" - hashes = [ - "h1:wDfbBn+171g9/+aWqkicrN5l1S3kuqEX4J1zyPCDsoY=", - ] -} - -provider "registry.terraform.io/hashicorp/null" { - version = "2.1.2" - constraints = "~> 2.1.0" - hashes = [ - "h1:CFnENdqQu4g3LJNevA32aDxcUz2qGkRGQpFfkI8TCdE=", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "2.2.1" - constraints = "~> 2.2.1" - hashes = [ - "h1:Zg1Bpi6vr7b0H6no8kVDfEucn5pvNALivdrVKVHarGs=", - ] -} - -provider "registry.terraform.io/hashicorp/template" { - version = "2.2.0" - hashes = [ - "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", - ] -} - -provider "registry.terraform.io/hashicorp/time" { - version = "0.7.0" - hashes = [ - "h1:1VPBq+jeoCf0wVCxnzK6BNnOmNbXf3fRnDmS43Jw7Oo=", - ] -} - -provider "registry.terraform.io/hashicorp/tls" { - version = "2.2.0" - constraints = "~> 2.2.0" - hashes = [ - "h1:BRvNNW/32RAFXRcEAovtJWVbFt8zesIKkQm2N0GBCn8=", - ] -} diff --git a/caf_launchpad/scenario/200/configuration.tfvars b/caf_launchpad/scenario/200/configuration.tfvars index 36645019e..cbd14725f 100644 --- a/caf_launchpad/scenario/200/configuration.tfvars +++ b/caf_launchpad/scenario/200/configuration.tfvars @@ -84,17 +84,11 @@ resource_groups = { security = { name = "launchpad-security" } - networking = { - name = "launchpad-networking" - } ops = { name = "operations" } siem = { name = "siem-logs" } - bastion_launchpad = { - name = "launchpad-bastion" - } } diff --git a/caf_launchpad/scenario/200/iam_azuread.tfvars b/caf_launchpad/scenario/200/iam_azuread.tfvars index 4a4856f72..9c7bedc6a 100644 --- a/caf_launchpad/scenario/200/iam_azuread.tfvars +++ b/caf_launchpad/scenario/200/iam_azuread.tfvars @@ -115,7 +115,7 @@ azuread_users = { password_expire_in_days = 180 # Value must match with var.keyvaults[keyname] to store username and password for password rotation - keyvault_key = "secrets" + keyvault_key = "level0" } } diff --git a/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars b/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars index e755b1ebd..368bc00c7 100644 --- a/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars +++ b/caf_launchpad/scenario/200/iam_keyvault_policies.tfvars @@ -43,14 +43,6 @@ keyvault_access_policies_azuread_apps = { secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] } } - - - secrets = { - caf_launchpad_level0 = { - azuread_app_key = "caf_launchpad_level0" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } } keyvault_access_policies = { @@ -100,15 +92,4 @@ keyvault_access_policies = { } } - - secrets = { - keyvault_level0_rw = { - azuread_group_key = "keyvault_level0_rw" - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - keyvault_password_rotation = { - azuread_group_key = "keyvault_password_rotation" - secret_permissions = ["Set", "Get", "List", "Delete", ] - } - } } diff --git a/caf_launchpad/scenario/200/iam_role_mapping.tfvars b/caf_launchpad/scenario/200/iam_role_mapping.tfvars index 23a919f2a..263e940a4 100644 --- a/caf_launchpad/scenario/200/iam_role_mapping.tfvars +++ b/caf_launchpad/scenario/200/iam_role_mapping.tfvars @@ -50,13 +50,6 @@ role_mapping = { } } } - networking = { - "Reader" = { - azuread_groups = { - keys = ["caf_launchpad_Reader"] - } - } - } ops = { "Reader" = { azuread_groups = { diff --git a/caf_launchpad/scenario/200/keyvaults.tfvars b/caf_launchpad/scenario/200/keyvaults.tfvars index 9b407a31d..91ed6deb8 100644 --- a/caf_launchpad/scenario/200/keyvaults.tfvars +++ b/caf_launchpad/scenario/200/keyvaults.tfvars @@ -170,35 +170,4 @@ keyvaults = { } - secrets = { - name = "secrets" - resource_group_key = "security" - region = "region1" - sku_name = "premium" - soft_delete_enabled = true - - # you can setup up to 5 profiles - diagnostic_profiles = { - operations = { - definition_key = "default_all" - destination_type = "log_analytics" - destination_key = "central_logs" - } - siem = { - definition_key = "siem_all" - destination_type = "storage" - destination_key = "all_regions" - } - } - - creation_policies = { - logged_in_user = { - # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy - # More examples in /examples/keyvault - secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] - } - } - - - } } diff --git a/caf_launchpad/scenario/200/compute.tfvars b/caf_solution/scenario/foundations/gitops/compute.tfvars similarity index 91% rename from caf_launchpad/scenario/200/compute.tfvars rename to caf_solution/scenario/foundations/gitops/compute.tfvars index 88164c5a4..5c7d99238 100644 --- a/caf_launchpad/scenario/200/compute.tfvars +++ b/caf_solution/scenario/foundations/gitops/compute.tfvars @@ -85,12 +85,13 @@ virtual_machines = { version = "latest" } - identity = { - type = "UserAssigned" - managed_identity_keys = [ - "level0", "level1", "level2", "level3", "level4" - ] - } + # identity = { + # type = "UserAssigned" + # lz_key = "launchpad" + # managed_identity_keys = [ + # "level0", "level1", "level2", "level3", "level4" + # ] + # } } } diff --git a/caf_solution/scenario/foundations/gitops/iam_keyvault_policies.tfvars b/caf_solution/scenario/foundations/gitops/iam_keyvault_policies.tfvars new file mode 100644 index 000000000..d4b3bedfb --- /dev/null +++ b/caf_solution/scenario/foundations/gitops/iam_keyvault_policies.tfvars @@ -0,0 +1,25 @@ +keyvault_access_policies_azuread_apps = { + + secrets = { + caf_launchpad_level0 = { + lz_key = "launchpad" + azuread_app_key = "caf_launchpad_level0" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } +} + +keyvault_access_policies = { + secrets = { + keyvault_level0_rw = { + lz_key = "launchpad" + azuread_group_key = "keyvault_level0_rw" + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + keyvault_password_rotation = { + lz_key = "launchpad" + azuread_group_key = "keyvault_password_rotation" + secret_permissions = ["Set", "Get", "List", "Delete", ] + } + } +} diff --git a/caf_solution/scenario/foundations/gitops/iam_role_mapping.tfvars b/caf_solution/scenario/foundations/gitops/iam_role_mapping.tfvars new file mode 100644 index 000000000..0503053df --- /dev/null +++ b/caf_solution/scenario/foundations/gitops/iam_role_mapping.tfvars @@ -0,0 +1,19 @@ + +# +# Services supported: subscriptions, storage accounts and resource groups +# Can assign roles to: AD groups, AD object ID, AD applications, Managed identities +# +role_mapping = { + built_in_role_mapping = { + resource_groups = { + networking = { + "Reader" = { + azuread_groups = { + lz_key = "launchpad" + keys = ["caf_launchpad_Reader"] + } + } + } + } + } +} diff --git a/caf_solution/scenario/foundations/gitops/keyvaults.tfvars b/caf_solution/scenario/foundations/gitops/keyvaults.tfvars new file mode 100644 index 000000000..a829929ce --- /dev/null +++ b/caf_solution/scenario/foundations/gitops/keyvaults.tfvars @@ -0,0 +1,34 @@ + +keyvaults = { + secrets = { + name = "secrets" + resource_group_key = "bastion_launchpad" + region = "region1" + sku_name = "premium" + soft_delete_enabled = true + + # you can setup up to 5 profiles + diagnostic_profiles = { + operations = { + definition_key = "default_all" + destination_type = "log_analytics" + destination_key = "central_logs" + } + siem = { + definition_key = "siem_all" + destination_type = "storage" + destination_key = "all_regions" + } + } + + creation_policies = { + logged_in_user = { + # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy + # More examples in /examples/keyvault + secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"] + } + } + + + } +} diff --git a/caf_solution/scenario/foundations/gitops/landingzone.tfvars b/caf_solution/scenario/foundations/gitops/landingzone.tfvars new file mode 100644 index 000000000..6aed75e5b --- /dev/null +++ b/caf_solution/scenario/foundations/gitops/landingzone.tfvars @@ -0,0 +1,21 @@ +landingzone = { + backend_type = "azurerm" + global_settings_key = "launchpad" + level = "level1" + key = "caf_gitops" + tfstates = { + launchpad = { + level = "lower" + tfstate = "caf_launchpad.tfstate" + } + } +} + +resource_groups = { + networking = { + name = "launchpad-networking" + } + bastion_launchpad = { + name = "launchpad-bastion" + } +} \ No newline at end of file diff --git a/caf_launchpad/scenario/200/networking.tfvars b/caf_solution/scenario/foundations/gitops/networking.tfvars similarity index 100% rename from caf_launchpad/scenario/200/networking.tfvars rename to caf_solution/scenario/foundations/gitops/networking.tfvars diff --git a/caf_launchpad/scenario/200/networking_nsg_definition.tfvars b/caf_solution/scenario/foundations/gitops/networking_nsg_definition.tfvars similarity index 100% rename from caf_launchpad/scenario/200/networking_nsg_definition.tfvars rename to caf_solution/scenario/foundations/gitops/networking_nsg_definition.tfvars diff --git a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars index 4b2c7b19f..123acb26e 100644 --- a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars @@ -1,12 +1,12 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "caf_foundations" + global_settings_key = "caf_gitops" level = "level2" key = "networking_hub" tfstates = { - caf_foundations = { + caf_gitops = { level = "lower" - tfstate = "caf_foundations.tfstate" + tfstate = "caf_gitops.tfstate" } } } @@ -75,8 +75,7 @@ vnet_peerings = { vnet_key = "hub_rg1" } to = { - tfstate_key = "caf_foundations" - lz_key = "caf_foundations" + lz_key = "caf_gitops" output_key = "vnets" vnet_key = "devops_region1" } @@ -90,8 +89,7 @@ vnet_peerings = { launchpad_devops-TO-hub_rg1 = { name = "launchpad_devops-TO-hub_rg1" from = { - tfstate_key = "caf_foundations" - lz_key = "caf_foundations" + lz_key = "caf_gitops" output_key = "vnets" vnet_key = "devops_region1" } diff --git a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars index 03812f573..b2895e82b 100644 --- a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars @@ -1,12 +1,12 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "caf_foundations" + global_settings_key = "caf_gitops" level = "level2" key = "networking_hub" tfstates = { - caf_foundations = { + caf_gitops = { level = "lower" - tfstate = "caf_foundations.tfstate" + tfstate = "caf_gitops.tfstate" } } } @@ -154,8 +154,7 @@ vnet_peerings = { vnet_key = "hub_rg1" } to = { - tfstate_key = "caf_foundations" - lz_key = "caf_foundations" + lz_key = "caf_gitops" output_key = "vnets" vnet_key = "devops_region1" } @@ -169,8 +168,7 @@ vnet_peerings = { launchpad_devops-TO-hub_rg1 = { name = "launchpad_devops-TO-hub_rg1" from = { - tfstate_key = "caf_foundations" - lz_key = "caf_foundations" + lz_key = "caf_gitops" output_key = "vnets" vnet_key = "devops_region1" } @@ -191,8 +189,7 @@ vnet_peerings = { vnet_key = "hub_rg2" } to = { - tfstate_key = "foundations" - lz_key = "launchpad" + lz_key = "caf_gitops" output_key = "vnets" vnet_key = "devops_region1" } @@ -206,8 +203,7 @@ vnet_peerings = { launchpad_devops-TO-hub_rg2 = { name = "launchpad_devops-TO-hub_rg2" from = { - tfstate_key = "foundations" - lz_key = "launchpad" + lz_key = "caf_gitops" output_key = "vnets" vnet_key = "devops_region1" } diff --git a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars index 286db0a27..20d78390f 100644 --- a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars +++ b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars @@ -1,12 +1,12 @@ landingzone = { backend_type = "azurerm" - global_settings_key = "caf_foundations" + global_settings_key = "caf_gitops" level = "level2" key = "networking_hub" tfstates = { - caf_foundations = { + caf_gitops = { level = "lower" - tfstate = "caf_foundations.tfstate" + tfstate = "caf_gitops.tfstate" } } } @@ -90,7 +90,7 @@ vnet_peerings = { vnet_key = "hub_rg1" } to = { - lz_key = "caf_foundations" + lz_key = "caf_gitops" output_key = "vnets" vnet_key = "devops_region1" } From 6620ea90a34148055fa7c97072187c42682fa569 Mon Sep 17 00:00:00 2001 From: Arnaud Lheureux Date: Fri, 9 Apr 2021 03:30:12 +0000 Subject: [PATCH 38/38] Pipelines updates --- .github/workflows/landingzones-tf13.yml | 2 +- .github/workflows/landingzones-tf14.yml | 2 +- .github/workflows/landingzones-tf15.yml | 2 +- .../networking/200-single-region-hub/configuration.tfvars | 2 +- .../networking/201-multi-region-hub/configuration.tfvars | 2 +- .../scenario/networking/210-aks-private/configuration.tfvars | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/landingzones-tf13.yml b/.github/workflows/landingzones-tf13.yml index da21482ee..12782b4b9 100644 --- a/.github/workflows/landingzones-tf13.yml +++ b/.github/workflows/landingzones-tf13.yml @@ -58,7 +58,7 @@ jobs: - name: foundations run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ diff --git a/.github/workflows/landingzones-tf14.yml b/.github/workflows/landingzones-tf14.yml index 539aeafb0..b32386bfd 100644 --- a/.github/workflows/landingzones-tf14.yml +++ b/.github/workflows/landingzones-tf14.yml @@ -64,7 +64,7 @@ jobs: - name: foundations run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ diff --git a/.github/workflows/landingzones-tf15.yml b/.github/workflows/landingzones-tf15.yml index d5fa64fea..58184cb32 100644 --- a/.github/workflows/landingzones-tf15.yml +++ b/.github/workflows/landingzones-tf15.yml @@ -58,7 +58,7 @@ jobs: - name: foundations run: | /tf/rover/rover.sh -lz ${GITHUB_WORKSPACE}/caf_solution -a apply \ - -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/gitops \ + -var-folder ${GITHUB_WORKSPACE}/caf_solution/scenario/foundations/100-passthrough \ -tfstate caf_foundations.tfstate \ -level level1 \ -parallelism=30 \ diff --git a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars index 123acb26e..3e4945769 100644 --- a/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/200-single-region-hub/configuration.tfvars @@ -6,7 +6,7 @@ landingzone = { tfstates = { caf_gitops = { level = "lower" - tfstate = "caf_gitops.tfstate" + tfstate = "caf_foundations.tfstate" } } } diff --git a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars index b2895e82b..45eb82b65 100644 --- a/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars +++ b/caf_solution/scenario/networking/201-multi-region-hub/configuration.tfvars @@ -6,7 +6,7 @@ landingzone = { tfstates = { caf_gitops = { level = "lower" - tfstate = "caf_gitops.tfstate" + tfstate = "caf_foundations.tfstate" } } } diff --git a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars index 20d78390f..f243d609e 100644 --- a/caf_solution/scenario/networking/210-aks-private/configuration.tfvars +++ b/caf_solution/scenario/networking/210-aks-private/configuration.tfvars @@ -6,7 +6,7 @@ landingzone = { tfstates = { caf_gitops = { level = "lower" - tfstate = "caf_gitops.tfstate" + tfstate = "caf_foundations.tfstate" } } }