Skip to content

Commit

Permalink
Update credentials for more valid values.
Browse files Browse the repository at this point in the history
  • Loading branch information
brendanburns committed Aug 11, 2017
1 parent 7717e65 commit 6333784
Show file tree
Hide file tree
Showing 22 changed files with 204 additions and 39 deletions.
4 changes: 4 additions & 0 deletions examples/simple/PodList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ static void Main(string[] args)
{
var k8sClientConfig = new KubernetesClientConfiguration();
IKubernetes client = new Kubernetes(k8sClientConfig);
Console.WriteLine("Starting Request!");
var listTask = client.ListNamespacedPodWithHttpMessagesAsync("default").Result;
var list = listTask.Body;
foreach (var item in list.Items) {
Console.WriteLine(item.Metadata.Name);
}
if (list.Items.Count == 0) {
Console.WriteLine("Empty!");
}
}
}
}
2 changes: 1 addition & 1 deletion examples/simple/simple.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>

</Project>
3 changes: 3 additions & 0 deletions src/KubeConfigModels/ClusterEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

public class ClusterEndpoint
{
[YamlMember(Alias = "certificate-authority")]
public string CertificateAuthority {get; set; }

[YamlMember(Alias = "certificate-authority-data")]
public string CertificateAuthorityData { get; set; }

Expand Down
3 changes: 3 additions & 0 deletions src/KubeConfigModels/K8SConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
/// </summary>
public class K8SConfiguration
{
[YamlMember(Alias = "preferences")]
public IDictionary<string, object> preferences{ get; set; }

[YamlMember(Alias = "apiVersion")]
public string ApiVersion { get; set; }

Expand Down
10 changes: 10 additions & 0 deletions src/KubeConfigModels/UserCredentials.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace k8s.KubeConfigModels
{
using System.Collections.Generic;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;

Expand All @@ -8,9 +9,15 @@ public class UserCredentials
[YamlMember(Alias = "client-certificate-data")]
public string ClientCertificateData { get; set; }

[YamlMember(Alias = "client-certificate")]
public string ClientCertificate { get; set; }

[YamlMember(Alias = "client-key-data")]
public string ClientKeyData { get; set; }

[YamlMember(Alias = "client-key")]
public string ClientKey { get; set; }

[YamlMember(Alias = "token")]
public string Token { get; set; }

Expand All @@ -19,5 +26,8 @@ public class UserCredentials

[YamlMember(Alias = "password")]
public string Password { get; set; }

[YamlMember(Alias = "auth-provider")]
public Dictionary<string, dynamic> AuthProvider { get; set; }
}
}
11 changes: 7 additions & 4 deletions src/Kubernetes.Auth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public Kubernetes(KubernetesClientConfiguration config)
{
this.Initialize();

this.CaCert = Utils.Base64Decode(config.SslCaCert);
this.CaCert = config.SslCaCert;
this.BaseUri = new Uri(config.Host);

// ssl cert validation
Expand All @@ -45,7 +45,7 @@ public Kubernetes(KubernetesClientConfiguration config)
this.InitializeHttpClient(handler);
}

private string CaCert { get; set; }
private X509Certificate2 CaCert { get; set; }

/// <summary>
/// Set credentials for the Client
Expand All @@ -65,7 +65,10 @@ private async Task SetCredentialsAsync(KubernetesClientConfiguration config, Htt
this.Credentials = new KubernetesClientCredentials(config.Username, config.Password);
}
// othwerwise set handler for clinet cert based auth
else if (!string.IsNullOrWhiteSpace(config.ClientCertificateData) && !string.IsNullOrWhiteSpace(config.ClientCertificateKey))
else if ((!string.IsNullOrWhiteSpace(config.ClientCertificateData) ||
!string.IsNullOrWhiteSpace(config.ClientCertificate)) &&
(!string.IsNullOrWhiteSpace(config.ClientCertificateKey) ||
!string.IsNullOrWhiteSpace(config.ClientKey)))
{
var pfxFilePath = await Utils.GeneratePfxAsync(config).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(pfxFilePath))
Expand Down Expand Up @@ -110,7 +113,7 @@ private async Task SetCredentialsAsync(KubernetesClientConfiguration config, Htt
chain0.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

// add all your extra certificate chain
chain0.ChainPolicy.ExtraStore.Add(new X509Certificate2(System.Text.Encoding.UTF8.GetBytes(this.CaCert)));
chain0.ChainPolicy.ExtraStore.Add(this.CaCert);
chain0.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
var isValid = chain0.Build((X509Certificate2)certificate);
return isValid;
Expand Down
33 changes: 29 additions & 4 deletions src/KubernetesClientConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace k8s
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using k8s.Exceptions;
using k8s.KubeConfigModels;
using YamlDotNet.Serialization;
Expand Down Expand Up @@ -49,7 +50,7 @@ public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentC
/// <summary>
/// Gets SslCaCert
/// </summary>
public string SslCaCert { get; private set; }
public X509Certificate2 SslCaCert { get; private set; }

/// <summary>
/// Gets ClientCertificateData
Expand All @@ -61,6 +62,16 @@ public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentC
/// </summary>
public string ClientCertificateKey { get; private set; }

/// <summary>
/// Gets ClientCertificate filename
/// </summary>
public string ClientCertificate { get; private set; }

/// <summary>
/// Gets ClientCertificate Key filename
/// </summary>
public string ClientKey { get; private set; }

/// <summary>
/// Gets a value indicating whether to skip ssl server cert validation
/// </summary>
Expand Down Expand Up @@ -145,13 +156,20 @@ private void Initialize(K8SConfiguration k8SConfig, string currentContext = null
}

if (!clusterDetails.ClusterEndpoint.SkipTlsVerify &&
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthorityData))
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthorityData) &&
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthority))
{
throw new KubeConfigException($"certificate-authority-data not found for current-context :{activeContext} in kubeconfig");
throw new KubeConfigException($"neither certificate-authority-data nor certificate-authority not found for current-context :{activeContext} in kubeconfig");
}

