Files
go-sip/internal/config/agent_runtime.go
T

101 lines
3.1 KiB
Go

package config
import (
"errors"
"fmt"
"net"
"os"
"strconv"
"strings"
"git.ipao.vip/rogee/go-sip/internal/tenant"
)
// AgentEnvironment is deployment-owned and is inspected without opening any
// durable file, media adapter, credential or network connection.
type AgentEnvironment struct {
AgentID string
CellID string
DispatcherID string
Listen string
SessionPath string
RecoveryRoot string
DispatcherEndpoint string
DispatcherServerName string
CAFile string
CertFile string
KeyFile string
PeerFingerprints map[string]struct{}
MockScenarioFile string
MockAppliedSIPFile string
}
func LoadAgentEnvironment(mode string) (AgentEnvironment, error) {
if mode != "mock" {
return AgentEnvironment{}, errors.New("Agent accepts only isolated Mock mode")
}
get := func(name string) (string, error) {
value := os.Getenv(name)
if strings.TrimSpace(value) == "" {
return "", fmt.Errorf("%s is required", name)
}
return value, nil
}
var settings AgentEnvironment
for _, field := range []struct {
name string
value *string
}{
{"AGENT_ID", &settings.AgentID}, {"CELL_ID", &settings.CellID},
{"DISPATCHER_ID", &settings.DispatcherID},
{"AGENT_GRPC_LISTEN", &settings.Listen}, {"AGENT_SESSION_PATH", &settings.SessionPath},
{"AGENT_RECOVERY_ROOT", &settings.RecoveryRoot},
{"DISPATCHER_GRPC_ENDPOINT", &settings.DispatcherEndpoint},
{"DISPATCHER_GRPC_SERVER_NAME", &settings.DispatcherServerName},
{"MTLS_CA_FILE", &settings.CAFile}, {"MTLS_CERT_FILE", &settings.CertFile},
{"MTLS_KEY_FILE", &settings.KeyFile},
{"AGENT_MOCK_SCENARIO_FILE", &settings.MockScenarioFile},
{"AGENT_MOCK_APPLIED_SIP_FILE", &settings.MockAppliedSIPFile},
} {
value, err := get(field.name)
if err != nil {
return AgentEnvironment{}, err
}
*field.value = value
}
if tenant.ValidateDispatcherID(settings.DispatcherID) != nil {
return AgentEnvironment{}, errors.New("DISPATCHER_ID must be a canonical UUID v4")
}
if !localGRPCAddress(settings.Listen, true) {
return AgentEnvironment{}, errors.New("AGENT_GRPC_LISTEN must be an isolated local Mock address")
}
if !localGRPCAddress(settings.DispatcherEndpoint, false) {
return AgentEnvironment{}, errors.New("DISPATCHER_GRPC_ENDPOINT must be an isolated local Mock address")
}
rawFingerprints, err := get("MTLS_PEER_CERT_FINGERPRINTS")
if err != nil {
return AgentEnvironment{}, err
}
settings.PeerFingerprints, err = ParseCertificateFingerprints(rawFingerprints)
if err != nil || len(settings.PeerFingerprints) == 0 {
return AgentEnvironment{}, errors.New("MTLS_PEER_CERT_FINGERPRINTS is invalid")
}
return settings, nil
}
func localGRPCAddress(raw string, allowZeroPort bool) bool {
host, port, err := net.SplitHostPort(raw)
if err != nil {
return false
}
portNumber, err := strconv.Atoi(port)
if err != nil || portNumber < 0 || portNumber > 65535 || (!allowZeroPort && portNumber == 0) {
return false
}
if strings.EqualFold(host, "localhost") {
return true
}
ip := net.ParseIP(host)
return ip != nil && ip.IsLoopback()
}