diff --git a/CHANGELOG.md b/CHANGELOG.md index 3627fef..46bc5f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ +2.1.1 +* Fix issue identifying whether inventoried certificate contains a private key. +* Renewing Unbound Certificates Causes The Job To Fail + 2.1.0 * Added new Custom Field, Link To Issuer, to identify if Managment-Add jobs should attempt to link an added certificate to its issuing certificate if it resides in Netscaler. - + 2.0.1 * Fixed Issue with Inventory when VServer Cannot be retreived by Citrix API diff --git a/CitrixAdcOrchestratorJobExtension/CitrixAdcStore.cs b/CitrixAdcOrchestratorJobExtension/CitrixAdcStore.cs index 9bfc12b..be56c46 100644 --- a/CitrixAdcOrchestratorJobExtension/CitrixAdcStore.cs +++ b/CitrixAdcOrchestratorJobExtension/CitrixAdcStore.cs @@ -669,6 +669,7 @@ public X509Certificate2 GetX509Certificate(string fileLocation, out bool hasKey) { Logger.LogDebug("Entering GetX509Certificate(string fileLocation, out bool hasKey)"); systemfile f; + string[] privateKeyDelims = new string[3] { "-----BEGIN RSA PRIVATE KEY-----", "-----BEGIN PRIVATE KEY-----", "-----BEGIN ENCRYPTED PRIVATE KEY-----" }; string certString = null; string keyString = null; @@ -701,18 +702,24 @@ public X509Certificate2 GetX509Certificate(string fileLocation, out bool hasKey) var fileString = Encoding.Default.GetString(b); // Check if private key is included with certificate - var containsKey = fileString.IndexOf("-----BEGIN RSA PRIVATE KEY-----", StringComparison.Ordinal) >= 0; + var privateKeyIdx = -1; + foreach(string privateKeyDelim in privateKeyDelims) + { + if (fileString.IndexOf(privateKeyDelim, StringComparison.Ordinal) >= 0) + privateKeyIdx = Array.IndexOf(privateKeyDelims, privateKeyDelim); + } + var containsCert = fileString.IndexOf("-----BEGIN CERTIFICATE-----", StringComparison.Ordinal) >= 0; - Logger.LogTrace($"containsKey: {containsKey} containsCert: {containsCert}"); + Logger.LogTrace($"containsKey: {privateKeyIdx > -1} containsCert: {containsCert}"); - if (containsCert && containsKey) + if (containsCert && privateKeyIdx > -1) { Logger.LogTrace($"File contains certificate and key: {fileLocation}"); - var keyStart = fileString.IndexOf("-----BEGIN RSA PRIVATE KEY-----", StringComparison.Ordinal); - var keyEnd = fileString.IndexOf("-----END RSA PRIVATE KEY-----", StringComparison.Ordinal) + - "-----END RSA PRIVATE KEY-----".Length; + var keyStart = fileString.IndexOf(privateKeyDelims[privateKeyIdx], StringComparison.Ordinal); + var keyEnd = fileString.IndexOf(privateKeyDelims[privateKeyIdx].Replace("BEGIN","END"), StringComparison.Ordinal) + + privateKeyDelims[privateKeyIdx].Replace("BEGIN", "END").Length; // check if need to remove new line keyString = fileString.Substring(keyStart, keyEnd - keyStart); @@ -725,7 +732,11 @@ public X509Certificate2 GetX509Certificate(string fileLocation, out bool hasKey) // check .key file try { - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileLocation); + var fileNameWithoutExtension = fileLocation; + if (fileLocation.EndsWith(".crt",StringComparison.CurrentCultureIgnoreCase) || fileLocation.EndsWith(".pem", StringComparison.CurrentCultureIgnoreCase) || fileLocation.EndsWith(".pfx", StringComparison.CurrentCultureIgnoreCase) || fileLocation.EndsWith(".cert", StringComparison.CurrentCultureIgnoreCase) || fileLocation.EndsWith(".der", StringComparison.CurrentCultureIgnoreCase)) + { + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileLocation); + } var keyFile = GetSystemFile(fileNameWithoutExtension + ".key"); keyString = Encoding.UTF8.GetString(Convert.FromBase64String(keyFile.filecontent)); } @@ -754,7 +765,7 @@ public X509Certificate2 GetX509Certificate(string fileLocation, out bool hasKey) return null; } - hasKey = EvaluatePrivateKey(x, keyString); + hasKey = !string.IsNullOrEmpty(keyString); } catch (Exception e) { diff --git a/CitrixAdcOrchestratorJobExtension/Management.cs b/CitrixAdcOrchestratorJobExtension/Management.cs index f0f9d14..247bafb 100644 --- a/CitrixAdcOrchestratorJobExtension/Management.cs +++ b/CitrixAdcOrchestratorJobExtension/Management.cs @@ -102,7 +102,8 @@ private void AddBindCert(CitrixAdcStore store, ManagementJobCertificate cert, st _logger.LogDebug("Updating cert bindings"); //update cert bindings - store.UpdateBindings(keyPairName, virtualServerName, sniCert); + if (virtualServerName != null) + store.UpdateBindings(keyPairName, virtualServerName, sniCert); if (linkToIssuer) { @@ -176,41 +177,47 @@ private JobResult ProcessJob(CitrixAdcStore store, ManagementJobConfiguration jo //2. For Each check the binding /config/sslcertkey_binding store.GetBinding(strKey) foreach (var kp in keyPairList) { - var binding = store.GetBinding(kp.certkey); - _logger.LogTrace($"binding: {JsonConvert.SerializeObject(binding)}"); - if (binding != null) + //4. Open the file and check the thumbprint + var x = store.GetX509Certificate( + kp.cert.Substring(kp.cert.LastIndexOf("/", StringComparison.Ordinal) + 1), + out _); + + //5. If the Thumbprint matches the cert renewed from KF then PerformAdd With Overwrite + if (x?.Thumbprint == _thumbprint) { - //4. Open the file and check the thumbprint - var x = store.GetX509Certificate( - kp.cert.Substring(kp.cert.LastIndexOf("/", StringComparison.Ordinal) + 1), - out _); - //5. If the Thumbprint matches the cert renewed from KF then PerformAdd With Overwrite - if (x?.Thumbprint == _thumbprint) + _logger.LogTrace($"Thumbprint Match: {_thumbprint}"); + var binding = store.GetBinding(kp.certkey); + _logger.LogTrace($"binding: {JsonConvert.SerializeObject(binding)}"); + if (binding != null) { - _logger.LogTrace($"Thumbprint Match: {_thumbprint}"); - if (binding.sslcertkey_sslvserver_binding == null) + if (binding?.sslcertkey_sslvserver_binding != null) { - _logger.LogTrace( - $"Starting PerformAdd Binding kp.certkey: {kp.certkey}"); - PerformAdd(store, jobConfiguration.JobCertificate, kp.certkey, - virtualServerName, true, sniCert, linkToIssuer); - _logger.LogTrace( - $"Finished PerformAdd kp.certkey: {kp.certkey}"); - } - else - { - foreach (var sBinding in binding.sslcertkey_sslvserver_binding) + foreach (var sBinding in binding?.sslcertkey_sslvserver_binding) { _logger.LogTrace( - $"Starting PerformAdd Binding Name: {sBinding.servername} kp.certkey: {kp.certkey}"); - PerformAdd(store, jobConfiguration.JobCertificate, kp.certkey, - sBinding.servername, true, sniCert, linkToIssuer); + $"Starting PerformAdd Binding Name: {sBinding?.servername} kp.certkey: {kp?.certkey}"); + PerformAdd(store, jobConfiguration.JobCertificate, kp?.certkey, + sBinding?.servername, true, sniCert, linkToIssuer); _logger.LogTrace( - $"Finished PerformAdd Binding Name: {sBinding.servername} kp.certkey: {kp.certkey}"); + $"Finished PerformAdd Binding Name: {sBinding?.servername} kp.certkey: {kp?.certkey}"); } } + else + { + _logger.LogTrace($"Renewing cert with no binding Information"); + PerformAdd(store, jobConfiguration.JobCertificate, kp?.certkey, null, true, null, linkToIssuer); + _logger.LogTrace($"Finished Renewing cert with no binding Information"); + } + } + else + { + _logger.LogTrace($"Renewing cert with no binding Information"); + PerformAdd(store, jobConfiguration.JobCertificate, kp?.certkey,null, true, null,linkToIssuer); + _logger.LogTrace($"Finished Renewing cert with no binding Information"); } + } + } } } diff --git a/README.md b/README.md index 6e8f5f0..60eca85 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ The Keyfactor Universal Orchestrator may be installed on either Windows or Linux |Supports Management Remove|✓ |✓ | |Supports Create Store| | | |Supports Discovery| | | -|Supports Renrollment| | | +|Supports Reenrollment| | | |Supports Inventory|✓ |✓ | @@ -248,3 +248,6 @@ Case Number|Case Name|Enrollment Params|Expected Results|Passed|Screenshot +When creating cert store type manually, that store property names and entry parameter names are case sensitive + +