@@ -766,7 +792,7 @@ export function ServiceConfigPage() {
/>
)}
- {!loading && !hasError && sections.length > 0 && (
+ {!configDisabled && !loading && !hasError && sections.length > 0 && (
{sections.map((s) => (
- {showWarning && (
+ {showWarning && !configDisabled && (
{
try {
diff --git a/pkg/config/flags.go b/pkg/config/flags.go
index a3562286..32e27183 100644
--- a/pkg/config/flags.go
+++ b/pkg/config/flags.go
@@ -276,6 +276,13 @@ func initServiceFlags(params *ServiceParameters) []cli.Flag {
Sources: cli.EnvVars("SERVICE_POSTURE_ENABLED"),
Destination: ¶ms.Service.PostureEnabled,
},
+ &cli.BoolFlag{
+ Name: "service-config-enabled",
+ Value: false,
+ Usage: "Serve the service-config API and show the matching section in the SPA. Disabled by default: the YAML sections are still seeded into the database at every boot and resolved back at startup, but none of the /api/v1/service-config routes are registered — change the rows or the YAML file directly instead.",
+ Sources: cli.EnvVars("SERVICE_CONFIG_ENABLED"),
+ Destination: ¶ms.Service.ServiceConfigEnabled,
+ },
&cli.StringFlag{
Name: "posture-query-prefix",
Value: "osctrl:posture:",
diff --git a/pkg/config/flags_test.go b/pkg/config/flags_test.go
index d6885f2f..6cea8692 100644
--- a/pkg/config/flags_test.go
+++ b/pkg/config/flags_test.go
@@ -33,6 +33,32 @@ func TestServicePostureEnabledFlagDefaultsOff(t *testing.T) {
}
}
+func TestServiceConfigEnabledFlagDefaultsOff(t *testing.T) {
+ params := &ServiceParameters{Service: &YAMLConfigurationService{}}
+ flags := initServiceFlags(params)
+
+ if params.Service.ServiceConfigEnabled {
+ t.Fatalf("service config enabled default: got true want false")
+ }
+
+ var found *cli.BoolFlag
+ for _, flag := range flags {
+ if f, ok := flag.(*cli.BoolFlag); ok && f.Name == "service-config-enabled" {
+ found = f
+ break
+ }
+ }
+ if found == nil {
+ t.Fatalf("missing service-config-enabled service flag")
+ }
+ if found.Value {
+ t.Fatalf("service-config-enabled flag default: got true want false")
+ }
+ if found.Destination != ¶ms.Service.ServiceConfigEnabled {
+ t.Fatalf("service-config-enabled flag destination does not wire Service.ServiceConfigEnabled")
+ }
+}
+
func TestOsqueryAcceleratedFlagDefaultsOff(t *testing.T) {
params := &ServiceParameters{Osquery: &YAMLConfigurationOsquery{}}
flags := initOsqueryFlags(params)
diff --git a/pkg/config/types.go b/pkg/config/types.go
index e87b627a..cc44085e 100644
--- a/pkg/config/types.go
+++ b/pkg/config/types.go
@@ -124,8 +124,18 @@ type YAMLConfigurationService struct {
// whose result logs are ingested as node posture data. Only used
// when PostureEnabled is true.
PostureQueryPrefix string `yaml:"postureQueryPrefix"`
- Auth string `yaml:"auth"`
- AuditLog bool `yaml:"auditLog"`
+ // ServiceConfigEnabled controls whether the service-config API and the
+ // matching SPA section exist. It does not change how configuration is
+ // loaded: every boot seeds the YAML sections into the database and
+ // then resolves the stored values back over them, so the services
+ // always read from the database rows. When false (default) none of the
+ // /api/v1/service-config routes are registered and the SPA hides the
+ // section — the rows can still be changed directly in the database, or
+ // in the YAML file, and are picked up on the next restart. Consumed by
+ // osctrl-api; osctrl-tls ignores it.
+ ServiceConfigEnabled bool `yaml:"serviceConfigEnabled"`
+ Auth string `yaml:"auth"`
+ AuditLog bool `yaml:"auditLog"`
// TrustedProxies is a comma-separated list of CIDRs whose
// X-Real-IP / X-Forwarded-For headers utils.GetIP will honor.
// Default empty → forwarding headers are ignored and the