From 1a5ddfc300b05fb012ab49605be6074ffeaac82f Mon Sep 17 00:00:00 2001 From: Mark Kachkaev Date: Fri, 27 Feb 2026 14:37:34 -0500 Subject: [PATCH 01/13] Update to provide "Enabled" flag support for SAAS deployment. --- .../keyfactor-bootstrap-workflow.yml | 29 ++++++++++++++ README.md | 9 +++-- .../Client/GlobalSignApiClient.cs | 7 ++++ globalsign-mssl-caplugin/Constants.cs | 1 + .../GlobalSignCAConfig.cs | 2 +- .../GlobalSignCAPlugin.cs | 38 ++++++++++++++++++- integration-manifest.json | 4 ++ 7 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/keyfactor-bootstrap-workflow.yml diff --git a/.github/workflows/keyfactor-bootstrap-workflow.yml b/.github/workflows/keyfactor-bootstrap-workflow.yml new file mode 100644 index 0000000..56756c6 --- /dev/null +++ b/.github/workflows/keyfactor-bootstrap-workflow.yml @@ -0,0 +1,29 @@ +name: Keyfactor Bootstrap Workflow + +on: + workflow_dispatch: + pull_request: + types: [opened, closed, synchronize, edited, reopened] + push: + create: + branches: + - 'release-*.*' + +jobs: + call-starter-workflow: + uses: keyfactor/actions/.github/workflows/starter.yml@v4 + permissions: + contents: write # Explicitly grant write permission + with: + command_token_url: ${{ vars.COMMAND_TOKEN_URL }} + command_hostname: ${{ vars.COMMAND_HOSTNAME }} + command_base_api_path: ${{ vars.COMMAND_API_PATH }} + secrets: + token: ${{ secrets.V2BUILDTOKEN}} + gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }} + gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }} + scan_token: ${{ secrets.SAST_TOKEN }} + entra_username: ${{ secrets.DOCTOOL_ENTRA_USERNAME }} + entra_password: ${{ secrets.DOCTOOL_ENTRA_PASSWD }} + command_client_id: ${{ secrets.COMMAND_CLIENT_ID }} + command_client_secret: ${{ secrets.COMMAND_CLIENT_SECRET }} \ No newline at end of file diff --git a/README.md b/README.md index 35a37ad..b2621da 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@

Integration Status: production -Release -Issues -GitHub Downloads (all assets, all releases) +Release +Issues +GitHub Downloads (all assets, all releases)

@@ -60,7 +60,7 @@ This extension uses the contact information of the GCC Domain point of contact f 1. Install the AnyCA Gateway REST per the [official Keyfactor documentation](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/InstallIntroduction.htm). -2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [GlobalSign MSSL Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/globalsign-mssl-caplugin/releases/latest) from GitHub. +2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [GlobalSign MSSL Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/globalsign-mssl-caplugin-dev/releases/latest) from GitHub. 3. Copy the unzipped directory (usually called `net6.0` or `net8.0`) to the Extensions directory: @@ -103,6 +103,7 @@ This extension uses the contact information of the GCC Domain point of contact f * **RetryCount** - This is the number of times the AnyGateway will attempt to pickup an new certificate before reporting an error. Default is 5. * **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. * **SyncStartDate** - If provided, full syncs will start at the specified date. + * **Enabled** - Flag to Enable or Disable gateway functionality. Disabling is primarily used to allow creation of the CA prior to configuration information being available. 2. Define [Certificate Profiles](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCP-Gateway.htm) and [Certificate Templates](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCA-Gateway.htm) for the Certificate Authority as required. One Certificate Profile must be defined per Certificate Template. It's recommended that each Certificate Profile be named after the Product ID. The GlobalSign MSSL Gateway plugin supports the following product IDs: diff --git a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs index 0c54492..9e03321 100644 --- a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs +++ b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs @@ -26,6 +26,13 @@ public GlobalSignApiClient(GlobalSignCAConfig config, ILogger logger) Logger = logger; Config = config; // Logger = LogHandler.GetClassLogger(this.GetType()); + var enabled =config.Enabled; + if (enabled) + { + Logger.LogWarning($"The CA is currently in the Disabled state. It must be Enabled to perform operations. Skipping config validation and MSSL Client creation..."); + Logger.MethodExit(); + return; + } QueryService = new GASV1Client { Endpoint = { Address = new EndpointAddress(config.GetUrl(GlobalSignServiceType.QUERY)), Name = "QUERY" } diff --git a/globalsign-mssl-caplugin/Constants.cs b/globalsign-mssl-caplugin/Constants.cs index 108da49..d9c517a 100644 --- a/globalsign-mssl-caplugin/Constants.cs +++ b/globalsign-mssl-caplugin/Constants.cs @@ -21,6 +21,7 @@ internal class Constants public static string PICKUPDELAY = "DelayTime"; public static string SYNCSTARTDATE = "SyncStartDate"; public static string SYNCINTERNVALDAYS = "SyncIntervalDays"; + public static string Enabled = "Enabled"; } public static class EnrollmentConfigConstants diff --git a/globalsign-mssl-caplugin/GlobalSignCAConfig.cs b/globalsign-mssl-caplugin/GlobalSignCAConfig.cs index 0340b09..1147e54 100644 --- a/globalsign-mssl-caplugin/GlobalSignCAConfig.cs +++ b/globalsign-mssl-caplugin/GlobalSignCAConfig.cs @@ -32,7 +32,7 @@ public class GlobalSignCAConfig public string SyncStartDate { get; set; } = ""; public int SyncIntervalDays { get; set; } = 0; - + public bool Enabled { get; set; } = true; public string GetUrl(GlobalSignServiceType queryType) { diff --git a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs index e4cfde3..20278bc 100644 --- a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs +++ b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs @@ -23,16 +23,24 @@ public class GlobalSignCAPlugin : IAnyCAPlugin private ICertificateDataReader? _certificateDataReader; private ILogger Logger; - private GlobalSignCAConfig Config { get; set; } = new(); - + private GlobalSignCAConfig Config { get; set; } = new(); + private bool _enabled = false; public void Initialize(IAnyCAPluginConfigProvider configProvider, ICertificateDataReader certificateDataReader) { Logger = LogHandler.GetClassLogger(GetType()); Logger.MethodEntry(); + _enabled = (bool)configProvider.CAConnectionData["Enabled"]; + if (!_enabled) + { + Logger.LogWarning($"The CA is currently in the Disabled state. It must be Enabled to perform operations. Skipping config validation and MSSL Client creation..."); + Logger.MethodExit(); + return; + } Config = new GlobalSignCAConfig { IsTest = bool.Parse((string)configProvider.CAConnectionData["TestAPI"]), + Enabled = bool.Parse((string)configProvider.CAConnectionData["Enabled"]), Password = (string)configProvider.CAConnectionData["GlobalSignPassword"], Username = (string)configProvider.CAConnectionData["GlobalSignUsername"], PickupDelay = int.Parse((string)configProvider.CAConnectionData["DelayTime"]), @@ -426,6 +434,12 @@ public async Task Enroll(string csr, string subject, Dictionar public async Task Ping() { Logger.MethodEntry(); + if (!_enabled) + { + Logger.LogWarning($"The CA is currently in the Disabled state. It must be Enabled to perform operations. Skipping config validation and MSSL Client creation..."); + Logger.MethodExit(); + return; + } try { Logger.LogInformation("Ping reqeuest recieved"); @@ -443,6 +457,19 @@ public async Task ValidateCAConnectionInfo(Dictionary connection { Logger = LogHandler.GetClassLogger(GetType()); Logger.MethodEntry(); + try + { + if (!(bool)connectionInfo["Enabled"]) + { + Logger.LogWarning($"The CA is currently in the Disabled state. It must be Enabled to perform operations. Skipping validation..."); + Logger.MethodExit(LogLevel.Trace); + return; + } + } + catch (Exception ex) + { + Logger.LogError($"Exception: {LogHandler.FlattenException(ex)}"); + } Config = new GlobalSignCAConfig { IsTest = bool.Parse((string)connectionInfo["TestAPI"]), @@ -592,6 +619,13 @@ public Dictionary GetCAConnectorAnnotations() Hidden = false, DefaultValue = "2000-01-01", Type = "Integer" + }, + [Constants.Enabled] = new() + { + Comments = "Flag to Enable or Disable gateway functionality. Disabling is primarily used to allow creation of the CA prior to configuration information being available.", + Hidden = false, + DefaultValue = true, + Type = "Boolean" } }; } diff --git a/integration-manifest.json b/integration-manifest.json index 49a628a..793eecf 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -60,6 +60,10 @@ { "name": "SyncStartDate", "description": "If provided, full syncs will start at the specified date." + }, + { + "name": "Enabled", + "description": "Flag to Enable or Disable gateway functionality. Disabling is primarily used to allow creation of the CA prior to configuration information being available." } ], "enrollment_config": [ From f9d677046a05d4c4be874f507d665bc164e76593 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Fri, 27 Feb 2026 19:39:06 +0000 Subject: [PATCH 02/13] Update generated docs --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b2621da..705c6a9 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@

