Search code examples
azureterraformrbacazure-policy

Azure Policy to deny role assignments for specific role definition ids (Roles)


Attempting to configure what Azure Role definitions Ids (roles) are allowed to be assigned, via role assignments, utilizing Azure Policy.

The below policies all create with out error, but Azure role assignments are still possible for all roles despite this policy being created / assigned.

I have tried parameter value snytax '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' as well as just the role id 'b24988ac-6180-42a0-ab88-20f7382dd24c'

Nothing seems to matter, when it comes to the policy actually preventing role assignments

I have hard coded values, as well as tried parameters

Policy following this thread, which is not preventing any role assignments:

Azure Policy to restrict role based access control(IAM) to users at Resource group level in Azure

resource "azurerm_policy_definition" "allowedRoleAssignments" {
  name                  = "${var.project_ident}-${var.cs_env_ident}-allowedRoleAssignments"
  policy_type           = "Custom"
  mode                  = "Indexed"
  display_name          = "${var.project_ident}-${var.cs_env_ident}-allowedRoleAssignments"
  management_group_name = var.mgmtGroupName

  metadata = <<METADATA
    {
        "category": "General"
    }
METADATA

  policy_rule = <<POLICY_RULE
  {
        "if": {
            "allOf": [
                {
                    "field": "type",
                    "equals": "Microsoft.Authorization/roleAssignments"
                },
                {
                    "not": {
                        "field": "Microsoft.Authorization/roleAssignments/roleDefinitionId",
                        "in": "[parameters('roleDefinitionIds')]"
                    }
                }
            ]
        },
        "then": {
            "effect": "deny"
        }
    }
POLICY_RULE

  parameters = <<PARAMETERS
    {
        "roleDefinitionIds": {
            "type": "Array",
            "metadata": {
                "displayName": "roleDefinitionIds",
                "description": "This policy defines a blacklist of role definitions that cannot be used in IAM, for role assignments"
            }
        }
    }
PARAMETERS
}

Initiative Parameters:

  policy_definition_reference {
    policy_definition_id = azurerm_policy_definition.allowedRoleAssignments.id
    parameters = {
        roleDefinitionIds = "[parameters('roleDefinitionIds')]"
  }
}

Policy assignment:

resource "azurerm_policy_assignment" "set-assignment-1" {
  name                 = "${var.cs_env_ident}-sec-controls" 
  scope                = var.policy_assignment_scope
  description          = "policy set definition assignment to specified management groups"
  display_name         = "${var.project_ident}-${var.cs_env_ident}-sec-controls"
  policy_definition_id = var.policy_set_definition_id
  identity { type = "SystemAssigned" }
  location             = var.location
  
  parameters = <<PARAMETERS
    {
    "roleDefinitionIds": {
      "value": ${jsonencode(var.roleDefinitionIds)}
    }
  }
PARAMETERS
}

Parameters passed in Policy Assignment, via Terraform Variable:

variable "roleDefinitionIds" {
  description = "List of allowed role definition Ids"
  default = [
    "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4"
  ] 
}

Policies attempted per other threads which have similar, but different logic to achieve the same goal, but also will not actually prevent role assignments:

Very helpful guide, made by an Azure employee, but again, the Policy does not restrict any role assignments

https://blog.soft-cor.com/empowering-developer-teams-to-manage-their-own-azure-rbac-permissions-in-highly-regulated-industries/

Other similar threads Azure custom role: authorize role assignment for a specific set of roles

 resource "azurerm_policy_definition" "allowedRoleAssignments" {
      name                  = "${var.project_ident}-${var.cs_env_ident}-allowedRoleAssignments"
      policy_type           = "Custom"
      mode                  = "Indexed"
      display_name          = "${var.project_ident}-${var.cs_env_ident}-allowedRoleAssignments"
      management_group_name = var.mgmtGroupName
    
      metadata = <<METADATA
        {
            "category": "General"
        }
    METADATA
    
      policy_rule = <<POLICY_RULE
        {
            "if": {
                "allOf": [
                    {
                        "field": "type",
                        "equals": "Microsoft.Authorization/roleAssignments"
                    },
                    {
                        "value": "[last(split(field('Microsoft.Authorization/roleAssignments/roleDefinitionId'),'/'))]",
                        "notIn": "[parameters('roleDefinitionIds')]"
                    }
                ]
            },
            "then": {
                "effect": "Deny"
            }
        }
    POLICY_RULE
    
      parameters = <<PARAMETERS
        {
            "roleDefinitionIds": {
                "type": "Array",
                "metadata": {
                    "displayName": "roleDefinitionIds",
                    "description": "This policy defines a blacklist of role definitions that cannot be used in IAM, for role assignments"
                }
            }
        }
    PARAMETERS
    }

Any help would be much appreciated. The policies do not fail on creation, and seem to logically make sense.

I do not understand why no matter if it is created as a whitelist, or blacklist, role assignments do not fail

I am creating and assigning these policies on a management group, so validate using a subscription / resources within the management group.

I have tried an array of role definition ids, single definitions ids, nothing successfully Denys a matching role assignment per policy.


Solution

  • This has been resolved after much testing and reading. The issue is that Azure RBAC role definition IDs are not a resource and are not tagged, thus the issue was in the policy Mode:

    Tagged resources and locations are processed with Indexed Policy Mode

    mode                  = "Indexed"
    

    To solve this issue, the policy Mode needs to be set to "All'

    mode                  = "All"
    

    Other wise, i have provided a complete working solution within this question!

    Cheers