this.Host = clusterDetails.ClusterEndpoint.Server;
this.SslCaCert = clusterDetails.ClusterEndpoint.CertificateAuthorityData;
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, null);
}
this.SkipTlsVerify = clusterDetails.ClusterEndpoint.SkipTlsVerify;
}
else
Expand Down Expand Up @@ -202,6 +220,13 @@ private void SetUserDetails(User userDetails)
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 kube config");
Expand Down
36 changes: 24 additions & 12 deletions src/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,35 @@ public static async Task<string> GeneratePfxAsync(KubernetesClientConfiguration
var certDirPath = Path.Combine(userHomeDir, ".k8scerts");
Directory.CreateDirectory(certDirPath);

var keyFilePath = "";
var certFilePath = "";

var filePrefix = config.CurrentContext;
var keyFilePath = Path.Combine(certDirPath, filePrefix + "key");
var certFilePath = Path.Combine(certDirPath, filePrefix + "cert");
var pfxFilePath = Path.Combine(certDirPath, filePrefix + "pfx");

using (FileStream fs = File.Create(keyFilePath))
{
byte[] info = Convert.FromBase64String(config.ClientCertificateKey);
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(config.ClientCertificateKey)) {
keyFilePath = Path.Combine(certDirPath, filePrefix + "key");
using (FileStream fs = File.Create(keyFilePath))
{
byte[] info = Convert.FromBase64String(config.ClientCertificateKey);
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
}
}

using (FileStream fs = File.Create(certFilePath))
{
byte[] info = Convert.FromBase64String(config.ClientCertificateData);
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(config.ClientKey)) {
keyFilePath = config.ClientKey;
}

if (!string.IsNullOrWhiteSpace(config.ClientCertificateData)) {
certFilePath = Path.Combine(certDirPath, filePrefix + "cert");

using (FileStream fs = File.Create(certFilePath))
{
byte[] info = Convert.FromBase64String(config.ClientCertificateData);
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
}
}
if (!string.IsNullOrWhiteSpace(config.ClientCertificate)) {
certFilePath = config.ClientCertificate;
}
var process = new Process();
process.StartInfo = new ProcessStartInfo()
{
Expand Down
30 changes: 26 additions & 4 deletions tests/KubernetesClientConfigurationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ namespace k8s.Tests
public class KubernetesClientConfigurationTests
{

public static string readLine(string fileName) {
StreamReader reader = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read));
return reader.ReadLine();
}

/// <summary>
/// This file contains a sample kubeconfig file
/// </summary>
Expand Down Expand Up @@ -110,16 +115,33 @@ public void ContextUserTokenTest(string context, string token)
/// <param name="clientCertData">'client-certificate-data' node content</param>
/// <param name="clientCertKey">'client-key-data' content</param>
[Theory]
[InlineData("federal-context", "path/to/my/client/cert" ,"path/to/my/client/key")]
public void ContextCertificateTest(string context, string clientCertData, string clientCertKey)
[InlineData("federal-context", "assets/client.crt" ,"assets/client.key")]
public void ContextCertificateTest(string context, string clientCert, string clientCertKey)
{
var fi = new FileInfo(kubeConfigFileName);
var cfg = new KubernetesClientConfiguration(fi, context);
Assert.Equal(context, cfg.CurrentContext);
Assert.Equal(cfg.ClientCertificate, clientCert);
Assert.Equal(cfg.ClientKey, clientCertKey);
}

/// <summary>
/// Checks if certificate-based authentication is loaded properly from the config file, per context
/// </summary>
/// <param name="context">Context to retreive the configuration</param>
[Theory]
[InlineData("victorian-context")]
public void ClientDataTest(string context)
{
var fi = new FileInfo(kubeConfigFileName);
var cfg = new KubernetesClientConfiguration(fi, context);
Assert.Equal(context, cfg.CurrentContext);
Assert.Equal(cfg.ClientCertificateData, clientCertData);
Assert.Equal(cfg.ClientCertificateKey, clientCertKey);
Assert.NotNull(cfg.SslCaCert);
Assert.Equal(readLine("assets/client-certificate-data.txt"), cfg.ClientCertificateData);
Assert.Equal(readLine("assets/client-key-data.txt"), cfg.ClientCertificateKey);
}


/// <summary>
/// Test that an Exception is thrown when initializating a KubernetClientConfiguration whose config file Context is not present
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions tests/assets/ca-data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURERENDQWZTZ0F3SUJBZ0lSQUo5ZCtLeThkTDJVSzRjdXplMmo2WnN3RFFZSktvWklodmNOQVFFTEJRQXcKTHpFdE1Dc0dBMVVFQXhNa1lXRTBZVFV3T0RZdE0yVm1aaTAwWWpCa0xUbGxORGt0WmpNeVpXWXpabUpqWWpNNApNQjRYRFRFM01ESXlOakExTURRek5Gb1hEVEl5TURJeU5UQTFNRFF6TkZvd0x6RXRNQ3NHQTFVRUF4TWtZV0UwCllUVXdPRFl0TTJWbVppMDBZakJrTFRsbE5Ea3Raak15WldZelptSmpZak00TUlJQklqQU5CZ2txaGtpRzl3MEIKQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBM2dkandhdHNsdCsvQVpqV3hmbkNQeGZqMzNHUUxlOU00VU42VmEwRQpKd0FYL2R3L1ZVa0dvVjlDc3NKRUZMdEdTUnM2K2h0RTEvOUN3ak1USDh2WExKcURHTE9KdFQ5dW9sR2c2Q2k1ClBKNDNKelVLWmJlYVE4Z3hhZndzQjdQU05vTTJOYzROVm9lZzBVTUw0bndGeEhXeTNYWHlFZ0QxTWxTUnVrb3oKTTNoRUVxUjJNVFdrNm9KK3VJNFF4WVZWMnZuWXdXaEJwUDlDR3RWUTlyUW9MVFowcmFpOCtDYURBMVltTWRhbQpRYUVPdURlSFRqU2FYM2dyR0FBVVFWNWl6MC9qVVBuK3lJNm1iV0trbzFzNytPY1dZR2F1aDFaMzFYSjJsc0RTCnU4a3F0d215UEcyUVl2aUQ4YjNOWFAyY0dRK2EwZlpRZnBrbTF0U3IxQnhhaXdJREFRQUJveU13SVRBT0JnTlYKSFE4QkFmOEVCQU1DQWdRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQQpuVzFXVXlLbVJ0TlNzU1VzVFBSUnhFRzhhek9kdjdYeUhRL0R5VWNqWm9rUEJVVHY4VjdvNG96RHgyVHV6UEdYCmZ2YlMvT2g0VDd6ZlYxdjJadmU3dTBxelNiRTl5OGpsaDNxYXJEcEd5ZmlTamwycmhIOFBmay9sZGR0VFpVL04KSkVtYW5ReGl6R20xV2pCSklRSE5LZENneVIwN3A1c0MwNnR3K25YUytla1MxMlBUTG45WjBuRDBKVDdQSzRXQgpQc3ZXeDVXN0w5dnJIdVN5SGRSTkt5eEEvbWI1WHdXMDBkZUpmaHZub0p3ZWRYNDVKZVRiME5MczUzaURqVEU1CnRpdU03Z1RVSjlCcGZTL0gvYSt2SmovVWQ2bHM0QndrWmpUNHNhOTA1bnNzdnRqamlwZ1N5a0QzVkxCQ3VueTkKd1NnbE1vSnZNWmg0bC9FVFJPeFE3Zz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
18 changes: 18 additions & 0 deletions tests/assets/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC5zCCAc+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p
a3ViZUNBMB4XDTE3MDcyNDA1NDExNloXDTI3MDcyMjA1NDExNlowFTETMBEGA1UE
AxMKbWluaWt1YmVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMfj
J9bJarUsN5Ynt/sbDFQQLp6BeHPXOcUdbNan1YbXdFGN8qLKkkQz0YY1hcVGrXdj
3vd2s8x9XlOyQPZ1SX4vJa5x/67BzFdxbCLg6jBYAisGvYu0hV4jvhHYOZH8sWUp
6n+gPm5c3J8gjqAmM0VwpvtG9HBIr1MWQ4HSTCBVoPvuG9TkOyxrB9RCha16hG7j
B3m9XNEkRVl1xvW6wkeTO4n5cFSoDG0bfCnnjf0oz+pf0yJoSHbl/f2jI/rggMft
0R0LJfqdGlNCKCuN4g0jMmf26313oe+7i8uU4ut9iM1OBv6vD+xy115DGYG7EQIy
lC1rd+gNlGQSxDafAb8CAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQW
MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
DQEBCwUAA4IBAQAnXDZUdfC22zyFpZ+Rez3tyk9SqpOeiN1xGirZ5obDgvOS9vSR
GLrsdN4UtXfGpKeMNQJV4e9YDz1ehLd1MK1BoxDVZHB0Sm2QxuyA4EyPfpHH9zaY
qoRgDeUKBmCteLLcY3ukOzGf915j+lWQHv+tk52gvHfxvRyEuawSxSnowkGGFY9R
6AQ2cFm7G3SdygRWVXT1hk5hVQXvBY9DNU1YNvN0qWE6ss5RHJ/cxHFWtrdcr86K
DqW9Ylr1l2iwkWpnXR4OMK3ZFjwX/qi11Z8eMDOi+0FxZ/6BkGQxe7X6D2GjCZ3r
Lfbj0HBpynkd6lfLmIWgEzGYxrQjvczbAKBD
-----END CERTIFICATE-----
1 change: 1 addition & 0 deletions tests/assets/client-certificate-data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlEUkRDQ0FpeWdBd0lCQWdJSUVIVm8zVzZXcnJjd0RRWUpLb1pJaHZjTkFRRUxCUUF3RXpFUk1BOEdBMVVFQXd3SVlXTnphemh6DQpZMkV3SGhjTk1UY3dOREU1TURBd01EQXdXaGNOTVRrd05ERTVNREF3TURBd1dqQVZNUk13RVFZRFZRUUREQXByZFdKbFkyOXVabWxuDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXVEZ0ttVUxsU0ZSTStCN0pNMWMxUEJqS25mWlZpL1d1DQpSUks2TE9xNHpzL1UxanUyN21TbE9HbWJxRWVYTlpCRVFCblYvVGptQXpqM0Zwd2VKbW5PdDY0TTFIeXZRUW8yTC9LS2JlOVlPbUxNDQpRWXZyeE9QeFRnZHVJeDYzTGxKSUJRZERqdVFhWUhBc0FqTllhbTB3UmQwZTNhVkUxeEJnVDA4QkVWZnVwZmUrUnpXUWhVemJXYkhDDQpydmU2b2s4aHQzRk9LYjNxRzhyR3UrYzN4bGM1MXNVa2ovMGhMK0xrZVBWOTBRYVVCRjF6czlDMVZGaVhoT1Z6WlRjQ0lWQThSTDNvDQpxRTdGUEwvczBNc0RsdkRoNkZ3ZFkvUWhwSUtRMkdKTHQ0ZGRobk5yYW5GbS9pM1RzQ3FJSWxieHl5TVRsT09YYytOUG9mZW9EUUcvDQpvQldjTVFJREFRQUJvNEdaTUlHV01FSUdBMVVkSXdRN01EbUFGSmcrY0p4ZHpaUzNabzdjajFjQXJFWjNxREh1b1Jla0ZUQVRNUkV3DQpEd1lEVlFRRERBaGhZM05yT0hOallZSUlGTjZKejlmRStOVXdIUVlEVlIwT0JCWUVGTmJxZURyeHRvbWZFYnd5bmFUaXp4WXVmeVRXDQpNQXdHQTFVZEV3RUIvd1FDTUFBd0RnWURWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWRKUVFNTUFvR0NDc0dBUVVGQndNQ01BMEdDU3FHDQpTSWIzRFFFQkN3VUFBNElCQVFCYkFKdjJDRzRnTDJtNlpiQmJKSEtqMVF5MGtmbUFJdWgyZHNISU5vUHZ4V0lqY3VXeHZlbUpRcndUDQpuUEZPeWFMY3VtNmVmcGZhWG04T2hxNWxjT3NldUtYaDVya2ZuRUp1VmNWYk9UNXY2aUU3TEY5eGMrelVlTkZDWjA1a1QwbU52eW9lDQpIVmhkYlljeG8yOXVwbGVqa3RqZXd0eGZBZjM2a25hQytOVGE3dVZyNVQ0aTd4MUNQMGkvcUY5ZVgwVHJqZ0diM09MTHVwcVhMSzd5DQpUWUllK3NCajNjOGZRNit6RUJDVFNib05DRlRldXpjOTMxclltc1VyZGtIdEp2SkI2aSthMG5iRjB4MnRYY3ZRbVJ6aUwzTGR0UG84DQptSWh0bDRRWXBQZG5Qdk1RWk1MMlZ4T0FqN3V0RnhNMW44OEpKV0NaTkNyUUdYZjBLSDFpdHhwNg0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0K

0 comments on commit 6333784

Please sign in to comment.