Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions examples/exec/Exec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Threading.Tasks;
using k8s;
using k8s.Models;

namespace exec
{
internal class Exec
{
private static async Task Main(string[] args)
{
var config = KubernetesClientConfiguration.BuildConfigFromConfigFile();
IKubernetes client = new Kubernetes(config);
Console.WriteLine("Starting Request!");

var list = client.ListNamespacedPod("default");
var pod = list.Items[0];
await ExecInPod(client, pod);
}

private async static Task ExecInPod(IKubernetes client, V1Pod pod) {
var webSocket = await client.WebSocketNamespacedPodExecAsync(pod.Metadata.Name, "default", "ls", pod.Spec.Containers[0].Name);

var demux = new StreamDemuxer(webSocket);
demux.Start();

var buff = new byte[4096];
var stream = demux.GetStream(1, 1);
var read = stream.Read(buff, 0, 4096);
var str = System.Text.Encoding.Default.GetString(buff);
Console.WriteLine(str);
}
}
}
13 changes: 13 additions & 0 deletions examples/exec/exec.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<ProjectReference Include="..\..\src\KubernetesClient.csproj" />
</ItemGroup>

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<LangVersion>7.1</LangVersion>
</PropertyGroup>

</Project>
19 changes: 14 additions & 5 deletions src/Kubernetes.ConfigInit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler
}

CaCert = config.SslCaCert;
SkipTlsVerify = config.SkipTlsVerify;

if (BaseUri.Scheme == "https")
{
Expand All @@ -59,10 +60,15 @@ public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler
}

#if NET452
((WebRequestHandler) HttpClientHandler).ServerCertificateValidationCallback =
CertificateValidationCallBack;
((WebRequestHandler) HttpClientHandler).ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted for next time :)

{
return Kubernetes.CertificateValidationCallBack(sender, CaCert, certificate, chain, sslPolicyErrors);
};
#else
HttpClientHandler.ServerCertificateCustomValidationCallback = CertificateValidationCallBack;
HttpClientHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
return Kubernetes.CertificateValidationCallBack(sender, CaCert, certificate, chain, sslPolicyErrors);
};
#endif
}
}
Expand All @@ -73,6 +79,8 @@ public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler

private X509Certificate2 CaCert { get; }

private bool SkipTlsVerify { get; }

partial void CustomInitialize()
{
#if NET452
Expand Down Expand Up @@ -151,8 +159,9 @@ private void SetCredentials(KubernetesClientConfiguration config, HttpClientHand
/// <param name="sslPolicyErrors">ssl policy errors</param>
/// <returns>true if valid cert</returns>
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "Unused by design")]
private bool CertificateValidationCallBack(
public static bool CertificateValidationCallBack(
object sender,
X509Certificate2 caCert,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
Expand All @@ -169,7 +178,7 @@ private bool CertificateValidationCallBack(
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

// add all your extra certificate chain
chain.ChainPolicy.ExtraStore.Add(CaCert);
chain.ChainPolicy.ExtraStore.Add(caCert);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
var isValid = chain.Build((X509Certificate2) certificate);
return isValid;
Expand Down
9 changes: 5 additions & 4 deletions src/Kubernetes.WebSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,18 +226,20 @@ public partial class Kubernetes

#if NETCOREAPP2_1
if (this.CaCert != null)
{
webSocketBuilder.ExpectServerCertificate(this.CaCert);
else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't these mutually exclusive? I suppose throwing an exception would have been clearer when I first wrote this...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? I sort of lean on "the customer is always right" or "the caller is always right"

If they ship us a config with a ca Cert and noVerifyTLS who are we to judge? We should obey their wishes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah fair enough, that reasoning makes sense to me :)

My personal approach to API design is "forgiving, but also willing to point out when the caller may be making a mistake". If someone specifies both CaCert and SkipTlsVerify, which one did they really intend to specify? Is it intuitive to them which one we'd select when there's a conflict like this, and do we document this assumption anywhere?

But in this case, correct behaviour is dictated by the K8s client config spec which doesn't prevent them specifying both (so I agree with you that there's not much point in stopping them from doing so).

}
if (this.SkipTlsVerify)
{
webSocketBuilder.SkipServerCertificateValidation();

}
webSocketBuilder.Options.RequestedSubProtocols.Add(K8sProtocol.ChannelV1);
#endif // NETCOREAPP2_1

// Send Request
cancellationToken.ThrowIfCancellationRequested();

WebSocket webSocket = null;

try
{
webSocket = await webSocketBuilder.BuildAndConnectAsync(uri, CancellationToken.None).ConfigureAwait(false);
Expand All @@ -258,7 +260,6 @@ public partial class Kubernetes
ServiceClientTracing.Exit(invocationId, null);
}
}

return webSocket;
}
}
Expand Down
28 changes: 2 additions & 26 deletions src/WebSocketBuilder.NetCoreApp2.1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,34 +39,10 @@ public WebSocketBuilder AddClientCertificate(X509Certificate2 certificate)

public WebSocketBuilder ExpectServerCertificate(X509Certificate2 serverCertificate)
{
Options.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
Options.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
if (sslPolicyErrors != SslPolicyErrors.RemoteCertificateChainErrors)
{
return false;
}

try
{
using (X509Chain certificateChain = new X509Chain())
{
certificateChain.ChainPolicy.ExtraStore.Add(serverCertificate);
certificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

return certificateChain.Build(
(X509Certificate2)certificate
);
}
}
catch (Exception chainException)
{
Debug.WriteLine(chainException);

return false;
}
return Kubernetes.CertificateValidationCallBack(sender, serverCertificate, certificate, chain, sslPolicyErrors);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops! Sorry, must have missed that :)

};

return this;
}

Expand Down