Skip to content

Commit 2a14c3f

Browse files
brendandburnsbrendanburns
authored andcommitted
Remove openssl dependency. Move to dotnet 2.0
1 parent d68e940 commit 2a14c3f

File tree

5 files changed

+136
-119
lines changed

5 files changed

+136
-119
lines changed

src/DotNetUtilities.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
namespace k8s {
2+
using System;
3+
using System.Security.Cryptography;
4+
5+
using Org.BouncyCastle.Crypto.Parameters;
6+
using Org.BouncyCastle.Math;
7+
8+
// This class was derived from:
9+
// https://github.com/bcgit/bc-csharp/blob/master/crypto/src/security/DotNetUtilities.cs
10+
// Copyright (c) 2000 - 2017 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org)
11+
//
12+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
13+
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15+
public class DotNetUtilities
16+
{
17+
public static RSAParameters ToRSAParameters(RsaPrivateCrtKeyParameters privKey)
18+
{
19+
RSAParameters rp = new RSAParameters();
20+
rp.Modulus = privKey.Modulus.ToByteArrayUnsigned();
21+
rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned();
22+
rp.P = privKey.P.ToByteArrayUnsigned();
23+
rp.Q = privKey.Q.ToByteArrayUnsigned();
24+
rp.D = ConvertRSAParametersField(privKey.Exponent, rp.Modulus.Length);
25+
rp.DP = ConvertRSAParametersField(privKey.DP, rp.P.Length);
26+
rp.DQ = ConvertRSAParametersField(privKey.DQ, rp.Q.Length);
27+
rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length);
28+
return rp;
29+
}
30+
31+
private static byte[] ConvertRSAParametersField(BigInteger n, int size)
32+
{
33+
byte[] bs = n.ToByteArrayUnsigned();
34+
35+
if (bs.Length == size)
36+
return bs;
37+
38+
if (bs.Length > size)
39+
throw new ArgumentException("Specified size too small", "size");
40+
41+
byte[] padded = new byte[size];
42+
Array.Copy(bs, 0, padded, size - bs.Length, bs.Length);
43+
return padded;
44+
}
45+
}
46+
}

src/Kubernetes.Auth.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ private async Task SetCredentialsAsync(KubernetesClientConfiguration config, Htt
7070
(!string.IsNullOrWhiteSpace(config.ClientCertificateKey) ||
7171
!string.IsNullOrWhiteSpace(config.ClientKey)))
7272
{
73-
var pfxFilePath = await Utils.GeneratePfxAsync(config).ConfigureAwait(false);
74-
75-
var cert = new X509Certificate2(pfxFilePath, string.Empty, X509KeyStorageFlags.PersistKeySet);
73+
var cert = await Utils.GeneratePfxAsync(config).ConfigureAwait(false);
7674
handler.ClientCertificates.Add(cert);
7775
}
7876
else

src/KubernetesClient.csproj

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>netstandard2.0</TargetFramework>
3+
<TargetFramework>netcoreapp2.0</TargetFramework>
44
</PropertyGroup>
55
<ItemGroup>
66
<Compile Remove="GlobalSuppressions.cs" />
77
</ItemGroup>
88
<ItemGroup>
9-
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="1.1.0" />
9+
<PackageReference Include="BouncyCastle.NetCore" Version="1.8.1.3" />
1010
<PackageReference Include="Microsoft.Rest.ClientRuntime" Version="3.0.3" />
1111
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
12-
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
1312
<PackageReference Include="YamlDotNet.NetCore" Version="1.0.0" />
1413
</ItemGroup>
15-
</Project>
14+
</Project>

src/Utils.cs