Integration Status: production -Release -Issues -GitHub Downloads (all assets, all releases) +Release +Issues +GitHub Downloads (all assets, all releases)

@@ -60,7 +60,7 @@ This extension uses the contact information of the GCC Domain point of contact f 1. Install the AnyCA Gateway REST per the [official Keyfactor documentation](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/InstallIntroduction.htm). -2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [GlobalSign MSSL Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/globalsign-mssl-caplugin-dev/releases/latest) from GitHub. +2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [GlobalSign MSSL Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/globalsign-mssl-caplugin/releases/latest) from GitHub. 3. Copy the unzipped directory (usually called `net6.0` or `net8.0`) to the Extensions directory: From ba0e2fd7972cd45ce09f7e2c87538a7bf4fb1356 Mon Sep 17 00:00:00 2001 From: Mark Kachkaev Date: Fri, 27 Feb 2026 14:41:29 -0500 Subject: [PATCH 03/13] Fixing build. --- .../keyfactor-bootstrap-workflow-v3.yml | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 .github/workflows/keyfactor-bootstrap-workflow-v3.yml diff --git a/.github/workflows/keyfactor-bootstrap-workflow-v3.yml b/.github/workflows/keyfactor-bootstrap-workflow-v3.yml deleted file mode 100644 index 64919a4..0000000 --- a/.github/workflows/keyfactor-bootstrap-workflow-v3.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Keyfactor Bootstrap Workflow - -on: - workflow_dispatch: - pull_request: - types: [opened, closed, synchronize, edited, reopened] - push: - create: - branches: - - 'release-*.*' - -jobs: - call-starter-workflow: - uses: keyfactor/actions/.github/workflows/starter.yml@v3 - secrets: - token: ${{ secrets.V2BUILDTOKEN}} - APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}} - gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }} - gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }} - scan_token: ${{ secrets.SAST_TOKEN }} From 0ca63d84eb8405d0fa42479e0f500c89677f930e Mon Sep 17 00:00:00 2001 From: Mark Kachkaev Date: Wed, 11 Mar 2026 13:29:03 -0400 Subject: [PATCH 04/13] Fixes for enabled. --- .../Client/GlobalSignApiClient.cs | 2 +- .../GlobalSignCAPlugin.cs | 34 +++++++++++++------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs index 9e03321..f95140b 100644 --- a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs +++ b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs @@ -27,7 +27,7 @@ public GlobalSignApiClient(GlobalSignCAConfig config, ILogger logger) Config = config; // Logger = LogHandler.GetClassLogger(this.GetType()); var enabled =config.Enabled; - if (enabled) + if (!enabled) { Logger.LogWarning($"The CA is currently in the Disabled state. It must be Enabled to perform operations. Skipping config validation and MSSL Client creation..."); Logger.MethodExit(); diff --git a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs index 20278bc..6439c71 100644 --- a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs +++ b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs @@ -457,19 +457,18 @@ public async Task ValidateCAConnectionInfo(Dictionary connection { Logger = LogHandler.GetClassLogger(GetType()); Logger.MethodEntry(); - try - { - if (!(bool)connectionInfo["Enabled"]) - { - Logger.LogWarning($"The CA is currently in the Disabled state. It must be Enabled to perform operations. Skipping validation..."); - Logger.MethodExit(LogLevel.Trace); - return; - } - } - catch (Exception ex) + + // Handle Enabled flag - could be bool or string + var enabledValue = connectionInfo["Enabled"]; + bool isEnabled = enabledValue is bool ? (bool)enabledValue : bool.Parse((string)enabledValue); + + if (!isEnabled) { - Logger.LogError($"Exception: {LogHandler.FlattenException(ex)}"); + Logger.LogWarning($"The CA is currently in the Disabled state. It must be Enabled to perform operations. Skipping validation..."); + Logger.MethodExit(LogLevel.Trace); + return; } + Config = new GlobalSignCAConfig { IsTest = bool.Parse((string)connectionInfo["TestAPI"]), @@ -482,6 +481,7 @@ public async Task ValidateCAConnectionInfo(Dictionary connection ORDER_TEST_URL = (string)connectionInfo["OrderAPITestURL"], QUERY_TEST_URL = (string)connectionInfo["QueryAPITestURL"], QUERY_PROD_URL = (string)connectionInfo["QueryAPIProdURL"], + Enabled = isEnabled, SyncStartDate = connectionInfo.TryGetValue("SyncStartDate", out object? value) ? (string)value : string.Empty, SyncIntervalDays = connectionInfo.TryGetValue("SyncIntervalDays", out var val) @@ -497,6 +497,17 @@ public async Task ValidateCAConnectionInfo(Dictionary connection public Task ValidateProductInfo(EnrollmentProductInfo productInfo, Dictionary connectionInfo) { + // Handle Enabled flag - could be bool or string + var enabledValue = connectionInfo["Enabled"]; + bool isEnabled = enabledValue is bool ? (bool)enabledValue : bool.Parse((string)enabledValue); + + if (!isEnabled) + { + Logger.LogWarning($"The CA is currently in the Disabled state. It must be Enabled to perform operations. Skipping validation..."); + Logger.MethodExit(LogLevel.Trace); + return Task.CompletedTask; + } + Config = new GlobalSignCAConfig { IsTest = bool.Parse((string)connectionInfo["TestAPI"]), @@ -509,6 +520,7 @@ public Task ValidateProductInfo(EnrollmentProductInfo productInfo, Dictionary Date: Wed, 11 Mar 2026 17:31:06 +0000 Subject: [PATCH 05/13] Update generated docs --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 705c6a9..3c4305d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- GlobalSign MSSL Gateway AnyCA Gateway REST Plugin + GlobalSign MSSL AnyCA Gateway REST Plugin

