Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,16 @@ This integration is tested and confirmed as working for Anygateway REST 24.2 and

2. On the server hosting the AnyCA Gateway REST, download and unzip the latest [CSCGlobal CA Gateway AnyCA Gateway REST plugin](https://github.com/Keyfactor/cscglobal-caplugin/releases/latest) from GitHub.

3. Copy the unzipped directory (usually called `net6.0`) to the Extensions directory:
3. Copy the unzipped directory (usually called `net6.0` or `net8.0`) to the Extensions directory:


```shell
Depending on your AnyCA Gateway REST version, copy the unzipped directory to one of the following locations:
Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net6.0\Extensions
Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net8.0\Extensions
```

> The directory containing the CSCGlobal CA Gateway AnyCA Gateway REST plugin DLLs (`net6.0`) can be named anything, as long as it is unique within the `Extensions` directory.
> The directory containing the CSCGlobal CA Gateway AnyCA Gateway REST plugin DLLs (`net6.0` or `net8.0`) can be named anything, as long as it is unique within the `Extensions` directory.

4. Restart the AnyCA Gateway REST service.

Expand Down
9 changes: 9 additions & 0 deletions cscglobal-caplugin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
v1.1.0
- Support for custom fields in enrollment
- Support for returning CNAME tokens from enrollment call

v1.0.1
- Fixed issue with SANs not being read correctly.

v1.0
- Initial Release.
10 changes: 6 additions & 4 deletions cscglobal-caplugin/CSCGlobalCAPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,17 @@ public async Task<EnrollmentResult> Enroll(string csr, string subject, Dictionar
}

string uUId;
switch (enrollmentType)
var customFields = await CscGlobalClient.SubmitGetCustomFields();

switch (enrollmentType)
{
case EnrollmentType.New:
Logger.LogTrace("Entering New Enrollment");
//If they renewed an expired cert it gets here and this will not be supported
IRegistrationResponse enrollmentResponse;
if (!productInfo.ProductParameters.ContainsKey("PriorCertSN"))
{
enrollmentRequest = _requestManager.GetRegistrationRequest(productInfo, csr, san);
enrollmentRequest = _requestManager.GetRegistrationRequest(productInfo, csr, san, customFields);
Logger.LogTrace($"Enrollment Request JSON: {JsonConvert.SerializeObject(enrollmentRequest)}");
enrollmentResponse =
Task.Run(async () => await CscGlobalClient.SubmitRegistrationAsync(enrollmentRequest))
Expand Down Expand Up @@ -253,7 +255,7 @@ public async Task<EnrollmentResult> Enroll(string csr, string subject, Dictionar
uUId = await _certificateDataReader.GetRequestIDBySerialNumber(
productInfo.ProductParameters["PriorCertSN"]);
Logger.LogTrace($"Renew uUId: {uUId}");
renewRequest = _requestManager.GetRenewalRequest(productInfo, uUId, csr, san);
renewRequest = _requestManager.GetRenewalRequest(productInfo, uUId, csr, san, customFields);
Logger.LogTrace($"Renewal Request JSON: {JsonConvert.SerializeObject(renewRequest)}");
var renewResponse = Task.Run(async () => await CscGlobalClient.SubmitRenewalAsync(renewRequest))
.Result;
Expand All @@ -278,7 +280,7 @@ public async Task<EnrollmentResult> Enroll(string csr, string subject, Dictionar
productInfo.ProductParameters["PriorCertSN"]);
uUId = requestid.Substring(0, 36); //uUId is a GUID
Logger.LogTrace($"Reissue uUId: {uUId}");
reissueRequest = _requestManager.GetReissueRequest(productInfo, uUId, csr, san);
reissueRequest = _requestManager.GetReissueRequest(productInfo, uUId, csr, san, customFields);
Logger.LogTrace($"Reissue JSON: {JsonConvert.SerializeObject(reissueRequest)}");
var reissueResponse = Task.Run(async () => await CscGlobalClient.SubmitReissueAsync(reissueRequest))
.Result;
Expand Down
11 changes: 11 additions & 0 deletions cscglobal-caplugin/Client/CscGlobalClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@ public async Task<CertificateResponse> SubmitGetCertificateAsync(string certific
}
}

public async Task<List<GetCustomField>> SubmitGetCustomFields()
{
using (var resp = await RestClient.GetAsync($"/dbs/api/v2/admin/customfields"))
{
resp.EnsureSuccessStatusCode();
var getCustomFieldsResponse =
JsonConvert.DeserializeObject<GetCustomFields>(await resp.Content.ReadAsStringAsync());
return getCustomFieldsResponse.CustomFields;
}
}

public async Task<RevokeResponse> SubmitRevokeCertificateAsync(string uuId)
{
using (var resp = await RestClient.PutAsync($"/dbs/api/v2/tls/revoke/{uuId}", new StringContent("")))
Expand Down
21 changes: 21 additions & 0 deletions cscglobal-caplugin/Client/Models/GetCustomField.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2021 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 the specific language governing permissions
// and limitations under the License.
using Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces;
using Newtonsoft.Json;

namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Client.Models;

public class GetCustomField : IGetCustomField
{
[JsonProperty("label")] public string Label { get; set; }
[JsonProperty("mandatory")] public bool Mandatory { get; set; }
}

public class GetCustomFields
{
[JsonProperty("customFields")] public List<GetCustomField> CustomFields { get; set; }
}
2 changes: 2 additions & 0 deletions cscglobal-caplugin/Interfaces/ICscGlobalClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Task<ReissueResponse> SubmitReissueAsync(

Task<CertificateResponse> SubmitGetCertificateAsync(string certificateId);

Task<List<GetCustomField>> SubmitGetCustomFields();

Task<CertificateListResponse> SubmitCertificateListRequestAsync();

Task<RevokeResponse> SubmitRevokeCertificateAsync(string uuId);
Expand Down
13 changes: 13 additions & 0 deletions cscglobal-caplugin/Interfaces/IGetCustomField.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2021 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 the specific language governing permissions
// and limitations under the License.
namespace Keyfactor.Extensions.CAPlugin.CSCGlobal.Interfaces;

public interface IGetCustomField
{
string Label { get; set; }
bool Mandatory { get; set; }
}
46 changes: 37 additions & 9 deletions cscglobal-caplugin/RequestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,34 @@
using Keyfactor.PKI;
using Keyfactor.PKI.Enums.EJBCA;

using Org.BouncyCastle.Bcpg;

namespace Keyfactor.Extensions.CAPlugin.CSCGlobal;

public class RequestManager
{
public static Func<string, string> Pemify = ss =>
ss.Length <= 64 ? ss : ss.Substring(0, 64) + "\n" + Pemify(ss.Substring(64));

private List<CustomField> GetCustomFields(EnrollmentProductInfo productInfo)
private List<CustomField> GetCustomFields(EnrollmentProductInfo productInfo, List<GetCustomField> customFields)
{
var customFieldList = new List<CustomField>();
foreach (var field in customFields)
{
if (productInfo.ProductParameters.ContainsKey(field.Label))
{
var newField = new CustomField
{
Name = field.Label,
Value = productInfo.ProductParameters[field.Label]
};
customFieldList.Add(newField);
}
else if (field.Mandatory)
{
throw new Exception($"Custom field {field.Label} is marked as mandatory, but was not supplied in the request.");
}
}
return customFieldList;
}

Expand Down Expand Up @@ -55,12 +73,22 @@ public EnrollmentResult
StatusMessage = registrationResponse.RegistrationError.Description
};

return new EnrollmentResult
Dictionary<string, string> cnames = new Dictionary<string, string>();
if (registrationResponse.Result.DcvDetails != null && registrationResponse.Result.DcvDetails.Count > 0)
{
foreach (var dcv in registrationResponse.Result.DcvDetails)
{
cnames.Add(dcv.CName.Name, dcv.CName.Value);
}
}

return new EnrollmentResult
{
Status = (int)EndEntityStatus.EXTERNALVALIDATION, //success
CARequestID = registrationResponse.Result.Status.Uuid,
StatusMessage =
$"Order Successfully Created With Order Number {registrationResponse.Result.CommonName}"
$"Order Successfully Created With Order Number {registrationResponse.Result.CommonName}",
EnrollmentContext = (cnames.Count > 0) ? cnames : null
};
}

Expand Down Expand Up @@ -116,7 +144,7 @@ public DomainControlValidation GetDomainControlValidation(string methodType, str
}

public RegistrationRequest GetRegistrationRequest(EnrollmentProductInfo productInfo, string csr,
Dictionary<string, string[]> sans)
Dictionary<string, string[]> sans, List<GetCustomField> customFields)
{
//var cert = "-----BEGIN CERTIFICATE REQUEST-----\r\n";
var cert = Pemify(csr);
Expand Down Expand Up @@ -144,7 +172,7 @@ public RegistrationRequest GetRegistrationRequest(EnrollmentProductInfo productI
OrganizationContact = productInfo.ProductParameters["Organization Contact"],
BusinessUnit = productInfo.ProductParameters["Business Unit"],
ShowPrice = true, //User should not have to fill this out
CustomFields = GetCustomFields(productInfo),
CustomFields = GetCustomFields(productInfo, customFields),
SubjectAlternativeNames = certificateType == "2" ? GetSubjectAlternativeNames(productInfo, sans) : null,
EvCertificateDetails = certificateType == "3" ? GetEvCertificateDetails(productInfo) : null
};
Expand Down Expand Up @@ -190,7 +218,7 @@ public Notifications GetNotifications(EnrollmentProductInfo productInfo)
}

public RenewalRequest GetRenewalRequest(EnrollmentProductInfo productInfo, string uUId, string csr,
Dictionary<string, string[]> sans)
Dictionary<string, string[]> sans, List<GetCustomField> customFields)
{
//var cert = "-----BEGIN CERTIFICATE REQUEST-----\r\n";
var cert = Pemify(csr);
Expand Down Expand Up @@ -219,7 +247,7 @@ public RenewalRequest GetRenewalRequest(EnrollmentProductInfo productInfo, strin
BusinessUnit = productInfo.ProductParameters["Business Unit"],
ShowPrice = true,
SubjectAlternativeNames = certificateType == "2" ? GetSubjectAlternativeNames(productInfo, sans) : null,
CustomFields = GetCustomFields(productInfo),
CustomFields = GetCustomFields(productInfo, customFields),
EvCertificateDetails = certificateType == "3" ? GetEvCertificateDetails(productInfo) : null
};
}
Expand Down Expand Up @@ -248,7 +276,7 @@ private List<SubjectAlternativeName> GetSubjectAlternativeNames(EnrollmentProduc
}

public ReissueRequest GetReissueRequest(EnrollmentProductInfo productInfo, string uUId, string csr,
Dictionary<string, string[]> sans)
Dictionary<string, string[]> sans, List<GetCustomField> customFields)
{
//var cert = "-----BEGIN CERTIFICATE REQUEST-----\r\n";
var cert = Pemify(csr);
Expand Down Expand Up @@ -277,7 +305,7 @@ public ReissueRequest GetReissueRequest(EnrollmentProductInfo productInfo, strin
BusinessUnit = productInfo.ProductParameters["Business Unit"],
ShowPrice = true,
SubjectAlternativeNames = certificateType == "2" ? GetSubjectAlternativeNames(productInfo, sans) : null,
CustomFields = GetCustomFields(productInfo),
CustomFields = GetCustomFields(productInfo, customFields),
EvCertificateDetails = certificateType == "3" ? GetEvCertificateDetails(productInfo) : null
};
}
Expand Down
Loading