package config import ( "errors" "fmt" "os" "strings" ) // DispatcherRuntimeEnvironment contains deployment-owned runtime settings. A // pure preflight must finish before any SQLite, MQ, HTTP or gRPC resource opens. type DispatcherRuntimeEnvironment struct { DispatcherEnvironment Listen string AgentEndpointsFile string OSSConfigFile string CAFile string CertFile string KeyFile string PeerFingerprints map[string]struct{} } func LoadDispatcherRuntimeEnvironment(mode string) (DispatcherRuntimeEnvironment, error) { base, err := LoadDispatcherEnvironment(mode) if err != nil { return DispatcherRuntimeEnvironment{}, err } settings := DispatcherRuntimeEnvironment{DispatcherEnvironment: base} get := func(name string) (string, error) { value := os.Getenv(name) if strings.TrimSpace(value) == "" { return "", fmt.Errorf("%s is required", name) } return value, nil } for _, field := range []struct { name string value *string }{ {"DISPATCHER_AGENT_ENDPOINTS_FILE", &settings.AgentEndpointsFile}, {"MTLS_CA_FILE", &settings.CAFile}, {"MTLS_CERT_FILE", &settings.CertFile}, {"MTLS_KEY_FILE", &settings.KeyFile}, } { value, err := get(field.name) if err != nil { return DispatcherRuntimeEnvironment{}, err } *field.value = value } if mode == "sip-only" { return settings, nil } if settings.Listen, err = get("DISPATCHER_GRPC_LISTEN"); err != nil { return DispatcherRuntimeEnvironment{}, err } if settings.OSSConfigFile, err = get("DISPATCHER_OSS_CONFIG_FILE"); err != nil { return DispatcherRuntimeEnvironment{}, err } if !localGRPCAddress(settings.Listen, true) { return DispatcherRuntimeEnvironment{}, errors.New("DISPATCHER_GRPC_LISTEN must be an isolated local Mock address") } fingerprints, err := get("MTLS_PEER_CERT_FINGERPRINTS") if err != nil { return DispatcherRuntimeEnvironment{}, err } settings.PeerFingerprints, err = ParseCertificateFingerprints(fingerprints) if err != nil || len(settings.PeerFingerprints) == 0 { return DispatcherRuntimeEnvironment{}, errors.New("MTLS_PEER_CERT_FINGERPRINTS is invalid") } return settings, nil }