Files
felhom-controller/controller/internal/web/deploy_secret_exposure_test.go
T
admin f037be7a6a
gates / gates (push) Successful in 48s
R-970: the box's hub key opens no route; Data tab leftovers; R-1103: the install form's dead branches
R-970: /api/config, /api/config/hash, /api/config/apply removed (they read and replaced controller.yaml with
every secret, reachable with the box's own hub API key, unsigned; nothing called them). The hub-key Bearer
door on /api/selfupdate/ and /api/geo/ and the matching CSRF exemption are gone; the dashboard keeps using
those with a session. The route table is buildMux, so a test drives the real one.

Data tab: the export password field is autocomplete=new-password with a non-login name; the 2nd copy's
status rows that repeated the form are gone (the no-target reason moves into the form).

R-1103: app_fields.html loses its installed-only branches (no page serves them since R-1095); the tests
that rendered that dead path are retired, their rules asserted on the settings tab (R-694 moved there).

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-16 18:24:00 +02:00

69 lines
3.2 KiB
Go

package web
import (
"bytes"
"strings"
"testing"
"gitea.dooplex.hu/admin/felhom-controller/internal/stacks"
)
// R-254 site two — WHAT §7.2 ESTABLISHED, PINNED SO IT CANNOT DRIFT BACK.
//
// The deploy page has TWO places a generated secret can appear, and they are NOT the same question:
//
// - the PRE-DEPLOY hidden input — a form must carry what it submits. README §318 documents why:
// the customer is shown the generated secrets so they can note them down, and submitting them
// back is what makes the saved value the SAME one they saw ("no silent re-generation on submit").
// This is NOT the defect and is deliberately left alone.
// - the READONLY display input on an ALREADY-DEPLOYED app — nothing is being submitted there (the
// hidden input is correctly omitted), yet the value was rendered into the body of a page the
// customer merely opens. That IS R-249's shape, and it is what v0.208.0 fixes.
//
// Both directions are asserted, because "fixed" here means one branch changed and the other did not.
const testDeploySecret = "TESTONLY-generated-db-pw-Xy91"
func renderDeployPage(t *testing.T, alreadyDeployed bool) string {
t.Helper()
s := securityHarness(t)
s.loadTemplates()
data := map[string]interface{}{
"Page": "stacks", "Title": "Telepítés", "Domain": "example.hu",
"Stack": stacks.Stack{Name: "vaultwarden", Deployed: alreadyDeployed},
"Meta": stacks.Metadata{DisplayName: "Vaultwarden", Slug: "vaultwarden"},
"AlreadyDeployed": alreadyDeployed,
"AutoFields": []stacks.DeployField{
{EnvVar: "DB_PASSWORD", Label: "Adatbázis jelszó", Type: "secret"},
},
"AutoFieldValues": map[string]string{"DB_PASSWORD": testDeploySecret},
}
var buf bytes.Buffer
if err := s.tmpl.ExecuteTemplate(&buf, "deploy", data); err != nil {
t.Fatalf("render deploy: %v", err)
}
return buf.String()
}
// v0.322.0 (R-1103): TestDeployPage_DeployedApp_DoesNotCarryTheSecret is retired — the install form no longer renders
// for an installed app (R-1095, 302 to the settings tab). Its rule (an installed app's generated secret is not in the
// page; an eye fetches it) is asserted where the value is shown now: TestAppPage_LoginPairPanel (SECRET_KEY,
// ADMIN_USER, ADMIN_PASSWORD never in the settings page; every eye answers) and TestR255_NoPlantedSecretReachesAnyPage.
// The OTHER half of §7.2's answer: the pre-deploy form still carries the value, deliberately. If this
// ever starts failing, someone has "fixed" a form by stopping it submitting what it must submit —
// which would silently re-generate the secret on save and hand the customer a password that is not
// the one they wrote down.
func TestDeployPage_PreDeployForm_StillCarriesTheValue_Deliberately(t *testing.T) {
html := renderDeployPage(t, false)
if !strings.Contains(html, `<input type="hidden" name="DB_PASSWORD" value="`+testDeploySecret+`">`) {
t.Error("the pre-deploy form no longer submits the generated secret — the saved value would " +
"then not be the one the customer was shown (README §318, 'no silent re-generation on submit')")
}
if strings.Contains(html, `onclick="revealAutoField(`) {
t.Error("the deployed-app reveal control leaked onto the pre-deploy form, where the value is " +
"already legitimately present")
}
}