Skip to content
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

feat: role assignments at mg scope #187

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ The following requirements are needed by this module:
The following resources are used by this module:

- [azapi_resource.hierarchy_settings](https://registry.terraform.io/providers/azure/azapi/latest/docs/resources/resource) (resource)
- [azapi_resource.management_group_role_assignments](https://registry.terraform.io/providers/azure/azapi/latest/docs/resources/resource) (resource)
- [azapi_resource.management_groups_level_0](https://registry.terraform.io/providers/azure/azapi/latest/docs/resources/resource) (resource)
- [azapi_resource.management_groups_level_1](https://registry.terraform.io/providers/azure/azapi/latest/docs/resources/resource) (resource)
- [azapi_resource.management_groups_level_2](https://registry.terraform.io/providers/azure/azapi/latest/docs/resources/resource) (resource)
Expand Down Expand Up @@ -260,6 +261,38 @@ object({

Default: `null`

### <a name="input_management_group_role_assignments"></a> [management\_group\_role\_assignments](#input\_management\_group\_role\_assignments)

Description: A map of role assignments to create. The map key is deliberately arbitrary to avoid issues where map keys maybe unknown at plan time.

- `management_group_name` - The name of the management group to assign the role to.
- `role_definition_id_or_name` - The ID or name of the role definition to assign to the principal.
- `principal_id` - The ID of the principal to assign the role to.
- `description` - (Optional) The description of the role assignment.
- `skip_service_principal_aad_check` - (Optional) No effect when using AzAPI.
- `condition` - (Optional) The condition which will be used to scope the role assignment.
- `condition_version` - (Optional) The version of the condition syntax. Leave as `null` if you are not using a condition, if you are then valid values are '2.0'.
- `delegated_managed_identity_resource_id` - (Optional) The delegated Azure Resource Id which contains a Managed Identity. Changing this forces a new resource to be created. This field is only used in cross-tenant scenario.
- `principal_type` - (Optional) The type of the `principal_id`. Possible values are `User`, `Group` and `ServicePrincipal`. It is necessary to explicitly set this attribute when creating role assignments if the principal creating the assignment is constrained by ABAC rules that filters on the PrincipalType attribute.

Type:

```hcl
map(object({
management_group_name = string
role_definition_id_or_name = string
principal_id = string
description = optional(string, null)
skip_service_principal_aad_check = optional(bool, false)
condition = optional(string, null)
condition_version = optional(string, null)
delegated_managed_identity_resource_id = optional(string, null)
principal_type = optional(string, null)
}))
```

Default: `{}`

### <a name="input_override_policy_definition_parameter_assign_permissions_set"></a> [override\_policy\_definition\_parameter\_assign\_permissions\_set](#input\_override\_policy\_definition\_parameter\_assign\_permissions\_set)

Description: This list of objects allows you to set the [`assignPermissions` metadata property](https://learn.microsoft.com/azure/governance/policy/concepts/definition-structure-parameters#parameter-properties) of the supplied definition and parameter names.
Expand Down Expand Up @@ -612,6 +645,15 @@ object({
multiplier = optional(number, null)
randomization_factor = optional(number, null)
}), {})
role_assignments = optional(object({
error_message_regex = optional(list(string), [
"AuthorizationFailed", # Avoids a eventual consistency issue where a recently created management group is not yet available for a GET operation.
])
interval_seconds = optional(number, null)
max_interval_seconds = optional(number, null)
multiplier = optional(number, null)
randomization_factor = optional(number, null)
}), {})
policy_definitions = optional(object({
error_message_regex = optional(list(string), [
"AuthorizationFailed" # Avoids a eventual consistency issue where a recently created management group is not yet available for a GET operation.
Expand Down Expand Up @@ -671,6 +713,15 @@ object({

Default: `{}`

### <a name="input_role_assignment_definition_lookup_enabled"></a> [role\_assignment\_definition\_lookup\_enabled](#input\_role\_assignment\_definition\_lookup\_enabled)

Description: A control to disable the lookup of role definitions when creating role assignments.
If you disable this then all role assignments must be supplied with a `role_definition_id_or_name` that is a valid role definition ID.

Type: `bool`

Default: `true`

### <a name="input_subscription_placement"></a> [subscription\_placement](#input\_subscription\_placement)

Description: A map of subscriptions to place into management groups. The key is deliberately arbitrary to avoid issues with known after apply values. The value is an object:
Expand Down Expand Up @@ -721,6 +772,13 @@ object({
read = optional(string, "5m")
}), {}
)
role_assignment = optional(object({
create = optional(string, "5m")
delete = optional(string, "5m")
update = optional(string, "5m")
read = optional(string, "5m")
}), {}
)
policy_definition = optional(object({
create = optional(string, "5m")
delete = optional(string, "5m")
Expand Down Expand Up @@ -788,7 +846,13 @@ Description: A map of role definition names to their resource ids.

## Modules

No modules.
The following Modules are called:

### <a name="module_avm_interfaces"></a> [avm\_interfaces](#module\_avm\_interfaces)

Source: Azure/avm-utl-interfaces/azure

Version:

<!-- markdownlint-disable-next-line MD041 -->
## Data Collection
Expand Down
14 changes: 14 additions & 0 deletions examples/default/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ This example shows how to deploy the ALZ reference architecture.
# This allows us to get the tenant id
data "azapi_client_config" "current" {}

# Include the additional policies and override archetypes
provider "alz" {
library_overwrite_enabled = true
library_references = [
{
path = "platform/alz",
ref = "2025.02.0"
},
{
custom_url = "${path.root}/lib"
}
]
}

module "alz_architecture" {
source = "../../"
architecture_name = "alz"
Expand Down
14 changes: 14 additions & 0 deletions examples/default/main.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# This allows us to get the tenant id
data "azapi_client_config" "current" {}

# Include the additional policies and override archetypes
provider "alz" {
library_overwrite_enabled = true
library_references = [
{
path = "platform/alz",
ref = "2025.02.0"
},
{
custom_url = "${path.root}/lib"
}
]
}

module "alz_architecture" {
source = "../../"
architecture_name = "alz"
Expand Down
7 changes: 0 additions & 7 deletions examples/default/terraform.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,3 @@ terraform {
}
}
}

provider "alz" {
library_references = [{
path = "platform/alz"
ref = "2025.01.0"
}]
}
Empty file added examples/management/.e2eignore
Empty file.
Empty file.
Empty file.
81 changes: 81 additions & 0 deletions examples/role-assignments/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!-- BEGIN_TF_DOCS -->
# role-assignments

This simplified example shows how to assign roles, both built-in and custom.

```hcl
# This allows us to get the tenant id
data "azapi_client_config" "current" {}

# Include the additional policies and override archetypes
provider "alz" {
library_references = [
{
custom_url = "${path.root}/lib"
}
]
}

module "alz_architecture" {
source = "../../"
architecture_name = "test"
parent_resource_id = data.azapi_client_config.current.tenant_id
location = "northeurope"
management_group_role_assignments = {
test1 = {
principal_type = "User"
role_definition_id_or_name = "Storage Blob Data Contributor"
principal_id = data.azapi_client_config.current.object_id
management_group_name = "test123"
}
test2 = {
principal_type = "User"
role_definition_id_or_name = "Security-Operations (test456)"
principal_id = data.azapi_client_config.current.object_id
management_group_name = "test456"
}
}
}
```

<!-- markdownlint-disable MD033 -->
## Requirements

The following requirements are needed by this module:

- <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) (>= 1.9, < 2.0)

- <a name="requirement_alz"></a> [alz](#requirement\_alz) (~> 0.17)

- <a name="requirement_azapi"></a> [azapi](#requirement\_azapi) (~> 2.0, >= 2.0.1)

## Resources

The following resources are used by this module:

- [azapi_client_config.current](https://registry.terraform.io/providers/azure/azapi/latest/docs/data-sources/client_config) (data source)

<!-- markdownlint-disable MD013 -->
## Required Inputs

No required inputs.

## Optional Inputs

No optional inputs.

## Outputs

No outputs.

## Modules

The following Modules are called:

### <a name="module_alz_architecture"></a> [alz\_architecture](#module\_alz\_architecture)

Source: ../../

Version:

<!-- END_TF_DOCS -->
Empty file.
3 changes: 3 additions & 0 deletions examples/role-assignments/_header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# role-assignments

This simplified example shows how to assign roles, both built-in and custom.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "d3584a79-4f0d-5980-aa3c-7a76ba783b76",
"type": "Microsoft.Authorization/roleDefinitions",
"apiVersion": "2018-01-01-preview",
"properties": {
"roleName": "Security-Operations",
"description": "Security Administrator role with a horizontal view across the entire Azure estate and the Azure Key Vault purge policy.",
"type": "CustomRole",
"permissions": [
{
"actions": [
"*/read",
"*/register/action",
"Microsoft.KeyVault/locations/deletedVaults/purge/action",
"Microsoft.PolicyInsights/*",
"Microsoft.Authorization/policyAssignments/*",
"Microsoft.Authorization/policyDefinitions/*",
"Microsoft.Authorization/policyExemptions/*",
"Microsoft.Authorization/policySetDefinitions/*",
"Microsoft.Insights/alertRules/*",
"Microsoft.Resources/deployments/*",
"Microsoft.Security/*",
"Microsoft.Support/*"
],
"notActions": [],
"dataActions": [],
"notDataActions": []
}
],
"assignableScopes": [
"${current_scope_resource_id}"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: test
role_definitions:
- Security-Operations
14 changes: 14 additions & 0 deletions examples/role-assignments/lib/test.alz_architecture_definition.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
management_groups:
- archetypes:
- empty
display_name: test123
exists: false
id: test123
parent_id: null
- archetypes:
- test
display_name: test456
exists: false
id: test456
parent_id: null
name: test
32 changes: 32 additions & 0 deletions examples/role-assignments/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# This allows us to get the tenant id
data "azapi_client_config" "current" {}

# Include the additional policies and override archetypes
provider "alz" {
library_references = [
{
custom_url = "${path.root}/lib"
}
]
}

module "alz_architecture" {
source = "../../"
architecture_name = "test"
parent_resource_id = data.azapi_client_config.current.tenant_id
location = "northeurope"
management_group_role_assignments = {
test1 = {
principal_type = "User"
role_definition_id_or_name = "Storage Blob Data Contributor"
principal_id = data.azapi_client_config.current.object_id
management_group_name = "test123"
}
test2 = {
principal_type = "User"
role_definition_id_or_name = "Security-Operations (test456)"
principal_id = data.azapi_client_config.current.object_id
management_group_name = "test456"
}
}
}
13 changes: 13 additions & 0 deletions examples/role-assignments/terraform.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
terraform {
required_version = ">= 1.9, < 2.0"
required_providers {
alz = {
source = "azure/alz"
version = "~> 0.17"
}
azapi = {
source = "azure/azapi"
version = "~> 2.0, >= 2.0.1"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
],
"display_name": "${prefix} ALZ root",
"exists": false,
"id": "${prefix}-alzroot",
"id": "${prefix}-alz",
"parent_id": null
},
{
Expand Down Expand Up @@ -49,11 +49,11 @@
},
{
"archetypes": [
"sandboxes"
"sandbox"
],
"display_name": "${prefix} Sandboxes",
"display_name": "${prefix} Sandbox",
"exists": false,
"id": "${prefix}-sandboxes",
"id": "${prefix}-sandbox",
"parent_id": "${prefix}-alzroot"
},
{
Expand Down
Loading
Loading