diff --git a/modules/azuread-group/.terraform-docs.yml b/modules/azuread-group/.terraform-docs.yml new file mode 100644 index 000000000..3a69365ff --- /dev/null +++ b/modules/azuread-group/.terraform-docs.yml @@ -0,0 +1,48 @@ +formatter: "markdown" + +version: "" + +header-from: docs/header.md +footer-from: docs/footer.md + +recursive: + enabled: false + path: modules + include-main: true + +sections: + hide: [] + show: [] + +content: "" + +output: + file: "README.md" + mode: inject + template: |- + + {{ .Content }} + + +output-values: + enabled: false + from: "" + +sort: + enabled: true + by: name + +settings: + anchor: true + color: true + default: true + description: false + escape: true + hide-empty: false + html: true + indent: 2 + lockfile: true + read-comments: true + required: true + sensitive: true + type: true diff --git a/modules/azuread-group/README.md b/modules/azuread-group/README.md index fcbd13ac7..cd79cc4cb 100644 --- a/modules/azuread-group/README.md +++ b/modules/azuread-group/README.md @@ -1,22 +1,13 @@ -## Requirements + +# Azure AD Group Module -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.0 | -| [azuread](#requirement\_azuread) | ~> 2.52.0 | -| [azurerm](#requirement\_azurerm) | = 4.16.0 | +This Terraform module creates and manages Azure Active Directory (AD) groups, including role assignments, PIM (Privileged Identity Management), owners, and members. It supports configuration via YAML for easier management and reproducibility. ### Provisioner actor and permissions -The provisioner actor must be a Service Principal due to a bug in the provider. For more details, check this [issue](https://github.com/hashicorp/terraform-provider-azuread/issues/1386). - -To make it work, you need to grant permissions to the Service Principal using a PowerShell console. You can open a terminal in the Azure console panel. +> The provisioner actor must be a Service Principal due to a bug in the provider. See [issue #1386](https://github.com/hashicorp/terraform-provider-azuread/issues/1386). -![image](https://github.com/prefapp/tfm/assets/91343444/5096b774-1cc9-4ab2-88c1-0d246d916955) - -To execute the following scripts, you should act as Global Administrator. - -Execute the following scripts in the powershell terminal. +To make it work, you need to grant permissions to the Service Principal using a PowerShell console as a Global Administrator. Example scripts: **1. PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup** ```powershell @@ -80,6 +71,55 @@ $GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$GraphAp $AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName -and $_.AllowedMemberTypes -contains "Application"}; New-AzureAdServiceAppRoleAssignment -ObjectId $MSI -PrincipalId $MSI -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id ``` +## Features +- Create Azure AD groups with custom name and description +- Assign directory and subscription roles +- Manage group owners and members (users, service principals) +- Enable and configure PIM for groups +- YAML-driven configuration for scalable examples + +## Minimal usage example + +**values.yaml** +```yaml +name: example-group-1 +description: Minimal test group +members: + - type: user + email: user-2@example.com +directory_roles: [] +subscription_roles: [] +``` + +**main.tf** +```hcl +locals { + values = yamldecode(file("./values.yaml")) +} + +module "azuread-group" { + source = "../.." + name = local.values.name + description = local.values.description + members = local.values.members + directory_roles = local.values.directory_roles + subscription_roles = local.values.subscription_roles +} +``` + +> For a more complete example configuration, see the `_examples/with_yaml_file` folder in this repository. Ensure that provider versions in the example align with the Requirements section above. +## Known issues +- Removing a `azuread_privileged_access_group_eligibility_schedule` resource may crash the provider ([issue #1399](https://github.com/hashicorp/terraform-provider-azuread/issues/1399)). +- Updating a `azuread_privileged_access_group_eligibility_schedule` may show a wrong log error; sometimes you must remove and recreate the resource ([issue #1412](https://github.com/hashicorp/terraform-provider-azuread/issues/1412)). + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.7.0 | +| [azuread](#requirement\_azuread) | ~> 2.52.0 | +| [azurerm](#requirement\_azurerm) | = 4.16.0 | + ## Providers | Name | Version | @@ -87,19 +127,24 @@ $AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $Permiss | [azuread](#provider\_azuread) | ~> 2.52.0 | | [azurerm](#provider\_azurerm) | = 4.16.0 | +## Modules + +No modules. + ## Resources | Name | Type | |------|------| | [azuread_directory_role_assignment.this](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/directory_role_assignment) | resource | | [azuread_group.this](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/group) | resource | +| [azuread_group_member.this](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/group_member) | resource | | [azuread_group_role_management_policy.members](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/group_role_management_policy) | resource | | [azuread_group_role_management_policy.owners](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/group_role_management_policy) | resource | | [azuread_privileged_access_group_assignment_schedule.members](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/privileged_access_group_assignment_schedule) | resource | | [azuread_privileged_access_group_assignment_schedule.owners](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/privileged_access_group_assignment_schedule) | resource | | [azuread_privileged_access_group_eligibility_schedule.members](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/privileged_access_group_eligibility_schedule) | resource | | [azuread_privileged_access_group_eligibility_schedule.owners](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/privileged_access_group_eligibility_schedule) | resource | -| [azurerm_role_assignment.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) | resource | +| [azurerm_role_assignment.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.16.0/docs/resources/role_assignment) | resource | | [azuread_directory_roles.current](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/directory_roles) | data source | | [azuread_groups.members_from_display_names](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/groups) | data source | | [azuread_groups.members_from_object_ids](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/groups) | data source | @@ -119,26 +164,35 @@ $AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $Permiss | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [assignable\_to\_role](#input\_assignable\_to\_role) | Indicates if the group is assignable to a role | `bool` | `true` | no | -| [enable\_pim](#input\_enable\_pim) | Enable PIM for groups | `bool` | `false` | no | | [default\_pim\_duration](#input\_default\_pim\_duration) | The default duration for PIM role assignments | `string` | `"12"` | no | | [description](#input\_description) | The description of the Azure AD group | `string` | n/a | yes | -| [directory\_roles](#input\_directory\_roles) | The list of directory roles to assign to the group |
list(object({

role_name = string

}))
| n/a | yes | +| [directory\_roles](#input\_directory\_roles) | The list of directory roles to assign to the group |
list(object({
role_name = string
}))
| n/a | yes | +| [enable\_pim](#input\_enable\_pim) | Enable Privileged Identity Management (PIM) for the group | `bool` | `false` | no | | [expiration\_required](#input\_expiration\_required) | Indicates if the expiration is required for the PIM eligible role assignments | `bool` | `false` | no | -| [members](#input\_members) | The list of Azure AD users, groups or service principals to assign to the group |
list(object({

type = string

email = optional(string)

display_name = optional(string)

object_id = optional(string)

pim = optional(object({

type = optional(string)

expiration_hours = optional(string)

permanent_assignment = optional(bool)
}),
{
type = "disabled"

permanent_assignment = false
})
}))
| n/a | yes | +| [members](#input\_members) | The list of Azure AD users, groups or service principals to assign to the group |
list(object({
type = string
email = optional(string)
display_name = optional(string)
object_id = optional(string)
pim = optional(object({
type = optional(string)
expiration_hours = optional(string)
permanent_assignment = optional(bool)
}),
{
type = "disabled"
permanent_assignment = false
})
}))
| `[]` | no | | [name](#input\_name) | The name of the Azure AD group | `string` | n/a | yes | -| [owners](#input\_owners) | The list of Azure AD users or service principal owners of the group |
list(object({

type = string

email = optional(string)

display_name = optional(string)

object_id = optional(string)

pim = optional(object({

type = optional(string)

expiration_hours = optional(string)

permanent_assignment = optional(bool)

}),
{
expiration_hours = null

type = "disabled"

permanent_assignment = false

})

}))
| `[]` | no | +| [owners](#input\_owners) | The list of Azure AD users or service principal owners of the group |
list(object({
type = string
email = optional(string)
display_name = optional(string)
object_id = optional(string)
pim = optional(object({
type = optional(string)
expiration_hours = optional(string)
permanent_assignment = optional(bool)
}),
{
expiration_hours = null
type = "disabled"
permanent_assignment = false
})
}))
| `[]` | no | | [pim\_maximum\_duration\_hours](#input\_pim\_maximum\_duration\_hours) | The maximum duration for PIM role assignments | `string` | `"8"` | no | | [pim\_require\_justification](#input\_pim\_require\_justification) | Indicates if the justification is required for the eligible PIM role assignments | `bool` | `true` | no | | [subscription](#input\_subscription) | The subscription id | `string` | `null` | no | -| [subscription\_roles](#input\_subscription\_roles) | The list of built-in roles to assign to the group |
list(object({

role_name = string

resources_scopes = list(string)

}))
| n/a | yes | +| [subscription\_roles](#input\_subscription\_roles) | The list of built-in roles to assign to the group |
list(object({
role_name = string
resources_scopes = list(string)
}))
| n/a | yes | ## Outputs | Name | Description | |------|-------------| -| [group\_id](#output\_group\_id) | group id | +| [group\_id](#output\_group\_id) | n/a | + +## Examples -### Known issues +For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azuread-group/_examples): + +- [basic](https://github.com/prefapp/tfm/tree/main/modules/azuread-group/_examples) - Example showing group creation, members and PIM configuration. + +## Resources +- [Terraform AzureAD Provider: group](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/group) +- [Terraform AzureAD Provider: privileged access group](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/privileged_access_group_assignment_schedule) -1. Sometimes, if you try to remove a `azuread_privileged_access_group_eligibility_schedule` resource, the provider crashes, we are waiting for a fix. Check the [issue](https://github.com/hashicorp/terraform-provider-azuread/issues/1399). -2. If you want to update a `azuread_privileged_access_group_eligibility_schedule`, the provider shows a wrong log error. You should remove from terraform the resource and then recreate it. But sometimes has conflicts with the previous point. Check the [issue](https://github.com/hashicorp/terraform-provider-azuread/issues/1412). +## Support +For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues). + \ No newline at end of file diff --git a/modules/azuread-group/docs/footer.md b/modules/azuread-group/docs/footer.md new file mode 100644 index 000000000..11949ea61 --- /dev/null +++ b/modules/azuread-group/docs/footer.md @@ -0,0 +1,12 @@ +## Examples + +For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azuread-group/_examples): + +- [basic](https://github.com/prefapp/tfm/tree/main/modules/azuread-group/_examples) - Example showing group creation, members and PIM configuration. + +## Resources +- [Terraform AzureAD Provider: group](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/group) +- [Terraform AzureAD Provider: privileged access group](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/privileged_access_group_assignment_schedule) + +## Support +For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues). \ No newline at end of file diff --git a/modules/azuread-group/docs/header.md b/modules/azuread-group/docs/header.md new file mode 100644 index 000000000..05c9e62b2 --- /dev/null +++ b/modules/azuread-group/docs/header.md @@ -0,0 +1,113 @@ +# Azure AD Group Module + +This Terraform module creates and manages Azure Active Directory (AD) groups, including role assignments, PIM (Privileged Identity Management), owners, and members. It supports configuration via YAML for easier management and reproducibility. + + +### Provisioner actor and permissions + +> The provisioner actor must be a Service Principal due to a bug in the provider. See [issue #1386](https://github.com/hashicorp/terraform-provider-azuread/issues/1386). + +To make it work, you need to grant permissions to the Service Principal using a PowerShell console as a Global Administrator. Example scripts: + +**1. PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup** +```powershell +$TenantID="" + +$GraphAppId = "00000003-0000-0000-c000-000000000000" + +$MSI="" + +$PermissionName = "PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup" + +# Install the module + +Install-Module AzureAD + +Connect-AzureAD -TenantId $TenantID + +$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$GraphAppId'" + +$AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName -and $_.AllowedMemberTypes -contains "Application"}; New-AzureAdServiceAppRoleAssignment -ObjectId $MSI -PrincipalId $MSI -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id +``` +**2. RoleManagementPolicy.ReadWrite.AzureADGroup** +```powershell +$TenantID="" + +$GraphAppId = "00000003-0000-0000-c000-000000000000" + +$MSI="" + +$PermissionName = "RoleManagementPolicy.ReadWrite.AzureADGroup" + +# Install the module + +Install-Module AzureAD + +Connect-AzureAD -TenantId $TenantID + +$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$GraphAppId'" + +$AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName -and $_.AllowedMemberTypes -contains "Application"}; New-AzureAdServiceAppRoleAssignment -ObjectId $MSI -PrincipalId $MSI -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id +``` + +**3. PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup** +```powershell +$TenantID="" + +$GraphAppId = "00000003-0000-0000-c000-000000000000" + +$MSI="" + +$PermissionName = "PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup" + +# Install the module + +Install-Module AzureAD + +Connect-AzureAD -TenantId $TenantID + +$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$GraphAppId'" + +$AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName -and $_.AllowedMemberTypes -contains "Application"}; New-AzureAdServiceAppRoleAssignment -ObjectId $MSI -PrincipalId $MSI -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id +``` + +## Features +- Create Azure AD groups with custom name and description +- Assign directory and subscription roles +- Manage group owners and members (users, service principals) +- Enable and configure PIM for groups +- YAML-driven configuration for scalable examples + +## Minimal usage example + +**values.yaml** +```yaml +name: example-group-1 +description: Minimal test group +members: + - type: user + email: user-2@example.com +directory_roles: [] +subscription_roles: [] +``` + +**main.tf** +```hcl +locals { + values = yamldecode(file("./values.yaml")) +} + +module "azuread-group" { + source = "../.." + name = local.values.name + description = local.values.description + members = local.values.members + directory_roles = local.values.directory_roles + subscription_roles = local.values.subscription_roles +} +``` + +> For a more complete example configuration, see the `_examples/with_yaml_file` folder in this repository. Ensure that provider versions in the example align with the Requirements section above. +## Known issues +- Removing a `azuread_privileged_access_group_eligibility_schedule` resource may crash the provider ([issue #1399](https://github.com/hashicorp/terraform-provider-azuread/issues/1399)). +- Updating a `azuread_privileged_access_group_eligibility_schedule` may show a wrong log error; sometimes you must remove and recreate the resource ([issue #1412](https://github.com/hashicorp/terraform-provider-azuread/issues/1412)). \ No newline at end of file