Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 1.0.10 to main #16

Merged
merged 25 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
141859c
Fixes for Gateway Version Upgrade
bhillkeyfactor Apr 27, 2023
58d517e
Change to Full Sync
bhillkeyfactor Apr 27, 2023
8b6fd31
update .gitignore, kick off pilot prerelease build (#8)
fiddlermikey Apr 27, 2023
6dad7d7
Update generated README
Apr 27, 2023
aad11ac
Update integration-manifest.json
bhillkeyfactor Apr 28, 2023
7ceefbc
Update generated README
Apr 28, 2023
c8db8e5
Update readme_source.md
bhillkeyfactor Apr 28, 2023
baf0daa
Update generated README
Apr 28, 2023
a4cf9e7
Merge pull request #10 from Keyfactor/gatewayversionupgrade
bhillkeyfactor May 1, 2023
10ba354
readme updates (#11)
bhillkeyfactor Jun 12, 2023
46b4c0e
Squash final updates for release (#13)
fiddlermikey Jun 12, 2023
abea92d
Fixed Multi domain Issue
bhillkeyfactor Jan 24, 2024
f7df018
Update generated README
Jan 24, 2024
7c0267b
Cleand up error conditions
bhillkeyfactor Jan 25, 2024
46fa492
Merge branch 'release1.0_dev' of https://github.com/Keyfactor/digicer…
bhillkeyfactor Jan 25, 2024
a5aef3b
Fixed Email Enrollment
bhillkeyfactor Jan 25, 2024
36a2b9b
Update CHANGELOG.md
bhillkeyfactor Jan 26, 2024
6cdf908
Update workflow
Jan 26, 2024
cd27049
Update generated README
Jan 26, 2024
5e88260
removed version
bhillkeyfactor Jan 31, 2024
8eebe48
Update generated README
Jan 31, 2024
3fc187b
Update generated README
Feb 1, 2024
418af78
Merge pull request #15 from Keyfactor/release1.0_dev
fiddlermikey Feb 2, 2024
ebf9d6c
Merge branch 'main' into release-1.0
fiddlermikey Feb 2, 2024
a87904b
Update generated README
Feb 2, 2024
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
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 EnrollmentRequest GetEnrollmentRequest(EnrollmentProductInfo productInfo,

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 EnrollmentRequest GetEnrollmentRequest(EnrollmentProductInfo productInfo,

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 EnrollmentRequest GetEnrollmentRequest(EnrollmentProductInfo productInfo,
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
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@

# DigiCert mPKI AnyGateway

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

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


## About the Keyfactor AnyGateway CA Connector

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


###### 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 All @@ -24,14 +28,16 @@ This repository contains an AnyGateway CA Connector, which is a plugin to the Ke

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.

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



---


# Getting Started
## Standard Gateway Installation
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.
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.
To install the gateway follow these instructions.

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