diff --git a/azure/arcgis-enterprise-k8s/image/build-admin-cli-image.sh b/azure/arcgis-enterprise-k8s/image/build-admin-cli-image.sh index 8351f74..f0dd7fc 100644 --- a/azure/arcgis-enterprise-k8s/image/build-admin-cli-image.sh +++ b/azure/arcgis-enterprise-k8s/image/build-admin-cli-image.sh @@ -31,8 +31,9 @@ SITE_ID=$4 az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET --tenant $ARM_TENANT_ID -ACR_NAME=$(az keyvault secret show --name acr-name --vault-name $SITE_ID --query value -o tsv) -ACR_LOGIN_SERVER=$(az keyvault secret show --name acr-login-server --vault-name $SITE_ID --query value -o tsv) +VAULT_NAME=$(az resource list --resource-group $SITE_ID-infrastructure-core --resource-type=Microsoft.KeyVault/vaults --query "[].{name:name}" -o tsv) +ACR_NAME=$(az keyvault secret show --name acr-name --vault-name $VAULT_NAME --query value -o tsv) +ACR_LOGIN_SERVER=$(az keyvault secret show --name acr-login-server --vault-name $VAULT_NAME --query value -o tsv) az acr login --name $ACR_NAME diff --git a/azure/arcgis-enterprise-k8s/ingress/README.md b/azure/arcgis-enterprise-k8s/ingress/README.md index aeb045d..88d0bbf 100644 --- a/azure/arcgis-enterprise-k8s/ingress/README.md +++ b/azure/arcgis-enterprise-k8s/ingress/README.md @@ -33,6 +33,12 @@ On the machine where Terraform is executed: | azurerm | ~> 4.16 | | kubernetes | ~> 2.26 | +## Modules + +| Name | Source | Version | +|------|--------|---------| +| site_core_info | ../../modules/site_core_info | n/a | + ## Resources | Name | Type | @@ -46,7 +52,6 @@ On the machine where Terraform is executed: | [kubernetes_namespace.arcgis_enterprise](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource | | [kubernetes_secret.ca_bundle_secret](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource | | [kubernetes_secret.listener_tls_secret](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource | -| [azurerm_key_vault.site_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault) | data source | | [azurerm_key_vault_secret.alb_id](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source | ## Inputs diff --git a/azure/arcgis-enterprise-k8s/ingress/main.tf b/azure/arcgis-enterprise-k8s/ingress/main.tf index 6ade5ab..75f51d0 100644 --- a/azure/arcgis-enterprise-k8s/ingress/main.tf +++ b/azure/arcgis-enterprise-k8s/ingress/main.tf @@ -68,15 +68,15 @@ provider "kubernetes" { config_path = "~/.kube/config" } -data "azurerm_key_vault" "site_vault" { - name = var.site_id - resource_group_name = "${var.site_id}-infrastructure-core" +module "site_core_info" { + source = "../../modules/site_core_info" + site_id = var.site_id } # Retrieve the Application Load Balancer ID from the Key Vault data "azurerm_key_vault_secret" "alb_id" { name = "alb-id" - key_vault_id = data.azurerm_key_vault.site_vault.id + key_vault_id = module.site_core_info.vault_id } locals { diff --git a/azure/arcgis-site-core/infrastructure-core/README.md b/azure/arcgis-site-core/infrastructure-core/README.md index dab49f5..c65f776 100644 --- a/azure/arcgis-site-core/infrastructure-core/README.md +++ b/azure/arcgis-site-core/infrastructure-core/README.md @@ -48,10 +48,8 @@ Attributes of the resources are stored as secrets in the Azure Key Vault created | [azurerm_bastion_host.bastion](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/bastion_host) | resource | | [azurerm_key_vault.site_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) | resource | | [azurerm_key_vault_access_policy.current_user](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) | resource | -| [azurerm_key_vault_secret.app_gateway_subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | -| [azurerm_key_vault_secret.internal_subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | -| [azurerm_key_vault_secret.private_subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | | [azurerm_key_vault_secret.storage_account_name](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | +| [azurerm_key_vault_secret.subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | | [azurerm_key_vault_secret.vnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | | [azurerm_nat_gateway.nat](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/nat_gateway) | resource | | [azurerm_nat_gateway_public_ip_association.nat](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/nat_gateway_public_ip_association) | resource | @@ -86,7 +84,7 @@ Attributes of the resources are stored as secrets in the Azure Key Vault created | [azurerm_subnet_network_security_group_association.internal_subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_network_security_group_association) | resource | | [azurerm_subnet_network_security_group_association.private_subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_network_security_group_association) | resource | | [azurerm_virtual_network.site_vnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network) | resource | -| [random_id.storage_account_suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | +| [random_id.unique_name_suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | | [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) | data source | ## Inputs diff --git a/azure/arcgis-site-core/infrastructure-core/main.tf b/azure/arcgis-site-core/infrastructure-core/main.tf index d57418b..e0db6a8 100644 --- a/azure/arcgis-site-core/infrastructure-core/main.tf +++ b/azure/arcgis-site-core/infrastructure-core/main.tf @@ -70,6 +70,15 @@ provider "azurerm" { data "azurerm_client_config" "current" {} +resource "random_id" "unique_name_suffix" { + keepers = { + # Generate a new id each time we switch to a new site id + site_id = var.site_id + } + + byte_length = 8 +} + resource "azurerm_resource_group" "site_rg" { name = "${var.site_id}-infrastructure-core" location = var.azure_region @@ -83,9 +92,8 @@ resource "azurerm_resource_group" "site_rg" { } # Key Vault of ArcGIS Enterprise site - resource "azurerm_key_vault" "site_vault" { - name = var.site_id + name = "site${random_id.unique_name_suffix.hex}" # must be globally unique location = azurerm_resource_group.site_rg.location resource_group_name = azurerm_resource_group.site_rg.name tenant_id = data.azurerm_client_config.current.tenant_id @@ -94,6 +102,7 @@ resource "azurerm_key_vault" "site_vault" { tags = { ArcGISSiteId = var.site_id + ArcGISRole = "site-vault" } } @@ -235,22 +244,6 @@ resource "azurerm_subnet_nat_gateway_association" "app_gateway" { nat_gateway_id = azurerm_nat_gateway.nat.id } -resource "azurerm_key_vault_secret" "app_gateway_subnets" { - count = length(azurerm_subnet.app_gateway_subnets) - name = "app-gateway-subnet-${count.index + 1}" - value = azurerm_subnet.app_gateway_subnets[count.index].id - key_vault_id = azurerm_key_vault.site_vault.id - - tags = { - ArcGISSiteId = var.site_id - ParameterRole = "AppGatewaySubnet" - } - - depends_on = [ - azurerm_key_vault_access_policy.current_user - ] -} - # Private subnets are routed to NAT Gateway resource "azurerm_subnet" "private_subnets" { @@ -282,22 +275,6 @@ resource "azurerm_subnet_nat_gateway_association" "private" { nat_gateway_id = azurerm_nat_gateway.nat.id } -resource "azurerm_key_vault_secret" "private_subnets" { - count = length(azurerm_subnet.private_subnets) - name = "private-subnet-${count.index + 1}" - value = azurerm_subnet.private_subnets[count.index].id - key_vault_id = azurerm_key_vault.site_vault.id - - tags = { - ArcGISSiteId = var.site_id - ParameterRole = "PrivateSubnet" - } - - depends_on = [ - azurerm_key_vault_access_policy.current_user - ] -} - # Internal subnets are routed to service endpoints only resource "azurerm_subnet" "internal_subnets" { @@ -324,18 +301,20 @@ resource "azurerm_subnet_network_security_group_association" "internal_subnets" network_security_group_id = azurerm_network_security_group.internal_nsg.id } -resource "azurerm_key_vault_secret" "internal_subnets" { - count = length(azurerm_subnet.internal_subnets) - name = "internal-subnet-${count.index + 1}" - value = azurerm_subnet.internal_subnets[count.index].id +resource "azurerm_key_vault_secret" "subnets" { + name = "subnets" + value = jsonencode({ + app_gateway = azurerm_subnet.app_gateway_subnets.*.id + private = azurerm_subnet.private_subnets.*.id + internal = azurerm_subnet.internal_subnets.*.id + }) key_vault_id = azurerm_key_vault.site_vault.id tags = { ArcGISSiteId = var.site_id - ParameterRole = "InternalSubnet" } depends_on = [ azurerm_key_vault_access_policy.current_user ] -} +} \ No newline at end of file diff --git a/azure/arcgis-site-core/infrastructure-core/storage.tf b/azure/arcgis-site-core/infrastructure-core/storage.tf index 5d4e55d..fcf7ba3 100644 --- a/azure/arcgis-site-core/infrastructure-core/storage.tf +++ b/azure/arcgis-site-core/infrastructure-core/storage.tf @@ -1,4 +1,4 @@ -# Copyright 2024 Esri +# Copyright 2024-2025 Esri # # Licensed under the Apache License Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,20 +14,12 @@ # Storage account and blob containers for ArcGIS Enterprise site -resource "random_id" "storage_account_suffix" { - keepers = { - # Generate a new id each time we switch to a new site id - site_id = var.site_id - } - - byte_length = 8 -} # Create storage account for the site's repository, backups, and logs. # Public network access is enabled for the storage account because it is required # to create the blob containers. resource "azurerm_storage_account" "site_storage" { - name = "site${random_id.storage_account_suffix.hex}" + name = "site${random_id.unique_name_suffix.hex}" resource_group_name = azurerm_resource_group.site_rg.name location = azurerm_resource_group.site_rg.location account_tier = "Standard" diff --git a/azure/arcgis-site-core/k8s-cluster/modules/container-registry/README.md b/azure/arcgis-site-core/k8s-cluster/modules/container-registry/README.md index 918ecaa..65fbb87 100644 --- a/azure/arcgis-site-core/k8s-cluster/modules/container-registry/README.md +++ b/azure/arcgis-site-core/k8s-cluster/modules/container-registry/README.md @@ -21,6 +21,12 @@ Azure CLI must be installed on the machine where terraform is executed. | azurerm | n/a | | random | n/a | +## Modules + +| Name | Source | Version | +|------|--------|---------| +| site_core_info | ../../../../modules/site_core_info | n/a | + ## Resources | Name | Type | @@ -28,7 +34,7 @@ Azure CLI must be installed on the machine where terraform is executed. | [azurerm_container_registry.cluster_acr](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_registry) | resource | | [azurerm_container_registry_cache_rule.pull_through_cache](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_registry_cache_rule) | resource | | [azurerm_container_registry_credential_set.credential_set](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_registry_credential_set) | resource | -| [azurerm_key_vault_access_policy.example](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) | resource | +| [azurerm_key_vault_access_policy.pull_through_cache](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) | resource | | [azurerm_key_vault_secret.acr_login_server](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | | [azurerm_key_vault_secret.acr_name](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | | [azurerm_key_vault_secret.cr_password](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | @@ -38,7 +44,6 @@ Azure CLI must be installed on the machine where terraform is executed. | [azurerm_private_endpoint.acr_private_endpoint](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | | [azurerm_role_assignment.acr](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | | [random_id.container_registry_suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | -| [azurerm_key_vault.site_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault) | data source | ## Inputs diff --git a/azure/arcgis-site-core/k8s-cluster/modules/container-registry/main.tf b/azure/arcgis-site-core/k8s-cluster/modules/container-registry/main.tf index 2e40821..8c2890f 100644 --- a/azure/arcgis-site-core/k8s-cluster/modules/container-registry/main.tf +++ b/azure/arcgis-site-core/k8s-cluster/modules/container-registry/main.tf @@ -29,9 +29,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -data "azurerm_key_vault" "site_vault" { - name = var.site_id - resource_group_name = "${var.site_id}-infrastructure-core" +module "site_core_info" { + source = "../../../../modules/site_core_info" + site_id = var.site_id } resource "random_id" "container_registry_suffix" { @@ -61,26 +61,26 @@ resource "azurerm_container_registry" "cluster_acr" { resource "azurerm_key_vault_secret" "acr_name" { name = "acr-name" value = azurerm_container_registry.cluster_acr.name - key_vault_id = data.azurerm_key_vault.site_vault.id + key_vault_id = module.site_core_info.vault_id } # Create Key Vault secrets for the ACR login server resource "azurerm_key_vault_secret" "acr_login_server" { name = "acr-login-server" value = azurerm_container_registry.cluster_acr.login_server - key_vault_id = data.azurerm_key_vault.site_vault.id + key_vault_id = module.site_core_info.vault_id } resource "azurerm_key_vault_secret" "cr_user" { name = "cr-user" value = var.container_registry_user - key_vault_id = data.azurerm_key_vault.site_vault.id + key_vault_id = module.site_core_info.vault_id } resource "azurerm_key_vault_secret" "cr_password" { name = "cr-password" value = var.container_registry_password - key_vault_id = data.azurerm_key_vault.site_vault.id + key_vault_id = module.site_core_info.vault_id } # Create container registry credential set for the pull-through cache. @@ -94,14 +94,14 @@ resource "azurerm_container_registry_credential_set" "credential_set" { } authentication_credentials { - username_secret_id = "${data.azurerm_key_vault.site_vault.vault_uri}secrets/cr-user" - password_secret_id = "${data.azurerm_key_vault.site_vault.vault_uri}secrets/cr-password" + username_secret_id = "${module.site_core_info.vault_uri}secrets/cr-user" + password_secret_id = "${module.site_core_info.vault_uri}secrets/cr-password" } } # Grant the ACR pull-through cache principal access to the Key Vault secrets. resource "azurerm_key_vault_access_policy" "pull_through_cache" { - key_vault_id = data.azurerm_key_vault.site_vault.id + key_vault_id = module.site_core_info.vault_id tenant_id = azurerm_container_registry_credential_set.credential_set.identity[0].tenant_id object_id = azurerm_container_registry_credential_set.credential_set.identity[0].principal_id diff --git a/azure/modules/site_core_info/README.md b/azure/modules/site_core_info/README.md index 41cc1f8..0e69de1 100644 --- a/azure/modules/site_core_info/README.md +++ b/azure/modules/site_core_info/README.md @@ -16,13 +16,10 @@ returns them as output values. | Name | Type | |------|------| | [azurerm_key_vault.site_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault) | data source | -| [azurerm_key_vault_secret.app_gateway_subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source | -| [azurerm_key_vault_secret.internal_subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source | -| [azurerm_key_vault_secret.private_subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source | -| [azurerm_key_vault_secret.storage_account_key](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source | | [azurerm_key_vault_secret.storage_account_name](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source | +| [azurerm_key_vault_secret.subnets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source | | [azurerm_key_vault_secret.vnet_id](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret) | data source | -| [azurerm_key_vault_secrets.secrets](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secrets) | data source | +| [azurerm_resources.site_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resources) | data source | | [azurerm_storage_account.site_storage](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/storage_account) | data source | ## Inputs @@ -41,7 +38,6 @@ returns them as output values. | resource_group_name | Resource Group Name | | storage_account_blob_endpoint | Azure storage account primary blob endpoint | | storage_account_id | Azure storage account Id | -| storage_account_key | Azure storage account key | | storage_account_name | Azure storage account name | | vault_id | Azure Key Vault Id | | vault_name | Azure Key Vault Name | diff --git a/azure/modules/site_core_info/main.tf b/azure/modules/site_core_info/main.tf index 98dd6a3..f48780a 100644 --- a/azure/modules/site_core_info/main.tf +++ b/azure/modules/site_core_info/main.tf @@ -6,7 +6,7 @@ * returns them as output values. */ -# Copyright 2024 Esri +# Copyright 2024-2025 Esri # # Licensed under the Apache License Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,39 +20,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -data "azurerm_key_vault" "site_vault" { - name = var.site_id +data "azurerm_resources" "site_vault" { resource_group_name = "${var.site_id}-infrastructure-core" -} - -data "azurerm_key_vault_secrets" "secrets" { - key_vault_id = data.azurerm_key_vault.site_vault.id -} -data "azurerm_key_vault_secret" "app_gateway_subnets" { - for_each = { - for secret in data.azurerm_key_vault_secrets.secrets.names : secret => secret - if startswith(secret, "app-gateway-subnet") + required_tags = { + ArcGISSiteId = var.site_id + ArcGISRole = "site-vault" } - name = each.key - key_vault_id = data.azurerm_key_vault.site_vault.id } -data "azurerm_key_vault_secret" "private_subnets" { - for_each = { - for secret in data.azurerm_key_vault_secrets.secrets.names : secret => secret - if startswith(secret, "private-subnet") - } - name = each.key - key_vault_id = data.azurerm_key_vault.site_vault.id +data "azurerm_key_vault" "site_vault" { + name = data.azurerm_resources.site_vault.resources[0].name + resource_group_name = data.azurerm_resources.site_vault.resource_group_name } -data "azurerm_key_vault_secret" "internal_subnets" { - for_each = { - for secret in data.azurerm_key_vault_secrets.secrets.names : secret => secret - if startswith(secret, "internal-subnet") - } - name = each.key +data "azurerm_key_vault_secret" "subnets" { + name = "subnets" key_vault_id = data.azurerm_key_vault.site_vault.id } diff --git a/azure/modules/site_core_info/outputs.tf b/azure/modules/site_core_info/outputs.tf index 839e144..9c09d2f 100644 --- a/azure/modules/site_core_info/outputs.tf +++ b/azure/modules/site_core_info/outputs.tf @@ -39,17 +39,17 @@ output "vnet_id" { output "app_gateway_subnets" { description = "Ids of app gateway subnets" - value = values(data.azurerm_key_vault_secret.app_gateway_subnets).*.value + value = jsondecode(data.azurerm_key_vault_secret.subnets.value).app_gateway } output "private_subnets" { description = "Ids of private subnets" - value = values(data.azurerm_key_vault_secret.private_subnets).*.value + value = jsondecode(data.azurerm_key_vault_secret.subnets.value).private } output "internal_subnets" { description = "Ids of internal subnets" - value = values(data.azurerm_key_vault_secret.internal_subnets).*.value + value = jsondecode(data.azurerm_key_vault_secret.subnets.value).internal } output "storage_account_name" {