Skip to content

Minimize diff for permissions#167

Open
alex-slynko wants to merge 4 commits intomainfrom
dekustoify-loaders
Open

Minimize diff for permissions#167
alex-slynko wants to merge 4 commits intomainfrom
dekustoify-loaders

Conversation

@alex-slynko
Copy link
Copy Markdown
Contributor

@alex-slynko alex-slynko commented Apr 14, 2026

Kusto allows specifying both object ID and client ID when setting permissions, but the diff always prefers one of them(ClientId), so it you have config with wrong identity it will always shows the diff.

Here I de-kustoify logic, so that it compared in C# rather then using complex Kusto queries and compare objects.

alex-slynko and others added 3 commits April 14, 2026 10:24
Extract ParseFromPolicyJson static method that parses raw JSON
from .show database policy managed_identity. Simplify the Kusto
query to just project the Policy column. Add ClientId property
(YamlIgnore) to support future principal normalization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Create PrincipalParser with testable static methods for role
extraction, display name cleaning, and principal grouping.
Simplify Kusto query to just project raw columns. Also loads
Monitor role which was previously missing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace ClientId with ObjectId in principal FQNs using exact
FQN parsing (only aadapp kind, case-insensitive). Handles
duplicate ClientId entries gracefully via GroupBy. Called in
KustoDatabaseHandler.LoadAsync() after all loaders complete.

Fixes phantom permission diffs when .show database principals
returns ClientId but YAML stores ObjectId.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 14, 2026 09:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces “phantom” permission diffs by shifting principal/policy shaping from Kusto queries into C# parsing and by normalizing principal IDs using managed identity policy data.

Changes:

  • Added PrincipalParser to parse .show database principals output in C# (role extraction, display name cleanup, filtering).
  • Updated managed identity policy loading to fetch the raw Policy JSON and parse it in C# (capturing ClientId for normalization).
  • Normalized loaded principal FQNs by rewriting aadapp=<clientId> to aadapp=<objectId> based on managed identity policy mapping, plus added targeted unit tests.
Show a summary per file
File Description
KustoSchemaTools/Parser/PrincipalParser.cs New C# parser for principal rows (role/name cleanup, grouping).
KustoSchemaTools/Parser/KustoLoader/KustoDatabasePrincipalLoader.cs Simplified Kusto query; delegates shaping to PrincipalParser; includes Monitor role.
KustoSchemaTools/Parser/KustoLoader/KustoManagedIdentityPolicyLoader.cs Loads raw managed identity Policy JSON and parses in C#.
KustoSchemaTools/Parser/KustoDatabaseHandler.cs Calls database.NormalizePrincipalIds() after loading from cluster.
KustoSchemaTools/Model/ManagedIdentityPolicy.cs Adds ClientId (YAML-ignored) and JSON parsing helper for policy column.
KustoSchemaTools/Model/Database.cs Adds principal-ID normalization logic and FQN parsing helpers.
KustoSchemaTools/KustoSchemaTools.csproj Adds InternalsVisibleTo for test access to internal helpers.
KustoSchemaTools.Tests/Parser/PrincipalParserTests.cs New tests for principal parsing behavior.
KustoSchemaTools.Tests/Model/ManagedIdentityPolicyTests.cs New tests for managed identity policy JSON parsing.
KustoSchemaTools.Tests/Changes/PrincipalNormalizationTests.cs New tests validating normalization and diff behavior scenarios.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 10/10 changed files
  • Comments generated: 3

.GroupBy(r => r.Role)
.ToDictionary(
g => g.Key,
g => g.Select(r => r.Principal).ToList()
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ParsePrincipals currently preserves the source order of principals within each role group. Since PermissionChange compares generated .set database ... (ids...) script text, non-deterministic ordering from .show database principals can create false diffs even when the principal sets are identical. Consider sorting (and optionally de-duplicating) principals within each role group by a stable key like Id (and/or Name) before returning the lists.

Suggested change
g => g.Select(r => r.Principal).ToList()
g => g.Select(r => r.Principal)
.GroupBy(p => new { p.Id, p.Name })
.Select(pg => pg.First())
.OrderBy(p => p.Id ?? string.Empty)
.ThenBy(p => p.Name ?? string.Empty)
.ToList()

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +46
internal static string ExtractRoleName(string role)
{
if (string.IsNullOrWhiteSpace(role))
return "";

var parts = role.Split(' ');
return parts[^1];
}
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Role parsing/filtering currently uses role.Split(' ') and StartsWith("All") without specifying comparison semantics. To better match Kusto's startswith behavior and avoid culture-sensitive comparisons / extra-space edge cases, consider using Split(' ', StringSplitOptions.RemoveEmptyEntries) and StartsWith("All", StringComparison.OrdinalIgnoreCase).

Copilot uses AI. Check for mistakes.
@@ -2,6 +2,7 @@
using Newtonsoft.Json;
using KustoSchemaTools.Helpers;
using KustoSchemaTools.Parser;
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using KustoSchemaTools.Parser; appears unused in this file after the refactor. If the repo treats warnings as failures in CI (or to keep the file clean), remove the unused using.

Suggested change
using KustoSchemaTools.Parser;

Copilot uses AI. Check for mistakes.
@alex-slynko alex-slynko enabled auto-merge April 14, 2026 10:23
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