diff --git a/README.md b/README.md
index bd13b56..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,19 +58,22 @@ 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:
-3. Copy the unzipped directory (usually called `net6.0`) to the Extensions directory:
```shell
+ Depending on your AnyCA Gateway REST version, copy the unzipped directory to one of the following locations:
Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net6.0\Extensions
+ Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net8.0\Extensions
```
- > The directory containing the Nameshield Gateway AnyCA Gateway REST plugin DLLs (`net6.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
diff --git a/integration-manifest.json b/integration-manifest.json
index f7d15ff..3511222 100644
--- a/integration-manifest.json
+++ b/integration-manifest.json
@@ -8,7 +8,8 @@
"update_catalog": false,
"description": "Nameshield plugin for the AnyCA REST Gateway framework",
"gateway_framework": "24.2.0",
- "release_dir": "nameshield-caplugin/bin/Release/net8.0",
+ "release_dir": "nameshield-caplugin/bin/Release",
+ "release_project": "nameshield-caplugin/nameshield-caplugin.csproj",
"about": {
"carest": {
"ca_plugin_config": [
diff --git a/nameshield-caplugin.sln b/nameshield-caplugin.sln
index c99563a..e345624 100644
--- a/nameshield-caplugin.sln
+++ b/nameshield-caplugin.sln
@@ -12,8 +12,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
integration-manifest.json = integration-manifest.json
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nameshield-testbed", "nameshield-testbed\nameshield-testbed.csproj", "{6A22BA99-5C36-4CFE-B807-64CD27652F3C}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -24,10 +22,6 @@ Global
{85906BEA-E3E6-413A-9E2C-6B9202449EC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85906BEA-E3E6-413A-9E2C-6B9202449EC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85906BEA-E3E6-413A-9E2C-6B9202449EC2}.Release|Any CPU.Build.0 = Release|Any CPU
- {6A22BA99-5C36-4CFE-B807-64CD27652F3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6A22BA99-5C36-4CFE-B807-64CD27652F3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6A22BA99-5C36-4CFE-B807-64CD27652F3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6A22BA99-5C36-4CFE-B807-64CD27652F3C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/nameshield-caplugin/API/RequestCertificate.cs b/nameshield-caplugin/API/RequestCertificate.cs
index c69e9c6..3825962 100644
--- a/nameshield-caplugin/API/RequestCertificate.cs
+++ b/nameshield-caplugin/API/RequestCertificate.cs
@@ -1,11 +1,13 @@
using Keyfactor.Extensions.CAPlugin.Nameshield.Models;
using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield.API
@@ -28,42 +30,62 @@ public CertificateRequest()
data.relationships.organization.data = new RelationshipData();
}
+ public string GetOrderData()
+ {
+ var orderData = new
+ {
+ data = data
+ };
+ return System.Text.Json.JsonSerializer.Serialize(orderData);
+ }
+
+
+ [JsonPropertyName("data")]
[JsonProperty("data")]
public CertificateRequestData data { get; set; }
}
public class CertificateRequestData
{
+ [JsonPropertyName("type")]
[JsonProperty("type")]
public string type { get; set; }
+ [JsonPropertyName("attributes")]
[JsonProperty("attributes")]
public CertificateRequestAttributes attributes { get; set; }
+ [JsonPropertyName("relationships")]
[JsonProperty("relationships")]
public CertificateRequestRelationships relationships { get; set; }
}
public class CertificateRequestAttributes
{
+ [JsonPropertyName("action")]
[JsonProperty("action")]
public string action { get; set; }
+ [JsonPropertyName("csr")]
[JsonProperty("csr")]
public string csr { get; set; }
+ [JsonPropertyName("duration")]
[JsonProperty("duration")]
public string duration { get; set; }
}
public class CertificateRequestRelationships
{
+ [JsonPropertyName("product")]
[JsonProperty("product")]
public CertRequestRel product { get; set; }
+ [JsonPropertyName("organization")]
[JsonProperty("organization")]
public CertRequestRel organization { get; set; }
}
public class CertRequestRel
{
+ [JsonPropertyName("data")]
[JsonProperty("data")]
public RelationshipData data { get; set; }
}
diff --git a/nameshield-caplugin/Client/NameshieldClient.cs b/nameshield-caplugin/Client/NameshieldClient.cs
index 6ff7d58..ea34c2b 100644
--- a/nameshield-caplugin/Client/NameshieldClient.cs
+++ b/nameshield-caplugin/Client/NameshieldClient.cs
@@ -13,6 +13,7 @@
using System.Linq;
using System.Net.Http.Json;
using System.Text;
+using System.Text.Json;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield.Client
@@ -40,8 +41,8 @@ public async Task ListOrganizations()
}
else
{
- var error = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
- throw new Exception($"Error retrieving organizations: {error.Error.Code} | {error.Error.Message}");
+ var errors = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
+ throw new Exception($"Error retrieving organizations: {errors.Errors[0].Title} | {errors.Errors[0].Detail}");
}
}
@@ -57,26 +58,42 @@ public async Task ListProducts()
}
else
{
- var error = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
- throw new Exception($"Error retrieving product list: {error.Error.Code} | {error.Error.Message}");
+ var errors = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
+ throw new Exception($"Error retrieving product list: {errors.Errors[0].Title} | {errors.Errors[0].Detail}");
}
}
public async Task ListCertificates()
{
- var response = await RestClient.GetAsync("ssl/v2/certificates?fields[certificate]=status,serial,pem");
- if (response.IsSuccessStatusCode)
- {
- string responseContent = await response.Content.ReadAsStringAsync();
- Logger.LogTrace($"GET Certificates response: {responseContent}");
- var responseObj = JsonConvert.DeserializeObject(responseContent);
- return new ListCertificatesResponse { Certificates = responseObj.Certificates };
- }
- else
- {
- var error = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
- throw new Exception($"Error retrieving certificate list: {error.Error.Code} | {error.Error.Message}");
- }
+ string url = "ssl/v2/certificates?fields[certificate]=status,serial,pem";
+ var response = await RestClient.GetAsync(url);
+ List certList = new List();
+ do
+ {
+ if (response.IsSuccessStatusCode)
+ {
+ string responseContent = await response.Content.ReadAsStringAsync();
+ Logger.LogTrace($"GET Certificates response: {responseContent}");
+ var responseObj = JsonConvert.DeserializeObject(responseContent);
+ certList.AddRange(responseObj.Certificates);
+ if (!string.IsNullOrEmpty(responseObj.Links.Next))
+ {
+ Uri uri = new Uri(responseObj.Links.Next);
+ url = uri.PathAndQuery.Substring(1); // remove the leading /
+ response = await RestClient.GetAsync(url);
+ }
+ else
+ {
+ url = null;
+ }
+ }
+ else
+ {
+ var errors = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
+ throw new Exception($"Error retrieving certificate list: {errors.Errors[0].Title} | {errors.Errors[0].Detail}");
+ }
+ } while (!string.IsNullOrEmpty(url));
+ return new ListCertificatesResponse { Certificates = certList };
}
public async Task GetCertificate(string ID)
@@ -91,8 +108,8 @@ public async Task GetCertificate(string ID)
}
else
{
- var error = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
- throw new Exception($"Error retrieving certificate: {error.Error.Code} | {error.Error.Message}");
+ var errors = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
+ throw new Exception($"Error retrieving certificate: {errors.Errors[0].Title} | {errors.Errors[0].Detail}");
}
}
@@ -108,14 +125,16 @@ public async Task GetCertificateProduct(string ID
}
else
{
- var error = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
- throw new Exception($"Error retrieving certificate product: {error.Error.Code} | {error.Error.Message}");
+ var errors = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
+ throw new Exception($"Error retrieving certificate product: {errors.Errors[0].Title} | {errors.Errors[0].Detail}");
}
}
public async Task RequestCertificate(CertificateRequest req)
{
- var response = await RestClient.PostAsJsonAsync("ssl/v2/orders", req);
+ var body = req.GetOrderData();
+ var content = new StringContent(body.ToString(), Encoding.UTF8, "application/json");
+ var response = await RestClient.PostAsync("ssl/v2/orders", content);
if (response.IsSuccessStatusCode)
{
string responseContent = await response.Content.ReadAsStringAsync();
@@ -125,8 +144,25 @@ public async Task RequestCertificate(CertificateRequ
}
else
{
- var error = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
- throw new Exception($"Error requesting certificate: {error.Error.Code} | {error.Error.Message}");
+ var errors = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
+ throw new Exception($"Error requesting certificate: {errors.Errors[0].Title} | {errors.Errors[0].Detail}");
+ }
+ }
+
+ 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}");
}
}
@@ -141,8 +177,8 @@ public async Task RevokeCertificate(string serialNum)
}
else
{
- var error = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
- throw new Exception($"Error revoking certificate: {error.Error.Code} | {error.Error.Message}");
+ var errors = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
+ throw new Exception($"Error revoking certificate: {errors.Errors[0].Title} | {errors.Errors[0].Detail}");
}
}
diff --git a/nameshield-caplugin/Models/Certificate.cs b/nameshield-caplugin/Models/Certificate.cs
index b519f0e..fe8b22b 100644
--- a/nameshield-caplugin/Models/Certificate.cs
+++ b/nameshield-caplugin/Models/Certificate.cs
@@ -6,38 +6,57 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield.Models
{
public class CertificateData
{
+ [JsonPropertyName("data")]
[JsonProperty("data")]
public Certificate Certificate { get; set; }
}
+ public class LinkData
+ {
+ [JsonPropertyName("next")]
+ [JsonProperty("next")]
+ public string Next { get; set; }
+ }
+
public class CertificatesData
{
+ [JsonPropertyName("data")]
[JsonProperty("data")]
public List Certificates { get; set; }
+
+ [JsonPropertyName("links")]
+ [JsonProperty("links")]
+ public LinkData Links { get; set; }
}
public class Certificate
{
+ [JsonPropertyName("id")]
[JsonProperty("id")]
public string Id { get; set; }
+ [JsonPropertyName("attributes")]
[JsonProperty("attributes")]
public CertificateAttributes Attributes { get; set; }
}
public class CertificateAttributes
{
+ [JsonPropertyName("status")]
[JsonProperty("status")]
public string Status { get; set; }
+ [JsonPropertyName("serial")]
[JsonProperty("serial")]
public string Serial { get; set; }
+ [JsonPropertyName("pem")]
[JsonProperty("pem")]
public string Pem { get; set; }
}
diff --git a/nameshield-caplugin/Models/CertificateProduct.cs b/nameshield-caplugin/Models/CertificateProduct.cs
index e12d65e..e27b69e 100644
--- a/nameshield-caplugin/Models/CertificateProduct.cs
+++ b/nameshield-caplugin/Models/CertificateProduct.cs
@@ -6,32 +6,40 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield.Models
{
public class CertificateProductData
{
+ [JsonPropertyName("data")]
[JsonProperty("data")]
public CertificateProduct CertificateProduct { get; set; }
}
public class CertificateProduct
{
+ [JsonPropertyName("id")]
[JsonProperty("id")]
public string Id { get; set; }
+ [JsonPropertyName("attributes")]
[JsonProperty("attributes")]
public CertificateProductAttributes Attributes { get; set; }
}
public class CertificateProductAttributes
{
+ [JsonPropertyName("name")]
[JsonProperty("name")]
public string Name { get; set; }
+ [JsonPropertyName("can_be_ordered")]
[JsonProperty("can_be_ordered")]
public bool CanBeOrdered { get; set; }
+ [JsonPropertyName("accept_reissue")]
[JsonProperty("accept_reissue")]
public bool CanReissue { get; set; }
+ [JsonPropertyName("allowed_durations")]
[JsonProperty("allowed_durations")]
public List Durations { get; set; }
}
diff --git a/nameshield-caplugin/Models/Error.cs b/nameshield-caplugin/Models/Error.cs
index c40f0da..cec487c 100644
--- a/nameshield-caplugin/Models/Error.cs
+++ b/nameshield-caplugin/Models/Error.cs
@@ -4,20 +4,27 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield.Models
{
public class ErrorData
{
+ [JsonPropertyName("errors")]
[JsonProperty("errors")]
- public Error Error { get; set; }
+ public List Errors { get; set; }
}
public class Error
{
- [JsonProperty("code")]
- public string Code { get; set; }
- [JsonProperty("message")]
- public string Message { get; set; }
+ [JsonPropertyName("status")]
+ [JsonProperty("status")]
+ public string Status { get; set; }
+ [JsonPropertyName("title")]
+ [JsonProperty("title")]
+ public string Title { get; set; }
+ [JsonPropertyName("detail")]
+ [JsonProperty("detail")]
+ public string Detail { get; set; }
}
}
diff --git a/nameshield-caplugin/Models/Order.cs b/nameshield-caplugin/Models/Order.cs
index db398b6..aff4d17 100644
--- a/nameshield-caplugin/Models/Order.cs
+++ b/nameshield-caplugin/Models/Order.cs
@@ -6,40 +6,48 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield.Models
{
public class OrderData
{
+ [JsonPropertyName("data")]
[JsonProperty("data")]
public Order Order { get; set; }
}
public class Order
{
+ [JsonPropertyName("id")]
[JsonProperty("id")]
public string Id { get; set; }
+ [JsonPropertyName("attributes")]
[JsonProperty("attributes")]
public OrderAttributes Attributes { get; set; }
+ [JsonPropertyName("relationships")]
[JsonProperty("relationships")]
public OrderRelationships Relationships { get; set; }
}
public class OrderAttributes
{
+ [JsonPropertyName("status")]
[JsonProperty("status")]
public string Status { get; set; }
}
public class OrderRelationships
{
+ [JsonPropertyName("certificate")]
[JsonProperty("certificate")]
public OrderCertRelationship Certificate { get; set; }
}
public class OrderCertRelationship
{
+ [JsonPropertyName("data")]
[JsonProperty("data")]
public RelationshipData Data { get; set; }
}
diff --git a/nameshield-caplugin/Models/Organizations.cs b/nameshield-caplugin/Models/Organizations.cs
index d2db538..45f51cf 100644
--- a/nameshield-caplugin/Models/Organizations.cs
+++ b/nameshield-caplugin/Models/Organizations.cs
@@ -4,26 +4,31 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield.Models
{
public class OrganizationData
{
+ [JsonPropertyName("data")]
[JsonProperty("data")]
public List Organizations { get; set; }
}
public class Organization
{
+ [JsonPropertyName("id")]
[JsonProperty("id")]
public string Id { get; set; }
+ [JsonPropertyName("attributes")]
[JsonProperty("attributes")]
public OrganizationAttributes Attributes { get; set; }
}
public class OrganizationAttributes
{
+ [JsonPropertyName("name")]
[JsonProperty("name")]
public string Name { get; set; }
}
diff --git a/nameshield-caplugin/Models/Products.cs b/nameshield-caplugin/Models/Products.cs
index 2b77bdb..50a7399 100644
--- a/nameshield-caplugin/Models/Products.cs
+++ b/nameshield-caplugin/Models/Products.cs
@@ -4,32 +4,40 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield.Models
{
public class ProductsData
{
+ [JsonPropertyName("data")]
[JsonProperty("data")]
public List Products { get; set; }
}
public class Product
{
+ [JsonPropertyName("id")]
[JsonProperty("id")]
public string Id { get; set; }
+ [JsonPropertyName("attributes")]
[JsonProperty("attributes")]
public ProductAttributes Attributes { get; set; }
}
public class ProductAttributes
{
+ [JsonPropertyName("name")]
[JsonProperty("name")]
public string Name { get; set; }
+ [JsonPropertyName("can_be_ordered")]
[JsonProperty("can_be_ordered")]
public bool CanBeOrdered { get; set; }
+ [JsonPropertyName("accept_reissue")]
[JsonProperty("accept_reissue")]
public bool CanReissue { get; set; }
+ [JsonPropertyName("allowed_durations")]
[JsonProperty("allowed_durations")]
public List Durations { get; set; }
}
diff --git a/nameshield-caplugin/Models/Relationship.cs b/nameshield-caplugin/Models/Relationship.cs
index 30ae6e0..f5a7ced 100644
--- a/nameshield-caplugin/Models/Relationship.cs
+++ b/nameshield-caplugin/Models/Relationship.cs
@@ -4,15 +4,18 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield.Models
{
public class RelationshipData
{
+ [JsonPropertyName("type")]
[JsonProperty("type")]
public string type { get; set; }
+ [JsonPropertyName("id")]
[JsonProperty("id")]
public string id { get; set; }
}
diff --git a/nameshield-caplugin/NameshieldCAPlugin.cs b/nameshield-caplugin/NameshieldCAPlugin.cs
index eff347c..cd7714b 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,15 +112,28 @@ public async Task Enroll(string csr, string subject, Dictionar
{
throw new Exception($"Certificate request for subect {subject} was rejected");
}
- else if (!string.Equals(status, "handled", StringComparison.OrdinalIgnoreCase))
+ int time = 1;
+ while (string.Equals(status, "checked_out", StringComparison.OrdinalIgnoreCase) && time <= 10)
+ {
+ _logger.LogTrace($"Cert request returned CHECKED_OUT status, rechecking in 5 seconds. Pickup attempt {time} of 10");
+ // Sleep for 5 seconds then try again, up to a max of 10 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.Relationships.Certificate.Data.id,
+ CARequestID = response.Order.Id,
Status = (int)EndEntityStatus.EXTERNALVALIDATION,
StatusMessage = "Certificate is pending issuance and will be picked up by a future sync."
};
}
+ _logger.LogTrace($"Certificate enrolled successfully");
var cert = GetSingleRecord(response.Order.Relationships.Certificate.Data.id).Result;
diff --git a/nameshield-caplugin/NameshieldConfig.cs b/nameshield-caplugin/NameshieldConfig.cs
index cf38e10..868c0ea 100644
--- a/nameshield-caplugin/NameshieldConfig.cs
+++ b/nameshield-caplugin/NameshieldConfig.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Keyfactor.Extensions.CAPlugin.Nameshield
@@ -12,12 +13,15 @@ public class NameshieldConfig
{
public NameshieldConfig() { }
+ [JsonPropertyName("ApiUrl")]
[JsonProperty("ApiUrl")]
public string ApiUrl { get; set; }
+ [JsonPropertyName("ApiToken")]
[JsonProperty("ApiToken")]
public string ApiToken { get; set; }
+ [JsonPropertyName("Enabled")]
[JsonProperty("Enabled")]
public bool Enabled { get; set; } = true;
}
diff --git a/nameshield-caplugin/nameshield-caplugin.csproj b/nameshield-caplugin/nameshield-caplugin.csproj
index 2ff43f5..054f6a7 100644
--- a/nameshield-caplugin/nameshield-caplugin.csproj
+++ b/nameshield-caplugin/nameshield-caplugin.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net6.0
Keyfactor.Extensions.CAPlugin.Nameshield
enable
disable
diff --git a/nameshield-testbed/Program.cs b/nameshield-testbed/Program.cs
deleted file mode 100644
index cacc900..0000000
--- a/nameshield-testbed/Program.cs
+++ /dev/null
@@ -1,132 +0,0 @@
-// See https://aka.ms/new-console-template for more information
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.Net.Http;
-using System.Text;
-using System.Threading.Tasks;
-
-public class Program
-{
- public static async Task Main(string[] args)
- {
- using (var client = new HttpClient())
- {
- client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "21cee8c3-b472-443e-ba47-1fbac18d7b7e");
-
- ListOrgs(client);
- //OrderCertificate(client);
- }
- Console.ReadLine();
- Console.WriteLine("Hello, World!");
- }
-
- public static void ListOrgs(HttpClient client)
- {
- var response = client.GetAsync("https://ote-api.nameshield.net/ssl/v2/organizations").Result;
- if (response.IsSuccessStatusCode)
- {
- var responseBody = response.Content.ReadAsStringAsync().Result;
-
- var responseObj = JsonConvert.DeserializeObject(responseBody);
- Console.WriteLine(responseBody);
- }
- else
- {
- Console.WriteLine($"Error: {response.StatusCode}");
- var errorContent = response.Content.ReadAsStringAsync().Result;
- var errorObj = JsonConvert.DeserializeObject(errorContent);
- Console.WriteLine(errorContent);
- }
- }
-
-
- public class ErrorData
- {
- [JsonProperty("errors")]
- public Error Error { get; set; }
- }
- public class Error
- {
- [JsonProperty("code")]
- public string Code { get; set; }
- [JsonProperty("message")]
- public string Message { get; set; }
- }
-
- public class OrganizationData
- {
- [JsonProperty("data")]
- public List Organizations { get; set; }
- }
-
- public class Organization
- {
- [JsonProperty("id")]
- public string Id { get; set; }
- [JsonProperty("attributes")]
- public OrganizationAttributes Attributes { get; set; }
- }
-
- public class OrganizationAttributes
- {
- [JsonProperty("name")]
- public string Name { get; set; }
- }
-
- public static async void OrderCertificate(HttpClient client)
- {
- var orderData = new JObject
- {
- ["data"] = new JObject
- {
- ["type"] = "order",
- ["attributes"] = new JObject
- {
- ["action"] = "create",
- ["csr"] = "-----BEGIN CERTIFICATE REQUEST-----MIICdjCCAV4CAQAwMTESMBAGA1UECgwJS2V5ZmFjdG9yMRswGQYDVQQDDBJrZXlmYWN0b3IudGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCENsFrFWrbrrVOr5XcO+yGBo4i5lGTyGNIqs1Thd0XwSRNXEHIKeQQsMbFK+vBGBCt66g6+5I60MkYbqItM5B5JlQJ79ChZu/Bb1WSNObf9Ie0T7olPUEUNecvjeHIREVWO1XdIM/eDkXIFfJykf0wJM1oAQbmhUVD2MYcbTCnc5GDWjWA2W3D2wHaK5eX8oTaEG/KwS9IttIxpuIHKyHlrPGDNzUrO3Ztbk2YyJ7EW6jJoIyzZpNQtQ+o5JVjfD5Q4vrPokmWolR2B+NwzmkNB2fA538UpZZGaedVTYHgKSpUCJGIJ+TSiywO784/LmWt52ji4452BmW6XXlPb5m3AgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAOr+RROgM7YEMECD9ukTQ7uFjs09wEP8ZLXbgAlscnGtQzINjJkawCyx7CidQZz0FISBdc1YjUgBCKzfHiecYrR1FpHi+HwuvK1obbxqDz3xKZ3GW8paeNyXq6wFtAGKF4DSpeTpOnkg1Ydlh3vegT5FOXakA3g51wiRy9LquV0jNb8yL9FbvhOLG/XRDcAZ45rH9S9BwMY95o7xsmOOcZVcuCsHaQGFPM5h8VgQqAOLeRMC1tpzCRqg12yp+bbHd6yb4nNiAPSm1o+2iItDfkA+7kbA7o04JDRhFN+Oy/m5IHzyDStnhgENja3duVnK1nevLNj+pdKDm6n9FIieGjw==-----END CERTIFICATE REQUEST-----",
- ["duration"] = "2 years",
- },
- ["relationships"] = new JObject
- {
- ["product"] = new JObject
- {
- ["data"] = new JObject
- {
- ["type"] = "product",
- ["id"] = "11"
- }
- },
- ["organization"] = new JObject
- {
- ["data"] = new JObject
- {
- ["type"] = "organization",
- ["id"] = "BSVBG"
- }
- }
- }
- }
- };
-
- var content = new StringContent(orderData.ToString(), Encoding.UTF8, "application/json");
- Console.WriteLine(content.ReadAsStringAsync().Result);
- var response = await client.PostAsync("https://ote-api.nameshield.net/ssl/v2/orders", content);
-
- if (response.IsSuccessStatusCode)
- {
- var responseBody = await response.Content.ReadAsStringAsync();
- Console.WriteLine(responseBody);
-
- }
- else
- {
- Console.WriteLine($"Error: {response.StatusCode}");
- var errorContent = await response.Content.ReadAsStringAsync();
- Console.WriteLine(errorContent);
- }
- }
-}
diff --git a/nameshield-testbed/nameshield-testbed.csproj b/nameshield-testbed/nameshield-testbed.csproj
deleted file mode 100644
index 7242ecf..0000000
--- a/nameshield-testbed/nameshield-testbed.csproj
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- Exe
- net8.0
- nameshield_testbed
- disable
- enable
-
-
-
-
-
-
-