feat: agent updates from SAC, poll config, SSH/WinRM fallback (0.12.0)
Add agent update settings, pending self-update via poll, desired config per host, and automatic or manual SSH/WinRM fallback when agents do not report agent.update events.
This commit is contained in:
@@ -120,6 +120,56 @@
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="card settings-card settings-policy">
|
||||
<h2>Обновления агентов</h2>
|
||||
<p class="settings-hint settings-hint-top">
|
||||
Режим <code>gpo</code> — обновления вручную/GPO; SAC только показывает устаревшие версии.
|
||||
Режим <code>sac</code> — «Запросить обновление» ставит флаг в poll; агент self-update;
|
||||
через {{ agentUpdateForm.fallback_after_minutes }} мин без ответа — fallback SSH/WinRM с SAC.
|
||||
</p>
|
||||
<form class="settings-form" @submit.prevent="saveAgentUpdateSettingsForm">
|
||||
<label class="settings-field">
|
||||
Режим
|
||||
<select v-model="agentUpdateForm.mode">
|
||||
<option value="gpo">GPO / ручной</option>
|
||||
<option value="sac">SAC (poll + fallback)</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="settings-field settings-inline">
|
||||
<input v-model="agentUpdateForm.fallback_enabled" type="checkbox" />
|
||||
Авто-fallback SSH/WinRM после таймаута
|
||||
</label>
|
||||
<label class="settings-field">
|
||||
Fallback через (мин)
|
||||
<input v-model.number="agentUpdateForm.fallback_after_minutes" type="number" min="1" max="1440" />
|
||||
</label>
|
||||
<label class="settings-field">
|
||||
Recommended RDP-login-monitor
|
||||
<input v-model="agentUpdateForm.recommended_rdp_version" type="text" placeholder="2.1.0-SAC" />
|
||||
</label>
|
||||
<label class="settings-field">
|
||||
Recommended ssh-monitor
|
||||
<input v-model="agentUpdateForm.recommended_ssh_version" type="text" placeholder="2.1.0-SAC" />
|
||||
</label>
|
||||
<label class="settings-field">
|
||||
WinRM: путь к Deploy-LoginMonitor.ps1 (fallback)
|
||||
<input
|
||||
v-model="agentUpdateForm.win_agent_update_script"
|
||||
type="text"
|
||||
placeholder="C:\ProgramData\LoginMonitor\Deploy-LoginMonitor.ps1"
|
||||
/>
|
||||
</label>
|
||||
<p v-if="agentUpdateLoaded" class="settings-meta">
|
||||
Источник: <code>{{ agentUpdateLoaded.source }}</code>
|
||||
</p>
|
||||
<div class="settings-actions">
|
||||
<button type="submit" :disabled="savingAgentUpdate">
|
||||
{{ savingAgentUpdate ? "Сохранение…" : "Сохранить обновления агентов" }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="card settings-card settings-policy">
|
||||
<h2>Правило оповещений</h2>
|
||||
<p class="settings-hint settings-hint-top">
|
||||
@@ -514,6 +564,8 @@ import {
|
||||
fetchUsers,
|
||||
fetchWinAdminSettings,
|
||||
fetchLinuxAdminSettings,
|
||||
fetchAgentUpdateSettings,
|
||||
saveAgentUpdateSettings,
|
||||
revokeMobileDevice,
|
||||
deleteMobileDevice,
|
||||
revokeMobileEnrollmentCode,
|
||||
@@ -524,6 +576,7 @@ import {
|
||||
type MobileDevice,
|
||||
type MobileEnrollmentCode,
|
||||
type MobileSettings,
|
||||
type AgentUpdateSettings,
|
||||
type UserSummary,
|
||||
} from "../api";
|
||||
|
||||
@@ -604,6 +657,7 @@ const savingPolicy = ref(false);
|
||||
const savingUi = ref(false);
|
||||
const savingWinAdmin = ref(false);
|
||||
const savingLinuxAdmin = ref(false);
|
||||
const savingAgentUpdate = ref(false);
|
||||
const savingTelegram = ref(false);
|
||||
const savingWebhook = ref(false);
|
||||
const savingEmail = ref(false);
|
||||
@@ -623,6 +677,7 @@ const policyLoaded = ref<NotificationPolicy | null>(null);
|
||||
const uiLoaded = ref<UiSettings | null>(null);
|
||||
const winAdminLoaded = ref<WinAdminSettings | null>(null);
|
||||
const linuxAdminLoaded = ref<LinuxAdminSettings | null>(null);
|
||||
const agentUpdateLoaded = ref<AgentUpdateSettings | null>(null);
|
||||
const severityRows = ref<SeverityOverrideRowUi[]>([]);
|
||||
const severityFilter = ref("");
|
||||
const mobileLoaded = ref<MobileSettings | null>(null);
|
||||
@@ -695,6 +750,15 @@ const linuxAdminForm = reactive({
|
||||
password: "",
|
||||
});
|
||||
|
||||
const agentUpdateForm = reactive({
|
||||
mode: "gpo" as "gpo" | "sac",
|
||||
fallback_enabled: true,
|
||||
fallback_after_minutes: 15,
|
||||
recommended_rdp_version: "",
|
||||
recommended_ssh_version: "",
|
||||
win_agent_update_script: "",
|
||||
});
|
||||
|
||||
const telegramForm = reactive({
|
||||
enabled: false,
|
||||
bot_token: "",
|
||||
@@ -909,6 +973,38 @@ async function saveLinuxAdminSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAgentUpdateSettings() {
|
||||
const data = await fetchAgentUpdateSettings();
|
||||
agentUpdateLoaded.value = data;
|
||||
agentUpdateForm.mode = data.mode;
|
||||
agentUpdateForm.fallback_enabled = data.fallback_enabled;
|
||||
agentUpdateForm.fallback_after_minutes = data.fallback_after_minutes;
|
||||
agentUpdateForm.recommended_rdp_version = data.recommended_rdp_version ?? "";
|
||||
agentUpdateForm.recommended_ssh_version = data.recommended_ssh_version ?? "";
|
||||
agentUpdateForm.win_agent_update_script = data.win_agent_update_script ?? "";
|
||||
}
|
||||
|
||||
async function saveAgentUpdateSettingsForm() {
|
||||
savingAgentUpdate.value = true;
|
||||
error.value = "";
|
||||
success.value = "";
|
||||
try {
|
||||
agentUpdateLoaded.value = await saveAgentUpdateSettings({
|
||||
mode: agentUpdateForm.mode,
|
||||
fallback_enabled: agentUpdateForm.fallback_enabled,
|
||||
fallback_after_minutes: agentUpdateForm.fallback_after_minutes,
|
||||
recommended_rdp_version: agentUpdateForm.recommended_rdp_version.trim() || null,
|
||||
recommended_ssh_version: agentUpdateForm.recommended_ssh_version.trim() || null,
|
||||
win_agent_update_script: agentUpdateForm.win_agent_update_script.trim() || null,
|
||||
});
|
||||
success.value = "Настройки обновления агентов сохранены.";
|
||||
} catch (e) {
|
||||
error.value = e instanceof Error ? e.message : "Ошибка сохранения agent-updates";
|
||||
} finally {
|
||||
savingAgentUpdate.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadMobileSection() {
|
||||
mobileLoaded.value = await fetchMobileSettings();
|
||||
mobileForm.devices_allowed = mobileLoaded.value.devices_allowed;
|
||||
@@ -1056,6 +1152,7 @@ async function load() {
|
||||
await loadUiSettings();
|
||||
await loadWinAdminSettings();
|
||||
await loadLinuxAdminSettings();
|
||||
await loadAgentUpdateSettings();
|
||||
await loadSeverityOverrides();
|
||||
await loadMobileSection();
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user