diff --git a/README.md b/README.md index 573438d..a731753 100644 --- a/README.md +++ b/README.md @@ -106,9 +106,10 @@ 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. diff --git a/digicert-certcentral-caplugin/API/OrderCertificate.cs b/digicert-certcentral-caplugin/API/OrderCertificate.cs index 71746db..1a30852 100644 --- a/digicert-certcentral-caplugin/API/OrderCertificate.cs +++ b/digicert-certcentral-caplugin/API/OrderCertificate.cs @@ -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 diff --git a/digicert-certcentral-caplugin/CertCentralCAPlugin.cs b/digicert-certcentral-caplugin/CertCentralCAPlugin.cs index 616f24c..ffc2c28 100644 --- a/digicert-certcentral-caplugin/CertCentralCAPlugin.cs +++ b/digicert-certcentral-caplugin/CertCentralCAPlugin.cs @@ -294,6 +294,11 @@ public async Task Enroll(string csr, string subject, Dictionar string priorCertSnString = null; string priorCertReqID = null; + if (typeOfCert.Equals("ssl") && Convert.ToBoolean(productInfo.ProductParameters[CertCentralConstants.Config.INCLUDE_CLIENT_AUTH])) + { + orderRequest.Certificate.ProfileOption = "server_client_auth_eku"; + } + // Current gateway core leaves it up to the integration to determine if it is a renewal or a reissue if (enrollmentType == EnrollmentType.RenewOrReissue) { @@ -584,6 +589,13 @@ public Dictionary 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.", @@ -600,7 +612,7 @@ public Dictionary 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", Type = "String" @@ -1023,7 +1035,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)) @@ -1680,9 +1692,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)) @@ -1693,6 +1706,10 @@ private EnrollmentResult EnrollForSmimeCert(string csr, string subject, Dictiona throw new Exception($"Invalid profile type provided. Valid values are: strict, multipurpose"); } } + else + { + profile = null; + } } if (cnIndic.Equals("given_name_surname", StringComparison.OrdinalIgnoreCase)) @@ -1884,12 +1901,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; + } orderRequest.Certificate.CommonNameIndicator = cnIndicator; if (productInfo.ProductID.Equals("secure_email_sponsor", StringComparison.OrdinalIgnoreCase)) { diff --git a/digicert-certcentral-caplugin/Constants.cs b/digicert-certcentral-caplugin/Constants.cs index 57e4ed2..c1a3bd3 100644 --- a/digicert-certcentral-caplugin/Constants.cs +++ b/digicert-certcentral-caplugin/Constants.cs @@ -32,6 +32,7 @@ public class Config public const string FILTER_EXPIRED = "FilterExpiredOrders"; public const string SYNC_EXPIRATION_DAYS = "SyncExpirationDays"; public const string CERT_TYPE = "CertType"; + public const string INCLUDE_CLIENT_AUTH = "IncludeClientAuthEKU"; public const string ENROLL_DIVISION_ID = "EnrollDivisionId"; public const string COMMON_NAME_INDICATOR = "CommonNameIndicator"; public const string PROFILE_TYPE = "ProfileType"; diff --git a/digicert-certcentral-caplugin/digicert-certcentral-caplugin.csproj b/digicert-certcentral-caplugin/digicert-certcentral-caplugin.csproj index 9edfa7f..84289d0 100644 --- a/digicert-certcentral-caplugin/digicert-certcentral-caplugin.csproj +++ b/digicert-certcentral-caplugin/digicert-certcentral-caplugin.csproj @@ -1,4 +1,4 @@ - + net6.0;net8.0 @@ -6,6 +6,8 @@ enable disable DigicertCAPlugin + 2.1.1 + 2.1.1 diff --git a/integration-manifest.json b/integration-manifest.json index ef10ed9..e211f33 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -72,6 +72,10 @@ "name": "CertType", "description": "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." }, + { + "name": "IncludeClientAuthEKU", + "description": "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." + }, { "name": "EnrollDivisionId", "description": "OPTIONAL: The division (container) ID to use for enrollments against this template." @@ -82,7 +86,7 @@ }, { "name": "ProfileType", - "description": "Optional for secure_email_* types, ignored otherwise. Valid values are: strict, multipurpose. Default value is strict." + "description": "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." }, { "name": "FirstName",