Skip to content

Commit 92ddad2

Browse files
Merge pull request #50 from tg123/movector
DelegatingHandler now works with Kubernetes clients
2 parents 8016b6c + 83559d5 commit 92ddad2

7 files changed

+156
-99
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,36 @@
11
using k8s.Models;
2+
using System;
3+
using System.Diagnostics.CodeAnalysis;
4+
using System.Net.Http;
5+
using System.Net.Security;
6+
using System.Security.Cryptography.X509Certificates;
7+
using k8s.Exceptions;
8+
using Microsoft.Rest;
29

310
namespace k8s
411
{
5-
using System;
6-
using System.Diagnostics.CodeAnalysis;
7-
using System.Net.Http;
8-
using System.Net.Security;
9-
using System.Security.Cryptography.X509Certificates;
10-
using System.Threading.Tasks;
11-
using k8s.Exceptions;
12-
using Microsoft.Rest;
13-
14-
public partial class Kubernetes : ServiceClient<Kubernetes>, IKubernetes
12+
public partial class Kubernetes
1513
{
1614
/// <summary>
17-
/// Initializes a new instance of the <see cref="Kubernetes"/> class.
15+
/// Initializes a new instance of the <see cref="Kubernetes" /> class.
1816
/// </summary>
1917
/// <param name='config'>
20-
/// Optional. The delegating handlers to add to the http client pipeline.
18+
/// Optional. The delegating handlers to add to the http client pipeline.
19+
/// </param>
20+
/// <param name="handlers">
21+
/// Optional. The delegating handlers to add to the http client pipeline.
2122
/// </param>
22-
public Kubernetes(KubernetesClientConfiguration config)
23+
public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler[] handlers) : this(handlers)
2324
{
24-
this.Initialize();
25-
26-
this.CaCert = config.SslCaCert;
27-
this.BaseUri = new Uri(config.Host);
28-
29-
var handler = new HttpClientHandler();
25+
CaCert = config.SslCaCert;
26+
BaseUri = new Uri(config.Host);
3027

3128
if (BaseUri.Scheme == "https")
3229
{
3330
if (config.SkipTlsVerify)
3431
{
35-
handler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
32+
HttpClientHandler.ServerCertificateCustomValidationCallback =
33+
(sender, certificate, chain, sslPolicyErrors) => true;
3634
}
3735
else
3836
{
@@ -41,21 +39,47 @@ public Kubernetes(KubernetesClientConfiguration config)
4139
throw new KubeConfigException("a CA must be set when SkipTlsVerify === false");
4240
}
4341

44-
handler.ServerCertificateCustomValidationCallback = CertificateValidationCallBack;
42+
HttpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationCallBack;
4543
}
4644
}
4745

4846
// set credentails for the kubernernet client
49-
this.SetCredentials(config, handler);
50-
this.InitializeHttpClient(handler, new DelegatingHandler[]{new WatcherDelegatingHandler()});
51-
52-
DeserializationSettings.Converters.Add(new V1Status.V1StatusObjectViewConverter());
47+
SetCredentials(config, HttpClientHandler);
48+
}
49+
50+
private X509Certificate2 CaCert { get; }
51+
52+
partial void CustomInitialize()
53+
{
54+
AppendDelegatingHandler<WatcherDelegatingHandler>();
55+
DeserializationSettings.Converters.Add(new V1Status.V1StatusObjectViewConverter());
5356
}
5457

55-
private X509Certificate2 CaCert { get; set; }
58+
private void AppendDelegatingHandler<T>() where T : DelegatingHandler, new()
59+
{
60+
var cur = FirstMessageHandler as DelegatingHandler;
61+
62+
while (cur != null)
63+
{
64+
var next = cur.InnerHandler as DelegatingHandler;
65+
66+
if (next == null)
67+
{
68+
// last one
69+
// append watcher handler between to last handler
70+
cur.InnerHandler = new T
71+
{
72+
InnerHandler = cur.InnerHandler
73+
};
74+
break;
75+
}
76+
77+
cur = next;
78+
}
79+
}
5680

