Public Access
61 lines
2.6 KiB
C#
61 lines
2.6 KiB
C#
using DodoSSH.Api.Features.Relay;
|
|
using Microsoft.AspNetCore.DataProtection;
|
|
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
|
using Microsoft.AspNetCore.DataProtection.Repositories;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace DodoSSH.Api.Setup;
|
|
|
|
/// <summary>The relay's services. See ADR 0004.</summary>
|
|
internal static class RelaySetup
|
|
{
|
|
/// <summary>
|
|
/// How much longer than the drain the host waits before it stops regardless.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Room for the close handshakes and the audit rows' final writes once the drain has run out, which
|
|
/// is the part of a shutdown an operator would otherwise lose without noticing.
|
|
/// </remarks>
|
|
private static readonly TimeSpan ShutdownMargin = TimeSpan.FromSeconds(10);
|
|
|
|
internal static IServiceCollection AddDodoRelay(this IServiceCollection services)
|
|
{
|
|
// Singletons: a session outlives the request that opened it, a protector is safe to share, and
|
|
// the network seam holds no state.
|
|
services.AddSingleton<RelayTicketCodec>();
|
|
services.AddSingleton<RelaySessionRegistry>();
|
|
services.AddSingleton<RelayAccessWatch>();
|
|
services.AddSingleton<IRelayNetwork, SystemRelayNetwork>();
|
|
|
|
// The application name isolates this deployment's payloads from any other ASP.NET application
|
|
// sharing a key directory, and — unlike the default, which is derived from the content root —
|
|
// is the same on every node, which is what lets any node verify any node's ticket.
|
|
services.AddDataProtection().SetApplicationName("DodoSSH");
|
|
|
|
services.AddOptions<KeyManagementOptions>()
|
|
.Configure<IOptions<RelayOptions>, ILoggerFactory>((keys, relay, loggers) =>
|
|
{
|
|
if (relay.Value.KeyRingDirectory is { Length: > 0 } directory)
|
|
{
|
|
keys.XmlRepository = new FileSystemXmlRepository(new DirectoryInfo(directory), loggers);
|
|
}
|
|
});
|
|
|
|
// Longer than the drain, or the host would stop waiting for live sessions before the drain ADR 0004
|
|
// promises them had run. Harmless with the relay off: nothing else holds a request open that long,
|
|
// and the host stops as soon as the last request has.
|
|
services.AddOptions<HostOptions>()
|
|
.Configure<IOptions<RelayOptions>>((host, relay) =>
|
|
{
|
|
var wanted = relay.Value.DrainTimeout + ShutdownMargin;
|
|
|
|
if (wanted > host.ShutdownTimeout)
|
|
{
|
|
host.ShutdownTimeout = wanted;
|
|
}
|
|
});
|
|
|
|
return services;
|
|
}
|
|
}
|