diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000..3f0e003 --- /dev/null +++ b/nuget.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/Elastic.Transport/Components/Connection/HttpConnection.cs b/src/Elastic.Transport/Components/Connection/HttpConnection.cs index b7f48b7..05bb440 100644 --- a/src/Elastic.Transport/Components/Connection/HttpConnection.cs +++ b/src/Elastic.Transport/Components/Connection/HttpConnection.cs @@ -286,53 +286,31 @@ protected virtual void SetAuthenticationIfNeeded(HttpRequestMessage requestMessa return; } - // Api Key authentication takes precedence - var apiKeySet = SetApiKeyAuthenticationIfNeeded(requestMessage, requestData); - - if (!apiKeySet) - SetBasicAuthenticationIfNeeded(requestMessage, requestData); + SetConfiguredAuthenticationHeaderIfNeeded(requestMessage, requestData); } - private static bool SetApiKeyAuthenticationIfNeeded(HttpRequestMessage requestMessage, RequestData requestData) - { - // ApiKey auth credentials take the following precedence (highest -> lowest): - // 1 - Specified on the request (highest precedence) - // 2 - Specified at the global IConnectionSettings level - - - string apiKey = null; - if (requestData.ApiKeyAuthenticationCredentials != null) - apiKey = requestData.ApiKeyAuthenticationCredentials.Base64EncodedApiKey.CreateString(); - - if (string.IsNullOrWhiteSpace(apiKey)) - return false; - - requestMessage.Headers.Authorization = new AuthenticationHeaderValue("ApiKey", apiKey); - return true; - - } - - private static void SetBasicAuthenticationIfNeeded(HttpRequestMessage requestMessage, RequestData requestData) + private static void SetConfiguredAuthenticationHeaderIfNeeded(HttpRequestMessage requestMessage, RequestData requestData) { // Basic auth credentials take the following precedence (highest -> lowest): - // 1 - Specified on the request (highest precedence) - // 2 - Specified at the global IConnectionSettings level - // 3 - Specified with the URI (lowest precedence) + // 1 - Specified with the URI (highest precedence) + // 2 - Specified on the request + // 3 - Specified at the global IConnectionSettings level (lowest precedence) - string userInfo = null; + string value = null; + string key = null; if (!requestData.Uri.UserInfo.IsNullOrEmpty()) - userInfo = Uri.UnescapeDataString(requestData.Uri.UserInfo); - else if (requestData.BasicAuthorizationCredentials != null) { - userInfo = - $"{requestData.BasicAuthorizationCredentials.Username}:{requestData.BasicAuthorizationCredentials.Password.CreateString()}"; + value = BasicAuthentication.GetBase64String(Uri.UnescapeDataString(requestData.Uri.UserInfo)); + key = BasicAuthentication.Base64Header; } - - if (!userInfo.IsNullOrEmpty()) + else if (requestData.AuthenticationHeader != null && requestData.AuthenticationHeader.TryGetHeader(out var v)) { - var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(userInfo!)); - requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials); + value = v; + key = requestData.AuthenticationHeader.Header; } + + if (value.IsNullOrEmpty()) return; + requestMessage.Headers.Authorization = new AuthenticationHeaderValue(key, value); } private static HttpRequestMessage CreateRequestMessage(RequestData requestData) diff --git a/src/Elastic.Transport/Components/Connection/HttpWebRequestConnection.cs b/src/Elastic.Transport/Components/Connection/HttpWebRequestConnection.cs index 6817e30..a11bbbf 100644 --- a/src/Elastic.Transport/Components/Connection/HttpWebRequestConnection.cs +++ b/src/Elastic.Transport/Components/Connection/HttpWebRequestConnection.cs @@ -311,11 +311,14 @@ protected virtual void SetProxyIfNeeded(HttpWebRequest request, RequestData requ /// Hook for subclasses to set authentication on protected virtual void SetAuthenticationIfNeeded(RequestData requestData, HttpWebRequest request) { - // Api Key authentication takes precedence - var apiKeySet = SetApiKeyAuthenticationIfNeeded(request, requestData); - - if (!apiKeySet) - SetBasicAuthenticationIfNeeded(request, requestData); + //If user manually specifies an Authorization Header give it preference + if (requestData.Headers.HasKeys() && requestData.Headers.AllKeys.Contains("Authorization")) + { + var header = requestData.Headers["Authorization"]; + request.Headers["Authorization"] = header; + return; + } + SetBasicAuthenticationIfNeeded(request, requestData); } private static void SetBasicAuthenticationIfNeeded(HttpWebRequest request, RequestData requestData) @@ -325,37 +328,28 @@ private static void SetBasicAuthenticationIfNeeded(HttpWebRequest request, Reque // 2 - Specified at the global IConnectionSettings level // 3 - Specified with the URI (lowest precedence) - string userInfo = null; - if (!string.IsNullOrEmpty(requestData.Uri.UserInfo)) - userInfo = Uri.UnescapeDataString(requestData.Uri.UserInfo); - else if (requestData.BasicAuthorizationCredentials != null) - { - userInfo = - $"{requestData.BasicAuthorizationCredentials.Username}:{requestData.BasicAuthorizationCredentials.Password.CreateString()}"; - } - - if (string.IsNullOrWhiteSpace(userInfo)) - return; - - request.Headers["Authorization"] = $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes(userInfo))}"; - } - private static bool SetApiKeyAuthenticationIfNeeded(HttpWebRequest request, RequestData requestData) - { - // ApiKey auth credentials take the following precedence (highest -> lowest): - // 1 - Specified on the request (highest precedence) - // 2 - Specified at the global IConnectionSettings level - - string apiKey = null; - if (requestData.ApiKeyAuthenticationCredentials != null) - apiKey = requestData.ApiKeyAuthenticationCredentials.Base64EncodedApiKey.CreateString(); + // Basic auth credentials take the following precedence (highest -> lowest): + // 1 - Specified with the URI (highest precedence) + // 2 - Specified on the request + // 3 - Specified at the global IConnectionSettings level (lowest precedence) - if (string.IsNullOrWhiteSpace(apiKey)) - return false; + string value = null; + string key = null; + if (!requestData.Uri.UserInfo.IsNullOrEmpty()) + { + value = BasicAuthentication.GetBase64String(Uri.UnescapeDataString(requestData.Uri.UserInfo)); + key = BasicAuthentication.Base64Header; + } + else if (requestData.AuthenticationHeader != null && requestData.AuthenticationHeader.TryGetHeader(out var v)) + { + value = v; + key = requestData.AuthenticationHeader.Header; + } - request.Headers["Authorization"] = $"ApiKey {apiKey}"; - return true; + if (value.IsNullOrEmpty()) return; + request.Headers["Authorization"] = $"{key} {value}"; } /// diff --git a/src/Elastic.Transport/Components/ConnectionPool/CloudConnectionPool.cs b/src/Elastic.Transport/Components/ConnectionPool/CloudConnectionPool.cs index 4c0797c..85c5e9a 100644 --- a/src/Elastic.Transport/Components/ConnectionPool/CloudConnectionPool.cs +++ b/src/Elastic.Transport/Components/ConnectionPool/CloudConnectionPool.cs @@ -37,32 +37,8 @@ public class CloudConnectionPool : SingleNodeConnectionPool /// /// /// Optionally inject an instance of used to set - public CloudConnectionPool(string cloudId, BasicAuthenticationCredentials credentials, IDateTimeProvider dateTimeProvider = null) : this(ParseCloudId(cloudId), dateTimeProvider) => - BasicCredentials = credentials; - - /// - /// An implementation that can be seeded with a cloud id - /// and will signal the right defaults for the client to use for Elastic Cloud to . - /// - /// Read more about Elastic Cloud Id here - /// https://www.elastic.co/guide/en/cloud/current/ec-cloud-id.html - /// - /// - /// The Cloud Id, this is available on your cluster's dashboard and is a string in the form of cluster_name:base_64_encoded_string - /// Base64 encoded string contains the following tokens in order separated by $: - /// * Host Name (mandatory) - /// * Elasticsearch UUID (mandatory) - /// * Kibana UUID - /// * APM UUID - /// - /// We then use these tokens to create the URI to your Elastic Cloud cluster! - /// - /// Read more here: https://www.elastic.co/guide/en/cloud/current/ec-cloud-id.html - /// - /// - /// Optionally inject an instance of used to set - public CloudConnectionPool(string cloudId, ApiKeyAuthenticationCredentials credentials, IDateTimeProvider dateTimeProvider = null) : this(ParseCloudId(cloudId), dateTimeProvider) => - ApiKeyCredentials = credentials; + public CloudConnectionPool(string cloudId, IAuthenticationHeader credentials, IDateTimeProvider dateTimeProvider = null) : this(ParseCloudId(cloudId), dateTimeProvider) => + AuthenticationHeader = credentials; private CloudConnectionPool(ParsedCloudId parsedCloudId, IDateTimeProvider dateTimeProvider = null) : base(parsedCloudId.Uri, dateTimeProvider) => ClusterName = parsedCloudId.Name; @@ -71,11 +47,8 @@ private CloudConnectionPool(ParsedCloudId parsedCloudId, IDateTimeProvider dateT // ReSharper disable once UnusedAutoPropertyAccessor.Local private string ClusterName { get; } - /// Read-only access to the basic authentication credentials that were passed in - public BasicAuthenticationCredentials BasicCredentials { get; } - - /// Read-only access to the api key authentication credentials that were passed in - public ApiKeyAuthenticationCredentials ApiKeyCredentials { get; } + /// + public IAuthenticationHeader AuthenticationHeader { get; } private readonly struct ParsedCloudId { @@ -121,10 +94,6 @@ private static ParsedCloudId ParseCloudId(string cloudId) } /// Allows subclasses to hook into the parents dispose - protected override void DisposeManagedResources() - { - ApiKeyCredentials?.Dispose(); - BasicCredentials?.Dispose(); - } + protected override void DisposeManagedResources() => AuthenticationHeader?.Dispose(); } } diff --git a/src/Elastic.Transport/Components/Pipeline/RequestData.cs b/src/Elastic.Transport/Components/Pipeline/RequestData.cs index 8e295ba..fa512e7 100644 --- a/src/Elastic.Transport/Components/Pipeline/RequestData.cs +++ b/src/Elastic.Transport/Components/Pipeline/RequestData.cs @@ -94,8 +94,7 @@ IMemoryStreamFactory memoryStreamFactory ProxyUsername = global.ProxyUsername; ProxyPassword = global.ProxyPassword; DisableAutomaticProxyDetection = global.DisableAutomaticProxyDetection; - BasicAuthorizationCredentials = local?.BasicAuthenticationCredentials ?? global.BasicAuthenticationCredentials; - ApiKeyAuthenticationCredentials = local?.ApiKeyAuthenticationCredentials ?? global.ApiKeyAuthenticationCredentials; + AuthenticationHeader = local?.AuthenticationHeader ?? global.AuthenticationHeader; AllowedStatusCodes = local?.AllowedStatusCodes ?? EmptyReadOnly.Collection; ClientCertificates = local?.ClientCertificates ?? global.ClientCertificates; UserAgent = global.UserAgent; @@ -109,9 +108,7 @@ IMemoryStreamFactory memoryStreamFactory public string Accept { get; } public IReadOnlyCollection AllowedStatusCodes { get; } - public ApiKeyAuthenticationCredentials ApiKeyAuthenticationCredentials { get; } - - public BasicAuthenticationCredentials BasicAuthorizationCredentials { get; } + public IAuthenticationHeader AuthenticationHeader { get; } public X509CertificateCollection ClientCertificates { get; } public ITransportConfigurationValues ConnectionSettings { get; } diff --git a/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs b/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs index af54ca0..a8dd478 100644 --- a/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs +++ b/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs @@ -62,8 +62,7 @@ IRequestParameters requestParameters { PingTimeout = PingTimeout, RequestTimeout = PingTimeout, - BasicAuthenticationCredentials = _settings.BasicAuthenticationCredentials, - ApiKeyAuthenticationCredentials = _settings.ApiKeyAuthenticationCredentials, + AuthenticationHeader = _settings.AuthenticationHeader, EnableHttpPipelining = RequestConfiguration?.EnableHttpPipelining ?? _settings.HttpPipeliningEnabled, ForceNode = RequestConfiguration?.ForceNode }; diff --git a/src/Elastic.Transport/Configuration/ITransportConfigurationValues.cs b/src/Elastic.Transport/Configuration/ITransportConfigurationValues.cs index c69be32..330854c 100644 --- a/src/Elastic.Transport/Configuration/ITransportConfigurationValues.cs +++ b/src/Elastic.Transport/Configuration/ITransportConfigurationValues.cs @@ -19,21 +19,8 @@ namespace Elastic.Transport /// public interface ITransportConfigurationValues : IDisposable { - /// - /// Basic access authorization credentials to specify with all requests. - /// - /// - /// Cannot be used in conjuction with - /// - BasicAuthenticationCredentials BasicAuthenticationCredentials { get; } - - /// - /// Api Key authorization credentials to specify with all requests. - /// - /// - /// Cannot be used in conjuction with - /// - ApiKeyAuthenticationCredentials ApiKeyAuthenticationCredentials { get; } + /// + IAuthenticationHeader AuthenticationHeader { get; } /// Provides a semaphoreslim to transport implementations that need to limit access to a resource SemaphoreSlim BootstrapLock { get; } diff --git a/src/Elastic.Transport/Configuration/RequestConfiguration.cs b/src/Elastic.Transport/Configuration/RequestConfiguration.cs index 2ca19cc..341eeb3 100644 --- a/src/Elastic.Transport/Configuration/RequestConfiguration.cs +++ b/src/Elastic.Transport/Configuration/RequestConfiguration.cs @@ -27,22 +27,9 @@ public interface IRequestConfiguration IReadOnlyCollection AllowedStatusCodes { get; set; } /// - /// Basic access authorization credentials to specify with this request. - /// Overrides any credentials that are set at the global IConnectionSettings level. + /// Provide an authentication header override for this request /// - /// - /// Cannot be used in conjunction with - /// - BasicAuthenticationCredentials BasicAuthenticationCredentials { get; set; } - - /// - /// An API-key authorization credentials to specify with this request. - /// Overrides any credentials that are set at the global IConnectionSettings level. - /// - /// - /// Cannot be used in conjunction with - /// - ApiKeyAuthenticationCredentials ApiKeyAuthenticationCredentials { get; set; } + IAuthenticationHeader AuthenticationHeader { get; set; } /// /// Use the following client certificates to authenticate this single request @@ -140,9 +127,7 @@ public class RequestConfiguration : IRequestConfiguration /// public IReadOnlyCollection AllowedStatusCodes { get; set; } /// - public BasicAuthenticationCredentials BasicAuthenticationCredentials { get; set; } - /// - public ApiKeyAuthenticationCredentials ApiKeyAuthenticationCredentials { get; set; } + public IAuthenticationHeader AuthenticationHeader { get; set; } /// public X509CertificateCollection ClientCertificates { get; set; } /// @@ -195,8 +180,7 @@ public RequestConfigurationDescriptor(IRequestConfiguration config) Self.DisablePing = config?.DisablePing; Self.DisableDirectStreaming = config?.DisableDirectStreaming; Self.AllowedStatusCodes = config?.AllowedStatusCodes; - Self.BasicAuthenticationCredentials = config?.BasicAuthenticationCredentials; - Self.ApiKeyAuthenticationCredentials = config?.ApiKeyAuthenticationCredentials; + Self.AuthenticationHeader = config?.AuthenticationHeader; Self.EnableHttpPipelining = config?.EnableHttpPipelining ?? true; Self.RunAs = config?.RunAs; Self.ClientCertificates = config?.ClientCertificates; @@ -210,8 +194,7 @@ public RequestConfigurationDescriptor(IRequestConfiguration config) string IRequestConfiguration.Accept { get; set; } IReadOnlyCollection IRequestConfiguration.AllowedStatusCodes { get; set; } - BasicAuthenticationCredentials IRequestConfiguration.BasicAuthenticationCredentials { get; set; } - ApiKeyAuthenticationCredentials IRequestConfiguration.ApiKeyAuthenticationCredentials { get; set; } + IAuthenticationHeader IRequestConfiguration.AuthenticationHeader { get; set; } X509CertificateCollection IRequestConfiguration.ClientCertificates { get; set; } string IRequestConfiguration.ContentType { get; set; } bool? IRequestConfiguration.DisableDirectStreaming { get; set; } @@ -329,45 +312,10 @@ public RequestConfigurationDescriptor MaxRetries(int retry) return this; } - /// - public RequestConfigurationDescriptor BasicAuthentication(string userName, string password) - { - Self.BasicAuthenticationCredentials = new BasicAuthenticationCredentials(userName, password); - return this; - } - - /// - public RequestConfigurationDescriptor BasicAuthentication(string userName, SecureString password) - { - Self.BasicAuthenticationCredentials = new BasicAuthenticationCredentials(userName, password); - return this; - } - - /// - public RequestConfigurationDescriptor ApiKeyAuthentication(string id, string apiKey) - { - Self.ApiKeyAuthenticationCredentials = new ApiKeyAuthenticationCredentials(id, apiKey); - return this; - } - - /// - public RequestConfigurationDescriptor ApiKeyAuthentication(string id, SecureString apiKey) - { - Self.ApiKeyAuthenticationCredentials = new ApiKeyAuthenticationCredentials(id, apiKey); - return this; - } - - /// - public RequestConfigurationDescriptor ApiKeyAuthentication(string base64EncodedApiKey) - { - Self.ApiKeyAuthenticationCredentials = new ApiKeyAuthenticationCredentials(base64EncodedApiKey); - return this; - } - - /// - public RequestConfigurationDescriptor ApiKeyAuthentication(SecureString base64EncodedApiKey) + /// + public RequestConfigurationDescriptor Authentication(IAuthenticationHeader authentication) { - Self.ApiKeyAuthenticationCredentials = new ApiKeyAuthenticationCredentials(base64EncodedApiKey); + Self.AuthenticationHeader = authentication; return this; } diff --git a/src/Elastic.Transport/Configuration/Security/ApiKey.cs b/src/Elastic.Transport/Configuration/Security/ApiKey.cs new file mode 100644 index 0000000..45bdd4a --- /dev/null +++ b/src/Elastic.Transport/Configuration/Security/ApiKey.cs @@ -0,0 +1,37 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System; +using System.Security; + +namespace Elastic.Transport +{ + /// + /// Credentials for Api Key Authentication + /// + public class ApiKey : IAuthenticationHeader + { + /// + public ApiKey(string apiKey) => Value = apiKey.CreateSecureString(); + + /// + public ApiKey(SecureString apiKey) => Value = apiKey; + + private SecureString Value { get; } + + /// + public virtual string Header { get; } = "Bearer"; + + /// + public bool TryGetHeader(out string value) + { + value = Value.CreateString(); + return true; + } + + /// + public void Dispose() => Value?.Dispose(); + + } +} diff --git a/src/Elastic.Transport/Configuration/Security/ApiKeyAuthenticationCredentials.cs b/src/Elastic.Transport/Configuration/Security/ApiKeyAuthenticationCredentials.cs deleted file mode 100644 index 2018192..0000000 --- a/src/Elastic.Transport/Configuration/Security/ApiKeyAuthenticationCredentials.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Licensed to Elasticsearch B.V under one or more agreements. -// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. -// See the LICENSE file in the project root for more information - -using System; -using System.Security; -using System.Text; - -namespace Elastic.Transport -{ - /// - /// Credentials for Api Key Authentication - /// - public class ApiKeyAuthenticationCredentials : IDisposable - { - /// - public ApiKeyAuthenticationCredentials(string id, SecureString apiKey) => - Base64EncodedApiKey = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{apiKey.CreateString()}")).CreateSecureString(); - - /// - public ApiKeyAuthenticationCredentials(string id, string apiKey) => - Base64EncodedApiKey = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{apiKey}")).CreateSecureString(); - - /// - public ApiKeyAuthenticationCredentials(string base64EncodedApiKey) => - Base64EncodedApiKey = base64EncodedApiKey.CreateSecureString(); - - /// - public ApiKeyAuthenticationCredentials(SecureString base64EncodedApiKey) => - Base64EncodedApiKey = base64EncodedApiKey; - - /// - /// The Base64 encoded api key with which to authenticate - /// Take the form, id:api_key, which is then base 64 encoded - /// - public SecureString Base64EncodedApiKey { get; } - - /// - public void Dispose() => Base64EncodedApiKey?.Dispose(); - } -} diff --git a/src/Elastic.Transport/Configuration/Security/Base64ApiKey.cs b/src/Elastic.Transport/Configuration/Security/Base64ApiKey.cs new file mode 100644 index 0000000..17d32d1 --- /dev/null +++ b/src/Elastic.Transport/Configuration/Security/Base64ApiKey.cs @@ -0,0 +1,47 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System; +using System.Security; +using System.Text; + +namespace Elastic.Transport +{ + /// + /// Credentials for Api Key Authentication + /// + public class Base64ApiKey : IAuthenticationHeader + { + /// + public Base64ApiKey(string id, SecureString apiKey) => + Value = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{apiKey.CreateString()}")).CreateSecureString(); + + /// + public Base64ApiKey(string id, string apiKey) => + Value = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{apiKey}")).CreateSecureString(); + + /// + public Base64ApiKey(string base64EncodedApiKey) => + Value = base64EncodedApiKey.CreateSecureString(); + + /// + public Base64ApiKey(SecureString base64EncodedApiKey) => + Value = base64EncodedApiKey; + + private SecureString Value { get; } + + /// + public void Dispose() => Value?.Dispose(); + + /// + public string Header { get; } = "ApiKey"; + + /// + public bool TryGetHeader(out string value) + { + value = Value.CreateString(); + return true; + } + } +} diff --git a/src/Elastic.Transport/Configuration/Security/BasicAuthenticationCredentials.cs b/src/Elastic.Transport/Configuration/Security/BasicAuthenticationCredentials.cs index 7376b09..074589a 100644 --- a/src/Elastic.Transport/Configuration/Security/BasicAuthenticationCredentials.cs +++ b/src/Elastic.Transport/Configuration/Security/BasicAuthenticationCredentials.cs @@ -4,34 +4,53 @@ using System; using System.Security; +using System.Text; namespace Elastic.Transport { /// Credentials for Basic Authentication - public class BasicAuthenticationCredentials : IDisposable + public class BasicAuthentication : IAuthenticationHeader { - /// - public BasicAuthenticationCredentials(string username, string password) + /// + public BasicAuthentication(string username, string password) { Username = username; - Password = password.CreateSecureString(); + _cachedHeaderValue = GetBase64String($"{Username}:{password}"); } - /// - public BasicAuthenticationCredentials(string username, SecureString password) + /// + public BasicAuthentication(string username, SecureString password) { Username = username; Password = password; } + private readonly string _cachedHeaderValue; + /// The password with which to authenticate - public SecureString Password { get; set; } + private SecureString Password { get; } /// The username with which to authenticate - public string Username { get; set; } + private string Username { get; } /// public void Dispose() => Password?.Dispose(); + /// + public string Header { get; } = Base64Header; + + /// The default http header used for basic authentication + public static string Base64Header { get; } = "Basic"; + + /// + public bool TryGetHeader(out string value) + { + value = _cachedHeaderValue ?? GetBase64String($"{Username}:{Password.CreateString()}"); + return true; + } + + /// Get Base64 representation for string + public static string GetBase64String(string header) => + Convert.ToBase64String(Encoding.UTF8.GetBytes(header)); } } diff --git a/src/Elastic.Transport/Configuration/Security/IAuthenticationHeader.cs b/src/Elastic.Transport/Configuration/Security/IAuthenticationHeader.cs new file mode 100644 index 0000000..37612a0 --- /dev/null +++ b/src/Elastic.Transport/Configuration/Security/IAuthenticationHeader.cs @@ -0,0 +1,21 @@ +using System; + +namespace Elastic.Transport +{ + /// + /// An implementation of describing what http header to use to authenticate with the product. + /// for basic authentication + /// for simple secret token + /// for Elastic Cloud style encoded api keys + /// + public interface IAuthenticationHeader : IDisposable + { + /// The header to use to authenticate the request + public string Header { get; } + + /// + /// If this instance is valid return the header name and value to use for authentication + /// + bool TryGetHeader(out string value); + } +} diff --git a/src/Elastic.Transport/Configuration/TransportConfiguration.cs b/src/Elastic.Transport/Configuration/TransportConfiguration.cs index 7bb4946..6d9a74e 100644 --- a/src/Elastic.Transport/Configuration/TransportConfiguration.cs +++ b/src/Elastic.Transport/Configuration/TransportConfiguration.cs @@ -118,14 +118,14 @@ public TransportConfiguration(Uri uri = null, IProductRegistration productRegist /// Sets up the client to communicate to Elastic Cloud using , /// documentation for more information on how to obtain your Cloud Id /// - public TransportConfiguration(string cloudId, BasicAuthenticationCredentials credentials, IProductRegistration productRegistration = null) + public TransportConfiguration(string cloudId, BasicAuthentication credentials, IProductRegistration productRegistration = null) : this(new CloudConnectionPool(cloudId, credentials), productRegistration: productRegistration) { } /// /// Sets up the client to communicate to Elastic Cloud using , /// documentation for more information on how to obtain your Cloud Id /// - public TransportConfiguration(string cloudId, ApiKeyAuthenticationCredentials credentials, IProductRegistration productRegistration = null) + public TransportConfiguration(string cloudId, Base64ApiKey credentials, IProductRegistration productRegistration = null) : this(new CloudConnectionPool(cloudId, credentials), productRegistration: productRegistration) { } /// @@ -156,8 +156,7 @@ public abstract class TransportConfigurationBase : ITransportConfigurationVal private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); private readonly UrlFormatter _urlFormatter; - private BasicAuthenticationCredentials _basicAuthCredentials; - private ApiKeyAuthenticationCredentials _apiKeyAuthCredentials; + private IAuthenticationHeader _authenticationHeader; private X509CertificateCollection _clientCertificates; private Action _completedRequestHandler = DefaultCompletedRequestHandler; private int _connectionLimit; @@ -223,8 +222,7 @@ protected TransportConfigurationBase(IConnectionPool connectionPool, IConnection if (connectionPool is CloudConnectionPool cloudPool) { - _basicAuthCredentials = cloudPool.BasicCredentials; - _apiKeyAuthCredentials = cloudPool.ApiKeyCredentials; + _authenticationHeader = cloudPool.AuthenticationHeader; _enableHttpCompression = true; } @@ -238,8 +236,7 @@ protected TransportConfigurationBase(IConnectionPool connectionPool, IConnection // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global protected ITransportSerializer UseThisRequestResponseSerializer { get; set; } - BasicAuthenticationCredentials ITransportConfigurationValues.BasicAuthenticationCredentials => _basicAuthCredentials; - ApiKeyAuthenticationCredentials ITransportConfigurationValues.ApiKeyAuthenticationCredentials => _apiKeyAuthCredentials; + IAuthenticationHeader ITransportConfigurationValues.AuthenticationHeader => _authenticationHeader; SemaphoreSlim ITransportConfigurationValues.BootstrapLock => _semaphore; X509CertificateCollection ITransportConfigurationValues.ClientCertificates => _clientCertificates; IConnection ITransportConfigurationValues.Connection => _connection; @@ -392,25 +389,8 @@ public T OnRequestCompleted(Action handler) => public T OnRequestDataCreated(Action handler) => Assign(handler, (a, v) => a._onRequestDataCreated += v ?? DefaultRequestDataCreated); - /// - public T BasicAuthentication(string username, string password) => - Assign(new BasicAuthenticationCredentials(username, password), (a, v) => a._basicAuthCredentials = v); - - /// - public T BasicAuthentication(string username, SecureString password) => - Assign(new BasicAuthenticationCredentials(username, password), (a, v) => a._basicAuthCredentials = v); - - /// - public T ApiKeyAuthentication(string id, SecureString apiKey) => - Assign(new ApiKeyAuthenticationCredentials(id, apiKey), (a, v) => a._apiKeyAuthCredentials = v); - - /// - public T ApiKeyAuthentication(string id, string apiKey) => - Assign(new ApiKeyAuthenticationCredentials(id, apiKey), (a, v) => a._apiKeyAuthCredentials = v); - - /// - public T ApiKeyAuthentication(ApiKeyAuthenticationCredentials credentials) => - Assign(credentials, (a, v) => a._apiKeyAuthCredentials = v); + /// + public T Authentication(IAuthenticationHeader header) => Assign(header, (a, v) => a._authenticationHeader = v); /// public T EnableHttpPipelining(bool enabled = true) => Assign(enabled, (a, v) => a._enableHttpPipelining = v); @@ -491,8 +471,7 @@ protected virtual void DisposeManagedResources() _connection?.Dispose(); _semaphore?.Dispose(); _proxyPassword?.Dispose(); - _basicAuthCredentials?.Dispose(); - _apiKeyAuthCredentials?.Dispose(); + _authenticationHeader?.Dispose(); } /// Allows subclasses to add/remove default global query string parameters