Skip to content

Commit

Permalink
Implement per instance credential delete, dns zone lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
webprofusion-chrisc committed Oct 30, 2024
1 parent fc0bb0d commit ec0682e
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -417,7 +417,7 @@ public async Task<ActionResult> RemoveAccount(string storageKey, bool includeAcc
{
_serviceLog?.Information($"Deleting account {storageKey}: " + account.AccountURI);

var resultOk = await _credentialsManager.Delete(_itemManager, storageKey);
var result = await _credentialsManager.Delete(_itemManager, storageKey);

// invalidate accounts cache
lock (_accountsLock)
Expand All @@ -426,7 +426,7 @@ public async Task<ActionResult> RemoveAccount(string storageKey, bool includeAcc
}

// attempt acme account deactivation
if (resultOk && includeAccountDeactivation && acmeProvider != null)
if (result.IsSuccess && includeAccountDeactivation && acmeProvider != null)
{
try
{
Expand All @@ -443,7 +443,7 @@ public async Task<ActionResult> RemoveAccount(string storageKey, bool includeAcc
}
}

return new ActionResult("RemoveAccount", resultOk);
return new ActionResult("RemoveAccount", result.IsSuccess);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,16 @@ private async Task<InstanceCommandResult> _managementServerClient_OnGetCommandRe
{
var args = JsonSerializer.Deserialize<KeyValuePair<string, string>[]>(arg.Value);
var itemArg = args.FirstOrDefault(a => a.Key == "storageKey");
var storedCredential = JsonSerializer.Deserialize<StoredCredential>(itemArg.Value);
val = await _credentialsManager.Delete(_itemManager, itemArg.Value);
}
else if (arg.CommandType == ManagementHubCommands.GetDnsZones)
{
var args = JsonSerializer.Deserialize<KeyValuePair<string, string>[]>(arg.Value);
var providerTypeArg = args.FirstOrDefault(a => a.Key == "providerTypeId");
var credentialsIdArg = args.FirstOrDefault(a => a.Key == "credentialsId");

val = await GetDnsProviderZones(providerTypeArg.Value, credentialsIdArg.Value);
}
else if (arg.CommandType == ManagementHubCommands.Reconnect)
{
await _managementServerClient.Disconnect();
Expand Down
2 changes: 2 additions & 0 deletions src/Certify.Models/API/Management/ManagementHubMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class ManagementHubCommands
public const string UpdateStoredCredential = "UpdateStoredCredential";
public const string DeleteStoredCredential = "DeleteStoredCredential";

public const string GetDnsZones = "GetDnsZones";

public const string Reconnect = "Reconnect";
}

Expand Down
2 changes: 1 addition & 1 deletion src/Certify.Models/Providers/ICredentialsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public interface ICredentialsManager
bool Init(string connectionString, ILog log);
Task<bool> IsInitialised();

Task<bool> Delete(IManagedItemStore itemStore, string storageKey);
Task<ActionResult> Delete(IManagedItemStore itemStore, string storageKey);
Task<List<StoredCredential>> GetCredentials(string type = null, string storageKey = null);
Task<StoredCredential> GetCredential(string storageKey);
Task<string> GetUnlockedCredential(string storageKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2771,23 +2771,32 @@ public virtual async System.Threading.Tasks.Task<ActionResult> RemoveAcmeAccount
}

/// <summary>
/// Fetch list of DNS zones for a given DNS provider and credential
/// Get List of Zones with the current DNS provider and credential [Generated by Certify.SourceGenerators]
/// </summary>
/// <returns>OK</returns>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual System.Threading.Tasks.Task<System.Collections.Generic.ICollection<DnsZone>> GetDnsZonesAsync(string providerTypeId, string credentialsId)
public virtual System.Threading.Tasks.Task<System.Collections.Generic.ICollection<DnsZone>> GetDnsZonesAsync(string instanceId, string providerTypeId, string credentialsId)
{
return GetDnsZonesAsync(providerTypeId, credentialsId, System.Threading.CancellationToken.None);
return GetDnsZonesAsync(instanceId, providerTypeId, credentialsId, System.Threading.CancellationToken.None);
}

/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <summary>
/// Fetch list of DNS zones for a given DNS provider and credential
/// Get List of Zones with the current DNS provider and credential [Generated by Certify.SourceGenerators]
/// </summary>
/// <returns>OK</returns>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async System.Threading.Tasks.Task<System.Collections.Generic.ICollection<DnsZone>> GetDnsZonesAsync(string providerTypeId, string credentialsId, System.Threading.CancellationToken cancellationToken)
public virtual async System.Threading.Tasks.Task<System.Collections.Generic.ICollection<DnsZone>> GetDnsZonesAsync(string instanceId, string providerTypeId, string credentialsId, System.Threading.CancellationToken cancellationToken)
{
if (instanceId == null)
throw new System.ArgumentNullException("instanceId");

if (providerTypeId == null)
throw new System.ArgumentNullException("providerTypeId");

if (credentialsId == null)
throw new System.ArgumentNullException("credentialsId");

var client_ = _httpClient;
var disposeClient_ = false;
try
Expand All @@ -2799,18 +2808,13 @@ public virtual async System.Threading.Tasks.Task<ActionResult> RemoveAcmeAccount

var urlBuilder_ = new System.Text.StringBuilder();
if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl);
// Operation Path: "internal/v1/challengeprovider/dnszones"
urlBuilder_.Append("internal/v1/challengeprovider/dnszones");
urlBuilder_.Append('?');
if (providerTypeId != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("providerTypeId")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(providerTypeId, System.Globalization.CultureInfo.InvariantCulture))).Append('&');
}
if (credentialsId != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("credentialsId")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(credentialsId, System.Globalization.CultureInfo.InvariantCulture))).Append('&');
}
urlBuilder_.Length--;
// Operation Path: "internal/v1/challengeprovider/challengeprovider/dnszones/{instanceId}/{providerTypeId}/{credentialsId}"
urlBuilder_.Append("internal/v1/challengeprovider/challengeprovider/dnszones/");
urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(instanceId, System.Globalization.CultureInfo.InvariantCulture)));
urlBuilder_.Append('/');
urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(providerTypeId, System.Globalization.CultureInfo.InvariantCulture)));
urlBuilder_.Append('/');
urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(credentialsId, System.Globalization.CultureInfo.InvariantCulture)));

