diff --git a/digicert-certcentral-anycagateway/API/ListCertificateOrders.cs b/digicert-certcentral-anycagateway/API/ListCertificateOrders.cs index 3ca84cb..3a5dafe 100644 --- a/digicert-certcentral-anycagateway/API/ListCertificateOrders.cs +++ b/digicert-certcentral-anycagateway/API/ListCertificateOrders.cs @@ -12,12 +12,13 @@ namespace Keyfactor.Extensions.CAGateway.DigiCert.API { public class ListCertificateOrdersRequest : CertCentralBaseRequest { - public ListCertificateOrdersRequest() + public ListCertificateOrdersRequest(bool ignoreExpired = false) { this.Resource = "services/v2/order/certificate"; this.Method = "GET"; this.limit = 1000; this.offset = 0; + this.ignoreExpired = ignoreExpired; } [JsonProperty("limit")] @@ -26,6 +27,9 @@ public ListCertificateOrdersRequest() [JsonProperty("offset")] public int offset { get; set; } + public bool ignoreExpired { get; set; } + public int expiredWindow { get; set; } = 0; + public new string BuildParameters() { StringBuilder sbParamters = new StringBuilder(); @@ -33,6 +37,12 @@ public ListCertificateOrdersRequest() sbParamters.Append("limit=").Append(this.limit.ToString()); sbParamters.Append("&offset=").Append(HttpUtility.UrlEncode(this.offset.ToString())); + if (ignoreExpired) + { + DateTime cutoffDate = DateTime.Today.AddDays(-1 - expiredWindow); + sbParamters.Append("&filters[valid_till]=>").Append(cutoffDate.ToString("yyyy-MM-dd")); + } + return sbParamters.ToString(); } } diff --git a/digicert-certcentral-anycagateway/API/OrderCertificate.cs b/digicert-certcentral-anycagateway/API/OrderCertificate.cs index 16b57d2..0bed442 100644 --- a/digicert-certcentral-anycagateway/API/OrderCertificate.cs +++ b/digicert-certcentral-anycagateway/API/OrderCertificate.cs @@ -12,7 +12,7 @@ namespace Keyfactor.Extensions.CAGateway.DigiCert.API { - public class OrderRequest : CertCentralBaseRequest + public class OrderRequest : CertCentralBaseRequest { public OrderRequest(CertCentralCertType certType) { @@ -57,6 +57,9 @@ public OrderRequest(CertCentralCertType certType) [JsonProperty("custom_fields")] public List CustomFields { get; set; } + [JsonProperty("skip_approval")] + public bool SkipApproval { get; set; } + public void SetOrganization(int? organizationId) { if (organizationId.HasValue) diff --git a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs index 6e56096..6a0c211 100644 --- a/digicert-certcentral-anycagateway/CertCentralCAConnector.cs +++ b/digicert-certcentral-anycagateway/CertCentralCAConnector.cs @@ -301,6 +301,8 @@ public async Task Enroll(string csr, string subject, Dictionar _logger.LogTrace("Making request to Enroll"); + orderRequest.SkipApproval = true; + switch (enrollmentType) { case EnrollmentType.New: @@ -426,7 +428,14 @@ public async Task GetSingleRecord(string caRequestID) CertificateChainResponse certificateChainResponse = client.GetCertificateChain(new CertificateChainRequest(certId)); if (certificateChainResponse.Status == CertCentralBaseResponse.StatusType.SUCCESS) { - certificate = certificateChainResponse.Intermediates[0].PEM; + if (certificateChainResponse.Intermediates.Count > 0) + { + certificate = certificateChainResponse.Intermediates[0].PEM; + } + else + { + throw new Exception($"No PEM certificate returned for certificate {certId} in order {orderId}. This could be due to a certificate that provisioned via an alternative method, such as a physical token."); + } } else { @@ -553,10 +562,12 @@ public async Task Revoke(string caRequestID, string hexSerialNumber, uint r RevokeCertificateResponse revokeResponse; if (_config.RevokeCertificateOnly.HasValue && _config.RevokeCertificateOnly.Value) { + _logger.LogInformation($"Attempting to revoke certificate with CA Request Id {caRequestID} and serial number {hexSerialNumber}. RevokeCertificateOnly is true, so revoking single certificate."); revokeResponse = client.RevokeCertificate(new RevokeCertificateRequest(certId) { comments = Conversions.RevokeReasonToString(revocationReason) }); } else { + _logger.LogInformation($"Attempting to revoke certificate with CA Request Id {caRequestID} and serial number {hexSerialNumber}. RevokeCertificateOnly is false, so revoking the entire order."); revokeResponse = client.RevokeCertificate(new RevokeCertificateByOrderRequest(orderResponse.id) { comments = Conversions.RevokeReasonToString(revocationReason) }); } @@ -606,12 +617,27 @@ public async Task Synchronize(BlockingCollection blockin List skippedOrders = new List(); int certCount = 0; + string syncCAstring = string.Join(",", _config.SyncCAFilter ?? new List()); + _logger.LogTrace($"Sync CAs: {syncCAstring}"); + List caList = _config.SyncCAFilter ?? new List(); + caList.ForEach(c => c.ToUpper()); + + if (fullSync) { + bool ignoreExpired = false; int expiredWindow = 0; + if (_config.FilterExpiredOrders.HasValue && _config.FilterExpiredOrders.Value) + { + ignoreExpired = true; + if (_config.SyncExpirationDays.HasValue) + { + expiredWindow = _config.SyncExpirationDays.Value; + } + } long time = DateTime.Now.Ticks; long starttime = time; _logger.LogDebug($"SYNC: Starting sync at time {time}"); - ListCertificateOrdersResponse ordersResponse = client.ListAllCertificateOrders(); + ListCertificateOrdersResponse ordersResponse = client.ListAllCertificateOrders(ignoreExpired, expiredWindow); if (ordersResponse.Status == CertCentralBaseResponse.StatusType.ERROR) { Error error = ordersResponse.Errors[0]; @@ -629,7 +655,11 @@ 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); + orderCerts = GetAllConnectorCertsForOrder(caReqId, caList); + if (orderCerts == null || orderCerts.Count == 0) + { + continue; + } _logger.LogDebug($"SYNC: Retrieved {orderCerts.Count} certs at time {DateTime.Now.Ticks}"); } catch @@ -668,7 +698,11 @@ public async Task Synchronize(BlockingCollection blockin { cancelToken.ThrowIfCancellationRequested(); string caReqId = order.order_id + "-" + order.certificate_id; - orderCerts = GetAllConnectorCertsForOrder(caReqId); + orderCerts = GetAllConnectorCertsForOrder(caReqId, caList); + if (orderCerts == null || orderCerts.Count > 0) + { + continue; + } } catch { @@ -1209,7 +1243,7 @@ string FormatSyncDate(DateTime? syncTime) /// /// /// - private List GetAllConnectorCertsForOrder(string caRequestID) + private List GetAllConnectorCertsForOrder(string caRequestID, List caFilterIds) { _logger.MethodEntry(LogLevel.Trace); // Split ca request id into order and cert id @@ -1222,6 +1256,12 @@ private List GetAllConnectorCertsForOrder(string caReque CertCentralClient client = CertCentralClientUtilities.BuildCertCentralClient(_config); ViewCertificateOrderResponse orderResponse = client.ViewCertificateOrder(new ViewCertificateOrderRequest((uint)orderId)); + if (caFilterIds != null && caFilterIds.Count > 0 && !caFilterIds.Contains(orderResponse.certificate.ca_cert.Id.ToUpper())) + { + _logger.LogTrace($"Found order ID {orderId} that does not match SyncCAFilter. CA ID: {orderResponse.certificate.ca_cert.Id} Skipping..."); + return null; + } + var orderCerts = GetAllCertsForOrder(orderId); List certList = new List(); diff --git a/digicert-certcentral-anycagateway/CertCentralConfig.cs b/digicert-certcentral-anycagateway/CertCentralConfig.cs index 04415e5..61c03fd 100644 --- a/digicert-certcentral-anycagateway/CertCentralConfig.cs +++ b/digicert-certcentral-anycagateway/CertCentralConfig.cs @@ -8,10 +8,18 @@ namespace Keyfactor.Extensions.CAGateway.DigiCert { public class CertCentralConfig { + + public CertCentralConfig() + { + SyncCAFilter = new List(); + } public string APIKey { get; set; } public string Region { get; set; } = "US"; public int? DivisionId { get; set; } public bool? RevokeCertificateOnly { get; set; } public bool Enabled { get; set; } = true; + public List SyncCAFilter { get; set; } + public bool? FilterExpiredOrders { get; set; } + public int? SyncExpirationDays { get; set; } } } diff --git a/digicert-certcentral-anycagateway/Client/CertCentralClient.cs b/digicert-certcentral-anycagateway/Client/CertCentralClient.cs index e02a790..ae1e5b4 100644 --- a/digicert-certcentral-anycagateway/Client/CertCentralClient.cs +++ b/digicert-certcentral-anycagateway/Client/CertCentralClient.cs @@ -473,7 +473,7 @@ public DownloadCertificateByFormatResponse DownloadCertificateByFormat(DownloadC return dlCertificateRequestResponse; } - public ListCertificateOrdersResponse ListAllCertificateOrders() + public ListCertificateOrdersResponse ListAllCertificateOrders(bool ignoreExpired = false, int expiredWindow = 0) { int batch = 1000; ListCertificateOrdersResponse totalResponse = new ListCertificateOrdersResponse(); @@ -483,7 +483,9 @@ public ListCertificateOrdersResponse ListAllCertificateOrders() ListCertificateOrdersRequest request = new ListCertificateOrdersRequest() { limit = batch, - offset = totalResponse.orders.Count + offset = totalResponse.orders.Count, + ignoreExpired = ignoreExpired, + expiredWindow = expiredWindow }; CertCentralResponse response = Request(request, request.BuildParameters());