From c65312290f346167026b92c3a2c26b96604e8300 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Fri, 7 Nov 2025 18:56:43 +0000 Subject: [PATCH 1/5] Update generated docs --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3ad40df..aa73d9a 100644 --- a/README.md +++ b/README.md @@ -55,13 +55,16 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and 2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [CSCGlobal CA Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/cscglobal-caplugin/releases/latest) from GitHub. -3. Copy the unzipped directory (usually called `net6.0`) to the Extensions directory: +3. Copy the unzipped directory (usually called `net6.0` or `net8.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 CSCGlobal CA 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 CSCGlobal CA 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. 4. Restart the AnyCA Gateway REST service. From 7a5f1586558a09ee9b3bfc1c6bfadd3547a1d971 Mon Sep 17 00:00:00 2001 From: Mark Kachkaev Date: Fri, 7 Nov 2025 13:58:01 -0500 Subject: [PATCH 2/5] Fix for issues with --- cscglobal-caplugin.sln | 6 + cscglobal-caplugin/CSCGlobalCAPlugin.cs | 251 +++++++++++++++--- cscglobal-caplugin/CSCGlobalCAPlugin.csproj | 35 ++- cscglobal-caplugin/Client/CscGlobalClient.cs | 18 +- cscglobal-caplugin/Client/Models/CName.cs | 1 + .../Client/Models/CertificateListResponse.cs | 2 +- .../Client/Models/CertificateResponse.cs | 1 + .../Client/Models/CustomField.cs | 1 + cscglobal-caplugin/Client/Models/DcvDetail.cs | 1 + .../Client/Models/DomainControlValidation.cs | 1 + .../Client/Models/EvCertificateDetails.cs | 1 + .../Client/Models/GetCustomField.cs | 22 ++ cscglobal-caplugin/Client/Models/Meta.cs | 1 + .../Client/Models/Notifications.cs | 1 + cscglobal-caplugin/Client/Models/Price.cs | 1 + .../Client/Models/RegistrationError.cs | 1 + .../Client/Models/RegistrationRequest.cs | 1 + .../Client/Models/RegistrationResponse.cs | 1 + .../Client/Models/ReissueRequest.cs | 1 + .../Client/Models/ReissueResponse.cs | 1 + .../Client/Models/RenewalRequest.cs | 1 + .../Client/Models/RenewalResponse.cs | 1 + cscglobal-caplugin/Client/Models/Result.cs | 1 + .../Client/Models/RevokeResponse.cs | 1 + .../Client/Models/RevokeSuccessResponse.cs | 1 + cscglobal-caplugin/Client/Models/Status.cs | 1 + .../Client/Models/SubjectAlternativeName.cs | 1 + cscglobal-caplugin/Constants.cs | 3 - .../Exceptions/RetryCountExceededException.cs | 1 + cscglobal-caplugin/Interfaces/ICName.cs | 1 + .../Interfaces/ICertificateListResponse.cs | 1 + .../Interfaces/ICertificateResponse.cs | 1 + .../Interfaces/ICscGlobalClient.cs | 3 + cscglobal-caplugin/Interfaces/ICustomField.cs | 1 + cscglobal-caplugin/Interfaces/IDcvDetail.cs | 1 + .../Interfaces/IDomainControlValidation.cs | 1 + .../Interfaces/IEvCertificateDetails.cs | 1 + .../Interfaces/IGetCustomField.cs | 14 + cscglobal-caplugin/Interfaces/IMeta.cs | 1 + .../Interfaces/INotifications.cs | 1 + cscglobal-caplugin/Interfaces/IPrice.cs | 1 + .../Interfaces/IRegistrationError.cs | 1 + .../Interfaces/IRegistrationRequest.cs | 1 + .../Interfaces/IRegistrationResponse.cs | 1 + .../Interfaces/IReissueRequest.cs | 1 + .../Interfaces/IReissueResponse.cs | 1 + .../Interfaces/IRenewalRequest.cs | 1 + .../Interfaces/IRenewalResponse.cs | 1 + cscglobal-caplugin/Interfaces/IResult.cs | 1 + .../Interfaces/IRevokeResponse.cs | 1 + cscglobal-caplugin/Interfaces/IStatus.cs | 1 + .../Interfaces/ISubjectAlternativeName.cs | 1 + cscglobal-caplugin/RequestManager.cs | 26 +- 53 files changed, 357 insertions(+), 66 deletions(-) create mode 100644 cscglobal-caplugin/Client/Models/GetCustomField.cs create mode 100644 cscglobal-caplugin/Interfaces/IGetCustomField.cs diff --git a/cscglobal-caplugin.sln b/cscglobal-caplugin.sln index e2a4e0e..05ae344 100644 --- a/cscglobal-caplugin.sln +++ b/cscglobal-caplugin.sln @@ -5,6 +5,12 @@ VisualStudioVersion = 17.11.35327.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSCGlobalCAPlugin", "cscglobal-caplugin\CSCGlobalCAPlugin.csproj", "{01DDFD6F-275D-46E7-B522-E0C965D1BF9C}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" + ProjectSection(SolutionItems) = preProject + CHANGELOG.md = CHANGELOG.md + integration-manifest.json = integration-manifest.json + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/cscglobal-caplugin/CSCGlobalCAPlugin.cs b/cscglobal-caplugin/CSCGlobalCAPlugin.cs index 70ced27..0c3bfc0 100644 --- a/cscglobal-caplugin/CSCGlobalCAPlugin.cs +++ b/cscglobal-caplugin/CSCGlobalCAPlugin.cs @@ -5,14 +5,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Net.Http; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Threading; -using System.Threading.Tasks; using Keyfactor.AnyGateway.Extensions; using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client; using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; @@ -22,7 +14,11 @@ using Keyfactor.PKI.X509; using Microsoft.Extensions.Logging; using Newtonsoft.Json; -using Org.BouncyCastle.Pqc.Crypto.Lms; +using System.Collections.Concurrent; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Text.RegularExpressions; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal; @@ -64,7 +60,7 @@ public async Task GetSingleRecord(string caRequestID) var certificateResponse = Task.Run(async () => await CscGlobalClient.SubmitGetCertificateAsync(keyfactorCaId)) .Result; - + Logger.LogTrace($"Single Cert JSON: {JsonConvert.SerializeObject(certificateResponse)}"); var fileContent = @@ -120,8 +116,8 @@ public async Task Synchronize(BlockingCollection blockin if (EnableTemplateSync) productId = currentResponseItem?.CertificateType; var fileContent = - Encoding.ASCII.GetString( - Convert.FromBase64String(currentResponseItem?.Certificate ?? string.Empty)); + PreparePemTextFromApi( + currentResponseItem?.Certificate ?? string.Empty); if (fileContent.Length > 0) { @@ -176,7 +172,8 @@ await CscGlobalClient.SubmitRevokeCertificateAsync(caRequestID.Substring(0, 36)) if (revokeResult == (int)EndEntityStatus.FAILED) if (!string.IsNullOrEmpty(revokeResponse?.RegistrationError?.Description)) - throw new HttpRequestException($"Revoke Failed with message {revokeResponse?.RegistrationError?.Description}"); + throw new HttpRequestException( + $"Revoke Failed with message {revokeResponse?.RegistrationError?.Description}"); return revokeResult; } @@ -203,6 +200,8 @@ public async Task Enroll(string csr, string subject, Dictionar } string uUId; + var customFields = await CscGlobalClient.SubmitGetCustomFields(); + switch (enrollmentType) { case EnrollmentType.New: @@ -394,37 +393,177 @@ public List GetProductIds() #region PRIVATE - //potential issues - private string GetEndEntityCertificate(string certData) + //Trying to fix leaf extraction + private static readonly Regex PemBlock = new( + "-----BEGIN CERTIFICATE-----\\s*(?[A-Za-z0-9+/=\\r\\n]+?)\\s*-----END CERTIFICATE-----", + RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.Singleline); + + private static readonly Regex Ws = new("\\s+", RegexOptions.Compiled); + + /// + /// Returns the end-entity certificate as Base64 DER (no PEM headers), or "" if none could be found. + /// + public string GetEndEntityCertificate(string pemChain) + { + if (string.IsNullOrWhiteSpace(pemChain)) + { + Logger.LogWarning("Empty PEM input."); + return string.Empty; + } + + // 1) Extract certs block-by-block, ignoring any garbage outside of valid fences. + var certs = ExtractCertificates(pemChain); + if (certs.Count == 0) + { + Logger.LogWarning("No valid certificate blocks found in input."); + return string.Empty; + } + + // 2) Pick the leaf (end-entity). + var leaf = FindLeaf(certs); + if (leaf is null) + { + Logger.LogWarning("Could not determine end-entity certificate from the provided chain."); + return string.Empty; + } + + try + { + // 3) Export to DER and Base64 (no headers). + byte[] der = leaf.Export(X509ContentType.Cert); + string b64 = Convert.ToBase64String(der); + Logger.LogTrace("End-entity certificate exported successfully."); + return b64; + } + catch (Exception ex) + { + Logger.LogError(ex, "Failed to export end-entity certificate."); + return string.Empty; + } + finally + { + // Dispose everything we created. + foreach (var c in certs) c.Dispose(); + } + } + + private List ExtractCertificates(string pem) + { + var results = new List(); + + foreach (Match m in PemBlock.Matches(pem)) + { + string b64 = m.Groups["b64"].Value; + if (string.IsNullOrWhiteSpace(b64)) + { + Logger.LogTrace("Skipping empty PEM block."); + continue; + } + + // Normalize: remove all whitespace and non-base64 spacers that sometimes creep in + b64 = Ws.Replace(b64, string.Empty); + + // Strict Base64 decode with validation. + try + { + // Convert.TryFromBase64String is fast and avoids temporary arrays when possible + if (!Convert.TryFromBase64String(b64, new Span(new byte[GetDecodedLength(b64)]), out int bytesWritten)) + { + // Fallback to FromBase64String to trigger a clear exception path + var discard = Convert.FromBase64String(b64); + bytesWritten = discard.Length; // unreachable if invalid + } + + byte[] der = Convert.FromBase64String(b64); + var cert = new X509Certificate2(der); + results.Add(cert); + Logger.LogTrace($"Imported certificate: Subject='{cert.Subject}', Issuer='{cert.Issuer}'"); + } + catch (FormatException fex) + { + Logger.LogWarning(fex, "Invalid Base64 inside a PEM block; skipping this block."); + } + catch (CryptographicException cex) + { + Logger.LogWarning(cex, "DER payload failed to parse as X509; skipping this block."); + } + catch (Exception ex) + { + Logger.LogWarning(ex, "Unexpected error while parsing a PEM block; skipping this block."); + } + } + + return results; + } + + // Heuristic leaf selection: + // - Prefer a certificate with CA=false (BasicConstraints) and whose Subject is not an Issuer of any other cert. + // - If multiple, prefer the one whose Subject does not appear as any Issuer at all. + // - As a last resort, pick the one with the longest chain distance (i.e., not issuing others). + private X509Certificate2? FindLeaf(IReadOnlyList certs) { - var splitCerts = - certData.Split(new[] { "-----END CERTIFICATE-----", "-----BEGIN CERTIFICATE-----" }, - StringSplitOptions.RemoveEmptyEntries); + // Build sets for quick lookups + var issuers = new HashSet(certs.Select(c => c.Issuer), StringComparer.OrdinalIgnoreCase); + var subjects = new HashSet(certs.Select(c => c.Subject), StringComparer.OrdinalIgnoreCase); - X509Certificate2Collection col = new X509Certificate2Collection(); - foreach (var cert in splitCerts) + bool IsCa(X509Certificate2 c) { - Logger.LogTrace($"Split Cert Value: {cert}"); - //skip these headers that came with the split function - if (!cert.Contains(".crt")) + try { - col.Import(Encoding.UTF8.GetBytes(cert)); + var bc = c.Extensions["2.5.29.19"]; // Basic Constraints + if (bc is X509BasicConstraintsExtension bce) + return bce.CertificateAuthority; } + catch { /* ignore and treat as unknown */ } + return false; // if unknown, bias towards non-CA for end-entity picking } - Logger.LogTrace("Getting End Entity Certificate"); - var currentCert = X509Utilities.ExtractEndEntityCertificateContents(ExportCollectionToPem(col), ""); - Logger.LogTrace("Converting to Byte Array"); - var byteArray = currentCert?.Export(X509ContentType.Cert); - Logger.LogTrace("Initializing empty string"); - var certString = string.Empty; - if (byteArray != null) + + // Candidates that do not issue others (their Subject is not an Issuer of any other). + var nonIssuers = certs.Where(c => + !certs.Any(o => !ReferenceEquals(o, c) && string.Equals(o.Issuer, c.Subject, StringComparison.OrdinalIgnoreCase)) + ).ToList(); + + // Prefer non-CA among non-issuers + var nonIssuerNonCa = nonIssuers.Where(c => !IsCa(c)).ToList(); + if (nonIssuerNonCa.Count == 1) return nonIssuerNonCa[0]; + if (nonIssuerNonCa.Count > 1) { - certString = Convert.ToBase64String(byteArray); + // If multiple, pick the one whose subject appears least as an issuer (tie-breaker unnecessary here since nonIssuers already exclude issuers). + return nonIssuerNonCa[0]; } - Logger.LogTrace($"Got certificate {certString}"); - return certString; + // If that failed, pick any non-CA that is not an issuer in the set of all issuers + var anyNonCa = certs.Where(c => !IsCa(c)).ToList(); + if (anyNonCa.Count == 1) return anyNonCa[0]; + if (anyNonCa.Count > 1) + { + // Prefer one whose subject is not equal to any issuer (a stricter non-issuer check across entire set) + var strict = anyNonCa.FirstOrDefault(c => !issuers.Contains(c.Subject)); + if (strict != null) return strict; + + return anyNonCa[0]; + } + + // Last resort: pick the cert that issues nobody else (even if CA=true) + if (nonIssuers.Count > 0) return nonIssuers[0]; + + // Give up + return null; + } + + private static int GetDecodedLength(string b64) + { + // Approximate decoded length: 3/4 of input, minus padding effect + int len = b64.Length; + int padding = 0; + if (len >= 2) + { + if (b64[^1] == '=') padding++; + if (b64[^2] == '=') padding++; + } + return Math.Max(0, (len / 4) * 3 - padding); } + private string ExportCollectionToPem(X509Certificate2Collection collection) { var pemBuilder = new StringBuilder(); @@ -438,10 +577,50 @@ private string ExportCollectionToPem(X509Certificate2Collection collection) return pemBuilder.ToString(); } + private static readonly Encoding Utf8Strict = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); + private static readonly Encoding Latin1 = Encoding.GetEncoding("ISO-8859-1"); - #endregion + private string PreparePemTextFromApi(string? base64) + { + if (string.IsNullOrWhiteSpace(base64)) + return string.Empty; + + byte[] raw; + try + { + raw = Convert.FromBase64String(base64); + } + catch (FormatException) + { + // Not even Base64; nothing we can do. + return string.Empty; + } + + // Try UTF-8 first (strict); if it fails, decode as Latin-1 to avoid loss. + string text; + try + { + text = Utf8Strict.GetString(raw); + } + catch (DecoderFallbackException) + { + text = Latin1.GetString(raw); + } + + // Drop UTF-8/UTF-16 BOMs if present + if (text.Length > 0 && text[0] == '\uFEFF') text = text[1..]; + + // Normalize line endings to '\n' (keep line structure!) + text = text.Replace("\r\n", "\n").Replace("\r", "\n"); + + // Remove NUL and non-printable control chars, but keep \n and \t + text = new string(text.Where(ch => + ch == '\n' || ch == '\t' || (ch >= ' ' && ch != '\u007F') + ).ToArray()); + + return text; + } - #region PUBLIC #endregion } \ No newline at end of file diff --git a/cscglobal-caplugin/CSCGlobalCAPlugin.csproj b/cscglobal-caplugin/CSCGlobalCAPlugin.csproj index 3561a0d..310ddeb 100644 --- a/cscglobal-caplugin/CSCGlobalCAPlugin.csproj +++ b/cscglobal-caplugin/CSCGlobalCAPlugin.csproj @@ -12,27 +12,22 @@ - - - - - - - - - - - - - - + - - - Always - - - + + + + + + + + + Always + + + + \ No newline at end of file diff --git a/cscglobal-caplugin/Client/CscGlobalClient.cs b/cscglobal-caplugin/Client/CscGlobalClient.cs index ad6aac3..fabd46b 100644 --- a/cscglobal-caplugin/Client/CscGlobalClient.cs +++ b/cscglobal-caplugin/Client/CscGlobalClient.cs @@ -4,12 +4,10 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. -using System; + using System.Net; -using System.Net.Http; using System.Net.Http.Headers; using System.Text; -using System.Threading.Tasks; using Keyfactor.AnyGateway.Extensions; using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; @@ -24,7 +22,7 @@ public sealed class CscGlobalClient : ICscGlobalClient private readonly ILogger Logger; public CscGlobalClient(IAnyCAPluginConfigProvider config) - { + { Logger = LogHandler.GetClassLogger(); if (config.CAConnectionData.ContainsKey(Constants.CscGlobalApiKey)) { @@ -88,6 +86,7 @@ public async Task SubmitRenewalAsync( response.Result = null; return response; } + var rawRenewResponse = await resp.Content.ReadAsStringAsync(); Logger.LogTrace("Logging Success Response Raw"); Logger.LogTrace(rawRenewResponse); @@ -134,6 +133,17 @@ public async Task SubmitGetCertificateAsync(string certific } } + public async Task> SubmitGetCustomFields() + { + using (var resp = await RestClient.GetAsync("/dbs/api/v2/admin/customfields")) + { + resp.EnsureSuccessStatusCode(); + var getCustomFieldsResponse = + JsonConvert.DeserializeObject(await resp.Content.ReadAsStringAsync()); + return getCustomFieldsResponse.CustomFields; + } + } + public async Task SubmitRevokeCertificateAsync(string uuId) { using (var resp = await RestClient.PutAsync($"/dbs/api/v2/tls/revoke/{uuId}", new StringContent(""))) diff --git a/cscglobal-caplugin/Client/Models/CName.cs b/cscglobal-caplugin/Client/Models/CName.cs index 04b2b13..b5e4b2c 100644 --- a/cscglobal-caplugin/Client/Models/CName.cs +++ b/cscglobal-caplugin/Client/Models/CName.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/CertificateListResponse.cs b/cscglobal-caplugin/Client/Models/CertificateListResponse.cs index 7e17154..ecff209 100644 --- a/cscglobal-caplugin/Client/Models/CertificateListResponse.cs +++ b/cscglobal-caplugin/Client/Models/CertificateListResponse.cs @@ -4,9 +4,9 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; -using System.Collections.Generic; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; diff --git a/cscglobal-caplugin/Client/Models/CertificateResponse.cs b/cscglobal-caplugin/Client/Models/CertificateResponse.cs index d81acf2..e1d5237 100644 --- a/cscglobal-caplugin/Client/Models/CertificateResponse.cs +++ b/cscglobal-caplugin/Client/Models/CertificateResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/CustomField.cs b/cscglobal-caplugin/Client/Models/CustomField.cs index 90cf119..86bff8b 100644 --- a/cscglobal-caplugin/Client/Models/CustomField.cs +++ b/cscglobal-caplugin/Client/Models/CustomField.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/DcvDetail.cs b/cscglobal-caplugin/Client/Models/DcvDetail.cs index ab1006b..5c12304 100644 --- a/cscglobal-caplugin/Client/Models/DcvDetail.cs +++ b/cscglobal-caplugin/Client/Models/DcvDetail.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/DomainControlValidation.cs b/cscglobal-caplugin/Client/Models/DomainControlValidation.cs index ed68fe6..e3eb7dc 100644 --- a/cscglobal-caplugin/Client/Models/DomainControlValidation.cs +++ b/cscglobal-caplugin/Client/Models/DomainControlValidation.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/EvCertificateDetails.cs b/cscglobal-caplugin/Client/Models/EvCertificateDetails.cs index 01fedbd..dc5f9a1 100644 --- a/cscglobal-caplugin/Client/Models/EvCertificateDetails.cs +++ b/cscglobal-caplugin/Client/Models/EvCertificateDetails.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/GetCustomField.cs b/cscglobal-caplugin/Client/Models/GetCustomField.cs new file mode 100644 index 0000000..fb4d043 --- /dev/null +++ b/cscglobal-caplugin/Client/Models/GetCustomField.cs @@ -0,0 +1,22 @@ +// Copyright 2021 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + +using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; +using Newtonsoft.Json; + +namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; + +public class GetCustomField : IGetCustomField +{ + [JsonProperty("label")] public string Label { get; set; } + [JsonProperty("mandatory")] public bool Mandatory { get; set; } +} + +public class GetCustomFields +{ + [JsonProperty("customFields")] public List CustomFields { get; set; } +} \ No newline at end of file diff --git a/cscglobal-caplugin/Client/Models/Meta.cs b/cscglobal-caplugin/Client/Models/Meta.cs index 83ffc5c..a046920 100644 --- a/cscglobal-caplugin/Client/Models/Meta.cs +++ b/cscglobal-caplugin/Client/Models/Meta.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/Notifications.cs b/cscglobal-caplugin/Client/Models/Notifications.cs index 3a1e193..4dc1e50 100644 --- a/cscglobal-caplugin/Client/Models/Notifications.cs +++ b/cscglobal-caplugin/Client/Models/Notifications.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/Price.cs b/cscglobal-caplugin/Client/Models/Price.cs index b2b029e..ad66ea3 100644 --- a/cscglobal-caplugin/Client/Models/Price.cs +++ b/cscglobal-caplugin/Client/Models/Price.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/RegistrationError.cs b/cscglobal-caplugin/Client/Models/RegistrationError.cs index 9ca8bc9..19afaff 100644 --- a/cscglobal-caplugin/Client/Models/RegistrationError.cs +++ b/cscglobal-caplugin/Client/Models/RegistrationError.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/RegistrationRequest.cs b/cscglobal-caplugin/Client/Models/RegistrationRequest.cs index 8fea3e7..1c56e9b 100644 --- a/cscglobal-caplugin/Client/Models/RegistrationRequest.cs +++ b/cscglobal-caplugin/Client/Models/RegistrationRequest.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/RegistrationResponse.cs b/cscglobal-caplugin/Client/Models/RegistrationResponse.cs index 5b1c2cd..b9c9f6e 100644 --- a/cscglobal-caplugin/Client/Models/RegistrationResponse.cs +++ b/cscglobal-caplugin/Client/Models/RegistrationResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/ReissueRequest.cs b/cscglobal-caplugin/Client/Models/ReissueRequest.cs index 944b865..040b2f1 100644 --- a/cscglobal-caplugin/Client/Models/ReissueRequest.cs +++ b/cscglobal-caplugin/Client/Models/ReissueRequest.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/ReissueResponse.cs b/cscglobal-caplugin/Client/Models/ReissueResponse.cs index df263fe..82d210b 100644 --- a/cscglobal-caplugin/Client/Models/ReissueResponse.cs +++ b/cscglobal-caplugin/Client/Models/ReissueResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/RenewalRequest.cs b/cscglobal-caplugin/Client/Models/RenewalRequest.cs index 9fac0fe..a99ace9 100644 --- a/cscglobal-caplugin/Client/Models/RenewalRequest.cs +++ b/cscglobal-caplugin/Client/Models/RenewalRequest.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/RenewalResponse.cs b/cscglobal-caplugin/Client/Models/RenewalResponse.cs index 5767c5f..4731106 100644 --- a/cscglobal-caplugin/Client/Models/RenewalResponse.cs +++ b/cscglobal-caplugin/Client/Models/RenewalResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/Result.cs b/cscglobal-caplugin/Client/Models/Result.cs index f3f9c92..244ec12 100644 --- a/cscglobal-caplugin/Client/Models/Result.cs +++ b/cscglobal-caplugin/Client/Models/Result.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/RevokeResponse.cs b/cscglobal-caplugin/Client/Models/RevokeResponse.cs index 15d6acf..58573fe 100644 --- a/cscglobal-caplugin/Client/Models/RevokeResponse.cs +++ b/cscglobal-caplugin/Client/Models/RevokeResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/RevokeSuccessResponse.cs b/cscglobal-caplugin/Client/Models/RevokeSuccessResponse.cs index 151f551..aea7ced 100644 --- a/cscglobal-caplugin/Client/Models/RevokeSuccessResponse.cs +++ b/cscglobal-caplugin/Client/Models/RevokeSuccessResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Newtonsoft.Json; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; diff --git a/cscglobal-caplugin/Client/Models/Status.cs b/cscglobal-caplugin/Client/Models/Status.cs index 10f6ea2..2b033b1 100644 --- a/cscglobal-caplugin/Client/Models/Status.cs +++ b/cscglobal-caplugin/Client/Models/Status.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Client/Models/SubjectAlternativeName.cs b/cscglobal-caplugin/Client/Models/SubjectAlternativeName.cs index 843e581..e75a9e5 100644 --- a/cscglobal-caplugin/Client/Models/SubjectAlternativeName.cs +++ b/cscglobal-caplugin/Client/Models/SubjectAlternativeName.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Newtonsoft.Json; diff --git a/cscglobal-caplugin/Constants.cs b/cscglobal-caplugin/Constants.cs index 816444d..897610f 100644 --- a/cscglobal-caplugin/Constants.cs +++ b/cscglobal-caplugin/Constants.cs @@ -16,9 +16,6 @@ public class Constants public static string TemplateSync = "TemplateSync"; } - - - public static class EnrollmentConfigConstants { public const string LastName = "LastName"; diff --git a/cscglobal-caplugin/Exceptions/RetryCountExceededException.cs b/cscglobal-caplugin/Exceptions/RetryCountExceededException.cs index e0b813b..a65c021 100644 --- a/cscglobal-caplugin/Exceptions/RetryCountExceededException.cs +++ b/cscglobal-caplugin/Exceptions/RetryCountExceededException.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Exceptions; public class RetryCountExceededException : Exception diff --git a/cscglobal-caplugin/Interfaces/ICName.cs b/cscglobal-caplugin/Interfaces/ICName.cs index 698712b..7e4c506 100644 --- a/cscglobal-caplugin/Interfaces/ICName.cs +++ b/cscglobal-caplugin/Interfaces/ICName.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; public interface ICName diff --git a/cscglobal-caplugin/Interfaces/ICertificateListResponse.cs b/cscglobal-caplugin/Interfaces/ICertificateListResponse.cs index 99e3d14..ad81b38 100644 --- a/cscglobal-caplugin/Interfaces/ICertificateListResponse.cs +++ b/cscglobal-caplugin/Interfaces/ICertificateListResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/ICertificateResponse.cs b/cscglobal-caplugin/Interfaces/ICertificateResponse.cs index b65415b..f4013f1 100644 --- a/cscglobal-caplugin/Interfaces/ICertificateResponse.cs +++ b/cscglobal-caplugin/Interfaces/ICertificateResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; public interface ICertificateResponse diff --git a/cscglobal-caplugin/Interfaces/ICscGlobalClient.cs b/cscglobal-caplugin/Interfaces/ICscGlobalClient.cs index 146c808..55d04be 100644 --- a/cscglobal-caplugin/Interfaces/ICscGlobalClient.cs +++ b/cscglobal-caplugin/Interfaces/ICscGlobalClient.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; @@ -21,6 +22,8 @@ Task SubmitReissueAsync( Task SubmitGetCertificateAsync(string certificateId); + Task> SubmitGetCustomFields(); + Task SubmitCertificateListRequestAsync(); Task SubmitRevokeCertificateAsync(string uuId); diff --git a/cscglobal-caplugin/Interfaces/ICustomField.cs b/cscglobal-caplugin/Interfaces/ICustomField.cs index c91c49d..0e7efe3 100644 --- a/cscglobal-caplugin/Interfaces/ICustomField.cs +++ b/cscglobal-caplugin/Interfaces/ICustomField.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; public interface ICustomField diff --git a/cscglobal-caplugin/Interfaces/IDcvDetail.cs b/cscglobal-caplugin/Interfaces/IDcvDetail.cs index 12ab1e3..f34e607 100644 --- a/cscglobal-caplugin/Interfaces/IDcvDetail.cs +++ b/cscglobal-caplugin/Interfaces/IDcvDetail.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/IDomainControlValidation.cs b/cscglobal-caplugin/Interfaces/IDomainControlValidation.cs index ef56077..8ae14ac 100644 --- a/cscglobal-caplugin/Interfaces/IDomainControlValidation.cs +++ b/cscglobal-caplugin/Interfaces/IDomainControlValidation.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; public interface IDomainControlValidation diff --git a/cscglobal-caplugin/Interfaces/IEvCertificateDetails.cs b/cscglobal-caplugin/Interfaces/IEvCertificateDetails.cs index b50f77a..7a1a5d2 100644 --- a/cscglobal-caplugin/Interfaces/IEvCertificateDetails.cs +++ b/cscglobal-caplugin/Interfaces/IEvCertificateDetails.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; public interface IEvCertificateDetails diff --git a/cscglobal-caplugin/Interfaces/IGetCustomField.cs b/cscglobal-caplugin/Interfaces/IGetCustomField.cs new file mode 100644 index 0000000..d065031 --- /dev/null +++ b/cscglobal-caplugin/Interfaces/IGetCustomField.cs @@ -0,0 +1,14 @@ +// Copyright 2021 Keyfactor +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +// and limitations under the License. + +namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; + +public interface IGetCustomField +{ + string Label { get; set; } + bool Mandatory { get; set; } +} \ No newline at end of file diff --git a/cscglobal-caplugin/Interfaces/IMeta.cs b/cscglobal-caplugin/Interfaces/IMeta.cs index 073a64b..80deae3 100644 --- a/cscglobal-caplugin/Interfaces/IMeta.cs +++ b/cscglobal-caplugin/Interfaces/IMeta.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; public interface IMeta diff --git a/cscglobal-caplugin/Interfaces/INotifications.cs b/cscglobal-caplugin/Interfaces/INotifications.cs index 288a5bb..3579ac5 100644 --- a/cscglobal-caplugin/Interfaces/INotifications.cs +++ b/cscglobal-caplugin/Interfaces/INotifications.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; public interface INotifications diff --git a/cscglobal-caplugin/Interfaces/IPrice.cs b/cscglobal-caplugin/Interfaces/IPrice.cs index c07f684..d4bab37 100644 --- a/cscglobal-caplugin/Interfaces/IPrice.cs +++ b/cscglobal-caplugin/Interfaces/IPrice.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; public interface IPrice diff --git a/cscglobal-caplugin/Interfaces/IRegistrationError.cs b/cscglobal-caplugin/Interfaces/IRegistrationError.cs index 31a349e..b5db028 100644 --- a/cscglobal-caplugin/Interfaces/IRegistrationError.cs +++ b/cscglobal-caplugin/Interfaces/IRegistrationError.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; internal interface IRegistrationError diff --git a/cscglobal-caplugin/Interfaces/IRegistrationRequest.cs b/cscglobal-caplugin/Interfaces/IRegistrationRequest.cs index 4e9bf4b..f3d2ad5 100644 --- a/cscglobal-caplugin/Interfaces/IRegistrationRequest.cs +++ b/cscglobal-caplugin/Interfaces/IRegistrationRequest.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/IRegistrationResponse.cs b/cscglobal-caplugin/Interfaces/IRegistrationResponse.cs index fe613f4..a436fd3 100644 --- a/cscglobal-caplugin/Interfaces/IRegistrationResponse.cs +++ b/cscglobal-caplugin/Interfaces/IRegistrationResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/IReissueRequest.cs b/cscglobal-caplugin/Interfaces/IReissueRequest.cs index 5ef63d3..3f79dce 100644 --- a/cscglobal-caplugin/Interfaces/IReissueRequest.cs +++ b/cscglobal-caplugin/Interfaces/IReissueRequest.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/IReissueResponse.cs b/cscglobal-caplugin/Interfaces/IReissueResponse.cs index 706a299..e735fc4 100644 --- a/cscglobal-caplugin/Interfaces/IReissueResponse.cs +++ b/cscglobal-caplugin/Interfaces/IReissueResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/IRenewalRequest.cs b/cscglobal-caplugin/Interfaces/IRenewalRequest.cs index 14e7f4d..58a0099 100644 --- a/cscglobal-caplugin/Interfaces/IRenewalRequest.cs +++ b/cscglobal-caplugin/Interfaces/IRenewalRequest.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/IRenewalResponse.cs b/cscglobal-caplugin/Interfaces/IRenewalResponse.cs index a208401..813b523 100644 --- a/cscglobal-caplugin/Interfaces/IRenewalResponse.cs +++ b/cscglobal-caplugin/Interfaces/IRenewalResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/IResult.cs b/cscglobal-caplugin/Interfaces/IResult.cs index 67ca619..19c4b79 100644 --- a/cscglobal-caplugin/Interfaces/IResult.cs +++ b/cscglobal-caplugin/Interfaces/IResult.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/IRevokeResponse.cs b/cscglobal-caplugin/Interfaces/IRevokeResponse.cs index 30864f5..28a4309 100644 --- a/cscglobal-caplugin/Interfaces/IRevokeResponse.cs +++ b/cscglobal-caplugin/Interfaces/IRevokeResponse.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/Interfaces/IStatus.cs b/cscglobal-caplugin/Interfaces/IStatus.cs index aafac7d..b8c0bc0 100644 --- a/cscglobal-caplugin/Interfaces/IStatus.cs +++ b/cscglobal-caplugin/Interfaces/IStatus.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; public interface IStatus diff --git a/cscglobal-caplugin/Interfaces/ISubjectAlternativeName.cs b/cscglobal-caplugin/Interfaces/ISubjectAlternativeName.cs index c9b911e..8463c73 100644 --- a/cscglobal-caplugin/Interfaces/ISubjectAlternativeName.cs +++ b/cscglobal-caplugin/Interfaces/ISubjectAlternativeName.cs @@ -4,6 +4,7 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; diff --git a/cscglobal-caplugin/RequestManager.cs b/cscglobal-caplugin/RequestManager.cs index 41a1a83..508dfe3 100644 --- a/cscglobal-caplugin/RequestManager.cs +++ b/cscglobal-caplugin/RequestManager.cs @@ -4,12 +4,12 @@ // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. + using System.Net.Mail; using System.Text; using Keyfactor.AnyGateway.Extensions; using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; -using Keyfactor.PKI; using Keyfactor.PKI.Enums.EJBCA; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal; @@ -22,6 +22,22 @@ public class RequestManager private List GetCustomFields(EnrollmentProductInfo productInfo) { var customFieldList = new List(); + foreach (var field in customFields) + if (productInfo.ProductParameters.ContainsKey(field.Label)) + { + var newField = new CustomField + { + Name = field.Label, + Value = productInfo.ProductParameters[field.Label] + }; + customFieldList.Add(newField); + } + else if (field.Mandatory) + { + throw new Exception( + $"Custom field {field.Label} is marked as mandatory, but was not supplied in the request."); + } + return customFieldList; } @@ -55,12 +71,18 @@ public EnrollmentResult StatusMessage = registrationResponse.RegistrationError.Description }; + var cnames = new Dictionary(); + if (registrationResponse.Result.DcvDetails != null && registrationResponse.Result.DcvDetails.Count > 0) + foreach (var dcv in registrationResponse.Result.DcvDetails) + cnames.Add(dcv.CName.Name, dcv.CName.Value); + return new EnrollmentResult { Status = (int)EndEntityStatus.EXTERNALVALIDATION, //success CARequestID = registrationResponse.Result.Status.Uuid, StatusMessage = - $"Order Successfully Created With Order Number {registrationResponse.Result.CommonName}" + $"Order Successfully Created With Order Number {registrationResponse.Result.CommonName}", + EnrollmentContext = cnames.Count > 0 ? cnames : null }; } From 3ade8254f3e85561c53e50b3ad0edac0d5283d10 Mon Sep 17 00:00:00 2001 From: Mark Kachkaev Date: Fri, 7 Nov 2025 15:27:34 -0500 Subject: [PATCH 3/5] Test --- cscglobal-caplugin/CSCGlobalCAPlugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cscglobal-caplugin/CSCGlobalCAPlugin.cs b/cscglobal-caplugin/CSCGlobalCAPlugin.cs index c5b7ff0..3e31c94 100644 --- a/cscglobal-caplugin/CSCGlobalCAPlugin.cs +++ b/cscglobal-caplugin/CSCGlobalCAPlugin.cs @@ -124,7 +124,7 @@ public async Task Synchronize(BlockingCollection blockin Logger.LogTrace($"File Content {fileContent}"); var certData = fileContent.Replace("\r\n", string.Empty); var certString = GetEndEntityCertificate(certData); - var currentCert = new X509Certificate2(Encoding.ASCII.GetBytes(certString)); + //var currentCert = new X509Certificate2(Encoding.ASCII.GetBytes(certString)); if (certString.Length > 0) blockingBuffer.Add(new AnyCAPluginCertificate { From 6afaec6157882e7fdccb00512f377d35740c5c65 Mon Sep 17 00:00:00 2001 From: Mark Kachkaev Date: Fri, 21 Nov 2025 16:44:19 -0500 Subject: [PATCH 4/5] Added template parameter configuration via REST gateway. Fixed bug with email used for verification. Changed docs and enrollment field/template parameter names. See changelog. --- CHANGELOG.md | 6 + README.md | 30 +++- cscglobal-caplugin.sln | 5 +- cscglobal-caplugin/CSCGlobalCAPlugin.cs | 165 ++++++++++++++---- cscglobal-caplugin/Constants.cs | 47 ++--- .../Interfaces/IGetCustomField.cs | 2 +- cscglobal-caplugin/RequestManager.cs | 26 ++- cscglobal-caplugin/manifest.json | 2 +- docsource/configuration.md | 35 ++-- integration-manifest.json | 51 +++++- 10 files changed, 278 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d0faf5..d1bd073 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +v.1.0.2 +- Warning: enrollment field/template parameter with the name "CN DCV Email (admin@boingy.com)" has been renamed to "CN DCV Email" to make it compatible with the REST gateway. "Aplicant Pgone (+nn.nnnnnnnn)" has also been renamed to "Applicant Phone". +- Updated dependencies. +- Added support for default values via enrollment parameters configured in the AnyGateway REST certificate template. +- Fixed issue with non-ASCII characters breaking the gateway. + v1.0.1 - Fixed issue with SANs not being read correctly. diff --git a/README.md b/README.md index aa73d9a..412fe75 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@

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

@@ -53,7 +53,7 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and 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 [CSCGlobal CA Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/cscglobal-caplugin/releases/latest) from GitHub. +2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [CSCGlobal CA Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/cscglobal-caplugin-dev/releases/latest) from GitHub. 3. Copy the unzipped directory (usually called `net6.0` or `net8.0`) to the Extensions directory: @@ -91,7 +91,8 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and 2. PLEASE NOTE, AT THIS TIME THE RAPID_SSL TEMPLATE IS NOT SUPPORTED BY THE CSC API AND WILL NOT WORK WITH THIS INTEGRATION The following certificate templates are supported. Please set up the key sizes accordingly in the Certificate Profile menu of Anygateway REST, then enter the remaining details - and the Enrollment Fields for each Template accordingly using the Certificate Templates section in Command: + and the Enrollment Fields for each Template accordingly using the Certificate Templates section in Command. If you would like to set up default values for enrollment parameters, you can do so the in the Certificate Template Menu of Anygateway REST. + If a field value is specified as both an Enrollment Field in Command and in the Certificate Template Menu in the REST Gateway, the value in the Enrollment Field will take precedence. CONFIG ELEMENT | DESCRIPTION ----------------------------|------------------ @@ -175,7 +176,7 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A CN DCV Email (admin@yourdomain.com) | String | N/A - Addtl Sans Comma Separated DVC Emails | String | N/A + Addtl Sans Comma Separated DCV Emails | String | N/A **CSC TrustedSecure Premium Wildcard Certificate - Details Tab** @@ -289,10 +290,25 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A CN DCV Email (admin@yourdomain.com) | String | N/A - Addtl Sans Comma Separated DVC Emails | String | N/A + Addtl Sans Comma Separated DCV Emails | String | N/A 3. Follow the [official Keyfactor documentation](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCA-Keyfactor.htm) to add each defined Certificate Authority to Keyfactor Command and import the newly defined Certificate Templates. +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: + + * **Term** - OPTIONAL: Certificate term (e.g. 12 or 24 months) + * **Applicant First Name** - OPTIONAL: Applicant First Name + * **Applicant Last Name** - OPTIONAL: Applicant Last Name + * **Applicant Email Address** - OPTIONAL: Applicant Email Address + * **Applicant Phone** - OPTIONAL: Applicant Phone (+nn.nnnnnnnn) + * **Domain Control Validation Method** - OPTIONAL: Domain Control Validation Method (e.g. EMAIL) + * **Organization Contact** - OPTIONAL: Organization Contact (selected from CSC configuration) + * **Business Unit** - OPTIONAL: Business Unit (selected from CSC configuration) + * **Notification Email(s) Comma Separated** - OPTIONAL: Notification Email(s), comma separated + * **CN DCV Email** - OPTIONAL: CN DCV Email (e.g. admin@yourdomain.com) + * **Organization Country** - OPTIONAL: Organization Country + * **Addtl Sans Comma Separated DCV Emails** - OPTIONAL: Additional SANs DCV Emails, comma separated + ## License diff --git a/cscglobal-caplugin.sln b/cscglobal-caplugin.sln index 05ae344..220a2cd 100644 --- a/cscglobal-caplugin.sln +++ b/cscglobal-caplugin.sln @@ -1,13 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.11.35327.3 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.11217.181 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSCGlobalCAPlugin", "cscglobal-caplugin\CSCGlobalCAPlugin.csproj", "{01DDFD6F-275D-46E7-B522-E0C965D1BF9C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" ProjectSection(SolutionItems) = preProject CHANGELOG.md = CHANGELOG.md + docsource\configuration.md = docsource\configuration.md integration-manifest.json = integration-manifest.json EndProjectSection EndProject diff --git a/cscglobal-caplugin/CSCGlobalCAPlugin.cs b/cscglobal-caplugin/CSCGlobalCAPlugin.cs index 3e31c94..1c112b3 100644 --- a/cscglobal-caplugin/CSCGlobalCAPlugin.cs +++ b/cscglobal-caplugin/CSCGlobalCAPlugin.cs @@ -5,20 +5,19 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions // and limitations under the License. +using System.Collections.Concurrent; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Text.RegularExpressions; using Keyfactor.AnyGateway.Extensions; using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client; using Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models; using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Keyfactor.Logging; using Keyfactor.PKI.Enums.EJBCA; -using Keyfactor.PKI.X509; using Microsoft.Extensions.Logging; using Newtonsoft.Json; -using System.Collections.Concurrent; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Text.RegularExpressions; namespace Keyfactor.Extensions.CAPlugin.CSCGlobal; @@ -324,6 +323,13 @@ public async Task ValidateCAConnectionInfo(Dictionary connection public async Task ValidateProductInfo(EnrollmentProductInfo productInfo, Dictionary connectionInfo) { + var certType = ProductIDs.productIds.Find(x => + x.Equals(productInfo.ProductID, StringComparison.InvariantCultureIgnoreCase)); + + if (certType == null) throw new ArgumentException($"Cannot find {productInfo.ProductID}", "ProductId"); + + Logger.LogInformation($"Validated {certType} ({certType})configured for AnyGateway"); + } //done @@ -372,23 +378,111 @@ public Dictionary GetCAConnectorAnnotations() //done public Dictionary GetTemplateParameterAnnotations() { - return new Dictionary(); + return new Dictionary + { + [EnrollmentConfigConstants.Term] = new() + { + Comments = "OPTIONAL: Certificate term (e.g. 12 or 24 months)", + Hidden = false, + DefaultValue = string.Empty, + Type = "Number" + }, + + [EnrollmentConfigConstants.ApplicantFirstName] = new() + { + Comments = "OPTIONAL: Applicant First Name", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.ApplicantLastName] = new() + { + Comments = "OPTIONAL: Applicant Last Name", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.ApplicantEmailAddress] = new() + { + Comments = "OPTIONAL: Applicant Email Address", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.ApplicantPhone] = new() + { + Comments = "OPTIONAL: Applicant Phone (+nn.nnnnnnnn)", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.DomainControlValidationMethod] = new() + { + Comments = "OPTIONAL: Domain Control Validation Method (e.g. EMAIL)", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.OrganizationContact] = new() + { + Comments = "OPTIONAL: Organization Contact (selected from CSC configuration)", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.BusinessUnit] = new() + { + Comments = "OPTIONAL: Business Unit (selected from CSC configuration)", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.NotificationEmailsCommaSeparated] = new() + { + Comments = "OPTIONAL: Notification Email(s), comma separated", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.CnDcvEmail] = new() + { + Comments = "OPTIONAL: CN DCV Email (e.g. admin@yourdomain.com)", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.OrganizationCountry] = new() + { + Comments = "OPTIONAL: Organization Country", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + }, + + [EnrollmentConfigConstants.AdditionalSansCommaSeparatedDcvEmails] = new() + { + Comments = "OPTIONAL: Additional SANs DCV Emails, comma separated", + Hidden = false, + DefaultValue = string.Empty, + Type = "String" + } + }; } //done public List GetProductIds() { - var ProductIDs = new List - { - "CSC TrustedSecure Premium Certificate", - "CSC TrustedSecure EV Certificate", - "CSC TrustedSecure UC Certificate", - "CSC TrustedSecure Premium Wildcard Certificate", - "CSC TrustedSecure Domain Validated SSL", - "CSC TrustedSecure Domain Validated Wildcard SSL", - "CSC TrustedSecure Domain Validated UC Certificate" - }; - return ProductIDs; + + return ProductIDs.productIds; } #region PRIVATE @@ -401,7 +495,7 @@ public List GetProductIds() private static readonly Regex Ws = new("\\s+", RegexOptions.Compiled); ///

- /// Returns the end-entity certificate as Base64 DER (no PEM headers), or "" if none could be found. + /// Returns the end-entity certificate as Base64 DER (no PEM headers), or "" if none could be found. /// public string GetEndEntityCertificate(string pemChain) { @@ -430,8 +524,8 @@ public string GetEndEntityCertificate(string pemChain) try { // 3) Export to DER and Base64 (no headers). - byte[] der = leaf.Export(X509ContentType.Cert); - string b64 = Convert.ToBase64String(der); + var der = leaf.Export(X509ContentType.Cert); + var b64 = Convert.ToBase64String(der); Logger.LogTrace("End-entity certificate exported successfully."); return b64; } @@ -453,7 +547,7 @@ private List ExtractCertificates(string pem) foreach (Match m in PemBlock.Matches(pem)) { - string b64 = m.Groups["b64"].Value; + var b64 = m.Groups["b64"].Value; if (string.IsNullOrWhiteSpace(b64)) { Logger.LogTrace("Skipping empty PEM block."); @@ -467,14 +561,15 @@ private List ExtractCertificates(string pem) try { // Convert.TryFromBase64String is fast and avoids temporary arrays when possible - if (!Convert.TryFromBase64String(b64, new Span(new byte[GetDecodedLength(b64)]), out int bytesWritten)) + if (!Convert.TryFromBase64String(b64, new Span(new byte[GetDecodedLength(b64)]), + out var bytesWritten)) { // Fallback to FromBase64String to trigger a clear exception path var discard = Convert.FromBase64String(b64); bytesWritten = discard.Length; // unreachable if invalid } - byte[] der = Convert.FromBase64String(b64); + var der = Convert.FromBase64String(b64); var cert = new X509Certificate2(der); results.Add(cert); Logger.LogTrace($"Imported certificate: Subject='{cert.Subject}', Issuer='{cert.Issuer}'"); @@ -514,23 +609,26 @@ bool IsCa(X509Certificate2 c) if (bc is X509BasicConstraintsExtension bce) return bce.CertificateAuthority; } - catch { /* ignore and treat as unknown */ } + catch + { + /* ignore and treat as unknown */ + } + return false; // if unknown, bias towards non-CA for end-entity picking } // Candidates that do not issue others (their Subject is not an Issuer of any other). var nonIssuers = certs.Where(c => - !certs.Any(o => !ReferenceEquals(o, c) && string.Equals(o.Issuer, c.Subject, StringComparison.OrdinalIgnoreCase)) + !certs.Any(o => + !ReferenceEquals(o, c) && string.Equals(o.Issuer, c.Subject, StringComparison.OrdinalIgnoreCase)) ).ToList(); // Prefer non-CA among non-issuers var nonIssuerNonCa = nonIssuers.Where(c => !IsCa(c)).ToList(); if (nonIssuerNonCa.Count == 1) return nonIssuerNonCa[0]; if (nonIssuerNonCa.Count > 1) - { // If multiple, pick the one whose subject appears least as an issuer (tie-breaker unnecessary here since nonIssuers already exclude issuers). return nonIssuerNonCa[0]; - } // If that failed, pick any non-CA that is not an issuer in the set of all issuers var anyNonCa = certs.Where(c => !IsCa(c)).ToList(); @@ -554,14 +652,15 @@ bool IsCa(X509Certificate2 c) private static int GetDecodedLength(string b64) { // Approximate decoded length: 3/4 of input, minus padding effect - int len = b64.Length; - int padding = 0; + var len = b64.Length; + var padding = 0; if (len >= 2) { if (b64[^1] == '=') padding++; if (b64[^2] == '=') padding++; } - return Math.Max(0, (len / 4) * 3 - padding); + + return Math.Max(0, len / 4 * 3 - padding); } private string ExportCollectionToPem(X509Certificate2Collection collection) @@ -577,7 +676,8 @@ private string ExportCollectionToPem(X509Certificate2Collection collection) return pemBuilder.ToString(); } - private static readonly Encoding Utf8Strict = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); + + private static readonly Encoding Utf8Strict = new UTF8Encoding(false, true); private static readonly Encoding Latin1 = Encoding.GetEncoding("ISO-8859-1"); private string PreparePemTextFromApi(string? base64) @@ -621,6 +721,5 @@ private string PreparePemTextFromApi(string? base64) return text; } - #endregion } \ No newline at end of file diff --git a/cscglobal-caplugin/Constants.cs b/cscglobal-caplugin/Constants.cs index 897610f..7cc8669 100644 --- a/cscglobal-caplugin/Constants.cs +++ b/cscglobal-caplugin/Constants.cs @@ -15,26 +15,33 @@ public class Constants public static string DefaultPageSize = "DefaultPageSize"; public static string TemplateSync = "TemplateSync"; } - -public static class EnrollmentConfigConstants + +public class ProductIDs { - public const string LastName = "LastName"; - public const string FirstName = "FirstName"; - public const string Email = "Email"; - public const string Phone = "Phone"; - - public const string OrganizationName = "OrganizationName"; - public const string OrganizationAddress = "OrganizationAddress"; - public const string OrganizationCity = "OrganizationCity"; - public const string OrganizationState = "OrganizationState"; - public const string OrganizationCountry = "OrganizationCountry"; - public const string OrganizationPhone = "OrganizationPhone"; - - public const string JobTitle = "JobTitle"; - public const string RegistrationAgent = "RegistrationAgent"; - public const string RegistrationNumber = "RegistrationNumber"; + public static List productIds = new List() + { + "CSC TrustedSecure Premium Certificate", + "CSC TrustedSecure EV Certificate", + "CSC TrustedSecure UC Certificate", + "CSC TrustedSecure Premium Wildcard Certificate", + "CSC TrustedSecure Domain Validated SSL", + "CSC TrustedSecure Domain Validated Wildcard SSL", + "CSC TrustedSecure Domain Validated UC Certificate" + }; +} - public const string RootCAType = "RootCAType"; - public const string SlotSize = "SlotSize"; - public const string CertificateValidityInYears = "CertificateValidityInYears"; +public class EnrollmentConfigConstants +{ + public const string Term = "Term"; + public const string ApplicantFirstName = "Applicant First Name"; + public const string ApplicantLastName = "Applicant Last Name"; + public const string ApplicantEmailAddress = "Applicant Email Address"; + public const string ApplicantPhone = "Applicant Phone"; + public const string DomainControlValidationMethod = "Domain Control Validation Method"; + public const string OrganizationContact = "Organization Contact"; + public const string BusinessUnit = "Business Unit"; + public const string NotificationEmailsCommaSeparated = "Notification Email(s) Comma Separated"; + public const string CnDcvEmail = "CN DCV Email"; + public const string OrganizationCountry = "Organization Country"; + public const string AdditionalSansCommaSeparatedDcvEmails = "Addtl Sans Comma Separated DCV Emails"; } \ No newline at end of file diff --git a/cscglobal-caplugin/Interfaces/IGetCustomField.cs b/cscglobal-caplugin/Interfaces/IGetCustomField.cs index 71c3395..d065031 100644 --- a/cscglobal-caplugin/Interfaces/IGetCustomField.cs +++ b/cscglobal-caplugin/Interfaces/IGetCustomField.cs @@ -11,4 +11,4 @@ public interface IGetCustomField { string Label { get; set; } bool Mandatory { get; set; } -} +} \ No newline at end of file diff --git a/cscglobal-caplugin/RequestManager.cs b/cscglobal-caplugin/RequestManager.cs index 0ae673a..aa19b1e 100644 --- a/cscglobal-caplugin/RequestManager.cs +++ b/cscglobal-caplugin/RequestManager.cs @@ -12,8 +12,6 @@ using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces; using Keyfactor.PKI.Enums.EJBCA; -using Org.BouncyCastle.Bcpg; - namespace Keyfactor.Extensions.CAPlugin.CSCGlobal; public class RequestManager @@ -76,8 +74,18 @@ public EnrollmentResult var cnames = new Dictionary(); if (registrationResponse.Result.DcvDetails != null && registrationResponse.Result.DcvDetails.Count > 0) foreach (var dcv in registrationResponse.Result.DcvDetails) - cnames.Add(dcv.CName.Name, dcv.CName.Value); + { + if (dcv.CName != null && !string.IsNullOrEmpty(dcv.CName.Name) && !string.IsNullOrEmpty(dcv.CName.Value)) + { + cnames.Add(dcv.CName.Name, dcv.CName.Value); + } + if (string.IsNullOrEmpty(dcv.Email)) + { + cnames.Add(dcv.Email, dcv.Email); + } + } + return new EnrollmentResult { Status = (int)EndEntityStatus.EXTERNALVALIDATION, //success @@ -149,7 +157,7 @@ public RegistrationRequest GetRegistrationRequest(EnrollmentProductInfo productI var bytes = Encoding.UTF8.GetBytes(cert); var encodedString = Convert.ToBase64String(bytes); - var commonNameValidationEmail = productInfo.ProductParameters["CN DCV Email (admin@yourdomain.com)"]; + var commonNameValidationEmail = productInfo.ProductParameters["CN DCV Email"]; var methodType = productInfo.ProductParameters["Domain Control Validation Method"]; var certificateType = GetCertificateType(productInfo.ProductID); @@ -162,7 +170,7 @@ public RegistrationRequest GetRegistrationRequest(EnrollmentProductInfo productI ApplicantFirstName = productInfo.ProductParameters["Applicant First Name"], ApplicantLastName = productInfo.ProductParameters["Applicant Last Name"], ApplicantEmailAddress = productInfo.ProductParameters["Applicant Email Address"], - ApplicantPhoneNumber = productInfo.ProductParameters["Applicant Phone (+nn.nnnnnnnn)"], + ApplicantPhoneNumber = productInfo.ProductParameters["Applicant Phone"], DomainControlValidation = GetDomainControlValidation(methodType, commonNameValidationEmail), Notifications = GetNotifications(productInfo), OrganizationContact = productInfo.ProductParameters["Organization Contact"], @@ -222,7 +230,7 @@ public RenewalRequest GetRenewalRequest(EnrollmentProductInfo productInfo, strin var bytes = Encoding.UTF8.GetBytes(cert); var encodedString = Convert.ToBase64String(bytes); - var commonNameValidationEmail = productInfo.ProductParameters["CN DCV Email (admin@yourdomain.com)"]; + var commonNameValidationEmail = productInfo.ProductParameters["CN DCV Email"]; var methodType = productInfo.ProductParameters["Domain Control Validation Method"]; var certificateType = GetCertificateType(productInfo.ProductID); @@ -236,7 +244,7 @@ public RenewalRequest GetRenewalRequest(EnrollmentProductInfo productInfo, strin ApplicantFirstName = productInfo.ProductParameters["Applicant First Name"], ApplicantLastName = productInfo.ProductParameters["Applicant Last Name"], ApplicantEmailAddress = productInfo.ProductParameters["Applicant Email Address"], - ApplicantPhoneNumber = productInfo.ProductParameters["Applicant Phone (+nn.nnnnnnnn)"], + ApplicantPhoneNumber = productInfo.ProductParameters["Applicant Phone"], DomainControlValidation = GetDomainControlValidation(methodType, commonNameValidationEmail), Notifications = GetNotifications(productInfo), OrganizationContact = productInfo.ProductParameters["Organization Contact"], @@ -280,7 +288,7 @@ public ReissueRequest GetReissueRequest(EnrollmentProductInfo productInfo, strin var bytes = Encoding.UTF8.GetBytes(cert); var encodedString = Convert.ToBase64String(bytes); - var commonNameValidationEmail = productInfo.ProductParameters["CN DCV Email (admin@yourdomain.com)"]; + var commonNameValidationEmail = productInfo.ProductParameters["CN DCV Email"]; var methodType = productInfo.ProductParameters["Domain Control Validation Method"]; var certificateType = GetCertificateType(productInfo.ProductID); @@ -294,7 +302,7 @@ public ReissueRequest GetReissueRequest(EnrollmentProductInfo productInfo, strin ApplicantFirstName = productInfo.ProductParameters["Applicant First Name"], ApplicantLastName = productInfo.ProductParameters["Applicant Last Name"], ApplicantEmailAddress = productInfo.ProductParameters["Applicant Email Address"], - ApplicantPhoneNumber = productInfo.ProductParameters["Applicant Phone (+nn.nnnnnnnn)"], + ApplicantPhoneNumber = productInfo.ProductParameters["Applicant Phone"], DomainControlValidation = GetDomainControlValidation(methodType, commonNameValidationEmail), Notifications = GetNotifications(productInfo), OrganizationContact = productInfo.ProductParameters["Organization Contact"], diff --git a/cscglobal-caplugin/manifest.json b/cscglobal-caplugin/manifest.json index 121fd24..d6ae873 100644 --- a/cscglobal-caplugin/manifest.json +++ b/cscglobal-caplugin/manifest.json @@ -1,4 +1,4 @@ -{ + { "extensions": { "Keyfactor.AnyGateway.Extensions.IAnyCAPlugin": { "CSCGlobalCAPlugin": { diff --git a/docsource/configuration.md b/docsource/configuration.md index fef556b..d8c196e 100644 --- a/docsource/configuration.md +++ b/docsource/configuration.md @@ -15,7 +15,8 @@ The Root certificates for installation on the Anygateway server machine should b PLEASE NOTE, AT THIS TIME THE RAPID_SSL TEMPLATE IS NOT SUPPORTED BY THE CSC API AND WILL NOT WORK WITH THIS INTEGRATION The following certificate templates are supported. Please set up the key sizes accordingly in the Certificate Profile menu of Anygateway REST, then enter the remaining details -and the Enrollment Fields for each Template accordingly using the Certificate Templates section in Command: +and the Enrollment Fields for each Template accordingly using the Certificate Templates section in Command. If you would like to set up default values for enrollment parameters, you can do so the in the Certificate Template Menu of Anygateway REST. +If a field value is specified as both an Enrollment Field in Command and in the Certificate Template Menu in the REST Gateway, the value in the Enrollment Field will take precedence. CONFIG ELEMENT | DESCRIPTION ----------------------------|------------------ @@ -36,12 +37,12 @@ Term | Multiple Choice | 12,24 Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A -Applicant Phone (+nn.nnnnnnnn) | String | N/A +Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A -CN DCV Email (admin@yourdomain.com) | String | N/A +CN DCV Email | String | N/A **CSC TrustedSecure EV Certificate - Details Tab** @@ -64,12 +65,12 @@ Term | Multiple Choice | 12,24 Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A -Applicant Phone (+nn.nnnnnnnn) | String | N/A +Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A -CN DCV Email (admin@yourdomain.com) | String | N/A +CN DCV Email | String | N/A Organization Country | String | N/A **CSC TrustedSecure UC Certificate - Details Tab** @@ -93,13 +94,13 @@ Term | Multiple Choice | 12,24 Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A -Applicant Phone (+nn.nnnnnnnn) | String | N/A +Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A -CN DCV Email (admin@yourdomain.com) | String | N/A -Addtl Sans Comma Separated DVC Emails | String | N/A +CN DCV Email | String | N/A +Addtl Sans Comma Separated DCV Emails | String | N/A **CSC TrustedSecure Premium Wildcard Certificate - Details Tab** @@ -123,12 +124,12 @@ Term | Multiple Choice | 12,24 Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A -Applicant Phone (+nn.nnnnnnnn) | String | N/A +Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A -CN DCV Email (admin@yourdomain.com) | String | N/A +CN DCV Email | String | N/A **CSC TrustedSecure Domain Validated SSL - Details Tab** @@ -151,12 +152,12 @@ Term | Multiple Choice | 12,24 Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A -Applicant Phone (+nn.nnnnnnnn) | String | N/A +Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A -CN DCV Email (admin@yourdomain.com) | String | N/A +CN DCV Email | String | N/A **CSC TrustedSecure Domain Validated Wildcard SSL - Details Tab** @@ -179,12 +180,12 @@ Term | Multiple Choice | 12,24 Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A -Applicant Phone (+nn.nnnnnnnn) | String | N/A +Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A -CN DCV Email (admin@yourdomain.com) | String | N/A +CN DCV Email | String | N/A **CSC TrustedSecure Domain Validated UC Certificate - Details Tab** @@ -207,11 +208,11 @@ Term | Multiple Choice | 12,24 Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A -Applicant Phone (+nn.nnnnnnnn) | String | N/A +Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A -CN DCV Email (admin@yourdomain.com) | String | N/A -Addtl Sans Comma Separated DVC Emails | String | N/A +CN DCV Email | String | N/A +Addtl Sans Comma Separated DCV Emails | String | N/A diff --git a/integration-manifest.json b/integration-manifest.json index 80800a9..7b39dd0 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -34,7 +34,56 @@ "description": "Enable template sync." } ], - "enrollment_config": [], + "enrollment_config": [ + { + "name": "Term", + "description": "OPTIONAL: Certificate term (e.g. 12 or 24 months)" + }, + { + "name": "Applicant First Name", + "description": "OPTIONAL: Applicant First Name" + }, + { + "name": "Applicant Last Name", + "description": "OPTIONAL: Applicant Last Name" + }, + { + "name": "Applicant Email Address", + "description": "OPTIONAL: Applicant Email Address" + }, + { + "name": "Applicant Phone", + "description": "OPTIONAL: Applicant Phone (+nn.nnnnnnnn)" + }, + { + "name": "Domain Control Validation Method", + "description": "OPTIONAL: Domain Control Validation Method (e.g. EMAIL)" + }, + { + "name": "Organization Contact", + "description": "OPTIONAL: Organization Contact (selected from CSC configuration)" + }, + { + "name": "Business Unit", + "description": "OPTIONAL: Business Unit (selected from CSC configuration)" + }, + { + "name": "Notification Email(s) Comma Separated", + "description": "OPTIONAL: Notification Email(s), comma separated" + }, + { + "name": "CN DCV Email", + "description": "OPTIONAL: CN DCV Email (e.g. admin@yourdomain.com)" + }, + { + "name": "Organization Country", + "description": "OPTIONAL: Organization Country" + }, + { + "name": "Addtl Sans Comma Separated DCV Emails", + "description": "OPTIONAL: Additional SANs DCV Emails, comma separated" + } + ], "product_ids": [ "CSC TrustedSecure Premium Certificate", "CSC TrustedSecure EV Certificate", From 8310fd60ab5e3cc08be8993268cadd5d119e6842 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Fri, 21 Nov 2025 21:46:12 +0000 Subject: [PATCH 5/5] Update generated docs --- README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 412fe75..dbf509b 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@

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

@@ -53,7 +53,7 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and 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 [CSCGlobal CA Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/cscglobal-caplugin-dev/releases/latest) from GitHub. +2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [CSCGlobal CA Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/cscglobal-caplugin/releases/latest) from GitHub. 3. Copy the unzipped directory (usually called `net6.0` or `net8.0`) to the Extensions directory: @@ -113,12 +113,12 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A - Applicant Phone (+nn.nnnnnnnn) | String | N/A + Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A - CN DCV Email (admin@yourdomain.com) | String | N/A + CN DCV Email | String | N/A **CSC TrustedSecure EV Certificate - Details Tab** @@ -141,12 +141,12 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A - Applicant Phone (+nn.nnnnnnnn) | String | N/A + Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A - CN DCV Email (admin@yourdomain.com) | String | N/A + CN DCV Email | String | N/A Organization Country | String | N/A **CSC TrustedSecure UC Certificate - Details Tab** @@ -170,12 +170,12 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A - Applicant Phone (+nn.nnnnnnnn) | String | N/A + Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A - CN DCV Email (admin@yourdomain.com) | String | N/A + CN DCV Email | String | N/A Addtl Sans Comma Separated DCV Emails | String | N/A @@ -200,12 +200,12 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A - Applicant Phone (+nn.nnnnnnnn) | String | N/A + Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A - CN DCV Email (admin@yourdomain.com) | String | N/A + CN DCV Email | String | N/A **CSC TrustedSecure Domain Validated SSL - Details Tab** @@ -228,12 +228,12 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A - Applicant Phone (+nn.nnnnnnnn) | String | N/A + Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A - CN DCV Email (admin@yourdomain.com) | String | N/A + CN DCV Email | String | N/A **CSC TrustedSecure Domain Validated Wildcard SSL - Details Tab** @@ -256,12 +256,12 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A - Applicant Phone (+nn.nnnnnnnn) | String | N/A + Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A - CN DCV Email (admin@yourdomain.com) | String | N/A + CN DCV Email | String | N/A **CSC TrustedSecure Domain Validated UC Certificate - Details Tab** @@ -284,12 +284,12 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and Applicant First Name | String | N/A Applicant Last Name | String | N/A Applicant Email Address | String | N/A - Applicant Phone (+nn.nnnnnnnn) | String | N/A + Applicant Phone | String | N/A Domain Control Validation Method | Multiple Choice | EMAIL Organization Contact | Multiple Choice | Get From CSC Differs For Clients Business Unit | Multiple Choice | Get From CSC Differs For Clients Notification Email(s) Comma Separated | String | N/A - CN DCV Email (admin@yourdomain.com) | String | N/A + CN DCV Email | String | N/A Addtl Sans Comma Separated DCV Emails | String | N/A 3. Follow the [official Keyfactor documentation](https://software.keyfactor.com/Guides/AnyCAGatewayREST/Content/AnyCAGatewayREST/AddCA-Keyfactor.htm) to add each defined Certificate Authority to Keyfactor Command and import the newly defined Certificate Templates.