101 lines
3.1 KiB
Go
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()
|
|
}
|