Skip to content

Commit

Permalink
Implement per instance target server/item API and mgmt hub method src…
Browse files Browse the repository at this point in the history
… gen
  • Loading branch information
webprofusion-chrisc committed Dec 3, 2024
1 parent d18d2b1 commit c8492c9
Show file tree
Hide file tree
Showing 12 changed files with 262 additions and 305 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -263,16 +263,47 @@ private async Task<InstanceCommandResult> _managementServerClient_OnGetCommandRe

val = await PerformDeploymentTask(null, managedCertificateIdArg.Value, taskIdArg.Value, isPreviewOnly: false, skipDeferredTasks: false, forceTaskExecution: false);
}
else if (arg.CommandType == ManagementHubCommands.GetTargetServiceTypes)
{
val = await GetTargetServiceTypes();
}
else if (arg.CommandType == ManagementHubCommands.GetTargetServiceItems)
{
var args = JsonSerializer.Deserialize<KeyValuePair<string, string>[]>(arg.Value);
var serviceTypeArg = args.FirstOrDefault(a => a.Key == "serviceType");

var serverType = MapStandardServerType(serviceTypeArg.Value);

val = await GetPrimaryWebSites(serverType, ignoreStoppedSites: true);
}
else if (arg.CommandType == ManagementHubCommands.GetTargetServiceItemIdentifiers)
{
var args = JsonSerializer.Deserialize<KeyValuePair<string, string>[]>(arg.Value);
var serviceTypeArg = args.FirstOrDefault(a => a.Key == "serviceType");
var itemArg = args.FirstOrDefault(a => a.Key == "itemId");

var serverType = MapStandardServerType(serviceTypeArg.Value);

val = await GetDomainOptionsFromSite(serverType, itemArg.Value);
}
else if (arg.CommandType == ManagementHubCommands.Reconnect)
{
await _managementServerClient.Disconnect();
}

var result = new InstanceCommandResult { CommandId = arg.CommandId, Value = JsonSerializer.Serialize(val) };

result.ObjectValue = val;
return new InstanceCommandResult { CommandId = arg.CommandId, Value = JsonSerializer.Serialize(val), ObjectValue = val };
}

return result;
private StandardServerTypes MapStandardServerType(string type)
{
if (StandardServerTypes.TryParse(type, out StandardServerTypes standardServerType))
{
return standardServerType;
}
else
{
return StandardServerTypes.Other;
}
}

