Skip to content
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<p align="center">
<!-- Badges -->
<img src="https://img.shields.io/badge/integration_status-pilot-3D1973?style=flat-square" alt="Integration Status: pilot" />
<img src="https://img.shields.io/badge/integration_status-production-3D1973?style=flat-square" alt="Integration Status: production" />
<a href="https://github.com/Keyfactor/cscglobal-caplugin/releases"><img src="https://img.shields.io/github/v/release/Keyfactor/cscglobal-caplugin?style=flat-square" alt="Release" /></a>
<img src="https://img.shields.io/github/issues/Keyfactor/cscglobal-caplugin?style=flat-square" alt="Issues" />
<img src="https://img.shields.io/github/downloads/Keyfactor/cscglobal-caplugin/total?style=flat-square&label=downloads&color=28B905" alt="GitHub Downloads (all assets, all releases)" />
Expand Down
15 changes: 4 additions & 11 deletions cscglobal-caplugin.Tests/CSCGlobalCAPluginTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,10 @@ public async Task Enroll_RenewOrReissue_NullExpirationDate_FallsBackToGetSingleR
var result = await plugin.Enroll("csr", "CN=test", new Dictionary<string, string[]>(), productInfo,
RequestFormat.PKCS10, EnrollmentType.RenewOrReissue);

Assert.Equal((int)EndEntityStatus.EXTERNALVALIDATION, result!.Status);
mockClient.Verify(c => c.SubmitReissueAsync(It.IsAny<ReissueRequest>()), Times.Once);
}

[Fact]
public void GetProductIds_ReturnsCanonicalAndLegacyNames()
{
Expand Down Expand Up @@ -1165,17 +1169,6 @@ public void GetTemplateParameterAnnotations_ContainsExpectedKeys()
Assert.Contains(EnrollmentConfigConstants.AdditionalSansCommaSeparatedDcvEmails, annotations.Keys);
}

[Fact]
public void GetProductIds_ReturnsFullList()
{
var plugin = MakePlugin();
var ids = plugin.GetProductIds();

Assert.Equal(10, ids.Count);
Assert.Contains("CSC TrustedSecure OV", ids);
Assert.Contains("CSC TrustedSecure DV Wildcard, Multiple Names", ids);
}

// ---------------------------------------------------------------------
// GetEndEntityCertificate
// ---------------------------------------------------------------------
Expand Down
6 changes: 3 additions & 3 deletions cscglobal-caplugin.Tests/RequestManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,8 @@ public void MapReturnStatus_MapsExpectedStatus(string? cscStatus, int expected)
[InlineData("CSC TrustedSecure UC Certificate", "2", true, false)]
[InlineData("CSC TrustedSecure EV Certificate", "3", false, true)]
[InlineData("CSC TrustedSecure Domain Validated SSL", "4", false, false)]
[InlineData("CSC TrustedSecure Domain Validated Wildcard SSL", "5", false, false)]
[InlineData("CSC TrustedSecure Domain Validated UC Certificate", "6", true, false)]
[InlineData("CSC Trusted Secure Domain Validated Wildcard SSL", "5", false, false)]
[InlineData("CSC Trusted Secure Domain Validated UC Certificate", "6", true, false)]
public void GetRegistrationRequest_RoutesCertificateTypeAndOptionalSections(
string productId, string expectedType, bool expectSans, bool expectEv)
{
Expand Down Expand Up @@ -684,7 +684,7 @@ public void GetRenewalRequest_LegacyProductName_ResolvesCertificateTypeAndSans()
// A Certificate Template in Command created before the 1.2.0 rename still carries the
// old product name; renewals against it must resolve the same as the canonical name.
var sans = new Dictionary<string, string[]> { ["dnsname"] = new[] { "www.example.com" } };
var productInfo = ProductInfo("CSC TrustedSecure Domain Validated UC Certificate", new Dictionary<string, string>
var productInfo = ProductInfo("CSC Trusted Secure Domain Validated UC Certificate", new Dictionary<string, string>
{
["Domain Control Validation Method"] = "CNAME"
});
Expand Down
31 changes: 31 additions & 0 deletions cscglobal-caplugin/RequestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ public class RequestManager
public static Func<string, string> Pemify = ss =>
ss.Length <= 64 ? ss : ss.Substring(0, 64) + "\n" + Pemify(ss.Substring(64));

// Certificate type codes (see ProductIdToCodeMap below) that carry multiple names
// and therefore need SubjectAlternativeNames populated on the registration request.
private static readonly HashSet<string> MultiNameCertificateTypes = new() { "2", "6", "7", "8", "9" };

// Certificate type codes that require EvCertificateDetails (Organization Country, etc.).
private static readonly HashSet<string> EvCertificateTypes = new() { "3", "7" };

private static string GetOptionalParam(EnrollmentProductInfo productInfo, string key)
{
return productInfo.ProductParameters != null &&
Expand Down Expand Up @@ -322,13 +329,37 @@ public RegistrationRequest GetRegistrationRequest(EnrollmentProductInfo productI
};
}

// Maps each canonical (1.2.0+) product ID to the numeric certificate type code CSC's API
// expects on enrollment. Order matches ProductIDs.productIds in Constants.cs.
private static readonly Dictionary<string, string> ProductIdToCodeMap = new(StringComparer.OrdinalIgnoreCase)
{
["CSC TrustedSecure OV"] = "0",
["CSC TrustedSecure OV Wildcard"] = "1",
["CSC TrustedSecure OV, Multiple Names"] = "2",
["CSC TrustedSecure EV"] = "3",
["CSC TrustedSecure DV"] = "4",
["CSC TrustedSecure DV Wildcard"] = "5",
["CSC TrustedSecure DV, Multiple Names"] = "6",
["CSC TrustedSecure EV, Multiple Names"] = "7",
["CSC TrustedSecure OV Wildcard, Multiple Names"] = "8",
["CSC TrustedSecure DV Wildcard, Multiple Names"] = "9"
};

private string GetCertificateType(string productId)
{
if (productId != null && ProductIDs.legacyProductIdAliases.TryGetValue(productId, out var canonicalProductId))
{
productId = canonicalProductId;
}

if (productId != null && ProductIdToCodeMap.TryGetValue(productId, out var code))
{
return code;
}

return "-1";
}

public Notifications GetNotifications(EnrollmentProductInfo productInfo)
{
var notificationEmails = GetOptionalParam(productInfo, "Notification Email(s) Comma Separated");
Expand Down