Instrument elevation path to diagnose ineffective grants
A SharePoint admin reported the grant runs without a logged error yet the account never appears as site-collection admin on Group/Teams sites. The failure was invisible: ElevateAsync called ExecuteQueryAsync directly (no enrichment/logging) and the coordinator only surfaced elevate failures on the page, not to Serilog. - Route the admin-endpoint ExecuteQuery through ExecuteQueryRetryHelper so a denial there is enriched (serverErrorType/httpStatus) and logged. - Log the resolved login and SetSiteAdmin acceptance in OwnershipElevationService. - Log elevate failures to Serilog in the coordinator. - Add a post-elevation verify that reads CurrentUser.IsSiteAdmin on the target site so logs distinguish a failed/no-op grant from a scan failing for another reason. Diagnostic only; never throws into the operation flow. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,10 @@ public class ElevationCoordinator : IElevationCoordinator
|
||||
await ElevateAsync(siteUrl, ct);
|
||||
_elevatedSites.Add(key);
|
||||
|
||||
// Verify the grant actually took effect for this delegated token before retrying,
|
||||
// so the logs distinguish "grant failed/no-op" from "scan still fails for another reason".
|
||||
await VerifyAdminAsync(siteUrl, ct);
|
||||
|
||||
// Re-run once. The closure re-issues its loads; the now-granted admin right applies.
|
||||
return await operation(ct);
|
||||
}
|
||||
@@ -88,12 +92,31 @@ public class ElevationCoordinator : IElevationCoordinator
|
||||
}
|
||||
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||
{
|
||||
Log.Error(ex, "Auto-elevate ownership failed for {Site}", siteUrl);
|
||||
throw new InvalidOperationException(
|
||||
$"Auto-elevate ownership failed for {siteUrl}. Granting site-collection admin requires " +
|
||||
$"SharePoint tenant administrator rights on the signed-in account. ({ex.Message})", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Reads the current user's site-admin flag on the target site right after elevation.
|
||||
// Diagnostic only — never throws into the operation flow.
|
||||
private async Task VerifyAdminAsync(string siteUrl, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ctx = await _sessionManager.GetOrCreateContextAsync(siteUrl, _session.CurrentProfile!, ct);
|
||||
ctx.Load(ctx.Web.CurrentUser, u => u.LoginName, u => u.IsSiteAdmin);
|
||||
await ctx.ExecuteQueryAsync();
|
||||
Log.Information("Post-elevation check {Site}: user={Login} IsSiteAdmin={IsAdmin}",
|
||||
siteUrl, ctx.Web.CurrentUser.LoginName, ctx.Web.CurrentUser.IsSiteAdmin);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning("Post-elevation check failed for {Site}: {Error}", siteUrl, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// https://abcube.sharepoint.com/sites/Foo → https://abcube-admin.sharepoint.com
|
||||
private static string BuildAdminUrl(string siteUrl)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user