private void ReportManagedItemUpdateToMgmtHub(ManagedCertificate item)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ namespace Certify.Management
{
public partial class CertifyManager
{
private async Task<ICollection<string>> GetTargetServiceTypes()
{
var list = new List<string>();

// TODO: make dynamic from service
if (await IsServerTypeAvailable(StandardServerTypes.IIS))
{
list.Add(StandardServerTypes.IIS.ToString());
};

if (await IsServerTypeAvailable(StandardServerTypes.Nginx))
{
list.Add(StandardServerTypes.Nginx.ToString());
};
return list;
}

private ITargetWebServer GetTargetServerProvider(StandardServerTypes serverType)
{
Expand Down
5 changes: 5 additions & 0 deletions src/Certify.Core/Management/Servers/ServerProviderIIS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ public IBindingDeploymentTarget GetDeploymentTarget()

public Task<bool> IsAvailable()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return Task.FromResult(false);
}

if (!_isIISAvailable)
{
try
Expand Down
3 changes: 3 additions & 0 deletions src/Certify.Models/Hub/ManagedCertificateSummary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ public class ManagedCertificateSummary
{
public string? InstanceId { get; set; } = string.Empty;
public string? InstanceTitle { get; set; } = string.Empty;

public string? OS { get; set; } = string.Empty;
public string? ClientDetails { get; set; } = string.Empty;
/// <summary>
/// Id for this managed item
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Certify.Models/Hub/ManagementHubMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public class ManagementHubCommands
public const string GetDeploymentProviders = "GetDeploymentProviders";
public const string ExecuteDeploymentTask = "ExecuteDeploymentTask";

public const string GetTargetServiceTypes = "GetTargetServiceTypes";
public const string GetTargetServiceItems = "GetTargetServiceItems";
public const string GetTargetServiceItemIdentifiers = "GetTargetServiceItemIdentifiers";

public const string Reconnect = "Reconnect";

/// <summary>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"runtime": "Net80",
"runtime": "Net90",
"defaultVariables": null,
"documentGenerator": {
"fromDocument": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,28 @@ public async Task<IActionResult> GetHubManagedItems(string? instanceId, string?
list.AddRange(
remote.Items
.Where(i => string.IsNullOrWhiteSpace(keyword) || (!string.IsNullOrWhiteSpace(keyword) && i.Name?.Contains(keyword) == true))
.Select(i => new ManagedCertificateSummary
.Select(i =>
{
InstanceId = remote.InstanceId,
InstanceTitle = instances.FirstOrDefault(i => i.InstanceId == remote.InstanceId)?.Title,
Id = i.Id ?? "",
Title = $"{i.Name}" ?? "",
PrimaryIdentifier = i.GetCertificateIdentifiers().FirstOrDefault(p => p.Value == i.RequestConfig.PrimaryDomain) ?? i.GetCertificateIdentifiers().FirstOrDefault(),
Identifiers = i.GetCertificateIdentifiers(),
DateRenewed = i.DateRenewed,
DateExpiry = i.DateExpiry,
Comments = i.Comments ?? "",
Status = i.LastRenewalStatus?.ToString() ?? "",
HasCertificate = !string.IsNullOrEmpty(i.CertificatePath)
})
var instance = instances.FirstOrDefault(i => i.InstanceId == remote.InstanceId);

return new ManagedCertificateSummary
{
InstanceId = remote.InstanceId,
InstanceTitle = instance?.Title,
Id = i.Id ?? "",
Title = $"{i.Name}" ?? "",
OS = instance?.OS,
ClientDetails = instance?.ClientName,
PrimaryIdentifier = i.GetCertificateIdentifiers().FirstOrDefault(p => p.Value == i.RequestConfig.PrimaryDomain) ?? i.GetCertificateIdentifiers().FirstOrDefault(),
Identifiers = i.GetCertificateIdentifiers(),
DateRenewed = i.DateRenewed,
DateExpiry = i.DateExpiry,
Comments = i.Comments ?? "",
Status = i.LastRenewalStatus?.ToString() ?? "",
HasCertificate = !string.IsNullOrEmpty(i.CertificatePath)
};
}
)
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Certify.Client;
using Certify.Models;
using Certify.Server.Api.Public.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -18,42 +19,18 @@ public partial class TargetController : ApiControllerBase

private readonly ICertifyInternalApiClient _client;

private readonly ManagementAPI _mgmtAPI;

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

/// <summary>
/// Get list of known service items (e.g. websites etc) we may want to then check for domains etc to add to cert. May return many items (e.g. thousands of sites)
/// </summary>
/// <returns></returns>
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("{serverType}/items")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List<SiteInfo>))]

public async Task<IActionResult> GetTargetServiceItems(string serverType)
{
var knownServerType = GetServerTypeFromString(serverType);
if (knownServerType == null)
{
return new NotFoundResult();
}

var targetList = new List<Models.SiteInfo>();

if (await _client.IsServerAvailable((StandardServerTypes)knownServerType))
{
targetList.AddRange(await _client.GetServerSiteList((StandardServerTypes)knownServerType));
}

return new OkObjectResult(targetList);
_mgmtAPI = mgmtAPI;
}

private static StandardServerTypes? GetServerTypeFromString(string value)
Expand All @@ -67,90 +44,5 @@ public async Task<IActionResult> GetTargetServiceItems(string serverType)
return null;
}
}

/// <summary>
/// Return details of single target server item (e.g. 1 site)
/// </summary>
/// <param name="serverType"></param>
/// <param name="itemId"></param>
/// <returns></returns>
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("{serverType}/item/{itemId}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(SiteInfo))]

public async Task<IActionResult> GetTargetServiceItem(string serverType, string itemId)
{
if (string.IsNullOrEmpty(itemId))
{
return new BadRequestResult();
}

var knownServerType = GetServerTypeFromString(serverType);
if (knownServerType == null)
{
return new NotFoundResult();
}

var results = await _client.GetServerSiteList((StandardServerTypes)knownServerType, itemId);

if (results.Count == 0)
{
return new NotFoundResult();
}
else
{
return new OkObjectResult(results.First());
}
}

/// <summary>
/// Get list of known service items (e.g. websites etc) we may want to then check for domains etc to add to cert
/// </summary>
/// <returns></returns>
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("{serverType}/item/{itemId}/identifiers")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List<DomainOption>))]

