77
88using System ;
99using System . Collections . Generic ;
10- using System . Configuration ;
1110using System . IO ;
1211using System . Linq ;
1312using 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