Skip to content

Commit f422ee8

Browse files
committed
chore(client): Add verbose logging, formatting + cleanup
1 parent 57f2a18 commit f422ee8

File tree

1 file changed

+132
-45
lines changed

1 file changed

+132
-45
lines changed

kubernetes-orchestrator-extension/Clients/KubeClient.cs

Lines changed: 132 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
using System;
99
using System.Collections.Generic;
10-
using System.Configuration;
1110
using System.IO;
1211
using System.Linq;
1312
using System.Net;
@@ -269,7 +268,7 @@ private IKubernetes GetKubeClient(string kubeconfig)
269268
}
270269
else if
271270
(string.IsNullOrEmpty(
272-
credentialFileName)) // If no config defined in store parameters, use default config. This should never happen though.
271+
credentialFileName)) // If no config defined in store parameters, use default config. This should never happen though.
273272
{
274273
_logger.LogWarning(
275274
"No config defined in store parameters, using default config. This should never happen!");
@@ -569,37 +568,117 @@ public V1Secret UpdatePKCS12SecretStore(K8SJobCertificate jobCertificate, string
569568
if (certdataFieldNames != null && !certdataFieldNames.Contains(searchFieldName)) continue;
570569

571570
certdataFieldName = fieldName;
572-
_logger.LogTrace($"Adding cert '{fieldName}' to existingPkcs12");
571+
_logger.LogTrace("Adding cert '{FieldName}' to existingPkcs12", fieldName);
573572
if (jobCertificate.PasswordIsK8SSecret)
574573
{
574+
_logger.LogDebug("Job certificate password is a K8S secret");
575575
if (!string.IsNullOrEmpty(jobCertificate.StorePasswordPath))
576576
{
577+
_logger.LogDebug("Job certificate store password path is {StorePasswordPath}",
578+
jobCertificate.StorePasswordPath);
579+
580+
_logger.LogDebug("Splitting store password path into namespace and secret name");
577581
var passwordPath = jobCertificate.StorePasswordPath.Split("/");
578-
var passwordNamespace = passwordPath[0];
579-
var passwordSecretName = passwordPath[1];
580-
// Get password from k8s secre
582+
583+
string passwordNamespace;
584+
string passwordSecretName;
585+
586+
if (passwordPath.Length == 1)
587+
{
588+
_logger.LogDebug("Password path length is 1, using KubeNamespace");
589+
passwordNamespace = namespaceName;
590+
_logger.LogTrace("Password namespace: {Namespace}", passwordNamespace);
591+
passwordSecretName = passwordPath[0];
592+
}
593+
else
594+
{
595+
_logger.LogDebug(
596+
"Password path length is not 1, using passwordPath[0] and passwordPath[^1]");
597+
passwordNamespace = passwordPath[0];
598+
_logger.LogTrace("Password namespace: {Namespace}", passwordNamespace);
599+
passwordSecretName = passwordPath[^1];
600+
}
601+
602+
_logger.LogDebug("Password namespace: {PasswordNamespace}", passwordNamespace);
603+
_logger.LogDebug("Password secret name: {PasswordSecretName}", passwordSecretName);
604+
581605
var k8sPasswordObj = ReadBuddyPass(passwordSecretName, passwordNamespace);
582-
storePasswordBytes = k8sPasswordObj.Data[passwordFieldName];
606+
_logger.LogDebug(
607+
"Successfully read password secret {PasswordSecretName} in namespace {PasswordNamespace}",
608+
passwordSecretName, passwordNamespace);
609+
610+
if (k8sPasswordObj?.Data == null)
611+
{
612+
_logger.LogError("Unable to read K8S buddy secret {SecretName} in namespace {Namespace}",
613+
passwordSecretName, passwordNamespace);
614+
throw new InvalidK8SSecretException(
615+
$"Unable to read K8S buddy secret {passwordSecretName} in namespace {passwordNamespace}");
616+
}
617+
618+
_logger.LogTrace("Secret response fields: {Keys}", k8sPasswordObj.Data.Keys);
619+
620+
if (!k8sPasswordObj.Data.TryGetValue(passwordFieldName, out storePasswordBytes) ||
621+
storePasswordBytes == null)
622+
{
623+
_logger.LogError("Unable to find password field {FieldName}", passwordFieldName);
624+
throw new InvalidK8SSecretException(
625+
$"Unable to find password field '{passwordFieldName}' in secret '{passwordSecretName}' in namespace '{passwordNamespace}'"
626+
);
627+
}
628+
629+
// storePasswordBytes = k8sPasswordObj.Data[passwordFieldName];
630+
if (storePasswordBytes == null || storePasswordBytes.Length == 0)
631+
{
632+
_logger.LogError(
633+
"Password field {FieldName} in secret {SecretName} in namespace {Namespace} is empty",
634+
passwordFieldName, passwordSecretName, passwordNamespace);
635+
throw new InvalidK8SSecretException(
636+
$"Password field '{passwordFieldName}' in secret '{passwordSecretName}' in namespace '{passwordNamespace}' is empty"
637+
);
638+
}
639+
583640
var storePasswdString = Encoding.UTF8.GetString(storePasswordBytes);
641+
_logger.LogTrace("Importing existing PKCS12 data with store password: {StorePassword}",
642+
storePasswdString); //TODO: INSECURE COMMENT OUT
584643
existingPkcs12.Import(existingPkcs12DataObj.Data[fieldName], storePasswdString,
585644
X509KeyStorageFlags.Exportable);
586645
}
587646
else
588647
{
648+
_logger.LogDebug("Job certificate store password path is empty, using existing secret data");
589649
storePasswordBytes = existingPkcs12DataObj.Data[passwordFieldName];
650+
if (storePasswordBytes == null || storePasswordBytes.Length == 0)
651+
{
652+
_logger.LogError(
653+
"Password field {FieldName} in secret {SecretName} in namespace {Namespace} is empty",
654+
passwordFieldName, secretName, namespaceName);
655+
throw new InvalidK8SSecretException(
656+
$"Password field '{passwordFieldName}' in secret '{secretName}' in namespace '{namespaceName}' is empty"
657+
);
658+
}
659+
660+
_logger.LogTrace("Importing existing PKCS12 data with store password: {StorePassword}",
661+
Encoding.UTF8.GetString(storePasswordBytes)); //TODO: INSECURE COMMENT OUT
590662
existingPkcs12.Import(existingPkcs12DataObj.Data[fieldName],
591663
Encoding.UTF8.GetString(storePasswordBytes), X509KeyStorageFlags.Exportable);
592664
}
593665
}
594666
else if (!string.IsNullOrEmpty(jobCertificate.StorePassword))
595667
{
668+
_logger.LogDebug(
669+
"Job certificate store password is not empty, using job certificate store password");
596670
storePasswordBytes = Encoding.UTF8.GetBytes(jobCertificate.StorePassword);
671+
// _logger.LogTrace("Importing existing PKCS12 data with store password: {StorePassword}",
672+
// Encoding.UTF8.GetString(storePasswordBytes)); //TODO: INSECURE COMMENT OUT
597673
existingPkcs12.Import(existingPkcs12DataObj.Data[fieldName],
598674
Encoding.UTF8.GetString(storePasswordBytes), X509KeyStorageFlags.Exportable);
599675
}
600676
else
601677
{
678+
_logger.LogDebug("Job certificate store password is empty, using provided store password");
602679
storePasswordBytes = Encoding.UTF8.GetBytes(storePasswd);
680+
_logger.LogTrace("Importing existing PKCS12 data with store password: {StorePassword}",
681+
Encoding.UTF8.GetString(storePasswordBytes)); //TODO: INSECURE COMMENT OUT
603682
existingPkcs12.Import(existingPkcs12DataObj.Data[fieldName],
604683
Encoding.UTF8.GetString(storePasswordBytes), X509KeyStorageFlags.Exportable);
605684
}
@@ -646,7 +725,10 @@ public V1Secret UpdatePKCS12SecretStore(K8SJobCertificate jobCertificate, string
646725
// Certificate not found
647726
// add the new certificate to the existingPkcs12
648727
var storePasswordString = Encoding.UTF8.GetString(storePasswordBytes);
649-
_logger.LogTrace("Certificate not found, adding the new certificate to the existingPkcs12");
728+
_logger.LogDebug("Certificate not found, adding the new certificate to the existingPkcs12");
729+
// _logger.LogTrace(
730+
// "Importing jobCertificate.CertBytes into existingPkcs12 with store password: {StorePassword}",
731+
// storePasswd); //TODO: INSECURE COMMENT OUT
650732
existingPkcs12.Import(jobCertificate.Pkcs12, storePasswd, X509KeyStorageFlags.Exportable);
651733
}
652734
}
@@ -657,15 +739,21 @@ public V1Secret UpdatePKCS12SecretStore(K8SJobCertificate jobCertificate, string
657739
}
658740
else
659741
{
742+
_logger.LogDebug("No existing PKCS12 data found, creating new PKCS12 collection");
743+
// _logger.LogTrace(
744+
// "Importing jobCertificate.CertBytes into newPkcs12Collection with store password: {StorePassword}",
745+
// storePasswd); //TODO: INSECURE COMMENT OUT
660746
newPkcs12Collection.Import(jobCertificate.CertBytes, storePasswd, X509KeyStorageFlags.Exportable);
661747
k8sCollection = newPkcs12Collection;
662748
}
663749
}
664750