public async Task<IActionResult> GetTargetServiceItemIdentifiers(string serverType, string itemId)
{
var targetList = new List<Models.DomainOption>();

var knownServerType = GetServerTypeFromString(serverType);
if (knownServerType == null)
{
return new NotFoundResult();
}

targetList.AddRange(await _client.GetServerSiteDomains((StandardServerTypes)knownServerType, itemId));

return new OkObjectResult(targetList);

}
/// <summary>
/// Get list of target services this server supports (e.g. IIS etc)
/// </summary>
/// <returns></returns>
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("services")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string[]))]
public async Task<IActionResult> GetTargetServiceTypes()
{
var list = new List<string>();

// TODO: make dynamic from service
if (await _client.IsServerAvailable(StandardServerTypes.IIS))
{
list.Add(StandardServerTypes.IIS.ToString());
};

if (await _client.IsServerAvailable(StandardServerTypes.Nginx))
{
list.Add(StandardServerTypes.Nginx.ToString());
};
return new OkObjectResult(list);
}
}
}
42 changes: 42 additions & 0 deletions src/Certify.SourceGenerators/ApiMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,48 @@ public static List<GeneratedAPI> GetApiDefinitions()
{ "instanceId", "string" }
}
},
new GeneratedAPI {
OperationName = "GetTargetServiceTypes",
OperationMethod = HttpGet,
Comment = "Get Service Types present on instance (IIS, nginx etc)",
UseManagementAPI = true,
ManagementHubCommandType = Models.Hub.ManagementHubCommands.GetTargetServiceTypes,
PublicAPIController = "Target",
PublicAPIRoute = "{instanceId}/types",
ReturnType = "ICollection<string>",
Params =new Dictionary<string, string>{
{ "instanceId", "string" }
}
},
new GeneratedAPI {
OperationName = "GetTargetServiceItems",
OperationMethod = HttpGet,
Comment = "Get Service items (sites) present on instance (IIS, nginx etc).",
UseManagementAPI = true,
ManagementHubCommandType = Models.Hub.ManagementHubCommands.GetTargetServiceItems,
PublicAPIController = "Target",
PublicAPIRoute = "{instanceId}/{serviceType}/items",
ReturnType = "ICollection<SiteInfo>",
Params =new Dictionary<string, string>{
{ "instanceId", "string" },
{ "serviceType", "string" }
}
},
new GeneratedAPI {
OperationName = "GetTargetServiceItemIdentifiers",
OperationMethod = HttpGet,
Comment = "Get Service item identifiers (domains on a website etc) present on instance (IIS, nginx etc)",
UseManagementAPI = true,
ManagementHubCommandType = Models.Hub.ManagementHubCommands.GetTargetServiceItemIdentifiers,
PublicAPIController = "Target",
PublicAPIRoute = "{instanceId}/{serviceType}/item/{itemId}/identifiers",
ReturnType = "ICollection<DomainOption>",
Params =new Dictionary<string, string>{
{ "instanceId", "string" },
{ "serviceType", "string" },
{ "itemId", "string" }
}
},
new GeneratedAPI {
OperationName = "GetChallengeProviders",
OperationMethod = HttpGet,
Expand Down
3 changes: 3 additions & 0 deletions src/Certify.SourceGenerators/Certify.SourceGenerators.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Certify.Models\Certify.Models.csproj" />
</ItemGroup>
</Project>
Loading

0 comments on commit c8492c9

Please sign in to comment.