5781
/// <summary>
58-
/// Set credentials for the Client
82+
/// Set credentials for the Client
5983
/// </summary>
6084
/// <param name="config">k8s client configuration</param>
6185
/// <param name="handler">http client handler for the rest client</param>
@@ -88,7 +112,7 @@ private void SetCredentials(KubernetesClientConfiguration config, HttpClientHand
88112
}
89113

90114
/// <summary>
91-
/// SSl Cert Validation Callback
115+
/// SSl Cert Validation Callback
92116
/// </summary>
93117
/// <param name="sender">sender</param>
94118
/// <param name="certificate">client certificate</param>
@@ -97,10 +121,10 @@ private void SetCredentials(KubernetesClientConfiguration config, HttpClientHand
97121
/// <returns>true if valid cert</returns>
98122
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "Unused by design")]
99123
private bool CertificateValidationCallBack(
100-
object sender,
101-
X509Certificate certificate,
102-
X509Chain chain,
103-
SslPolicyErrors sslPolicyErrors)
124+
object sender,
125+
X509Certificate certificate,
126+
X509Chain chain,
127+
SslPolicyErrors sslPolicyErrors)
104128
{
105129
// If the certificate is a valid, signed certificate, return true.
106130
if (sslPolicyErrors == SslPolicyErrors.None)
@@ -114,16 +138,13 @@ private bool CertificateValidationCallBack(
114138
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
115139

116140
// add all your extra certificate chain
117-
chain.ChainPolicy.ExtraStore.Add(this.CaCert);
141+
chain.ChainPolicy.ExtraStore.Add(CaCert);
118142
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
119-
var isValid = chain.Build((X509Certificate2)certificate);
143+
var isValid = chain.Build((X509Certificate2) certificate);
120144
return isValid;
121145
}
122-
else
123-
{
124-
// In all other cases, return false.
125-
return false;
126-
}
146+
// In all other cases, return false.
147+
return false;
127148
}
128149
}
129150
}

src/KubernetesClientConfiguration.ConfigFile.cs

+2-13
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,6 @@ public partial class KubernetesClientConfiguration
2424
? Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), @".kube\config")
2525
: Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".kube/config");
2626

