diff --git a/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPlugin.cs b/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPlugin.cs index 24a69a25..9a5223b3 100644 --- a/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPlugin.cs +++ b/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPlugin.cs @@ -22,6 +22,7 @@ public sealed class ApiCenterMinimalPermissionsPluginConfiguration public string ServiceName { get; set; } = ""; public string SubscriptionId { get; set; } = ""; public string WorkspaceName { get; set; } = "default"; + public string? SchemeName { get; set; } } public sealed class ApiCenterMinimalPermissionsPlugin( @@ -143,7 +144,8 @@ public override async Task AfterRecordingStopAsync(RecordingArgs e, Cancellation TokenPermissions = [.. minimalPermissions.TokenPermissions.Distinct()], MinimalPermissions = minimalPermissions.MinimalScopes, ExcessivePermissions = [.. minimalPermissions.TokenPermissions.Except(minimalPermissions.MinimalScopes)], - UsesMinimalPermissions = !minimalPermissions.TokenPermissions.Except(minimalPermissions.MinimalScopes).Any() + UsesMinimalPermissions = !minimalPermissions.TokenPermissions.Except(minimalPermissions.MinimalScopes).Any(), + SchemeName = Configuration.SchemeName }; results.Add(result); @@ -155,20 +157,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()) @@ -208,7 +235,7 @@ private ApiPermissionsInfo CheckMinimalPermissions(IEnumerable reque { Logger.LogInformation("Checking minimal permissions for API {ApiName}...", apiDefinition.Definition!.Servers.First().Url); - return apiDefinition.Definition.CheckMinimalPermissions(requests, Logger); + return apiDefinition.Definition.CheckMinimalPermissions(requests, Logger, Configuration.SchemeName); } private (Dictionary> RequestsByApiDefinition, IEnumerable UnmatchedRequests) GetRequestsByApiDefinition(IEnumerable interceptedRequests, Dictionary apiDefinitionsByUrl) diff --git a/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPluginReport.cs b/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPluginReport.cs index 09530ad6..4a422a37 100644 --- a/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPluginReport.cs +++ b/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPluginReport.cs @@ -19,6 +19,7 @@ public sealed class ApiCenterMinimalPermissionsPluginReportApiResult 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 ApiCenterMinimalPermissionsPluginReport : IMarkdownReport, IPlainTextReport @@ -52,11 +53,14 @@ public string ToMarkdown() { foreach (var apiResult in Results) { + var permissionsHeader = "#### Permissions" + (string.IsNullOrWhiteSpace(apiResult.SchemeName) + ? "" : $" for {apiResult.SchemeName} scheme"); + _ = sb.AppendFormat(CultureInfo.InvariantCulture, "### {0}{1}", apiResult.ApiName, Environment.NewLine) .AppendLine() .AppendFormat(CultureInfo.InvariantCulture, apiResult.UsesMinimalPermissions ? "✅ Called using minimal permissions{0}" : "🛑 Called using excessive permissions{0}", Environment.NewLine) .AppendLine() - .AppendLine("#### Permissions") + .AppendLine(permissionsHeader) .AppendLine() .AppendFormat(CultureInfo.InvariantCulture, "- Minimal permissions: {0}{1}", string.Join(", ", apiResult.MinimalPermissions.Order().Select(p => $"`{p}`")), Environment.NewLine) .AppendFormat(CultureInfo.InvariantCulture, "- Permissions on the token: {0}{1}", string.Join(", ", apiResult.TokenPermissions.Order().Select(p => $"`{p}`")), Environment.NewLine) @@ -115,11 +119,14 @@ public string ToMarkdown() { foreach (var apiResult in Results) { + var permissionsHeader = "Permissions" + (string.IsNullOrWhiteSpace(apiResult.SchemeName) + ? "" : $" for {apiResult.SchemeName} scheme"); + _ = sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", apiResult.ApiName, Environment.NewLine) .AppendLine() .AppendLine(apiResult.UsesMinimalPermissions ? "v Called using minimal permissions" : "x Called using excessive permissions") .AppendLine() - .AppendLine("Permissions") + .AppendLine(permissionsHeader) .AppendLine() .AppendFormat(CultureInfo.InvariantCulture, "- Minimal permissions: {0}{1}", string.Join(", ", apiResult.MinimalPermissions.Order()), Environment.NewLine) .AppendFormat(CultureInfo.InvariantCulture, "- Permissions on the token: {0}{1}", string.Join(", ", apiResult.TokenPermissions.Order()), Environment.NewLine) diff --git a/schemas/v1.3.0/apicenterminimalpermissionsplugin.schema.json b/schemas/v1.3.0/apicenterminimalpermissionsplugin.schema.json index 9350a97b..e0b473c3 100644 --- a/schemas/v1.3.0/apicenterminimalpermissionsplugin.schema.json +++ b/schemas/v1.3.0/apicenterminimalpermissionsplugin.schema.json @@ -23,6 +23,10 @@ "type": "string", "description": "Name of the Azure API Center workspace to use. Default is 'default'.", "default": "default" + }, + "schemeName": { + "type": "string", + "description": "The name of the security scheme definition. Used to determine minimal permissions required for API calls." } }, "required": [