Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge Release 1.1.0 to main #34

Merged
merged 8 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
Expand Down Expand Up @@ -186,6 +190,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": {
Expand Down
10 changes: 9 additions & 1 deletion readme_source.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
Expand Down Expand Up @@ -144,6 +148,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": {
Expand Down
29 changes: 27 additions & 2 deletions src/GlobalSignCAProxy/Client/GlobalSignApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,39 @@ public GlobalSignApiClient(GlobalSignCAConfig config)
OrderService = new ManagedSSLService() { Url = config.GetUrl(GlobalSignServiceType.ORDER) };
}

public List<OrderDetail> GetCertificatesForSync(bool fullSync, DateTime? lastSync)
public List<OrderDetail> 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<OrderDetail > certs = new List<OrderDetail>();
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
{
Expand Down
4 changes: 4 additions & 0 deletions src/GlobalSignCAProxy/GlobalSignCAConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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)
Expand Down
59 changes: 49 additions & 10 deletions src/GlobalSignCAProxy/GlobalSignCAProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -46,11 +47,34 @@ public override void Initialize(ICAConnectorConfigProvider configProvider)
public override EnrollmentResult Enroll(ICertificateDataReader certificateDataReader, string csr, string subject, Dictionary<string, string[]> 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
{
Expand Down Expand Up @@ -152,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,
Expand All @@ -175,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,
Expand Down Expand Up @@ -233,8 +257,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)
{
Expand Down Expand Up @@ -332,6 +362,15 @@ public override void ValidateCAConnectionInfo(Dictionary<string, object> 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);
}

Expand Down
Loading