Skip to content

Commit

Permalink
Add documentation
Browse files Browse the repository at this point in the history
Rename some fields to make more sense
  • Loading branch information
oWretch committed Mar 5, 2024
1 parent 2acc9de commit 7e35ecb
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 25 deletions.
173 changes: 173 additions & 0 deletions docs/resources/group_role_management_policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
---
subcategory: "Policies"
---

# Resource: azuread_group_role_management_policy

Manage a role policy for an Azure AD group.

## API Permissions

The following API permissions are required in order to use this resource.

When authenticated with a service principal, this resource requires the `RoleManagementPolicy.ReadWrite.AzureADGroup` Microsoft Graph API permissions.

When authenticated with a user principal, this resource requires `Global Administrator` directory role, or the `Privileged Role Administrator` role in Identity Governance.

## Example Usage

```terraform
resource "azuread_group" "example" {
display_name = "group-name"
security_enabled = true
}
resource "azuread_user" "member" {
user_principal_name = "jdoe@hashicorp.com"
display_name = "J. Doe"
mail_nickname = "jdoe"
password = "SecretP@sswd99!"
}
resource "azuread_group_role_management_policy" "example" {
object_id = azuread_group.example.id
assignment_type = "member"
eligible_assignment_rules {
expiration_required = false
}
active_assignment_rules {
expire_after = "P365D"
}
notification_rules {
approver_notifications {
eligible_assignments {
notification_level = "Critical"
default_recipients = false
additional_recipients = [
"someone@example.com",
"someone.else@example.com",
]
}
}
}
}
```

## Argument Reference

* `object_id` - (Required) The Object ID of the Azure AD group for which the policy applies.
* `assignment_type` - (Required) The type of assignment this policy coveres. Can be either `member` or `owner`.
* `active_assignment_rules` - (Optional) An `active_assignment_rules` block as defined below.
* `activation_rules` - (Optional) An `activation_rules` block as defined below.
* `eligible_assignment_rules` - (Optional) An `eligible_assignment_rules` block as defined below.
* `notification_rules` - (Optional) An `notification_rules` block as defined below.

---

An `active_assignment_rules` block supports the following:

* `expiration_required` - (Optional) Must an assignment have an expiry date. `false` allows permanent assignment.
* `expire_after` - (Optional) The maximum length of time an assignment can be valid, as an ISO8601 duration. Permitted values: `P15D`, `P30D`, `P90D`, `P180D`, or `P365D`.
* `require_multifactor_authentication` - (Optional) Is multi-factor authentication required to create new assignments.
* `require_justification` - (Optional) Is a justification required to create new assignments.
* `require_ticket_info` - (Optional) Is ticket information required to create new assignments.

One of `expiration_required` or `expire_after` must be provided.

---

An `activation_rules` block supports the following:

* `maximum_duration` - (Optional) The maximum length of time an activated role can be valid, in an IS)8601 Duration format (e.g. `PT8H`). Valid range is `PT30M` to `PT23H30M`, in 30 minute increments, or `PT1D`.
* `approval_stages` - (Optional) An `approval_stages` block as defined below.
* `require_approval` - (Optional) Is approval required for activation. If `true` an `approval_stages` block must be provided.
* `required_conditional_access_authentication_context` - (Optional) The Entra ID Conditional Access context that must be present for activation. Conflicts with `require_multifactor_authentication`.
* `require_multifactor_authentication` - (Optional) Is multi-factor authentication required to activate the role. Conflicts with `required_conditional_access_authentication_context`.
* `require_justification` - (Optional) Is a justification required during activation of the role.
* `require_ticket_info` - (Optional) Is ticket information requrired during activation of the role.

---

An `admin_notifications` block supports the following:

* `activations` An optional `notification_settings` block as defined below for configuring notifications to adminstrators of role activations.
* `active_assignments` An optional `notification_settings` block as defined below for configuring notifications to adminstrators of new active assignments.
* `eligible_assignments` An optional `notification_settings` block as defined below for configuring notifications to adminstrators of new eligible assignments.

---

An `approval_stages` block supports the following:

* One or more `primary_approver` blocks as defined below.

---

An `approver_notifications` block supports the following:

* `activations` - An optional `notification_settings` block as defined below for configuring notifications to approvers of new activation request.
* `active_assignments` - An optional `notification_settings` block as defined below for configuring notifications to approvers of new active assignment requests.
* `eligible_assignments` - An optional `notification_settings` block as defined below for configuring notifications to approvers of new eligible assignment requests.

---

An `assignee_notifications` block supports the following:

* `activations` - An optional `notification_settings` block as defined below for configuring notifications to assignees of role activations.
* `active_assignments` - An optional `notification_settings` block as defined below for configuring notifications to assignees of new active assignments.
* `eligible_assignments` - An optional `notification_settings` block as defined below for configuring notifications to assignees of new eligible assignments.

