Skip to content

Commit 720b7bd

Browse files
Merge pull request #17 from jpoon/master
Improve error messaging with OpenSSL
2 parents c6a769b + 0e1b6b7 commit 720b7bd

File tree

5 files changed

+95
-90
lines changed

5 files changed

+95
-90
lines changed

README.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,58 @@
11
# csharp
22
Work In Progress
3-
Currently only supported on Linux
43

54
[![Travis](https://img.shields.io/travis/kubernetes-client/csharp.svg)](https://travis-ci.org/kubernetes-client/csharp)
65

7-
# Generating the client code
6+
# Generating the Client Code
87

98
## Prerequisites
109

1110
Check out the generator project into some other directory
1211
(henceforth `$GEN_DIR`)
1312

14-
```
13+
```bash
1514
cd $GEN_DIR/..
1615
git clone https://github.com/kubernetes-client/gen
1716
```
1817

1918
Install the [`autorest` tool](https://github.com/azure/autorest):
2019

21-
```
20+
```bash
2221
npm install autorest
2322
```
2423

2524
## Generating code
2625

27-
```
26+
```bash
2827
# Where REPO_DIR points to the root of the csharp repository
2928
cd ${REPO_DIR}/csharp/src
3029
${GEN_DIR}/openapi/csharp.sh generated csharp.settings
3130
```
3231

33-
# Testing
32+
# Usage
33+
34+
## Prerequisities
35+
36+
* [OpenSSL](https://www.openssl.org/)
37+
* For Linux/Mac:
38+
* LibCurl built with OpenSSL (Mac: `brew install curl --with-nghttp2`)
39+
40+
## Running the Examples
41+
42+
```bash
43+
git clone [email protected]:kubernetes-client/csharp.git
44+
cd csharp\examples\simple
45+
dotnet run
46+
```
47+
48+
## Testing
3449

3550
The project uses [XUnit](https://xunit.github.io) as unit testing framework.
3651

37-
To run the tests you need to:
52+
To run the tests
3853

3954
```bash
40-
cd tests
55+
cd csharp\tests
4156
dotnet restore
4257
dotnet xunit
4358
```

src/Kubernetes.Auth.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,6 @@ private async Task SetCredentialsAsync(KubernetesClientConfiguration config, Htt
7171
!string.IsNullOrWhiteSpace(config.ClientKey)))
7272
{
7373
var pfxFilePath = await Utils.GeneratePfxAsync(config).ConfigureAwait(false);
74-
if (string.IsNullOrWhiteSpace(pfxFilePath))
75-
{
76-
throw new KubernetesClientException("Failed to generate pfx file");
77-
}
7874

7975
var cert = new X509Certificate2(pfxFilePath, string.Empty, X509KeyStorageFlags.PersistKeySet);
8076
handler.ClientCertificates.Add(cert);

src/KubernetesClientConfiguration.cs

Lines changed: 44 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,12 @@ public class KubernetesClientConfiguration
1616
{
1717
/// <summary>
1818
/// Initializes a new instance of the <see cref="KubernetesClientConfiguration"/> class.
19-
/// Initializes a new instance of the ClientConfiguration class
2019
/// </summary>
2120
/// <param name="kubeconfig">kubeconfig file info</param>
2221
/// <param name="currentContext">Context to use from kube config</param>
2322
public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentContext = null)
2423
{
25-
if (kubeconfig == null)
26-
{
27-
kubeconfig = new FileInfo(KubeConfigDefaultLocation);
28-
}
29-
var k8SConfig = this.LoadKubeConfig(kubeconfig);
24+
var k8SConfig = this.LoadKubeConfig(kubeconfig ?? new FileInfo(KubeConfigDefaultLocation));
3025
this.Initialize(k8SConfig, currentContext);
3126
}
3227

@@ -108,86 +103,73 @@ public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentC
108103
/// <param name="currentContext">Current Context</param>
109104
private void Initialize(K8SConfiguration k8SConfig, string currentContext = null)
110105
{
111-
Context activeContext;
112-
113106
if (k8SConfig.Contexts == null)
114107
{
115108
throw new KubeConfigException("No contexts found in kubeconfig");
116-
}
109+
}
117110

118-
// set the currentCOntext to passed context if not null
119-
if (!string.IsNullOrWhiteSpace(currentContext))
111+
if (k8SConfig.Clusters == null)
120112
{
121-
122-
activeContext = k8SConfig.Contexts.FirstOrDefault(c => c.Name.Equals(currentContext, StringComparison.OrdinalIgnoreCase));
123-
if (activeContext != null)
124-
{
125-
this.CurrentContext = activeContext.Name;
126-
}
127-
else
128-
{
129-
throw new KubeConfigException($"CurrentContext: {0} not found in contexts in kubeconfig");
130-
}
113+
throw new KubeConfigException($"No clusters found in kubeconfig");
131114
}
132-
// otherwise set current context from kubeconfig
133-
else
115+
116+
if (k8SConfig.Users == null)
134117
{
135-
activeContext = k8SConfig.Contexts.FirstOrDefault(c => c.Name.Equals(k8SConfig.CurrentContext, StringComparison.OrdinalIgnoreCase));
136-
137-
if (activeContext == null)
138-
{
139-
throw new KubeConfigException($"CurrentContext: {currentContext} not found in contexts in kubeconfig");
140-
}
118+
throw new KubeConfigException($"No users found in kubeconfig");
119+
}
141120

142-
this.CurrentContext = activeContext.Name;
121+
// current context
122+
currentContext = currentContext ?? k8SConfig.CurrentContext;
123+
Context activeContext = k8SConfig.Contexts.FirstOrDefault(c => c.Name.Equals(currentContext, StringComparison.OrdinalIgnoreCase));
124+
if (activeContext == null)
125+
{
126+
throw new KubeConfigException($"CurrentContext: {currentContext} not found in contexts in kubeconfig");
143127
}
144128

145-
if (k8SConfig.Clusters == null)
129+
this.CurrentContext = activeContext.Name;
130+
131+
// cluster
132+
var clusterDetails = k8SConfig.Clusters.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.Cluster, StringComparison.OrdinalIgnoreCase));
133+
if (clusterDetails?.ClusterEndpoint == null)
146134
{
147-
throw new KubeConfigException($"clusters not found for current-context :{activeContext} in kubeconfig");
135+
throw new KubeConfigException($"Cluster not found for context {activeContext} in kubeconfig");
148136
}
149137

150-
var clusterDetails = k8SConfig.Clusters.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.Cluster, StringComparison.OrdinalIgnoreCase));
151-
if (clusterDetails?.ClusterEndpoint != null)
138+
if (string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.Server))
152139
{
153-
if (string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.Server))
154-
{
155-
throw new KubeConfigException($"server not found for current-context :{activeContext} in kubeconfig");
156-
}
140+
throw new KubeConfigException($"Server not found for current-context {activeContext} in kubeconfig");
141+
}
157142

158-
if (!clusterDetails.ClusterEndpoint.SkipTlsVerify &&
159-
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthorityData) &&
160-
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthority))
161-
{
162-
throw new KubeConfigException($"neither certificate-authority-data nor certificate-authority not found for current-context :{activeContext} in kubeconfig");
163-
}
143+
if (!clusterDetails.ClusterEndpoint.SkipTlsVerify &&
144+
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthorityData) &&
145+
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthority))
146+
{
147+
throw new KubeConfigException($"neither certificate-authority-data nor certificate-authority not found for current-context :{activeContext} in kubeconfig");
148+
}
164149

165-
this.Host = clusterDetails.ClusterEndpoint.Server;
166-
if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthorityData)) {
167-
string data = clusterDetails.ClusterEndpoint.CertificateAuthorityData;
168-
this.SslCaCert = new X509Certificate2(System.Text.Encoding.UTF8.GetBytes(Utils.Base64Decode(data)));
169-
}
170-
else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority)) {
171-
this.SslCaCert = new X509Certificate2(clusterDetails.ClusterEndpoint.CertificateAuthority, null);
172-
}
173-
this.SkipTlsVerify = clusterDetails.ClusterEndpoint.SkipTlsVerify;
150+
this.Host = clusterDetails.ClusterEndpoint.Server;
151+
if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthorityData))
152+
{
153+
string data = clusterDetails.ClusterEndpoint.CertificateAuthorityData;
154+
this.SslCaCert = new X509Certificate2(System.Text.Encoding.UTF8.GetBytes(Utils.Base64Decode(data)));
174155
}
175-
else
156+
else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority))
176157
{
177-
throw new KubeConfigException($"Cluster details not found for current-context: {activeContext} in kubeconfig");
158+
this.SslCaCert = new X509Certificate2(clusterDetails.ClusterEndpoint.CertificateAuthority, null);
178159
}
160+
this.SkipTlsVerify = clusterDetails.ClusterEndpoint.SkipTlsVerify;
179161

180-
// set user details from kubeconfig
181-
var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.User, StringComparison.OrdinalIgnoreCase));
182-
183-
this.SetUserDetails(userDetails);
162+
// user
163+
this.SetUserDetails(k8SConfig, activeContext);
184164
}
185165

186-
private void SetUserDetails(User userDetails)
166+
private void SetUserDetails(K8SConfiguration k8SConfig, Context activeContext)
187167
{
168+
var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.User, StringComparison.OrdinalIgnoreCase));
169+
188170
if (userDetails == null)
189171
{
190-
throw new KubeConfigException("User not found for the current context in kubeconfig");
172+
throw new KubeConfigException("User not found for context {activeContext.Name} in kubeconfig");
191173
}
192174

193175
if (userDetails.UserCredentials == null)
@@ -229,7 +211,7 @@ private void SetUserDetails(User userDetails)
229211

230212
if (!userCredentialsFound)
231213
{
232-
throw new KubeConfigException($"User: {userDetails.Name} does not have appropriate auth credentials in kube config");
214+
throw new KubeConfigException($"User: {userDetails.Name} does not have appropriate auth credentials in kubeconfig");
233215
}
234216
}
235217

src/Utils.cs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
namespace k8s
22
{
3+
using k8s.Exceptions;
34
using System;
5+
using System.ComponentModel;
46
using System.Diagnostics;
5-
using System.Globalization;
67
using System.IO;
78
using System.Runtime.InteropServices;
89
using System.Text;
@@ -50,32 +51,36 @@ public static async Task<string> GeneratePfxAsync(KubernetesClientConfiguration
5051

5152
var filePrefix = config.CurrentContext;
5253
var pfxFilePath = Path.Combine(certDirPath, filePrefix + "pfx");
53-
if (!string.IsNullOrWhiteSpace(config.ClientCertificateKey)) {
54+
if (!string.IsNullOrWhiteSpace(config.ClientCertificateKey))
55+
{
5456
keyFilePath = Path.Combine(certDirPath, filePrefix + "key");
5557
using (FileStream fs = File.Create(keyFilePath))
5658
{
5759
byte[] info = Convert.FromBase64String(config.ClientCertificateKey);
5860
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
5961
}
6062
}
61-
if (!string.IsNullOrWhiteSpace(config.ClientKey)) {
63+
if (!string.IsNullOrWhiteSpace(config.ClientKey))
64+
{
6265
keyFilePath = config.ClientKey;
6366
}
6467

65-
if (!string.IsNullOrWhiteSpace(config.ClientCertificateData)) {
68+
if (!string.IsNullOrWhiteSpace(config.ClientCertificateData))
69+
{
6670
certFilePath = Path.Combine(certDirPath, filePrefix + "cert");
67-
71+
6872
using (FileStream fs = File.Create(certFilePath))
6973
{
7074
byte[] info = Convert.FromBase64String(config.ClientCertificateData);
7175
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
7276
}
7377
}
74-
if (!string.IsNullOrWhiteSpace(config.ClientCertificate)) {
78+
if (!string.IsNullOrWhiteSpace(config.ClientCertificate))
79+
{
7580
certFilePath = config.ClientCertificate;
7681
}
77-
var process = new Process();
78-
process.StartInfo = new ProcessStartInfo()
82+
83+
var processStartInfo = new ProcessStartInfo
7984
{
8085
FileName = @"openssl",
8186
Arguments = $"pkcs12 -export -out {pfxFilePath} -inkey {keyFilePath} -in {certFilePath} -passout pass:",
@@ -84,14 +89,23 @@ public static async Task<string> GeneratePfxAsync(KubernetesClientConfiguration
8489
RedirectStandardOutput = true
8590
};
8691

87-
process.Start();
88-
process.WaitForExit();
89-
if (process.ExitCode == 0)
92+
try
93+
{
94+
using (Process process = Process.Start(processStartInfo))
95+
{
96+
process.WaitForExit();
97+
if (process.ExitCode != 0)
98+
{
99+
throw new KubernetesClientException($"Failed to generate pfx file with openssl. ExitCode = {process.ExitCode}.");
100+
}
101+
}
102+
}
103+
catch (Win32Exception e)
90104
{
91-
return pfxFilePath;
105+
throw new KubernetesClientException("Failed to generate pfx file with openssl.", e);
92106
}
93107

94-
return null;
108+
return pfxFilePath;
95109
}
96110
}
97111
}

tests/KubernetesClientConfigurationTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System;
2-
using Xunit;
3-
using k8s;
1+
using Xunit;
42
using System.IO;
53

64
namespace k8s.Tests

0 commit comments

Comments
 (0)