From 1b25f99f03530b214747abfe42edf30a2cb522ee Mon Sep 17 00:00:00 2001 From: lemaitre-aneo Date: Tue, 28 May 2024 17:02:11 +0200 Subject: [PATCH] Add proxy options --- .../ArmoniK.Api.Client/Options/GrpcClient.cs | 19 ++++ .../Submitter/GrpcChannelFactory.cs | 97 +++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/packages/csharp/ArmoniK.Api.Client/Options/GrpcClient.cs b/packages/csharp/ArmoniK.Api.Client/Options/GrpcClient.cs index 938b1b562..83cae164f 100644 --- a/packages/csharp/ArmoniK.Api.Client/Options/GrpcClient.cs +++ b/packages/csharp/ArmoniK.Api.Client/Options/GrpcClient.cs @@ -135,5 +135,24 @@ public bool HasClientCertificate /// If the handler is not set, the best one will be used. /// public string HttpMessageHandler { get; set; } = ""; + + /// + /// Proxy configuration. + /// If empty, the default proxy configuration is used. + /// If "none", proxy is disabled. + /// If "system", the system proxy is used + /// Otherwise, it is the URL of the proxy to use + /// + public string Proxy { get; set; } = ""; + + /// + /// Username used for proxy authentication + /// + public string ProxyUsername { get; set; } = ""; + + /// + /// Password used for proxy authentication + /// + public string ProxyPassword { get; set; } = ""; } } diff --git a/packages/csharp/ArmoniK.Api.Client/Submitter/GrpcChannelFactory.cs b/packages/csharp/ArmoniK.Api.Client/Submitter/GrpcChannelFactory.cs index 280a91040..0fc348da9 100644 --- a/packages/csharp/ArmoniK.Api.Client/Submitter/GrpcChannelFactory.cs +++ b/packages/csharp/ArmoniK.Api.Client/Submitter/GrpcChannelFactory.cs @@ -134,6 +134,8 @@ public static class GrpcChannelFactory /// Whether the Server Certificate should be validated or not /// Root certificate to validate the server certificate against /// Client certificate to be used for mTLS + /// Proxy configuration to use + /// Type of the proxy used /// Which HttpMessageHandler type to use /// Optional logger /// HttpMessageHandler @@ -141,6 +143,8 @@ private static HttpMessageHandler CreateHttpMessageHandler(bool htt bool insecure, X509Certificate? caCert, X509Certificate2? clientCert, + IWebProxy? proxy, + ProxyType proxyType, HandlerType handlerType, ILogger? logger = null) { @@ -165,6 +169,22 @@ private static HttpMessageHandler CreateHttpMessageHandler(bool htt httpHandler.SslProtocols = sslProtocols; httpHandler.ServerCertificateCustomValidationCallback = validationCallback; + switch (proxyType) + { + case ProxyType.None: + httpHandler.Proxy = null; + httpHandler.UseProxy = false; + break; + case ProxyType.System: + httpHandler.Proxy = null; + httpHandler.UseProxy = true; + break; + case ProxyType.Custom: + httpHandler.Proxy = proxy; + httpHandler.UseProxy = true; + break; + } + if (clientCert is not null) { httpHandler.ClientCertificates.Add(clientCert); @@ -191,6 +211,22 @@ private static HttpMessageHandler CreateHttpMessageHandler(bool htt } } + switch (proxyType) + { + case ProxyType.None: + winHandler.Proxy = null; + winHandler.WindowsProxyUsePolicy = WindowsProxyUsePolicy.DoNotUseProxy; + break; + case ProxyType.System: + winHandler.Proxy = null; + winHandler.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseWinHttpProxy; + break; + case ProxyType.Custom: + winHandler.Proxy = proxy; + winHandler.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseCustomProxy; + break; + } + if (handlerType is HandlerType.Web) { return new GrpcWebHandler(winHandler); @@ -292,6 +328,42 @@ private static GrpcChannel CreateChannelInternal(GrpcClient optionsGrpcClient, ? GetCertificate(optionsGrpcClient) : null; + ICredentials? proxyCredentials = null; + if (!string.IsNullOrEmpty(optionsGrpcClient.ProxyUsername) || !string.IsNullOrEmpty(optionsGrpcClient.ProxyPassword)) + { + proxyCredentials = new NetworkCredential(optionsGrpcClient.ProxyUsername, + optionsGrpcClient.ProxyPassword); + } + + IWebProxy? proxy = null; + ProxyType proxyType; + + switch (optionsGrpcClient.Proxy) + { + case "": + proxyType = ProxyType.Undefined; + break; + case "none": + case "None": + logger?.LogDebug("Unsetting proxy for the gRPC channel"); + proxyType = ProxyType.None; + break; + case "system": + case "System": + logger?.LogDebug("Using system proxy for the gRPC channel"); + proxyType = ProxyType.System; + break; + default: + logger?.LogDebug("Using custom proxy for the gRPC channel: {Proxy}", + optionsGrpcClient.Proxy); + proxyType = ProxyType.Custom; + proxy = new WebProxy(optionsGrpcClient.Proxy, + false, + Array.Empty(), + proxyCredentials); + break; + } + switch (handlerType) { case HandlerType.Http: @@ -312,6 +384,8 @@ private static GrpcChannel CreateChannelInternal(GrpcClient optionsGrpcClient, optionsGrpcClient.AllowUnsafeConnection, caCert, clientCert, + proxy, + proxyType, handlerType, logger); @@ -510,6 +584,29 @@ public static X509Certificate2 GetCertificate(GrpcClient optionsGrpcClient) _ => throw new ArgumentException($"Invalid HandlerType: {handler}"), }; + private enum ProxyType + { + /// + /// No proxy configuration defined + /// + Undefined, + + /// + /// Do not use any proxy, even if the system has one configured + /// + None, + + /// + /// Use the proxy configured on the system + /// + System, + + /// + /// Use a custom proxy + /// + Custom, + } + private enum HandlerType { ///