---

An `eligible_assignment_rules` block supports the following:

* `expiration_required`- Must an assignment have an expiry date. `false` allows permanent assignment.
* `expire_after` - The maximum length of time an assignment can be valid, as an ISO8601 duration. Permitted values: `P15D`, `P30D`, `P90D`, `P180D`, or `P365D`.

One of `expiration_required` or `expire_after` must be provided.

---

A `notification_rules` block supports the following:

* `admin_notifications` - (Optional) An `admin_notifications` block as defined above.
* `approver_notifications` - (Optional) An `approver_notifications` block as defined above.
* `assignee_notifications` - (Optional) An `assignee_notifications` block as defined above.

---

A `notification_settings` block supports the following:

* `notification_level` - (Required) What level of notifications should be sent. Options are `All` or `Critical`.
* `default_recipients` - (Required) Should the default recipients receive these notifications.
* `additional_recipients` - (Optional) A list of additional email addresses that will receive these notifications.

---

A `primary_approver` block supports the following:

* `user_id` - (Required) The ID of the user or group which will act as an approver.
* `group_id` - (Required) The ID of the user or group which will act as an approver.
* `description` - (Required) A description of the approver.

Only one of `user_id` or `group_id` can be supplied per block. Multiple approvers can be set by providing multiple `primary_approver` blocks.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:

* `id` (String) The ID of this policy.
* `display_name` (String) The display name of this policy.
* `description` (String) The description of this policy.

## Import

An assignment schedule can be imported using the ID, e.g.

```shell
terraform import azuread_privileged_access_group_eligibility_schedule_request.example Group_00000000-0000-0000-0000-000000000000_00000000-0000-0000-0000-000000000000
```

Because these policies are created automatically by Entra ID, they will auto-import on first use.
58 changes: 35 additions & 23 deletions internal/services/policies/group_role_management_policy_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type GroupRoleManagementPolicyActiveAssignmentRules struct {
ExpireAfter string `tfschema:"expire_after"`
RequireMultiFactorAuth bool `tfschema:"require_multifactor_authentication"`
RequireJustification bool `tfschema:"require_justification"`
RequireTicketInfo bool `tfschema:"require_ticket_info"`
}

type GroupRoleManagementPolicyEligibleAssignmentRules struct {
Expand All @@ -44,7 +45,7 @@ type GroupRoleManagementPolicyActivationRules struct {
MaximumDuration string `tfschema:"maximum_duration"`
RequireApproval bool `tfschema:"require_approval"`
ApprovalStages []GroupRoleManagementPolicyApprovalStage `tfschema:"approval_stages"`
RequireConditionalAccessContext string `tfschema:"require_conditional_access_authentication_context"`
RequireConditionalAccessContext string `tfschema:"required_conditional_access_authentication_context"`
RequireMultiFactorAuth bool `tfschema:"require_multifactor_authentication"`
RequireJustification bool `tfschema:"require_justification"`
RequireTicketInfo bool `tfschema:"require_ticket_info"`
Expand All @@ -56,8 +57,8 @@ type GroupRoleManagementPolicyApprovalStage struct {

type GroupRoleManagementPolicyApprover struct {
Description string `tfschema:"description"`
ObjectId string `tfschema:"object_id"`
ObjectType string `tfschema:"object_type"`
GroupId string `tfschema:"group_id"`
UserId string `tfschema:"user_id"`
}

type GroupRoleManagementPolicyNotificationRules struct {
Expand Down Expand Up @@ -178,6 +179,13 @@ func (r GroupRoleManagementPolicyResource) Arguments() map[string]*pluginsdk.Sch
Optional: true,
Computed: true,
},

"require_ticket_info": {
Description: "Whether ticket information is required to make an assignment",
Type: pluginsdk.TypeBool,
Optional: true,
Computed: true,
},
},
},
},
Expand Down Expand Up @@ -231,18 +239,18 @@ func (r GroupRoleManagementPolicyResource) Arguments() map[string]*pluginsdk.Sch
ValidateDiagFunc: validation.ValidateDiag(validation.StringIsNotEmpty),
},

"object_id": {
Description: "The ID of the useror group to act as an approver",
"group_id": {
Description: "The ID of the group to act as an approver",
Type: pluginsdk.TypeString,
Required: true,
ValidateDiagFunc: validation.ValidateDiag(validation.IsUUID),
},

"object_type": {
Description: "The type of the object to act as an approver",
"user_id": {
Description: "The ID of the user to act as an approver",
Type: pluginsdk.TypeString,
Required: true,
ValidateDiagFunc: validation.ValidateDiag(validation.StringInSlice([]string{"user", "group"}, false)),
ValidateDiagFunc: validation.ValidateDiag(validation.IsUUID),
},
},
},
Expand All @@ -251,7 +259,7 @@ func (r GroupRoleManagementPolicyResource) Arguments() map[string]*pluginsdk.Sch
},
},

