diff --git a/main.tf b/main.tf index b70c1c9..fab8d23 100644 --- a/main.tf +++ b/main.tf @@ -4,14 +4,35 @@ locals { basename(data.azurerm_role_definition.delegable[name].id) ]) + restricted_role_definition_ids_list = join(", ", [ + for name in var.restricted_roles : + basename(data.azurerm_role_definition.restricted[name].id) + ]) + rbac_admin_write_constraint_principal_type = "@Request[Microsoft.Authorization/roleAssignments:PrincipalType] ForAnyOfAnyValues:StringEquals {'ServicePrincipal'}" rbac_admin_delete_constraint_principal_type = "@Resource[Microsoft.Authorization/roleAssignments:PrincipalType] ForAnyOfAnyValues:StringEquals {'ServicePrincipal'}" + rbac_admin_write_clause_roles = join( + "\nAND\n", + compact([ + length(var.delegable_roles) > 0 ? "@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${local.allowed_role_definition_ids_list}}" : "", + length(var.restricted_roles) > 0 ? "@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidNotEquals {${local.restricted_role_definition_ids_list}}" : "", + ]) + ) + + rbac_admin_delete_clause_roles = join( + "\nAND\n", + compact([ + length(var.delegable_roles) > 0 ? "@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${local.allowed_role_definition_ids_list}}" : "", + length(var.restricted_roles) > 0 ? "@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidNotEquals {${local.restricted_role_definition_ids_list}}" : "", + ]) + ) + rbac_admin_write_clause = ( var.delegable_roles_to_sp_only ? <<-EOT ( - @Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${local.allowed_role_definition_ids_list}} + ${local.rbac_admin_write_clause_roles} ) AND ( @@ -19,14 +40,14 @@ locals { ) EOT : - "@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${local.allowed_role_definition_ids_list}}" + local.rbac_admin_write_clause_roles ) rbac_admin_delete_clause = ( var.delegable_roles_to_sp_only ? <<-EOT ( - @Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${local.allowed_role_definition_ids_list}} + ${local.rbac_admin_delete_clause_roles} ) AND ( @@ -34,7 +55,7 @@ locals { ) EOT : - "@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${local.allowed_role_definition_ids_list}}" + local.rbac_admin_delete_clause_roles ) rbac_admin_condition = <<-EOT @@ -61,7 +82,7 @@ locals { } data "azurerm_role_definition" "rbac_admin" { - for_each = length(var.delegable_roles) > 0 ? { this = true } : {} + for_each = length(var.delegable_roles) > 0 || length(var.restricted_roles) > 0 ? { this = true } : {} name = "Role Based Access Control Administrator" scope = var.scope @@ -74,6 +95,13 @@ data "azurerm_role_definition" "delegable" { scope = var.scope } +data "azurerm_role_definition" "restricted" { + for_each = toset(var.restricted_roles) + + name = each.value + scope = var.scope +} + resource "azurerm_role_assignment" "role" { for_each = toset(var.roles) @@ -87,7 +115,7 @@ resource "azurerm_role_assignment" "role" { resource "azurerm_role_assignment" "rbac_admin" { - for_each = length(var.delegable_roles) > 0 ? { this = true } : {} + for_each = length(var.delegable_roles) > 0 || length(var.restricted_roles) > 0 ? { this = true } : {} scope = var.scope role_definition_id = data.azurerm_role_definition.rbac_admin["this"].id # Role Based Access Control Administrator diff --git a/variables.tf b/variables.tf index d19daba..31f6944 100644 --- a/variables.tf +++ b/variables.tf @@ -27,7 +27,7 @@ variable "roles" { variable "delegable_roles" { type = list(string) default = [] - description = "Role definition names that RBAC Administrator is allowed to assign/delete via ABAC condition. When empty, RBAC Administrator assignment is not created." + description = "Role definition names that RBAC Administrator is allowed to assign/delete via ABAC condition." validation { condition = length(distinct(var.delegable_roles)) == length(var.delegable_roles) @@ -35,6 +35,17 @@ variable "delegable_roles" { } } +variable "restricted_roles" { + type = list(string) + default = [] + description = "Role definitions names that RBAC Administrator is not allowed to assign/delete via ABAC condition." + + validation { + condition = length(distinct(var.restricted_roles)) == length(var.restricted_roles) + error_message = "restricted_roles must not contain duplicates." + } +} + variable "principal_type" { type = string default = "ServicePrincipal"