diff --git a/CHANGELOG.md b/CHANGELOG.md index 41b85e2..6d95b6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,11 +16,9 @@ Add support for using the cert upload feature to upload auth certs Switch to .NET 8 1.1.1 -Allow for manual specification of enrollment term length -Add Lifetime parameter to allow for manual specification of cert validity -Bugfix - Properly handle syncs of 0 records Allow for manual specification of enrollment term length +Add Lifetime parameter to allow for manual specification of cert validity +Bugfix - Properly handle syncs of 0 records 1.1.2 -Add Lifetime parameter to allow for manual specification of cert validity -Bugfix - Properly handle syncs of 0 records +Bugfix - Properly check for existance of Lifetime parameter diff --git a/sectigo-scm-caplugin/Client/SectigoClient.cs b/sectigo-scm-caplugin/Client/SectigoClient.cs index 66e7caf..583a233 100644 --- a/sectigo-scm-caplugin/Client/SectigoClient.cs +++ b/sectigo-scm-caplugin/Client/SectigoClient.cs @@ -8,6 +8,8 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Org.BouncyCastle.Asn1.Ocsp; + using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -19,6 +21,8 @@ using System.Threading; using System.Threading.Tasks; +using Error = Keyfactor.Extensions.CAPlugin.Sectigo.API.Error; + namespace Keyfactor.Extensions.CAPlugin.Sectigo.Client { public class SectigoClient @@ -34,7 +38,9 @@ public SectigoClient(HttpClient client) public async Task GetCertificate(int sslId) { - var response = await RestClient.GetAsync($"api/ssl/v1/{sslId}"); + string url = $"api/ssl/v1/{sslId}"; + Logger.LogTrace($"API Request: GET {url}"); + var response = await RestClient.GetAsync(url); return await ProcessResponse(response); } @@ -139,7 +145,7 @@ public async Task CertificateListProducer(BlockingCollection certs, public async Task> PageCertificates(int position = 0, int size = 25, string filter = "") { string filterQueryString = string.IsNullOrEmpty(filter) ? string.Empty : $"&{filter}"; - Logger.LogTrace($"API Request: api/ssl/v1?position={position}&size={size}{filterQueryString}".TrimEnd()); + Logger.LogTrace($"API Request: GET api/ssl/v1?position={position}&size={size}{filterQueryString}".TrimEnd()); var response = await RestClient.GetAsync($"api/ssl/v1?position={position}&size={size}{filterQueryString}".TrimEnd()); return await ProcessResponse>(response); } @@ -151,23 +157,17 @@ public async Task RevokeSslCertificateById(int sslId, int revcode, string reasonCode = revcode, reason = revreason }; + Logger.LogTrace($"API Request: POST api/ssl/v1/revoke/{sslId}\nParameters: {JsonConvert.SerializeObject(data, Formatting.Indented)}"); var response = await RestClient.PostAsJsonAsync($"api/ssl/v1/revoke/{sslId}", data); - if (response.IsSuccessStatusCode) - { - return true; - } - var failedResp = ProcessResponse(response).Result; - return failedResp.IsSuccess;//Should throw an exception with error message from API + var resp = ProcessResponse(response).Result; + + return true;//Should throw an exception with error message from API, should only hit this if success } public async Task ListOrganizations() { + Logger.LogTrace($"API Request: GET api/organization/v1"); var response = await RestClient.GetAsync("api/organization/v1"); - if (response.IsSuccessStatusCode) - { - string responseContent = await response.Content.ReadAsStringAsync(); - Logger.LogTrace($"Raw Response: {responseContent}"); - } var orgsResponse = await ProcessResponse>(response); return new ListOrganizationsResponse { Organizations = orgsResponse }; @@ -175,13 +175,8 @@ public async Task ListOrganizations() public async Task GetOrganizationDetails(int orgId) { + Logger.LogTrace($"API Request: GET api/organization/v1/{orgId}"); var response = await RestClient.GetAsync($"api/organization/v1/{orgId}"); - if (response.IsSuccessStatusCode) - { - string responseContent = await response.Content.ReadAsStringAsync(); - Logger.LogTrace($"Raw Response: {responseContent}"); - } - var orgDetailsResponse = await ProcessResponse(response); return orgDetailsResponse; } @@ -203,6 +198,7 @@ public async Task ListPersons(int orgId) public async Task ListCustomFields() { + Logger.LogTrace($"API Request: GET api/ssl/v1/customFields"); var response = await RestClient.GetAsync("api/ssl/v1/customFields"); return new ListCustomFieldsResponse { CustomFields = await ProcessResponse>(response) }; } @@ -214,13 +210,14 @@ public async Task ListSslProfiles(int? orgId = null) { urlSuffix = $"?organizationId={orgId}"; } - + Logger.LogTrace($"API Request: GET api/ssl/v1/types{urlSuffix}"); var response = await RestClient.GetAsync($"api/ssl/v1/types{urlSuffix}"); return new ListSslProfilesResponse { SslProfiles = await ProcessResponse>(response) }; } public async Task> PagePersons(int orgId, int position = 0, int size = 25) { + Logger.LogTrace($"API Request: GET api/person/v1?position={position}&size={size}&organizationId={orgId}"); var response = await RestClient.GetAsync($"api/person/v1?position={position}&size={size}&organizationId={orgId}"); return await ProcessResponse>(response); } @@ -229,6 +226,7 @@ public async Task Enroll(EnrollRequest request) { try { + Logger.LogTrace($"API Request: POST api/ssl/v1/enroll\nParameters: {JsonConvert.SerializeObject(request, Formatting.Indented)}"); var response = await RestClient.PostAsJsonAsync("api/ssl/v1/enroll", request); var enrollResponse = await ProcessResponse(response); @@ -248,35 +246,14 @@ public async Task Enroll(EnrollRequest request) } } - public async Task Renew(int sslId) - { - try - { - var response = await RestClient.PostAsJsonAsync($"api/ssl/v1/renewById/{sslId}", ""); - var renewResponse = await ProcessResponse(response); - - return renewResponse.sslId; - } - catch (InvalidOperationException invalidOp) - { - throw new Exception($"Invalid Operation. {invalidOp.Message}|{invalidOp.StackTrace}"); - } - catch (HttpRequestException httpEx) - { - throw new Exception($"HttpRequestException. {httpEx.Message}|{httpEx.StackTrace}"); - } - catch (Exception) - { - throw; - } - } - public async Task PickupCertificate(int sslId, string subject) { + Logger.LogTrace($"API Request: GET api/ssl/v1/collect/{sslId}/x509C0"); var response = await RestClient.GetAsync($"api/ssl/v1/collect/{sslId}/x509CO"); - + if (response.IsSuccessStatusCode && response.Content.Headers.ContentLength > 0) { + Logger.LogTrace($"Raw response: {response.Content.ReadAsStringAsync()}"); string pemChain = await response.Content.ReadAsStringAsync(); string[] splitChain = pemChain.Replace("\r\n", string.Empty).Split(new string[] { "-----" }, StringSplitOptions.RemoveEmptyEntries); @@ -287,24 +264,19 @@ public async Task PickupCertificate(int sslId, string subject) //return new X509Certificate2(); } - public async Task Reissue(ReissueRequest request, int sslId) - { - var response = await RestClient.PostAsJsonAsync($"api/ssl/v1/replace/{sslId}", request); - response.EnsureSuccessStatusCode(); - } - #region Static Methods private static async Task ProcessResponse(HttpResponseMessage response) { + string responseContent = await response.Content.ReadAsStringAsync(); + Logger.LogDebug($"Raw API response: {responseContent}"); if (response.IsSuccessStatusCode) { - string responseContent = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject(responseContent); } else { - var error = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + var error = JsonConvert.DeserializeObject(responseContent); throw new Exception($"{error.Code} | {error.Description}"); } } diff --git a/sectigo-scm-caplugin/SectigoCAPlugin.cs b/sectigo-scm-caplugin/SectigoCAPlugin.cs index c21ea3d..e6b4a0d 100644 --- a/sectigo-scm-caplugin/SectigoCAPlugin.cs +++ b/sectigo-scm-caplugin/SectigoCAPlugin.cs @@ -198,7 +198,7 @@ public async Task Enroll(string csr, string subject, Dictionar int termLength; var profileTerms = Task.Run(async () => await GetProfileTerms(int.Parse(productInfo.ProductID))).Result; - if (!string.IsNullOrEmpty(productInfo.ProductParameters[Constants.Config.LIFETIME])) + if (productInfo.ProductParameters.ContainsKey(Constants.Config.LIFETIME) && !string.IsNullOrEmpty(productInfo.ProductParameters[Constants.Config.LIFETIME])) { var tempTerm = int.Parse(productInfo.ProductParameters[Constants.Config.LIFETIME]); if (profileTerms.Contains(tempTerm)) @@ -249,8 +249,6 @@ public async Task Enroll(string csr, string subject, Dictionar }; _logger.LogDebug($"Submit {enrollmentType} request"); - var jsonReq = JsonConvert.SerializeObject(request, Formatting.Indented); - _logger.LogDebug($"Request object: {jsonReq}"); sslId = Task.Run(async () => await client.Enroll(request)).Result; newCert = Task.Run(async () => await client.GetCertificate(sslId)).Result; _logger.LogDebug($"Enrolled for Certificate {newCert.CommonName} (ID: {newCert.Id}) | Status: {newCert.status}. Attempt to Pickup Certificate.");