"require_conditional_access_authentication_context": {
"required_conditional_access_authentication_context": {
Description: "Whether a conditional access context is required during activation",
Type: pluginsdk.TypeString,
Optional: true,
Expand All @@ -265,7 +273,7 @@ func (r GroupRoleManagementPolicyResource) Arguments() map[string]*pluginsdk.Sch
Type: pluginsdk.TypeBool,
Optional: true,
Computed: true,
ConflictsWith: []string{"activation_rules.0.require_conditional_access_authentication_context"},
ConflictsWith: []string{"activation_rules.0.required_conditional_access_authentication_context"},
},

"require_justification": {
Expand Down Expand Up @@ -779,14 +787,12 @@ func (r GroupRoleManagementPolicyResource) Read() sdk.ResourceFunc {
case *approver.ODataType == "#microsoft.graph.singleUser":
primaryApprovers = append(primaryApprovers, GroupRoleManagementPolicyApprover{
Description: *approver.Description,
ObjectId: *approver.UserID,
ObjectType: "user",
UserId: *approver.UserID,
})
case *approver.ODataType == "#microsoft.graph.groupMembers":
primaryApprovers = append(primaryApprovers, GroupRoleManagementPolicyApprover{
Description: *approver.Description,
ObjectId: *approver.GroupID,
ObjectType: "group",
GroupId: *approver.GroupID,
})
default:
return fmt.Errorf("unknown approver type: %s", *approver.ODataType)
Expand Down Expand Up @@ -991,6 +997,9 @@ func buildPolicyForUpdate(metadata *sdk.ResourceMetaData, policy *msgraph.Unifie
if model.ActiveAssignmentRules[0].RequireJustification {
enabledRules = append(enabledRules, "Justification")
}
if model.ActiveAssignmentRules[0].RequireTicketInfo {
enabledRules = append(enabledRules, "Ticketing")
}

rule := msgraph.UnifiedRoleManagementPolicyRule{
ID: policyRules["Enablement_Admin_Assignment"].ID,
Expand Down Expand Up @@ -1050,20 +1059,23 @@ func buildPolicyForUpdate(metadata *sdk.ResourceMetaData, policy *msgraph.Unifie
for _, stage := range model.ActivationRules[0].ApprovalStages {
primaryApprovers := make([]msgraph.UserSet, 0)
for _, approver := range stage.PrimaryApprovers {
if approver.ObjectType == "user" {
if approver.UserId != "" && approver.GroupId != "" {
return nil, fmt.Errorf("Only one of user_id or group_id can be set in a block")
} else if approver.UserId == "" && approver.GroupId == "" {
return nil, fmt.Errorf("One of user_id or group_id must be set in a block")
}
if approver.UserId != "" {
primaryApprovers = append(primaryApprovers, msgraph.UserSet{
ODataType: pointer.To("#microsoft.graph.singleUser"),
UserID: &approver.ObjectId,
UserID: &approver.UserId,
Description: &approver.Description,
})
} else if approver.ObjectType == "group" {
} else if approver.GroupId != "" {
primaryApprovers = append(primaryApprovers, msgraph.UserSet{
ODataType: pointer.To("#microsoft.graph.groupMembers"),
GroupID: &approver.ObjectId,
ODataType: pointer.To("#microsoft.graph.singleUser"),
GroupID: &approver.GroupId,
Description: &approver.Description,
})
} else {
return nil, fmt.Errorf("either user_id or group_id must be set")
}
}

Expand All @@ -1087,11 +1099,11 @@ func buildPolicyForUpdate(metadata *sdk.ResourceMetaData, policy *msgraph.Unifie
updatedRules = append(updatedRules, rule)
}

if metadata.ResourceData.HasChange("activation_rules.0.require_conditional_access_authentication_context") {
if metadata.ResourceData.HasChange("activation_rules.0.required_conditional_access_authentication_context") {
isEnabled := policyRules["AuthenticationContext_EndUser_Assignment"].IsEnabled
claimValue := policyRules["AuthenticationContext_EndUser_Assignment"].ClaimValue

if _, set := metadata.ResourceData.GetOk("activation_rules.0.require_conditional_access_authentication_context"); set {
if _, set := metadata.ResourceData.GetOk("activation_rules.0.required_conditional_access_authentication_context"); set {
isEnabled = pointer.To(true)
claimValue = pointer.To(model.ActivationRules[0].RequireConditionalAccessContext)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,8 @@ resource "azuread_group_role_management_policy" "test" {
require_approval = true
approval_stages {
primary_approver {
user_id = azuread_user.approver.object_id
description = azuread_user.approver.display_name
object_id = azuread_user.approver.object_id
object_type = "user"
}
}
}
Expand Down

0 comments on commit 7e35ecb

Please sign in to comment.