@@ -38,10 +38,10 @@ The GlobalSign CAPlugin enables the Synchronization, Enrollment, and Revocation ## Compatibility -The GlobalSign MSSL Gateway AnyCA Gateway REST plugin is compatible with the Keyfactor AnyCA Gateway REST 25.2.0 and later. +The GlobalSign MSSL AnyCA Gateway REST plugin is compatible with the Keyfactor AnyCA Gateway REST 25.2.0 and later. ## Support -The GlobalSign MSSL Gateway AnyCA Gateway REST plugin is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. +The GlobalSign MSSL AnyCA Gateway REST plugin is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. > 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. @@ -60,7 +60,7 @@ This extension uses the contact information of the GCC Domain point of contact f 1. Install the AnyCA Gateway REST per the [official Keyfactor documentation](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/InstallIntroduction.htm). -2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [GlobalSign MSSL Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/globalsign-mssl-caplugin/releases/latest) from GitHub. +2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [GlobalSign MSSL AnyCA Gateway REST plugin](https://github.com/Keyfactor/globalsign-mssl-caplugin/releases/latest) from GitHub. 3. Copy the unzipped directory (usually called `net6.0` or `net8.0`) to the Extensions directory: @@ -71,11 +71,11 @@ This extension uses the contact information of the GCC Domain point of contact f Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net8.0\Extensions ``` - > The directory containing the GlobalSign MSSL Gateway AnyCA Gateway REST plugin DLLs (`net6.0` or `net8.0`) can be named anything, as long as it is unique within the `Extensions` directory. + > The directory containing the GlobalSign MSSL AnyCA Gateway REST plugin DLLs (`net6.0` or `net8.0`) can be named anything, as long as it is unique within the `Extensions` directory. 4. Restart the AnyCA Gateway REST service. -5. Navigate to the AnyCA Gateway REST portal and verify that the Gateway recognizes the GlobalSign MSSL Gateway plugin by hovering over the ⓘ symbol to the right of the Gateway on the top left of the portal. +5. Navigate to the AnyCA Gateway REST portal and verify that the Gateway recognizes the GlobalSign MSSL plugin by hovering over the ⓘ symbol to the right of the Gateway on the top left of the portal. ## Configuration @@ -105,7 +105,7 @@ This extension uses the contact information of the GCC Domain point of contact f * **SyncStartDate** - If provided, full syncs will start at the specified date. * **Enabled** - Flag to Enable or Disable gateway functionality. Disabling is primarily used to allow creation of the CA prior to configuration information being available. -2. Define [Certificate Profiles](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCP-Gateway.htm) and [Certificate Templates](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCA-Gateway.htm) for the Certificate Authority as required. One Certificate Profile must be defined per Certificate Template. It's recommended that each Certificate Profile be named after the Product ID. The GlobalSign MSSL Gateway plugin supports the following product IDs: +2. Define [Certificate Profiles](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCP-Gateway.htm) and [Certificate Templates](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCA-Gateway.htm) for the Certificate Authority as required. One Certificate Profile must be defined per Certificate Template. It's recommended that each Certificate Profile be named after the Product ID. The GlobalSign MSSL plugin supports the following product IDs: * **PEV_SHA2** * **PEV** From c58cc5ef5250c6655e00af781d7f633d0888360a Mon Sep 17 00:00:00 2001 From: Mark Kachkaev Date: Wed, 11 Mar 2026 13:33:28 -0400 Subject: [PATCH 06/13] More fixes. --- globalsign-mssl-caplugin/GlobalSignCAPlugin.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs index 6439c71..b7310cb 100644 --- a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs +++ b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs @@ -30,8 +30,9 @@ public void Initialize(IAnyCAPluginConfigProvider configProvider, ICertificateDa { Logger = LogHandler.GetClassLogger(GetType()); Logger.MethodEntry(); - _enabled = (bool)configProvider.CAConnectionData["Enabled"]; - if (!_enabled) + var enabledValue = configProvider.CAConnectionData["Enabled"]; + bool isEnabled = enabledValue is bool ? (bool)enabledValue : bool.Parse((string)enabledValue); + if (!isEnabled) { Logger.LogWarning($"The CA is currently in the Disabled state. It must be Enabled to perform operations. Skipping config validation and MSSL Client creation..."); Logger.MethodExit(); @@ -40,7 +41,7 @@ public void Initialize(IAnyCAPluginConfigProvider configProvider, ICertificateDa Config = new GlobalSignCAConfig { IsTest = bool.Parse((string)configProvider.CAConnectionData["TestAPI"]), - Enabled = bool.Parse((string)configProvider.CAConnectionData["Enabled"]), + Enabled = isEnabled, Password = (string)configProvider.CAConnectionData["GlobalSignPassword"], Username = (string)configProvider.CAConnectionData["GlobalSignUsername"], PickupDelay = int.Parse((string)configProvider.CAConnectionData["DelayTime"]), From c5bb5d8682e7ec76a1dc6c35b8eca7993851f420 Mon Sep 17 00:00:00 2001 From: David Galey Date: Tue, 17 Mar 2026 14:06:42 -0400 Subject: [PATCH 07/13] Add sync product filter Fixes for SAN duplications --- .../Api/GlobalSignEnrollRequest.cs | 27 ++++- .../Api/GlobalSignRenewRequest.cs | 25 +++- .../Client/GlobalSignApiClient.cs | 10 +- globalsign-mssl-caplugin/Constants.cs | 4 +- .../GlobalSignCAConfig.cs | 1 + .../GlobalSignCAPlugin.cs | 108 ++++++++++++++---- 6 files changed, 144 insertions(+), 31 deletions(-) diff --git a/globalsign-mssl-caplugin/Api/GlobalSignEnrollRequest.cs b/globalsign-mssl-caplugin/Api/GlobalSignEnrollRequest.cs index 9d4b16e..df91f0c 100644 --- a/globalsign-mssl-caplugin/Api/GlobalSignEnrollRequest.cs +++ b/globalsign-mssl-caplugin/Api/GlobalSignEnrollRequest.cs @@ -107,7 +107,32 @@ public BmV2PvOrderRequest Request continue; } - var entry = new SANEntry(); + string trimCN = CommonName, trimItem = item; + + if (CommonName.StartsWith("*.")) + { + trimCN = CommonName.Substring(2).ToLower(); + trimItem = item.ToLower(); + List equivs = new List { $"*.{trimCN}", $"www.{trimCN}", $"{trimCN}" }; + if (equivs.Contains(trimItem)) + { + Logger.LogInformation($"SAN Entry {item} is equivalent to CN ignoring wildcards or www prefix, removing from request"); + continue; + } + } + else if (CommonName.StartsWith("www.")) + { + trimCN = CommonName.Substring(4).ToLower(); + trimItem = item.ToLower(); + List equivs = new List { $"www.{trimCN}", $"{trimCN}" }; + if (equivs.Contains(trimItem)) + { + Logger.LogInformation($"SAN Entry {item} is equivalent to CN ignoring wildcards or www prefix, removing from request"); + continue; + } + } + + var entry = new SANEntry(); entry.SubjectAltName = item; var sb = new StringBuilder(); sb.Append("Adding SAN entry of type "); diff --git a/globalsign-mssl-caplugin/Api/GlobalSignRenewRequest.cs b/globalsign-mssl-caplugin/Api/GlobalSignRenewRequest.cs index 8ab88d7..117576c 100644 --- a/globalsign-mssl-caplugin/Api/GlobalSignRenewRequest.cs +++ b/globalsign-mssl-caplugin/Api/GlobalSignRenewRequest.cs @@ -53,8 +53,31 @@ public GlobalSignRenewRequest(GlobalSignCAConfig config, bool privateDomain, boo Logger.LogInformation($"SAN Entry {item} matches CN, removing from request"); continue; } + string trimCN = CommonName, trimItem = item; - var entry = new SANEntry(); + if (CommonName.StartsWith("*.")) + { + trimCN = CommonName.Substring(2).ToLower(); + trimItem = item.ToLower(); + List equivs = new List { $"*.{trimCN}", $"www.{trimCN}", $"{trimCN}" }; + if (equivs.Contains(trimItem)) + { + Logger.LogInformation($"SAN Entry {item} is equivalent to CN ignoring wildcards or www prefix, removing from request"); + continue; + } + } + else if (CommonName.StartsWith("www.")) + { + trimCN = CommonName.Substring(4).ToLower(); + trimItem = item.ToLower(); + List equivs = new List { $"www.{trimCN}", $"{trimCN}" }; + if (equivs.Contains(trimItem)) + { + Logger.LogInformation($"SAN Entry {item} is equivalent to CN ignoring wildcards or www prefix, removing from request"); + continue; + } + } + var entry = new SANEntry(); entry.SubjectAltName = item; var sb = new StringBuilder(); sb.Append("Adding SAN entry of type "); diff --git a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs index 0c54492..37b0df1 100644 --- a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs +++ b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs @@ -272,11 +272,11 @@ public async Task Enroll(GlobalSignEnrollRequest enrollRequest Logger.MethodEntry(); var rawRequest = enrollRequest.Request; Logger.LogTrace("Request details:"); - Logger.LogTrace($"Profile ID: {enrollRequest.MsslProfileId}"); - Logger.LogTrace($"Domain ID: {enrollRequest.MsslDomainId}"); + Logger.LogTrace($"Profile ID: {rawRequest.MSSLProfileID}"); + Logger.LogTrace($"Domain ID: {rawRequest.MSSLDomainID}"); Logger.LogTrace( - $"Contact Info: {enrollRequest.FirstName}, {enrollRequest.LastName}, {enrollRequest.Email}, {enrollRequest.Phone}"); - Logger.LogTrace($"SAN Count: {enrollRequest.SANs.Count()}"); + $"Contact Info: {rawRequest.ContactInfo.FirstName}, {rawRequest.ContactInfo.LastName}, {rawRequest.ContactInfo.Email}, {rawRequest.ContactInfo.Phone}"); + Logger.LogTrace($"SAN Count: {rawRequest.SANEntries.Count()}"); if (rawRequest.SANEntries.Count() > 0) Logger.LogTrace($"SANs: {string.Join(",", rawRequest.SANEntries.Select(s => s.SubjectAltName))}"); Logger.LogTrace($"Product Code: {rawRequest.OrderRequestParameter.ProductCode}"); @@ -284,7 +284,7 @@ public async Task Enroll(GlobalSignEnrollRequest enrollRequest if (!string.IsNullOrEmpty(rawRequest.OrderRequestParameter.BaseOption)) Logger.LogTrace($"Order Base Option: {rawRequest.OrderRequestParameter.BaseOption}"); - var requestwrapper = new PVOrder(enrollRequest.Request); + var requestwrapper = new PVOrder(rawRequest); var responsewrapper = await OrderService.PVOrderAsync(requestwrapper); ; var response = responsewrapper.Response; diff --git a/globalsign-mssl-caplugin/Constants.cs b/globalsign-mssl-caplugin/Constants.cs index 108da49..6bc0946 100644 --- a/globalsign-mssl-caplugin/Constants.cs +++ b/globalsign-mssl-caplugin/Constants.cs @@ -21,11 +21,13 @@ internal class Constants public static string PICKUPDELAY = "DelayTime"; public static string SYNCSTARTDATE = "SyncStartDate"; public static string SYNCINTERNVALDAYS = "SyncIntervalDays"; + public static string SYNCPRODUCTS = "SyncProducts"; } public static class EnrollmentConfigConstants { public const string RootCAType = "RootCAType"; public const string SlotSize = "SlotSize"; - public const string CertificateValidityInYears = "CertificateValidityInYears"; + public const string CertificateValidityInDays = "CertificateValidityInDays"; + public const string MSSLProfileId = "MSSLProfileId"; } \ No newline at end of file diff --git a/globalsign-mssl-caplugin/GlobalSignCAConfig.cs b/globalsign-mssl-caplugin/GlobalSignCAConfig.cs index 0340b09..13aca06 100644 --- a/globalsign-mssl-caplugin/GlobalSignCAConfig.cs +++ b/globalsign-mssl-caplugin/GlobalSignCAConfig.cs @@ -32,6 +32,7 @@ public class GlobalSignCAConfig public string SyncStartDate { get; set; } = ""; public int SyncIntervalDays { get; set; } = 0; + public string SyncProducts { get; set; } = ""; public string GetUrl(GlobalSignServiceType queryType) diff --git a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs index e4cfde3..ee18041 100644 --- a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs +++ b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs @@ -90,8 +90,30 @@ public async Task Synchronize(BlockingCollection blockin var certs = await apiClient.GetCertificatesForSyncAsync(fullSync, syncFrom, fullSyncFrom, Config.SyncIntervalDays); + bool productFilter = false; + List products = null; + if (!string.IsNullOrEmpty(Config.SyncProducts)) + { + products = Config.SyncProducts.Split(',').ToList(); + products.ForEach(p => p.ToUpper()); + productFilter = true; + } + foreach (var c in certs) { + if (productFilter) + { + bool prodMatch = false; + if (c.OrderInfo?.ProductCode != null && products.Contains(c.OrderInfo.ProductCode.ToUpper())) + { + prodMatch = true; + } + if (!prodMatch) + { + Logger.LogInformation($"Found certificate with product code {c.OrderInfo?.ProductCode}, which does not match the filter criteria. Skipping."); + continue; + } + } var orderStatus = (GlobalSignOrderStatus)Enum.Parse(typeof(GlobalSignOrderStatus), c.CertificateInfo?.CertificateStatus ?? string.Empty); DateTime? subDate = DateTime.TryParse(c.OrderInfo?.OrderDate, out var orderDate) ? orderDate : null; @@ -237,6 +259,8 @@ public async Task Enroll(string csr, string subject, Dictionar if (sanDict.TryGetValue("ipaddress", out var ipSans)) Logger.LogTrace($"IP SAN Count: {ipSans.Length}"); + List matchedDomains = new List(); + // only try to resolve a domain if we don't already have a commonName if (string.IsNullOrWhiteSpace(commonName)) { @@ -247,16 +271,16 @@ public async Task Enroll(string csr, string subject, Dictionar if (string.IsNullOrWhiteSpace(ipSan)) continue; - var tempDomain = validDomains? - .FirstOrDefault(d => + var tempDomains = validDomains + .Where(d => !string.IsNullOrEmpty(d?.DomainName) && ipSan.EndsWith($".{d.DomainName}", StringComparison.OrdinalIgnoreCase) - ); + ).ToList(); - if (tempDomain != null) + if (tempDomains != null && tempDomains.Count > 0) { Logger.LogDebug($"ipSAN Domain match found for ipSAN: {ipSan}"); - domain = tempDomain; + matchedDomains = tempDomains; commonName = ipSan; break; } @@ -269,23 +293,23 @@ public async Task Enroll(string csr, string subject, Dictionar if (string.IsNullOrWhiteSpace(dnsSan)) continue; - var tempDomain = validDomains? - .FirstOrDefault(d => + var tempDomains = validDomains + .Where(d => !string.IsNullOrEmpty(d?.DomainName) && dnsSan.EndsWith(d.DomainName, StringComparison.OrdinalIgnoreCase) - ); + ).ToList(); - if (tempDomain != null) + if (tempDomains != null && tempDomains.Count > 0) { Logger.LogDebug($"SAN Domain match found for SAN: {dnsSan}"); - domain = tempDomain; + matchedDomains = tempDomains; commonName = dnsSan; break; } } } // If private domain skip domain resolution. - if (privateDomain) + else if (privateDomain) { var profiles = await apiClient.GetProfiles(); var fillProfile = profiles.FirstOrDefault(); @@ -302,18 +326,41 @@ public async Task Enroll(string csr, string subject, Dictionar } }; domain.MSSLProfileID = fillProfile.MSSLProfileId; + matchedDomains = new List { domain }; } // 3) Fallback: if we did obtain a commonName (or it was already set), try matching it - if (domain == null && !string.IsNullOrWhiteSpace(commonName)) - domain = validDomains? - .FirstOrDefault(d => + else if (domain == null && !string.IsNullOrWhiteSpace(commonName)) + matchedDomains = validDomains + .Where(d => !string.IsNullOrEmpty(d?.DomainName) && commonName.EndsWith(d.DomainName, StringComparison.OrdinalIgnoreCase) - ); - - - if (domain == null) throw new Exception("Unable to determine GlobalSign domain"); + ).ToList(); + + if (matchedDomains.Count == 1) + { + domain = matchedDomains[0]; + } + else + { + var profId = productInfo.ProductParameters["MSSLProfileID"]; + if (!string.IsNullOrEmpty(profId) ) + { + var tempDomain = matchedDomains.Where(d => + d.MSSLProfileID.Equals(profId, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); + if (tempDomain != null) + { + domain = tempDomain; + } + else + { + throw new Exception($"No domain matching common name {commonName} has provided MSSLProfileID of {profId}. Check configuration."); + } + } + } + + + if (domain == null) throw new Exception("Unable to determine GlobalSign domain"); @@ -592,7 +639,14 @@ public Dictionary GetCAConnectorAnnotations() Hidden = false, DefaultValue = "2000-01-01", Type = "Integer" - } + }, + [Constants.SYNCPRODUCTS] = new() + { + Comments = "OPTIONAL: If provided as a comma-separated list of product IDs, will limit the certificate sync to only certificates of those products. If blank or not provided, will sync all certs.", + Hidden = false, + DefaultValue = null, + Type = "String" + } }; } @@ -601,11 +655,11 @@ public Dictionary GetTemplateParameterAnnotations() { return new Dictionary { - [EnrollmentConfigConstants.CertificateValidityInYears] = new() + [EnrollmentConfigConstants.CertificateValidityInDays] = new() { - Comments = "Number of years the certificate will be valid for", + Comments = "Number of days the certificate will be valid for", Hidden = false, - DefaultValue = "1", + DefaultValue = "199", Type = "Number" }, [EnrollmentConfigConstants.SlotSize] = new() @@ -623,7 +677,15 @@ public Dictionary GetTemplateParameterAnnotations() Hidden = false, DefaultValue = "GLOBALSIGN_ROOT_R3", Type = "String" - } + }, + [EnrollmentConfigConstants.MSSLProfileId] = new() + { + Comments = + "OPTIONAL: If specified, enrollments will use that profile ID for domain lookups. If not provided, domain lookup will be done based on the Common Name or first DNS SAN. Useful if your GlobalSign account has multiple domain objects with the same domain string, or subdomains (e.g. sub.test.com vs test.com).", + Hidden = false, + DefaultValue = null, + Type = "String" + } }; } From f27672540cff24df78ddbc9a3b3ae7030eed8f32 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Tue, 17 Mar 2026 18:08:36 +0000 Subject: [PATCH 08/13] Update generated docs --- README.md | 18 ++++++++++-------- integration-manifest.json | 12 ++++++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 35a37ad..bd3a895 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- GlobalSign MSSL Gateway AnyCA Gateway REST Plugin + GlobalSign MSSL AnyCA Gateway REST Plugin

