Skip to content

Commit 418af78

Browse files
authored
Merge pull request #15 from Keyfactor/release1.0_dev
Release1.0.10
2 parents 46b4c0e + 3fc187b commit 418af78

File tree

8 files changed

+141
-133
lines changed

8 files changed

+141
-133
lines changed
Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,19 @@
1-
name: Starter Workflow
2-
on: [workflow_dispatch, push, pull_request]
1+
name: Keyfactor Bootstrap Workflow
32

4-
jobs:
5-
call-create-github-release-workflow:
6-
uses: Keyfactor/actions/.github/workflows/github-release.yml@main
7-
get-manifest-properties:
8-
runs-on: windows-latest
9-
outputs:
10-
update_catalog: ${{ steps.read-json.outputs.prop }}
11-
steps:
12-
- uses: actions/checkout@v3
13-
- name: Read json
14-
id: read-json
15-
shell: pwsh
16-
run: |
17-
$json = Get-Content integration-manifest.json | ConvertFrom-Json
18-
echo "::set-output name=prop::$(echo $json.update_catalog)"
19-
20-
call-dotnet-build-and-release-workflow:
21-
needs: [call-create-github-release-workflow]
22-
uses: Keyfactor/actions/.github/workflows/dotnet-build-and-release.yml@main
23-
with:
24-
release_version: ${{ needs.call-create-github-release-workflow.outputs.release_version }}
25-
release_url: ${{ needs.call-create-github-release-workflow.outputs.release_url }}
26-
release_dir: DigiCertSymCaProxy\bin\Release
27-
secrets:
28-
token: ${{ secrets.PRIVATE_PACKAGE_ACCESS }}
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
types: [opened, closed, synchronize, edited, reopened]
7+
push:
8+
create:
9+
branches:
10+
- 'release-*.*'
2911

30-
call-generate-readme-workflow:
31-
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
32-
uses: Keyfactor/actions/.github/workflows/generate-readme.yml@main
12+
jobs:
13+
call-starter-workflow:
14+
uses: keyfactor/actions/.github/workflows/starter.yml@v2
3315
secrets:
34-
token: ${{ secrets.APPROVE_README_PUSH }}
35-
36-
call-update-catalog-workflow:
37-
needs: get-manifest-properties
38-
if: needs.get-manifest-properties.outputs.update_catalog == 'True' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
39-
uses: Keyfactor/actions/.github/workflows/update-catalog.yml@main
40-
secrets:
41-
token: ${{ secrets.SDK_SYNC_PAT }}
16+
token: ${{ secrets.V2BUILDTOKEN}}
17+
APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}}
18+
gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }}
19+
gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }}

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
1.0.10
2+
* Fixed bug with multiple DNS entries and fixed IP Sans issue
3+
14
1.0.9
25
* Initial Public Release Version

DigiCertSymCaProxy/Client/Models/San.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ public class San : ISan
2222
[JsonProperty("other_name", NullValueHandling = NullValueHandling.Ignore)] public List<OtherName> OtherName { get; set; }
2323
[JsonProperty("registered_id", NullValueHandling = NullValueHandling.Ignore)] public List<RegisteredId> RegisteredId { get; set; }
2424
[JsonProperty("rfc822_name", NullValueHandling = NullValueHandling.Ignore)] public List<Rfc822Name> Rfc822Name { get; set; }
25-
[JsonProperty("user_principal_name", NullValueHandling = NullValueHandling.Ignore)] public List<UserPrincipalName> UserPrincipalName { get; set; }
25+
[JsonProperty("user_principal_name", NullValueHandling = NullValueHandling.Ignore)] public List<UserPrincipalName> UserPrincipalName { get; set; }
2626
}
2727
}

