Skip to content

fix(CPV): Retry CPV initial consent and check SAM manifest changes by hash, not mtime - #299

Merged
KelvinTegelaar merged 2 commits into
devfrom
fix/cpv-consent-retry-gate
Aug 15, 2026
Merged

fix(CPV): Retry CPV initial consent and check SAM manifest changes by hash, not mtime#299
KelvinTegelaar merged 2 commits into
devfrom
fix/cpv-consent-retry-gate

Conversation

@JohnDuprey

Copy link
Copy Markdown
Contributor

No description provided.

Push-UpdatePermissionsQueue skipped Set-CIPPCPVConsent whenever a cpvtenants
row named the current SAM app. Its finally block writes that row on every run
including failures, so the first failed attempt left behind exactly the record
that suppressed all later attempts. The tenant then failed indefinitely on the
token call that only consent could have made possible, and
Start-UpdatePermissionsOrchestrator re-queued it nightly to no effect.

The gate now also re-consents when LastStatus is Failed, matching the status
check the orchestrator already makes. Rows predating LastStatus are left alone
so deploying this does not re-consent an entire estate.

A plain re-consent cannot repair every case: Set-CIPPCPVConsent short-circuits
on 'Permission entry already exists', which leaves both a recorded-but-
ineffective entry and one whose scopes no longer cover what CIPP needs
unfixable. Escalate to ResetSP on a recognised consent error, or after a
re-consent has already been tried, tracked in ConsentAttempts. Resets are
limited to one per week via LastResetUtc since they briefly remove access.

Test-CIPPAccessPermissions judged CPV freshness from the row Timestamp alone,
which the failed runs kept current - a permanently broken tenant never
appeared in "Some tenants need a CPV refresh". It now also reports failures.
Get-CippSamPermissions reported the manifest's LastWriteTime as "when the
required permission set last changed". Git does not store mtimes, so every
checkout and every container build restamps SAMManifest.json with the build
time. Docker COPY faithfully preserves that fresh timestamp, so the value was
really "when was this image built".

Consumers compare it against each tenant's cpvtenants row, so every release
made it newer than every row: Start-UpdatePermissionsOrchestrator re-queued the
entire estate through the permission and admin-role calls, and
Test-CIPPAccessPermissions reported that tenants needed a CPV refresh. Only
instances with saved extra permissions escaped, their AppPermissions row being
newer than the image.

Hash SAMManifest.json + AdditionalPermissions.json instead and keep the time
the hash was first seen, in an AppPermissions/ManifestHash row. A rebuild with
unchanged permissions no longer moves the timestamp; a genuine change still
does. If the row cannot be written, fall back to the mtime rather than treating
every call as first sight.

Upgrading records the hash once, which costs one final estate-wide refresh.
@KelvinTegelaar
KelvinTegelaar merged commit 301ccbc into dev Aug 15, 2026
6 of 7 checks passed
@JohnDuprey
JohnDuprey deleted the fix/cpv-consent-retry-gate branch August 15, 2026 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants