Skip to content
Open
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
131 changes: 87 additions & 44 deletions digicert-certcentral-caplugin/Client/CertCentralClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,47 @@ public CertCentralResponse()

public bool Success { get; set; }
public string Response { get; set; }
public int StatusCode { get; set; }
}

/// <summary>
/// Turn a DigiCert response body into a non-empty list of Errors, without throwing.
///
/// Callers used to do `JsonConvert.DeserializeObject&lt;Errors&gt;(body)` and read `.errors`
/// directly, which yields null in three reachable cases - an empty body, a JSON body that is
/// not the {"errors":[...]} envelope (GET /services/v2/account/metadata answers literally {}
/// on an account with no custom fields), and a non-JSON body such as a proxy or WAF error page
/// - so the Errors[0] / .First() / .Count sites downstream threw NullReferenceException, and a
/// non-JSON body threw JsonReaderException from outside Request()'s try/catch.
/// </summary>
internal static List<Error> ParseErrors(string body, int statusCode)
{
string codeSuffix = statusCode > 0 ? $" (HTTP {statusCode})" : "";

if (string.IsNullOrWhiteSpace(body))
{
return new List<Error> { new Error { code = "empty_response_body", message = $"DigiCert returned no response body{codeSuffix}." } };
}

try
{
Errors parsed = JsonConvert.DeserializeObject<Errors>(body);
if (parsed?.errors != null && parsed.errors.Count > 0)
{
return parsed.errors;
}
return new List<Error> { new Error { code = "unrecognized_error_response", message = $"DigiCert returned a response with no 'errors' array{codeSuffix}: {Truncate(body)}" } };
}
catch (JsonException)
{
return new List<Error> { new Error { code = "non_json_response", message = $"DigiCert returned a non-JSON response{codeSuffix}: {Truncate(body)}" } };
}
}

private static string Truncate(string s)
{
s = s.Replace("\r", " ").Replace("\n", " ").Trim();
return s.Length <= 500 ? s : s.Substring(0, 500) + "\u2026";
}

private CertCentralResponse Request(CertCentralBaseRequest request)
Expand Down Expand Up @@ -118,6 +159,7 @@ private CertCentralResponse Request(CertCentralBaseRequest request, string param
{
string respString = new StreamReader(objResponse.GetResponseStream()).ReadToEnd();
oCertCertResponse.Response = respString;
oCertCertResponse.StatusCode = (int)objResponse.StatusCode;
Logger.LogTrace($"CertCentral CA (Request ID: {reqID}) has returned Response '{objResponse.StatusCode}: {respString}");
}
}
Expand All @@ -141,6 +183,7 @@ private CertCentralResponse Request(CertCentralBaseRequest request, string param
string errorString = reader.ReadToEnd();
oCertCertResponse.Success = false;
oCertCertResponse.Response = errorString;
oCertCertResponse.StatusCode = (int)errorResponse.StatusCode;
Logger.LogTrace($"CertCentral CA (Request ID: {reqID}) has returned Response '{errorResponse.StatusCode}: {errorString}");
}
}
Expand Down Expand Up @@ -169,9 +212,9 @@ public ListOrganizationsResponse ListOrganizations(ListOrganizationsRequest requ

if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
listOrganizationsResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
listOrganizationsResponse.Errors = errors.errors;
listOrganizationsResponse.Errors = errors;
}
else
listOrganizationsResponse = JsonConvert.DeserializeObject<ListOrganizationsResponse>(response.Response);
Expand All @@ -187,9 +230,9 @@ public ListDomainsResponse ListDomains(ListDomainsRequest request)

if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
listDomainsResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
listDomainsResponse.Errors = errors.errors;
listDomainsResponse.Errors = errors;
}
else
listDomainsResponse = JsonConvert.DeserializeObject<ListDomainsResponse>(response.Response);
Expand All @@ -205,9 +248,9 @@ public ListContainersResponse ListContainers(ListContainersRequest request)

