Skip to content

Commit

Permalink
Merge 6cdf908 into 46b4c0e
Browse files Browse the repository at this point in the history
  • Loading branch information
bhillkeyfactor committed Jan 26, 2024
2 parents 46b4c0e + 6cdf908 commit fcf522f
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 129 deletions.
54 changes: 16 additions & 38 deletions .github/workflows/keyfactor-starter-workflow.yml
Original file line number Diff line number Diff line change
@@ -1,41 +1,19 @@
name: Starter Workflow
on: [workflow_dispatch, push, pull_request]
name: Keyfactor Bootstrap Workflow

jobs:
call-create-github-release-workflow:
uses: Keyfactor/actions/.github/workflows/github-release.yml@main
get-manifest-properties:
runs-on: windows-latest
outputs:
update_catalog: ${{ steps.read-json.outputs.prop }}
steps:
- uses: actions/checkout@v3
- name: Read json
id: read-json
shell: pwsh
run: |
$json = Get-Content integration-manifest.json | ConvertFrom-Json
echo "::set-output name=prop::$(echo $json.update_catalog)"
call-dotnet-build-and-release-workflow:
needs: [call-create-github-release-workflow]
uses: Keyfactor/actions/.github/workflows/dotnet-build-and-release.yml@main
with:
release_version: ${{ needs.call-create-github-release-workflow.outputs.release_version }}
release_url: ${{ needs.call-create-github-release-workflow.outputs.release_url }}
release_dir: DigiCertSymCaProxy\bin\Release
secrets:
token: ${{ secrets.PRIVATE_PACKAGE_ACCESS }}
on:
workflow_dispatch:
pull_request:
types: [opened, closed, synchronize, edited, reopened]
push:
create:
branches:
- 'release-*.*'

call-generate-readme-workflow:
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
uses: Keyfactor/actions/.github/workflows/generate-readme.yml@main
jobs:
call-starter-workflow:
uses: keyfactor/actions/.github/workflows/starter.yml@v2
secrets:
token: ${{ secrets.APPROVE_README_PUSH }}

call-update-catalog-workflow:
needs: get-manifest-properties
if: needs.get-manifest-properties.outputs.update_catalog == 'True' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
uses: Keyfactor/actions/.github/workflows/update-catalog.yml@main
secrets:
token: ${{ secrets.SDK_SYNC_PAT }}
token: ${{ secrets.V2BUILDTOKEN}}
APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}}
gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }}
gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
1.0.10
* Fixed bug with multiple DNS entries and fixed IP Sans issue