665-
_logger.LogTrace("Creating V1Secret object");
666-
667-
var p12bytes = k8sCollection.Export(X509ContentType.Pkcs12, Encoding.UTF8.GetString(storePasswordBytes));
751+
// _logger.LogDebug("Exporting PKCS12 data to byte array using store password: {StorePassword}",
752+
// Encoding.UTF8.GetString(storePasswordBytes)); //TODO: INSECURE COMMENT OUT
753+
var p12Bytes = k8sCollection.Export(X509ContentType.Pkcs12, Encoding.UTF8.GetString(storePasswordBytes));
668754

755+
_logger.LogDebug("Creating V1Secret object for PKCS12 data with name {SecretName} in namespace {NamespaceName}",
756+
secretName, namespaceName);
669757
var secret = new V1Secret
670758
{
671759
ApiVersion = "v1",
@@ -678,20 +766,20 @@ public V1Secret UpdatePKCS12SecretStore(K8SJobCertificate jobCertificate, string
678766
Type = "Opaque",
679767
Data = new Dictionary<string, byte[]>
680768
{
681-
{ certdataFieldName, p12bytes }
769+
{ certdataFieldName, p12Bytes }
682770
}
683771
};
684772

685773
if (existingPkcs12DataObj?.Data != null)
686774
{
687775
secret.Data = existingPkcs12DataObj.Data;
688-
secret.Data[certdataFieldName] = p12bytes;
776+
secret.Data[certdataFieldName] = p12Bytes;
689777
}
690778

691779
// Convert p12bytes to pkcs12store
692780
var pkcs12StoreBuilder = new Pkcs12StoreBuilder();
693781
var pkcs12Store = pkcs12StoreBuilder.Build();
694-
pkcs12Store.Load(new MemoryStream(p12bytes), storePasswd.ToCharArray());
782+
pkcs12Store.Load(new MemoryStream(p12Bytes), storePasswd.ToCharArray());
695783

696784

697785
switch (string.IsNullOrEmpty(storePasswd))
@@ -1123,14 +1211,19 @@ private V1Secret CreateOrUpdatePKCS12Secret(string secretName, string namespaceN
11231211

11241212
public V1Secret ReadBuddyPass(string secretName, string passwordSecretPath)
11251213
{
1214+
_logger.MethodEntry();
11261215
// Lookup password secret path on cluster to see if it exists
11271216
_logger.LogDebug("Attempting to lookup password secret path on cluster...");
11281217
var splitPasswordPath = passwordSecretPath.Split("/");
1129-
// Assume secret pattern is namespace/secretName
1130-
var passwordSecretName = splitPasswordPath[splitPasswordPath.Length - 1];
1218+
_logger.LogDebug("Split password secret path: {SplitPasswordPath}", splitPasswordPath.ToString());
1219+
var passwordSecretName = splitPasswordPath[^1];
11311220
var passwordSecretNamespace = splitPasswordPath[0];
1132-
_logger.LogDebug($"Attempting to lookup secret {passwordSecretName} in namespace {passwordSecretNamespace}");
1221+
_logger.LogDebug("Attempting to lookup secret {PasswordSecretName} in namespace {PasswordSecretNamespace}",
1222+
passwordSecretName, passwordSecretNamespace);
11331223
var passwordSecretResponse = Client.CoreV1.ReadNamespacedSecret(secretName, passwordSecretNamespace);
1224+
_logger.LogDebug("Successfully found secret {PasswordSecretName} in namespace {PasswordSecretNamespace}",
1225+
passwordSecretName, passwordSecretNamespace);
1226+
_logger.MethodExit();
11341227
return passwordSecretResponse;
11351228
}
11361229

@@ -1835,7 +1928,6 @@ private IEnumerable<V1Namespace> FetchNamespaces(string clusterName)
18351928
private IEnumerable<V1Namespace> FilterNamespaces(IEnumerable<V1Namespace> namespaces, string[] nsList)
18361929
{
18371930
foreach (var nsObj in namespaces)
1838-
{
18391931
if (nsList.Contains("all") || nsList.Contains(nsObj.Metadata.Name))
18401932
{
18411933
_logger.LogDebug("Processing namespace: {Namespace}", nsObj.Metadata.Name);
@@ -1845,7 +1937,6 @@ private IEnumerable<V1Namespace> FilterNamespaces(IEnumerable<V1Namespace> names
18451937
{
18461938
_logger.LogDebug("Skipping namespace '{Namespace}' as it does not match filter", nsObj.Metadata.Name);
18471939
}
1848-
}
18491940
}
18501941

18511942
private void AddNamespaceLocation(List<string> locations, string clusterName, string namespaceName)
@@ -1864,9 +1955,7 @@ private void DiscoverSecretsInNamespace(
18641955
Client.CoreV1.ListNamespacedSecret(namespaceName).Items);
18651956

18661957
foreach (var secret in secrets)
1867-
{
18681958
ProcessSecretIfSupported(secret, secType, allowedKeys, clusterName, namespaceName, locations);
1869-
}
18701959
}
18711960

18721961
private void ProcessSecretIfSupported(
@@ -1894,7 +1983,6 @@ private T RetryPolicy<T>(Func<T> action)
18941983
const double maxDelaySeconds = 30.0;
18951984

18961985
for (var attempt = 1; attempt <= maxRetries; attempt++)
1897-
{
18981986
try
18991987
{
19001988
return action();
@@ -1914,7 +2002,6 @@ private T RetryPolicy<T>(Func<T> action)
19142002
attempt, maxRetries, ex.Message, delay.TotalSeconds);
19152003
Thread.Sleep(delay);
19162004
}
1917-
}
19182005

19192006
throw new InvalidOperationException("Unexpected error in retry logic."); // This will never be reached
19202007
}
@@ -2008,28 +2095,6 @@ private void ParseOpaqueSecret(V1Secret secretData, string[] allowedKeys)
20082095
}
20092096
}
20102097

