<#954 Consume service configuration values from th...
# osctrl
g
#954 Consume service configuration values from the DB stored ones Pull request opened by javuto Summary Makes services consume DB-edited configuration at startup, so changes made through the API actually affect runtime behavior. This is phase 3 of the service config design. Problem Phases 1 and 2 persisted YAML config sections to the DB and allowed editing via the API, but the DB was still just a mirror. Services loaded config from YAML into
ServiceParameters
and used it directly — DB edits had no runtime effect. An operator could change
debug.enableHttp
to
true
in the frontend, but the service kept using the YAML value on the next boot. Changes
pkg/serviceconfig
—
Resolve
method
Resolve(service, cfg, envID)
reads all sections for a service from the DB and, for any section with
source=db
, unmarshals the JSON value into the matching
ServiceParameters
field — overriding the YAML default. Sections with
source=yaml
are skipped (the YAML value is already in
ServiceParameters
from the initial load). The
applySection
helper maps each section name to its
ServiceParameters
field and does the
json.Unmarshal
. All 15 sections are handled (
service
,
db
,
redis
,
osquery
,
tls
,
logger
,
carver
,
debug
,
batchWriter
,
configEndpoints
,
osctrld
,
metrics
,
saml
,
oidc
,
jwt
). Startup wiring Both services now call
Resolve
right after `Seed`: • `cmd/tls/main.go`:
Seed
→
Resolve
— DB-edited sections override YAML defaults in
flagParams
before any downstream consumer reads them. • `cmd/api/main.go`: same flow for the API service. The startup flow is now: load YAML → seed to DB (create-if-missing) → resolve DB overrides back into
ServiceParameters
. Every downstream consumer of
flagParams
(logger, carver, metrics, TLS, handlers, etc.) gets the resolved values. Tests (8 new in
pkg/serviceconfig/serviceconfig_test.go
) •
TestResolve_NoDBEdits_KeepsYAMLValues
— no-op when nothing is DB-edited. •
TestResolve_DBEditedSection_OverridesYAML
— debug section override. •
TestResolve_ServiceSection_OverridesYAML
— service section override (listener, port, host, log level, audit log). •
TestResolve_YAMLSourceSectionsAreSkipped
— source=yaml sections are not touched. •
TestResolve_UnknownService
— rejects unknown service. •
TestResolve_NilConfig
— rejects nil config. •
TestResolve_FullRoundTrip
— seed → edit → re-seed → resolve: DB value wins over fresh YAML. •
TestResolve_MultipleDBEdits
— multiple sections resolved simultaneously. Validation •
go build ./...
— clean •
go test ./...
— all packages pass (8 new tests in
pkg/serviceconfig
) •
golangci-lint run ./pkg/serviceconfig/...
— 0 issues •
gofmt
clean on all modified files How it works end-to-end 1. First boot: YAML loads into
ServiceParameters
→
Seed
creates DB rows with
source=yaml
→
Resolve
finds nothing to override (all
source=yaml
) → service uses YAML values. 2. Operator edits
debug
in the frontend
:
UpdateSection
flips
source=db
and stores the new JSON. 3. Next boot: YAML loads into
ServiceParameters
→
Seed
doesn't clobber the
source=db
row (create-if-missing) →
Resolve
sees
source=db
, unmarshals the DB value into
cfg.Debug
→ service uses the DB-edited value. Security notes •
Resolve
applies all sections with
source=db
, including non-editable ones like
db
and
redis
. This is intentional: non-editable sections can only get
source=db
through direct DB access (operator/automation), not through the API. The
Editable
flag gates the API write path;
Resolve
trusts any row the operator put in the DB. • The YAML file remains the bootstrap — if the DB is empty or the table is dropped, the service falls back to pure YAML behavior. jmpsec/osctrl