From e812ffcfe34fc79af4ce732bcfacc3a35990c6ba Mon Sep 17 00:00:00 2001 From: "Caleb Magiya (from Dev Box)" Date: Wed, 16 Oct 2024 15:20:40 +0300 Subject: [PATCH 1/3] wip: start validating plugin manifest --- kiota.sln | 6 ++++++ src/Kiota.Builder/Kiota.Builder.csproj | 5 ++++- src/Kiota.Builder/Plugins/PluginsGenerationService.cs | 6 +++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/kiota.sln b/kiota.sln index 0f9857aaac..2ec6ecf0ac 100644 --- a/kiota.sln +++ b/kiota.sln @@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EAAC5CEA-33B EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KiotaGenerated", "src\Kiota.Generated\KiotaGenerated.csproj", "{01ABDF23-60CD-4CE3-8DC7-8654C4BA1EE8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginsManifest", "..\Microsoft.Plugins.Manifest\src\PluginsManifest\PluginsManifest.csproj", "{55D60842-09BB-4EA8-9DF6-4ED9D2B1AA05}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -49,6 +51,10 @@ Global {01ABDF23-60CD-4CE3-8DC7-8654C4BA1EE8}.Debug|Any CPU.Build.0 = Debug|Any CPU {01ABDF23-60CD-4CE3-8DC7-8654C4BA1EE8}.Release|Any CPU.ActiveCfg = Release|Any CPU {01ABDF23-60CD-4CE3-8DC7-8654C4BA1EE8}.Release|Any CPU.Build.0 = Release|Any CPU + {55D60842-09BB-4EA8-9DF6-4ED9D2B1AA05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55D60842-09BB-4EA8-9DF6-4ED9D2B1AA05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55D60842-09BB-4EA8-9DF6-4ED9D2B1AA05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55D60842-09BB-4EA8-9DF6-4ED9D2B1AA05}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index 3f54277d82..c807dd39ac 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -47,7 +47,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive @@ -62,4 +62,7 @@ + + + diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index ef638601fa..8f8d69557f 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -261,10 +261,11 @@ private PluginManifestDocument GetManifestDocument(string openApiDocumentPath) var (runtimes, functions, conversationStarters) = GetRuntimesFunctionsAndConversationStartersFromTree(OAIDocument, Configuration.PluginAuthInformation, TreeNode, openApiDocumentPath); var descriptionForHuman = OAIDocument.Info?.Description is string d && !string.IsNullOrEmpty(d) ? d : $"Description for {OAIDocument.Info?.Title}"; var manifestInfo = ExtractInfoFromDocument(OAIDocument.Info); + const string schemaVersion = "v2.1"; var pluginManifestDocument = new PluginManifestDocument { Schema = "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.1/schema.json", - SchemaVersion = "v2.1", + SchemaVersion = schemaVersion, NameForHuman = OAIDocument.Info?.Title.CleanupXMLString(), DescriptionForHuman = descriptionForHuman, DescriptionForModel = manifestInfo.DescriptionForModel ?? descriptionForHuman, @@ -295,6 +296,9 @@ private PluginManifestDocument GetManifestDocument(string openApiDocumentPath) }) .ToList() }; + + var ruleSet = PluginManifestRuleSets.GetDefaultAuthoringRuleSet(); + pluginManifestDocument.Validate(ruleSet, new ValidationContext(schemaVersion)); return pluginManifestDocument; } From 2bdd1bba407fd1615b5144f41598be814a2e9f9c Mon Sep 17 00:00:00 2001 From: "Caleb Magiya (from Dev Box)" Date: Wed, 16 Oct 2024 15:24:22 +0300 Subject: [PATCH 2/3] format files --- src/Kiota.Builder/Plugins/PluginsGenerationService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index 8f8d69557f..a1d99ebe89 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -296,7 +296,7 @@ private PluginManifestDocument GetManifestDocument(string openApiDocumentPath) }) .ToList() }; - + var ruleSet = PluginManifestRuleSets.GetDefaultAuthoringRuleSet(); pluginManifestDocument.Validate(ruleSet, new ValidationContext(schemaVersion)); return pluginManifestDocument; From 1812e9bbdf2f2d7ef5b48cfc60b8b54c3c5ed7b6 Mon Sep 17 00:00:00 2001 From: "Caleb Magiya (from Dev Box)" Date: Thu, 17 Oct 2024 16:00:00 +0300 Subject: [PATCH 3/3] Use OpenAPI.NET validation API --- .../Plugins/PluginsGenerationService.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index a1d99ebe89..0b5c166811 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -10,10 +10,12 @@ using Kiota.Builder.Extensions; using Kiota.Builder.OpenApiExtensions; using Microsoft.OpenApi.ApiManifest; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Writers; using Microsoft.Plugins.Manifest; +using ValidationRuleSet = Microsoft.OpenApi.Validations.ValidationRuleSet; namespace Kiota.Builder.Plugins; @@ -258,6 +260,21 @@ private OpenApiDocument GetDocumentWithTrimmedComponentsAndResponses(OpenApiDocu private PluginManifestDocument GetManifestDocument(string openApiDocumentPath) { + // Validate OpenAPI + var ruleSet = new ValidationRuleSet + { + Microsoft.Plugins.Manifest.OpenApiRules.OpenApiServerUrlRule.ServerUrlMustBeHttps, + Microsoft.Plugins.Manifest.OpenApiRules.OpenApiCombinedAuthFlowRule + .PathsCanOnlyHaveOneSecuritySchemePerOperation(OAIDocument.SecurityRequirements), + Microsoft.Plugins.Manifest.OpenApiRules.OpenApiRequestBodySchemaRule.RequestBodySchemaObjectsMustNeverBeNested, + Microsoft.Plugins.Manifest.OpenApiRules.OpenApiApiKeyBearerRule.ApiKeyNotSupportedOnlyBearerPlusHttp(OAIDocument.SecurityRequirements) + }; + var errors = OAIDocument.Validate(ruleSet)?.ToArray(); + if (errors != null && errors.Length != 0) + { + var message = string.Join(Environment.NewLine, errors.Select(e => $"{e.Pointer}: {e.Message}")); + throw new InvalidOperationException(message); + } var (runtimes, functions, conversationStarters) = GetRuntimesFunctionsAndConversationStartersFromTree(OAIDocument, Configuration.PluginAuthInformation, TreeNode, openApiDocumentPath); var descriptionForHuman = OAIDocument.Info?.Description is string d && !string.IsNullOrEmpty(d) ? d : $"Description for {OAIDocument.Info?.Title}"; var manifestInfo = ExtractInfoFromDocument(OAIDocument.Info); @@ -297,8 +314,6 @@ private PluginManifestDocument GetManifestDocument(string openApiDocumentPath) .ToList() }; - var ruleSet = PluginManifestRuleSets.GetDefaultAuthoringRuleSet(); - pluginManifestDocument.Validate(ruleSet, new ValidationContext(schemaVersion)); return pluginManifestDocument; }