From 002a52633cd32a0414eb228d3c967434a56bcabd Mon Sep 17 00:00:00 2001 From: Artem Azaraev Date: Mon, 13 Oct 2025 10:54:50 +0300 Subject: [PATCH 1/4] Add SchemeName optional parameter to MinimalPermissionsGuidancePlugin --- .../Reporting/MinimalPermissionsGuidancePlugin.cs | 1 + schemas/v1.3.0/minimalpermissionsguidanceplugin.schema.json | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs index 9c18c01a..7913fada 100644 --- a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs +++ b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs @@ -17,6 +17,7 @@ public sealed class MinimalPermissionsGuidancePluginConfiguration { public string? ApiSpecsFolderPath { get; set; } public IEnumerable? PermissionsToExclude { get; set; } + public string? SchemeName { get; set; } } public sealed class MinimalPermissionsGuidancePlugin( diff --git a/schemas/v1.3.0/minimalpermissionsguidanceplugin.schema.json b/schemas/v1.3.0/minimalpermissionsguidanceplugin.schema.json index d9f54eed..967657c7 100644 --- a/schemas/v1.3.0/minimalpermissionsguidanceplugin.schema.json +++ b/schemas/v1.3.0/minimalpermissionsguidanceplugin.schema.json @@ -18,6 +18,10 @@ }, "description": "The scopes to ignore and not include in the report. Default: ['profile', 'openid', 'offline_access', 'email'].", "default": ["profile", "openid", "offline_access", "email"] + }, + "schemeName": { + "type": "string", + "description": "The name of the security scheme definition. Used to determine minimal permissions required for API calls." } }, "required": [ From 38d4c60c57505905dcc9b32599372601579093e5 Mon Sep 17 00:00:00 2001 From: Artem Azaraev Date: Mon, 13 Oct 2025 10:56:20 +0300 Subject: [PATCH 2/4] Evaluate minimal permissions based on scheme name --- DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs index 7913fada..3c9dff43 100644 --- a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs +++ b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs @@ -84,7 +84,7 @@ public override async Task AfterRecordingStopAsync(RecordingArgs e, Cancellation foreach (var (apiSpec, requests) in requestsByApiSpec) { - var minimalPermissions = apiSpec.CheckMinimalPermissions(requests, Logger); + var minimalPermissions = apiSpec.CheckMinimalPermissions(requests, Logger, Configuration.SchemeName); IEnumerable excessivePermissions = [.. minimalPermissions.TokenPermissions .Except(Configuration.PermissionsToExclude ?? []) From 505e7e86973600ed84a96a63f068d9cacc29778e Mon Sep 17 00:00:00 2001 From: Artem Azaraev Date: Mon, 13 Oct 2025 11:04:52 +0300 Subject: [PATCH 3/4] Extend report to specify scheme name if defined --- .../Reporting/MinimalPermissionsGuidancePlugin.cs | 3 ++- .../MinimalPermissionsGuidancePluginReport.cs | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs index 3c9dff43..d5f88992 100644 --- a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs +++ b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs @@ -101,7 +101,8 @@ public override async Task AfterRecordingStopAsync(RecordingArgs e, Cancellation TokenPermissions = [.. minimalPermissions.TokenPermissions.Distinct()], MinimalPermissions = minimalPermissions.MinimalScopes, ExcessivePermissions = excessivePermissions, - UsesMinimalPermissions = !excessivePermissions.Any() + UsesMinimalPermissions = !excessivePermissions.Any(), + SchemeName = Configuration.SchemeName }; results.Add(result); diff --git a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePluginReport.cs b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePluginReport.cs index 89df8c62..26bcb6a4 100644 --- a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePluginReport.cs +++ b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePluginReport.cs @@ -17,6 +17,7 @@ public sealed class MinimalPermissionsGuidancePluginReportApiResult public required IEnumerable Requests { get; init; } public required IEnumerable TokenPermissions { get; init; } public required bool UsesMinimalPermissions { get; init; } + public string? SchemeName { get; init; } } public sealed class MinimalPermissionsGuidancePluginReport : IMarkdownReport, IPlainTextReport @@ -39,6 +40,9 @@ public sealed class MinimalPermissionsGuidancePluginReport : IMarkdownReport, IP foreach (var result in Results) { + var permissionsHeader = "### Minimal permissions" + (string.IsNullOrWhiteSpace(result.SchemeName) + ? "" : $" for {result.SchemeName} scheme"); + _ = sb.AppendLine(CultureInfo.InvariantCulture, $"## API: {result.ApiName}") .AppendLine() .AppendLine("### Requests") @@ -46,7 +50,7 @@ public sealed class MinimalPermissionsGuidancePluginReport : IMarkdownReport, IP .AppendJoin(Environment.NewLine, result.Requests.Select(r => $"- {r}")) .AppendLine() .AppendLine() - .AppendLine("### Minimal permissions") + .AppendLine(permissionsHeader) .AppendLine() .AppendJoin(Environment.NewLine, result.MinimalPermissions.Select(p => $"- `{p}`")) .AppendLine() @@ -120,6 +124,8 @@ public sealed class MinimalPermissionsGuidancePluginReport : IMarkdownReport, IP foreach (var result in Results) { var apiTitle = $"API: {result.ApiName}"; + var permissionsHeader = "Minimal permissions" + (string.IsNullOrWhiteSpace(result.SchemeName) + ? "" : $" for {result.SchemeName} scheme") + ":"; _ = sb.AppendLine() .AppendLine(apiTitle) .AppendLine(new string('-', apiTitle.Length)) @@ -129,7 +135,7 @@ public sealed class MinimalPermissionsGuidancePluginReport : IMarkdownReport, IP .AppendJoin(Environment.NewLine, result.Requests.Select(r => $"- {r}")).AppendLine() .AppendLine(); - _ = sb.AppendLine("Minimal permissions:") + _ = sb.AppendLine(permissionsHeader) .AppendJoin(", ", result.MinimalPermissions).AppendLine() .AppendLine(); From a048915402bbdaf4fdab89098f88875e32e1edf4 Mon Sep 17 00:00:00 2001 From: Artem Azaraev Date: Mon, 13 Oct 2025 11:12:51 +0300 Subject: [PATCH 4/4] Update logging with scheme name if defined --- .../MinimalPermissionsGuidancePlugin.cs | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs index d5f88992..71b4a338 100644 --- a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs +++ b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs @@ -114,20 +114,45 @@ public override async Task AfterRecordingStopAsync(RecordingArgs e, Cancellation if (result.UsesMinimalPermissions) { - Logger.LogInformation( - "API {ApiName} is called with minimal permissions: {MinimalPermissions}", - result.ApiName, - string.Join(", ", result.MinimalPermissions) - ); + if (string.IsNullOrWhiteSpace(Configuration.SchemeName)) + { + Logger.LogInformation( + "API {ApiName} is called with minimal permissions: {MinimalPermissions}", + result.ApiName, + string.Join(", ", result.MinimalPermissions) + ); + } + else + { + Logger.LogInformation( + "API {ApiName} is called with minimal permissions of '{SchemeName}' scheme: {MinimalPermissions}", + result.ApiName, + Configuration.SchemeName, + string.Join(", ", result.MinimalPermissions) + ); + } } else { - Logger.LogWarning( - "Calling API {ApiName} with excessive permissions: {ExcessivePermissions}. Minimal permissions are: {MinimalPermissions}", - result.ApiName, - string.Join(", ", result.ExcessivePermissions), - string.Join(", ", result.MinimalPermissions) - ); + if (string.IsNullOrWhiteSpace(Configuration.SchemeName)) + { + Logger.LogWarning( + "Calling API {ApiName} with excessive permissions: {ExcessivePermissions}. Minimal permissions are: {MinimalPermissions}", + result.ApiName, + string.Join(", ", result.ExcessivePermissions), + string.Join(", ", result.MinimalPermissions) + ); + } + else + { + Logger.LogWarning( + "Calling API {ApiName} with excessive permissions of '{SchemeName}' scheme: {ExcessivePermissions}. Minimal permissions are: {MinimalPermissions}", + result.ApiName, + Configuration.SchemeName, + string.Join(", ", result.ExcessivePermissions), + string.Join(", ", result.MinimalPermissions) + ); + } } if (unmatchedApiRequests.Any())