private static void AKSAdministration() { var configuration = new k8s.KubernetesClientConfiguration { Host = "https://ari-aks-22-demo-f681ed-b4579bd4.hcp.southeastasia.azmk8s.io:443", AccessToken = ReadAccessToken() }; configuration.SkipTlsVerify = true; var client = new k8s.Kubernetes(configuration); var namespaces = client.ListNamespace(); foreach (var ns in namespaces.Items) { Console.WriteLine(ns.Metadata.Name); } // ## Uncomment below lines to test creation of namespace //client.CreateNamespace(new k8s.Models.V1Namespace { // Metadata= new k8s.Models.V1ObjectMeta // { // Name= "automation" // } //}); }
/// <summary>Creates <see cref="ServiceClientCredentials"/> based on the given config, or returns null if no such credentials are /// needed. /// </summary> public static ServiceClientCredentials CreateCredentials(KubernetesClientConfiguration config) { if (config == null) { throw new ArgumentNullException(nameof(config)); } if (!string.IsNullOrEmpty(config.AccessToken)) { return(new TokenCredentials(config.AccessToken)); } else if (!string.IsNullOrEmpty(config.Username)) { return(new BasicAuthenticationCredentials() { UserName = config.Username, Password = config.Password }); } return(null); }
private void ValidateConfig(KubernetesClientConfiguration config) { if (config == null) { throw new KubeConfigException("KubeConfig must be provided"); } if (string.IsNullOrWhiteSpace(config.Host)) { throw new KubeConfigException("Host url must be set"); } try { BaseUri = new Uri(config.Host); } catch (UriFormatException e) { throw new KubeConfigException("Bad host url", e); } }
/// <summary> /// Initializes a new instance of the <see cref="KubernetesClientConfiguration" /> from config file /// </summary> public static KubernetesClientConfiguration BuildDefaultConfig() { var kubeconfig = Environment.GetEnvironmentVariable("KUBECONFIG"); if (kubeconfig != null) { return(BuildConfigFromConfigFile(kubeconfigPath: kubeconfig)); } if (File.Exists(KubeConfigDefaultLocation)) { return(BuildConfigFromConfigFile(kubeconfigPath: KubeConfigDefaultLocation)); } if (IsInCluster()) { return(InClusterConfig()); } var config = new KubernetesClientConfiguration(); config.Host = "http://localhost:8080"; return(config); }
/// <summary> /// Initializes a new instance of the <see cref="Kubernetes" /> class. /// </summary> /// <param name='config'> /// Optional. The delegating handlers to add to the http client pipeline. /// </param> /// <param name="handlers"> /// Optional. The delegating handlers to add to the http client pipeline. /// </param> public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler[] handlers) : this(handlers) { if (string.IsNullOrWhiteSpace(config.Host)) { throw new KubeConfigException("Host url must be set"); } try { BaseUri = new Uri(config.Host); } catch (UriFormatException e) { throw new KubeConfigException("Bad host url", e); } CaCert = config.SslCaCert; if (BaseUri.Scheme == "https") { if (config.SkipTlsVerify) { HttpClientHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; } else { if (CaCert == null) { throw new KubeConfigException("a CA must be set when SkipTlsVerify === false"); } HttpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationCallBack; } } // set credentails for the kubernernet client SetCredentials(config, HttpClientHandler); }
private static KubernetesClientConfiguration GetKubernetesClientConfiguration(string currentContext, string masterUrl, K8SConfiguration k8SConfig) { var k8SConfiguration = new KubernetesClientConfiguration(); currentContext = currentContext ?? k8SConfig.CurrentContext; // only init context if context if set if (currentContext != null) { k8SConfiguration.InitializeContext(k8SConfig, currentContext); } if (!string.IsNullOrWhiteSpace(masterUrl)) { k8SConfiguration.Host = masterUrl; } if (string.IsNullOrWhiteSpace(k8SConfiguration.Host)) { throw new KubeConfigException("Cannot infer server host url either from context or masterUrl"); } return(k8SConfiguration); }
public static KubernetesClientConfiguration InClusterConfig() { if (!IsInCluster()) { throw new KubeConfigException( "unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined"); } var rootCAFile = Path.Combine(ServiceAccountPath, ServiceAccountRootCAKeyFileName); var host = Environment.GetEnvironmentVariable("KUBERNETES_SERVICE_HOST"); var port = Environment.GetEnvironmentVariable("KUBERNETES_SERVICE_PORT"); if (string.IsNullOrEmpty(host)) { host = "kubernetes.default.svc"; } if (string.IsNullOrEmpty(port)) { port = "443"; } var result = new KubernetesClientConfiguration { Host = new UriBuilder("https", host, Convert.ToInt32(port)).ToString(), TokenProvider = new TokenFileAuth(Path.Combine(ServiceAccountPath, ServiceAccountTokenKeyFileName)), SslCaCerts = CertUtils.LoadPemFileCert(rootCAFile), }; var namespaceFile = Path.Combine(ServiceAccountPath, ServiceAccountNamespaceFileName); if (FileUtils.FileSystem().File.Exists(namespaceFile)) { result.Namespace = FileUtils.FileSystem().File.ReadAllText(namespaceFile); } return(result); }
/// <summary> /// Generates pfx from client configuration /// </summary> /// <param name="config">Kubernetes Client Configuration</param> /// <returns>Generated Pfx Path</returns> public static X509Certificate2 GeneratePfx(KubernetesClientConfiguration config) { byte[] keyData = null; byte[] certData = null; if (!string.IsNullOrWhiteSpace(config.ClientCertificateKeyData)) { keyData = Convert.FromBase64String(config.ClientCertificateKeyData); } if (!string.IsNullOrWhiteSpace(config.ClientKeyFilePath)) { keyData = File.ReadAllBytes(config.ClientKeyFilePath); } if (keyData == null) { throw new KubeConfigException("keyData is empty"); } if (!string.IsNullOrWhiteSpace(config.ClientCertificateData)) { certData = Convert.FromBase64String(config.ClientCertificateData); } if (!string.IsNullOrWhiteSpace(config.ClientCertificateFilePath)) { certData = File.ReadAllBytes(config.ClientCertificateFilePath); } if (certData == null) { throw new KubeConfigException("certData is empty"); } var cert = new X509CertificateParser().ReadCertificate(new MemoryStream(certData)); // key usage is a bit string, zero-th bit is 'digitalSignature' // See https://www.alvestrand.no/objectid/2.5.29.15.html for more details. if (cert != null && cert.GetKeyUsage() != null && !cert.GetKeyUsage()[0]) { throw new Exception( "Client certificates must be marked for digital signing. " + "See https://github.com/kubernetes-client/csharp/issues/319"); } object obj; using (var reader = new StreamReader(new MemoryStream(keyData))) { obj = new PemReader(reader).ReadObject(); var key = obj as AsymmetricCipherKeyPair; if (key != null) { var cipherKey = key; obj = cipherKey.Private; } } var keyParams = (AsymmetricKeyParameter)obj; var store = new Pkcs12StoreBuilder().Build(); store.SetKeyEntry("K8SKEY", new AsymmetricKeyEntry(keyParams), new[] { new X509CertificateEntry(cert) }); using (var pkcs = new MemoryStream()) { store.Save(pkcs, new char[0], new SecureRandom()); if (config.ClientCertificateKeyStoreFlags.HasValue) { return(new X509Certificate2(pkcs.ToArray(), "", config.ClientCertificateKeyStoreFlags.Value)); } else { return(new X509Certificate2(pkcs.ToArray())); } } }
private void InitializeFromConfig(KubernetesClientConfiguration config) { if (BaseUri.Scheme == "https") { if (config.SkipTlsVerify) { #if NET452 ((WebRequestHandler)HttpClientHandler).ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; #elif XAMARINIOS1_0 || MONOANDROID8_1 System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return(true); }; #else HttpClientHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; #endif } else { if (CaCerts == null) { throw new KubeConfigException("A CA must be set when SkipTlsVerify === false"); } #if NET452 ((WebRequestHandler)HttpClientHandler).ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return(Kubernetes.CertificateValidationCallBack(sender, CaCerts, certificate, chain, sslPolicyErrors)); }; #elif XAMARINIOS1_0 System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { var cert = new X509Certificate2(certificate); return(Kubernetes.CertificateValidationCallBack(sender, CaCerts, cert, chain, sslPolicyErrors)); }; #elif MONOANDROID8_1 var certList = new System.Collections.Generic.List <Java.Security.Cert.Certificate>(); foreach (X509Certificate2 caCert in CaCerts) { using (var certStream = new System.IO.MemoryStream(caCert.RawData)) { Java.Security.Cert.Certificate cert = Java.Security.Cert.CertificateFactory.GetInstance("X509").GenerateCertificate(certStream); certList.Add(cert); } } var handler = (Xamarin.Android.Net.AndroidClientHandler) this.HttpClientHandler; handler.TrustedCerts = certList; #else HttpClientHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return(Kubernetes.CertificateValidationCallBack(sender, CaCerts, certificate, chain, sslPolicyErrors)); }; #endif } } // set credentails for the kubernetes client SetCredentials(config); config.AddCertificates(HttpClientHandler); }
/// <summary> /// Initializes a new instance of the <see cref="Kubernetes" /> class. /// </summary> /// <param name='config'> /// The kube config to use. /// </param> /// <param name="httpClient"> /// The <see cref="HttpClient" /> to use for all requests. /// </param> public Kubernetes(KubernetesClientConfiguration config, HttpClient httpClient) : this(config, httpClient, false) { }
/// <summary> /// Set credentials for the Client /// </summary> /// <param name="config">k8s client configuration</param> private void SetCredentials(KubernetesClientConfiguration config) => Credentials = CreateCredentials(config);
/// <summary> /// Initializes a new instance of the <see cref="Kubernetes" /> class. /// </summary> /// <param name='config'> /// The kube config to use. /// </param> /// <param name="handlers"> /// Optional. The delegating handlers to add to the http client pipeline. /// </param> public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler[] handlers) #if MONOANDROID8_1 : this(new Xamarin.Android.Net.AndroidClientHandler(), handlers) #else : this(handlers)
/// <summary> /// Initializes a new instance of the <see cref="Kubernetes" /> class. /// </summary> /// <param name='config'> /// Optional. The delegating handlers to add to the http client pipeline. /// </param> /// <param name="handlers"> /// Optional. The delegating handlers to add to the http client pipeline. /// </param> public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler[] handlers) : this(handlers) { if (string.IsNullOrWhiteSpace(config.Host)) { throw new KubeConfigException("Host url must be set"); } try { BaseUri = new Uri(config.Host); } catch (UriFormatException e) { throw new KubeConfigException("Bad host url", e); } CaCert = config.SslCaCert; SkipTlsVerify = config.SkipTlsVerify; if (BaseUri.Scheme == "https") { if (config.SkipTlsVerify) { #if NET452 ((WebRequestHandler)HttpClientHandler).ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; #elif XAMARINIOS1_0 System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return(true); }; #else HttpClientHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; #endif } else { if (CaCert == null) { throw new KubeConfigException("a CA must be set when SkipTlsVerify === false"); } #if NET452 ((WebRequestHandler)HttpClientHandler).ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return(Kubernetes.CertificateValidationCallBack(sender, CaCert, certificate, chain, sslPolicyErrors)); }; #elif XAMARINIOS1_0 System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { var cert = new X509Certificate2(certificate); return(Kubernetes.CertificateValidationCallBack(sender, CaCert, cert, chain, sslPolicyErrors)); }; #else HttpClientHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return(Kubernetes.CertificateValidationCallBack(sender, CaCert, certificate, chain, sslPolicyErrors)); }; #endif } } // set credentails for the kubernernet client SetCredentials(config, HttpClientHandler); }
// NOTE: this method replicates the logic that the base ServiceClient uses except that it doesn't insert the RetryDelegatingHandler // and it does insert the WatcherDelegatingHandler. we don't want the RetryDelegatingHandler because it has a very broad definition // of what requests have failed. it considers everything outside 2xx to be failed, including 1xx (e.g. 101 Switching Protocols) and // 3xx. in particular, this prevents upgraded connections and certain generic/custom requests from working. private void CreateHttpClient(DelegatingHandler[] handlers, KubernetesClientConfiguration config) { FirstMessageHandler = HttpClientHandler = CreateRootHandler(); #if NET5_0 // https://github.com/kubernetes-client/csharp/issues/587 // let user control if tcp keep alive until better fix if (config.TcpKeepAlive) { // https://github.com/kubernetes-client/csharp/issues/533 // net5 only // this is a temp fix to attach SocketsHttpHandler to HttpClient in order to set SO_KEEPALIVE // https://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/ // // _underlyingHandler is not a public accessible field // src of net5 HttpClientHandler and _underlyingHandler field defined here // https://github.com/dotnet/runtime/blob/79ae74f5ca5c8a6fe3a48935e85bd7374959c570/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs#L22 // // Should remove after better solution var sh = new SocketsHttpHandler(); sh.ConnectCallback = async(context, token) => { var socket = new Socket(SocketType.Stream, ProtocolType.Tcp) { NoDelay = true, }; socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); var host = context.DnsEndPoint.Host; if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // https://github.com/dotnet/runtime/issues/24917 // GetHostAddresses will return {host} if host is an ip var ips = Dns.GetHostAddresses(host); if (ips.Length == 0) { throw new Exception($"{host} DNS lookup failed"); } host = ips[new Random().Next(ips.Length)].ToString(); } await socket.ConnectAsync(host, context.DnsEndPoint.Port, token).ConfigureAwait(false); return(new NetworkStream(socket, ownsSocket: true)); }; // set HttpClientHandler's cert callback before replace _underlyingHandler // force HttpClientHandler use our callback InitializeFromConfig(config); var p = HttpClientHandler.GetType().GetField("_underlyingHandler", BindingFlags.NonPublic | BindingFlags.Instance); p.SetValue(HttpClientHandler, (sh)); } #endif if (handlers == null || handlers.Length == 0) { // ensure we have at least one DelegatingHandler so AppendDelegatingHandler will work FirstMessageHandler = new ForwardingHandler(HttpClientHandler); } else { for (int i = handlers.Length - 1; i >= 0; i--) { DelegatingHandler handler = handlers[i]; while (handler.InnerHandler is DelegatingHandler d) { handler = d; } handler.InnerHandler = FirstMessageHandler; FirstMessageHandler = handlers[i]; } } AppendDelegatingHandler <WatcherDelegatingHandler>(); HttpClient = new HttpClient(FirstMessageHandler, false); }
/// <summary> /// Initializes a new instance of the <see cref="Kubernetes" /> class. /// </summary> /// <param name='k8SConfiguration'> /// The configuration file for connection to Kubernetes /// </param> public Kubernetes(IK8SConfiguration k8SConfiguration) { var config = KubernetesClientConfiguration.BuildConfigFromConfigObject(k8SConfiguration); InitKubernetes(config); }
/// <summary> /// Initializes a new instance of the <see cref="Kubernetes" /> class. /// </summary> /// <param name='config'> /// The configuration file for connecting to Kubernetes /// </param> /// <param name="handlers"> /// Optional. The delegating handlers to add to the http client pipeline. /// </param> public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler[] handlers) : this(handlers) { InitKubernetes(config); }
/// <summary> /// Generates pfx from client configuration /// </summary> /// <param name="config">Kubernetes Client Configuration</param> /// <returns>Generated Pfx Path</returns> public static X509Certificate2 GeneratePfx(KubernetesClientConfiguration config) { byte[] keyData = null; byte[] certData = null; if (!string.IsNullOrWhiteSpace(config.ClientCertificateKeyData)) { keyData = Convert.FromBase64String(config.ClientCertificateKeyData); } if (!string.IsNullOrWhiteSpace(config.ClientKeyFilePath)) { keyData = File.ReadAllBytes(config.ClientKeyFilePath); } if (keyData == null) { throw new KubeConfigException("keyData is empty"); } if (!string.IsNullOrWhiteSpace(config.ClientCertificateData)) { certData = Convert.FromBase64String(config.ClientCertificateData); } if (!string.IsNullOrWhiteSpace(config.ClientCertificateFilePath)) { certData = File.ReadAllBytes(config.ClientCertificateFilePath); } if (certData == null) { throw new KubeConfigException("certData is empty"); } var cert = new X509CertificateParser().ReadCertificate(new MemoryStream(certData)); object obj; using (var reader = new StreamReader(new MemoryStream(keyData))) { obj = new PemReader(reader).ReadObject(); var key = obj as AsymmetricCipherKeyPair; if (key != null) { var cipherKey = key; obj = cipherKey.Private; } } var rsaKeyParams = (RsaPrivateCrtKeyParameters)obj; var store = new Pkcs12StoreBuilder().Build(); store.SetKeyEntry("K8SKEY", new AsymmetricKeyEntry(rsaKeyParams), new[] { new X509CertificateEntry(cert) }); using (var pkcs = new MemoryStream()) { store.Save(pkcs, new char[0], new SecureRandom()); if (config.ClientCertificateKeyStoreFlags.HasValue) { return(new X509Certificate2(pkcs.ToArray(), "", config.ClientCertificateKeyStoreFlags.Value)); } else { return(new X509Certificate2(pkcs.ToArray())); } } }
public GenericClient(KubernetesClientConfiguration config, string group, string version, string plural) : this(new Kubernetes(config), group, version, plural) { }