Lines changed: 85 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,85 @@
1-
namespace k8s
2-
{
3-
using k8s.Exceptions;
4-
using System;
5-
using System.ComponentModel;
6-
using System.Diagnostics;
7-
using System.IO;
8-
using System.Runtime.InteropServices;
9-
using System.Text;
10-
using System.Threading.Tasks;
11-
12-
public static class Utils
13-
{
14-
/// <summary>
15-
/// Encode string in base64 format.
16-
/// </summary>
17-
/// <param name="text">string to be encoded.</param>
18-
/// <returns>Encoded string.</returns>
19-
public static string Base64Encode(string text)
20-
{
21-
return Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
22-
}
23-
24-
/// <summary>
25-
/// Encode string in base64 format.
26-
/// </summary>
27-
/// <param name="text">string to be encoded.</param>
28-
/// <returns>Encoded string.</returns>
29-
public static string Base64Decode(string text)
30-
{
31-
return Encoding.UTF8.GetString(Convert.FromBase64String(text));
32-
}
33-
34-
/// <summary>
35-
/// Generates pfx from client configuration
36-
/// </summary>
37-
/// <param name="config">Kuberentes Client Configuration</param>
38-
/// <returns>Generated Pfx Path</returns>
39-
/// TODO: kabhishek8260 Remplace the method with X509 Certificate with private key(in dotnet 2.0)
40-
public static async Task<string> GeneratePfxAsync(KubernetesClientConfiguration config)
41-
{
42-
var userHomeDir = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
43-
Environment.GetEnvironmentVariable("USERPROFILE") :
44-
Environment.GetEnvironmentVariable("HOME");
45-
46-
var certDirPath = Path.Combine(userHomeDir, ".k8scerts");
47-
Directory.CreateDirectory(certDirPath);
48-
49-
var keyFilePath = "";
50-
var certFilePath = "";
51-
52-
var filePrefix = config.CurrentContext;
53-
var pfxFilePath = Path.Combine(certDirPath, filePrefix + "pfx");
54-
if (!string.IsNullOrWhiteSpace(config.ClientCertificateKey))
55-
{
56-
keyFilePath = Path.Combine(certDirPath, filePrefix + "key");
57-
using (FileStream fs = File.Create(keyFilePath))
58-
{
59-
byte[] info = Convert.FromBase64String(config.ClientCertificateKey);
60-
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
61-
}
62-
}
63-
if (!string.IsNullOrWhiteSpace(config.ClientKey))
64-
{
65-
keyFilePath = config.ClientKey;
66-
}
67-
68-
if (!string.IsNullOrWhiteSpace(config.ClientCertificateData))
69-
{
70-
certFilePath = Path.Combine(certDirPath, filePrefix + "cert");
71-
72-
using (FileStream fs = File.Create(certFilePath))
73-
{
74-
byte[] info = Convert.FromBase64String(config.ClientCertificateData);
75-
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
76-
}
77-
}
78-
if (!string.IsNullOrWhiteSpace(config.ClientCertificate))
79-
{
80-
certFilePath = config.ClientCertificate;
81-
}
82-
83-
var processStartInfo = new ProcessStartInfo
84-
{
85-
FileName = @"openssl",
86-
Arguments = $"pkcs12 -export -out {pfxFilePath} -inkey {keyFilePath} -in {certFilePath} -passout pass:",
87-
CreateNoWindow = true,
88-
RedirectStandardError = true,
89-
RedirectStandardOutput = true
90-
};
91-
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)
104-
{
105-
throw new KubernetesClientException("Failed to generate pfx file with openssl.", e);
106-
}
107-
108-
return pfxFilePath;
109-
}
110-
}
111-
}
1+
namespace k8s
2+
{
3+
using System;
4+
using System.Diagnostics;
5+
using System.Globalization;
6+
using System.IO;
7+
using System.Runtime.InteropServices;
8+
using System.Security.Cryptography;
9+
using System.Security.Cryptography.X509Certificates;
10+
using System.Text;
11+
using System.Threading.Tasks;
12+
13+
using Org.BouncyCastle.Crypto;
14+
using Org.BouncyCastle.Crypto.Parameters;
15+
using Org.BouncyCastle.Security;
16+
using Org.BouncyCastle.OpenSsl;
17+
18+
public static class Utils
19+
{
20+
/// <summary>
21+
/// Encode string in base64 format.
22+
/// </summary>
23+
/// <param name="text">string to be encoded.</param>
24+
/// <returns>Encoded string.</returns>
25+
public static string Base64Encode(string text)
26+
{
27+
return Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
28+
}
29+
30+
/// <summary>
31+
/// Encode string in base64 format.
32+
/// </summary>
33+
/// <param name="text">string to be encoded.</param>
34+
/// <returns>Encoded string.</returns>
35+
public static string Base64Decode(string text)
36+
{
37+
return Encoding.UTF8.GetString(Convert.FromBase64String(text));
38+
}
39+
40+
/// <summary>
41+
/// Generates pfx from client configuration
42+
/// </summary>
43+
/// <param name="config">Kuberentes Client Configuration</param>
44+
/// <returns>Generated Pfx Path</returns>
45+
/// TODO: kabhishek8260 Remplace the method with X509 Certificate with private key(in dotnet 2.0)
46+
public static async Task<X509Certificate2> GeneratePfxAsync(KubernetesClientConfiguration config)
47+
{
48+
var keyData = new byte[]{};
49+
var certData = new byte[]{};
50+
51+
var filePrefix = config.CurrentContext;
52+
if (!string.IsNullOrWhiteSpace(config.ClientCertificateKey))
53+
{
54+
keyData = Convert.FromBase64String(config.ClientCertificateKey);
55+
}
56+
if (!string.IsNullOrWhiteSpace(config.ClientKey))
57+
{
58+
keyData = File.ReadAllBytes(config.ClientKey);
59+
}
60+
61+
if (!string.IsNullOrWhiteSpace(config.ClientCertificateData))
62+
{
63+
certData = Convert.FromBase64String(config.ClientCertificateData);
64+
}
65+
if (!string.IsNullOrWhiteSpace(config.ClientCertificate))
66+
{
67+
certData = File.ReadAllBytes(config.ClientCertificate);
68+
}
69+
70+
var cert = new X509Certificate2(certData);
71+
return addPrivateKey(cert, keyData);
72+
}
73+
74+
public static X509Certificate2 addPrivateKey(X509Certificate2 cert, byte[] keyData)
75+
{
76+
using (var reader = new StreamReader(new MemoryStream(keyData)))
77+
{
78+
var cipherKey = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();
79+
var rsaKeyParams = (RsaPrivateCrtKeyParameters)cipherKey.Private;
80+
var rsaKey = RSA.Create(DotNetUtilities.ToRSAParameters(rsaKeyParams));
81+
return cert.CopyWithPrivateKey(rsaKey);
82+
}
83+
}
84+
}
85+
}

tests/tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>netstandard2.0</TargetFramework>
3+
<TargetFramework>netcoreapp2.0</TargetFramework>
44
<IsPackable>false</IsPackable>
55
</PropertyGroup>
66
<ItemGroup>

0 commit comments

Comments
 (0)