PrepareRequest(client_, request_, urlBuilder_);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Certify.Client;
using Certify.Models.Providers;
using Certify.Server.Api.Public.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -17,16 +18,17 @@ public partial class ChallengeProviderController : ApiControllerBase
private readonly ILogger<ChallengeProviderController> _logger;

private readonly ICertifyInternalApiClient _client;

private readonly ManagementAPI _mgmtAPI;
/// <summary>
/// Constructor
/// </summary>
/// <param name="logger"></param>
/// <param name="client"></param>
public ChallengeProviderController(ILogger<ChallengeProviderController> logger, ICertifyInternalApiClient client)
public ChallengeProviderController(ILogger<ChallengeProviderController> logger, ICertifyInternalApiClient client, ManagementAPI mgmtAPI)
{
_logger = logger;
_client = client;
_mgmtAPI = mgmtAPI;
}

/// <summary>
Expand All @@ -42,20 +44,5 @@ public async Task<IActionResult> GetChallengeProviders()
var list = await _client.GetChallengeAPIList();
return new OkObjectResult(list);
}

/// <summary>
/// Fetch list of DNS zones for a given DNS provider and credential
/// </summary>
/// <param name="providerTypeId"></param>
/// <param name="credentialsId"></param>
/// <returns></returns>
[HttpGet]
[Route("dnszones")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List<DnsZone>))]
public async Task<List<DnsZone>> GetDnsZones(string providerTypeId, string credentialsId)
{
return await _client.GetDnsProviderZones(providerTypeId, credentialsId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public async Task<IActionResult> GetHubManagedItems(string? instanceId, string?
InstanceId = remote.InstanceId,
InstanceTitle = instances.FirstOrDefault(i => i.InstanceId == remote.InstanceId)?.Title,
Id = i.Id ?? "",
Title = $"[remote] {i.Name}" ?? "",
Title = $"{i.Name}" ?? "",
PrimaryIdentifier = i.GetCertificateIdentifiers().FirstOrDefault(p => p.Value == i.RequestConfig.PrimaryDomain) ?? i.GetCertificateIdentifiers().FirstOrDefault(),
Identifiers = i.GetCertificateIdentifiers(),
DateRenewed = i.DateRenewed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,28 @@ public async Task<StatusSummary> GetManagedCertificateSummary(AuthContext? curre
}
}

public async Task<ICollection<Models.Providers.DnsZone>?> GetDnsZones(string instanceId, string providerTypeId, string credentialsId, AuthContext? currentAuthContext)
{
var args = new KeyValuePair<string, string>[] {
new("instanceId", instanceId),
new("providerTypeId", providerTypeId),
new("credentialsId", credentialsId)
};

var cmd = new InstanceCommandRequest(ManagementHubCommands.GetDnsZones, args);

var result = await GetCommandResult(instanceId, cmd);

if (result?.Value != null)
{
return JsonSerializer.Deserialize<ICollection<Models.Providers.DnsZone>>(result.Value);
}
else
{
return null;
}
}

public async Task<ICollection<Models.Config.StoredCredential>?> GetStoredCredentials(string instanceId, AuthContext? currentAuthContext)
{
var args = new KeyValuePair<string, string>[] {
Expand Down Expand Up @@ -262,7 +284,7 @@ public async Task<StatusSummary> GetManagedCertificateSummary(AuthContext? curre
}
}

public async Task<bool> DeleteStoredCredential(string instanceId, string storageKey, AuthContext authContext)
public async Task<ActionResult?> DeleteStoredCredential(string instanceId, string storageKey, AuthContext authContext)
{
// delete stored credential via management hub

Expand All @@ -275,7 +297,14 @@ public async Task<bool> DeleteStoredCredential(string instanceId, string storage

var result = await GetCommandResult(instanceId, cmd);

return result?.ObjectValue as bool? ?? false;
if (result?.Value != null)
{
return JsonSerializer.Deserialize<ActionResult>(result.Value);
}
else
{
return null;
}
}

public async Task<LogItem[]> GetItemLog(string instanceId, string managedCertId, int maxLines, AuthContext? currentAuthContext)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Certify.Management;
using Certify.Management;
using Certify.Models.Config;
using Microsoft.AspNetCore.Mvc;

Expand Down Expand Up @@ -33,7 +33,7 @@ public async Task<StoredCredential> UpdateCredentials(StoredCredential credentia
}

[HttpDelete, Route("{storageKey}")]
public async Task<bool> DeleteCredential(string storageKey)
public async Task<Models.Config.ActionResult> DeleteCredential(string storageKey)
{
DebugLog();

Expand Down
4 changes: 2 additions & 2 deletions src/Certify.Service/Controllers/CredentialsController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web.Http;
using Certify.Management;
Expand Down Expand Up @@ -34,7 +34,7 @@ public async Task<StoredCredential> UpdateCredentials(StoredCredential credentia
}

[HttpDelete, Route("{storageKey}")]
public async Task<bool> DeleteCredential(string storageKey)
public async Task<Models.Config.ActionResult> DeleteCredential(string storageKey)
{
DebugLog();

Expand Down
40 changes: 38 additions & 2 deletions src/Certify.SourceGenerators/ApiMethods.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;

using SourceGenerator;

namespace Certify.SourceGenerators
{
internal class ApiMethods
{
public static string HttpGet = "HttpGet";
public static string HttpPost = "HttpPost";
public static string HttpDelete = "HttpDelete";

public static string GetFormattedTypeName(Type type)
{
if (type.IsGenericType)
{
var genericArguments = type.GetGenericArguments()
.Select(x => x.FullName)
.Aggregate((x1, x2) => $"{x1}, {x2}");
return $"{type.FullName.Substring(0, type.FullName.IndexOf("`"))}"
+ $"<{genericArguments}>";
}

return type.FullName;
}
public static List<GeneratedAPI> GetApiDefinitions()
{
// declaring an API definition here is then used by the source generators to:
Expand Down Expand Up @@ -189,7 +210,7 @@ public static List<GeneratedAPI> GetApiDefinitions()
PublicAPIRoute = "credentials/{instanceId}",
ServiceAPIRoute = "credentials",
ReturnType = "ICollection<Models.Config.StoredCredential>",
UseManagementAPI = true,
UseManagementAPI = true,
Params =new Dictionary<string, string>{ { "instanceId", "string" } }
},
new GeneratedAPI {
Expand All @@ -213,6 +234,21 @@ public static List<GeneratedAPI> GetApiDefinitions()
ReturnType = "Models.Config.ActionResult",
UseManagementAPI = true,
Params =new Dictionary<string, string>{ { "instanceId", "string" },{ "storageKey", "string" } }
},
new GeneratedAPI {
OperationName = "GetDnsZones",
OperationMethod = HttpGet,
Comment = "Get List of Zones with the current DNS provider and credential",
PublicAPIController = "ChallengeProvider",
PublicAPIRoute = "challengeprovider/dnszones/{instanceId}/{providerTypeId}/{credentialsId}",
ServiceAPIRoute = "managedcertificates/dnszones/{providerTypeId}/{credentialsId}",
ReturnType = "ICollection<Certify.Models.Providers.DnsZone>",
UseManagementAPI = true,
Params =new Dictionary<string, string>{
{ "instanceId", "string" } ,
{ "providerTypeId", "string" },
{ "credentialsId", "string" }
}
},
new GeneratedAPI {
OperationName = "PerformExport",
Expand Down
Loading

0 comments on commit ec0682e

Please sign in to comment.