1.0.9
* Initial Public Release Version
2 changes: 1 addition & 1 deletion DigiCertSymCaProxy/Client/Models/San.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ public class San : ISan
[JsonProperty("other_name", NullValueHandling = NullValueHandling.Ignore)] public List<OtherName> OtherName { get; set; }
[JsonProperty("registered_id", NullValueHandling = NullValueHandling.Ignore)] public List<RegisteredId> RegisteredId { get; set; }
[JsonProperty("rfc822_name", NullValueHandling = NullValueHandling.Ignore)] public List<Rfc822Name> Rfc822Name { get; set; }
[JsonProperty("user_principal_name", NullValueHandling = NullValueHandling.Ignore)] public List<UserPrincipalName> UserPrincipalName { get; set; }
[JsonProperty("user_principal_name", NullValueHandling = NullValueHandling.Ignore)] public List<UserPrincipalName> UserPrincipalName { get; set; }
}
}
3 changes: 3 additions & 0 deletions DigiCertSymCaProxy/DigiCertSymProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ public override CAConnectorCertificate GetSingleRecord(string caRequestId)
try
{
Logger.MethodEntry(ILogExtensions.MethodLogLevel.Debug);
if (string.IsNullOrEmpty(caRequestId))
return null;

var keyfactorCaId = caRequestId;
Logger.Trace($"Keyfactor Ca Id: {keyfactorCaId}");
var certificateResponse =
Expand Down
180 changes: 98 additions & 82 deletions DigiCertSymCaProxy/RequestManager.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Copyright 2023 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
// thespecific language governing permissions and limitations under the
// License.
using System;
// Copyright 2023 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
// thespecific language governing permissions and limitations under the
// License.
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
Expand All @@ -23,6 +23,7 @@
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using System.Linq;

namespace Keyfactor.AnyGateway.DigiCertSym
{
Expand Down Expand Up @@ -232,6 +233,49 @@ public SearchCertificateRequestType GetSearchCertificatesRequest(int pageCounter
}
}

private (Dictionary<string, string> DNSOut, Dictionary<string, string> MultiOut) ProcessSansArray(
string[] sanArray, string commonName)
{
Dictionary<string, string> dnsOut = new Dictionary<string, string>();
Dictionary<string, string> multiOut = new Dictionary<string, string>();

if (sanArray.Length == 1)
{
var singleItem = sanArray.First();
if (singleItem == commonName || string.IsNullOrWhiteSpace(commonName))
{
dnsOut.Add(singleItem, singleItem);
}
else
{
throw new InvalidOperationException("Error: Single item does not match CommonName.");
}
}
else if (sanArray.Length > 1)
{
if (!string.IsNullOrWhiteSpace(commonName))
{
if (!sanArray.Contains(commonName))
{
throw new InvalidOperationException("Error: Multiple items, none of them match CommonName.");
}
else
{
dnsOut.Add(commonName, commonName);
multiOut = sanArray.Where(item => item != commonName)
.ToDictionary(item => item, item => item);
}
}
else
{
dnsOut.Add(sanArray.First(), sanArray.First());
multiOut = sanArray.Skip(1).ToDictionary(item => item, item => item);
}
}

return (dnsOut, multiOut);
}

public EnrollmentRequest GetEnrollmentRequest(EnrollmentProductInfo productInfo, string csr,
Dictionary<string, string[]> san)
{
Expand Down Expand Up @@ -303,38 +347,46 @@ public SearchCertificateRequestType GetSearchCertificatesRequest(int pageCounter

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

//5. Loop through DNS Entries, if coming from Cert bot, then need to get common name from here as well
Dictionary<string, string> MultiOut=null;

List<DnsName> dnsList = new List<DnsName>();

//5. If it contains the dns and it is not multi domain get the DNS
if (san.ContainsKey("dns"))
{
var dnsList = new List<DnsName>();
var dnsKp = san["dns"];
Logger.Trace($"dnsKP: {dnsKp}");
var commonNameList = new List<string>();

var j = 1;
foreach (var item in dnsKp)
(Dictionary<string, string> DNSOut, Dictionary<string, string> MultiOut) result;

if (!getCommonNameFromSubject)
{
commonNameList.Add(item);
if (j < 2)
{
DnsName dns = new DnsName { Id = DnsConstantName, Value = item };
dnsList.Add(dns);
}
else
{
DnsName dns = new DnsName { Id = DnsConstantName + j, Value = item };
dnsList.Add(dns);
}
j++;
//Cert Bot flow, Cert Bot has no common name and the dns comes from the SAN blank for common name returns first DNS
result = ProcessSansArray(dnsKp, "");
}
string commonName = string.Join(",", commonNameList);
else
{
result = ProcessSansArray(dnsKp, enrollmentRequest?.Attributes?.CommonName);
}

DnsName up = new DnsName { Id = DnsConstantName, Value = result.DNSOut.FirstOrDefault().Value };

MultiOut = result.MultiOut;
var jsonResultDns = JsonConvert.SerializeObject(enrollmentRequest);

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

enrollmentRequest = JsonConvert.DeserializeObject<EnrollmentRequest>(jsonResultDns);
dnsList.Add(up);

//5. Handle the multiple domain scenario domains go in a different attribute
if (MultiOut?.Count > 0)
{
DnsName mdns = new DnsName { Id = "custom_encode_dnsName_multi", Value = string.Join(",", MultiOut.Values) };
dnsList.Add(mdns);
}

sn.DnsName = dnsList;
}

Expand All @@ -346,73 +398,37 @@ public SearchCertificateRequestType GetSearchCertificatesRequest(int pageCounter

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

var k = 1;
foreach (var item in upKp)
{
if (k < 2)
{
UserPrincipalName up = new UserPrincipalName { Id = UpnConstantName, Value = item };
upList.Add(up);
}
else
{
UserPrincipalName up = new UserPrincipalName { Id = UpnConstantName + k, Value = item };
upList.Add(up);
}
k++;
}
//Multiple UPNs not supported by Digicert so take the first one in the list
UserPrincipalName up = new UserPrincipalName { Id = UpnConstantName, Value = upKp.FirstOrDefault() };
upList.Add(up);
sn.UserPrincipalName = upList;
}

//7. Loop through IP Entries
if (san.ContainsKey("ip4") || san.ContainsKey("ip6"))
if (san.ContainsKey("ipaddress"))
{
var ipList = new List<IpAddress>();

var ipKp = san.ContainsKey("ip4") ? san["ip4"] : san["ip6"];
var ipKp = san["ipaddress"];
Logger.Trace($"ip: {ipKp}");

var k = 1;
foreach (var item in ipKp)
{
if (k < 2)
{
IpAddress ip = new IpAddress { Id = IpConstantName, Value = item };
ipList.Add(ip);
}
else
{
IpAddress ip = new IpAddress { Id = IpConstantName + k, Value = item };
ipList.Add(ip);
}
k++;
}
//Multiple IP Addresses not supported by Digicert so take the first one in the list
IpAddress ip = new IpAddress { Id = IpConstantName, Value = ipKp.FirstOrDefault() };
ipList.Add(ip);
sn.IpAddress = ipList;
}

//8. Loop through mail Entries
if (san.ContainsKey("mail"))
if (san.ContainsKey("email"))
{
var mailList = new List<Rfc822Name>();
var mailKp = san["mail"];
var mailKp = san["email"];

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

var k = 1;
foreach (var item in mailKp)
{
if (k < 2)
{
Rfc822Name mail = new Rfc822Name { Id = EmailConstantName, Value = item };
mailList.Add(mail);
}
else
{
Rfc822Name mail = new Rfc822Name { Id = EmailConstantName + k, Value = item };
mailList.Add(mail);
}
k++;
}
//Multiple IP Addresses not supported by Digicert so take the first one in the list
Rfc822Name mail = new Rfc822Name { Id = EmailConstantName, Value = mailKp.FirstOrDefault() };
mailList.Add(mail);
sn.Rfc822Name = mailList;
}

Expand All @@ -425,11 +441,11 @@ public SearchCertificateRequestType GetSearchCertificatesRequest(int pageCounter
var i = OuStartPoint;
foreach (var ou in organizationalUnits)
{
var organizationUnit = new OrganizationUnit { Id = OuStartPoint==0?"cert_org_unit":"cert_org_unit" + i, Value = ou };
var organizationUnit = new OrganizationUnit { Id = OuStartPoint == 0 ? "cert_org_unit" : "cert_org_unit" + i, Value = ou };
orgUnits.Add(organizationUnit);
i++;
}

var attributes = enrollmentRequest.Attributes;
attributes.OrganizationUnit = orgUnits;
attributes.San = sn;
Expand Down Expand Up @@ -463,8 +479,8 @@ public EnrollmentResult
return new EnrollmentResult
{
Status = (int)PKIConstants.Microsoft.RequestDisposition.ISSUED, //success
CARequestID = enrollmentResponse.Result.SerialNumber,
Certificate = cert.Certificate,
CARequestID = enrollmentResponse?.Result?.SerialNumber,
Certificate = cert?.Certificate,
StatusMessage =
$"Order Successfully Created With Order Number {enrollmentResponse.Result.SerialNumber}"
};
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ This gateway integration supports the Digicert MPKI platform. It handles Enrollm
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.


## Support for DigiCert mPKI AnyGateway

DigiCert mPKI AnyGateway

###### 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.


---
Expand Down
18 changes: 10 additions & 8 deletions integration-manifest.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"$schema": "https://keyfactor.github.io/integration-manifest-schema.json",
"integration_type": "ca-gateway",
"name": "DigiCert mPKI AnyGateway",
"status": "production",
"update_catalog": false,
"link_github": false,
"gateway_framework": "22.1.1",
"description": "This gateway integration supports the Digicert MPKI platform. It handles Enrollment, Renewal, Revoke and inventory by multiple seat Ids."
"$schema": "https://keyfactor.github.io/integration-manifest-schema.json",
"integration_type": "ca-gateway",
"name": "DigiCert mPKI AnyGateway",
"status": "production",
"update_catalog": false,
"link_github": false,
"support_level": "kf-supported",
"gateway_framework": "22.1.1",
"release_dir": "DigiCertSymCaProxy/bin/Release",
"description": "This gateway integration supports the Digicert MPKI platform. It handles Enrollment, Renewal, Revoke and inventory by multiple seat Ids."
}

0 comments on commit fcf522f

Please sign in to comment.