DigiCertSymCaProxy/DigiCertSymProxy.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ public override CAConnectorCertificate GetSingleRecord(string caRequestId)
283283
try
284284
{
285285
Logger.MethodEntry(ILogExtensions.MethodLogLevel.Debug);
286+
if (string.IsNullOrEmpty(caRequestId))
287+
return null;
288+
286289
var keyfactorCaId = caRequestId;
287290
Logger.Trace($"Keyfactor Ca Id: {keyfactorCaId}");
288291
var certificateResponse =

DigiCertSymCaProxy/RequestManager.cs

Lines changed: 98 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
// Copyright 2023 Keyfactor
2-
// Licensed under the Apache License, Version 2.0 (the "License"); you may
3-
// not use this file except in compliance with the License. You may obtain a
4-
// copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless
5-
// required by applicable law or agreed to in writing, software distributed
6-
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
7-
// OR CONDITIONS OF ANY KIND, either express or implied. See the License for
8-
// thespecific language governing permissions and limitations under the
9-
// License.
10-
using System;
1+
// Copyright 2023 Keyfactor
2+
// Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
// not use this file except in compliance with the License. You may obtain a
4+
// copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless
5+
// required by applicable law or agreed to in writing, software distributed
6+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
7+
// OR CONDITIONS OF ANY KIND, either express or implied. See the License for
8+
// thespecific language governing permissions and limitations under the
9+
// License.
10+
using System;
1111
using System.Collections.Generic;
1212
using System.IO;
1313
using System.Reflection;
@@ -23,6 +23,7 @@
2323
using Org.BouncyCastle.Asn1.Pkcs;
2424
using Org.BouncyCastle.OpenSsl;
2525
using Org.BouncyCastle.Pkcs;
26+
using System.Linq;
2627

2728
namespace Keyfactor.AnyGateway.DigiCertSym
2829
{
@@ -232,6 +233,49 @@ public SearchCertificateRequestType GetSearchCertificatesRequest(int pageCounter
232233
}
233234
}
234235

236+
private (Dictionary<string, string> DNSOut, Dictionary<string, string> MultiOut) ProcessSansArray(
237+
string[] sanArray, string commonName)
238+
{
239+
Dictionary<string, string> dnsOut = new Dictionary<string, string>();
240+
Dictionary<string, string> multiOut = new Dictionary<string, string>();
241+
242+
if (sanArray.Length == 1)
243+
{
244+
var singleItem = sanArray.First();
245+
if (singleItem == commonName || string.IsNullOrWhiteSpace(commonName))
246+
{
247+
dnsOut.Add(singleItem, singleItem);
248+
}
249+
else
250+
{
251+
throw new InvalidOperationException("Error: Single item does not match CommonName.");
252+
}
253+
}
254+
else if (sanArray.Length > 1)
255+
{
256+
if (!string.IsNullOrWhiteSpace(commonName))
257+
{
258+
if (!sanArray.Contains(commonName))
259+
{
260+
throw new InvalidOperationException("Error: Multiple items, none of them match CommonName.");
261+
}
262+
else
263+
{
264+
dnsOut.Add(commonName, commonName);
265+
multiOut = sanArray.Where(item => item != commonName)
266+
.ToDictionary(item => item, item => item);
267+
}
268+
}
269+
else
270+
{
271+
dnsOut.Add(sanArray.First(), sanArray.First());
272+
multiOut = sanArray.Skip(1).ToDictionary(item => item, item => item);
273+
}
274+
}
275+
276+
return (dnsOut, multiOut);
277+
}
278+
235279
public EnrollmentRequest GetEnrollmentRequest(EnrollmentProductInfo productInfo, string csr,
236280
Dictionary<string, string[]> san)
237281
{
@@ -303,38 +347,46 @@ public EnrollmentRequest GetEnrollmentRequest(EnrollmentProductInfo productInfo,
303347

304348
Logger.Trace($"Enrollment Serialized JSON before DNS and OU, result: {JsonConvert.SerializeObject(enrollmentRequest)}");
305349

306-
//5. Loop through DNS Entries, if coming from Cert bot, then need to get common name from here as well
350+
Dictionary<string, string> MultiOut=null;
351+
352+
List<DnsName> dnsList = new List<DnsName>();
353+
354+
//5. If it contains the dns and it is not multi domain get the DNS
307355
if (san.ContainsKey("dns"))
308356
{
309-
var dnsList = new List<DnsName>();
310357
var dnsKp = san["dns"];
311358
Logger.Trace($"dnsKP: {dnsKp}");
312-
var commonNameList = new List<string>();
313359

314-
var j = 1;
315-
foreach (var item in dnsKp)
360+
(Dictionary<string, string> DNSOut, Dictionary<string, string> MultiOut) result;
361+
362+
if (!getCommonNameFromSubject)
316363
{
317-
commonNameList.Add(item);
318-
if (j < 2)
319-
{
320-
DnsName dns = new DnsName { Id = DnsConstantName, Value = item };
321-
dnsList.Add(dns);
322-
}
323-
else
324-
{
325-
DnsName dns = new DnsName { Id = DnsConstantName + j, Value = item };
326-
dnsList.Add(dns);
327-
}
328-
j++;
364+
//Cert Bot flow, Cert Bot has no common name and the dns comes from the SAN blank for common name returns first DNS
365+
result = ProcessSansArray(dnsKp, "");
329366
}
330-
string commonName = string.Join(",", commonNameList);
367+
else
368+
{
369+
result = ProcessSansArray(dnsKp, enrollmentRequest?.Attributes?.CommonName);
370+
}
371+
372+
DnsName up = new DnsName { Id = DnsConstantName, Value = result.DNSOut.FirstOrDefault().Value };
331373

374+
MultiOut = result.MultiOut;
332375
var jsonResultDns = JsonConvert.SerializeObject(enrollmentRequest);
333376

334377
if (!getCommonNameFromSubject)
335-
jsonResultDns = ReplaceCsrEntry(new[] { "CN", commonName }, jsonResult);
378+
jsonResultDns = ReplaceCsrEntry(new[] { "CN", result.DNSOut.FirstOrDefault().Value }, jsonResult);
336379

337380
enrollmentRequest = JsonConvert.DeserializeObject<EnrollmentRequest>(jsonResultDns);
381+
dnsList.Add(up);
382+
383+
//5. Handle the multiple domain scenario domains go in a different attribute
384+
if (MultiOut?.Count > 0)
385+
{
386+
DnsName mdns = new DnsName { Id = "custom_encode_dnsName_multi", Value = string.Join(",", MultiOut.Values) };
387+
dnsList.Add(mdns);
388+
}
389+
338390
sn.DnsName = dnsList;
339391
}
340392

@@ -346,73 +398,37 @@ public EnrollmentRequest GetEnrollmentRequest(EnrollmentProductInfo productInfo,
346398

347399
Logger.Trace($"upn: {upKp}");
348400

349-
var k = 1;
350-
foreach (var item in upKp)
351-
{
352-
if (k < 2)
353-
{
354-
UserPrincipalName up = new UserPrincipalName { Id = UpnConstantName, Value = item };
355-
upList.Add(up);
356-
}
357-
else
358-
{
359-
UserPrincipalName up = new UserPrincipalName { Id = UpnConstantName + k, Value = item };
360-
upList.Add(up);
361-
}
362-
k++;
363-
}
401+
//Multiple UPNs not supported by Digicert so take the first one in the list
402+
UserPrincipalName up = new UserPrincipalName { Id = UpnConstantName, Value = upKp.FirstOrDefault() };
403+
upList.Add(up);
364404
sn.UserPrincipalName = upList;
365405
}
366406

367407
//7. Loop through IP Entries
368-
if (san.ContainsKey("ip4") || san.ContainsKey("ip6"))
408+
if (san.ContainsKey("ipaddress"))
369409
{
370410
var ipList = new List<IpAddress>();
371411

372-
var ipKp = san.ContainsKey("ip4") ? san["ip4"] : san["ip6"];
412+
var ipKp = san["ipaddress"];
373413
Logger.Trace($"ip: {ipKp}");
374414

375-
var k = 1;
376-
foreach (var item in ipKp)
377-
{
378-
if (k < 2)
379-
{
380-
IpAddress ip = new IpAddress { Id = IpConstantName, Value = item };
381-
ipList.Add(ip);
382-
}
383-
else
384-
{
385-
IpAddress ip = new IpAddress { Id = IpConstantName + k, Value = item };
386-
ipList.Add(ip);
387-
}
388-
k++;
389-
}
415+
//Multiple IP Addresses not supported by Digicert so take the first one in the list
416+
IpAddress ip = new IpAddress { Id = IpConstantName, Value = ipKp.FirstOrDefault() };
417+
ipList.Add(ip);
390418
sn.IpAddress = ipList;
391419
}
392420

393421
//8. Loop through mail Entries
394-
if (san.ContainsKey("mail"))
422+
if (san.ContainsKey("email"))
395423
{
396424
var mailList = new List<Rfc822Name>();
397-
var mailKp = san["mail"];
425+
var mailKp = san["email"];
398426

399427
Logger.Trace($"mail: {mailKp}");
400428

401-
var k = 1;
402-
foreach (var item in mailKp)
403-
{
404-
if (k < 2)
405-
{
406-
Rfc822Name mail = new Rfc822Name { Id = EmailConstantName, Value = item };
407-
mailList.Add(mail);
408-
}
409-
else
410-
{
411-
Rfc822Name mail = new Rfc822Name { Id = EmailConstantName + k, Value = item };
412-
mailList.Add(mail);
413-
}
414-
k++;
415-
}
429+
//Multiple IP Addresses not supported by Digicert so take the first one in the list
430+
Rfc822Name mail = new Rfc822Name { Id = EmailConstantName, Value = mailKp.FirstOrDefault() };
431+
mailList.Add(mail);
416432
sn.Rfc822Name = mailList;
417433
}
418434

@@ -425,11 +441,11 @@ public EnrollmentRequest GetEnrollmentRequest(EnrollmentProductInfo productInfo,
425441
var i = OuStartPoint;
426442
foreach (var ou in organizationalUnits)
427443
{
428-
var organizationUnit = new OrganizationUnit { Id = OuStartPoint==0?"cert_org_unit":"cert_org_unit" + i, Value = ou };
444+
var organizationUnit = new OrganizationUnit { Id = OuStartPoint == 0 ? "cert_org_unit" : "cert_org_unit" + i, Value = ou };
429445
orgUnits.Add(organizationUnit);
430446
i++;
431447
}
432-
448+
433449
var attributes = enrollmentRequest.Attributes;
434450
attributes.OrganizationUnit = orgUnits;
435451
attributes.San = sn;
@@ -463,8 +479,8 @@ public EnrollmentResult
463479
return new EnrollmentResult
464480
{
465481
Status = (int)PKIConstants.Microsoft.RequestDisposition.ISSUED, //success
466-
CARequestID = enrollmentResponse.Result.SerialNumber,
467-
Certificate = cert.Certificate,
482+
CARequestID = enrollmentResponse?.Result?.SerialNumber,
483+
Certificate = cert?.Certificate,
468484
StatusMessage =
469485
$"Order Successfully Created With Order Number {enrollmentResponse.Result.SerialNumber}"
470486
};

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
1+
12
# DigiCert mPKI AnyGateway
23

34
This gateway integration supports the Digicert MPKI platform. It handles Enrollment, Renewal, Revoke and inventory by multiple seat Ids.
45

56
#### Integration status: Production - Ready for use in production environments.
67

7-
88
## About the Keyfactor AnyGateway CA Connector
99

1010
This repository contains an AnyGateway CA Connector, which is a plugin to the Keyfactor AnyGateway. AnyGateway CA Connectors allow Keyfactor Command to be used for inventory, issuance, and revocation of certificates from a third-party certificate authority.
1111

12+
## Support for DigiCert mPKI AnyGateway
1213

14+
DigiCert mPKI AnyGateway is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com
1315

14-
16+
###### To report a problem or suggest a new feature, use the **[Issues](../../issues)** tab. If you want to contribute actual bug fixes or proposed enhancements, use the **[Pull requests](../../pulls)** tab.
1517

1618
---
1719

1820

21+
---
22+
1923

2024

2125

@@ -24,14 +28,16 @@ This repository contains an AnyGateway CA Connector, which is a plugin to the Ke
2428

2529
This gateway was compiled against version 22.1.1 of the AnyGateway Framework. You will need at least this version of the AnyGateway Framework Installed. If you have a later AnyGateway Framework Installed you will probably need to add binding redirects in the CAProxyServer.exe.config file to make things work properly.
2630

31+
[Keyfactor CAGateway Install Guide](https://software.keyfactor.com/Guides/AnyGateway_Generic/Content/AnyGateway/Introduction.htm)
32+
2733

2834

2935
---
3036

3137

3238
# Getting Started
3339
## Standard Gateway Installation
34-
To begin, you must have the CA Gateway Service 21.3.2 installed and operational before attempting to configure the DigiCertSym mPKI plugin. This integration was tested with Keyfactor 9.1.0.0.
40+
To begin, you must have the CA Gateway Service installed and operational before attempting to configure the DigiCertSym mPKI plugin. This integration was tested with Keyfactor 9.1.0.0.
3541
To install the gateway follow these instructions.
3642

3743
1) **Gateway Server** - Get the latest gateway .msi installer from Keyfactor and run the installation on the gateway server.

0 commit comments

Comments
 (0)