Skip to content

Commit 3c7d747

Browse files
committed
client cert support
1 parent e361fa7 commit 3c7d747

3 files changed

Lines changed: 64 additions & 9 deletions

File tree

digicert-certcentral-caplugin/API/OrderCertificate.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ public class CertificateRequest
8484
[JsonProperty("dns_names")]
8585
public List<string> DNSNames { get; set; }
8686

87+
[JsonProperty("emails")]
88+
public List<String> Emails { get; set; }
89+
8790
[JsonProperty("csr")]
8891
public string CSR { get; set; }
8992

digicert-certcentral-caplugin/CertCentralCAPlugin.cs

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Microsoft.Extensions.Logging;
1212
using Microsoft.Extensions.Logging.Abstractions;
1313
using Microsoft.VisualBasic;
14+
using Microsoft.Win32.SafeHandles;
1415

1516
using Newtonsoft.Json;
1617

@@ -70,11 +71,12 @@ public async Task<EnrollmentResult> Enroll(string csr, string subject, Dictionar
7071
CertCentralCertType certType = CertCentralCertType.GetAllTypes(_config).FirstOrDefault(x => x.ProductCode.Equals(productInfo.ProductID));
7172
OrderRequest orderRequest = new OrderRequest(certType);
7273

73-
//var days = (productInfo.ProductParameters.ContainsKey("LifetimeDays") && !st) ? int.Parse(productInfo.ProductParameters["LifetimeDays"]) : 365;
74+
string typeOfCert = (productInfo.ProductParameters.ContainsKey(CertCentralConstants.Config.CERT_TYPE)) ? productInfo.ProductParameters[CertCentralConstants.Config.CERT_TYPE].ToLower() : "ssl";
75+
7476
var days = 365;
75-
if (productInfo.ProductParameters.ContainsKey("LifetimeDays") && !string.IsNullOrEmpty(productInfo.ProductParameters["LifetimeDays"]))
77+
if (productInfo.ProductParameters.ContainsKey(CertCentralConstants.Config.LIFETIME) && !string.IsNullOrEmpty(productInfo.ProductParameters[CertCentralConstants.Config.LIFETIME]))
7678
{
77-
days = int.Parse(productInfo.ProductParameters["LifetimeDays"]);
79+
days = int.Parse(productInfo.ProductParameters[CertCentralConstants.Config.LIFETIME]);
7880
}
7981
int validityYears = 0;
8082
DateTime? customExpirationDate = null;
@@ -90,16 +92,31 @@ public async Task<EnrollmentResult> Enroll(string csr, string subject, Dictionar
9092
break;
9193
}
9294

95+
// Convert to case-insensitive dictionary
96+
Dictionary<string, string[]> sandict = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
97+
foreach (var s in san)
98+
{
99+
sandict.Add(s.Key, s.Value);
100+
}
101+
93102
List<string> dnsNames = new List<string>();
94-
if (san.ContainsKey("Dns"))
103+
List<string> emails = new List<string>();
104+
if (sandict.ContainsKey("Dns"))
95105
{
96106
dnsNames = new List<string>(san["Dns"]);
97107
}
98-
99-
if (san.ContainsKey("dnsname"))
108+
if (sandict.ContainsKey("dnsname"))
100109
{
101110
dnsNames = new List<string>(san["dnsname"]);
102111
}
112+
if (sandict.ContainsKey("Email"))
113+
{
114+
emails = new List<string>(san["Email"]);
115+
}
116+
if (sandict.ContainsKey("Rfc822Name"))
117+
{
118+
emails = new List<string>(san["Rfc822Name"]);
119+
}
103120

104121
X509Name subjectParsed = null;
105122
string commonName = null, organization = null, orgUnit = null;
@@ -114,13 +131,24 @@ public async Task<EnrollmentResult> Enroll(string csr, string subject, Dictionar
114131

115132
if (commonName == null)
116133
{
117-
if (dnsNames.Count > 0)
134+
if (typeOfCert.Equals("ssl") && dnsNames.Count > 0)
118135
{
119136
commonName = dnsNames[0];
120137
}
138+
else if (typeOfCert.Equals("client") && emails.Count > 0)
139+
{
140+
commonName = emails[0];
141+
}
121142
else
122143
{
123-
throw new Exception("No Common Name or DNS SAN provided, unable to enroll");
144+
throw new Exception("No Common Name or SAN provided, unable to enroll");
145+
}
146+
}
147+
else
148+
{
149+
if (typeOfCert.Equals("client") && emails.Count == 0)
150+
{
151+
emails.Add(commonName);
124152
}
125153
}
126154

@@ -190,7 +218,14 @@ public async Task<EnrollmentResult> Enroll(string csr, string subject, Dictionar
190218
orderRequest.Certificate.CommonName = commonName;
191219
orderRequest.Certificate.CSR = csr;
192220
orderRequest.Certificate.SignatureHash = signatureHash;
193-
orderRequest.Certificate.DNSNames = dnsNames;
221+
if (typeOfCert.Equals("ssl"))
222+
{
223+
orderRequest.Certificate.DNSNames = dnsNames;
224+
}
225+
else if (typeOfCert.Equals("client"))
226+
{
227+
orderRequest.Certificate.Emails = emails;
228+
}
194229
orderRequest.Certificate.CACertID = caCertId;
195230
orderRequest.SetOrganization(organizationId);
196231
if (!string.IsNullOrEmpty(orgUnit))
@@ -524,6 +559,13 @@ public Dictionary<string, PropertyConfigInfo> GetTemplateParameterAnnotations()
524559
Hidden = false,
525560
DefaultValue = 90,
526561
Type = "Number"
562+
},
563+
[CertCentralConstants.Config.CERT_TYPE] = new PropertyConfigInfo()
564+
{
565+
Comments = "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'.",
566+
Hidden = false,
567+
DefaultValue = "ssl",
568+
Type = "String"
527569
}
528570
};
529571
}
@@ -864,6 +906,15 @@ public async Task ValidateProductInfo(EnrollmentProductInfo productInfo, Diction
864906
}
865907
CertCentralClient client = new CertCentralClient(apiKey, region);
866908

909+
if (connectionInfo.ContainsKey(CertCentralConstants.Config.CERT_TYPE))
910+
{
911+
var typeOfCert = (string)connectionInfo[CertCentralConstants.Config.CERT_TYPE];
912+
if (!(typeOfCert.Equals("ssl") || typeOfCert.Equals("client")))
913+
{
914+
throw new Exception("Invalid Cert Type specified. Valid options are 'ssl' or 'client'");
915+
}
916+
}
917+
867918
// Get the available types and check that it's one of them.
868919
// We're doing this because to get the list of valid product IDs in a comment, the user must have at least one correct product/template mapping.
869920
// We therefore need to have some way of telling them what the valid product IDs are to begin with.

digicert-certcentral-caplugin/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class Config
3030
public const string SYNC_CA_FILTER = "SyncCAFilter";
3131
public const string FILTER_EXPIRED = "FilterExpiredOrders";
3232
public const string SYNC_EXPIRATION_DAYS = "SyncExpirationDays";
33+
public const string CERT_TYPE = "CertType";
3334
}
3435

3536
public class RequestAttributes

0 commit comments

Comments
 (0)