From e04c5cdedab8f62e85206be32337f1ad720aae9d Mon Sep 17 00:00:00 2001 From: Cynthia Date: Sat, 1 Jul 2023 12:35:29 -0600 Subject: [PATCH] check for `http_proxy` & `https_proxy` env-vars this brings us in line with many other AWS SDKs which check for these environment variables to modify client behavior. it does not change behavior if you've already been setting your web proxy explicitly, or in properties (the same as the java (and other) sdks). we do introduce this with two new methods in ClientConfig to not break any existing callers using the methods that are public. while all of our callers have been updated to properly check web proxy, and then if that's unset check the protocol being used and optionally call `GetHttpProxy`/`GetHttpsProxy` as needed. If we're okay with breaking ever IT MAY be worthwhile to break `GetWebProxy` by taking in the protocol, and then just having the one method to prevent any accidental mis-use, and to ensure everyone is using those environment variables. it's also important to note: meaning a user will just get an error if they try to proxy to something that is using `HTTPS`. i figured just letting it error on construction is probably the 'safest' option. letting the user know that their setting isn't being respected, as opposed to just silently 'ignoring' it. this is also a decision we might want to change. --- .../HttpHandler/_bcl/HttpWebRequestFactory.cs | 8 ++++++ .../_netstandard/HttpRequestMessageFactory.cs | 6 +++- .../Core/Amazon.Runtime/_bcl/ClientConfig.cs | 28 +++++++++++++++++++ .../Amazon.Runtime/_bcl/IClientConfig.bcl.cs | 11 ++++++++ .../_netstandard/ClientConfig.cs | 28 +++++++++++++++++++ .../_netstandard/IClientConfig.cs | 12 ++++++++ .../Util/_async/ImageUtilities.async.cs | 24 ++++++++++++++-- .../Custom/Util/_bcl/ImageUtilities.bcl.cs | 24 ++++++++++++++-- .../S3/Custom/AmazonS3Client.Extensions.cs | 11 ++++++++ .../S3/Custom/Util/AmazonS3HttpUtil.cs | 14 ++++++---- ...zonSecurityTokenServiceClient.Extension.cs | 16 ++++++++++- 11 files changed, 171 insertions(+), 11 deletions(-) diff --git a/sdk/src/Core/Amazon.Runtime/Pipeline/HttpHandler/_bcl/HttpWebRequestFactory.cs b/sdk/src/Core/Amazon.Runtime/Pipeline/HttpHandler/_bcl/HttpWebRequestFactory.cs index a118ff34e5f4..8d989dc5d0dc 100644 --- a/sdk/src/Core/Amazon.Runtime/Pipeline/HttpHandler/_bcl/HttpWebRequestFactory.cs +++ b/sdk/src/Core/Amazon.Runtime/Pipeline/HttpHandler/_bcl/HttpWebRequestFactory.cs @@ -474,6 +474,14 @@ public virtual void ConfigureRequest(IRequestContext requestContext) requestContext.Metrics.AddProperty(Metric.ProxyPort, requestContext.ClientConfig.ProxyPort); _request.Proxy = proxy; } + else if (_request.RequestUri.Scheme == Uri.UriSchemeHttp) + { + _request.Proxy = requestContext.ClientConfig.GetHttpProxy(); + } + else if (_request.RequestUri.Scheme == Uri.UriSchemeHttps) + { + _request.Proxy = requestContext.ClientConfig.GetHttpsProxy(); + } // Set service point properties. _request.ServicePoint.ConnectionLimit = clientConfig.ConnectionLimit; diff --git a/sdk/src/Core/Amazon.Runtime/Pipeline/HttpHandler/_netstandard/HttpRequestMessageFactory.cs b/sdk/src/Core/Amazon.Runtime/Pipeline/HttpHandler/_netstandard/HttpRequestMessageFactory.cs index bc6d279e8a6f..b8b345e93651 100644 --- a/sdk/src/Core/Amazon.Runtime/Pipeline/HttpHandler/_netstandard/HttpRequestMessageFactory.cs +++ b/sdk/src/Core/Amazon.Runtime/Pipeline/HttpHandler/_netstandard/HttpRequestMessageFactory.cs @@ -270,7 +270,11 @@ private static HttpClient CreateManagedHttpClient(IClientConfig clientConfig) } try - { + { + // HTTP Client will automatically read `HTTP_PROXY`, + // and `HTTPS_PROXY`. So we let it use those variables, since + // we don't know at client construction time whether they're + // using HTTP or HTTPS. var proxy = clientConfig.GetWebProxy(); if (proxy != null) { diff --git a/sdk/src/Core/Amazon.Runtime/_bcl/ClientConfig.cs b/sdk/src/Core/Amazon.Runtime/_bcl/ClientConfig.cs index df3a34b47ff8..a3dff3af9ede 100644 --- a/sdk/src/Core/Amazon.Runtime/_bcl/ClientConfig.cs +++ b/sdk/src/Core/Amazon.Runtime/_bcl/ClientConfig.cs @@ -133,6 +133,34 @@ public WebProxy GetWebProxy() return proxy; } + /// + /// Returns a WebProxy instance to use for HTTPS connections if an + /// explicit web proxy hasn't been configured. + /// + public WebProxy GetHttpsProxy() + { + var httpsProxy = Environment.GetEnvironmentVariable("https_proxy"); + if (!string.IsNullOrEmpty(httpsProxy)) + { + return new WebProxy(httpsProxy); + } + return null; + } + + /// + /// Returns a WebProxy instance to use for HTTP connections if an + /// explicit web proxy hasn't been configured. + /// + public WebProxy GetHttpProxy() + { + var httpProxy = Environment.GetEnvironmentVariable("http_proxy"); + if (!string.IsNullOrEmpty(httpProxy)) + { + return new WebProxy(httpProxy); + } + return null; + } + /// /// Unpacks the host, port and any credentials info into the instance's /// proxy-related fields. diff --git a/sdk/src/Core/Amazon.Runtime/_bcl/IClientConfig.bcl.cs b/sdk/src/Core/Amazon.Runtime/_bcl/IClientConfig.bcl.cs index 6425c0db5ccb..d5186dee9161 100644 --- a/sdk/src/Core/Amazon.Runtime/_bcl/IClientConfig.bcl.cs +++ b/sdk/src/Core/Amazon.Runtime/_bcl/IClientConfig.bcl.cs @@ -70,5 +70,16 @@ public partial interface IClientConfig /// WebProxy GetWebProxy(); + /// + /// Returns a WebProxy instance to use for HTTPS connections if an + /// explicit web proxy hasn't been configured. + /// + WebProxy GetHttpsProxy(); + + /// + /// Returns a WebProxy instance to use for HTTP connections if an + /// explicit web proxy hasn't been configured. + /// + WebProxy GetHttpProxy(); } } \ No newline at end of file diff --git a/sdk/src/Core/Amazon.Runtime/_netstandard/ClientConfig.cs b/sdk/src/Core/Amazon.Runtime/_netstandard/ClientConfig.cs index fedf026bd769..b92fa6547d0f 100644 --- a/sdk/src/Core/Amazon.Runtime/_netstandard/ClientConfig.cs +++ b/sdk/src/Core/Amazon.Runtime/_netstandard/ClientConfig.cs @@ -46,6 +46,34 @@ public IWebProxy GetWebProxy() return proxy; } + /// + /// Returns a WebProxy instance to use for HTTPS connections if an + /// explicit web proxy hasn't been configured. + /// + public IWebProxy GetHttpsProxy() + { + var httpsProxy = Environment.GetEnvironmentVariable("https_proxy"); + if (!string.IsNullOrEmpty(httpsProxy)) + { + return new Amazon.Runtime.Internal.Util.WebProxy(httpsProxy); + } + return proxy; + } + + /// + /// Returns a WebProxy instance to use for HTTP connections if an + /// explicit web proxy hasn't been configured. + /// + public IWebProxy GetHttpProxy() + { + var httpProxy = Environment.GetEnvironmentVariable("http_proxy"); + if (!string.IsNullOrEmpty(httpProxy)) + { + return new Amazon.Runtime.Internal.Util.WebProxy(httpProxy); + } + return proxy; + } + /// /// Unpacks the host, port and any credentials info into the instance's /// proxy-related fields. diff --git a/sdk/src/Core/Amazon.Runtime/_netstandard/IClientConfig.cs b/sdk/src/Core/Amazon.Runtime/_netstandard/IClientConfig.cs index 11306e21e0b4..470e84710047 100644 --- a/sdk/src/Core/Amazon.Runtime/_netstandard/IClientConfig.cs +++ b/sdk/src/Core/Amazon.Runtime/_netstandard/IClientConfig.cs @@ -43,6 +43,18 @@ public partial interface IClientConfig /// IWebProxy GetWebProxy(); + /// + /// Returns a WebProxy instance to use for HTTPS connections if an + /// explicit web proxy hasn't been configured. + /// + IWebProxy GetHttpsProxy(); + + /// + /// Returns a WebProxy instance to use for HTTP connections if an + /// explicit web proxy hasn't been configured. + /// + IWebProxy GetHttpProxy(); + /// /// HttpClientFactory used to create new HttpClients. /// If null, an HttpClient will be created by the SDK. diff --git a/sdk/src/Services/EC2/Custom/Util/_async/ImageUtilities.async.cs b/sdk/src/Services/EC2/Custom/Util/_async/ImageUtilities.async.cs index f212c247be74..3a5d2e215194 100644 --- a/sdk/src/Services/EC2/Custom/Util/_async/ImageUtilities.async.cs +++ b/sdk/src/Services/EC2/Custom/Util/_async/ImageUtilities.async.cs @@ -82,10 +82,17 @@ private static async Task LoadDefinitionsFromWebAsync(AmazonEC2Config ec2Config) if (ImageDefinitionsLoaded) return; } + const string httpPrefix = "http://"; + const string httpsPrefix = "https://"; IWebProxy webProxy = null; - if (ec2Config != null) + IWebProxy httpProxy = null; + IWebProxy httpsProxy = null; + if (ec2Config != null) { webProxy = ec2Config.GetWebProxy(); + httpProxy = ec2Config.GetHttpProxy(); + httpsProxy = ec2Config.GetHttpsProxy(); + } int retries = 0; while (retries < MAX_DOWNLOAD_RETRIES) @@ -95,9 +102,22 @@ private static async Task LoadDefinitionsFromWebAsync(AmazonEC2Config ec2Config) HttpWebResponse response = null; foreach (var location in DownloadLocations) { + var useProxy = webProxy; + if (useProxy == null) + { + if (location.StartsWith(httpPrefix)) + { + useProxy = httpProxy; + } + else if (location.StartsWith(httpsPrefix)) + { + useProxy = httpsProxy; + } + } + try { - response = await DownloadControlFileAsync(location, webProxy).ConfigureAwait(false); + response = await DownloadControlFileAsync(location, useProxy).ConfigureAwait(false); if (response != null) break; } diff --git a/sdk/src/Services/EC2/Custom/Util/_bcl/ImageUtilities.bcl.cs b/sdk/src/Services/EC2/Custom/Util/_bcl/ImageUtilities.bcl.cs index 35cd7ee4eae2..9ffb0b5e7382 100644 --- a/sdk/src/Services/EC2/Custom/Util/_bcl/ImageUtilities.bcl.cs +++ b/sdk/src/Services/EC2/Custom/Util/_bcl/ImageUtilities.bcl.cs @@ -82,10 +82,17 @@ private static void LoadDefinitionsFromWeb(AmazonEC2Config ec2Config) if (ImageDefinitionsLoaded) return; } + const string httpPrefix = "http://"; + const string httpsPrefix = "https://"; IWebProxy webProxy = null; - if (ec2Config != null) + IWebProxy httpProxy = null; + IWebProxy httpsProxy = null; + if (ec2Config != null) { webProxy = ec2Config.GetWebProxy(); + httpProxy = ec2Config.GetHttpProxy(); + httpsProxy = ec2Config.GetHttpsProxy(); + } int retries = 0; while (retries < MAX_DOWNLOAD_RETRIES) @@ -95,9 +102,22 @@ private static void LoadDefinitionsFromWeb(AmazonEC2Config ec2Config) HttpWebResponse response = null; foreach (var location in DownloadLocations) { + var useProxy = webProxy; + if (useProxy == null) + { + if (location.StartsWith(httpPrefix)) + { + useProxy = httpProxy; + } + else if (location.StartsWith(httpsPrefix)) + { + useProxy = httpsProxy; + } + } + try { - response = DownloadControlFile(location, webProxy); + response = DownloadControlFile(location, useProxy); if (response != null) break; } diff --git a/sdk/src/Services/S3/Custom/AmazonS3Client.Extensions.cs b/sdk/src/Services/S3/Custom/AmazonS3Client.Extensions.cs index 5525e45ad330..3a557559bcba 100644 --- a/sdk/src/Services/S3/Custom/AmazonS3Client.Extensions.cs +++ b/sdk/src/Services/S3/Custom/AmazonS3Client.Extensions.cs @@ -361,6 +361,17 @@ internal void ConfigureProxy(HttpWebRequest httpRequest) { httpRequest.Proxy.Credentials = Config.ProxyCredentials; } + if (httpRequest.Proxy == null) + { + if (httpRequest.RequestUri.Scheme == Uri.UriSchemeHttp) + { + httpRequest.Proxy = Config.GetHttpProxy(); + } + else if (httpRequest.RequestUri.Scheme == Uri.UriSchemeHttps) + { + httpRequest.Proxy = Config.GetHttpsProxy(); + } + } } diff --git a/sdk/src/Services/S3/Custom/Util/AmazonS3HttpUtil.cs b/sdk/src/Services/S3/Custom/Util/AmazonS3HttpUtil.cs index aac06b86847d..a81379623280 100644 --- a/sdk/src/Services/S3/Custom/Util/AmazonS3HttpUtil.cs +++ b/sdk/src/Services/S3/Custom/Util/AmazonS3HttpUtil.cs @@ -112,15 +112,19 @@ private static GetHeadResponse HandleWebException(string header, WebException we private static void SetProxyIfAvailableAndConfigured(IClientConfig config, HttpWebRequest httpWebRequest) { - var proxy = GetProxyIfAvailableAndConfigured(config); + var proxy = config.GetWebProxy(); if (proxy != null) { httpWebRequest.Proxy = proxy; } - } - private static IWebProxy GetProxyIfAvailableAndConfigured(IClientConfig config) - { - return config.GetWebProxy(); + else if (httpWebRequest.RequestUri.Scheme == Uri.UriSchemeHttp) + { + httpWebRequest.Proxy = config.GetHttpProxy(); + } + else if (httpWebRequest.RequestUri.Scheme == Uri.UriSchemeHttps) + { + httpWebRequest.Proxy = config.GetHttpsProxy(); + } } } } diff --git a/sdk/src/Services/SecurityToken/Custom/AmazonSecurityTokenServiceClient.Extension.cs b/sdk/src/Services/SecurityToken/Custom/AmazonSecurityTokenServiceClient.Extension.cs index 2aab79b99b09..0008ca0246b8 100644 --- a/sdk/src/Services/SecurityToken/Custom/AmazonSecurityTokenServiceClient.Extension.cs +++ b/sdk/src/Services/SecurityToken/Custom/AmazonSecurityTokenServiceClient.Extension.cs @@ -40,11 +40,25 @@ public partial class AmazonSecurityTokenServiceClient : AmazonServiceClient, IAm TimeSpan credentialDuration, ICredentials userCredential) { + const string httpPrefix = "http://"; + const string httpsPrefix = "https://"; SAMLAssertion assertion; try { - var authController = new SAMLAuthenticationController(Config.GetWebProxy()); + var proxy = Config.GetWebProxy(); + if (proxy == null) + { + if (endpoint.StartsWith(httpPrefix)) + { + proxy = Config.GetHttpProxy(); + } + else if (endpoint.StartsWith(httpsPrefix)) + { + proxy = Config.GetHttpsProxy(); + } + } + var authController = new SAMLAuthenticationController(proxy); assertion = authController.GetSAMLAssertion(endpoint, userCredential, authenticationType); } catch (Exception e)