feat: initial public release (MAESTRO)
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { useState } from 'react';
|
||||
import { SshGlobalConnectionsForm } from './SshGlobalConnectionsForm';
|
||||
import { SshGrantsForm } from './SshGrantsForm';
|
||||
import { SshMasterKeyRotationForm } from './SshMasterKeyRotationForm';
|
||||
import { SshAuditLog } from './SshAuditLog';
|
||||
import { SshConfigForm } from './SshConfigForm';
|
||||
import type { SectionFormProps } from './types';
|
||||
|
||||
type SubTab = 'config' | 'connections' | 'grants' | 'rotation' | 'audit';
|
||||
|
||||
const TABS: { id: SubTab; label: string }[] = [
|
||||
{ id: 'config', label: 'Config' },
|
||||
{ id: 'connections', label: 'Global connections' },
|
||||
{ id: 'grants', label: 'Grants' },
|
||||
{ id: 'rotation', label: 'Rotation' },
|
||||
{ id: 'audit', label: 'Audit log' },
|
||||
];
|
||||
|
||||
interface Props extends SectionFormProps {
|
||||
showToast?: (msg: string, variant?: 'success' | 'error') => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin SSH panel — 5 sub-tabs:
|
||||
* - config: ssh.* + ssh.console.* config.yaml editor (uses the parent
|
||||
* draft / save-bar flow via SectionFormProps)
|
||||
* - connections: global SSH connection registry (own per-row CRUD)
|
||||
* - grants: per-user / per-piece access grants (own CRUD)
|
||||
* - rotation: master encryption key rotation (own state machine)
|
||||
* - audit: ssh_audit_log viewer with prune action
|
||||
*
|
||||
* Sub-tab layout because the 5 concerns share no vertical space and have
|
||||
* very different shapes (form / lists / per-row CRUD / mode / table).
|
||||
*/
|
||||
export function SshForm({ config, onChange, overriddenByEnv, showToast }: Props) {
|
||||
const [tab, setTab] = useState<SubTab>('config');
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<header>
|
||||
<h2 className="text-base font-semibold text-slate-900 mb-1">SSH 管理</h2>
|
||||
<p className="text-2xs text-slate-500 leading-relaxed">
|
||||
グローバル SSH 設定 / 接続の登録 / アクセス権 (grants) / マスターキーローテーション / 監査ログ。
|
||||
ユーザー個人の SSH 接続は <code className="font-mono">User Folder</code> →{' '}
|
||||
<code className="font-mono">ssh-connections/</code> から管理します。
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<nav className="flex items-center gap-1 border-b border-hairline">
|
||||
{TABS.map(t => (
|
||||
<button
|
||||
key={t.id}
|
||||
type="button"
|
||||
onClick={() => setTab(t.id)}
|
||||
className={`px-3 py-1.5 text-xs font-medium border-b-2 -mb-px transition-colors ${
|
||||
tab === t.id
|
||||
? 'border-accent text-accent'
|
||||
: 'border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300'
|
||||
}`}
|
||||
>
|
||||
{t.label}
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<div className="pt-2">
|
||||
{tab === 'config' && <SshConfigForm config={config} onChange={onChange} overriddenByEnv={overriddenByEnv} />}
|
||||
{tab === 'connections' && <SshGlobalConnectionsForm showToast={showToast} />}
|
||||
{tab === 'grants' && <SshGrantsForm showToast={showToast} />}
|
||||
{tab === 'rotation' && <SshMasterKeyRotationForm showToast={showToast} />}
|
||||
{tab === 'audit' && <SshAuditLog />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user