From 0101f528f80738e1b2eb48411e3192ae59e48c99 Mon Sep 17 00:00:00 2001 From: David Galey Date: Fri, 30 Jun 2023 10:58:32 -0400 Subject: [PATCH 01/16] add comments --- .../CertCentralCAConnector.cs | 104 +++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index 2881854..dabc244 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -41,6 +41,17 @@ public void Initialize(ICAConnectorConfigProvider configProvider, ICertificateDa _config = JsonConvert.DeserializeObject(rawConfig); } + /// + /// Enroll for a certificate + /// + /// The CSR for the certificate request + /// The subject string + /// The list of SANs + /// Collection of product information and options. Includes both product-level config options as well as custom enrollment fields. + /// The format of the request + /// The type of enrollment (new, renew, reissue) + /// The result of the enrollment + /// public async Task Enroll(string csr, string subject, Dictionary san, EnrollmentProductInfo productInfo, RequestFormat requestFormat, EnrollmentType enrollmentType) { _logger.MethodEntry(LogLevel.Trace); @@ -206,6 +217,8 @@ public async Task Enroll(string csr, string subject, Dictionar var renewWindow = (productInfo.ProductParameters.ContainsKey(CertCentralConstants.Config.RENEWAL_WINDOW)) ? int.Parse(productInfo.ProductParameters[CertCentralConstants.Config.RENEWAL_WINDOW]) : 90; string priorCertSnString = null; string priorCertReqID = null; + + // Current gateway core leaves it up to the integration to determine if it is a renewal or a reissue if (enrollmentType == EnrollmentType.RenewOrReissue) { //// Determine if we're going to do a renew or a reissue. @@ -272,6 +285,10 @@ public async Task Enroll(string csr, string subject, Dictionar } } + /// + /// Get the annotations for the CA Connector-level configuration fields + /// + /// public Dictionary GetCAConnectorAnnotations() { return new Dictionary() @@ -303,6 +320,10 @@ public Dictionary GetCAConnectorAnnotations() }; } + /// + /// Get the list of valid product IDs from DigiCert + /// + /// public List GetProductIds() { try @@ -329,6 +350,12 @@ public List GetProductIds() } } + + /// + /// Retrieve a single record from DigiCert + /// + /// The gateway request ID of the record to retrieve, in the format 'orderID-certID' + /// public async Task GetSingleRecord(string caRequestID) { _logger.MethodEntry(LogLevel.Trace); @@ -372,6 +399,10 @@ public async Task GetSingleRecord(string caRequestID) }; } + /// + /// Get the annotations for the product-level configuration fields + /// + /// public Dictionary GetTemplateParameterAnnotations() { return new Dictionary() @@ -403,6 +434,11 @@ public Dictionary GetTemplateParameterAnnotations() }; } + /// + /// Verify connectivity with the DigiCert web service + /// + /// + /// public async Task Ping() { _logger.MethodEntry(LogLevel.Trace); @@ -428,6 +464,15 @@ public async Task Ping() _logger.MethodExit(LogLevel.Trace); } + /// + /// Revoke either a single certificate or an order, depending on your configuration settings + /// + /// + /// + /// + /// + /// + /// public async Task Revoke(string caRequestID, string hexSerialNumber, uint revocationReason) { _logger.MethodEntry(LogLevel.Trace); @@ -477,6 +522,15 @@ public async Task Revoke(string caRequestID, string hexSerialNumber, uint r return (int)RequestDisposition.REVOKED; } + /// + /// Perform an inventory of DigiCert certs + /// + /// Buffer to return retrieved certs in + /// DateTime of the last sync performed + /// If true, return all certs from DigiCert. If false, only return certs that are new or changed status since the lastSync time. + /// + /// + /// public async Task Synchronize(BlockingCollection blockingBuffer, DateTime? lastSync, bool fullSync, CancellationToken cancelToken) { _logger.MethodEntry(LogLevel.Trace); @@ -582,6 +636,11 @@ public async Task Synchronize(BlockingCollection blockin _logger.MethodExit(LogLevel.Trace); } + /// + /// Validate CA Connection-level configuration fields + /// + /// + /// public async Task ValidateCAConnectionInfo(Dictionary connectionInfo) { _logger.MethodEntry(LogLevel.Trace); @@ -631,6 +690,13 @@ private void ThrowValidationException(List errors) throw new ArgumentException(string.Join("\n", errors)); } + /// + /// Validate product-level configuration fields + /// + /// + /// + /// + /// public async Task ValidateProductInfo(EnrollmentProductInfo productInfo, Dictionary connectionInfo) { _logger.MethodEntry(LogLevel.Trace); @@ -821,6 +887,12 @@ private async Task ExtractEnrollmentResult(CertCentralClient c }; } + /// + /// Convert DigiCert status string into a RequestDisposition code + /// + /// + /// + /// private int GetCertificateStatusFromCA(string status, int orderId) { switch (status) @@ -851,6 +923,13 @@ private int GetCertificateStatusFromCA(string status, int orderId) } } + /// + /// Get the list of reissues for a given order + /// + /// + /// + /// + /// private List GetReissues(CertCentralClient digiClient, int orderId) { _logger.LogTrace($"Getting Reissues for order {orderId}"); @@ -879,6 +958,13 @@ private List GetReissues(CertCentralClient digiClient, int orderId) return reissueCerts; } + /// + /// Get the list of duplicate certs for a given order + /// + /// + /// + /// + /// private List GetDuplicates(CertCentralClient digiClient, int orderId) { _logger.LogTrace($"Getting Duplicates for order {orderId}"); @@ -977,6 +1063,11 @@ private async Task Reissue(CertCentralClient client, Enrollmen return await ExtractEnrollmentResult(client, client.ReissueCertificate(reissueRequest), commonName); } + /// + /// Verify that the given product ID is valid + /// + /// + /// private void CheckProductExistence(string productId) { // Check that the product type is still valid. @@ -1023,7 +1114,11 @@ string FormatSyncDate(DateTime? syncTime) return date + "+" + time; } - + /// + /// Get all of the certs for a given order, including reissues and duplicates, in CAConnectorCertificate form + /// + /// + /// private List GetAllConnectorCertsForOrder(string caRequestID) { _logger.MethodEntry(LogLevel.Trace); @@ -1071,6 +1166,13 @@ private List GetAllConnectorCertsForOrder(string caReque } return certList; } + + /// + /// Get all of the certs for a given order, including reissues and duplicates, in StatusOrder form + /// + /// + /// + /// private List GetAllCertsForOrder(int orderId) { CertCentralClient client = CertCentralClientUtilities.BuildCertCentralClient(_config); From 347b7104cc5d5e7c93f8ba2cf5d732e75e945608 Mon Sep 17 00:00:00 2001 From: David Galey Date: Fri, 30 Jun 2023 12:39:22 -0400 Subject: [PATCH 02/16] add release_dir to manifest --- integration-manifest.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integration-manifest.json b/integration-manifest.json index f9c7984..e0ca91a 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -7,5 +7,6 @@ "link_github": false, "update_catalog": false, "description": "DigiCert CertCentral plugin for the AnyCA Gateway framework", - "gateway_framework": "1.0.0" + "gateway_framework": "1.0.0", + "release_dir": "digicert-certcentral-anycagateway/bin/Release/net6.0" } From f2b8ea96fd8eaa214eb4aa671853ed44f2908b9f Mon Sep 17 00:00:00 2001 From: David Galey Date: Fri, 30 Jun 2023 12:54:21 -0400 Subject: [PATCH 03/16] package reference --- Keyfactor.AnyGateway.ICAConnector.dll | Bin 0 -> 15360 bytes .../digicert-certcentral-anycagateway.csproj | 7 ++++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Keyfactor.AnyGateway.ICAConnector.dll diff --git a/Keyfactor.AnyGateway.ICAConnector.dll b/Keyfactor.AnyGateway.ICAConnector.dll new file mode 100644 index 0000000000000000000000000000000000000000..aee346c9eaa0a4332adc1a8181fc18a2fa0bd519 GIT binary patch literal 15360 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 - + + + ..\Keyfactor.AnyGateway.ICAConnector.dll + + + From 382cf67d394ec18ba819cde8e4c5e902020d16c0 Mon Sep 17 00:00:00 2001 From: David Galey Date: Fri, 30 Jun 2023 12:57:08 -0400 Subject: [PATCH 04/16] package reference --- Keyfactor.AnyGateway.ICAConnector.dll | Bin 0 -> 15360 bytes .../digicert-certcentral-anycagateway.csproj | 7 ++++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Keyfactor.AnyGateway.ICAConnector.dll diff --git a/Keyfactor.AnyGateway.ICAConnector.dll b/Keyfactor.AnyGateway.ICAConnector.dll new file mode 100644 index 0000000000000000000000000000000000000000..aee346c9eaa0a4332adc1a8181fc18a2fa0bd519 GIT binary patch literal 15360 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 - + + + ..\Keyfactor.AnyGateway.ICAConnector.dll + + + From c94f7d938b4e09ffb6cb37861ed627be0c4f21dd Mon Sep 17 00:00:00 2001 From: David Galey Date: Tue, 11 Jul 2023 10:42:43 -0400 Subject: [PATCH 05/16] Change status codes to EndEntityStatus codes --- .../CertCentralCAConnector.cs | 82 +++++++++++-------- .../digicert-certcentral-anycagateway.csproj | 11 +-- 2 files changed, 49 insertions(+), 44 deletions(-) diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index dabc244..e691694 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -4,6 +4,7 @@ using Keyfactor.Extensions.CAGateway.DigiCert.Client; using Keyfactor.Extensions.CAGateway.DigiCert.Models; using Keyfactor.Logging; +using Keyfactor.PKI.Enums; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -375,7 +376,7 @@ public async Task GetSingleRecord(string caRequestID) string certificate = null; int status = GetCertificateStatusFromCA(certToCheck.status, orderId); - if (status == (int)RequestDisposition.ISSUED || status == (int)RequestDisposition.REVOKED || status == (int)RequestDisposition.UNKNOWN) + if (status == (int)EndEntityStatus.GENERATED || status == (int)EndEntityStatus.REVOKED) { // We have a status where there may be a cert to download, try to download it CertificateChainResponse certificateChainResponse = client.GetCertificateChain(new CertificateChainRequest(certId)); @@ -519,7 +520,7 @@ public async Task Revoke(string caRequestID, string hexSerialNumber, uint r _logger.LogError(errMsg); throw new Exception(errMsg); } - return (int)RequestDisposition.REVOKED; + return (int)EndEntityStatus.REVOKED; } /// @@ -768,7 +769,7 @@ private async Task NewCertificate(CertCentralClient client, Or /// private async Task ExtractEnrollmentResult(CertCentralClient client, OrderResponse orderResponse, string commonName) { - int status = (int)RequestDisposition.UNKNOWN; + int status = 0; string statusMessage = null; string certificate = null; string caRequestID = null; @@ -777,7 +778,7 @@ private async Task ExtractEnrollmentResult(CertCentralClient c { _logger.LogError($"Error from CertCentral client: {orderResponse.Errors.First().message}"); - status = (int)RequestDisposition.FAILED; + status = (int)EndEntityStatus.FAILED; statusMessage = orderResponse.Errors[0].message; } else if (orderResponse.Status == CertCentralBaseResponse.StatusType.SUCCESS) @@ -837,12 +838,12 @@ private async Task ExtractEnrollmentResult(CertCentralClient c caRequestID = orderResponse.OrderId.ToString(); if (updateStatusResponse.Errors.Any(x => x.code == "access_denied|invalid_approver")) { - status = (int)RequestDisposition.EXTERNAL_VALIDATION; + status = (int)EndEntityStatus.EXTERNALVALIDATION; statusMessage = errors; } else { - status = (int)RequestDisposition.FAILED; + status = (int)EndEntityStatus.FAILED; statusMessage = $"Approval of order '{orderResponse.OrderId}' failed. Check the gateway logs for more details."; } } @@ -864,7 +865,7 @@ private async Task ExtractEnrollmentResult(CertCentralClient c catch (Exception getRecordEx) { _logger.LogWarning($"Unable to retrieve certificate {order.certificate.id} for order {order.id}: {getRecordEx.Message}"); - status = (int)RequestDisposition.UNKNOWN; + status = (int)EndEntityStatus.INPROCESS; statusMessage = $"Post-submission approval of order {order.id} was successful, but pickup failed"; } } @@ -873,8 +874,7 @@ private async Task ExtractEnrollmentResult(CertCentralClient c else { _logger.LogWarning("The request disposition is for this enrollment could not be determined."); - status = (int)RequestDisposition.UNKNOWN; - statusMessage = "The request disposition could not be determined."; + throw new Exception($"The request disposition is for this enrollment could not be determined."); } } } @@ -888,7 +888,7 @@ private async Task ExtractEnrollmentResult(CertCentralClient c } /// - /// Convert DigiCert status string into a RequestDisposition code + /// Convert DigiCert status string into a EndEntityStatus code /// /// /// @@ -900,26 +900,29 @@ private int GetCertificateStatusFromCA(string status, int orderId) case "issued": case "approved": case "expired": - return (int)RequestDisposition.ISSUED; + return (int)EndEntityStatus.GENERATED; case "processing": case "reissue_pending": case "pending": // Pending from DigiCert means it will be issued after validation - return (int)RequestDisposition.EXTERNAL_VALIDATION; + case "waiting_pickup": + return (int)EndEntityStatus.EXTERNALVALIDATION; case "denied": - return (int)RequestDisposition.DENIED; + case "rejected": + case "canceled": + return (int)EndEntityStatus.FAILED; case "revoked": - return (int)RequestDisposition.REVOKED; + return (int)EndEntityStatus.REVOKED; case "needs_approval": // This indicates that the request has to be approved through DigiCert, which is a misconfiguration _logger.LogWarning($"Order {orderId} needs to be approved in the DigiCert portal prior to issuance"); - return (int)RequestDisposition.EXTERNAL_VALIDATION; + return (int)EndEntityStatus.EXTERNALVALIDATION; default: - _logger.LogWarning($"Order {orderId} has unexpected status {status}"); - return (int)RequestDisposition.UNKNOWN; + _logger.LogError($"Order {orderId} has unexpected status {status}"); + throw new Exception($"Order {orderId} has unknown status {status}"); } } @@ -1138,31 +1141,38 @@ private List GetAllConnectorCertsForOrder(string caReque foreach (var cert in orderCerts) { - string certificate = null; - string caReqId = cert.order_id + "-" + cert.certificate_id; - int status = GetCertificateStatusFromCA(cert.status, orderId); - if (status == (int)RequestDisposition.ISSUED || status == (int)RequestDisposition.REVOKED || status == (int)RequestDisposition.UNKNOWN) + try { - // We have a status where there may be a cert to download, try to download it - CertificateChainResponse certificateChainResponse = client.GetCertificateChain(new CertificateChainRequest(certId)); - if (certificateChainResponse.Status == CertCentralBaseResponse.StatusType.SUCCESS) + string certificate = null; + string caReqId = cert.order_id + "-" + cert.certificate_id; + int status = GetCertificateStatusFromCA(cert.status, orderId); + if (status == (int)EndEntityStatus.GENERATED || status == (int)EndEntityStatus.REVOKED) { - certificate = certificateChainResponse.Intermediates[0].PEM; + // We have a status where there may be a cert to download, try to download it + CertificateChainResponse certificateChainResponse = client.GetCertificateChain(new CertificateChainRequest(certId)); + if (certificateChainResponse.Status == CertCentralBaseResponse.StatusType.SUCCESS) + { + certificate = certificateChainResponse.Intermediates[0].PEM; + } + else + { + throw new Exception($"Unexpected error downloading certificate {certId} for order {orderId}: {certificateChainResponse.Errors.FirstOrDefault()?.message}"); + } } - else + var connCert = new CAConnectorCertificate { - _logger.LogWarning($"Unexpected error downloading certificate {certId} for order {orderId}: {certificateChainResponse.Errors.FirstOrDefault()?.message}"); - } + CARequestID = caReqId, + Certificate = certificate, + Status = status, + ProductID = orderResponse.product.name_id, + RevocationDate = GetRevocationDate(orderResponse) + }; + certList.Add(connCert); } - var connCert = new CAConnectorCertificate + catch (Exception ex) { - CARequestID = caReqId, - Certificate = certificate, - Status = status, - ProductID = orderResponse.product.name_id, - RevocationDate = GetRevocationDate(orderResponse) - }; - certList.Add(connCert); + _logger.LogWarning($"Error processing cert {cert.order_id}-{cert.certificate_id}: {ex.Message}. Skipping record."); + } } return certList; } diff --git a/digicert-certcentral-anycagateway/digicert-certcentral-anycagateway.csproj b/digicert-certcentral-anycagateway/digicert-certcentral-anycagateway.csproj index 7f095c1..3dd2a72 100644 --- a/digicert-certcentral-anycagateway/digicert-certcentral-anycagateway.csproj +++ b/digicert-certcentral-anycagateway/digicert-certcentral-anycagateway.csproj @@ -9,16 +9,11 @@ - + + - + - - - ..\Keyfactor.AnyGateway.ICAConnector.dll - - - From 813a0a819c76e9debc26adb4270bae2cfb8e1fdf Mon Sep 17 00:00:00 2001 From: David Galey Date: Tue, 11 Jul 2023 13:02:25 -0400 Subject: [PATCH 06/16] If digicert returns multiple identical certs (same order/cert ID pair), only return one of them --- .../CertCentralCAConnector.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index e691694..1d4543b 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -936,6 +936,7 @@ private int GetCertificateStatusFromCA(string status, int orderId) private List GetReissues(CertCentralClient digiClient, int orderId) { _logger.LogTrace($"Getting Reissues for order {orderId}"); + List reqIds = new List(); List reissueCerts = new List(); ListReissueResponse reissueResponse = digiClient.ListReissues(new ListReissueRequest(orderId)); if (reissueResponse.Status == CertCentralBaseResponse.StatusType.ERROR) @@ -1222,7 +1223,18 @@ private List GetAllCertsForOrder(int orderId) { orderCerts.AddRange(dupeCerts); } - return orderCerts; + List retCerts = new List(); + List reqIds = new List(); + foreach (var cert in orderCerts) + { + string req = $"{cert.order_id}-{cert.certificate_id}"; + if (!reqIds.Contains(req)) + { + reqIds.Add(req); + retCerts.Add(cert); + } + } + return retCerts; } } } \ No newline at end of file From 1b3ceb06fe9d395cd9dc1dbc925e174ab5ba9ed3 Mon Sep 17 00:00:00 2001 From: David Galey Date: Wed, 26 Jul 2023 12:06:41 -0400 Subject: [PATCH 07/16] Renew/reissue check added, parameter data types specified --- .../CertCentralCAConnector.cs | 89 +++++++++++++------ 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index 1d4543b..c151331 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -60,7 +60,12 @@ public async Task Enroll(string csr, string subject, Dictionar CertCentralCertType certType = CertCentralCertType.GetAllTypes(_config).FirstOrDefault(x => x.ProductCode.Equals(productInfo.ProductID)); OrderRequest orderRequest = new OrderRequest(certType); - var days = (productInfo.ProductParameters.ContainsKey("LifetimeDays")) ? int.Parse(productInfo.ProductParameters["LifetimeDays"]) : 365; + //var days = (productInfo.ProductParameters.ContainsKey("LifetimeDays") && !st) ? int.Parse(productInfo.ProductParameters["LifetimeDays"]) : 365; + var days = 365; + if (productInfo.ProductParameters.ContainsKey("LifetimeDays") && !string.IsNullOrEmpty(productInfo.ProductParameters["LifetimeDays"])) + { + days = int.Parse(productInfo.ProductParameters["LifetimeDays"]); + } int validityYears = 0; DateTime? customExpirationDate = null; switch (days) @@ -107,7 +112,10 @@ public async Task Enroll(string csr, string subject, Dictionar if (productInfo.ProductParameters.TryGetValue(CertCentralConstants.RequestAttributes.ORGANIZATION_NAME, out string orgName)) { // If org name is provided as a parameter, it overrides whatever is in the CSR - organization = orgName; + if (!string.IsNullOrEmpty(orgName)) + { + organization = orgName; + } } string signatureHash = certType.signatureAlgorithm; @@ -158,8 +166,11 @@ public async Task Enroll(string csr, string subject, Dictionar } // Get CA Cert ID (if present) - string caCertId = (productInfo.ProductParameters.ContainsKey("CACertId")) ? (string)productInfo.ProductParameters["CACertId"] : null; - + string caCertId = null; + if (productInfo.ProductParameters.ContainsKey("CACertId") && !string.IsNullOrEmpty(productInfo.ProductParameters["CACertId"])) + { + caCertId = (string)productInfo.ProductParameters["CACertId"]; + } // Set up request orderRequest.Certificate.CommonName = commonName; orderRequest.Certificate.CSR = csr; @@ -215,7 +226,11 @@ public async Task Enroll(string csr, string subject, Dictionar orderRequest.ValidityYears = validityYears; } - var renewWindow = (productInfo.ProductParameters.ContainsKey(CertCentralConstants.Config.RENEWAL_WINDOW)) ? int.Parse(productInfo.ProductParameters[CertCentralConstants.Config.RENEWAL_WINDOW]) : 90; + var renewWindow = 90; + if (productInfo.ProductParameters.ContainsKey(CertCentralConstants.Config.RENEWAL_WINDOW) && !string.IsNullOrEmpty(productInfo.ProductParameters[CertCentralConstants.Config.RENEWAL_WINDOW])) + { + renewWindow = int.Parse(productInfo.ProductParameters[CertCentralConstants.Config.RENEWAL_WINDOW]); + } string priorCertSnString = null; string priorCertReqID = null; @@ -223,24 +238,34 @@ public async Task Enroll(string csr, string subject, Dictionar if (enrollmentType == EnrollmentType.RenewOrReissue) { //// Determine if we're going to do a renew or a reissue. - //string priorCertSnString = productInfo.ProductParameters["PriorCertSN"]; - //_logger.LogTrace($"Attempting to retrieve the certificate with serial number {priorCertSnString}."); - //byte[] priorCertSn = DataConversion.HexToBytes(priorCertSnString); - //CAConnectorCertificate anyGatewayCertificate = _certificateDataReader.(priorCertSn); - //if (anyGatewayCertificate == null) - //{ - // throw new Exception($"No certificate with serial number '{priorCertSnString}' could be found."); - //} - enrollmentType = EnrollmentType.Renew; + priorCertSnString = productInfo.ProductParameters["PriorCertSN"]; + _logger.LogTrace($"Attempting to retrieve the certificate with serial number {priorCertSnString}."); + var reqId = _certificateDataReader.GetRequestIDBySerialNumber(priorCertSnString).Result; + if (string.IsNullOrEmpty(reqId)) + { + throw new Exception($"No certificate with serial number '{priorCertSnString}' could be found."); + } + var expDate = _certificateDataReader.GetExpirationDateByRequestId(reqId); + var renewCutoff = DateTime.Now.AddDays(renewWindow * -1); + + if (expDate > renewCutoff) + { + _logger.LogTrace($"Certificate with serial number {priorCertSnString} is within renewal window"); + enrollmentType = EnrollmentType.Renew; + } + else + { + _logger.LogTrace($"Certificate with serial number {priorCertSnString} is not within renewal window. Reissuing..."); + enrollmentType = EnrollmentType.Reissue; + } } // Check if the order has more validity in it (multi-year cert). If so, do a reissue instead of a renew if (enrollmentType == EnrollmentType.Renew) { // Get the old cert so we can properly construct the request. - priorCertSnString = productInfo.ProductParameters["PriorCertSN"]; - _logger.LogTrace($"Attempting to retrieve the certificate with serial number {priorCertSnString}."); + _logger.LogTrace($"Checking for additional order validity."); priorCertReqID = await _certificateDataReader.GetRequestIDBySerialNumber(priorCertSnString); if (string.IsNullOrEmpty(priorCertReqID)) { @@ -263,8 +288,13 @@ public async Task Enroll(string csr, string subject, Dictionar if (certOrder.order_valid_till.HasValue && certOrder.order_valid_till.Value.AddDays(renewWindow * -1) > DateTime.UtcNow) { + _logger.LogTrace($"Additional order validity found. Reissuing cert with new expiration."); enrollmentType = EnrollmentType.Reissue; } + else + { + _logger.LogTrace($"No additional order validity found. Renewing certificate."); + } } @@ -298,25 +328,29 @@ public Dictionary GetCAConnectorAnnotations() { Comments = "API Key for connecting to DigiCert", Hidden = true, - DefaultValue = "" + DefaultValue = "", + Type = "String" }, [CertCentralConstants.Config.DIVISION_ID] = new PropertyConfigInfo() { Comments = "Division ID to use for retrieving product details (only if account is configured with per-divison product settings)", Hidden = false, - DefaultValue = "" + DefaultValue = "", + Type = "Number" }, [CertCentralConstants.Config.REGION] = new PropertyConfigInfo() { Comments = "The geographic region that your DigiCert CertCentral account is in. Valid options are US and EU.", Hidden = false, - DefaultValue = "US" + DefaultValue = "US", + Type = "String" }, [CertCentralConstants.Config.REVOKE_CERT] = new PropertyConfigInfo() { Comments = "Default DigiCert behavior on revocation requests is to revoke the entire order. If this value is changed to 'true', revocation requests will instead just revoke the individual certificate.", Hidden = false, - DefaultValue = "false" + DefaultValue = false, + Type = "Boolean" } }; } @@ -342,7 +376,8 @@ public List GetProductIds() throw new Exception("Unable to retrieve product list"); } - return productTypesResponse.Products.Select(x => x.NameId).ToList(); } + return productTypesResponse.Products.Select(x => x.NameId).ToList(); + } catch (Exception ex) { // Swallow exceptions and return an empty string. @@ -412,25 +447,29 @@ public Dictionary GetTemplateParameterAnnotations() { Comments = "OPTIONAL: The number of days of validity to use when requesting certs. If not provided, default is 365.", Hidden = false, - DefaultValue = "365" + DefaultValue = 365, + Type = "Number" }, [CertCentralConstants.Config.CA_CERT_ID] = new PropertyConfigInfo() { Comments = "OPTIONAL: ID of issuing CA to use by DigiCert. If not provided, the default for your account will be used.", Hidden = false, - DefaultValue = "" + DefaultValue = "", + Type = "String" }, [CertCentralConstants.RequestAttributes.ORGANIZATION_NAME] = new PropertyConfigInfo() { Comments = "OPTIONAL: For requests that will not have a subject (such as ACME) you can use this field to provide the organization name. Value supplied here will override any CSR values, so do not include this field if you want the organization from the CSR to be used.", Hidden = false, - DefaultValue = "" + DefaultValue = "", + Type = "String" }, [CertCentralConstants.Config.RENEWAL_WINDOW] = new PropertyConfigInfo() { Comments = "OPTIONAL: The number of days from certificate expiration that the gateway should do a renewal rather than a reissue. If not provided, default is 90.", Hidden = false, - DefaultValue = "90" + DefaultValue = 90, + Type = "Number" } }; } From 4f08099d400b5a4c4781854e3e2410688d598f7f Mon Sep 17 00:00:00 2001 From: David Galey Date: Tue, 22 Aug 2023 10:25:55 -0400 Subject: [PATCH 08/16] Don't throw exceptions when unable to retreive product IDs --- .../CertCentralCAConnector.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index c151331..0d05a09 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -373,7 +373,8 @@ public List GetProductIds() // If we couldn't get the types, return an empty comment. if (productTypesResponse.Status != CertCentralBaseResponse.StatusType.SUCCESS) { - throw new Exception("Unable to retrieve product list"); + _logger.LogError($"Unable to retrieve product list: {productTypesResponse.Errors[0]}"); + return new List(); } return productTypesResponse.Products.Select(x => x.NameId).ToList(); @@ -382,7 +383,7 @@ public List GetProductIds() { // Swallow exceptions and return an empty string. _logger.LogError($"Unable to retrieve product list: {ex.Message}"); - throw; + return new List(); } } @@ -591,6 +592,9 @@ public async Task Synchronize(BlockingCollection blockin if (fullSync) { + long time = DateTime.Now.Ticks; + long starttime = time; + _logger.LogDebug($"SYNC: Starting sync at time {time}"); ListCertificateOrdersResponse ordersResponse = client.ListAllCertificateOrders(); if (ordersResponse.Status == CertCentralBaseResponse.StatusType.ERROR) { @@ -600,6 +604,7 @@ public async Task Synchronize(BlockingCollection blockin } else { + _logger.LogDebug($"SYNC: Found {ordersResponse.orders.Count} records"); foreach (var orderDetails in ordersResponse.orders) { List orderCerts = new List(); @@ -607,7 +612,9 @@ public async Task Synchronize(BlockingCollection blockin { cancelToken.ThrowIfCancellationRequested(); string caReqId = orderDetails.id + "-" + orderDetails.certificate.id; + _logger.LogDebug($"SYNC: Retrieving certs for order id {orderDetails.id}"); orderCerts = GetAllConnectorCertsForOrder(caReqId); + _logger.LogDebug($"SYNC: Retrieved {orderCerts.Count} certs at time {DateTime.Now.Ticks}"); } catch { @@ -623,6 +630,7 @@ public async Task Synchronize(BlockingCollection blockin } } + _logger.LogDebug($"SYNC: Complete after {DateTime.Now.Ticks - starttime} ticks"); } } else From 94a7cb2e2801f52bfeb89372f01652da5ef0f7db Mon Sep 17 00:00:00 2001 From: David Galey Date: Wed, 23 Aug 2023 09:27:46 -0400 Subject: [PATCH 09/16] Prevent duplicate certs from syncing --- .../API/StatusChanges.cs | 3 ++ .../CertCentralCAConnector.cs | 34 +++++++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/digicert-certcentral-anycagateway/API/StatusChanges.cs b/digicert-certcentral-anycagateway/API/StatusChanges.cs index 0b9a2cf..eaced16 100644 --- a/digicert-certcentral-anycagateway/API/StatusChanges.cs +++ b/digicert-certcentral-anycagateway/API/StatusChanges.cs @@ -27,6 +27,9 @@ public class StatusOrder [JsonProperty("status")] public string status { get; set; } + + [JsonIgnore] + public string serialNum { get; set; } } public class StatusChangesResponse : CertCentralBaseResponse diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index 0d05a09..4bf7879 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -1000,7 +1000,8 @@ private List GetReissues(CertCentralClient digiClient, int orderId) { order_id = orderId, certificate_id = reissueCert.id, - status = reissueCert.status + status = reissueCert.status, + serialNum = reissueCert.serial_number }; reissueCerts.Add(reissueStatusOrder); } @@ -1035,7 +1036,8 @@ private List GetDuplicates(CertCentralClient digiClient, int orderI { order_id = orderId, certificate_id = dupeCert.id, - status = dupeCert.status + status = dupeCert.status, + serialNum = dupeCert.serial_number }; dupeCerts.Add(dupeStatusOrder); } @@ -1258,10 +1260,13 @@ private List GetAllCertsForOrder(int orderId) { order_id = orderId, certificate_id = orderResponse.certificate.id, - status = orderStatusString + status = orderStatusString, + serialNum = orderResponse.certificate.serial_number + }; + List orderCerts = new List + { + primary }; - List orderCerts = new List(); - orderCerts.Add(primary); if (reissueCerts?.Count > 0) { orderCerts.AddRange(reissueCerts); @@ -1272,13 +1277,28 @@ private List GetAllCertsForOrder(int orderId) } List retCerts = new List(); List reqIds = new List(); + List serNums = new List(); foreach (var cert in orderCerts) { string req = $"{cert.order_id}-{cert.certificate_id}"; + + // Listing reissues/duplicates can also return the primary certificate. This check insures that only one copy of the primary certificate gets added to the sync list. if (!reqIds.Contains(req)) { - reqIds.Add(req); - retCerts.Add(cert); + // This is actually caused by an issue in the DigiCert API. For some orders (but not all), retrieving the reissued/duplicate certificates on an order + // instead just retrieves multiple copies of the primary certificate on that order. Since the gateway database must have unique certificates + // (serial number column is unique), we work around this by only syncing the primary cert in these cases. Other orders that correctly retrieve the + // reissued/duplicate certificates will pass this check. + if (!serNums.Contains(req)) + { + reqIds.Add(req); + retCerts.Add(cert); + serNums.Add(cert.serialNum); + } + else + { + _logger.LogWarning($"Duplicate certificate serial numbers found. Only one will be synced. Order ID: {cert.order_id}"); + } } } return retCerts; From 4008aee015bd5d3e5c958e654b25e0c715b5ec0d Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Wed, 23 Aug 2023 13:28:28 +0000 Subject: [PATCH 10/16] Update generated README --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 036f8e3..7e18ce1 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,6 @@ DigiCert CertCentral plugin for the AnyCA Gateway framework This repository contains an AnyGateway CA Connector, which is a plugin to the Keyfactor AnyGateway. AnyGateway CA Connectors allow Keyfactor Command to be used for inventory, issuance, and revocation of certificates from a third-party certificate authority. - - ## Support for digicert-certcentral-anycagateway digicert-certcentral-anycagateway is open source and community supported, meaning that there is **no SLA** applicable for these tools. @@ -19,7 +17,6 @@ digicert-certcentral-anycagateway is open source and community supported, meanin ###### To report a problem or suggest a new feature, use the **[Issues](../../issues)** tab. If you want to contribute actual bug fixes or proposed enhancements, use the **[Pull requests](../../pulls)** tab. - --- From ab2e40299bc8a323c0dcd12ddeed961388d134ec Mon Sep 17 00:00:00 2001 From: David Galey Date: Mon, 16 Oct 2023 13:05:01 -0400 Subject: [PATCH 11/16] Error update --- digicert-certcentral-anycagateway/CertCentralCAConnector.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index 4bf7879..c485d67 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -1,5 +1,6 @@ using Keyfactor.AnyGateway.Extensions; using Keyfactor.Common; +using Keyfactor.Common.Exceptions; using Keyfactor.Extensions.CAGateway.DigiCert.API; using Keyfactor.Extensions.CAGateway.DigiCert.Client; using Keyfactor.Extensions.CAGateway.DigiCert.Models; @@ -723,7 +724,7 @@ public async Task ValidateCAConnectionInfo(Dictionary connection if (domains.Status == CertCentralBaseResponse.StatusType.ERROR) { _logger.LogError($"Error from CertCentral client: {domains.Errors[0].message}"); - errors.Add("Error grabbing DigiCert domains"); + errors.Add("Error grabbing DigiCert domains. See log file for details."); } _logger.MethodExit(LogLevel.Trace); // We cannot proceed if there are any errors. @@ -735,7 +736,8 @@ public async Task ValidateCAConnectionInfo(Dictionary connection private void ThrowValidationException(List errors) { - throw new ArgumentException(string.Join("\n", errors)); + string validationMsg = $"Validation errors:\n{string.Join("\n", errors)}"; + throw new KeyfactorException(validationMsg, unchecked((uint)HRESULTs.INVALID_DATA)); } /// From a9d979b042d0733811dbc2f968043be8d0cdb496 Mon Sep 17 00:00:00 2001 From: David Galey Date: Thu, 16 Nov 2023 06:16:23 -0500 Subject: [PATCH 12/16] update package reference and object names --- .../CertCentralCAConnector.cs | 32 +++++++++---------- .../digicert-certcentral-anycagateway.csproj | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index c485d67..fe3c3fc 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -24,7 +24,7 @@ namespace Keyfactor.Extensions.CAGateway.DigiCert { - public class CertCentralCAConnector : ICAConnector + public class CertCentralCAConnector : IAnyCAPlugin { private CertCentralConfig _config; private readonly ILogger _logger; @@ -36,7 +36,7 @@ public CertCentralCAConnector() { _logger = LogHandler.GetClassLogger(); } - public void Initialize(ICAConnectorConfigProvider configProvider, ICertificateDataReader certificateDataReader) + public void Initialize(IAnyCAPluginConfigProvider configProvider, ICertificateDataReader certificateDataReader) { _certificateDataReader = certificateDataReader; string rawConfig = JsonConvert.SerializeObject(configProvider.CAConnectionData); @@ -394,7 +394,7 @@ public List GetProductIds() /// /// The gateway request ID of the record to retrieve, in the format 'orderID-certID' /// - public async Task GetSingleRecord(string caRequestID) + public async Task GetSingleRecord(string caRequestID) { _logger.MethodEntry(LogLevel.Trace); // Split ca request id into order and cert id @@ -427,7 +427,7 @@ public async Task GetSingleRecord(string caRequestID) } } _logger.MethodExit(LogLevel.Trace); - return new CAConnectorCertificate + return new AnyCAPluginCertificate { CARequestID = caRequestID, Certificate = certificate, @@ -573,7 +573,7 @@ public async Task Revoke(string caRequestID, string hexSerialNumber, uint r /// /// /// - public async Task Synchronize(BlockingCollection blockingBuffer, DateTime? lastSync, bool fullSync, CancellationToken cancelToken) + public async Task Synchronize(BlockingCollection blockingBuffer, DateTime? lastSync, bool fullSync, CancellationToken cancelToken) { _logger.MethodEntry(LogLevel.Trace); @@ -582,7 +582,7 @@ public async Task Synchronize(BlockingCollection blockin string lastSyncFormat = FormatSyncDate(lastSync); string todaySyncFormat = FormatSyncDate(utcDate); - List certs = new List(); + List certs = new List(); List certsToSync = new List(); _logger.LogDebug("Attempting to create a CertCentral client"); @@ -608,7 +608,7 @@ public async Task Synchronize(BlockingCollection blockin _logger.LogDebug($"SYNC: Found {ordersResponse.orders.Count} records"); foreach (var orderDetails in ordersResponse.orders) { - List orderCerts = new List(); + List orderCerts = new List(); try { cancelToken.ThrowIfCancellationRequested(); @@ -648,7 +648,7 @@ public async Task Synchronize(BlockingCollection blockin int orderCount = statusChangesResponse.orders.Count; foreach (var order in statusChangesResponse.orders) { - List orderCerts = new List(); + List orderCerts = new List(); try { cancelToken.ThrowIfCancellationRequested(); @@ -737,7 +737,7 @@ public async Task ValidateCAConnectionInfo(Dictionary connection private void ThrowValidationException(List errors) { string validationMsg = $"Validation errors:\n{string.Join("\n", errors)}"; - throw new KeyfactorException(validationMsg, unchecked((uint)HRESULTs.INVALID_DATA)); + throw new AnyCAValidationException(validationMsg); } /// @@ -770,14 +770,14 @@ public async Task ValidateProductInfo(EnrollmentProductInfo productInfo, Diction CertificateTypesResponse productIdResponse = client.GetAllCertificateTypes(); if (productIdResponse.Status != CertCentralBaseResponse.StatusType.SUCCESS) { - throw new Exception($"The product types could not be retrieved from the server. The following errors occurred: {string.Join(" ", productIdResponse.Errors.Select(x => x.message))}"); + throw new AnyCAValidationException($"The product types could not be retrieved from the server. The following errors occurred: {string.Join(" ", productIdResponse.Errors.Select(x => x.message))}"); } // Get product and check if it exists. var product = productIdResponse.Products.FirstOrDefault(x => x.NameId.Equals(productId, StringComparison.InvariantCultureIgnoreCase)); if (product == null) { - throw new Exception($"The product ID '{productId}' does not exist. The following product IDs are valid: {string.Join(", ", productIdResponse.Products.Select(x => x.NameId))}"); + throw new AnyCAValidationException($"The product ID '{productId}' does not exist. The following product IDs are valid: {string.Join(", ", productIdResponse.Products.Select(x => x.NameId))}"); } // Get product ID details. @@ -793,7 +793,7 @@ public async Task ValidateProductInfo(EnrollmentProductInfo productInfo, Diction CertificateTypeDetailsResponse details = client.GetCertificateTypeDetails(detailsRequest); if (details.Errors.Any()) { - throw new Exception($"Validation of '{productId}' failed for the following reasons: {string.Join(" ", details.Errors.Select(x => x.message))}."); + throw new AnyCAValidationException($"Validation of '{productId}' failed for the following reasons: {string.Join(" ", details.Errors.Select(x => x.message))}."); } _logger.MethodExit(LogLevel.Trace); } @@ -906,7 +906,7 @@ private async Task ExtractEnrollmentResult(CertCentralClient c caRequestID = $"{order.id}-{order.certificate.id}"; try { - CAConnectorCertificate connCert = await GetSingleRecord($"{order.id}-{order.certificate.id}"); + AnyCAPluginCertificate connCert = await GetSingleRecord($"{order.id}-{order.certificate.id}"); certificate = connCert.Certificate; status = connCert.Status; statusMessage = $"Post-submission approval of order {order.id} returned success"; @@ -1174,7 +1174,7 @@ string FormatSyncDate(DateTime? syncTime) /// /// /// - private List GetAllConnectorCertsForOrder(string caRequestID) + private List GetAllConnectorCertsForOrder(string caRequestID) { _logger.MethodEntry(LogLevel.Trace); // Split ca request id into order and cert id @@ -1189,7 +1189,7 @@ private List GetAllConnectorCertsForOrder(string caReque var orderCerts = GetAllCertsForOrder(orderId); - List certList = new List(); + List certList = new List(); foreach (var cert in orderCerts) { @@ -1211,7 +1211,7 @@ private List GetAllConnectorCertsForOrder(string caReque throw new Exception($"Unexpected error downloading certificate {certId} for order {orderId}: {certificateChainResponse.Errors.FirstOrDefault()?.message}"); } } - var connCert = new CAConnectorCertificate + var connCert = new AnyCAPluginCertificate { CARequestID = caReqId, Certificate = certificate, diff --git a/digicert-certcentral-anycagateway/digicert-certcentral-anycagateway.csproj b/digicert-certcentral-anycagateway/digicert-certcentral-anycagateway.csproj index 3dd2a72..c96dcd7 100644 --- a/digicert-certcentral-anycagateway/digicert-certcentral-anycagateway.csproj +++ b/digicert-certcentral-anycagateway/digicert-certcentral-anycagateway.csproj @@ -9,7 +9,7 @@ - + From 8c59dae9c8b7d4329ca0855075aff12806cce6cb Mon Sep 17 00:00:00 2001 From: Mikey Henderson Date: Thu, 16 Nov 2023 10:40:15 -0800 Subject: [PATCH 13/16] Remove unused cert-store-merge step --- .github/workflows/keyfactor-integrations-workflow.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/keyfactor-integrations-workflow.yml b/.github/workflows/keyfactor-integrations-workflow.yml index 088548d..b779b53 100644 --- a/.github/workflows/keyfactor-integrations-workflow.yml +++ b/.github/workflows/keyfactor-integrations-workflow.yml @@ -31,10 +31,3 @@ jobs: uses: Keyfactor/actions/.github/workflows/update-catalog.yml@main secrets: token: ${{ secrets.SDK_SYNC_PAT }} - - call-update-store-types-workflow: - needs: call-assign-from-json-workflow - if: needs.call-assign-from-json-workflow.outputs.integration_type == 'orchestrator' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') - uses: Keyfactor/actions/.github/workflows/update-store-types.yml@main - secrets: - token: ${{ secrets.UPDATE_STORE_TYPES }} From bf52f55f979a3df1ddb5c2ec9d5849da60eee641 Mon Sep 17 00:00:00 2001 From: David Galey Date: Tue, 2 Jan 2024 11:07:06 -0500 Subject: [PATCH 14/16] readme update --- readme_source.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme_source.md b/readme_source.md index 101b084..c0d1cd8 100644 --- a/readme_source.md +++ b/readme_source.md @@ -17,7 +17,7 @@ In order to enroll for certificates the Keyfactor Command server must trust the ```json { "extensions": { - "Keyfactor.AnyGateway.Extensions.ICAConnector": { + "Keyfactor.AnyGateway.Extensions.IAnyCAPlugin": { "DigiCertCAConnector": { "assemblypath": "../DigiCertCAGateway.dll", "TypeFullName": "Keyfactor.Extensions.CAGateway.DigiCert.CertCentralCAConnector" From 98ad09066251f2a495411d0cfbdf778eeffc1196 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Tue, 2 Jan 2024 16:07:22 +0000 Subject: [PATCH 15/16] Update generated README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7e18ce1..97dffe9 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This repository contains an AnyGateway CA Connector, which is a plugin to the Ke ## Support for digicert-certcentral-anycagateway -digicert-certcentral-anycagateway is open source and community supported, meaning that there is **no SLA** applicable for these tools. +digicert-certcentral-anycagateway is open source and community supported, meaning that there is no support guaranteed from Keyfactor Support for these tools. ###### To report a problem or suggest a new feature, use the **[Issues](../../issues)** tab. If you want to contribute actual bug fixes or proposed enhancements, use the **[Pull requests](../../pulls)** tab. @@ -52,7 +52,7 @@ In order to enroll for certificates the Keyfactor Command server must trust the ```json { "extensions": { - "Keyfactor.AnyGateway.Extensions.ICAConnector": { + "Keyfactor.AnyGateway.Extensions.IAnyCAPlugin": { "DigiCertCAConnector": { "assemblypath": "../DigiCertCAGateway.dll", "TypeFullName": "Keyfactor.Extensions.CAGateway.DigiCert.CertCentralCAConnector" From 768ab96688a5689c60a7ef46bbed5be37065f7a0 Mon Sep 17 00:00:00 2001 From: David Galey Date: Tue, 2 Jan 2024 15:33:58 -0500 Subject: [PATCH 16/16] fix unit conversion --- .../CertCentralCAConnector.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index fe3c3fc..3f8a512 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -786,8 +786,14 @@ public async Task ValidateProductInfo(EnrollmentProductInfo productInfo, Diction detailsRequest.ContainerId = null; if (connectionInfo.ContainsKey(CertCentralConstants.Config.DIVISION_ID)) { - int.TryParse((string)connectionInfo[CertCentralConstants.Config.DIVISION_ID], out int divId); - detailsRequest.ContainerId = divId; + if (int.TryParse($"{connectionInfo[CertCentralConstants.Config.DIVISION_ID]}", out int divId)) + { + detailsRequest.ContainerId = divId; + } + else + { + throw new AnyCAValidationException($"Unable to parse division ID '{connectionInfo[CertCentralConstants.Config.DIVISION_ID]}'. Check that this is a valid division ID."); + } } CertificateTypeDetailsResponse details = client.GetCertificateTypeDetails(detailsRequest);