Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,18 @@
* Add support for enrolling for client certs
* Option to filter sync by division ID
* Option to provide division ID for enrollment
* Add support for secure_email_* SMIME product types
* Add support for secure_email_* SMIME product types

### 2.1.1
* Add configuration flag to support adding client auth EKU to ssl cert requests
* NOTE: This is a temporary feature which is planned for loss of support by Digicert in May 2026
* For smime certs, use profile type defined on the product as the default if not supplied, rather than just defaulting to 'strict'
* Hotfix for data type conversion

### 2.1.2
* Hotfix for incremental sync to default to a 6 day window if no previous incremental sync has run
* Workaround for DigiCert API issue where retrieving the PEM data of multiple certificates in the same order can occasionally return duplicate data rather than the correct cert
* Remove caching of product ID lookups from DigiCert account

### 2.2.0
* Add support for duplicating certs
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,20 @@ An API Key within your Digicert account that has the necessary permissions to en
* **Organization-Name** - OPTIONAL: For requests that will not have a subject (such as ACME) you can use this field to provide the organization name. Value supplied here will override any CSR values, so do not include this field if you want the organization from the CSR to be used.
* **RenewalWindowDays** - OPTIONAL: The number of days from certificate expiration that the gateway should do a renewal rather than a reissue. If not provided, default is 90.
* **CertType** - OPTIONAL: The type of cert to enroll for. Valid values are 'ssl' and 'client'. The value provided here must be consistant with the ProductID. If not provided, default is 'ssl'. Ignored for secure_email_* product types.
* **IncludeClientAuthEKU** - OPTIONAL for SSL certs, ignored otherwise. If set to 'true', SSL certs enrolled under this template will have the Client Authentication EKU added to the request. NOTE: This feature is currently planned to be removed by DigiCert in May 2026.
* **EnrollDivisionId** - OPTIONAL: The division (container) ID to use for enrollments against this template.
* **CommonNameIndicator** - Required for secure_email_sponsor and secure_email_organization products, ignored otherwise. Defines the source of the common name. Valid values are: email_address, given_name_surname, pseudonym, organization_name
* **ProfileType** - Optional for secure_email_* types, ignored otherwise. Valid values are: strict, multipurpose. Default value is strict.
* **ProfileType** - Optional for secure_email_* types, ignored otherwise. Valid values are: strict, multipurpose. Use 'multipurpose' if your cert includes any additional EKUs such as client auth. Default if not provided is dependent on product configuration within Digicert portal.
* **FirstName** - Required for secure_email_* types if CommonNameIndicator is given_name_surname, ignored otherwise.
* **LastName** - Required for secure_email_* types if CommonNameIndicator is given_name_surname, ignored otherwise.
* **Pseudonym** - Required for secure_email_* types if CommonNameIndicator is pseudonym, ignored otherwise.
* **UsageDesignation** - Required for secure_email_* types, ignored otherwise. The primary usage of the certificate. Valid values are: signing, key_management, dual_use


## Certificate Duplicates

DigiCert supports the ability to duplicate existing certificate orders. To take advantage of this functionality, in Keyfactor Command, under the enrollment pattern you're using, create an Enrollment Field named 'Duplicate' of type Multiple Choice, and the values 'False', 'True'. When performing a renew operation against that enrollment pattern, set the value to True to tell the gateway to duplicate instead of renew. The field will be ignored on new enrollments.


## License

