Netpulse_SasS/server/internal/store/ncm_redact_account_test.go
byrsapty c83324ae3e
Some checks failed
CI / hygiene (push) Successful in 9s
CI / web (push) Successful in 1m13s
CI / server (push) Successful in 1m34s
CI / dbtest (push) Successful in 1m52s
CI / agent (push) Has been cancelled
Відкат на живому залізі: пароль адміністратора лежав відкритим
Механізм відкату існував з 0035 і жодного разу не виконувався на
справжньому обладнанні. Прогін до межі заліза (план -> заявка ->
погодження, без заливки) дав три правильні відмови й одну знахідку.

D-Link питає пароль інтерактивно, і `show config` віддає відповіді
окремими рядками без ключових слів. Порядкове маскування за зразками
такий рядок не бачить, тож пароль адміністратора живого комутатора
лежав у плані відкату, у ncm.rollbacks і в git-дзеркалі — маскування
перед записом у git немає взагалі.

redactLines отримав стан: після рядка заведення облікового запису до
двох односкладових рядків маскуються. Ім'я запису лишається видимим.

Дорогою: перший рядок збереженого конфігу — відлуння команди
(`Command: show config`), і планувальникклав його в команди до заливки.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 23:42:43 +03:00

73 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package store
import (
"strings"
"testing"
)
// Точний уривок із конфігу живого комутатора D-Link DGS-1100-06/ME,
// через який вада й знайшлась: пароль адміністратора лежав відкритим у
// плані відкату, у базі й у git-дзеркалі.
//
// Пароль тут вигаданий; форма — справжня.
func TestAccountPasswordEchoIsMasked(t *testing.T) {
in := []string{
"# User Account",
"create account admin btadmin ",
"s3cr3tpass",
"s3cr3tpass",
"disable password encryption",
}
got := redactLines(nil, in)
for i, line := range got {
if strings.Contains(line, "s3cr3tpass") {
t.Errorf("рядок %d лишив пароль відкритим: %q", i, line)
}
}
if got[2] != "***" || got[3] != "***" {
t.Errorf("відлуння пароля не замасковане: %q, %q", got[2], got[3])
}
// Рядок про сам обліковий запис має лишитись читабельним: людина при
// погодженні мусить бачити, ЩО саме змінюється.
if !strings.Contains(got[1], "btadmin") {
t.Errorf("з'їдено ім'я облікового запису: %q", got[1])
}
}
// Маскування не має пожирати справжні рядки конфігу.
func TestAccountEchoDoesNotEatConfig(t *testing.T) {
in := []string{
"create account user guest ",
"pass1",
"pass1",
"enable", // односкладова команда одразу після відлуння
"disable clipaging", // звичайний рядок
}
got := redactLines(nil, in)
if got[3] != "enable" {
t.Errorf("з'їдено команду після двох рядків відлуння: %q", got[3])
}
if got[4] != "disable clipaging" {
t.Errorf("з'їдено звичайний рядок: %q", got[4])
}
}
// Односкладовий рядок САМ ПО СОБІ не секрет: маскується лише той, що
// стоїть одразу після заведення облікового запису.
func TestBareTokenAloneIsNotMasked(t *testing.T) {
got := redactLines(nil, []string{"enable", "end", "exit"})
for i, line := range got {
if line == "***" {
t.Errorf("рядок %d замасковано без причини: був %q", i, []string{"enable", "end", "exit"}[i])
}
}
}
// Стара поведінка не зламана: секрет в одному рядку з ключовим словом.
func TestInlineSecretStillMasked(t *testing.T) {
got := redactLines(nil, []string{"snmp-server community public RO"})
if strings.Contains(got[0], "public") {
t.Errorf("community лишилась відкритою: %q", got[0])
}
}