diff --git a/.github/policies/resourceManagement.yml b/.github/policies/resourceManagement.yml index 25cff265f1..b9f1ee1a07 100644 --- a/.github/policies/resourceManagement.yml +++ b/.github/policies/resourceManagement.yml @@ -1,14 +1,14 @@ -id: +id: name: GitOps.PullRequestIssueManagement description: GitOps.PullRequestIssueManagement primitive -owner: +owner: resource: repository disabled: false -where: +where: configuration: resourceManagementConfiguration: scheduledSearches: - - description: + - description: frequencies: - hourly: hour: 6 @@ -16,14 +16,14 @@ configuration: - isIssue - isOpen - hasLabel: - label: 'Needs: Author Feedback' + label: 'status:waiting-for-author-feedback' - hasLabel: label: 'Status: No Recent Activity' - noActivitySince: days: 3 actions: - closeIssue - - description: + - description: frequencies: - hourly: hour: 6 @@ -31,7 +31,7 @@ configuration: - isIssue - isOpen - hasLabel: - label: 'Needs: Author Feedback' + label: 'status:waiting-for-author-feedback' - noActivitySince: days: 4 - isNotLabeledWith: @@ -41,7 +41,7 @@ configuration: label: 'Status: No Recent Activity' - addReply: reply: This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **4 days**. It will be closed if no further activity occurs **within 3 days of this comment**. - - description: + - description: frequencies: - hourly: hour: 6 @@ -64,14 +64,14 @@ configuration: - isActivitySender: issueAuthor: True - hasLabel: - label: 'Needs: Author Feedback' + label: 'status:waiting-for-author-feedback' - isOpen then: - addLabel: label: 'Needs: Attention :wave:' - removeLabel: - label: 'Needs: Author Feedback' - description: + label: 'status:waiting-for-author-feedback' + description: - if: - payloadType: Issues - not: @@ -82,7 +82,7 @@ configuration: then: - removeLabel: label: 'Status: No Recent Activity' - description: + description: - if: - payloadType: Issue_Comment - hasLabel: @@ -90,12 +90,12 @@ configuration: then: - removeLabel: label: 'Status: No Recent Activity' - description: + description: - if: - payloadType: Pull_Request then: - inPrLabel: label: WIP - description: -onFailure: -onSuccess: + description: +onFailure: +onSuccess: diff --git a/CHANGELOG.md b/CHANGELOG.md index 611469f436..2e2b58c4ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for multipart form data request body in PHP. [#3029](https://github.com/microsoft/kiota/issues/3029) - Added uri-form encoded serialization for PHP. [#2074](https://github.com/microsoft/kiota/issues/2074) - Added information message with base URL in the CLI experience. [#4635](https://github.com/microsoft/kiota/issues/4635) +- Added optional parameter --disable-ssl-validation for generate, show, and download commands. [#4176](https://github.com/microsoft/kiota/issues/4176) ### Changed diff --git a/it/python/requirements-dev.txt b/it/python/requirements-dev.txt index 8c72e67286..9c0f3a43c3 100644 --- a/it/python/requirements-dev.txt +++ b/it/python/requirements-dev.txt @@ -1,6 +1,6 @@ -i https://pypi.org/simple -astroid==3.2.1 ; python_full_version >= '3.7.2' +astroid==3.2.2 ; python_full_version >= '3.7.2' certifi==2024.2.2 ; python_version >= '3.6' @@ -40,11 +40,11 @@ platformdirs==4.2.2 ; python_version >= '3.7' pluggy==1.5.0 ; python_version >= '3.7' -pylint==3.2.0 +pylint==3.2.2 -pytest==8.2.0 +pytest==8.2.1 -pytest-asyncio==0.23.6 +pytest-asyncio==0.23.7 requests==2.31.0 ; python_version >= '3.7' diff --git a/src/Kiota.Builder/Configuration/DownloadConfiguration.cs b/src/Kiota.Builder/Configuration/DownloadConfiguration.cs index df3c30ef24..b63a5a41d8 100644 --- a/src/Kiota.Builder/Configuration/DownloadConfiguration.cs +++ b/src/Kiota.Builder/Configuration/DownloadConfiguration.cs @@ -9,6 +9,10 @@ public bool CleanOutput { get; set; } + public bool DisableSSLValidation + { + get; set; + } public object Clone() { @@ -16,7 +20,8 @@ public object Clone() { OutputPath = OutputPath, CleanOutput = CleanOutput, - ClearCache = ClearCache + ClearCache = ClearCache, + DisableSSLValidation = DisableSSLValidation, }; } } diff --git a/src/Kiota.Builder/Configuration/GenerationConfiguration.cs b/src/Kiota.Builder/Configuration/GenerationConfiguration.cs index d00d410f9b..7200211e63 100644 --- a/src/Kiota.Builder/Configuration/GenerationConfiguration.cs +++ b/src/Kiota.Builder/Configuration/GenerationConfiguration.cs @@ -151,6 +151,7 @@ public object Clone() Operation = Operation, PatternsOverride = new(PatternsOverride ?? Enumerable.Empty(), StringComparer.OrdinalIgnoreCase), PluginTypes = new(PluginTypes ?? Enumerable.Empty()), + DisableSSLValidation = DisableSSLValidation, }; } private static readonly StringIEnumerableDeepComparer comparer = new(); @@ -200,6 +201,11 @@ private string NormalizeDescriptionLocation(string targetDirectory) return OpenAPIFilePath; } public bool IsPluginConfiguration => PluginTypes.Count != 0; + + public bool DisableSSLValidation + { + get; set; + } } #pragma warning restore CA1056 #pragma warning restore CA2227 diff --git a/src/Kiota.Builder/Lock/KiotaLock.cs b/src/Kiota.Builder/Lock/KiotaLock.cs index a299234a5d..433861a2fa 100644 --- a/src/Kiota.Builder/Lock/KiotaLock.cs +++ b/src/Kiota.Builder/Lock/KiotaLock.cs @@ -59,6 +59,13 @@ public bool IncludeAdditionalData { get; set; } + /// + /// Whether SSL Validation was disabled for this client. + /// + public bool DisableSSLValidation + { + get; set; + } #pragma warning disable CA2227 /// /// The serializers used for this client. @@ -108,6 +115,7 @@ public void UpdateGenerationConfigurationFromLock(GenerationConfiguration config config.ExcludePatterns = ExcludePatterns; config.OpenAPIFilePath = DescriptionLocation; config.DisabledValidationRules = DisabledValidationRules; + config.DisableSSLValidation = DisableSSLValidation; } /// /// Initializes a new instance of the class. @@ -135,5 +143,6 @@ public KiotaLock(GenerationConfiguration config) ExcludePatterns = config.ExcludePatterns; DescriptionLocation = config.OpenAPIFilePath; DisabledValidationRules = config.DisabledValidationRules; + DisableSSLValidation = config.DisableSSLValidation; } } diff --git a/src/Kiota.Builder/Lock/KiotaLockComparer.cs b/src/Kiota.Builder/Lock/KiotaLockComparer.cs index d4e564b776..ccaa75a1a4 100644 --- a/src/Kiota.Builder/Lock/KiotaLockComparer.cs +++ b/src/Kiota.Builder/Lock/KiotaLockComparer.cs @@ -21,6 +21,7 @@ public int GetHashCode([DisallowNull] KiotaLock obj) { if (obj == null) return 0; return + obj.DisableSSLValidation.GetHashCode() * 59 + _stringIEnumerableDeepComparer.GetHashCode(obj.DisabledValidationRules?.Order(StringComparer.OrdinalIgnoreCase) ?? Enumerable.Empty()) * 53 + obj.KiotaVersion.GetHashCode(StringComparison.OrdinalIgnoreCase) * 47 + obj.LockFileVersion.GetHashCode(StringComparison.OrdinalIgnoreCase) * 43 + diff --git a/src/Kiota.Builder/SearchProviders/GitHub/GitHubClient/kiota-lock.json b/src/Kiota.Builder/SearchProviders/GitHub/GitHubClient/kiota-lock.json index 226089fd75..0b438e5c4f 100644 --- a/src/Kiota.Builder/SearchProviders/GitHub/GitHubClient/kiota-lock.json +++ b/src/Kiota.Builder/SearchProviders/GitHub/GitHubClient/kiota-lock.json @@ -37,5 +37,6 @@ "**/generate", "**/repos/**/topics" ], - "disabledValidationRules": [] -} \ No newline at end of file + "disabledValidationRules": [], + "disableSSLValidation": false +} diff --git a/src/kiota/Handlers/BaseKiotaCommandHandler.cs b/src/kiota/Handlers/BaseKiotaCommandHandler.cs index 8d9f25d494..f1f2ce5fb7 100644 --- a/src/kiota/Handlers/BaseKiotaCommandHandler.cs +++ b/src/kiota/Handlers/BaseKiotaCommandHandler.cs @@ -31,7 +31,16 @@ protected static void DefaultSerializersAndDeserializers(GenerationConfiguration Logger = logger, FileName = "pat-api.github.com" }; - internal static readonly HttpClient httpClient = new(); + + private HttpClient? _httpClient; + protected HttpClient httpClient + { + get + { + _httpClient ??= GetHttpClient(); + return _httpClient; + } + } public required Option LogLevelOption { get; init; @@ -52,6 +61,21 @@ protected KiotaConfiguration Configuration configObject.BindConfiguration(configuration); return configObject; }); + + protected HttpClient GetHttpClient() + { + var httpClientHandler = new HttpClientHandler(); + if (Configuration.Generation.DisableSSLValidation) + httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; + + var httpClient = new HttpClient(httpClientHandler); + + disposables.Add(httpClientHandler); + disposables.Add(httpClient); + + return httpClient; + } + private const string GitHubScope = "repo"; private Func> GetIsGitHubDeviceSignedInCallback(ILogger logger) => (cancellationToken) => { diff --git a/src/kiota/Handlers/KiotaDownloadCommandHandler.cs b/src/kiota/Handlers/KiotaDownloadCommandHandler.cs index e5d8334be3..e61fa83fc3 100644 --- a/src/kiota/Handlers/KiotaDownloadCommandHandler.cs +++ b/src/kiota/Handlers/KiotaDownloadCommandHandler.cs @@ -31,6 +31,10 @@ public required Option CleanOutputOption { get; init; } + public required Option DisableSSLValidationOption + { + get; init; + } public override async Task InvokeAsync(InvocationContext context) { string searchTerm = context.ParseResult.GetValueForArgument(SearchTermArgument); @@ -38,9 +42,11 @@ public override async Task InvokeAsync(InvocationContext context) string outputPath = context.ParseResult.GetValueForOption(OutputPathOption) ?? string.Empty; bool cleanOutput = context.ParseResult.GetValueForOption(CleanOutputOption); bool clearCache = context.ParseResult.GetValueForOption(ClearCacheOption); + bool disableSSLValidation = context.ParseResult.GetValueForOption(DisableSSLValidationOption); CancellationToken cancellationToken = context.BindingContext.GetService(typeof(CancellationToken)) is CancellationToken token ? token : CancellationToken.None; Configuration.Download.ClearCache = clearCache; + Configuration.Download.DisableSSLValidation = disableSSLValidation; Configuration.Download.CleanOutput = cleanOutput; Configuration.Download.OutputPath = NormalizeSlashesInPath(outputPath); diff --git a/src/kiota/Handlers/KiotaGenerateCommandHandler.cs b/src/kiota/Handlers/KiotaGenerateCommandHandler.cs index 1f9cbbee49..a0442d81af 100644 --- a/src/kiota/Handlers/KiotaGenerateCommandHandler.cs +++ b/src/kiota/Handlers/KiotaGenerateCommandHandler.cs @@ -69,6 +69,7 @@ public override async Task InvokeAsync(InvocationContext context) bool backingStore = context.ParseResult.GetValueForOption(BackingStoreOption); bool excludeBackwardCompatible = context.ParseResult.GetValueForOption(ExcludeBackwardCompatibleOption); bool clearCache = context.ParseResult.GetValueForOption(ClearCacheOption); + bool disableSSLValidation = context.ParseResult.GetValueForOption(DisableSSLValidationOption); bool includeAdditionalData = context.ParseResult.GetValueForOption(AdditionalDataOption); string className = context.ParseResult.GetValueForOption(ClassOption) ?? string.Empty; string namespaceName = context.ParseResult.GetValueForOption(NamespaceOption) ?? string.Empty; @@ -112,6 +113,7 @@ public override async Task InvokeAsync(InvocationContext context) Configuration.Generation.ApiManifestPath = NormalizeSlashesInPath(GetAbsolutePath(Configuration.Generation.ApiManifestPath)); Configuration.Generation.CleanOutput = cleanOutput; Configuration.Generation.ClearCache = clearCache; + Configuration.Generation.DisableSSLValidation = disableSSLValidation; var (loggerFactory, logger) = GetLoggerAndFactory(context, Configuration.Generation.OutputPath); using (loggerFactory) @@ -173,4 +175,8 @@ public required Option ExcludeBackwardCompatibleOption get; set; } + public required Option DisableSSLValidationOption + { + get; init; + } } diff --git a/src/kiota/Handlers/KiotaShowCommandHandler.cs b/src/kiota/Handlers/KiotaShowCommandHandler.cs index eba912371e..e268ab55bf 100644 --- a/src/kiota/Handlers/KiotaShowCommandHandler.cs +++ b/src/kiota/Handlers/KiotaShowCommandHandler.cs @@ -41,6 +41,10 @@ public required Option ManifestOption { get; init; } + public required Option DisableSSLValidationOption + { + get; init; + } public override async Task InvokeAsync(InvocationContext context) { @@ -52,11 +56,13 @@ public override async Task InvokeAsync(InvocationContext context) List includePatterns = context.ParseResult.GetValueForOption(IncludePatternsOption) ?? new List(); List excludePatterns = context.ParseResult.GetValueForOption(ExcludePatternsOption) ?? new List(); bool clearCache = context.ParseResult.GetValueForOption(ClearCacheOption); + bool disableSSLValidation = context.ParseResult.GetValueForOption(DisableSSLValidationOption); CancellationToken cancellationToken = context.BindingContext.GetService(typeof(CancellationToken)) is CancellationToken token ? token : CancellationToken.None; var (loggerFactory, logger) = GetLoggerAndFactory(context); Configuration.Search.ClearCache = clearCache; + Configuration.Generation.DisableSSLValidation = disableSSLValidation; using (loggerFactory) { await CheckForNewVersionAsync(logger, cancellationToken).ConfigureAwait(false); diff --git a/src/kiota/KiotaHost.cs b/src/kiota/KiotaHost.cs index 8dda187bf3..955d22e4a4 100644 --- a/src/kiota/KiotaHost.cs +++ b/src/kiota/KiotaHost.cs @@ -153,6 +153,7 @@ private static Command GetShowCommand() var searchTermOption = GetSearchKeyOption(); var maxDepthOption = new Option("--max-depth", () => 5, "The maximum depth of the tree to display"); maxDepthOption.AddAlias("--m-d"); + var disableSSLValidationOption = GetDisableSSLValidationOption(defaultGenerationConfiguration.DisableSSLValidation); var displayCommand = new Command("show", "Displays the API tree in a given description."){ searchTermOption, logLevelOption, @@ -163,6 +164,7 @@ private static Command GetShowCommand() includePatterns, excludePatterns, clearCacheOption, + disableSSLValidationOption, }; displayCommand.Handler = new KiotaShowCommandHandler { @@ -175,6 +177,7 @@ private static Command GetShowCommand() IncludePatternsOption = includePatterns, ExcludePatternsOption = excludePatterns, ClearCacheOption = clearCacheOption, + DisableSSLValidationOption = disableSSLValidationOption, }; return displayCommand; } @@ -213,6 +216,8 @@ private static Command GetDownloadCommand() var outputOption = GetOutputPathOption(defaultConfiguration.OutputPath); + var disableSSLValidationOption = GetDisableSSLValidationOption(defaultConfiguration.DisableSSLValidation); + var searchCommand = new Command("download", "Downloads an OpenAPI description from multiple registries."){ keyArgument, logLevelOption, @@ -220,6 +225,7 @@ private static Command GetDownloadCommand() versionOption, cleanOutputOption, outputOption, + disableSSLValidationOption, }; searchCommand.Handler = new KiotaDownloadCommandHandler { @@ -229,6 +235,7 @@ private static Command GetDownloadCommand() VersionOption = versionOption, CleanOutputOption = cleanOutputOption, OutputPathOption = outputOption, + DisableSSLValidationOption = disableSSLValidationOption, }; return searchCommand; } @@ -444,6 +451,8 @@ private static Command GetGenerateCommand() var clearCacheOption = GetClearCacheOption(defaultConfiguration.ClearCache); + var disableSSLValidationOption = GetDisableSSLValidationOption(defaultConfiguration.DisableSSLValidation); + var command = new Command("generate", "Generates a REST HTTP API client from an OpenAPI description file.") { descriptionOption, manifestOption, @@ -463,6 +472,7 @@ private static Command GetGenerateCommand() excludePatterns, dvrOption, clearCacheOption, + disableSSLValidationOption, }; command.Handler = new KiotaGenerateCommandHandler { @@ -484,6 +494,7 @@ private static Command GetGenerateCommand() ExcludePatternsOption = excludePatterns, DisabledValidationRulesOption = dvrOption, ClearCacheOption = clearCacheOption, + DisableSSLValidationOption = disableSSLValidationOption, }; return command; } @@ -541,6 +552,14 @@ private static Option GetClearCacheOption(bool defaultValue) clearCacheOption.AddAlias("--cc"); return clearCacheOption; } + + private static Option GetDisableSSLValidationOption(bool defaultValue) + { + var disableSSLValidationOption = new Option("--disable-ssl-validation", () => defaultValue, "Disables SSL certificate validation."); + disableSSLValidationOption.AddAlias("--dsv"); + return disableSSLValidationOption; + } + private static void AddStringRegexValidator(Option option, Regex validator, string parameterName, bool allowEmpty = false) { option.AddValidator(input => diff --git a/src/kiota/Properties/launchSettings.json b/src/kiota/Properties/launchSettings.json index cfdf1701e0..627716184d 100644 --- a/src/kiota/Properties/launchSettings.json +++ b/src/kiota/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "kiota": { "commandName": "Project", - "commandLineArgs": "--openapi C:\\src\\msgraph-sdk-powershell\\openApiDocs\\v1.0\\mail.yml -o C:\\Users\\darrmi\\source\\github\\darrelmiller\\OpenApiClient\\Generated -c GraphClient --loglevel Information" + "commandLineArgs": "generate --openapi https://localhost:3000/swagger.json -o E:\\OSS\\kiota\\Output\\local_3 -c GraphClient --log-level Information -l CSharp --dsv" } } }