DatabaseSelection decides which databases the database-specific checks run in (system databases always), and which may send Dynamics AX findings to the hub (default none). CredentialEnvelope seals a SQL login password with the agent's RSA public key (RSA-OAEP-SHA256 + AES-256-GCM), bound to server and login, so only the agent can open it. Shared contracts for connection tests and discovery, server address validation, the service account login rule, and the least-privilege GRANT script filled in for one login. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
49 lines
2.4 KiB
C#
49 lines
2.4 KiB
C#
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace SQLInsight.Core.Configuration;
|
|
|
|
/// <summary>
|
|
/// db/permissions/grant-least-privilege.sql, ready to run for one login: what SQLInsight Web shows for a newly added
|
|
/// server. SQLInsight never runs it on the customer's server itself; a sysadmin runs it.
|
|
/// </summary>
|
|
public static partial class GrantScript
|
|
{
|
|
/// <summary>The script with <paramref name="login"/> filled in. For a Windows login it starts by creating the login if it is missing.</summary>
|
|
public static string For(string login, bool windowsLogin)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(login);
|
|
var literal = "N'" + login.Trim().Replace("'", "''", StringComparison.Ordinal) + "'";
|
|
var script = LoginPlaceholder().Replace(Template(), _ => "SET @LoginName = " + literal + ";", 1);
|
|
var header = new StringBuilder();
|
|
header.Append("/* Kør som sysadmin på instansen. Giver SQLInsight-agentens login ").Append(InComment(login.Trim())).Append(" de rettigheder, den skal bruge. */\r\n");
|
|
if (windowsLogin)
|
|
{
|
|
header.Append("IF SUSER_ID(").Append(literal).Append(") IS NULL\r\n CREATE LOGIN ")
|
|
.Append(Quote(login.Trim())).Append(" FROM WINDOWS;\r\nGO\r\n");
|
|
}
|
|
else
|
|
{
|
|
header.Append("/* SQL-login: opret det først, hvis det mangler, fx\r\n CREATE LOGIN ").Append(InComment(Quote(login.Trim())))
|
|
.Append(" WITH PASSWORD = N'…', CHECK_POLICY = ON; */\r\n");
|
|
}
|
|
|
|
return header.Append(script).ToString();
|
|
}
|
|
|
|
/// <summary>The script as shipped, with the placeholder login.</summary>
|
|
public static string Template()
|
|
{
|
|
using var stream = typeof(GrantScript).Assembly.GetManifestResourceStream("SQLInsight.Core.grant-least-privilege.sql")
|
|
?? throw new InvalidOperationException("grant-least-privilege.sql mangler i programmet.");
|
|
using var reader = new StreamReader(stream);
|
|
return reader.ReadToEnd();
|
|
}
|
|
|
|
private static string InComment(string text) => text.Replace("*/", "* /", StringComparison.Ordinal).Replace("/*", "/ *", StringComparison.Ordinal);
|
|
|
|
private static string Quote(string name) => "[" + name.Replace("]", "]]", StringComparison.Ordinal) + "]";
|
|
|
|
[GeneratedRegex(@"SET @LoginName = N'[^']*';[^\r\n]*")]
|
|
private static partial Regex LoginPlaceholder();
|
|
}
|