Expand Down
70 changes: 70 additions & 0 deletions digicert-certcentral-caplugin/API/Duplicate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Keyfactor.Extensions.CAPlugin.DigiCert.Models;
using Newtonsoft.Json;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Keyfactor.Extensions.CAPlugin.DigiCert.API
{
[Serializable]
public class DuplicateRequest : CertCentralBaseRequest
{
public DuplicateRequest(uint orderId)
{
Method = "POST";
OrderId = orderId;
Resource = $"services/v2/order/certificate/{OrderId}/duplicate";
Certificate = new CertificateDuplicateRequest();
}

[JsonProperty("certificate")]
public CertificateDuplicateRequest Certificate { get; set; }

[JsonProperty("order_id")]
public uint OrderId { get; set; }

[JsonProperty("skip_approval")]
public bool SkipApproval { get; set; }
}

public class CertificateDuplicateRequest
{
[JsonProperty("common_name")]
public string CommonName { get; set; }

[JsonProperty("dns_names")]
public List<string> DnsNames { get; set; }

[JsonProperty("csr")]
public string CSR { get; set; }

[JsonProperty("server_platform")]
public Server_platform ServerPlatform { get; set; }

[JsonProperty("signature_hash")]
public string SignatureHash { get; set; }

[JsonProperty("ca_cert_id")]
public string CACertID { get; set; }
}

public class DuplicateResponse : CertCentralBaseResponse
{
public DuplicateResponse()
{
Requests = new List<Requests>();
}

[JsonProperty("id")]
public int OrderId { get; set; }

[JsonProperty("requests")]
public List<Requests> Requests { get; set; }

[JsonProperty("certificate_chain")]
public List<CertificateChainElement> CertificateChain { get; set; }
}
}
3 changes: 3 additions & 0 deletions digicert-certcentral-caplugin/API/OrderCertificate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ public class CertificateRequest

[JsonProperty("ca_cert_id")]
public string CACertID { get; set; }

[JsonProperty("profile_option")]
public string ProfileOption { get; set; }
}

public class CertificateOrderContainer
Expand Down
139 changes: 117 additions & 22 deletions digicert-certcentral-caplugin/CertCentralCAPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Newtonsoft.Json;

using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Pqc.Crypto.Falcon;
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import 'using Org.BouncyCastle.Pqc.Crypto.Falcon;' appears to be unused. This namespace is typically used for post-quantum cryptography (Falcon signature scheme), but there are no references to Falcon types anywhere in this file. This unused import should be removed to keep the code clean and avoid confusion.

Suggested change
using Org.BouncyCastle.Pqc.Crypto.Falcon;

Copilot uses AI. Check for mistakes.