if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
listContainersResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
listContainersResponse.Errors = errors.errors;
listContainersResponse.Errors = errors;
}
else
{
Expand All @@ -225,9 +268,9 @@ public ListDuplicatesResponse ListDuplicates(ListDuplicatesRequest duplicatesReq

if (!ccResponse.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(ccResponse.Response);
List<Error> errors = ParseErrors(ccResponse.Response, ccResponse.StatusCode);
duplicatesResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
duplicatesResponse.Errors = errors.errors;
duplicatesResponse.Errors = errors;
}
else
{
Expand All @@ -245,9 +288,9 @@ public ListReissueResponse ListReissues(ListReissueRequest reissueRequest)

if (!ccResponse.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(ccResponse.Response);
List<Error> errors = ParseErrors(ccResponse.Response, ccResponse.StatusCode);
reissueResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
reissueResponse.Errors = errors.errors;
reissueResponse.Errors = errors;
}
else
{
Expand All @@ -265,9 +308,9 @@ public ListRequestsResponse ListRequests(ListRequestsRequest request)

if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
listRequestsResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
listRequestsResponse.Errors = errors.errors;
listRequestsResponse.Errors = errors;
}
else
listRequestsResponse = JsonConvert.DeserializeObject<ListRequestsResponse>(response.Response);
Expand All @@ -283,9 +326,9 @@ public ListMetadataResponse ListMetadata(ListMetadataRequest request)

if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
listMetadataResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
listMetadataResponse.Errors = errors.errors;
listMetadataResponse.Errors = errors;
}
else
listMetadataResponse = JsonConvert.DeserializeObject<ListMetadataResponse>(response.Response);
Expand All @@ -304,9 +347,9 @@ public OrderResponse OrderCertificate(OrderRequest request)
OrderResponse orderResponse = new OrderResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
orderResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
orderResponse.Errors = errors.errors;
orderResponse.Errors = errors;
}
else
orderResponse = JsonConvert.DeserializeObject<OrderResponse>(response.Response);
Expand All @@ -325,9 +368,9 @@ public OrderResponse OrderSmimeCertificate(OrderSmimeRequest request)
OrderResponse orderResponse = new OrderResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
orderResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
orderResponse.Errors = errors.errors;
orderResponse.Errors = errors;
}
else
orderResponse = JsonConvert.DeserializeObject<OrderResponse>(response.Response);
Expand All @@ -345,9 +388,9 @@ public OrderResponse ReissueCertificate(ReissueRequest request)
OrderResponse reissueResponse = new OrderResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
reissueResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
reissueResponse.Errors = errors.errors;
reissueResponse.Errors = errors;
}
else
{
Expand All @@ -367,9 +410,9 @@ public OrderResponse DuplicateCertificate(DuplicateRequest request)
OrderResponse duplicateResponse = new OrderResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
duplicateResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
duplicateResponse.Errors = errors.errors;
duplicateResponse.Errors = errors;
}
else
{
Expand All @@ -386,9 +429,9 @@ public RevokeCertificateResponse RevokeCertificate(RevokeCertificateRequest requ
RevokeCertificateResponse revokeOrderResponse = new RevokeCertificateResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
revokeOrderResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
revokeOrderResponse.Errors = errors.errors;
revokeOrderResponse.Errors = errors;
}
else
revokeOrderResponse = JsonConvert.DeserializeObject<RevokeCertificateResponse>(response.Response);
Expand All @@ -403,9 +446,9 @@ public RevokeCertificateResponse RevokeCertificate(RevokeCertificateByOrderReque
RevokeCertificateResponse revokeOrderResponse = new RevokeCertificateResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
revokeOrderResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
revokeOrderResponse.Errors = errors.errors;
revokeOrderResponse.Errors = errors;
}
else
revokeOrderResponse = JsonConvert.DeserializeObject<RevokeCertificateResponse>(response.Response);
Expand All @@ -420,9 +463,9 @@ public UpdateRequestStatusResponse UpdateRequestStatus(UpdateRequestStatusReques
UpdateRequestStatusResponse updateRequestResponse = new UpdateRequestStatusResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
updateRequestResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
updateRequestResponse.Errors = errors.errors;
updateRequestResponse.Errors = errors;
}
else
{
Expand All @@ -443,9 +486,9 @@ public DVCheckDCVResponse DVCheckDCV(DVCheckDCVRequest request)
DVCheckDCVResponse checkDCVResponse = new DVCheckDCVResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
checkDCVResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
checkDCVResponse.Errors = errors.errors;
checkDCVResponse.Errors = errors;
}
else
{
Expand All @@ -461,9 +504,9 @@ public CertificateChainResponse GetCertificateChain(CertificateChainRequest requ
CertificateChainResponse chainResponse = new CertificateChainResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
chainResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
chainResponse.Errors = errors.errors;
chainResponse.Errors = errors;
}
else
{
Expand All @@ -479,9 +522,9 @@ public StatusChangesResponse StatusChanges(StatusChangesRequest request)
StatusChangesResponse statusChangeResponse = new StatusChangesResponse();
if (!certResponse.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(certResponse.Response);
List<Error> errors = ParseErrors(certResponse.Response, certResponse.StatusCode);
statusChangeResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
statusChangeResponse.Errors = errors.errors;
statusChangeResponse.Errors = errors;
}
else
{
Expand All @@ -496,9 +539,9 @@ public DownloadCertificateByFormatResponse DownloadCertificateByFormat(DownloadC
DownloadCertificateByFormatResponse dlCertificateRequestResponse = new DownloadCertificateByFormatResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
dlCertificateRequestResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
dlCertificateRequestResponse.Errors = errors.errors;
dlCertificateRequestResponse.Errors = errors;
}
else
{
Expand Down Expand Up @@ -545,9 +588,9 @@ public ListCertificateOrdersResponse ListAllCertificateOrders(bool ignoreExpired
ListCertificateOrdersResponse listCertificateResponse = new ListCertificateOrdersResponse();
if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
listCertificateResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
listCertificateResponse.Errors = errors.errors;
listCertificateResponse.Errors = errors;

return listCertificateResponse;
}
Expand All @@ -571,9 +614,9 @@ public ViewCertificateOrderResponse ViewCertificateOrder(ViewCertificateOrderReq

if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
viewCertResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
viewCertResponse.Errors = errors.errors;
viewCertResponse.Errors = errors;
}
else
{
Expand All @@ -596,9 +639,9 @@ public CertificateTypeDetailsResponse GetCertificateTypeDetails(CertificateTypeD

if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
detailsResponse.Status = CertCentralBaseResponse.StatusType.ERROR;
detailsResponse.Errors = errors.errors;
detailsResponse.Errors = errors;
}
else
{
Expand All @@ -620,9 +663,9 @@ public CertificateTypesResponse GetAllCertificateTypes()

if (!response.Success)
{
Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
List<Error> errors = ParseErrors(response.Response, response.StatusCode);
allTypes.Status = CertCentralBaseResponse.StatusType.ERROR;
allTypes.Errors = errors.errors;
allTypes.Errors = errors;
}
else
{
Expand Down