Configure CertificateCheckUrl per container for curl-like TLS checks, classify Sonic permission errors, and extend setup wizard for container management. Co-authored-by: Cursor <cursoragent@cursor.com>
241 lines
7.4 KiB
C#
241 lines
7.4 KiB
C#
using System.Data;
|
|
using Microsoft.Data.SqlClient;
|
|
using ZA.CoreService.ESBCertificateManager.Models;
|
|
|
|
namespace ZA.CoreService.ESBCertificateManager.Services;
|
|
|
|
public sealed class DeploymentTargetRepository
|
|
{
|
|
private readonly string _connectionString;
|
|
|
|
public DeploymentTargetRepository(string connectionString)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(connectionString))
|
|
{
|
|
throw new ArgumentException(
|
|
"Der SQL-Connection-String ist nicht konfiguriert.",
|
|
nameof(connectionString));
|
|
}
|
|
|
|
_connectionString = connectionString;
|
|
}
|
|
|
|
public async Task<IReadOnlyList<DeploymentTarget>> GetActiveAsync(
|
|
string environmentCode,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(environmentCode))
|
|
{
|
|
throw new ArgumentException(
|
|
"Der EnvironmentCode fehlt.",
|
|
nameof(environmentCode));
|
|
}
|
|
|
|
const string sql = """
|
|
SELECT
|
|
target.[CertificateTargetId],
|
|
target.[TargetDirectory],
|
|
target.[TargetFileName],
|
|
target.[BackupEnabled],
|
|
target.[BackupDirectoryName],
|
|
target.[IsActive] AS [TargetIsActive],
|
|
|
|
container.[SonicContainerId],
|
|
container.[ContainerName],
|
|
container.[ContainerDisplayName],
|
|
container.[CertificateCheckUrl],
|
|
container.[RestartTimeoutSeconds],
|
|
|
|
connection.[ConnectionName],
|
|
|
|
environment.[EnvironmentCode],
|
|
environment.[SortOrder] AS [EnvironmentSortOrder],
|
|
|
|
company.[CompanyCode]
|
|
FROM [dbo].[CertificateTarget] AS target
|
|
INNER JOIN [dbo].[SonicContainer] AS container
|
|
ON container.[SonicContainerId] = target.[SonicContainerId]
|
|
INNER JOIN [dbo].[SonicConnection] AS connection
|
|
ON connection.[SonicConnectionId] = container.[SonicConnectionId]
|
|
INNER JOIN [dbo].[Environment] AS environment
|
|
ON environment.[EnvironmentId] = connection.[EnvironmentId]
|
|
INNER JOIN [dbo].[Company] AS company
|
|
ON company.[CompanyId] = container.[CompanyId]
|
|
WHERE target.[IsActive] = 1
|
|
AND container.[IsActive] = 1
|
|
AND connection.[IsActive] = 1
|
|
AND company.[IsActive] = 1
|
|
AND environment.[IsActive] = 1
|
|
AND environment.[EnvironmentCode] = @EnvironmentCode
|
|
ORDER BY
|
|
company.[CompanyCode],
|
|
environment.[SortOrder],
|
|
container.[ContainerName],
|
|
target.[TargetDirectory],
|
|
target.[TargetFileName];
|
|
""";
|
|
|
|
List<DeploymentTarget> targets = [];
|
|
|
|
await using SqlConnection connection = new(_connectionString);
|
|
await connection.OpenAsync(cancellationToken);
|
|
|
|
await using SqlCommand command = new(sql, connection);
|
|
|
|
command.Parameters.Add(
|
|
new SqlParameter(
|
|
"@EnvironmentCode",
|
|
SqlDbType.NVarChar,
|
|
30)
|
|
{
|
|
Value = environmentCode
|
|
.Trim()
|
|
.ToUpperInvariant()
|
|
});
|
|
|
|
await using SqlDataReader reader =
|
|
await command.ExecuteReaderAsync(cancellationToken);
|
|
|
|
int targetIdOrdinal =
|
|
reader.GetOrdinal("CertificateTargetId");
|
|
|
|
int targetDirectoryOrdinal =
|
|
reader.GetOrdinal("TargetDirectory");
|
|
|
|
int targetFileNameOrdinal =
|
|
reader.GetOrdinal("TargetFileName");
|
|
|
|
int backupEnabledOrdinal =
|
|
reader.GetOrdinal("BackupEnabled");
|
|
|
|
int backupDirectoryNameOrdinal =
|
|
reader.GetOrdinal("BackupDirectoryName");
|
|
|
|
int targetIsActiveOrdinal =
|
|
reader.GetOrdinal("TargetIsActive");
|
|
|
|
int containerNameOrdinal =
|
|
reader.GetOrdinal("ContainerName");
|
|
|
|
int containerDisplayNameOrdinal =
|
|
reader.GetOrdinal("ContainerDisplayName");
|
|
|
|
int certificateCheckUrlOrdinal =
|
|
reader.GetOrdinal("CertificateCheckUrl");
|
|
|
|
int restartTimeoutOrdinal =
|
|
reader.GetOrdinal("RestartTimeoutSeconds");
|
|
|
|
int connectionNameOrdinal =
|
|
reader.GetOrdinal("ConnectionName");
|
|
|
|
int environmentCodeOrdinal =
|
|
reader.GetOrdinal("EnvironmentCode");
|
|
|
|
int environmentSortOrderOrdinal =
|
|
reader.GetOrdinal("EnvironmentSortOrder");
|
|
|
|
int companyCodeOrdinal =
|
|
reader.GetOrdinal("CompanyCode");
|
|
|
|
while (await reader.ReadAsync(cancellationToken))
|
|
{
|
|
string containerName =
|
|
reader.GetString(containerNameOrdinal);
|
|
|
|
string? containerDisplayName =
|
|
ReadNullableString(
|
|
reader,
|
|
containerDisplayNameOrdinal);
|
|
|
|
string? certificateCheckUrl =
|
|
ReadNullableString(
|
|
reader,
|
|
certificateCheckUrlOrdinal);
|
|
|
|
string companyCode =
|
|
reader.GetString(companyCodeOrdinal);
|
|
|
|
string displayName =
|
|
string.IsNullOrWhiteSpace(containerDisplayName)
|
|
? containerName
|
|
: containerDisplayName;
|
|
|
|
string tlsHost = string.Empty;
|
|
int? tlsPort = null;
|
|
string tlsServerName = string.Empty;
|
|
|
|
if (TlsEndpointProbeService.TryParseEndpoint(
|
|
certificateCheckUrl,
|
|
out string host,
|
|
out int port,
|
|
out string serverName,
|
|
out _))
|
|
{
|
|
tlsHost = host;
|
|
tlsPort = port;
|
|
tlsServerName = serverName;
|
|
}
|
|
|
|
targets.Add(new DeploymentTarget
|
|
{
|
|
Id = reader.GetInt32(targetIdOrdinal),
|
|
|
|
Name = $"{companyCode} / {displayName}",
|
|
|
|
Environment =
|
|
reader.GetString(environmentCodeOrdinal),
|
|
|
|
IsActive =
|
|
reader.GetBoolean(targetIsActiveOrdinal),
|
|
|
|
TargetDirectory =
|
|
reader.GetString(targetDirectoryOrdinal),
|
|
|
|
CertificateFileName =
|
|
reader.GetString(targetFileNameOrdinal),
|
|
|
|
BackupEnabled =
|
|
reader.GetBoolean(backupEnabledOrdinal),
|
|
|
|
BackupDirectoryName =
|
|
reader.GetString(backupDirectoryNameOrdinal),
|
|
|
|
BackupRetentionDays = null,
|
|
|
|
ContainerName = containerName,
|
|
|
|
RestartType = RestartType.SonicContainer,
|
|
|
|
SonicConnectionName =
|
|
reader.GetString(connectionNameOrdinal),
|
|
|
|
RestartTimeoutSeconds =
|
|
reader.GetInt32(restartTimeoutOrdinal),
|
|
|
|
TlsHost = tlsHost,
|
|
|
|
TlsPort = tlsPort,
|
|
|
|
TlsServerName = tlsServerName,
|
|
|
|
ExpectedFingerprint = null,
|
|
|
|
SortOrder =
|
|
reader.GetInt32(environmentSortOrderOrdinal)
|
|
});
|
|
}
|
|
|
|
return targets;
|
|
}
|
|
|
|
private static string? ReadNullableString(
|
|
SqlDataReader reader,
|
|
int ordinal)
|
|
{
|
|
return reader.IsDBNull(ordinal)
|
|
? null
|
|
: reader.GetString(ordinal);
|
|
}
|
|
}
|