work with authentik
This commit is contained in:
@@ -2,6 +2,7 @@ using System.Security.Cryptography;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OTSSignsOrchestrator.Core.Configuration;
|
||||
|
||||
namespace OTSSignsOrchestrator.Core.Services;
|
||||
|
||||
@@ -106,6 +107,9 @@ public class PostInstanceInitService
|
||||
_logger.LogInformation("[PostInit] Setting Xibo theme to 'otssigns'");
|
||||
await xibo.SetThemeAsync(instanceUrl, accessToken, "otssigns");
|
||||
|
||||
// ── 6a. Deploy SAML configuration ─────────────────────────────────
|
||||
await DeploySamlConfigurationAsync(abbrev, instanceUrl, settings, ct);
|
||||
|
||||
// ── 7. Store credentials in Bitwarden ─────────────────────────────
|
||||
_logger.LogInformation("[PostInit] Storing credentials in Bitwarden");
|
||||
|
||||
@@ -196,6 +200,9 @@ public class PostInstanceInitService
|
||||
_logger.LogInformation("[PostInit] Setting theme to 'otssigns'");
|
||||
await xibo.SetThemeAsync(instanceUrl, accessToken, "otssigns");
|
||||
|
||||
// ── 5a. Deploy SAML configuration ─────────────────────────────────
|
||||
await DeploySamlConfigurationAsync(abbrev, instanceUrl, settings, ct);
|
||||
|
||||
// ── 6. Store admin password in Bitwarden ──────────────────────────
|
||||
_logger.LogInformation("[PostInit] Storing credentials in Bitwarden");
|
||||
var adminSecretId = await bws.CreateInstanceSecretAsync(
|
||||
@@ -335,6 +342,90 @@ public class PostInstanceInitService
|
||||
};
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// SAML configuration deployment
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// Provisions a SAML application in Authentik, renders the settings-custom.php template,
|
||||
/// and writes the rendered file to the instance's NFS-backed cms-custom volume.
|
||||
/// Errors are logged but do not fail the overall post-init process.
|
||||
/// </summary>
|
||||
private async Task DeploySamlConfigurationAsync(
|
||||
string abbrev,
|
||||
string instanceUrl,
|
||||
SettingsService settings,
|
||||
CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("[PostInit] Deploying SAML settings-custom.php for {Abbrev}", abbrev);
|
||||
|
||||
using var scope = _services.CreateScope();
|
||||
var authentik = scope.ServiceProvider.GetRequiredService<IAuthentikService>();
|
||||
var git = scope.ServiceProvider.GetRequiredService<GitTemplateService>();
|
||||
var docker = scope.ServiceProvider.GetRequiredService<IDockerCliService>();
|
||||
|
||||
// ── 1. Fetch template from git repo ───────────────────────────────
|
||||
var repoUrl = await settings.GetAsync(SettingsService.GitRepoUrl);
|
||||
var repoPat = await settings.GetAsync(SettingsService.GitRepoPat);
|
||||
if (string.IsNullOrWhiteSpace(repoUrl))
|
||||
throw new InvalidOperationException("Git repository URL is not configured.");
|
||||
|
||||
var templateConfig = await git.FetchAsync(repoUrl, repoPat);
|
||||
var templatePath = Path.Combine(templateConfig.CacheDir, "settings-custom.php.template");
|
||||
|
||||
if (!File.Exists(templatePath))
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"[PostInit] settings-custom.php.template not found in git repo — skipping SAML deployment");
|
||||
return;
|
||||
}
|
||||
|
||||
var templateContent = await File.ReadAllTextAsync(templatePath, ct);
|
||||
|
||||
// ── 2. Provision Authentik SAML application ───────────────────────
|
||||
var samlBaseUrl = instanceUrl.TrimEnd('/') + "/saml";
|
||||
var samlConfig = await authentik.ProvisionSamlAsync(abbrev, instanceUrl, ct);
|
||||
|
||||
// ── 3. Render template ────────────────────────────────────────────
|
||||
var rendered = templateContent
|
||||
.Replace("{{SAML_BASE_URL}}", samlBaseUrl)
|
||||
.Replace("{{SAML_SP_ENTITY_ID}}", $"{samlBaseUrl}/metadata")
|
||||
.Replace("{{AUTHENTIK_IDP_ENTITY_ID}}", samlConfig.IdpEntityId)
|
||||
.Replace("{{AUTHENTIK_SSO_URL}}", samlConfig.SsoUrlRedirect)
|
||||
.Replace("{{AUTHENTIK_SLO_URL}}", samlConfig.SloUrlRedirect)
|
||||
.Replace("{{AUTHENTIK_IDP_X509_CERT}}", samlConfig.IdpX509Cert);
|
||||
|
||||
// ── 4. Write rendered file to NFS volume ──────────────────────────
|
||||
var nfsServer = await settings.GetAsync(SettingsService.NfsServer);
|
||||
var nfsExport = await settings.GetAsync(SettingsService.NfsExport);
|
||||
var nfsExportFolder = await settings.GetAsync(SettingsService.NfsExportFolder);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(nfsServer) || string.IsNullOrWhiteSpace(nfsExport))
|
||||
throw new InvalidOperationException("NFS settings are not configured — cannot write SAML config to volume.");
|
||||
|
||||
// Path within the NFS export: {abbrev}/cms-custom/settings-custom.php
|
||||
var nfsRelativePath = $"{abbrev}/cms-custom/settings-custom.php";
|
||||
|
||||
var (success, error) = await docker.WriteFileToNfsAsync(
|
||||
nfsServer, nfsExport, nfsRelativePath, rendered, nfsExportFolder);
|
||||
|
||||
if (!success)
|
||||
throw new InvalidOperationException($"Failed to write settings-custom.php to NFS: {error}");
|
||||
|
||||
_logger.LogInformation(
|
||||
"[PostInit] SAML configuration deployed for {Abbrev} (Authentik provider={ProviderId})",
|
||||
abbrev, samlConfig.ProviderId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "[PostInit] SAML deployment failed for {Abbrev}: {Message}. " +
|
||||
"Instance will continue without SAML — configure manually if needed.", abbrev, ex.Message);
|
||||
// Don't rethrow — SAML failure should not block the rest of post-init
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// Helpers
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user