From adeab58f58852b8e18c7e1fc8e5b0fd40c04a746 Mon Sep 17 00:00:00 2001 From: Boshi Lian Date: Wed, 11 Oct 2017 21:27:22 +0800 Subject: [PATCH 1/3] introduce go client style config creating functions --- ...ubernetesClientConfiguration.ConfigFile.cs | 202 ++++++++++++++++++ ...KubernetesClientConfiguration.InCluster.cs | 35 +++ src/KubernetesClientConfiguration.cs | 161 +------------- src/Utils.cs | 20 +- 4 files changed, 258 insertions(+), 160 deletions(-) create mode 100644 src/KubernetesClientConfiguration.ConfigFile.cs create mode 100644 src/KubernetesClientConfiguration.InCluster.cs diff --git a/src/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClientConfiguration.ConfigFile.cs new file mode 100644 index 000000000..0817d3bd6 --- /dev/null +++ b/src/KubernetesClientConfiguration.ConfigFile.cs @@ -0,0 +1,202 @@ +using System; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; +using k8s.Exceptions; +using k8s.KubeConfigModels; +using YamlDotNet.Serialization; + +namespace k8s +{ + public partial class KubernetesClientConfiguration + { + /// + /// Gets CurrentContext + /// + public string CurrentContext { get; private set; } + + /// + /// kubeconfig Default Location + /// + private static readonly string KubeConfigDefaultLocation = + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), @".kube\config") + : Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".kube/config"); + + /// + /// Initializes a new instance of the class. + /// + /// kubeconfig file info + /// Context to use from kube config + public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentContext = null) + { + var k8SConfig = LoadKubeConfig(kubeconfig ?? new FileInfo(KubeConfigDefaultLocation)); + this.Initialize(k8SConfig, currentContext); + } + + /// + /// Initializes a new instance of the from config file + /// + /// kube api server endpoint + /// kubeconfig filepath + /// + public static KubernetesClientConfiguration BuildConfigFromConfigFile(string masterUrl = null, string kubeconfigPath = null) + { + var k8SConfig = LoadKubeConfig(new FileInfo(kubeconfigPath ?? KubeConfigDefaultLocation)); + var k8SConfiguration = new KubernetesClientConfiguration(); + k8SConfiguration.Initialize(k8SConfig); + + if (!string.IsNullOrWhiteSpace(masterUrl)) + { + k8SConfiguration.Host = masterUrl; + } + return k8SConfiguration; + } + + /// + /// Validates and Intializes Client Configuration + /// + /// Kubernetes Configuration + /// Current Context + private void Initialize(K8SConfiguration k8SConfig, string currentContext = null) + { + if (k8SConfig.Contexts == null) + { + throw new KubeConfigException("No contexts found in kubeconfig"); + } + + if (k8SConfig.Clusters == null) + { + throw new KubeConfigException($"No clusters found in kubeconfig"); + } + + if (k8SConfig.Users == null) + { + throw new KubeConfigException($"No users found in kubeconfig"); + } + + // current context + currentContext = currentContext ?? k8SConfig.CurrentContext; + Context activeContext = + k8SConfig.Contexts.FirstOrDefault( + c => c.Name.Equals(currentContext, StringComparison.OrdinalIgnoreCase)); + if (activeContext == null) + { + throw new KubeConfigException($"CurrentContext: {currentContext} not found in contexts in kubeconfig"); + } + + this.CurrentContext = activeContext.Name; + + // cluster + var clusterDetails = + k8SConfig.Clusters.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.Cluster, + StringComparison.OrdinalIgnoreCase)); + if (clusterDetails?.ClusterEndpoint == null) + { + throw new KubeConfigException($"Cluster not found for context {activeContext} in kubeconfig"); + } + + if (string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.Server)) + { + throw new KubeConfigException($"Server not found for current-context {activeContext} in kubeconfig"); + } + + if (!clusterDetails.ClusterEndpoint.SkipTlsVerify && + string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthorityData) && + string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthority)) + { + throw new KubeConfigException( + $"neither certificate-authority-data nor certificate-authority not found for current-context :{activeContext} in kubeconfig"); + } + + this.Host = clusterDetails.ClusterEndpoint.Server; + if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthorityData)) + { + string data = clusterDetails.ClusterEndpoint.CertificateAuthorityData; + this.SslCaCert = new X509Certificate2(System.Text.Encoding.UTF8.GetBytes(Utils.Base64Decode(data))); + } + else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority)) + { + this.SslCaCert = new X509Certificate2(clusterDetails.ClusterEndpoint.CertificateAuthority); + } + this.SkipTlsVerify = clusterDetails.ClusterEndpoint.SkipTlsVerify; + + // user + this.SetUserDetails(k8SConfig, activeContext); + } + + private void SetUserDetails(K8SConfiguration k8SConfig, Context activeContext) + { + var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.User, + StringComparison.OrdinalIgnoreCase)); + + if (userDetails == null) + { + throw new KubeConfigException("User not found for context {activeContext.Name} in kubeconfig"); + } + + if (userDetails.UserCredentials == null) + { + throw new KubeConfigException($"User credentials not found for user: {userDetails.Name} in kubeconfig"); + } + + var userCredentialsFound = false; + + // Basic and bearer tokens are mutually exclusive + if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.Token)) + { + this.AccessToken = userDetails.UserCredentials.Token; + userCredentialsFound = true; + } + else if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.UserName) && + !string.IsNullOrWhiteSpace(userDetails.UserCredentials.Password)) + { + this.Username = userDetails.UserCredentials.UserName; + this.Password = userDetails.UserCredentials.Password; + userCredentialsFound = true; + } + + // Token and cert based auth can co-exist + if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificateData) && + !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKeyData)) + { + this.ClientCertificateData = userDetails.UserCredentials.ClientCertificateData; + this.ClientCertificateKey = userDetails.UserCredentials.ClientKeyData; + userCredentialsFound = true; + } + + if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificate) && + !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKey)) + { + this.ClientCertificate = userDetails.UserCredentials.ClientCertificate; + this.ClientKey = userDetails.UserCredentials.ClientKey; + userCredentialsFound = true; + } + + if (!userCredentialsFound) + { + throw new KubeConfigException( + $"User: {userDetails.Name} does not have appropriate auth credentials in kubeconfig"); + } + } + + /// + /// Loads Kube Config + /// + /// Kube config file contents + /// Instance of the class + private static K8SConfiguration LoadKubeConfig(FileInfo kubeconfig) + { + if (!kubeconfig.Exists) + { + throw new KubeConfigException($"kubeconfig file not found at {kubeconfig.FullName}"); + } + var kubeconfigContent = File.ReadAllText(kubeconfig.FullName); + + var deserializeBuilder = new DeserializerBuilder(); + var deserializer = deserializeBuilder.Build(); + return deserializer.Deserialize(kubeconfigContent); + } + } +} \ No newline at end of file diff --git a/src/KubernetesClientConfiguration.InCluster.cs b/src/KubernetesClientConfiguration.InCluster.cs new file mode 100644 index 000000000..da70d5f81 --- /dev/null +++ b/src/KubernetesClientConfiguration.InCluster.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using k8s.Exceptions; + +namespace k8s +{ + public partial class KubernetesClientConfiguration + { + private const string ServiceAccountTokenKey = "token"; + private const string ServiceAccountRootCAKey = "ca.crt"; + + public static KubernetesClientConfiguration InClusterConfig() + { + var host = Environment.GetEnvironmentVariable("KUBERNETES_SERVICE_HOST"); + var port = Environment.GetEnvironmentVariable("KUBERNETES_SERVICE_PORT"); + + if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(port)) + { + throw new KubeConfigException( + "unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined"); + } + + var token = File.ReadAllText("/var/run/secrets/kubernetes.io/serviceaccount/" + ServiceAccountTokenKey); + var rootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/" + ServiceAccountRootCAKey; + + return new KubernetesClientConfiguration + { + Host = new UriBuilder("https", host, Convert.ToInt32(port)).ToString(), + AccessToken = token, + SslCaCert = Utils.LoadPemFileCert(rootCAFile) + }; + } + } +} \ No newline at end of file diff --git a/src/KubernetesClientConfiguration.cs b/src/KubernetesClientConfiguration.cs index 90ed05eac..441759e88 100644 --- a/src/KubernetesClientConfiguration.cs +++ b/src/KubernetesClientConfiguration.cs @@ -12,31 +12,13 @@ namespace k8s /// /// Represents a set of kubernetes client configuration settings /// - public class KubernetesClientConfiguration + public partial class KubernetesClientConfiguration { - /// - /// Initializes a new instance of the class. - /// - /// kubeconfig file info - /// Context to use from kube config - public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentContext = null) + private KubernetesClientConfiguration() { - var k8SConfig = this.LoadKubeConfig(kubeconfig ?? new FileInfo(KubeConfigDefaultLocation)); - this.Initialize(k8SConfig, currentContext); + } - /// - /// kubeconfig Default Location - /// - private static readonly string KubeConfigDefaultLocation = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? - Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), @".kube\config") : - Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".kube/config"); - - /// - /// Gets CurrentContext - /// - public string CurrentContext { get; private set; } - /// /// Gets Host /// @@ -95,142 +77,5 @@ public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentC /// /// The access token. public string AccessToken { get; set; } - - /// - /// Validates and Intializes Client Configuration - /// - /// Kubernetes Configuration - /// Current Context - private void Initialize(K8SConfiguration k8SConfig, string currentContext = null) - { - if (k8SConfig.Contexts == null) - { - throw new KubeConfigException("No contexts found in kubeconfig"); - } - - if (k8SConfig.Clusters == null) - { - throw new KubeConfigException($"No clusters found in kubeconfig"); - } - - if (k8SConfig.Users == null) - { - throw new KubeConfigException($"No users found in kubeconfig"); - } - - // current context - currentContext = currentContext ?? k8SConfig.CurrentContext; - Context activeContext = k8SConfig.Contexts.FirstOrDefault(c => c.Name.Equals(currentContext, StringComparison.OrdinalIgnoreCase)); - if (activeContext == null) - { - throw new KubeConfigException($"CurrentContext: {currentContext} not found in contexts in kubeconfig"); - } - - this.CurrentContext = activeContext.Name; - - // cluster - var clusterDetails = k8SConfig.Clusters.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.Cluster, StringComparison.OrdinalIgnoreCase)); - if (clusterDetails?.ClusterEndpoint == null) - { - throw new KubeConfigException($"Cluster not found for context {activeContext} in kubeconfig"); - } - - if (string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.Server)) - { - throw new KubeConfigException($"Server not found for current-context {activeContext} in kubeconfig"); - } - - if (!clusterDetails.ClusterEndpoint.SkipTlsVerify && - string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthorityData) && - string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthority)) - { - throw new KubeConfigException($"neither certificate-authority-data nor certificate-authority not found for current-context :{activeContext} in kubeconfig"); - } - - this.Host = clusterDetails.ClusterEndpoint.Server; - if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthorityData)) - { - string data = clusterDetails.ClusterEndpoint.CertificateAuthorityData; - this.SslCaCert = new X509Certificate2(System.Text.Encoding.UTF8.GetBytes(Utils.Base64Decode(data))); - } - else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority)) - { - this.SslCaCert = new X509Certificate2(clusterDetails.ClusterEndpoint.CertificateAuthority); - } - this.SkipTlsVerify = clusterDetails.ClusterEndpoint.SkipTlsVerify; - - // user - this.SetUserDetails(k8SConfig, activeContext); - } - - private void SetUserDetails(K8SConfiguration k8SConfig, Context activeContext) - { - var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.User, StringComparison.OrdinalIgnoreCase)); - - if (userDetails == null) - { - throw new KubeConfigException("User not found for context {activeContext.Name} in kubeconfig"); - } - - if (userDetails.UserCredentials == null) - { - throw new KubeConfigException($"User credentials not found for user: {userDetails.Name} in kubeconfig"); - } - - var userCredentialsFound = false; - - // Basic and bearer tokens are mutually exclusive - if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.Token)) - { - this.AccessToken = userDetails.UserCredentials.Token; - userCredentialsFound = true; - } - else if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.UserName) && - !string.IsNullOrWhiteSpace(userDetails.UserCredentials.Password)) - { - this.Username = userDetails.UserCredentials.UserName; - this.Password = userDetails.UserCredentials.Password; - userCredentialsFound = true; - } - - // Token and cert based auth can co-exist - if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificateData) && - !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKeyData)) - { - this.ClientCertificateData = userDetails.UserCredentials.ClientCertificateData; - this.ClientCertificateKey = userDetails.UserCredentials.ClientKeyData; - userCredentialsFound = true; - } - - if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificate) && - !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKey)) { - this.ClientCertificate = userDetails.UserCredentials.ClientCertificate; - this.ClientKey = userDetails.UserCredentials.ClientKey; - userCredentialsFound = true; - } - - if (!userCredentialsFound) - { - throw new KubeConfigException($"User: {userDetails.Name} does not have appropriate auth credentials in kubeconfig"); - } - } - - /// - /// Loads Kube Config - /// - /// Kube config file contents - /// Instance of the class - private K8SConfiguration LoadKubeConfig(FileInfo kubeconfig) - { - if (!kubeconfig.Exists) - { - throw new KubeConfigException($"kubeconfig file not found at {kubeconfig.FullName}"); - } - var kubeconfigContent = File.ReadAllText(kubeconfig.FullName); - - var deserializeBuilder = new DeserializerBuilder(); - var deserializer = deserializeBuilder.Build(); - return deserializer.Deserialize(kubeconfigContent); - } } } diff --git a/src/Utils.cs b/src/Utils.cs index 81a14c921..bf2573ecf 100644 --- a/src/Utils.cs +++ b/src/Utils.cs @@ -35,7 +35,23 @@ public static string Base64Decode(string text) } /// - /// Generates pfx from client configuration + /// Load pem encoded cert file + /// + /// Path to pem encoded cert file + /// x509 instance. + public static X509Certificate2 LoadPemFileCert(string file) + { + var certdata = File.ReadAllText(file) + .Replace("-----BEGIN CERTIFICATE-----", "") + .Replace("-----END CERTIFICATE-----", "") + .Replace("\r", "") + .Replace("\n", ""); + + return new X509Certificate2(Convert.FromBase64String(certdata)); + } + + /// + /// Generates pfx from client configuration /// /// Kuberentes Client Configuration /// Generated Pfx Path @@ -98,4 +114,4 @@ public static X509Certificate2 GeneratePfx(KubernetesClientConfiguration config) } } } -} \ No newline at end of file +} From 8d7845189003262d34a4535fdcca36d20c5dffc0 Mon Sep 17 00:00:00 2001 From: Boshi Lian Date: Thu, 12 Oct 2017 16:55:59 +0800 Subject: [PATCH 2/3] support anonymous for client --- src/Kubernetes.Auth.cs | 41 ++++++----- ...ubernetesClientConfiguration.ConfigFile.cs | 20 +++++- src/KubernetesClientConfiguration.cs | 17 +++-- src/KubernetesClientCredentials.cs | 70 ------------------- tests/KubernetesClientCredentialsTests.cs | 60 ---------------- 5 files changed, 48 insertions(+), 160 deletions(-) delete mode 100644 src/KubernetesClientCredentials.cs delete mode 100644 tests/KubernetesClientCredentialsTests.cs diff --git a/src/Kubernetes.Auth.cs b/src/Kubernetes.Auth.cs index dd1d1fb40..d3fc3b5c8 100644 --- a/src/Kubernetes.Auth.cs +++ b/src/Kubernetes.Auth.cs @@ -24,21 +24,24 @@ public Kubernetes(KubernetesClientConfiguration config) this.CaCert = config.SslCaCert; this.BaseUri = new Uri(config.Host); - // ssl cert validation - Func sslCertValidationFunc; - if (config.SkipTlsVerify) - { - sslCertValidationFunc = (sender, certificate, chain, sslPolicyErrors) => true; - } - else - { - sslCertValidationFunc = this.CertificateValidationCallBack; - } + var handler = new HttpClientHandler(); - var handler = new HttpClientHandler + if (BaseUri.Scheme == "https") { - ServerCertificateCustomValidationCallback = sslCertValidationFunc - }; + if (config.SkipTlsVerify) + { + handler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; + } + else + { + if (CaCert == null) + { + throw new KubeConfigException("a CA must be set when SkipTlsVerify === false"); + } + + handler.ServerCertificateCustomValidationCallback = CertificateValidationCallBack; + } + } // set credentails for the kubernernet client this.SetCredentials(config, handler); @@ -58,11 +61,15 @@ private void SetCredentials(KubernetesClientConfiguration config, HttpClientHand // set the Credentails for token based auth if (!string.IsNullOrWhiteSpace(config.AccessToken)) { - this.Credentials = new KubernetesClientCredentials(config.AccessToken); + Credentials = new TokenCredentials(config.AccessToken); } else if (!string.IsNullOrWhiteSpace(config.Username) && !string.IsNullOrWhiteSpace(config.Password)) { - this.Credentials = new KubernetesClientCredentials(config.Username, config.Password); + Credentials = new BasicAuthenticationCredentials + { + UserName = config.Username, + Password = config.Password + }; } // othwerwise set handler for clinet cert based auth else if ((!string.IsNullOrWhiteSpace(config.ClientCertificateData) || @@ -73,10 +80,6 @@ private void SetCredentials(KubernetesClientConfiguration config, HttpClientHand var cert = Utils.GeneratePfx(config); handler.ClientCertificates.Add(cert); } - else - { - throw new KubeConfigException("Configuration does not have appropriate auth credentials"); - } } /// diff --git a/src/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClientConfiguration.ConfigFile.cs index 0817d3bd6..e2f24d3d6 100644 --- a/src/KubernetesClientConfiguration.ConfigFile.cs +++ b/src/KubernetesClientConfiguration.ConfigFile.cs @@ -40,10 +40,25 @@ public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentC /// /// kube api server endpoint /// kubeconfig filepath - /// public static KubernetesClientConfiguration BuildConfigFromConfigFile(string masterUrl = null, string kubeconfigPath = null) { - var k8SConfig = LoadKubeConfig(new FileInfo(kubeconfigPath ?? KubeConfigDefaultLocation)); + return BuildConfigFromConfigFile(new FileInfo(kubeconfigPath ?? KubeConfigDefaultLocation), null, masterUrl); + } + + /// + /// + /// + /// Fileinfo of the kubeconfig, cannot be null + /// override the context in config file, set null if do not want to override + /// overrider kube api server endpoint, set null if do not want to override + public static KubernetesClientConfiguration BuildConfigFromConfigFile(FileInfo kubeconfig, string currentContext = null, string masterUrl = null) + { + if (kubeconfig == null) + { + throw new NullReferenceException(nameof(kubeconfig)); + } + + var k8SConfig = LoadKubeConfig(kubeconfig); var k8SConfiguration = new KubernetesClientConfiguration(); k8SConfiguration.Initialize(k8SConfig); @@ -53,6 +68,7 @@ public static KubernetesClientConfiguration BuildConfigFromConfigFile(string mas } return k8SConfiguration; } + /// /// Validates and Intializes Client Configuration diff --git a/src/KubernetesClientConfiguration.cs b/src/KubernetesClientConfiguration.cs index 441759e88..df4e9225b 100644 --- a/src/KubernetesClientConfiguration.cs +++ b/src/KubernetesClientConfiguration.cs @@ -14,45 +14,44 @@ namespace k8s /// public partial class KubernetesClientConfiguration { - private KubernetesClientConfiguration() + public KubernetesClientConfiguration() { - } /// /// Gets Host /// - public string Host { get; private set; } + public string Host { get; set; } /// /// Gets SslCaCert /// - public X509Certificate2 SslCaCert { get; private set; } + public X509Certificate2 SslCaCert { get; set; } /// /// Gets ClientCertificateData /// - public string ClientCertificateData { get; private set; } + public string ClientCertificateData { get; set; } /// /// Gets ClientCertificate Key /// - public string ClientCertificateKey { get; private set; } + public string ClientCertificateKey { get; set; } /// /// Gets ClientCertificate filename /// - public string ClientCertificate { get; private set; } + public string ClientCertificate { get; set; } /// /// Gets ClientCertificate Key filename /// - public string ClientKey { get; private set; } + public string ClientKey { get; set; } /// /// Gets a value indicating whether to skip ssl server cert validation /// - public bool SkipTlsVerify { get; private set; } + public bool SkipTlsVerify { get; set; } /// /// Gets or sets the HTTP user agent. diff --git a/src/KubernetesClientCredentials.cs b/src/KubernetesClientCredentials.cs deleted file mode 100644 index 8fa6073e2..000000000 --- a/src/KubernetesClientCredentials.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace k8s -{ - using System; - using System.Globalization; - using System.Net.Http; - using System.Net.Http.Headers; - using System.Threading; - using System.Threading.Tasks; - using k8s.Exceptions; - using Microsoft.Rest; - - /// - /// Class to set the Kubernetes Client Credentials for token based auth - /// - public class KubernetesClientCredentials : ServiceClientCredentials - { - public KubernetesClientCredentials(string token) - { - if (string.IsNullOrWhiteSpace(token)) - { - throw new ArgumentNullException(nameof(token)); - } - - this.AuthenticationToken = token; - this.AuthenticationScheme = "Bearer"; - } - - public KubernetesClientCredentials(string userName, string password) - { - if (string.IsNullOrWhiteSpace(userName)) - { - throw new ArgumentNullException(nameof(userName)); - } - - if (string.IsNullOrWhiteSpace(password)) - { - throw new ArgumentNullException(nameof(password)); - } - - this.AuthenticationToken = Utils.Base64Encode(string.Format(CultureInfo.InvariantCulture, "{0}:{1}", userName, password)); - this.AuthenticationScheme = "Basic"; - } - - private string AuthenticationToken { get; } - - private string AuthenticationScheme { get; } - - public override async Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } - - if (string.IsNullOrWhiteSpace(this.AuthenticationScheme)) - { - throw new KubernetesClientException("AuthenticationScheme cannot be null. Please set the AuthenticationScheme to Basic/Bearer"); - } - - if (string.IsNullOrWhiteSpace(this.AuthenticationToken)) - { - throw new KubernetesClientException("AuthenticationToken cannot be null. Please set the authentication token"); - } - - request.Headers.Authorization = new AuthenticationHeaderValue(this.AuthenticationScheme, this.AuthenticationToken); - - await base.ProcessHttpRequestAsync(request, cancellationToken).ConfigureAwait(false); - } - } -} \ No newline at end of file diff --git a/tests/KubernetesClientCredentialsTests.cs b/tests/KubernetesClientCredentialsTests.cs deleted file mode 100644 index 1f36728a9..000000000 --- a/tests/KubernetesClientCredentialsTests.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using Xunit; -using k8s; -using System.IO; - -namespace k8s.Tests -{ - public class KubernetesClientCredentialsTests - { - /// - /// Checks that a ArgumentNullException is thrown when trying to create a KubernetesClientCredentials with null token - /// - [Fact] - public void TokenNull() - { - Assert.Throws(() => new KubernetesClientCredentials(null)); - } - - /// - /// Checks that a ArgumentNullException is thrown when trying to create a KubernetesClientCredentials with null username - /// - [Fact] - public void UsernameNull() - { - Assert.Throws(() => new KubernetesClientCredentials(null,"password")); - } - - /// - /// Checks that a ArgumentNullException is thrown when trying to create a KubernetesClientCredentials with null password - /// - [Fact] - public void PasswordNull() - { - Assert.Throws(() => new KubernetesClientCredentials("username", null)); - } - - /// - /// Checks that the Token is set with no exceptions - /// - [Fact] - public void ValidTokenIsSet() - { - var token = "mytoken"; - var credentials = new KubernetesClientCredentials(token); - Assert.NotNull(credentials); - } - - /// - /// Checks that the Username and Password is set with no exceptions - /// - [Fact] - public void ValidUserPasswordIsSet() - { - var username = "myuser"; - var password = "mypassword"; - var credentials = new KubernetesClientCredentials(username, password); - Assert.NotNull(credentials); - } - } -} \ No newline at end of file From 7096b1560440e8dc9f4cd42b6de0f55bf5193f1a Mon Sep 17 00:00:00 2001 From: Boshi Lian Date: Sat, 21 Oct 2017 21:37:38 +0800 Subject: [PATCH 3/3] extract path to shared const --- src/KubernetesClientConfiguration.InCluster.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/KubernetesClientConfiguration.InCluster.cs b/src/KubernetesClientConfiguration.InCluster.cs index da70d5f81..d2a61895c 100644 --- a/src/KubernetesClientConfiguration.InCluster.cs +++ b/src/KubernetesClientConfiguration.InCluster.cs @@ -1,14 +1,14 @@ using System; using System.IO; -using System.Security.Cryptography.X509Certificates; using k8s.Exceptions; namespace k8s { public partial class KubernetesClientConfiguration { - private const string ServiceAccountTokenKey = "token"; - private const string ServiceAccountRootCAKey = "ca.crt"; + private const string ServiceaccountPath = "/var/run/secrets/kubernetes.io/serviceaccount/"; + private const string ServiceAccountTokenKeyFileName = "token"; + private const string ServiceAccountRootCAKeyFileName = "ca.crt"; public static KubernetesClientConfiguration InClusterConfig() { @@ -21,8 +21,8 @@ public static KubernetesClientConfiguration InClusterConfig() "unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined"); } - var token = File.ReadAllText("/var/run/secrets/kubernetes.io/serviceaccount/" + ServiceAccountTokenKey); - var rootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/" + ServiceAccountRootCAKey; + var token = File.ReadAllText(Path.Combine(ServiceaccountPath, ServiceAccountTokenKeyFileName)); + var rootCAFile = Path.Combine(ServiceaccountPath, ServiceAccountRootCAKeyFileName); return new KubernetesClientConfiguration {