From 875cbe8d32d170951e6e66936172fd6c0536a2c2 Mon Sep 17 00:00:00 2001 From: David Galey Date: Wed, 2 Sep 2026 08:21:19 -0400 Subject: [PATCH 1/2] recheck status for checked_out orders --- .../Client/NameshieldClient.cs | 17 +++++++++++++++ nameshield-caplugin/NameshieldCAPlugin.cs | 21 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/nameshield-caplugin/Client/NameshieldClient.cs b/nameshield-caplugin/Client/NameshieldClient.cs index e5de62e..ea34c2b 100644 --- a/nameshield-caplugin/Client/NameshieldClient.cs +++ b/nameshield-caplugin/Client/NameshieldClient.cs @@ -149,6 +149,23 @@ public async Task RequestCertificate(CertificateRequ } } + public async Task GetOrderDetails(string reqId) + { + var response = await RestClient.GetAsync($"ssl/v2/orders/{reqId}"); + if (response.IsSuccessStatusCode) + { + string responseContent = await response.Content.ReadAsStringAsync(); + Logger.LogTrace($"GET Order Details response: {responseContent}"); + var responseObj = JsonConvert.DeserializeObject(responseContent); + return new RequestCertificateResponse { Order = responseObj.Order }; + } + else + { + var errors = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + throw new Exception($"Error pulling order details: {errors.Errors[0].Title} | {errors.Errors[0].Detail}"); + } + } + public async Task RevokeCertificate(string serialNum) { var response = await RestClient.PostAsync($"ssl/v2/certificates/{serialNum}/revoke", null); diff --git a/nameshield-caplugin/NameshieldCAPlugin.cs b/nameshield-caplugin/NameshieldCAPlugin.cs index 3aca18f..6469690 100644 --- a/nameshield-caplugin/NameshieldCAPlugin.cs +++ b/nameshield-caplugin/NameshieldCAPlugin.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.Metrics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -37,14 +38,17 @@ public void Initialize(IAnyCAPluginConfigProvider configProvider, ICertificateDa public async Task Enroll(string csr, string subject, Dictionary san, EnrollmentProductInfo productInfo, RequestFormat requestFormat, EnrollmentType enrollmnentType) { + _logger.MethodEntry(LogLevel.Debug); NameshieldClient client = NameshieldClient.InitializeClient(_config); var allProducts = Task.Run(async () => await client.ListProducts()).Result; + _logger.LogTrace($"Found {allProducts.Products.Count} products"); string productId = null; foreach (var product in allProducts.Products) { if (string.Equals(product.Attributes.Name, productInfo.ProductID)) { + _logger.LogTrace($"Found {productInfo.ProductID} product, using ID {product.Id}"); productId = product.Id; break; } @@ -58,6 +62,7 @@ public async Task Enroll(string csr, string subject, Dictionar if (productInfo.ProductParameters.ContainsKey(Constants.Config.Template.ORGANIZATION_ID) && !string.IsNullOrEmpty(productInfo.ProductParameters[Constants.Config.Template.ORGANIZATION_ID])) { orgId = productInfo.ProductParameters[Constants.Config.Template.ORGANIZATION_ID]; + _logger.LogTrace($"Using organization ID {orgId}"); } if (string.IsNullOrEmpty(orgId)) @@ -72,10 +77,12 @@ public async Task Enroll(string csr, string subject, Dictionar orgName = ParseSubject(subject, "O="); } var organizations = Task.Run(async () => await client.ListOrganizations()).Result; + _logger.LogTrace($"Found {organizations.Organizations.Count} organizations"); foreach (var organization in organizations.Organizations) { if (string.Equals(organization.Attributes.Name, orgName, StringComparison.OrdinalIgnoreCase)) { + _logger.LogTrace($"Found organization with name {orgName}, using ID {organization.Id}"); orgId = organization.Id; break; } @@ -105,8 +112,20 @@ public async Task Enroll(string csr, string subject, Dictionar { throw new Exception($"Certificate request for subect {subject} was rejected"); } - else if (!string.Equals(status, "delivered", StringComparison.OrdinalIgnoreCase)) + int time = 0; + while (string.Equals(status, "checked_out", StringComparison.OrdinalIgnoreCase) && time < 8) + { + _logger.LogTrace($"Cert retured CHECKED_OUT status, rechecking in 5 seconds. Pickup attempt {time} of 8"); + // Sleep for 5 seconds then try again, up to a max of 8 tries + Thread.Sleep(5000); + time++; + response = Task.Run(async () => await client.GetOrderDetails(response.Order.Id)).Result; + status = response.Order.Attributes.Status; + } + + if (!string.Equals(status, "delivered", StringComparison.OrdinalIgnoreCase)) { + _logger.LogTrace($"Cert request submitted successfully but not delivered, will be picked up by a fugure sync once it is issued."); return new EnrollmentResult { CARequestID = response.Order.Id, From 6bef37bc6b89a92fb946f055e5f4161e6fef275a Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Wed, 2 Sep 2026 12:22:55 +0000 Subject: [PATCH 2/2] Update generated docs --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index dcd2509..0bfb158 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- Nameshield Gateway AnyCA Gateway REST Plugin + Nameshield AnyCA Gateway REST Plugin

@@ -43,10 +43,10 @@ The Nameshield AnyCA Gateway REST plugin extends the capabilities of Nameshield ## Compatibility -The Nameshield Gateway AnyCA Gateway REST plugin is compatible with the Keyfactor AnyCA Gateway REST 24.2.0 and later. +The Nameshield AnyCA Gateway REST plugin is compatible with the Keyfactor AnyCA Gateway REST 24.2.0 and later. ## Support -The Nameshield Gateway AnyCA Gateway REST plugin is open source and community supported, meaning that there is **no SLA** applicable. +The Nameshield AnyCA Gateway REST plugin is open source and community supported, meaning that there is **no SLA** applicable. > 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. @@ -58,7 +58,7 @@ TODO Requirements is a required section 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 [Nameshield Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/nameshield-caplugin/releases/latest) from GitHub. +2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [Nameshield AnyCA Gateway REST plugin](https://github.com/Keyfactor/nameshield-caplugin/releases/latest) from GitHub. 3. Copy the unzipped directory (usually called `net6.0` or `net8.0`) to the Extensions directory: @@ -69,11 +69,11 @@ TODO Requirements is a required section Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net8.0\Extensions ``` - > The directory containing the Nameshield 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 Nameshield 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 Nameshield 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 Nameshield plugin by hovering over the ⓘ symbol to the right of the Gateway on the top left of the portal. ## Configuration