@@ -38,10 +38,10 @@ The GlobalSign CAPlugin enables the Synchronization, Enrollment, and Revocation ## Compatibility -The GlobalSign MSSL Gateway AnyCA Gateway REST plugin is compatible with the Keyfactor AnyCA Gateway REST 25.2.0 and later. +The GlobalSign MSSL AnyCA Gateway REST plugin is compatible with the Keyfactor AnyCA Gateway REST 25.2.0 and later. ## Support -The GlobalSign MSSL Gateway AnyCA Gateway REST plugin is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. +The GlobalSign MSSL AnyCA Gateway REST plugin is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. > 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. @@ -60,7 +60,7 @@ This extension uses the contact information of the GCC Domain point of contact f 1. Install the AnyCA Gateway REST per the [official Keyfactor documentation](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/InstallIntroduction.htm). -2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [GlobalSign MSSL Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/globalsign-mssl-caplugin/releases/latest) from GitHub. +2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [GlobalSign MSSL AnyCA Gateway REST plugin](https://github.com/Keyfactor/globalsign-mssl-caplugin/releases/latest) from GitHub. 3. Copy the unzipped directory (usually called `net6.0` or `net8.0`) to the Extensions directory: @@ -71,11 +71,11 @@ This extension uses the contact information of the GCC Domain point of contact f Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net8.0\Extensions ``` - > The directory containing the GlobalSign MSSL Gateway AnyCA Gateway REST plugin DLLs (`net6.0` or `net8.0`) can be named anything, as long as it is unique within the `Extensions` directory. + > The directory containing the GlobalSign MSSL AnyCA Gateway REST plugin DLLs (`net6.0` or `net8.0`) can be named anything, as long as it is unique within the `Extensions` directory. 4. Restart the AnyCA Gateway REST service. -5. Navigate to the AnyCA Gateway REST portal and verify that the Gateway recognizes the GlobalSign MSSL Gateway plugin by hovering over the ⓘ symbol to the right of the Gateway on the top left of the portal. +5. Navigate to the AnyCA Gateway REST portal and verify that the Gateway recognizes the GlobalSign MSSL plugin by hovering over the ⓘ symbol to the right of the Gateway on the top left of the portal. ## Configuration @@ -103,8 +103,9 @@ This extension uses the contact information of the GCC Domain point of contact f * **RetryCount** - This is the number of times the AnyGateway will attempt to pickup an new certificate before reporting an error. Default is 5. * **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. * **SyncStartDate** - If provided, full syncs will start at the specified date. + * **SyncProducts** - OPTIONAL: If provided as a comma-separated list of product IDs, will limit the certificate sync to only certificates of those products. If blank or not provided, will sync all certs. -2. Define [Certificate Profiles](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCP-Gateway.htm) and [Certificate Templates](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCA-Gateway.htm) for the Certificate Authority as required. One Certificate Profile must be defined per Certificate Template. It's recommended that each Certificate Profile be named after the Product ID. The GlobalSign MSSL Gateway plugin supports the following product IDs: +2. Define [Certificate Profiles](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCP-Gateway.htm) and [Certificate Templates](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCA-Gateway.htm) for the Certificate Authority as required. One Certificate Profile must be defined per Certificate Template. It's recommended that each Certificate Profile be named after the Product ID. The GlobalSign MSSL plugin supports the following product IDs: * **PEV_SHA2** * **PEV** @@ -120,9 +121,10 @@ This extension uses the contact information of the GCC Domain point of contact f 4. In Keyfactor Command (v12.3+), for each imported Certificate Template, follow the [official documentation](https://software.keyfactor.com/Core-OnPrem/Current/Content/ReferenceGuide/Configuring%20Template%20Options.htm) to define enrollment fields for each of the following parameters: - * **CertificateValidityInYears** - Number of years the certificate will be valid for + * **CertificateValidityInDays** - Number of days the certificate will be valid for * **SlotSize** - Maximum number of SANs that a certificate may have - valid values are [FIVE, TEN, FIFTEEN, TWENTY, THIRTY, FOURTY, FIFTY, ONE_HUNDRED] * **RootCAType** - The certificate's root CA - Depending on certificate expiration date, SHA_1 not be allowed. Will default to SHA_2 if expiration date exceeds sha1 allowed date. Options are GlobalSign R certs. + * **MSSLProfileId** - OPTIONAL: If specified, enrollments will use that profile ID for domain lookups. If not provided, domain lookup will be done based on the Common Name or first DNS SAN. Useful if your GlobalSign account has multiple domain objects with the same domain string, or subdomains (e.g. sub.test.com vs test.com). ## Valid GlobalSign SAN Usage diff --git a/integration-manifest.json b/integration-manifest.json index 49a628a..046de02 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -60,12 +60,16 @@ { "name": "SyncStartDate", "description": "If provided, full syncs will start at the specified date." + }, + { + "name": "SyncProducts", + "description": "OPTIONAL: If provided as a comma-separated list of product IDs, will limit the certificate sync to only certificates of those products. If blank or not provided, will sync all certs." } ], "enrollment_config": [ { - "name": "CertificateValidityInYears", - "description": "Number of years the certificate will be valid for" + "name": "CertificateValidityInDays", + "description": "Number of days the certificate will be valid for" }, { "name": "SlotSize", @@ -74,6 +78,10 @@ { "name": "RootCAType", "description": "The certificate's root CA - Depending on certificate expiration date, SHA_1 not be allowed. Will default to SHA_2 if expiration date exceeds sha1 allowed date. Options are GlobalSign R certs." + }, + { + "name": "MSSLProfileId", + "description": "OPTIONAL: If specified, enrollments will use that profile ID for domain lookups. If not provided, domain lookup will be done based on the Common Name or first DNS SAN. Useful if your GlobalSign account has multiple domain objects with the same domain string, or subdomains (e.g. sub.test.com vs test.com)." } ], "product_ids": [ From afca7c9c0981cad2f0336a43c4a639ff3fcbb968 Mon Sep 17 00:00:00 2001 From: David Galey Date: Wed, 18 Mar 2026 17:32:07 -0400 Subject: [PATCH 09/13] change sync default start date to 1 year past --- globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs | 6 +++++- globalsign-mssl-caplugin/GlobalSignCAPlugin.cs | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs index 326caae..467bf6e 100644 --- a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs +++ b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs @@ -79,8 +79,12 @@ public async Task> GetCertificatesForSyncAsync( } else { - // incremental sync since lastSync + // incremental sync since lastSync, unless lastSync is earlier than startDate, then use that var from = lastSync; + if (from < startDate) + { + from = startDate; + } var to = DateTime.UtcNow; results.AddRange( diff --git a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs index ceb6f6b..13e0c4e 100644 --- a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs +++ b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs @@ -92,7 +92,7 @@ public async Task Synchronize(BlockingCollection blockin if (Config == null) throw new InvalidOperationException("Config is not initialized."); var apiClient = new GlobalSignApiClient(Config, Logger); - var fullSyncFrom = new DateTime(2000, 01, 01); + var fullSyncFrom = DateTime.UtcNow.AddYears(-1); if (!string.IsNullOrEmpty(Config.SyncStartDate)) fullSyncFrom = DateTime.Parse(Config.SyncStartDate); var syncFrom = lastSync; @@ -677,8 +677,8 @@ public Dictionary GetCAConnectorAnnotations() Comments = "If provided, full syncs will start at the specified date.", Hidden = false, - DefaultValue = "2000-01-01", - Type = "Integer" + DefaultValue = "", + Type = "String" }, [Constants.SYNCPRODUCTS] = new() { From 7ee3feefaa9c2e81632439895018556c1d1ed17b Mon Sep 17 00:00:00 2001 From: David Galey Date: Wed, 18 Mar 2026 17:34:49 -0400 Subject: [PATCH 10/13] Revert to months validity for now (globalsign will truncate at 200 days automatically) --- globalsign-mssl-caplugin/Constants.cs | 2 +- globalsign-mssl-caplugin/GlobalSignCAPlugin.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/globalsign-mssl-caplugin/Constants.cs b/globalsign-mssl-caplugin/Constants.cs index 3b1d8d9..67d5251 100644 --- a/globalsign-mssl-caplugin/Constants.cs +++ b/globalsign-mssl-caplugin/Constants.cs @@ -29,6 +29,6 @@ public static class EnrollmentConfigConstants { public const string RootCAType = "RootCAType"; public const string SlotSize = "SlotSize"; - public const string CertificateValidityInDays = "CertificateValidityInDays"; + public const string CertificateValidityInYears = "CertificateValidityInYears"; public const string MSSLProfileId = "MSSLProfileId"; } \ No newline at end of file diff --git a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs index 13e0c4e..45932da 100644 --- a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs +++ b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs @@ -702,11 +702,11 @@ public Dictionary GetTemplateParameterAnnotations() { return new Dictionary { - [EnrollmentConfigConstants.CertificateValidityInDays] = new() + [EnrollmentConfigConstants.CertificateValidityInYears] = new() { - Comments = "Number of days the certificate will be valid for", + Comments = "Number of years the certificate will be valid for", Hidden = false, - DefaultValue = "199", + DefaultValue = 1, Type = "Number" }, [EnrollmentConfigConstants.SlotSize] = new() From 55823bb942c19de73bbe757c7494fc4ba027635e Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Wed, 18 Mar 2026 21:36:41 +0000 Subject: [PATCH 11/13] Update generated docs --- README.md | 2 +- integration-manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3a6f6f6..32dc417 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ This extension uses the contact information of the GCC Domain point of contact f 4. In Keyfactor Command (v12.3+), for each imported Certificate Template, follow the [official documentation](https://software.keyfactor.com/Core-OnPrem/Current/Content/ReferenceGuide/Configuring%20Template%20Options.htm) to define enrollment fields for each of the following parameters: - * **CertificateValidityInDays** - Number of days the certificate will be valid for + * **CertificateValidityInYears** - Number of years the certificate will be valid for * **SlotSize** - Maximum number of SANs that a certificate may have - valid values are [FIVE, TEN, FIFTEEN, TWENTY, THIRTY, FOURTY, FIFTY, ONE_HUNDRED] * **RootCAType** - The certificate's root CA - Depending on certificate expiration date, SHA_1 not be allowed. Will default to SHA_2 if expiration date exceeds sha1 allowed date. Options are GlobalSign R certs. * **MSSLProfileId** - OPTIONAL: If specified, enrollments will use that profile ID for domain lookups. If not provided, domain lookup will be done based on the Common Name or first DNS SAN. Useful if your GlobalSign account has multiple domain objects with the same domain string, or subdomains (e.g. sub.test.com vs test.com). diff --git a/integration-manifest.json b/integration-manifest.json index 44f349b..b4f465d 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -72,8 +72,8 @@ ], "enrollment_config": [ { - "name": "CertificateValidityInDays", - "description": "Number of days the certificate will be valid for" + "name": "CertificateValidityInYears", + "description": "Number of years the certificate will be valid for" }, { "name": "SlotSize", From 1320855f4198eb5926d60b644e3645114991cc1c Mon Sep 17 00:00:00 2001 From: David Galey Date: Wed, 18 Mar 2026 17:46:30 -0400 Subject: [PATCH 12/13] Add ContactName to the template parameters --- globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs | 6 ++---- globalsign-mssl-caplugin/Constants.cs | 1 + globalsign-mssl-caplugin/GlobalSignCAPlugin.cs | 8 ++++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs index 467bf6e..ef4c468 100644 --- a/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs +++ b/globalsign-mssl-caplugin/Client/GlobalSignApiClient.cs @@ -54,10 +54,8 @@ public async Task> GetCertificatesForSyncAsync( var results = new List(); if (fullSync) { - // If startDate is before year 2000, treat it as “since the dawn of time” - var from = startDate > new DateTime(2000, 1, 1) - ? startDate - : DateTime.MinValue; + + var from = startDate; var finalStop = DateTime.UtcNow; // first window diff --git a/globalsign-mssl-caplugin/Constants.cs b/globalsign-mssl-caplugin/Constants.cs index 67d5251..dbbcb43 100644 --- a/globalsign-mssl-caplugin/Constants.cs +++ b/globalsign-mssl-caplugin/Constants.cs @@ -31,4 +31,5 @@ public static class EnrollmentConfigConstants public const string SlotSize = "SlotSize"; public const string CertificateValidityInYears = "CertificateValidityInYears"; public const string MSSLProfileId = "MSSLProfileId"; + public const string ContactName = "ContactName"; } \ No newline at end of file diff --git a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs index 45932da..d6ec046 100644 --- a/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs +++ b/globalsign-mssl-caplugin/GlobalSignCAPlugin.cs @@ -732,6 +732,14 @@ public Dictionary GetTemplateParameterAnnotations() Hidden = false, DefaultValue = null, Type = "String" + }, + [EnrollmentConfigConstants.ContactName] = new() + { + Comments = + "The name of the contact to use for enrollments. Can be specified here or via an Enrollment Field in Command. Enrollment Fields will override any value supplied here.", + Hidden = false, + DefaultValue = "", + Type = "String" } }; } From bd814bebddbc46b9ba3e0a7cbaf7ed23ffbcb1bb Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Wed, 18 Mar 2026 21:48:21 +0000 Subject: [PATCH 13/13] Update generated docs --- README.md | 1 + integration-manifest.json | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/README.md b/README.md index 32dc417..d58ec3f 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,7 @@ This extension uses the contact information of the GCC Domain point of contact f * **SlotSize** - Maximum number of SANs that a certificate may have - valid values are [FIVE, TEN, FIFTEEN, TWENTY, THIRTY, FOURTY, FIFTY, ONE_HUNDRED] * **RootCAType** - The certificate's root CA - Depending on certificate expiration date, SHA_1 not be allowed. Will default to SHA_2 if expiration date exceeds sha1 allowed date. Options are GlobalSign R certs. * **MSSLProfileId** - OPTIONAL: If specified, enrollments will use that profile ID for domain lookups. If not provided, domain lookup will be done based on the Common Name or first DNS SAN. Useful if your GlobalSign account has multiple domain objects with the same domain string, or subdomains (e.g. sub.test.com vs test.com). + * **ContactName** - The name of the contact to use for enrollments. Can be specified here or via an Enrollment Field in Command. Enrollment Fields will override any value supplied here. ## Valid GlobalSign SAN Usage diff --git a/integration-manifest.json b/integration-manifest.json index b4f465d..412b9e5 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -86,6 +86,10 @@ { "name": "MSSLProfileId", "description": "OPTIONAL: If specified, enrollments will use that profile ID for domain lookups. If not provided, domain lookup will be done based on the Common Name or first DNS SAN. Useful if your GlobalSign account has multiple domain objects with the same domain string, or subdomains (e.g. sub.test.com vs test.com)." + }, + { + "name": "ContactName", + "description": "The name of the contact to use for enrollments. Can be specified here or via an Enrollment Field in Command. Enrollment Fields will override any value supplied here." } ], "product_ids": [