microsoft / microsoft/terraform-provider-msgraph
`msgraph_resource` for access review definitions shows perpetual drift because Graph normalizes `scope.query` and `reviewers[].query`
@QixiaLu is already working on this.
Since Sep 14, 2026.
- Dominant language
- Go
- Stars
- 65
- Forks
- 25
- Avg merge
- 3d 10h
- Merged PRs (30d)
- 6
Description
Summary
When managing identityGovernance/accessReviews/definitions via msgraph_resource, Terraform repeatedly plans in-place updates although the resource is already configured correctly.
The root cause seems to be that Microsoft Graph returns normalized query values on GET that differ from the values accepted on PUT.
Environment
- Terraform:
1.14.6 - Provider:
registry.terraform.io/microsoft/msgraph0.3.0 - API resource:
identityGovernance/accessReviews/definitions - Update method:
PUT
Reproduction
- Create an access review definition using
msgraph_resourcebody values like:scope.query = "/groups/<group-id>/transitiveMembers"reviewers[0].query = "/groups/<admin-group-id>/transitiveMembers"
- Run
terraform apply. - Run
terraform planagain.
Actual behavior
Terraform plans updates for msgraph_resource.access_review_definition every time.
Diff example:
- Config/PUT style:
/groups/<id>/transitiveMembers
- Read/GET style returned by Graph:
/v1.0/groups/<id>/transitiveMembers/microsoft.graph.user
Observed drift fields:
body.scope.querybody.reviewers[0].query
Expected behavior
Provider should suppress diffs for semantically equivalent Graph query forms (canonicalization), so repeated plan runs are stable after apply.
Evidence from Graph GET
For the same access review definitions, Graph returns:
scope.query = "/v1.0/groups/<id>/transitiveMembers/microsoft.graph.user"reviewers[0].query = "/v1.0/groups/<id>/transitiveMembers/microsoft.graph.user"
Minimal Terraform example
resource "msgraph_resource" "access_review_definition" {
url = "identityGovernance/accessReviews/definitions"
update_method = "PUT"
body = {
displayName = "example-quarterly"
descriptionForAdmins = "Scheduled review"
descriptionForReviewers = "Please review"
scope = {
"@odata.type" = "#microsoft.graph.accessReviewQueryScope"
query = "/groups/${var.target_group_object_id}/transitiveMembers"
queryType = "MicrosoftGraph"
}
reviewers = [
{
query = "/groups/${var.reviewer_group_object_id}/transitiveMembers"
queryType = "MicrosoftGraph"
}
]
settings = {
autoApplyDecisionsEnabled = true
mailNotificationsEnabled = true
reminderNotificationsEnabled = true
justificationRequiredOnApproval = false
defaultDecisionEnabled = false
defaultDecision = "None"
instanceDurationInDays = 14
recommendationsEnabled = false
recurrence = {
pattern = {
type = "absoluteMonthly"
interval = 3
}
range = {
type = "noEnd"
startDate = "2026-05-01"
}
}
}
}
}
Current workaround
Use targeted lifecycle ignores:
lifecycle {
ignore_changes = [
body.scope["query"],
body.reviewers[0]["query"]
]
}
This works, but hides query drift checks that ideally should be handled by provider-level normalization/diff suppression.
Request
Please add canonicalization or diff suppression for access review query fields that are semantically equivalent but returned by Graph in normalized form.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.