diff --git a/azuread_federated_credentials.tf b/azuread_federated_credentials.tf new file mode 100644 index 0000000000..5b9ff7a746 --- /dev/null +++ b/azuread_federated_credentials.tf @@ -0,0 +1,12 @@ +module "azuread_federated_credentials" { + source = "./modules/azuread/federated_credentials/" + for_each = local.azuread.azuread_federated_credentials + depends_on = [module.azuread_applications_v1] + client_config = local.client_config + settings = each.value + azuread_applications = local.combined_objects_azuread_applications +} + +output "azuread_federated_credentials" { + value = module.azuread_federated_credentials +} \ No newline at end of file diff --git a/examples/azuread/202-azuread-application-federated-credentials/configurations.tfvars b/examples/azuread/202-azuread-application-federated-credentials/configurations.tfvars new file mode 100644 index 0000000000..d6ab21993a --- /dev/null +++ b/examples/azuread/202-azuread-application-federated-credentials/configurations.tfvars @@ -0,0 +1,24 @@ +azuread_applications = { + aks_auth_app = { + application_name = "app-najeeb-sandbox-aksadmin" + } +} + +azuread_federated_credentials = { + cred1 = { + display_name = "app-wi-fed01" + subject = "system:serviceaccount:demo:workload-identity-sa" + oidc_issuer_url = "https://westeurope.oic.prod-aks.azure.com/" + azuread_application = { + key = "aks_auth_app" + } + } +} + +azuread_service_principals = { + aks_auth_app = { + azuread_application = { + key = "aks_auth_app" + } + } +} \ No newline at end of file diff --git a/examples/managed_service_identity/101-mi-federated_credentials/configuration.tfvars b/examples/managed_service_identity/101-mi-federated_credentials/configuration.tfvars new file mode 100644 index 0000000000..4fa515f030 --- /dev/null +++ b/examples/managed_service_identity/101-mi-federated_credentials/configuration.tfvars @@ -0,0 +1,27 @@ +resource_groups = { + msi_region1 = { + name = "security-rg1" + region = "region1" + } +} + +managed_identities = { + workload_system_mi = { + name = "demo-mi-wi" + resource_group_key = "msi_region1" + } +} + +mi_federated_credentials = { + cred1 = { + name = "mi-wi-demo01" + subject = "system:serviceaccount:demo:workload-identity-sa" + oidc_issuer_url = "https://westeurope.oic.prod-aks.azure.com/" + managed_identity = { + key = "workload_system_mi" + } + resource_group = { + key = "msi_region1" + } + } +} \ No newline at end of file diff --git a/local.remote_objects.tf b/local.remote_objects.tf index 76de44f2cd..ae7871aa99 100644 --- a/local.remote_objects.tf +++ b/local.remote_objects.tf @@ -91,6 +91,7 @@ locals { logic_app_standard = try(local.combined_objects_logic_app_standard, null) machine_learning = try(local.combined_objects_machine_learning, null) managed_identities = try(local.combined_objects_managed_identities, null) + mi_federated_credentials = try(local.combined_objects_mi_federated_credentials, null) monitor_action_groups = try(local.combined_objects_monitor_action_groups, null) mssql_databases = try(local.combined_objects_mssql_databases, null) mssql_elastic_pools = try(local.combined_objects_mssql_elastic_pools, null) diff --git a/locals.combined_objects.tf b/locals.combined_objects.tf index 8c2f27186a..b0f1abc891 100644 --- a/locals.combined_objects.tf +++ b/locals.combined_objects.tf @@ -124,6 +124,7 @@ locals { combined_objects_mssql_managed_instances = merge(tomap({ (local.client_config.landingzone_key) = merge(module.mssql_managed_instances, module.mssql_managed_instances_v1, lookup(var.data_sources, "mssql_managed_instances", {})) }), lookup(var.remote_objects, "mssql_managed_instances", {}), lookup(var.data_sources, "mssql_managed_instances", {})) combined_objects_mssql_managed_instances_secondary = merge(tomap({ (local.client_config.landingzone_key) = merge(module.mssql_managed_instances_secondary, module.mssql_managed_instances_secondary_v1, lookup(var.data_sources, "mssql_managed_instances_secondary", {})) }), lookup(var.remote_objects, "mssql_managed_instances_secondary", {}), lookup(var.remote_objects, "mssql_managed_instances_secondary", {})) combined_objects_mssql_servers = merge(tomap({ (local.client_config.landingzone_key) = merge(module.mssql_servers, lookup(var.data_sources, "mssql_servers", {})) }), lookup(var.remote_objects, "mssql_servers", {})) + combined_objects_mi_federated_credentials = merge(tomap({ (local.client_config.landingzone_key) = module.mi_federated_credentials }), try(var.remote_objects.mi_federated_credentials, {})) combined_objects_mysql_flexible_server = merge(tomap({ (local.client_config.landingzone_key) = module.mysql_flexible_server }), lookup(var.remote_objects, "mysql_flexible_server", {})) combined_objects_mysql_servers = merge(tomap({ (local.client_config.landingzone_key) = module.mysql_servers }), lookup(var.remote_objects, "mysql_servers", {}), lookup(var.data_sources, "mysql_servers", {})) combined_objects_nat_gateways = merge(tomap({ (local.client_config.landingzone_key) = module.nat_gateways }), lookup(var.remote_objects, "nat_gateways", {}), lookup(var.data_sources, "nat_gateways", {})) diff --git a/locals.tf b/locals.tf index e81350b46f..0ae4e4f8bc 100644 --- a/locals.tf +++ b/locals.tf @@ -25,6 +25,7 @@ locals { azuread_service_principal_passwords = try(var.azuread.azuread_service_principal_passwords, {}) azuread_service_principals = try(var.azuread.azuread_service_principals, {}) azuread_users = try(var.azuread.azuread_users, {}) + azuread_federated_credentials = try(var.azuread.azuread_federated_credentials, {}) } client_config = var.client_config == {} ? { diff --git a/mi_federated_credentials.tf b/mi_federated_credentials.tf new file mode 100644 index 0000000000..f9579197b9 --- /dev/null +++ b/mi_federated_credentials.tf @@ -0,0 +1,13 @@ +module "mi_federated_credentials" { + source = "./modules/security/mi_federated_credentials/" + for_each = var.mi_federated_credentials + depends_on = [module.managed_identities] + client_config = local.client_config + resource_group = local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group_key, each.value.resource_group.key)] + settings = each.value + managed_identities = local.combined_objects_managed_identities +} + +output "mi_federated_credentials" { + value = module.mi_federated_credentials +} \ No newline at end of file diff --git a/modules/azuread/federated_credentials/federated_credential.tf b/modules/azuread/federated_credentials/federated_credential.tf new file mode 100644 index 0000000000..a5f8d4862b --- /dev/null +++ b/modules/azuread/federated_credentials/federated_credential.tf @@ -0,0 +1,8 @@ +resource "azuread_application_federated_identity_credential" "fed_cred" { + application_object_id = coalesce(try(var.settings.azuread_application.object_id, null), var.azuread_applications[try(var.settings.azuread_application.lz_key, var.client_config.landingzone_key)][var.settings.azuread_application.key].object_id) + display_name = var.settings.display_name + description = try(var.settings.description, null) + audiences = ["api://AzureADTokenExchange"] + issuer = coalesce(try(var.oidc_issuer_url, null), try(var.settings.oidc_issuer_url, null)) + subject = var.settings.subject +} \ No newline at end of file diff --git a/modules/azuread/federated_credentials/output.tf b/modules/azuread/federated_credentials/output.tf new file mode 100644 index 0000000000..3fed8cfd88 --- /dev/null +++ b/modules/azuread/federated_credentials/output.tf @@ -0,0 +1,3 @@ +output "credential_id" { + value = azuread_application_federated_identity_credential.fed_cred.id +} \ No newline at end of file diff --git a/modules/azuread/federated_credentials/variables.tf b/modules/azuread/federated_credentials/variables.tf new file mode 100644 index 0000000000..147c2418e4 --- /dev/null +++ b/modules/azuread/federated_credentials/variables.tf @@ -0,0 +1,12 @@ +variable "settings" { + default = {} +} +variable "client_config" { + description = "Client configuration object (see module README.md)." +} +variable "azuread_applications" { + default = {} +} +variable "oidc_issuer_url" { + default = null +} \ No newline at end of file diff --git a/modules/security/mi_federated_credentials/federated_credential.tf b/modules/security/mi_federated_credentials/federated_credential.tf new file mode 100644 index 0000000000..9247cf41b6 --- /dev/null +++ b/modules/security/mi_federated_credentials/federated_credential.tf @@ -0,0 +1,8 @@ +resource "azurerm_federated_identity_credential" "fed_cred" { + name = var.settings.name + resource_group_name = coalesce(try(var.settings.resource_group.name, null), try(var.resource_group.name, null)) + audience = try(var.settings.audience, ["api://AzureADTokenExchange"]) + parent_id = coalesce(try(var.settings.managed_identity.id, null), var.managed_identities[try(var.settings.managed_identity.lz_key, var.client_config.landingzone_key)][var.settings.managed_identity.key].id) + subject = var.settings.subject + issuer = coalesce(try(var.oidc_issuer_url, null), try(var.settings.oidc_issuer_url, null)) +} \ No newline at end of file diff --git a/modules/security/mi_federated_credentials/output.tf b/modules/security/mi_federated_credentials/output.tf new file mode 100644 index 0000000000..9811216428 --- /dev/null +++ b/modules/security/mi_federated_credentials/output.tf @@ -0,0 +1,3 @@ +output "id" { + value = azurerm_federated_identity_credential.fed_cred.id +} \ No newline at end of file diff --git a/modules/security/mi_federated_credentials/variables.tf b/modules/security/mi_federated_credentials/variables.tf new file mode 100644 index 0000000000..c0be9567e6 --- /dev/null +++ b/modules/security/mi_federated_credentials/variables.tf @@ -0,0 +1,16 @@ + +variable "settings" { + default = {} +} +variable "client_config" { + description = "Client configuration object (see module README.md)." +} +variable "resource_group" { + default = {} +} +variable "managed_identities" { + default = {} +} +variable "oidc_issuer_url" { + default = null +} \ No newline at end of file diff --git a/variables.tf b/variables.tf index 4c4d69c4a1..bc9510200b 100644 --- a/variables.tf +++ b/variables.tf @@ -450,3 +450,7 @@ variable "load_test" { default = {} } +variable "mi_federated_credentials" { + default = {} +} +