This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
// NetworksConfig represents the /etc/user/config/networks.json structure
|
||||
type NetworksConfig struct {
|
||||
Networks map[string]NetworkConfig `json:"networks"`
|
||||
IPs map[string]IPConfig `json:"ips"`
|
||||
Policies []PolicyConfig `json:"policies"`
|
||||
}
|
||||
|
||||
// NetworkConfig represents a single network definition
|
||||
type NetworkConfig struct {
|
||||
NetworkName string `json:"network_name"`
|
||||
Subnet string `json:"subnet"`
|
||||
Gateway string `json:"gateway"`
|
||||
}
|
||||
|
||||
// IPConfig represents a single IP assignment
|
||||
type IPConfig struct {
|
||||
IP string `json:"ip"`
|
||||
ContainerName string `json:"container_name"`
|
||||
Selector string `json:"selector"`
|
||||
ServiceName string `json:"service_name"`
|
||||
}
|
||||
|
||||
// PolicyConfig represents a single policy rule from networks.json
|
||||
type PolicyConfig struct {
|
||||
ServiceName string `json:"service_name,omitempty"`
|
||||
ContainerName string `json:"container_name,omitempty"`
|
||||
Selector string `json:"selector,omitempty"`
|
||||
From string `json:"from,omitempty"`
|
||||
To string `json:"to,omitempty"`
|
||||
Port int `json:"port,omitempty"`
|
||||
Proto string `json:"proto,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Iface string `json:"iface,omitempty"`
|
||||
Nat string `json:"nat,omitempty"`
|
||||
}
|
||||
|
||||
// FirewallRule is a resolved, executable firewall rule derived from a PolicyConfig
|
||||
type FirewallRule struct {
|
||||
// Source info
|
||||
SourceIP string
|
||||
SourcePort int
|
||||
SourceIface string
|
||||
|
||||
// Target info
|
||||
TargetIP string
|
||||
TargetPort int
|
||||
|
||||
// Protocol (tcp/udp)
|
||||
Proto string
|
||||
|
||||
// Chain and table
|
||||
Chain string // PREROUTING, POSTROUTING, FORWARD, DOCKER-USER, etc.
|
||||
Table string // nat, filter
|
||||
|
||||
// Action
|
||||
Action string // DNAT, MASQUERADE, ACCEPT, DROP
|
||||
|
||||
// Comment for iptables
|
||||
Comment string
|
||||
|
||||
// Namespace info (empty = host, non-empty = container PID namespace)
|
||||
ContainerPID string
|
||||
}
|
||||
|
||||
// ToCIDR converts an IP without mask to a /24 CIDR notation (matching shell script behavior)
|
||||
func ToCIDR(ip string) string {
|
||||
// If it's already a CIDR, return as-is
|
||||
if _, _, err := net.ParseCIDR(ip); err == nil {
|
||||
return ip
|
||||
}
|
||||
// If last octet is 0, it's already a network address
|
||||
parsed := net.ParseIP(ip)
|
||||
if parsed == nil {
|
||||
return ip
|
||||
}
|
||||
ipv4 := parsed.To4()
|
||||
if ipv4 == nil {
|
||||
return ip
|
||||
}
|
||||
if ipv4[3] == 0 {
|
||||
return fmt.Sprintf("%d.%d.%d.0/24", ipv4[0], ipv4[1], ipv4[2])
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
// NetworkPrefix returns the first three octets as a /24 CIDR
|
||||
func NetworkPrefix(ip string) string {
|
||||
parsed := net.ParseIP(ip)
|
||||
if parsed == nil {
|
||||
return ip
|
||||
}
|
||||
ipv4 := parsed.To4()
|
||||
if ipv4 == nil {
|
||||
return ip
|
||||
}
|
||||
return fmt.Sprintf("%d.%d.%d.0/24", ipv4[0], ipv4[1], ipv4[2])
|
||||
}
|
||||
|
||||
// IsIP checks if a string is an IPv4 address
|
||||
func IsIP(s string) bool {
|
||||
parsed := net.ParseIP(s)
|
||||
return parsed != nil && parsed.To4() != nil
|
||||
}
|
||||
|
||||
// ParseCIDR parses the subnet string into an IPNet
|
||||
func (n NetworkConfig) ParseCIDR() (*net.IPNet, error) {
|
||||
_, ipNet, err := net.ParseCIDR(n.Subnet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse subnet %s: %w", n.Subnet, err)
|
||||
}
|
||||
return ipNet, nil
|
||||
}
|
||||
|
||||
// Load reads and parses the networks.json configuration file
|
||||
func Load(path string) (*NetworksConfig, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read config file %s: %w", path, err)
|
||||
}
|
||||
|
||||
var config NetworksConfig
|
||||
if err := json.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse config file %s: %w", path, err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
Reference in New Issue
Block a user