From d76094ae17b69fc59392b8b30beff40e7f645ffa Mon Sep 17 00:00:00 2001 From: David Galey Date: Mon, 12 Aug 2024 12:41:00 -0400 Subject: [PATCH 1/5] implement paging for full sync --- readme_source.md | 4 +++ .../Client/GlobalSignApiClient.cs | 29 +++++++++++++++++-- src/GlobalSignCAProxy/GlobalSignCAConfig.cs | 4 +++ src/GlobalSignCAProxy/GlobalSignCAProxy.cs | 20 +++++++++++-- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/readme_source.md b/readme_source.md index 8a77d78..45fa403 100644 --- a/readme_source.md +++ b/readme_source.md @@ -144,6 +144,10 @@ This is the number of seconds between retries when attempting to download a cert This is the username that will be used to connect to the GlobalSign API * ```Password``` This is the password that will be used to connect to the GlobalSign API +* ```SyncStartDate``` +OPTIONAL: If provided, full syncs will start at the specified date. +* ```SyncIntervalDays``` +OPTIONAL: Required if SyncStartDate is used. Specifies how to page the certificate sync. Should be a value such that no interval of that length contains > 500 certificate enrollments. ```json "CAConnection": { diff --git a/src/GlobalSignCAProxy/Client/GlobalSignApiClient.cs b/src/GlobalSignCAProxy/Client/GlobalSignApiClient.cs index f84dbb0..3ded199 100644 --- a/src/GlobalSignCAProxy/Client/GlobalSignApiClient.cs +++ b/src/GlobalSignCAProxy/Client/GlobalSignApiClient.cs @@ -37,14 +37,39 @@ public GlobalSignApiClient(GlobalSignCAConfig config) OrderService = new ManagedSSLService() { Url = config.GetUrl(GlobalSignServiceType.ORDER) }; } - public List GetCertificatesForSync(bool fullSync, DateTime? lastSync) + public List GetCertificatesForSync(bool fullSync, DateTime? lastSync, DateTime startDate, int intervalDays) { Logger.MethodEntry(ILogExtensions.MethodLogLevel.Debug); using (this.QueryService) { if (fullSync) { - return GetCertificatesByDateRange(DateTime.MinValue, DateTime.UtcNow); + if (startDate > new DateTime(2000, 01, 01)) + { + DateTime finalStop = DateTime.UtcNow; + List certs = new List(); + DateTime endDate = startDate.AddDays(intervalDays); + if (endDate > finalStop) + { + endDate = finalStop; + } + certs.AddRange(GetCertificatesByDateRange(startDate, endDate)); + while (endDate < finalStop) + { + startDate = endDate.AddSeconds(1); + endDate = startDate.AddDays(intervalDays); + if (endDate > finalStop) + { + endDate = finalStop; + } + certs.AddRange(GetCertificatesByDateRange(startDate, endDate)); + } + return certs; + } + else + { + return GetCertificatesByDateRange(startDate, DateTime.UtcNow); + } } else //Incremental Sync { diff --git a/src/GlobalSignCAProxy/GlobalSignCAConfig.cs b/src/GlobalSignCAProxy/GlobalSignCAConfig.cs index 1e12136..247e9fb 100644 --- a/src/GlobalSignCAProxy/GlobalSignCAConfig.cs +++ b/src/GlobalSignCAProxy/GlobalSignCAConfig.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json.Converters; using query = Keyfactor.Extensions.AnyGateway.GlobalSign.Services.Query; using order = Keyfactor.Extensions.AnyGateway.GlobalSign.Services.Order; +using System.Diagnostics.Contracts; namespace Keyfactor.Extensions.AnyGateway.GlobalSign { @@ -22,6 +23,9 @@ public class GlobalSignCAConfig public string Username { get; set; } public string Password { get; set; } + public string SyncStartDate { get; set; } + public int SyncIntervalDays { get; set; } + public string GetUrl(GlobalSignServiceType queryType) { switch (queryType) diff --git a/src/GlobalSignCAProxy/GlobalSignCAProxy.cs b/src/GlobalSignCAProxy/GlobalSignCAProxy.cs index 4c261d9..ddaaac6 100644 --- a/src/GlobalSignCAProxy/GlobalSignCAProxy.cs +++ b/src/GlobalSignCAProxy/GlobalSignCAProxy.cs @@ -25,6 +25,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Security.Policy; using System.Text; using System.Threading; using System.Web.Services.Configuration; @@ -233,8 +234,14 @@ public override void Synchronize(ICertificateDataReader certificateDataReader, B { GlobalSignApiClient apiClient = new GlobalSignApiClient(Config); - DateTime? syncFrom = certificateAuthoritySyncInfo.DoFullSync ? new DateTime(2000, 01, 01) : certificateAuthoritySyncInfo.OverallLastSync; - var certs = apiClient.GetCertificatesForSync(certificateAuthoritySyncInfo.DoFullSync, syncFrom); + DateTime fullSyncFrom = new DateTime(2000, 01, 01); + if (!string.IsNullOrEmpty(Config.SyncStartDate)) + { + fullSyncFrom = DateTime.Parse(Config.SyncStartDate); + } + + DateTime? syncFrom = certificateAuthoritySyncInfo.DoFullSync ? fullSyncFrom : certificateAuthoritySyncInfo.OverallLastSync; + var certs = apiClient.GetCertificatesForSync(certificateAuthoritySyncInfo.DoFullSync, syncFrom, fullSyncFrom, Config.SyncIntervalDays); foreach (var c in certs) { @@ -332,6 +339,15 @@ public override void ValidateCAConnectionInfo(Dictionary connect var apiClient = new GlobalSignApiClient(validateConfig); apiClient.GetDomains().ForEach(x => Logger.Info($"Connection established for {x.DomainName}")); + + if (!string.IsNullOrEmpty(validateConfig.SyncStartDate)) + { + _ = DateTime.Parse(validateConfig.SyncStartDate); + if (validateConfig.SyncIntervalDays <= 0) + { + throw new Exception("SyncIntervalDays must be a value greater than 0 when using SyncStartDate"); + } + } Logger.MethodExit(ILogExtensions.MethodLogLevel.Debug); } From 794f33bd19b41017aab5212bcdff7337b813d059 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Mon, 12 Aug 2024 16:41:35 +0000 Subject: [PATCH 2/5] Update generated README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index abda15d..b4199b6 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,10 @@ This is the number of seconds between retries when attempting to download a cert This is the username that will be used to connect to the GlobalSign API * ```Password``` This is the password that will be used to connect to the GlobalSign API +* ```SyncStartDate``` +OPTIONAL: If provided, full syncs will start at the specified date. +* ```SyncIntervalDays``` +OPTIONAL: Required if SyncStartDate is used. Specifies how to page the certificate sync. Should be a value such that no interval of that length contains > 500 certificate enrollments. ```json "CAConnection": { From 32887baf72f5a9dd7569a78ea4788346043eb998 Mon Sep 17 00:00:00 2001 From: David Galey Date: Wed, 6 Nov 2024 10:19:21 -0500 Subject: [PATCH 3/5] remove dependence on ad lookup --- CHANGELOG.md | 4 +++ readme_source.md | 6 +++- src/GlobalSignCAProxy/GlobalSignCAProxy.cs | 39 +++++++++++++++++----- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46545d1..7c8b66f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,3 +21,7 @@ Better datetime parsing of returned certificates 1.0.16 Fix for adding additional SANs to certificate requests + +1.1.0 +Add ability to page inventory +Fix to remove AD-dependence \ No newline at end of file diff --git a/readme_source.md b/readme_source.md index 45fa403..1dca047 100644 --- a/readme_source.md +++ b/readme_source.md @@ -51,12 +51,16 @@ The following sections will breakdown the required configurations for the AnyGat ## Templates The Template section will map the CA's SSL profile to an AD template. The Lifetime parameter is required and represents the certificate duration in months. +* ```ContactName``` +The name to pass to GlobalSign as the contact name for enrollments. OPTIONAL if Active Directory authentication is used in Keyfactor Command, in that case it can look up the name of the requesting user. Value provided in this config field overrides AD lookups. + ```json "Templates": { "WebServer": { "ProductID": "PV_SHA2", "Parameters": { - "Lifetime":"12" + "Lifetime":"12", + "ContactName":"John Doe" } } } diff --git a/src/GlobalSignCAProxy/GlobalSignCAProxy.cs b/src/GlobalSignCAProxy/GlobalSignCAProxy.cs index ddaaac6..e08ae12 100644 --- a/src/GlobalSignCAProxy/GlobalSignCAProxy.cs +++ b/src/GlobalSignCAProxy/GlobalSignCAProxy.cs @@ -47,11 +47,34 @@ public override void Initialize(ICAConnectorConfigProvider configProvider) public override EnrollmentResult Enroll(ICertificateDataReader certificateDataReader, string csr, string subject, Dictionary san, EnrollmentProductInfo productInfo, PKIConstants.X509.RequestFormat requestFormat, RequestUtilities.EnrollmentType enrollmentType) { Logger.MethodEntry(ILogExtensions.MethodLogLevel.Debug); - CAProxy.Common.Config.ADUserInfoResolver userInfoResolver = new ADUserInfoResolver(); + string requesterName = ""; + if (productInfo.ProductParameters.ContainsKey("ContactName") && !string.IsNullOrEmpty(productInfo.ProductParameters["ContactName"])) + { + requesterName = productInfo.ProductParameters["ContactName"]; + } + + if (string.IsNullOrEmpty(requesterName)) + { + if (productInfo.ProductParameters.ContainsKey("Keyfactor-Requester")) + { + var requestor = productInfo.ProductParameters["Keyfactor-Requester"]; + if (!string.IsNullOrEmpty(requestor)) + { + try + { + ADUserInfoResolver userInfoResolver = new ADUserInfoResolver(); + Logger.Debug($"Resolving requesting user as '{requestor}'"); + var userInfo = userInfoResolver.Resolve(requestor); + requesterName = userInfo.Name; + } catch (Exception) { } + } + } + } - var requestor = productInfo.ProductParameters["Keyfactor-Requester"]; - Logger.Debug($"Resolving requesting user as '{requestor}'"); - var userInfo = userInfoResolver.Resolve(requestor); + if (string.IsNullOrEmpty(requesterName)) + { + throw new Exception("ContactName configuration field is required but not found, or could not be looked up"); + } try { @@ -153,8 +176,8 @@ public override EnrollmentResult Enroll(ICertificateDataReader certificateDataRe Licenses = "1", OrderKind = "new", Months = months, - FirstName = userInfo.Name, - LastName = userInfo.Name, + FirstName = requesterName, + LastName = requesterName, Email = domain?.ContactInfo?.Email, Phone = domain?.ContactInfo?.Phone, CommonName = commonName, @@ -176,8 +199,8 @@ public override EnrollmentResult Enroll(ICertificateDataReader certificateDataRe Licenses = "1", OrderKind = "renewal", Months = months, - FirstName = userInfo.Name, - LastName = userInfo.Name, + FirstName = requesterName, + LastName = requesterName, Email = domain?.ContactInfo?.Email, Phone = domain?.ContactInfo?.Phone, CommonName = commonName, From cc26e5cfc679cb7ba743092e22b4018c3ab43690 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Wed, 6 Nov 2024 15:19:57 +0000 Subject: [PATCH 4/5] Update generated README --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b4199b6..38d6e3e 100644 --- a/README.md +++ b/README.md @@ -93,12 +93,16 @@ The following sections will breakdown the required configurations for the AnyGat ## Templates The Template section will map the CA's SSL profile to an AD template. The Lifetime parameter is required and represents the certificate duration in months. +* ```ContactName``` +The name to pass to GlobalSign as the contact name for enrollments. OPTIONAL if Active Directory authentication is used in Keyfactor Command, in that case it can look up the name of the requesting user. Value provided in this config field overrides AD lookups. + ```json "Templates": { "WebServer": { "ProductID": "PV_SHA2", "Parameters": { - "Lifetime":"12" + "Lifetime":"12", + "ContactName":"John Doe" } } } From 2a3645e372221c66323b51c18f0ab696c499e6aa Mon Sep 17 00:00:00 2001 From: David Galey Date: Mon, 18 Nov 2024 15:21:06 -0500 Subject: [PATCH 5/5] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c8b66f..5a44bb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,5 +23,5 @@ Better datetime parsing of returned certificates Fix for adding additional SANs to certificate requests 1.1.0 -Add ability to page inventory +Add ability to page inventory Fix to remove AD-dependence \ No newline at end of file