135 lines
4.9 KiB
C#
135 lines
4.9 KiB
C#
using HanaToolbox.Config;
|
|
using HanaToolbox.Logging;
|
|
using HanaToolbox.Services;
|
|
using HanaToolbox.Services.Interfaces;
|
|
using Spectre.Console;
|
|
|
|
namespace HanaToolbox.Tui;
|
|
|
|
/// <summary>
|
|
/// Interactive TUI for managing hdbuserstore keys.
|
|
/// Mirrors keymanager.sh flow: Create / Delete / Test.
|
|
/// </summary>
|
|
public sealed class KeyManagerTui(
|
|
KeyManagerService keyService,
|
|
IHdbClientLocator locator,
|
|
AppLogger _logger)
|
|
{
|
|
public async Task RunAsync(HanaConfig hana, string sid, CancellationToken ct = default)
|
|
{
|
|
var hdbsql = locator.LocateHdbsql(hana.HdbsqlPath, sid, hana.InstanceNumber);
|
|
|
|
while (true)
|
|
{
|
|
AnsiConsole.Clear();
|
|
AnsiConsole.Write(new Rule("[blue]SAP HANA Secure User Store Key Manager[/]").RuleStyle("blue"));
|
|
AnsiConsole.WriteLine();
|
|
|
|
var choice = AnsiConsole.Prompt(
|
|
new SelectionPrompt<string>()
|
|
.Title("Select an action:")
|
|
.AddChoices("Create a New Key", "Delete an Existing Key",
|
|
"Test an Existing Key", "Exit")
|
|
.HighlightStyle("cyan"));
|
|
|
|
switch (choice)
|
|
{
|
|
case "Create a New Key":
|
|
await CreateKeyAsync(hdbsql, hana, sid, ct);
|
|
break;
|
|
case "Delete an Existing Key":
|
|
await DeleteKeyAsync(sid, ct);
|
|
break;
|
|
case "Test an Existing Key":
|
|
await TestKeyAsync(hdbsql, sid, ct);
|
|
break;
|
|
case "Exit":
|
|
return;
|
|
}
|
|
|
|
AnsiConsole.MarkupLine("\n[grey]Press any key to continue...[/]");
|
|
Console.ReadKey(intercept: true);
|
|
}
|
|
}
|
|
|
|
private async Task CreateKeyAsync(
|
|
string hdbsql, HanaConfig hana, string sid, CancellationToken ct)
|
|
{
|
|
AnsiConsole.Write(new Rule("[blue]Create New Key[/]").RuleStyle("blue"));
|
|
|
|
var keyName = AnsiConsole.Prompt(new TextPrompt<string>("Key name:").DefaultValue("CRONKEY"));
|
|
var host = AnsiConsole.Prompt(new TextPrompt<string>("HANA host:").DefaultValue(System.Net.Dns.GetHostName()));
|
|
var instance = AnsiConsole.Prompt(new TextPrompt<string>("Instance number:").DefaultValue(hana.InstanceNumber));
|
|
var isSystemDb = AnsiConsole.Confirm("Connecting to SYSTEMDB?", defaultValue: false);
|
|
|
|
string connStr;
|
|
if (isSystemDb)
|
|
{
|
|
connStr = $"{host}:3{instance}13";
|
|
}
|
|
else
|
|
{
|
|
var tenant = AnsiConsole.Prompt(new TextPrompt<string>("Tenant DB name:").DefaultValue(sid.ToUpperInvariant()));
|
|
connStr = $"{host}:3{instance}15@{tenant}";
|
|
}
|
|
|
|
var user = AnsiConsole.Prompt(new TextPrompt<string>("Database user:").DefaultValue("SYSTEM"));
|
|
var pass = AnsiConsole.Prompt(new TextPrompt<string>("Password:").Secret());
|
|
|
|
AnsiConsole.MarkupLine($"\n[yellow]Command preview:[/] hdbuserstore SET \"{keyName}\" \"{connStr}\" \"{user}\" <password>");
|
|
if (!AnsiConsole.Confirm("Execute?", defaultValue: true)) return;
|
|
|
|
var created = await keyService.CreateKeyAsync(keyName, connStr, user, pass, sid, ct);
|
|
if (!created) return;
|
|
|
|
// Auto-test and rollback on failure
|
|
var ok = await keyService.TestKeyAsync(hdbsql, keyName, sid, ct);
|
|
if (!ok)
|
|
{
|
|
AnsiConsole.MarkupLine("[yellow]Rolling back: deleting key due to connection failure...[/]");
|
|
await keyService.DeleteKeyAsync(keyName, sid, ct);
|
|
}
|
|
}
|
|
|
|
private async Task DeleteKeyAsync(string sid, CancellationToken ct)
|
|
{
|
|
AnsiConsole.Write(new Rule("[red]Delete Key[/]").RuleStyle("red"));
|
|
|
|
var keys = await keyService.ListKeysAsync(sid, ct);
|
|
if (keys.Count == 0)
|
|
{
|
|
AnsiConsole.MarkupLine("[yellow]No keys found.[/]");
|
|
return;
|
|
}
|
|
|
|
var key = AnsiConsole.Prompt(
|
|
new SelectionPrompt<string>()
|
|
.Title("Select key to delete:")
|
|
.AddChoices(keys)
|
|
.HighlightStyle("red"));
|
|
|
|
if (!AnsiConsole.Confirm($"Permanently delete '{key}'?", defaultValue: false)) return;
|
|
await keyService.DeleteKeyAsync(key, sid, ct);
|
|
}
|
|
|
|
private async Task TestKeyAsync(string hdbsql, string sid, CancellationToken ct)
|
|
{
|
|
AnsiConsole.Write(new Rule("[blue]Test Key[/]").RuleStyle("blue"));
|
|
|
|
var keys = await keyService.ListKeysAsync(sid, ct);
|
|
if (keys.Count == 0)
|
|
{
|
|
AnsiConsole.MarkupLine("[yellow]No keys found.[/]");
|
|
return;
|
|
}
|
|
|
|
var key = AnsiConsole.Prompt(
|
|
new SelectionPrompt<string>()
|
|
.Title("Select key to test:")
|
|
.AddChoices(keys)
|
|
.HighlightStyle("cyan"));
|
|
|
|
await keyService.TestKeyAsync(hdbsql, key, sid, ct);
|
|
}
|
|
}
|