fix: prevent group loss when paginating checkIfUserHasGroups past 2 pages - #2898
Open
rasta-rocket wants to merge 1 commit into
Open
fix: prevent group loss when paginating checkIfUserHasGroups past 2 pages#2898rasta-rocket wants to merge 1 commit into
rasta-rocket wants to merge 1 commit into
Conversation
…ages checkIfUserHasGroups declared the per-page slice once, outside the pagination loop, and reused it across resp.Next() calls. Decoding a JSON array into a slice that already holds non-nil pointers makes encoding/json reuse those pointers and overwrite the pointed-to structs in place, so decoding page N clobbered entries already appended to the accumulator from page N-1. The corruption starts on the third page (page two decodes into a nil slice, so it allocates fresh). Users with more than 400 group memberships (2 pages of 200) hit this: real memberships silently disappeared from the read-back, checkIfUserHasGroups reported them missing, and Create's backoff.Retry exhausted with "did not have expected group memberships after multiple checks" even though the group assignment had succeeded. Move the slice declaration inside the loop so each page decodes into a fresh slice.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
checkIfUserHasGroups(used byokta_user_group_membershipscreate/read) declared its per-page slice outside the pagination loop and reused it across pages:encoding/jsondoes not allocate new structs when the destination slice already holds non-nil pointers - it follows the existing pointers and overwrites the structs in place. SinceuserGroupsholds those same pointers, decoding page 3 silently rewrites the entries copied from page 2.Why it matters
Any user with more than 400 group memberships (2 pages of the API's 200-per-page limit) triggers this on the third page onward. Groups the user is genuinely a member of vanish from the collected set,
checkIfUserHasGroupsreports them as missing, andresourceUserGroupMembershipsCreate'sbackoff.Retryexhausts with:...even though
addUserToGroupsalready succeeded and the group assignment is correct in Okta.terraform applyfails deterministically every time for these users - it isn't a flaky eventual-consistency race.This is the same bug class as #1542 (pagination wasn't looped at all), one layer deeper: the loop is correct, but the accumulation across iterations isn't.
Fix
Move the slice declaration inside the loop so each page decodes into its own freshly allocated slice:
Testing
Added
TestUserGroupMembershipsReadPaginationDoesNotDropGroups, a unit test (httpmock, noTF_ACC) that mocks a 3-pageGET /users/{id}/groupsresponse with the target group on page 2 and asserts it survives to the final result. Verified it fails onmain(before this fix) with:and passes with the fix applied.
go vetandgofmtclean.Reproduced against my company's real Okta org data with a local build - the failing users have 401-600 group memberships (3 pages), and the missing group falls in the corrupted range as predicted.
Cheers ☀️