2011-
public struct JksSecret
2012-
{
2013-
public string SecretPath;
2014-
public string SecretFieldName;
2015-
public V1Secret Secret;
2016-
public string Password;
2017-
public string PasswordPath;
2018-
public List<string> AllowedKeys;
2019-
public Dictionary<string, byte[]> Inventory;
2020-
}
2021-
2022-
public struct Pkcs12Secret
2023-
{
2024-
public string SecretPath;
2025-
public string SecretFieldName;
2026-
public V1Secret Secret;
2027-
public string Password;
2028-
public string PasswordPath;
2029-
public List<string> AllowedKeys;
2030-
public Dictionary<string, byte[]> Inventory;
2031-
}
2032-
20332098
public JksSecret GetJksSecret(string secretName, string namespaceName, string password = null,
20342099
string passwordPath = null, List<string> allowedKeys = null)
20352100
{
@@ -2344,6 +2409,28 @@ public V1Secret CreateOrUpdatePkcs12Secret(Pkcs12Secret k8SData, string kubeSecr
23442409
return Client.CoreV1.ReplaceNamespacedSecret(s1, kubeSecretName, kubeNamespace);
23452410
}
23462411

2412+
public struct JksSecret
2413+
{
2414+
public string SecretPath;
2415+
public string SecretFieldName;
2416+
public V1Secret Secret;
2417+
public string Password;
2418+
public string PasswordPath;
2419+
public List<string> AllowedKeys;
2420+
public Dictionary<string, byte[]> Inventory;
2421+
}
2422+
2423+
public struct Pkcs12Secret
2424+
{
2425+
public string SecretPath;
2426+
public string SecretFieldName;
2427+
public V1Secret Secret;
2428+
public string Password;
2429+
public string PasswordPath;
2430+
public List<string> AllowedKeys;
2431+
public Dictionary<string, byte[]> Inventory;
2432+
}
2433+
23472434
public struct CsrObject
23482435
{
23492436
public string Csr;

0 commit comments

Comments
 (0)