-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
azurerm_role_assignment support conditional ABAC for Microsoft.Authorization/roleAssignments #23364
Comments
@audunsolemdal Thank you for taking the time to open this feature request! |
This now works since azurem provider version 3.87 was released which included this PR #24271 Thanks @pemcne ! It is necessary to explicitly set the Example below resource "azurerm_role_assignment" "example_expected_to_work" {
scope = "/subscriptions/xxxxxxxxxxxxxxxxxxxx"
role_definition_name = "Storage Queue Data Contributor"
principal_id = data.azuread_group.contributors.object_id
principal_type = "Group" # Need to Explicitly set "Group", "ServicePrincipal" or "User" depending on which principal id is to be assigned
} |
Module quick start with dynamic logic if anyone is interested resource "azuread_group" "readers" {
display_name = "az rbac sub ${var.subscription_kv.display_name} readers"
security_enabled = true
prevent_duplicate_names = true
}
resource "azuread_group" "owners" {
display_name = "az rbac sub ${var.subscription_kv.display_name} owners"
security_enabled = true
prevent_duplicate_names = true
}
resource "azuread_group" "contributors" {
display_name = "az rbac sub ${var.subscription_kv.display_name} contributors"
security_enabled = true
prevent_duplicate_names = true
}
locals {
# Map of roles which the "owner" group should be able to assign to Service Principals and Groups
delegated_roles = {
"Azure Service Bus Data Receiver" = "4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0"
"Azure Service Bus Data Sender" = "69a216fc-b8fb-44d8-bc22-1f3c2cd27a39"
"Key Vault Secrets Officer" = "b86a8fe4-44ce-4948-aee5-eccb2c155cd7"
"Key Vault Secrets User" = "4633458b-17de-408a-b874-0445c86b69e6"
"Key Vault Administrator" = "00482a5a-887f-4fb3-b363-3b7fe8e74483"
"Key Vault Crypto User" = "12338af0-0e69-4776-bea7-57ae8d297424"
"App Configuration Data Owner" = "5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b"
"App Configuration Data Reader" = "516239f1-63e1-4d78-a4de-a74fb236a071"
"Website Contributor" = "de139f84-1756-47ae-9be6-808fbbe84772"
"Cosmos DB Account Reader Role" = "fbdf93bf-df7d-467e-a4d2-9458aa1360c8"
"Cosmos DB Operator" = "230815da-be43-4aae-9cb4-875f7bd000aa"
"Storage Account Contributor" = "17d1049b-9a84-46fb-8f53-869881c3d3ab"
"Storage Blob Data Owner" = "b7e6dc6d-f1e8-4753-8033-0f276bb0955b"
"Storage Blob Data Contributor" = "ba92f5b4-2d11-453d-a403-e96b0029c9fe"
"Storage Blob Data Reader" = "2a2b9908-6ea1-4ae2-8e65-a410df84e7d1"
"Storage File Data SMB Share Elevated Contributor" = "a7264617-510b-434b-a828-9731dc254ea7"
"Storage File Data SMB Share Reader" = "aba4ae5f-2193-4029-9191-0cb91df5e314"
"Storage Queue Data Contributor" = "974c5e8b-45b9-4653-ba55-5f855dd0fb88"
"Storage Queue Data Message Sender" = "c6a89b2d-59bc-44d0-9896-0f6e12d7b80a"
"Storage Queue Data Reader" = "19e7f393-937e-4f77-808e-94535e297925"
"Storage Queue Data Message Processor" = "974c5e8b-45b9-4653-ba55-5f855dd0fb88"
}
delegated_role_ids_string = join(", ", values(local.delegated_roles))
# map of groups which can be assigned the roles listed above
delegated_groups = {
"readers" = azuread_group.readers.id
"contributors" = azuread_group.contributors.id
"owners" = azuread_group.owners.id
}
delegated_group_ids_string = join(", ", concat(values(local.delegated_groups), var.rbac_extra_allowed_group_principal_ids))
delegated_sp_ids_string = join(", ", var.rbac_allowed_service_principal_ids)
delegated_user_ids_string = join(", ", var.rbac_allowed_user_principal_ids)
allowed_group_ids = var.rbac_allow_any_group_assignment == true ? "" : "AND @Request[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {${local.delegated_group_ids_string}}"
allow_user_assignment = var.rbac_allow_user_assignment == true || local.delegated_user_ids_string != "" ? "OR @Request[Microsoft.Authorization/roleAssignments:PrincipalType] StringEqualsIgnoreCase 'User'" : ""
allowed_user_ids = local.delegated_user_ids_string != "" ? "AND @Request[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {${local.delegated_user_ids_string}}" : ""
allow_service_principal_assignment = var.rbac_allow_service_principal_assignment == true || local.delegated_sp_ids_string != "" ? "OR @Request[Microsoft.Authorization/roleAssignments:PrincipalType] StringEqualsIgnoreCase 'ServicePrincipal'" : ""
limit_sp_user_assignment = local.delegated_sp_ids_string != "" ? "AND @Request[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {${local.delegated_sp_ids_string}}" : ""
allowed_group_ids_delete = var.rbac_allow_any_group_assignment == true ? "" : "AND @Resource[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {${local.delegated_group_ids_string}}"
allow_user_assignment_delete = var.rbac_allow_user_assignment == true || local.delegated_user_ids_string != "" ? "OR @Resource[Microsoft.Authorization/roleAssignments:PrincipalType] StringEqualsIgnoreCase 'User'" : ""
allowed_user_ids_delete = local.delegated_user_ids_string != "" ? "AND @Resource[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {${local.delegated_user_ids_string}}" : ""
allow_service_principal_assignment_delete = var.rbac_allow_service_principal_assignment == true || local.delegated_sp_ids_string != "" ? "OR @Resource[Microsoft.Authorization/roleAssignments:PrincipalType] StringEqualsIgnoreCase 'ServicePrincipal'" : ""
limit_sp_user_assignment_delete = local.delegated_sp_ids_string != "" ? "AND @Resource[Microsoft.Authorization/roleAssignments:PrincipalId] ForAnyOfAnyValues:GuidEquals {${local.delegated_sp_ids_string}}" : ""
}
resource "azurerm_role_assignment" "ua_admins" {
role_definition_name = "User Access Administrator"
principal_id = azuread_group.owners.id
scope = var.subscription_kv.id
condition_version = "2.0"
principal_type = "Group"
provider = azurerm.spoke
description = "User Access Admin role assignment for the ${var.subscription_kv.display_name} subscription. This role can grant role assignments to certain roles and groups under specific constraints."
condition = <<-EOT
(
(
!(ActionMatches{'Microsoft.Authorization/roleAssignments/write'})
)
OR
(
@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${local.delegated_role_ids_string}}
AND
(
@Request[Microsoft.Authorization/roleAssignments:PrincipalType] StringEqualsIgnoreCase 'Group'
${local.allowed_group_ids}
${local.allow_service_principal_assignment}
${local.limit_sp_user_assignment}
${local.allow_user_assignment}
${local.allowed_user_ids}
)
)
)
AND
(
(
!(ActionMatches{'Microsoft.Authorization/roleAssignments/delete'})
)
OR
(
@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${local.delegated_role_ids_string}}
AND
(
@Resource[Microsoft.Authorization/roleAssignments:PrincipalType] StringEqualsIgnoreCase 'Group'
${local.allowed_group_ids_delete}
${local.allow_service_principal_assignment_delete}
${local.limit_sp_user_assignment_delete}
${local.allow_user_assignment_delete}
${local.allowed_user_ids_delete}
)
)
)
EOT
} variables.tf variable "subscription_kv" {
type = object({
display_name = string
id = string
})
description = "object pair for /subscriptions/subscription_id and subscription display_name"
}
variable "rbac_allow_user_assignment" {
type = bool
description = "Allows terraform managed identity to assign RBAC roles to user principals, not just service principals or groups"
default = false
}
variable "rbac_allow_any_group_assignment" {
type = bool
description = "Allows terraform managed identity to assign RBAC roles to any group in the tenant, not just a limited set of groups"
default = false
}
variable "rbac_allow_service_principal_assignment" {
type = bool
description = "Allows terraform managed identity to assign RBAC roles to service principals"
default = false
}
variable "rbac_allowed_service_principal_ids" {
type = list(string)
description = "IDs of service principals allowed to be assigned RBAC roles. Leave empty to allow all service principals"
default = []
}
variable "rbac_allowed_user_principal_ids" {
type = list(string)
description = "Only relevant if rbac_allow_user_assignment == true. IDs of user principals allowed to be assigned RBAC roles. Leave empty to allow all user principals"
default = []
}
variable "rbac_extra_allowed_group_principal_ids" {
type = list(string)
description = "IDs of groups allowed to be assigned RBAC roles. Reader, owner and contributor groups for the subscription are always allowed."
default = []
}
terraform {
required_version = "~> 1.5"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.87"
configuration_aliases = [azurerm.spoke]
}
azuread = {
source = "hashicorp/azuread"
version = "~> 2.38"
}
}
}
|
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. |
Is there an existing issue for this?
Community Note
Description
This functionality came out recently in preview https://learn.microsoft.com/en-us/azure/role-based-access-control/delegate-role-assignments-overview?tabs=template#a-more-secure-method-delegate-role-assignments-with-conditions-preview
Via the Azure portal it works as expected, but via the azurerm provider it seems like the new ABAC constraints are not accounted for properly. I am not sure what the reason is.
The below code describes an example in detail. "User A" has unconstrained owner permissions and is attempting to delegate user access administrator with some constraints to the group "contributors" - which User B is a member of.
User B is able to grant role assignments within the constraints if using the Azure portal, but not if using terraform.
New or Affected Resource(s)/Data Source(s)
azurerm_role_assignment
Potential Terraform Configuration
References
No response
The text was updated successfully, but these errors were encountered: