feat(hosts): Schluessel auf dem Host anzeigen und ausrollen (#016)
Die Hostseite listet, welche Public und Private Keys sshkv dort verwaltet - direkt oder ueber eine Hostgruppe - mit Zustand als Punkt und Text. Ein Dry-Run je Host zeigt das Diff aller Benutzer dieses Hosts und rollt nach Bestaetigung aus. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,9 @@ import { sitzungErforderlich } from "@/server/auth/sitzungspflicht";
|
||||
import { hostDetail, type HostDetail } from "@/server/queries/hosts";
|
||||
import { BootstrapAktionen } from "./BootstrapAktionen";
|
||||
import { sshdHinweise } from "@/lib/sshd-hinweise";
|
||||
import { AusrollenPanel } from "@/components/ausrollen/AusrollenPanel";
|
||||
import { VerwendungsZustand } from "@/components/ausrollen/VerwendungsZustand";
|
||||
import { verwendungenAufHost } from "@/server/queries/ziele";
|
||||
import { HostKeyAktionen } from "./HostKeyAktionen";
|
||||
import { HostKeyEntscheidung } from "./HostKeyEntscheidung";
|
||||
import { bootstrapBefehlFuer } from "@/server/queries/bootstrap";
|
||||
@@ -95,6 +98,8 @@ export default async function HostSeite({ params }: { params: Promise<{ id: stri
|
||||
const archiviert = host.archiviertAm !== null;
|
||||
const verwalten = darf(benutzer.rolle, "hostsVerwalten") && !archiviert;
|
||||
const darfEntscheiden = darf(benutzer.rolle, "hostKeyEntscheiden") && !archiviert;
|
||||
const darfAusrollen = darf(benutzer.rolle, "publicKeyAusrollen") && !archiviert;
|
||||
const verwendungen = await verwendungenAufHost(host.id);
|
||||
const jetzt = new Date();
|
||||
|
||||
return (
|
||||
@@ -217,7 +222,7 @@ export default async function HostSeite({ params }: { params: Promise<{ id: stri
|
||||
|
||||
<Karte
|
||||
titel="Schlüssel auf diesem Host"
|
||||
untertitel={`${host.publicVerwendungen} Public-Key-Verwendungen · ${host.privateVerwendungen} Private-Key-Verwendungen`}
|
||||
untertitel="Public Keys in authorized_keys und Private Keys, die sshkv hier verwaltet"
|
||||
>
|
||||
{host.zielkonten.length > 0 && (
|
||||
<p className="text-muted mb-4 text-[14px]">
|
||||
@@ -230,11 +235,64 @@ export default async function HostSeite({ params }: { params: Promise<{ id: stri
|
||||
))}
|
||||
</p>
|
||||
)}
|
||||
<Leerzustand
|
||||
icon={<KeyRound className="size-5" />}
|
||||
titel="Folgt mit #016"
|
||||
text="Hier erscheinen die Public und Private Keys, die sshkv auf diesem Host verwaltet."
|
||||
/>
|
||||
{verwendungen.oeffentlich.length === 0 && verwendungen.privat.length === 0 ? (
|
||||
<Leerzustand
|
||||
icon={<KeyRound className="size-5" />}
|
||||
titel="Noch keine Schlüssel zugewiesen"
|
||||
text="Zuweisen geht über die Seite eines Schlüssels („+ Ausrollen“)."
|
||||
/>
|
||||
) : (
|
||||
<ul className="flex flex-col">
|
||||
{verwendungen.oeffentlich.map((v) => (
|
||||
<li
|
||||
key={v.id}
|
||||
className="border-border flex flex-col gap-1 border-b py-3 first:pt-0 last:border-b-0 sm:flex-row sm:items-center sm:justify-between sm:gap-4"
|
||||
>
|
||||
<span className="min-w-0">
|
||||
<a
|
||||
href={`/schluessel/${v.schluessel.id}`}
|
||||
className="text-text hover:text-accent font-medium"
|
||||
>
|
||||
{v.schluessel.name}
|
||||
</a>
|
||||
<span className="text-muted block font-mono text-[12.5px] break-all">
|
||||
Public · {v.zielbenutzer}@{host.name}
|
||||
{v.hostgruppe ? ` · über ${v.hostgruppe.name}` : ""}
|
||||
{v.optionen ? ` · ${v.optionen}` : ""}
|
||||
</span>
|
||||
</span>
|
||||
<VerwendungsZustand zustand={v.zustand} />
|
||||
</li>
|
||||
))}
|
||||
{verwendungen.privat.map((v) => (
|
||||
<li
|
||||
key={v.id}
|
||||
className="border-border flex flex-col gap-1 border-b py-3 first:pt-0 last:border-b-0 sm:flex-row sm:items-center sm:justify-between sm:gap-4"
|
||||
>
|
||||
<span className="min-w-0">
|
||||
<a
|
||||
href={`/schluessel/${v.schluessel.id}`}
|
||||
className="text-text hover:text-accent font-medium"
|
||||
>
|
||||
{v.schluessel.name}
|
||||
</a>
|
||||
<span className="text-muted block font-mono text-[12.5px] break-all">
|
||||
Private · {v.zielbenutzer}@{host.name}:{v.pfad}
|
||||
</span>
|
||||
</span>
|
||||
<VerwendungsZustand zustand={v.zustand} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{darfAusrollen && verwendungen.oeffentlich.length > 0 && host.bootstrapAm && (
|
||||
<div className="border-border mt-5 border-t pt-5">
|
||||
<AusrollenPanel
|
||||
auswahl={{ hostId: host.id }}
|
||||
offen={verwendungen.oeffentlich.filter((v) => v.zustand !== "AUSGEROLLT").length}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Karte>
|
||||
|
||||
{verwalten && (
|
||||
|
||||
Reference in New Issue
Block a user