quorate/services/short/config/config.go

103 lines
2.1 KiB
Go
Raw Normal View History

package config
import (
"encoding/json"
"fmt"
"net/netip"
"os"
)
type Peer struct {
ID string `json:"id"`
Address string `json:"address"`
Secret string `json:"secret"`
}
type Bundle struct {
WAN string `json:"wan"`
Peers []Peer `json:"peers"`
}
type Runtime struct {
Bundle
Path Path `json:"path"`
}
type Cloud struct {
Tenancy string `json:"tenancy"`
User string `json:"user"`
Fingerprint string `json:"fingerprint"`
Region string `json:"region"`
Compartment string `json:"compartment"`
DRG string `json:"drg"`
Address string `json:"address"`
Network string `json:"network"`
}
type Path struct {
Address string `json:"address"`
Network string `json:"network"`
Gateway string `json:"gateway"`
Ports []uint16 `json:"ports"`
}
func Read[T any](path string) (T, error) {
var value T
data, err := os.ReadFile(path)
if err != nil {
return value, err
}
err = json.Unmarshal(data, &value)
return value, err
}
func (b Bundle) Validate() error {
if err := IPv4(b.WAN); err != nil {
return fmt.Errorf("WAN: %w", err)
}
if len(b.Peers) != 2 {
return fmt.Errorf("expected two OCI headends")
}
for _, p := range b.Peers {
if p.ID == "" || p.Secret == "" {
return fmt.Errorf("incomplete headend")
}
if err := IPv4(p.Address); err != nil {
return fmt.Errorf("headend: %w", err)
}
}
if b.Peers[0].ID == b.Peers[1].ID || b.Peers[0].Address == b.Peers[1].Address {
return fmt.Errorf("duplicate headend")
}
return nil
}
func (p Path) Validate() error {
if err := IPv4(p.Address); err != nil {
return err
}
if err := IPv4(p.Gateway); err != nil {
return fmt.Errorf("Gateway: %w", err)
}
n, err := netip.ParsePrefix(p.Network)
if err != nil || !n.Addr().Is4() {
return fmt.Errorf("invalid OCI network")
}
if len(p.Ports) == 0 {
return fmt.Errorf("empty service allowlist")
}
for _, port := range p.Ports {
if port == 0 {
return fmt.Errorf("invalid service port")
}
}
return nil
}
func IPv4(value string) error {
ip, err := netip.ParseAddr(value)
if err != nil || !ip.Is4() || !ip.IsGlobalUnicast() {
return fmt.Errorf("invalid unicast IPv4")
}
return nil
}