27-
/// <summary>
28-
/// Initializes a new instance of the <see cref="KubernetesClientConfiguration"/> class.
29-
/// </summary>
30-
/// <param name="kubeconfig">kubeconfig file info</param>
31-
/// <param name="currentContext">Context to use from kube config</param>
32-
public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentContext = null)
33-
{
34-
var k8SConfig = LoadKubeConfig(kubeconfig ?? new FileInfo(KubeConfigDefaultLocation));
35-
this.Initialize(k8SConfig, currentContext);
36-
}
37-
3827
/// <summary>
3928
/// Initializes a new instance of the <see cref="KubernetesClientConfiguration"/> from config file
4029
/// </summary>
@@ -60,7 +49,7 @@ public static KubernetesClientConfiguration BuildConfigFromConfigFile(FileInfo k
6049

6150
var k8SConfig = LoadKubeConfig(kubeconfig);
6251
var k8SConfiguration = new KubernetesClientConfiguration();
63-
k8SConfiguration.Initialize(k8SConfig);
52+
k8SConfiguration.Initialize(k8SConfig, currentContext);
6453

6554
if (!string.IsNullOrWhiteSpace(masterUrl))
6655
{
@@ -200,7 +189,7 @@ private void SetUserDetails(K8SConfiguration k8SConfig, Context activeContext)
200189
/// <summary>
201190
/// Loads Kube Config
202191
/// </summary>
203-
/// <param name="config">Kube config file contents</param>
192+
/// <param name="kubeconfig">Kube config file contents</param>
204193
/// <returns>Instance of the <see cref="K8SConfiguration"/> class</returns>
205194
private static K8SConfiguration LoadKubeConfig(FileInfo kubeconfig)
206195
{

src/KubernetesClientConfiguration.cs

+14-25
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,67 @@
1+
using System.Security.Cryptography.X509Certificates;
2+
13
namespace k8s
24
{
3-
using System;
4-
using System.IO;
5-
using System.Linq;
6-
using System.Security.Cryptography.X509Certificates;
7-
using k8s.Exceptions;
8-
using k8s.KubeConfigModels;
9-
using YamlDotNet.Serialization;
10-
using System.Runtime.InteropServices;
11-
125
/// <summary>
13-
/// Represents a set of kubernetes client configuration settings
6+
/// Represents a set of kubernetes client configuration settings
147
/// </summary>
158
public partial class KubernetesClientConfiguration
169
{
17-
public KubernetesClientConfiguration()
18-
{
19-
}
20-
2110
/// <summary>
22-
/// Gets Host
11+
/// Gets Host
2312
/// </summary>
2413
public string Host { get; set; }
2514

2615
/// <summary>
27-
/// Gets SslCaCert
16+
/// Gets SslCaCert
2817
/// </summary>
2918
public X509Certificate2 SslCaCert { get; set; }
3019

3120
/// <summary>
32-
/// Gets ClientCertificateData
21+
/// Gets ClientCertificateData
3322
/// </summary>
3423
public string ClientCertificateData { get; set; }
3524

3625
/// <summary>
37-
/// Gets ClientCertificate Key
26+
/// Gets ClientCertificate Key
3827
/// </summary>
3928
public string ClientCertificateKeyData { get; set; }
4029

4130
/// <summary>
42-
/// Gets ClientCertificate filename
31+
/// Gets ClientCertificate filename
4332
/// </summary>
4433
public string ClientCertificateFilePath { get; set; }
4534

4635
/// <summary>
47-
/// Gets ClientCertificate Key filename
36+
/// Gets ClientCertificate Key filename
4837
/// </summary>
4938
public string ClientKeyFilePath { get; set; }
5039

5140
/// <summary>
52-
/// Gets a value indicating whether to skip ssl server cert validation
41+
/// Gets a value indicating whether to skip ssl server cert validation
5342
/// </summary>
5443
public bool SkipTlsVerify { get; set; }
5544

5645
/// <summary>
57-
/// Gets or sets the HTTP user agent.
46+
/// Gets or sets the HTTP user agent.
5847
/// </summary>
5948
/// <value>Http user agent.</value>
6049
public string UserAgent { get; set; }
6150

6251
/// <summary>
63-
/// Gets or sets the username (HTTP basic authentication).
52+
/// Gets or sets the username (HTTP basic authentication).
6453
/// </summary>
6554
/// <value>The username.</value>
6655
public string Username { get; set; }
6756

6857
/// <summary>
69-
/// Gets or sets the password (HTTP basic authentication).
58+
/// Gets or sets the password (HTTP basic authentication).
7059
/// </summary>
7160
/// <value>The password.</value>
7261
public string Password { get; set; }
7362

7463
/// <summary>
75-
/// Gets or sets the access token for OAuth2 authentication.
64+
/// Gets or sets the access token for OAuth2 authentication.
7665
/// </summary>
7766
/// <value>The access token.</value>
7867
public string AccessToken { get; set; }

tests/CertUtilsTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class CertUtilsTests
1919
public void LoadFromFiles()
2020
{
2121
var fi = new FileInfo(kubeConfigFileName);
22-
var cfg = new KubernetesClientConfiguration(fi, "federal-context");
22+
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, "federal-context");
2323

2424
// Just validate that this doesn't throw and private key is non-null
2525
var cert = CertUtils.GeneratePfx(cfg);
@@ -33,7 +33,7 @@ public void LoadFromFiles()
3333
public void LoadFromInlineData()
3434
{
3535
var fi = new FileInfo(kubeConfigFileName);
36-
var cfg = new KubernetesClientConfiguration(fi, "victorian-context");
36+
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, "victorian-context");
3737

3838
// Just validate that this doesn't throw and private key is non-null
3939
var cert = CertUtils.GeneratePfx(cfg);

0 commit comments

Comments
 (0)