using System.Collections.Concurrent;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -294,33 +295,62 @@ public async Task<EnrollmentResult> Enroll(string csr, string subject, Dictionar
string priorCertSnString = null;
string priorCertReqID = null;

// Current gateway core leaves it up to the integration to determine if it is a renewal or a reissue
if (typeOfCert.Equals("ssl") && Convert.ToBoolean(productInfo.ProductParameters[CertCentralConstants.Config.INCLUDE_CLIENT_AUTH]))
{
orderRequest.Certificate.ProfileOption = "server_client_auth_eku";
_logger.LogWarning($"{CertCentralConstants.Config.INCLUDE_CLIENT_AUTH}: Ability to include client auth EKU in SSL certs is currently planned to cease in May 2026. Make sure any workflows that depend on this feature are updated before then to avoid interruptions.");
}
Comment on lines +298 to +302
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code calls 'Convert.ToBoolean(productInfo.ProductParameters[CertCentralConstants.Config.INCLUDE_CLIENT_AUTH])' without first checking if the key exists in the dictionary. This will throw a KeyNotFoundException if the INCLUDE_CLIENT_AUTH parameter is not present. Since this is an OPTIONAL parameter (as documented), consider using 'ContainsKey' to check for existence first, or use 'TryGetValue', before attempting the conversion.

Copilot uses AI. Check for mistakes.

bool dupe = false;
// Current gateway core leaves it up to the integration to determine if it is a renewal, a reissue, or a duplicate
if (enrollmentType == EnrollmentType.RenewOrReissue)
{
//// Determine if we're going to do a renew or a reissue.
//// Determine if we're going to do a renew, reissue, or duplicate.
priorCertSnString = productInfo.ProductParameters["PriorCertSN"];
_logger.LogTrace($"Attempting to retrieve the certificate with serial number {priorCertSnString}.");
var reqId = _certificateDataReader.GetRequestIDBySerialNumber(priorCertSnString).Result;
if (string.IsNullOrEmpty(reqId))
priorCertReqID = await _certificateDataReader.GetRequestIDBySerialNumber(priorCertSnString);
if (string.IsNullOrEmpty(priorCertReqID))
{
throw new Exception($"No certificate with serial number '{priorCertSnString}' could be found.");
}
var expDate = _certificateDataReader.GetExpirationDateByRequestId(reqId);

var renewCutoff = DateTime.Now.AddDays(renewWindow * -1);

if (expDate > renewCutoff)
if (productInfo.ProductParameters.ContainsKey(CertCentralConstants.Config.DUPLICATE))
{
string dupStr = productInfo.ProductParameters[CertCentralConstants.Config.DUPLICATE].ToString();
if (!bool.TryParse(dupStr, out dupe))
{
_logger.LogError($"Could not parse 'Duplicate' field as true or false. Check configuration. Value: {dupStr}");
throw new Exception($"Could not parse 'Duplicate' field as true or false. Check configuration");
}
}
if (!dupe)
{
_logger.LogTrace($"Certificate with serial number {priorCertSnString} is within renewal window");
enrollmentType = EnrollmentType.Renew;
var expDate = _certificateDataReader.GetExpirationDateByRequestId(priorCertReqID);

var renewCutoff = DateTime.Now.AddDays(renewWindow * -1);

if (expDate > renewCutoff)
{
_logger.LogTrace($"Certificate with serial number {priorCertSnString} is within renewal window");
enrollmentType = EnrollmentType.Renew;
}
else
{
_logger.LogTrace($"Certificate with serial number {priorCertSnString} is not within renewal window. Reissuing...");
enrollmentType = EnrollmentType.Reissue;
}
}
else
{
_logger.LogTrace($"Certificate with serial number {priorCertSnString} is not within renewal window. Reissuing...");
enrollmentType = EnrollmentType.Reissue;
_logger.LogTrace($"'Duplicate' flag set, performing duplication");
}
}

if (dupe)
{
return await Duplicate(client, productInfo, priorCertReqID, commonName, csr, dnsNames, signatureHash, caCertId);
}

// Check if the order has more validity in it (multi-year cert). If so, do a reissue instead of a renew
if (enrollmentType == EnrollmentType.Renew)
{
Expand Down Expand Up @@ -584,6 +614,13 @@ public Dictionary<string, PropertyConfigInfo> GetTemplateParameterAnnotations()
DefaultValue = "ssl",
Type = "String"
},
[CertCentralConstants.Config.INCLUDE_CLIENT_AUTH] = new PropertyConfigInfo()
{
Comments = "OPTIONAL for SSL certs, ignored otherwise. If set to 'true', SSL certs enrolled under this template will have the Client Authentication EKU added to the request. NOTE: This feature is currently planned to be removed by DigiCert in May 2026.",
Hidden = false,
DefaultValue = false,
Type = "Boolean"
},
[CertCentralConstants.Config.ENROLL_DIVISION_ID] = new PropertyConfigInfo()
{
Comments = "OPTIONAL: The division (container) ID to use for enrollments against this template.",
Expand All @@ -600,9 +637,9 @@ public Dictionary<string, PropertyConfigInfo> GetTemplateParameterAnnotations()
},
[CertCentralConstants.Config.PROFILE_TYPE] = new PropertyConfigInfo()
{
Comments = "Optional for secure_email_* types, ignored otherwise. Valid values are: strict, multipurpose. Default value is strict.",
Comments = "Optional for secure_email_* types, ignored otherwise. Valid values are: strict, multipurpose. Use 'multipurpose' if your cert includes any additional EKUs such as client auth. Default if not provided is dependent on product configuration within Digicert portal.",
Hidden = false,
DefaultValue = "strict",
DefaultValue = "",
Type = "String"
},
[CertCentralConstants.Config.FIRST_NAME] = new PropertyConfigInfo()
Expand Down Expand Up @@ -747,8 +784,14 @@ public async Task Synchronize(BlockingCollection<AnyCAPluginCertificate> blockin
{
_logger.MethodEntry(LogLevel.Trace);

lastSync = lastSync.HasValue ? lastSync.Value.AddHours(-7) : DateTime.MinValue; // DigiCert issue with treating the timezone as mountain time. -7 to accomodate DST
// DigiCert issue with treating the timezone as mountain time. -7 hours to accomodate DST
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment contains a spelling error: 'accomodate' should be spelled 'accommodate' (with two 'm's).

Suggested change
// DigiCert issue with treating the timezone as mountain time. -7 hours to accomodate DST
// DigiCert issue with treating the timezone as mountain time. -7 hours to accommodate DST

Copilot uses AI. Check for mistakes.
// If no last sync, use a 6 day window for the sync range (only relevant for incremental syncs)
lastSync = lastSync.HasValue ? lastSync.Value.AddHours(-7) : DateTime.UtcNow.AddDays(-5);
DateTime? utcDate = DateTime.UtcNow.AddDays(1);
if ((utcDate.Value - lastSync.Value).Days > 6)
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The date calculation uses '.Days' property which returns only the whole number of days in the TimeSpan, potentially losing precision. For example, if the difference is 6.5 days, this will evaluate to 6 and the condition won't trigger. Consider using '.TotalDays' instead and comparing with a double value, or ensure this behavior is intentional for the sync window logic.

Suggested change
if ((utcDate.Value - lastSync.Value).Days > 6)
if ((utcDate.Value - lastSync.Value).TotalDays > 6.0)

Copilot uses AI. Check for mistakes.
{
lastSync = DateTime.UtcNow.AddDays(-5);
}
string lastSyncFormat = FormatSyncDate(lastSync);
string todaySyncFormat = FormatSyncDate(utcDate);

Expand Down Expand Up @@ -1023,7 +1066,7 @@ public async Task ValidateProductInfo(EnrollmentProductInfo productInfo, Diction
detailsRequest.ContainerId = null;
if (connectionInfo.ContainsKey(CertCentralConstants.Config.DIVISION_ID))
{
string div = (string)connectionInfo[CertCentralConstants.Config.DIVISION_ID];
string div = connectionInfo[CertCentralConstants.Config.DIVISION_ID].ToString();
if (!string.IsNullOrWhiteSpace(div))
{
if (int.TryParse($"{div}", out int divId))
Expand Down Expand Up @@ -1440,6 +1483,46 @@ private async Task<EnrollmentResult> Reissue(CertCentralClient client, Enrollmen
return await ExtractEnrollmentResult(client, client.ReissueCertificate(reissueRequest), commonName);
}

/// <summary>
/// Duplicates a certificate.
/// </summary>
/// <param name="client">The client used to contact DigiCert.</param>
/// <param name="request">The <see cref="OrderRequest"/>.</param>
/// <param name="enrollmentProductInfo">Information about the DigiCert product this certificate uses.</param>
/// <returns></returns>
Comment on lines +1490 to +1492
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter documentation mentions 'request' with type 'OrderRequest', but this parameter does not exist in the method signature. The method actually has individual parameters like 'enrollmentProductInfo', 'caRequestId', 'commonName', etc. Update the documentation to accurately reflect the actual parameters or remove the incorrect parameter reference.

Suggested change
/// <param name="request">The <see cref="OrderRequest"/>.</param>
/// <param name="enrollmentProductInfo">Information about the DigiCert product this certificate uses.</param>
/// <returns></returns>
/// <param name="enrollmentProductInfo">Information about the DigiCert product this certificate uses.</param>
/// <param name="caRequestId">The CA request identifier from which to derive the original order ID.</param>
/// <param name="commonName">The common name (CN) for the certificate.</param>
/// <param name="csr">The certificate signing request (CSR) for the new duplicate certificate.</param>
/// <param name="dnsNames">Additional DNS names (SANs) to include in the duplicate certificate.</param>
/// <param name="signatureHash">The signature hash algorithm to use.</param>
/// <param name="caCertId">The DigiCert CA certificate identifier to use for issuance.</param>
/// <returns>The result of the duplicate enrollment operation.</returns>

Copilot uses AI. Check for mistakes.
private async Task<EnrollmentResult> Duplicate(CertCentralClient client, EnrollmentProductInfo enrollmentProductInfo, string caRequestId, string commonName, string csr, List<string> dnsNames, string signatureHash, string caCertId)
{
CheckProductExistence(enrollmentProductInfo.ProductID);

// Get order ID
_logger.LogTrace("Attempting to parse the order ID from the AnyGateway certificate.");
uint orderId = 0;
try
{
orderId = uint.Parse(caRequestId.Split('-').First());
}
catch (Exception e)
{
throw new Exception($"There was an error parsing the order ID from the certificate: {e.Message}", e);
}

// Duplicate certificate.
DuplicateRequest duplicateRequest = new DuplicateRequest(orderId)
{
Certificate = new CertificateDuplicateRequest
{
CommonName = commonName,
CSR = csr,
DnsNames = dnsNames,
SignatureHash = signatureHash,
CACertID = caCertId
}
};
Comment on lines +1510 to +1520
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DuplicateRequest is created without setting 'SkipApproval', which will default to false. The similar Reissue method explicitly sets 'SkipApproval = true' with a comment explaining it allows the certificate ID to return a value (see line 1479). Consider whether the Duplicate method should also set 'SkipApproval = true' for consistency and to ensure the certificate ID is returned, unless there's a specific reason for the different behavior.

Copilot uses AI. Check for mistakes.

_logger.LogTrace("Attempting to duplicate certificate.");
return await ExtractEnrollmentResult(client, client.DuplicateCertificate(duplicateRequest), commonName);
}

/// <summary>
/// Verify that the given product ID is valid
/// </summary>
Expand Down Expand Up @@ -1544,6 +1627,7 @@ private List<AnyCAPluginCertificate> GetAllConnectorCertsForOrder(string caReque
var orderCerts = GetAllCertsForOrder(orderId);

List<AnyCAPluginCertificate> certList = new List<AnyCAPluginCertificate>();
List<string> pemList = new List<string>();

foreach (var cert in orderCerts)
{
Expand All @@ -1565,6 +1649,13 @@ private List<AnyCAPluginCertificate> GetAllConnectorCertsForOrder(string caReque
throw new Exception($"Unexpected error downloading certificate {certId} for order {orderId}: {certificateChainResponse.Errors.FirstOrDefault()?.message}");
}
}
//Another check for duplicate PEMs to get arround issue with DigiCert API returning incorrect data sometimes on reissued/duplicate certs
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment contains a spelling error: 'arround' should be spelled 'around' (with one 'r').

Suggested change
//Another check for duplicate PEMs to get arround issue with DigiCert API returning incorrect data sometimes on reissued/duplicate certs
//Another check for duplicate PEMs to get around issue with DigiCert API returning incorrect data sometimes on reissued/duplicate certs

Copilot uses AI. Check for mistakes.
if (pemList.Contains(certificate))
{
_logger.LogWarning($"Found duplicate PEM for ID {caReqId}. Skipping...");
continue;
}
pemList.Add(certificate);
Comment on lines +1652 to +1658
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'certificate' variable could be null if the certificate status is not GENERATED or REVOKED (line 1639-1650), but it's added to 'pemList' unconditionally at line 1658. This means null values could be added to the list, and the duplicate check at line 1653 would match multiple null values incorrectly. Consider only adding to pemList when certificate is not null, or restructure the logic to handle null certificates appropriately.

Suggested change
//Another check for duplicate PEMs to get arround issue with DigiCert API returning incorrect data sometimes on reissued/duplicate certs
if (pemList.Contains(certificate))
{
_logger.LogWarning($"Found duplicate PEM for ID {caReqId}. Skipping...");
continue;
}
pemList.Add(certificate);
//Another check for duplicate PEMs to get around issue with DigiCert API returning incorrect data sometimes on reissued/duplicate certs
if (certificate != null)
{
if (pemList.Contains(certificate))
{
_logger.LogWarning($"Found duplicate PEM for ID {caReqId}. Skipping...");
continue;
}
pemList.Add(certificate);
}

Copilot uses AI. Check for mistakes.
var connCert = new AnyCAPluginCertificate
{
CARequestID = caReqId,
Expand Down Expand Up @@ -1680,9 +1771,10 @@ private EnrollmentResult EnrollForSmimeCert(string csr, string subject, Dictiona
}
}

string profile = null;
if (productInfo.ProductParameters.ContainsKey(CertCentralConstants.Config.PROFILE_TYPE))
{
string profile = productInfo.ProductParameters[CertCentralConstants.Config.PROFILE_TYPE].ToString();
profile = productInfo.ProductParameters[CertCentralConstants.Config.PROFILE_TYPE].ToString();

// Only validate if value provided
if (!string.IsNullOrEmpty(profile))
Expand All @@ -1693,6 +1785,10 @@ private EnrollmentResult EnrollForSmimeCert(string csr, string subject, Dictiona
throw new Exception($"Invalid profile type provided. Valid values are: strict, multipurpose");
}
}
else
{
profile = null;
}
Comment on lines +1788 to +1791
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The else block at lines 1788-1791 that sets 'profile = null' is redundant. The variable 'profile' is already initialized to null at line 1774, and the only assignment inside the if block (line 1777) converts the parameter to a string. If that string is empty, it won't pass the validation at line 1780-1786 and profile would remain as set. This else block appears unnecessary and could be removed for clarity.

Suggested change
else
{
profile = null;
}

Copilot uses AI. Check for mistakes.
}

if (cnIndic.Equals("given_name_surname", StringComparison.OrdinalIgnoreCase))
Expand Down Expand Up @@ -1884,12 +1980,11 @@ private EnrollmentResult EnrollForSmimeCert(string csr, string subject, Dictiona
orderRequest.Certificate.SignatureHash = certType.signatureAlgorithm;
orderRequest.Certificate.CACertID = caCertId;
orderRequest.SetOrganization(organizationId);
string profileType = "strict";
if (productInfo.ProductParameters.ContainsKey(Constants.Config.PROFILE_TYPE))
//If profile type is not provided, use the default on the digicert product configuration
if (!string.IsNullOrEmpty(profile))
{
profileType = productInfo.ProductParameters[Constants.Config.PROFILE_TYPE];
}
orderRequest.Certificate.ProfileType = profileType;
orderRequest.Certificate.ProfileType = profile;
}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line has trailing whitespace after the closing brace. Consider removing the trailing whitespace to maintain code cleanliness and consistency.

Suggested change
}
}

Copilot uses AI. Check for mistakes.
orderRequest.Certificate.CommonNameIndicator = cnIndicator;
if (productInfo.ProductID.Equals("secure_email_sponsor", StringComparison.OrdinalIgnoreCase))
{
Expand Down
22 changes: 22 additions & 0 deletions digicert-certcentral-caplugin/Client/CertCentralClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@

Logger.LogTrace($"Entered CertCentral Request (ID: {reqID}) Method: {request.Method} - URL: {targetURI}");

HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(targetURI);

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 100 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

'WebRequest.Create(string)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)
objRequest.Method = request.Method;
objRequest.Headers.Add("X-DC-DEVKEY", this.CertCentralCreds.APIKey);

Expand Down Expand Up @@ -148,13 +148,13 @@
}
else
{
Logger.LogDebug("CertCentral Response Error", wex);

Check warning on line 151 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 151 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 151 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 151 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 151 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 151 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 151 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 151 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 151 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)
throw new Exception("Unable to establish connection to CertCentral web service", wex);
}
}
catch (Exception ex)
{
Logger.LogError("CertCentral Response Error", ex);

Check warning on line 157 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 157 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 157 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-generate-readme-workflow / Use private doctool action in public repository

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 157 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 157 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 157 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 157 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 157 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)

Check warning on line 157 in digicert-certcentral-caplugin/Client/CertCentralClient.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

Number of parameters supplied in the logging message template do not match the number of named placeholders (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017)
throw new Exception("Unable to establish connection to CertCentral web service", ex);
}

Expand Down Expand Up @@ -357,6 +357,28 @@
return reissueResponse;
}

public OrderResponse DuplicateCertificate(DuplicateRequest request)
{
string jsonRequest = JsonConvert.SerializeObject(request, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
Logger.LogTrace($"Duplicate request:\n{jsonRequest}");

CertCentralResponse response = Request(request, jsonRequest);

OrderResponse duplicateResponse = new OrderResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
duplicateResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
duplicateResponse.Errors = errors.errors;
}
else
{
duplicateResponse = JsonConvert.DeserializeObject<OrderResponse>(response.Response);
}

return duplicateResponse;
}

public RevokeCertificateResponse RevokeCertificate(RevokeCertificateRequest request)
{
CertCentralResponse response = Request(request, JsonConvert.SerializeObject(request, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));
Expand Down
Loading