chore(sources/env): bump gosettings to v0.3.0-rc13
- Use `RetroKeys` option with env.* method calls - Use `CSV*` typed methods - Inject `handleDeprecatedKey` function
This commit is contained in:
2
go.mod
2
go.mod
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/qdm12/dns v1.11.0
|
github.com/qdm12/dns v1.11.0
|
||||||
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6
|
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6
|
||||||
github.com/qdm12/gosettings v0.3.0-rc12
|
github.com/qdm12/gosettings v0.3.0-rc13
|
||||||
github.com/qdm12/goshutdown v0.3.0
|
github.com/qdm12/goshutdown v0.3.0
|
||||||
github.com/qdm12/gosplash v0.1.0
|
github.com/qdm12/gosplash v0.1.0
|
||||||
github.com/qdm12/gotree v0.2.0
|
github.com/qdm12/gotree v0.2.0
|
||||||
|
|||||||
8
go.sum
8
go.sum
@@ -91,12 +91,8 @@ github.com/qdm12/golibs v0.0.0-20210603202746-e5494e9c2ebb/go.mod h1:15RBzkun0i8
|
|||||||
github.com/qdm12/golibs v0.0.0-20210723175634-a75ca7fd74c2/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg=
|
github.com/qdm12/golibs v0.0.0-20210723175634-a75ca7fd74c2/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg=
|
||||||
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6 h1:bge5AL7cjHJMPz+5IOz5yF01q/l8No6+lIEBieA8gMg=
|
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6 h1:bge5AL7cjHJMPz+5IOz5yF01q/l8No6+lIEBieA8gMg=
|
||||||
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg=
|
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg=
|
||||||
github.com/qdm12/gosettings v0.3.0-rc11 h1:zbH+TiimUdZTzOTMuFqCCC0XFKr3KGC6sZDyuw6y65A=
|
github.com/qdm12/gosettings v0.3.0-rc13 h1:fag+/hFPBUcNk3a5ifUbwNS2VgXFpxindkl8mQNk76U=
|
||||||
github.com/qdm12/gosettings v0.3.0-rc11/go.mod h1:+hHzN8lsE63T01t6SruGzc6xkpvfsZFod/ooDs8FWnQ=
|
github.com/qdm12/gosettings v0.3.0-rc13/go.mod h1:JRV3opOpHvnKlIA29lKQMdYw1WSMVMfHYLLHPHol5ME=
|
||||||
github.com/qdm12/gosettings v0.3.0-rc12 h1:HhdVkpFiZfwsAbSiPNpCHk/OsY7Ogl+wrU/y9/1R0y4=
|
|
||||||
github.com/qdm12/gosettings v0.3.0-rc12/go.mod h1:+hHzN8lsE63T01t6SruGzc6xkpvfsZFod/ooDs8FWnQ=
|
|
||||||
github.com/qdm12/gosettings v0.3.0-rc9 h1:/Hr+lXjAeZFQ5LiEX+sKgMyWSckmhvTSs9iGo/Ch+q0=
|
|
||||||
github.com/qdm12/gosettings v0.3.0-rc9/go.mod h1:+hHzN8lsE63T01t6SruGzc6xkpvfsZFod/ooDs8FWnQ=
|
|
||||||
github.com/qdm12/goshutdown v0.3.0 h1:pqBpJkdwlZlfTEx4QHtS8u8CXx6pG0fVo6S1N0MpSEM=
|
github.com/qdm12/goshutdown v0.3.0 h1:pqBpJkdwlZlfTEx4QHtS8u8CXx6pG0fVo6S1N0MpSEM=
|
||||||
github.com/qdm12/goshutdown v0.3.0/go.mod h1:EqZ46No00kCTZ5qzdd3qIzY6ayhMt24QI8Mh8LVQYmM=
|
github.com/qdm12/goshutdown v0.3.0/go.mod h1:EqZ46No00kCTZ5qzdd3qIzY6ayhMt24QI8Mh8LVQYmM=
|
||||||
github.com/qdm12/gosplash v0.1.0 h1:Sfl+zIjFZFP7b0iqf2l5UkmEY97XBnaKkH3FNY6Gf7g=
|
github.com/qdm12/gosplash v0.1.0 h1:Sfl+zIjFZFP7b0iqf2l5UkmEY97XBnaKkH3FNY6Gf7g=
|
||||||
|
|||||||
15
internal/configuration/sources/env/dns.go
vendored
15
internal/configuration/sources/env/dns.go
vendored
@@ -27,19 +27,24 @@ func (s *Source) readDNS() (dns settings.DNS, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readDNSServerAddress() (address netip.Addr, err error) {
|
func (s *Source) readDNSServerAddress() (address netip.Addr, err error) {
|
||||||
key, value := s.getEnvWithRetro("DNS_ADDRESS", []string{"DNS_PLAINTEXT_ADDRESS"})
|
const currentKey = "DNS_ADDRESS"
|
||||||
if value == nil {
|
key := firstKeySet(s.env, "DNS_PLAINTEXT_ADDRESS", currentKey)
|
||||||
|
switch key {
|
||||||
|
case "":
|
||||||
return address, nil
|
return address, nil
|
||||||
|
case currentKey:
|
||||||
|
default: // Retro-compatibility
|
||||||
|
s.handleDeprecatedKey(key, currentKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
address, err = netip.ParseAddr(*value)
|
address, err = s.env.NetipAddr(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return address, fmt.Errorf("environment variable %s: %w", key, err)
|
return address, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove in v4
|
// TODO remove in v4
|
||||||
if address.Unmap().Compare(netip.AddrFrom4([4]byte{127, 0, 0, 1})) != 0 {
|
if address.Unmap().Compare(netip.AddrFrom4([4]byte{127, 0, 0, 1})) != 0 {
|
||||||
s.warner.Warn(key + " is set to " + *value +
|
s.warner.Warn(key + " is set to " + address.String() +
|
||||||
" so the DNS over TLS (DoT) server will not be used." +
|
" so the DNS over TLS (DoT) server will not be used." +
|
||||||
" The default value changed to 127.0.0.1 so it uses the internal DoT serves." +
|
" The default value changed to 127.0.0.1 so it uses the internal DoT serves." +
|
||||||
" If the DoT server fails to start, the IPv4 address of the first plaintext DNS server" +
|
" If the DoT server fails to start, the IPv4 address of the first plaintext DNS server" +
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readDNSBlacklist() (blacklist settings.DNSBlacklist, err error) {
|
func (s *Source) readDNSBlacklist() (blacklist settings.DNSBlacklist, err error) {
|
||||||
@@ -14,7 +15,8 @@ func (s *Source) readDNSBlacklist() (blacklist settings.DNSBlacklist, err error)
|
|||||||
return blacklist, err
|
return blacklist, err
|
||||||
}
|
}
|
||||||
|
|
||||||
blacklist.BlockSurveillance, err = s.readBlockSurveillance()
|
blacklist.BlockSurveillance, err = s.env.BoolPtr("BLOCK_SURVEILLANCE",
|
||||||
|
env.RetroKeys("BLOCK_NSA"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return blacklist, err
|
return blacklist, err
|
||||||
}
|
}
|
||||||
@@ -35,11 +37,6 @@ func (s *Source) readDNSBlacklist() (blacklist settings.DNSBlacklist, err error)
|
|||||||
return blacklist, nil
|
return blacklist, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readBlockSurveillance() (blocked *bool, err error) {
|
|
||||||
key, _ := s.getEnvWithRetro("BLOCK_SURVEILLANCE", []string{"BLOCK_NSA"})
|
|
||||||
return s.env.BoolPtr(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrPrivateAddressNotValid = errors.New("private address is not a valid IP or CIDR range")
|
ErrPrivateAddressNotValid = errors.New("private address is not a valid IP or CIDR range")
|
||||||
)
|
)
|
||||||
|
|||||||
60
internal/configuration/sources/env/firewall.go
vendored
60
internal/configuration/sources/env/firewall.go
vendored
@@ -1,32 +1,25 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net/netip"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readFirewall() (firewall settings.Firewall, err error) {
|
func (s *Source) readFirewall() (firewall settings.Firewall, err error) {
|
||||||
vpnInputPortStrings := s.env.CSV("FIREWALL_VPN_INPUT_PORTS")
|
firewall.VPNInputPorts, err = s.env.CSVUint16("FIREWALL_VPN_INPUT_PORTS")
|
||||||
firewall.VPNInputPorts, err = stringsToPorts(vpnInputPortStrings)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return firewall, fmt.Errorf("environment variable FIREWALL_VPN_INPUT_PORTS: %w", err)
|
return firewall, err
|
||||||
}
|
}
|
||||||
|
|
||||||
inputPortStrings := s.env.CSV("FIREWALL_INPUT_PORTS")
|
firewall.InputPorts, err = s.env.CSVUint16("FIREWALL_INPUT_PORTS")
|
||||||
firewall.InputPorts, err = stringsToPorts(inputPortStrings)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return firewall, fmt.Errorf("environment variable FIREWALL_INPUT_PORTS: %w", err)
|
return firewall, err
|
||||||
}
|
}
|
||||||
|
|
||||||
outboundSubnetsKey, _ := s.getEnvWithRetro("FIREWALL_OUTBOUND_SUBNETS", []string{"EXTRA_SUBNETS"})
|
firewall.OutboundSubnets, err = s.env.CSVNetipPrefixes("FIREWALL_OUTBOUND_SUBNETS",
|
||||||
outboundSubnetStrings := s.env.CSV(outboundSubnetsKey)
|
env.RetroKeys("EXTRA_SUBNETS"))
|
||||||
firewall.OutboundSubnets, err = stringsToNetipPrefixes(outboundSubnetStrings)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return firewall, fmt.Errorf("environment variable %s: %w", outboundSubnetsKey, err)
|
return firewall, err
|
||||||
}
|
}
|
||||||
|
|
||||||
firewall.Enabled, err = s.env.BoolPtr("FIREWALL")
|
firewall.Enabled, err = s.env.BoolPtr("FIREWALL")
|
||||||
@@ -41,40 +34,3 @@ func (s *Source) readFirewall() (firewall settings.Firewall, err error) {
|
|||||||
|
|
||||||
return firewall, nil
|
return firewall, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
ErrPortParsing = errors.New("cannot parse port")
|
|
||||||
ErrPortValue = errors.New("port value is not valid")
|
|
||||||
)
|
|
||||||
|
|
||||||
func stringsToPorts(ss []string) (ports []uint16, err error) {
|
|
||||||
if len(ss) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
ports = make([]uint16, len(ss))
|
|
||||||
for i, s := range ss {
|
|
||||||
port, err := strconv.Atoi(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%w: %s: %s", ErrPortParsing, s, err)
|
|
||||||
} else if port < 1 || port > 65535 {
|
|
||||||
return nil, fmt.Errorf("%w: must be between 1 and 65535: %d",
|
|
||||||
ErrPortValue, port)
|
|
||||||
}
|
|
||||||
ports[i] = uint16(port)
|
|
||||||
}
|
|
||||||
return ports, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringsToNetipPrefixes(ss []string) (ipPrefixes []netip.Prefix, err error) {
|
|
||||||
if len(ss) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
ipPrefixes = make([]netip.Prefix, len(ss))
|
|
||||||
for i, s := range ss {
|
|
||||||
ipPrefixes[i], err = netip.ParsePrefix(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("parsing IP network %q: %w", s, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ipPrefixes, nil
|
|
||||||
}
|
|
||||||
|
|||||||
20
internal/configuration/sources/env/health.go
vendored
20
internal/configuration/sources/env/health.go
vendored
@@ -1,15 +1,14 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) ReadHealth() (health settings.Health, err error) {
|
func (s *Source) ReadHealth() (health settings.Health, err error) {
|
||||||
health.ServerAddress = s.env.String("HEALTH_SERVER_ADDRESS")
|
health.ServerAddress = s.env.String("HEALTH_SERVER_ADDRESS")
|
||||||
targetAddressEnvKey, _ := s.getEnvWithRetro("HEALTH_TARGET_ADDRESS", []string{"HEALTH_ADDRESS_TO_PING"})
|
health.TargetAddress = s.env.String("HEALTH_TARGET_ADDRESS",
|
||||||
health.TargetAddress = s.env.String(targetAddressEnvKey)
|
env.RetroKeys("HEALTH_ADDRESS_TO_PING"))
|
||||||
|
|
||||||
successWaitPtr, err := s.env.DurationPtr("HEALTH_SUCCESS_WAIT_DURATION")
|
successWaitPtr, err := s.env.DurationPtr("HEALTH_SUCCESS_WAIT_DURATION")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -18,24 +17,19 @@ func (s *Source) ReadHealth() (health settings.Health, err error) {
|
|||||||
health.SuccessWait = *successWaitPtr
|
health.SuccessWait = *successWaitPtr
|
||||||
}
|
}
|
||||||
|
|
||||||
health.VPN.Initial, err = s.readDurationWithRetro(
|
health.VPN.Initial, err = s.env.DurationPtr(
|
||||||
"HEALTH_VPN_DURATION_INITIAL",
|
"HEALTH_VPN_DURATION_INITIAL",
|
||||||
"HEALTH_OPENVPN_DURATION_INITIAL")
|
env.RetroKeys("HEALTH_OPENVPN_DURATION_INITIAL"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return health, err
|
return health, err
|
||||||
}
|
}
|
||||||
|
|
||||||
health.VPN.Addition, err = s.readDurationWithRetro(
|
health.VPN.Addition, err = s.env.DurationPtr(
|
||||||
"HEALTH_VPN_DURATION_ADDITION",
|
"HEALTH_VPN_DURATION_ADDITION",
|
||||||
"HEALTH_OPENVPN_DURATION_ADDITION")
|
env.RetroKeys("HEALTH_OPENVPN_DURATION_ADDITION"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return health, err
|
return health, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return health, nil
|
return health, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readDurationWithRetro(envKey, retroEnvKey string) (d *time.Duration, err error) {
|
|
||||||
envKey, _ = s.getEnvWithRetro(envKey, []string{retroEnvKey})
|
|
||||||
return s.env.DurationPtr(envKey)
|
|
||||||
}
|
|
||||||
|
|||||||
12
internal/configuration/sources/env/helpers.go
vendored
12
internal/configuration/sources/env/helpers.go
vendored
@@ -3,6 +3,8 @@ package env
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
func unsetEnvKeys(envKeys []string, err error) (newErr error) {
|
func unsetEnvKeys(envKeys []string, err error) (newErr error) {
|
||||||
@@ -19,3 +21,13 @@ func unsetEnvKeys(envKeys []string, err error) (newErr error) {
|
|||||||
func ptrTo[T any](value T) *T {
|
func ptrTo[T any](value T) *T {
|
||||||
return &value
|
return &value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func firstKeySet(e env.Env, keys ...string) (firstKeySet string) {
|
||||||
|
for _, key := range keys {
|
||||||
|
value := e.Get(key)
|
||||||
|
if value != nil {
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
66
internal/configuration/sources/env/httproxy.go
vendored
66
internal/configuration/sources/env/httproxy.go
vendored
@@ -9,15 +9,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readHTTPProxy() (httpProxy settings.HTTPProxy, err error) {
|
func (s *Source) readHTTPProxy() (httpProxy settings.HTTPProxy, err error) {
|
||||||
_, httpProxy.User = s.getEnvWithRetro("HTTPPROXY_USER",
|
httpProxy.User = s.env.Get("HTTPPROXY_USER",
|
||||||
[]string{"PROXY_USER", "TINYPROXY_USER"}, env.ForceLowercase(false))
|
env.RetroKeys("PROXY_USER", "TINYPROXY_USER"),
|
||||||
|
env.ForceLowercase(false))
|
||||||
|
|
||||||
_, httpProxy.Password = s.getEnvWithRetro("HTTPPROXY_PASSWORD",
|
httpProxy.Password = s.env.Get("HTTPPROXY_PASSWORD",
|
||||||
[]string{"PROXY_PASSWORD", "TINYPROXY_PASSWORD"}, env.ForceLowercase(false))
|
env.RetroKeys("PROXY_PASSWORD", "TINYPROXY_PASSWORD"),
|
||||||
|
env.ForceLowercase(false))
|
||||||
|
|
||||||
httpProxy.ListeningAddress = s.readHTTProxyListeningAddress()
|
httpProxy.ListeningAddress, err = s.readHTTProxyListeningAddress()
|
||||||
|
if err != nil {
|
||||||
|
return httpProxy, err
|
||||||
|
}
|
||||||
|
|
||||||
httpProxy.Enabled, err = s.readHTTProxyEnabled()
|
httpProxy.Enabled, err = s.env.BoolPtr("HTTPPROXY", env.RetroKeys("PROXY", "TINYPROXY"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return httpProxy, err
|
return httpProxy, err
|
||||||
}
|
}
|
||||||
@@ -35,37 +40,42 @@ func (s *Source) readHTTPProxy() (httpProxy settings.HTTPProxy, err error) {
|
|||||||
return httpProxy, nil
|
return httpProxy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readHTTProxyListeningAddress() (listeningAddress string) {
|
func (s *Source) readHTTProxyListeningAddress() (listeningAddress string, err error) {
|
||||||
key, value := s.getEnvWithRetro("HTTPPROXY_LISTENING_ADDRESS",
|
const currentKey = "HTTPPROXY_LISTENING_ADDRESS"
|
||||||
[]string{"PROXY_PORT", "TINYPROXY_PORT", "HTTPPROXY_PORT"})
|
key := firstKeySet(s.env, "HTTPPROXY_PORT", "TINYPROXY_PORT", "PROXY_PORT",
|
||||||
if value == nil {
|
currentKey)
|
||||||
return ""
|
switch key {
|
||||||
} else if key == "HTTPPROXY_LISTENING_ADDRESS" {
|
case "":
|
||||||
return *value
|
return "", nil
|
||||||
|
case currentKey:
|
||||||
|
return s.env.String(key), nil
|
||||||
}
|
}
|
||||||
return ":" + *value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Source) readHTTProxyEnabled() (enabled *bool, err error) {
|
// Retro-compatible keys using a port only
|
||||||
key, _ := s.getEnvWithRetro("HTTPPROXY",
|
s.handleDeprecatedKey(key, currentKey)
|
||||||
[]string{"PROXY", "TINYPROXY"})
|
port, err := s.env.Uint16Ptr(key)
|
||||||
return s.env.BoolPtr(key)
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(":%d", *port), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readHTTProxyLog() (enabled *bool, err error) {
|
func (s *Source) readHTTProxyLog() (enabled *bool, err error) {
|
||||||
key, value := s.getEnvWithRetro("HTTPPROXY_LOG",
|
const currentKey = "HTTPPROXY_LOG"
|
||||||
[]string{"PROXY_LOG_LEVEL", "TINYPROXY_LOG"})
|
key := firstKeySet(s.env, "PROXY_LOG", "TINYPROXY_LOG", "HTTPPROXY_LOG")
|
||||||
if value == nil {
|
switch key {
|
||||||
|
case "":
|
||||||
return nil, nil //nolint:nilnil
|
return nil, nil //nolint:nilnil
|
||||||
|
case currentKey:
|
||||||
|
return s.env.BoolPtr(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
var binaryOptions []binary.Option
|
// Retro-compatible keys using different boolean verbs
|
||||||
if key != "HTTPROXY_LOG" {
|
s.handleDeprecatedKey(key, currentKey)
|
||||||
retroOption := binary.OptionEnabled("on", "info", "connect", "notice")
|
value := s.env.String(key)
|
||||||
binaryOptions = append(binaryOptions, retroOption)
|
retroOption := binary.OptionEnabled("on", "info", "connect", "notice")
|
||||||
}
|
|
||||||
|
|
||||||
enabled, err = binary.Validate(*value, binaryOptions...)
|
enabled, err = binary.Validate(value, retroOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("environment variable %s: %w", key, err)
|
return nil, fmt.Errorf("environment variable %s: %w", key, err)
|
||||||
}
|
}
|
||||||
|
|||||||
56
internal/configuration/sources/env/openvpn.go
vendored
56
internal/configuration/sources/env/openvpn.go
vendored
@@ -1,12 +1,10 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/gosettings/sources/env"
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
"github.com/qdm12/govalid/binary"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readOpenVPN() (
|
func (s *Source) readOpenVPN() (
|
||||||
@@ -17,15 +15,12 @@ func (s *Source) readOpenVPN() (
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
openVPN.Version = s.env.String("OPENVPN_VERSION")
|
openVPN.Version = s.env.String("OPENVPN_VERSION")
|
||||||
_, openVPN.User = s.getEnvWithRetro("OPENVPN_USER",
|
openVPN.User = s.env.Get("OPENVPN_USER",
|
||||||
[]string{"USER"}, env.ForceLowercase(false))
|
env.RetroKeys("USER"), env.ForceLowercase(false))
|
||||||
_, openVPN.Password = s.getEnvWithRetro("OPENVPN_PASSWORD",
|
openVPN.Password = s.env.Get("OPENVPN_PASSWORD",
|
||||||
[]string{"PASSWORD"}, env.ForceLowercase(false))
|
env.RetroKeys("PASSWORD"), env.ForceLowercase(false))
|
||||||
openVPN.ConfFile = s.env.Get("OPENVPN_CUSTOM_CONFIG")
|
openVPN.ConfFile = s.env.Get("OPENVPN_CUSTOM_CONFIG")
|
||||||
|
openVPN.Ciphers = s.env.CSV("OPENVPN_CIPHERS", env.RetroKeys("OPENVPN_CIPHER"))
|
||||||
ciphersKey, _ := s.getEnvWithRetro("OPENVPN_CIPHERS", []string{"OPENVPN_CIPHER"})
|
|
||||||
openVPN.Ciphers = s.env.CSV(ciphersKey)
|
|
||||||
|
|
||||||
openVPN.Auth = s.env.Get("OPENVPN_AUTH")
|
openVPN.Auth = s.env.Get("OPENVPN_AUTH")
|
||||||
openVPN.Cert = s.env.Get("OPENVPN_CERT", env.ForceLowercase(false))
|
openVPN.Cert = s.env.Get("OPENVPN_CERT", env.ForceLowercase(false))
|
||||||
openVPN.Key = s.env.Get("OPENVPN_KEY", env.ForceLowercase(false))
|
openVPN.Key = s.env.Get("OPENVPN_KEY", env.ForceLowercase(false))
|
||||||
@@ -39,11 +34,8 @@ func (s *Source) readOpenVPN() (
|
|||||||
return openVPN, err
|
return openVPN, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, openvpnInterface := s.getEnvWithRetro("VPN_INTERFACE",
|
openVPN.Interface = s.env.String("VPN_INTERFACE",
|
||||||
[]string{"OPENVPN_INTERFACE"}, env.ForceLowercase(false))
|
env.RetroKeys("OPENVPN_INTERFACE"), env.ForceLowercase(false))
|
||||||
if openvpnInterface != nil {
|
|
||||||
openVPN.Interface = *openvpnInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
openVPN.ProcessUser, err = s.readOpenVPNProcessUser()
|
openVPN.ProcessUser, err = s.readOpenVPNProcessUser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -64,32 +56,22 @@ func (s *Source) readOpenVPN() (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readPIAEncryptionPreset() (presetPtr *string) {
|
func (s *Source) readPIAEncryptionPreset() (presetPtr *string) {
|
||||||
_, presetPtr = s.getEnvWithRetro(
|
return s.env.Get(
|
||||||
"PRIVATE_INTERNET_ACCESS_OPENVPN_ENCRYPTION_PRESET",
|
"PRIVATE_INTERNET_ACCESS_OPENVPN_ENCRYPTION_PRESET",
|
||||||
[]string{"PIA_ENCRYPTION", "ENCRYPTION"})
|
env.RetroKeys("ENCRYPTION", "PIA_ENCRYPTION"))
|
||||||
return presetPtr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readOpenVPNProcessUser() (processUser string, err error) {
|
func (s *Source) readOpenVPNProcessUser() (processUser string, err error) {
|
||||||
key, value := s.getEnvWithRetro("OPENVPN_PROCESS_USER",
|
value, err := s.env.BoolPtr("OPENVPN_ROOT") // Retro-compatibility
|
||||||
[]string{"OPENVPN_ROOT"})
|
if err != nil {
|
||||||
if value == nil {
|
return "", err
|
||||||
return "", nil
|
} else if value != nil {
|
||||||
} else if key == "OPENVPN_PROCESS_USER" {
|
if *value {
|
||||||
return *value, nil
|
return "root", nil
|
||||||
|
}
|
||||||
|
const defaultNonRootUser = "nonrootuser"
|
||||||
|
return defaultNonRootUser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retro-compatibility
|
return s.env.String("OPENVPN_PROCESS_USER"), nil
|
||||||
if *value == "" {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
root, err := binary.Validate(*value)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("environment variable %s: %w", key, err)
|
|
||||||
}
|
|
||||||
if *root {
|
|
||||||
return "root", nil
|
|
||||||
}
|
|
||||||
const defaultNonRootUser = "nonrootuser"
|
|
||||||
return defaultNonRootUser, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ func (s *Source) readOpenVPNSelection() (
|
|||||||
return selection, err
|
return selection, err
|
||||||
}
|
}
|
||||||
|
|
||||||
selection.CustomPort, err = s.readOpenVPNCustomPort()
|
selection.CustomPort, err = s.env.Uint16Ptr("VPN_ENDPOINT_PORT",
|
||||||
|
env.RetroKeys("PORT", "OPENVPN_PORT"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return selection, err
|
return selection, err
|
||||||
}
|
}
|
||||||
@@ -32,15 +33,18 @@ func (s *Source) readOpenVPNSelection() (
|
|||||||
var ErrOpenVPNProtocolNotValid = errors.New("OpenVPN protocol is not valid")
|
var ErrOpenVPNProtocolNotValid = errors.New("OpenVPN protocol is not valid")
|
||||||
|
|
||||||
func (s *Source) readOpenVPNProtocol() (tcp *bool, err error) {
|
func (s *Source) readOpenVPNProtocol() (tcp *bool, err error) {
|
||||||
envKey, protocolPtr := s.getEnvWithRetro("OPENVPN_PROTOCOL", []string{"PROTOCOL"})
|
const currentKey = "OPENVPN_PROTOCOL"
|
||||||
if protocolPtr == nil {
|
envKey := firstKeySet(s.env, "PROTOCOL", currentKey)
|
||||||
return nil, nil //nolint:nilnil
|
switch envKey {
|
||||||
}
|
|
||||||
protocol := *protocolPtr
|
|
||||||
|
|
||||||
switch strings.ToLower(protocol) {
|
|
||||||
case "":
|
case "":
|
||||||
return nil, nil //nolint:nilnil
|
return nil, nil //nolint:nilnil
|
||||||
|
case currentKey:
|
||||||
|
default: // Retro compatibility
|
||||||
|
s.handleDeprecatedKey(envKey, currentKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol := s.env.String(envKey)
|
||||||
|
switch strings.ToLower(protocol) {
|
||||||
case constants.UDP:
|
case constants.UDP:
|
||||||
return ptrTo(false), nil
|
return ptrTo(false), nil
|
||||||
case constants.TCP:
|
case constants.TCP:
|
||||||
@@ -50,8 +54,3 @@ func (s *Source) readOpenVPNProtocol() (tcp *bool, err error) {
|
|||||||
envKey, ErrOpenVPNProtocolNotValid, protocol)
|
envKey, ErrOpenVPNProtocolNotValid, protocol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readOpenVPNCustomPort() (customPort *uint16, err error) {
|
|
||||||
key, _ := s.getEnvWithRetro("VPN_ENDPOINT_PORT", []string{"PORT", "OPENVPN_PORT"})
|
|
||||||
return s.env.Uint16Ptr(key)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,21 +7,21 @@ import (
|
|||||||
|
|
||||||
func (s *Source) readPortForward() (
|
func (s *Source) readPortForward() (
|
||||||
portForwarding settings.PortForwarding, err error) {
|
portForwarding settings.PortForwarding, err error) {
|
||||||
key, _ := s.getEnvWithRetro("VPN_PORT_FORWARDING",
|
portForwarding.Enabled, err = s.env.BoolPtr("VPN_PORT_FORWARDING",
|
||||||
[]string{
|
env.RetroKeys(
|
||||||
"PRIVATE_INTERNET_ACCESS_VPN_PORT_FORWARDING",
|
|
||||||
"PORT_FORWARDING",
|
"PORT_FORWARDING",
|
||||||
})
|
"PRIVATE_INTERNET_ACCESS_VPN_PORT_FORWARDING",
|
||||||
portForwarding.Enabled, err = s.env.BoolPtr(key)
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return portForwarding, err
|
return portForwarding, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, portForwarding.Filepath = s.getEnvWithRetro("VPN_PORT_FORWARDING_STATUS_FILE",
|
portForwarding.Filepath = s.env.Get("VPN_PORT_FORWARDING_STATUS_FILE",
|
||||||
[]string{
|
env.ForceLowercase(false),
|
||||||
"PRIVATE_INTERNET_ACCESS_VPN_PORT_FORWARDING_STATUS_FILE",
|
env.RetroKeys(
|
||||||
"PORT_FORWARDING_STATUS_FILE",
|
"PORT_FORWARDING_STATUS_FILE",
|
||||||
}, env.ForceLowercase(false))
|
"PRIVATE_INTERNET_ACCESS_VPN_PORT_FORWARDING_STATUS_FILE",
|
||||||
|
))
|
||||||
|
|
||||||
return portForwarding, nil
|
return portForwarding, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/gluetun/internal/constants/providers"
|
"github.com/qdm12/gluetun/internal/constants/providers"
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readProvider(vpnType string) (provider settings.Provider, err error) {
|
func (s *Source) readProvider(vpnType string) (provider settings.Provider, err error) {
|
||||||
@@ -30,7 +31,7 @@ func (s *Source) readProvider(vpnType string) (provider settings.Provider, err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readVPNServiceProvider(vpnType string) (vpnProviderPtr *string) {
|
func (s *Source) readVPNServiceProvider(vpnType string) (vpnProviderPtr *string) {
|
||||||
_, valuePtr := s.getEnvWithRetro("VPN_SERVICE_PROVIDER", []string{"VPNSP"})
|
valuePtr := s.env.Get("VPN_SERVICE_PROVIDER", env.RetroKeys("VPNSP"))
|
||||||
if valuePtr == nil {
|
if valuePtr == nil {
|
||||||
if vpnType != vpn.Wireguard && s.env.Get("OPENVPN_CUSTOM_CONFIG") != nil {
|
if vpnType != vpn.Wireguard && s.env.Get("OPENVPN_CUSTOM_CONFIG") != nil {
|
||||||
// retro compatibility
|
// retro compatibility
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ func (s *Source) readPublicIP() (publicIP settings.PublicIP, err error) {
|
|||||||
return publicIP, err
|
return publicIP, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, publicIP.IPFilepath = s.getEnvWithRetro("PUBLICIP_FILE",
|
publicIP.IPFilepath = s.env.Get("PUBLICIP_FILE",
|
||||||
[]string{"IP_STATUS_FILE"}, env.ForceLowercase(false))
|
env.ForceLowercase(false), env.RetroKeys("IP_STATUS_FILE"))
|
||||||
|
|
||||||
return publicIP, nil
|
return publicIP, nil
|
||||||
}
|
}
|
||||||
|
|||||||
43
internal/configuration/sources/env/reader.go
vendored
43
internal/configuration/sources/env/reader.go
vendored
@@ -8,8 +8,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Source struct {
|
type Source struct {
|
||||||
env env.Env
|
env env.Env
|
||||||
warner Warner
|
warner Warner
|
||||||
|
handleDeprecatedKey func(deprecatedKey, newKey string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Warner interface {
|
type Warner interface {
|
||||||
@@ -17,9 +18,16 @@ type Warner interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(warner Warner) *Source {
|
func New(warner Warner) *Source {
|
||||||
|
handleDeprecatedKey := func(deprecatedKey, newKey string) {
|
||||||
|
warner.Warn(
|
||||||
|
"You are using the old environment variable " + deprecatedKey +
|
||||||
|
", please consider changing it to " + newKey)
|
||||||
|
}
|
||||||
|
|
||||||
return &Source{
|
return &Source{
|
||||||
env: *env.New(os.Environ()),
|
env: *env.New(os.Environ(), handleDeprecatedKey),
|
||||||
warner: warner,
|
warner: warner,
|
||||||
|
handleDeprecatedKey: handleDeprecatedKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,30 +101,3 @@ func (s *Source) Read() (settings settings.Settings, err error) {
|
|||||||
|
|
||||||
return settings, nil
|
return settings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) onRetroActive(oldKey, newKey string) {
|
|
||||||
s.warner.Warn(
|
|
||||||
"You are using the old environment variable " + oldKey +
|
|
||||||
", please consider changing it to " + newKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getEnvWithRetro returns the first set environment variable
|
|
||||||
// key and corresponding value from the environment
|
|
||||||
// variable keys given. It first goes through the retroKeys
|
|
||||||
// and end on returning the value corresponding to the currentKey.
|
|
||||||
// Note retroKeys should be in order from oldest to most
|
|
||||||
// recent retro-compatibility key.
|
|
||||||
func (s *Source) getEnvWithRetro(currentKey string,
|
|
||||||
retroKeys []string, options ...env.Option) (key string, value *string) {
|
|
||||||
// We check retro-compatibility keys first since
|
|
||||||
// the current key might be set in the Dockerfile.
|
|
||||||
for _, key = range retroKeys {
|
|
||||||
value = s.env.Get(key, options...)
|
|
||||||
if value != nil {
|
|
||||||
s.onRetroActive(key, currentKey)
|
|
||||||
return key, value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentKey, s.env.Get(currentKey, options...)
|
|
||||||
}
|
|
||||||
|
|||||||
19
internal/configuration/sources/env/server.go
vendored
19
internal/configuration/sources/env/server.go
vendored
@@ -16,17 +16,16 @@ func (s *Source) readControlServer() (controlServer settings.ControlServer, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readControlServerAddress() (address *string) {
|
func (s *Source) readControlServerAddress() (address *string) {
|
||||||
key, value := s.getEnvWithRetro("HTTP_CONTROL_SERVER_ADDRESS",
|
const currentKey = "HTTP_CONTROL_SERVER_ADDRESS"
|
||||||
[]string{"CONTROL_SERVER_ADDRESS"})
|
key := firstKeySet(s.env, "CONTROL_SERVER_ADDRESS", currentKey)
|
||||||
|
if key == currentKey {
|
||||||
|
return s.env.Get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.handleDeprecatedKey(key, currentKey)
|
||||||
|
value := s.env.Get("CONTROL_SERVER_ADDRESS")
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
return ptrTo(":" + *value)
|
||||||
if key == "HTTP_CONTROL_SERVER_ADDRESS" {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
address = new(string)
|
|
||||||
*address = ":" + *value
|
|
||||||
return address
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,72 +2,43 @@ package env
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"net/netip"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/gluetun/internal/constants/providers"
|
"github.com/qdm12/gluetun/internal/constants/providers"
|
||||||
)
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
|
|
||||||
var (
|
|
||||||
ErrServerNumberNotValid = errors.New("server number is not valid")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readServerSelection(vpnProvider, vpnType string) (
|
func (s *Source) readServerSelection(vpnProvider, vpnType string) (
|
||||||
ss settings.ServerSelection, err error) {
|
ss settings.ServerSelection, err error) {
|
||||||
ss.VPN = vpnType
|
ss.VPN = vpnType
|
||||||
|
|
||||||
ss.TargetIP, err = s.readOpenVPNTargetIP()
|
ss.TargetIP, err = s.env.NetipAddr("VPN_ENDPOINT_IP",
|
||||||
|
env.RetroKeys("OPENVPN_TARGET_IP"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ss, err
|
return ss, err
|
||||||
}
|
}
|
||||||
|
|
||||||
countriesKey, _ := s.getEnvWithRetro("SERVER_COUNTRIES", []string{"COUNTRY"})
|
ss.Countries = s.env.CSV("SERVER_COUNTRIES", env.RetroKeys("COUNTRY"))
|
||||||
ss.Countries = s.env.CSV(countriesKey)
|
|
||||||
if vpnProvider == providers.Cyberghost && len(ss.Countries) == 0 {
|
if vpnProvider == providers.Cyberghost && len(ss.Countries) == 0 {
|
||||||
// Retro-compatibility for Cyberghost using the REGION variable
|
// Retro-compatibility for Cyberghost using the REGION variable
|
||||||
ss.Countries = s.env.CSV("REGION")
|
ss.Countries = s.env.CSV("REGION")
|
||||||
if len(ss.Countries) > 0 {
|
if len(ss.Countries) > 0 {
|
||||||
s.onRetroActive("REGION", "SERVER_COUNTRIES")
|
s.handleDeprecatedKey("REGION", "SERVER_COUNTRIES")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
regionsKey, _ := s.getEnvWithRetro("SERVER_REGIONS", []string{"REGION"})
|
ss.Regions = s.env.CSV("SERVER_REGIONS", env.RetroKeys("REGION"))
|
||||||
ss.Regions = s.env.CSV(regionsKey)
|
ss.Cities = s.env.CSV("SERVER_CITIES", env.RetroKeys("CITY"))
|
||||||
|
|
||||||
citiesKey, _ := s.getEnvWithRetro("SERVER_CITIES", []string{"CITY"})
|
|
||||||
ss.Cities = s.env.CSV(citiesKey)
|
|
||||||
|
|
||||||
ss.ISPs = s.env.CSV("ISP")
|
ss.ISPs = s.env.CSV("ISP")
|
||||||
|
ss.Hostnames = s.env.CSV("SERVER_HOSTNAMES", env.RetroKeys("SERVER_HOSTNAME"))
|
||||||
hostnamesKey, _ := s.getEnvWithRetro("SERVER_HOSTNAMES", []string{"SERVER_HOSTNAME"})
|
ss.Names = s.env.CSV("SERVER_NAMES", env.RetroKeys("SERVER_NAME"))
|
||||||
ss.Hostnames = s.env.CSV(hostnamesKey)
|
ss.Numbers, err = s.env.CSVUint16("SERVER_NUMBER")
|
||||||
|
if err != nil {
|
||||||
serverNamesKey, _ := s.getEnvWithRetro("SERVER_NAMES", []string{"SERVER_NAME"})
|
return ss, err
|
||||||
ss.Names = s.env.CSV(serverNamesKey)
|
|
||||||
|
|
||||||
if csv := s.env.Get("SERVER_NUMBER"); csv != nil {
|
|
||||||
numbersStrings := strings.Split(*csv, ",")
|
|
||||||
numbers := make([]uint16, len(numbersStrings))
|
|
||||||
for i, numberString := range numbersStrings {
|
|
||||||
const base, bitSize = 10, 16
|
|
||||||
number, err := strconv.ParseInt(numberString, base, bitSize)
|
|
||||||
if err != nil {
|
|
||||||
return ss, fmt.Errorf("%w: %s",
|
|
||||||
ErrServerNumberNotValid, numberString)
|
|
||||||
} else if number < 0 || number > 65535 {
|
|
||||||
return ss, fmt.Errorf("%w: %d must be between 0 and 65535",
|
|
||||||
ErrServerNumberNotValid, number)
|
|
||||||
}
|
|
||||||
numbers[i] = uint16(number)
|
|
||||||
}
|
|
||||||
ss.Numbers = numbers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mullvad only
|
// Mullvad only
|
||||||
ss.OwnedOnly, err = s.readOwnedOnly()
|
ss.OwnedOnly, err = s.env.BoolPtr("OWNED_ONLY", env.RetroKeys("OWNED"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ss, err
|
return ss, err
|
||||||
}
|
}
|
||||||
@@ -112,22 +83,3 @@ func (s *Source) readServerSelection(vpnProvider, vpnType string) (
|
|||||||
var (
|
var (
|
||||||
ErrInvalidIP = errors.New("invalid IP address")
|
ErrInvalidIP = errors.New("invalid IP address")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readOpenVPNTargetIP() (ip netip.Addr, err error) {
|
|
||||||
envKey, value := s.getEnvWithRetro("VPN_ENDPOINT_IP", []string{"OPENVPN_TARGET_IP"})
|
|
||||||
if value == nil {
|
|
||||||
return ip, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ip, err = netip.ParseAddr(*value)
|
|
||||||
if err != nil {
|
|
||||||
return ip, fmt.Errorf("environment variable %s: %w", envKey, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ip, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Source) readOwnedOnly() (ownedOnly *bool, err error) {
|
|
||||||
envKey, _ := s.getEnvWithRetro("OWNED_ONLY", []string{"OWNED"})
|
|
||||||
return s.env.BoolPtr(envKey)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/gosettings/sources/env"
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
)
|
)
|
||||||
@@ -11,35 +13,30 @@ func (s *Source) readShadowsocks() (shadowsocks settings.Shadowsocks, err error)
|
|||||||
return shadowsocks, err
|
return shadowsocks, err
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowsocks.Address = s.readShadowsocksAddress()
|
shadowsocks.Address, err = s.readShadowsocksAddress()
|
||||||
|
if err != nil {
|
||||||
|
return shadowsocks, err
|
||||||
|
}
|
||||||
shadowsocks.LogAddresses, err = s.env.BoolPtr("SHADOWSOCKS_LOG")
|
shadowsocks.LogAddresses, err = s.env.BoolPtr("SHADOWSOCKS_LOG")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return shadowsocks, err
|
return shadowsocks, err
|
||||||
}
|
}
|
||||||
shadowsocks.CipherName = s.readShadowsocksCipher()
|
shadowsocks.CipherName = s.env.String("SHADOWSOCKS_CIPHER",
|
||||||
|
env.RetroKeys("SHADOWSOCKS_METHOD"))
|
||||||
shadowsocks.Password = s.env.Get("SHADOWSOCKS_PASSWORD", env.ForceLowercase(false))
|
shadowsocks.Password = s.env.Get("SHADOWSOCKS_PASSWORD", env.ForceLowercase(false))
|
||||||
|
|
||||||
return shadowsocks, nil
|
return shadowsocks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readShadowsocksAddress() (address *string) {
|
func (s *Source) readShadowsocksAddress() (address *string, err error) {
|
||||||
key, value := s.getEnvWithRetro("SHADOWSOCKS_LISTENING_ADDRESS",
|
const currentKey = "SHADOWSOCKS_LISTENING_ADDRESS"
|
||||||
[]string{"SHADOWSOCKS_PORT"})
|
port, err := s.env.Uint16Ptr("SHADOWSOCKS_PORT") // retro-compatibility
|
||||||
if value == nil {
|
if err != nil {
|
||||||
return nil
|
return nil, err
|
||||||
|
} else if port != nil {
|
||||||
|
s.handleDeprecatedKey("SHADOWSOCKS_PORT", currentKey)
|
||||||
|
return ptrTo(fmt.Sprintf(":%d", *port)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if key == "SHADOWSOCKS_LISTENING_ADDRESS" {
|
return s.env.Get(currentKey), nil
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retro-compatibility
|
|
||||||
*value = ":" + *value
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Source) readShadowsocksCipher() (cipher string) {
|
|
||||||
envKey, _ := s.getEnvWithRetro("SHADOWSOCKS_CIPHER",
|
|
||||||
[]string{"SHADOWSOCKS_METHOD"})
|
|
||||||
return s.env.String(envKey)
|
|
||||||
}
|
}
|
||||||
|
|||||||
40
internal/configuration/sources/env/system.go
vendored
40
internal/configuration/sources/env/system.go
vendored
@@ -1,26 +1,17 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
)
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
|
|
||||||
var (
|
|
||||||
ErrSystemPUIDNotValid = errors.New("PUID is not valid")
|
|
||||||
ErrSystemPGIDNotValid = errors.New("PGID is not valid")
|
|
||||||
ErrSystemTimezoneNotValid = errors.New("timezone is not valid")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readSystem() (system settings.System, err error) {
|
func (s *Source) readSystem() (system settings.System, err error) {
|
||||||
system.PUID, err = s.readID("PUID", "UID")
|
system.PUID, err = s.env.Uint32Ptr("PUID", env.RetroKeys("UID"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return system, err
|
return system, err
|
||||||
}
|
}
|
||||||
|
|
||||||
system.PGID, err = s.readID("PGID", "GID")
|
system.PGID, err = s.env.Uint32Ptr("PGID", env.RetroKeys("GID"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return system, err
|
return system, err
|
||||||
}
|
}
|
||||||
@@ -29,28 +20,3 @@ func (s *Source) readSystem() (system settings.System, err error) {
|
|||||||
|
|
||||||
return system, nil
|
return system, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrSystemIDNotValid = errors.New("system ID is not valid")
|
|
||||||
|
|
||||||
func (s *Source) readID(key, retroKey string) (
|
|
||||||
id *uint32, err error) {
|
|
||||||
idEnvKey, idStringPtr := s.getEnvWithRetro(key, []string{retroKey})
|
|
||||||
if idStringPtr == nil {
|
|
||||||
return nil, nil //nolint:nilnil
|
|
||||||
}
|
|
||||||
idString := *idStringPtr
|
|
||||||
|
|
||||||
const base = 10
|
|
||||||
const bitSize = 64
|
|
||||||
const max = uint64(^uint32(0))
|
|
||||||
idUint64, err := strconv.ParseUint(idString, base, bitSize)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("environment variable %s: %w: %s",
|
|
||||||
idEnvKey, ErrSystemIDNotValid, err)
|
|
||||||
} else if idUint64 > max {
|
|
||||||
return nil, fmt.Errorf("environment variable %s: %w: %d: must be between 0 and %d",
|
|
||||||
idEnvKey, ErrSystemIDNotValid, idUint64, max)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptrTo(uint32(idUint64)), nil
|
|
||||||
}
|
|
||||||
|
|||||||
105
internal/configuration/sources/env/system_test.go
vendored
105
internal/configuration/sources/env/system_test.go
vendored
@@ -1,105 +0,0 @@
|
|||||||
package env
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/qdm12/gosettings/sources/env"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Reader_readID(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
testCases := map[string]struct {
|
|
||||||
source Source
|
|
||||||
key string
|
|
||||||
retroKey string
|
|
||||||
id *uint32
|
|
||||||
errWrapped error
|
|
||||||
errMessage string
|
|
||||||
}{
|
|
||||||
"empty string": {
|
|
||||||
source: Source{
|
|
||||||
env: *env.New([]string{
|
|
||||||
"ID=",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
key: "ID",
|
|
||||||
retroKey: "RETRO_ID",
|
|
||||||
},
|
|
||||||
"invalid string": {
|
|
||||||
source: Source{
|
|
||||||
env: *env.New([]string{
|
|
||||||
"ID=invalid",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
key: "ID",
|
|
||||||
retroKey: "RETRO_ID",
|
|
||||||
errWrapped: ErrSystemIDNotValid,
|
|
||||||
errMessage: `environment variable ID: ` +
|
|
||||||
`system ID is not valid: ` +
|
|
||||||
`strconv.ParseUint: parsing "invalid": invalid syntax`,
|
|
||||||
},
|
|
||||||
"negative number": {
|
|
||||||
source: Source{
|
|
||||||
env: *env.New([]string{
|
|
||||||
"ID=-1",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
key: "ID",
|
|
||||||
retroKey: "RETRO_ID",
|
|
||||||
errWrapped: ErrSystemIDNotValid,
|
|
||||||
errMessage: `environment variable ID: ` +
|
|
||||||
`system ID is not valid: ` +
|
|
||||||
`strconv.ParseUint: parsing "-1": invalid syntax`,
|
|
||||||
},
|
|
||||||
"id 1000": {
|
|
||||||
source: Source{
|
|
||||||
env: *env.New([]string{
|
|
||||||
"ID=1000",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
key: "ID",
|
|
||||||
retroKey: "RETRO_ID",
|
|
||||||
id: ptrTo(uint32(1000)),
|
|
||||||
},
|
|
||||||
"max id": {
|
|
||||||
source: Source{
|
|
||||||
env: *env.New([]string{
|
|
||||||
"ID=4294967295",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
key: "ID",
|
|
||||||
retroKey: "RETRO_ID",
|
|
||||||
id: ptrTo(uint32(4294967295)),
|
|
||||||
},
|
|
||||||
"above max id": {
|
|
||||||
source: Source{
|
|
||||||
env: *env.New([]string{
|
|
||||||
"ID=4294967296",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
key: "ID",
|
|
||||||
retroKey: "RETRO_ID",
|
|
||||||
errWrapped: ErrSystemIDNotValid,
|
|
||||||
errMessage: `environment variable ID: ` +
|
|
||||||
`system ID is not valid: 4294967296: must be between 0 and 4294967295`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, testCase := range testCases {
|
|
||||||
testCase := testCase
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
id, err := testCase.source.readID(testCase.key, testCase.retroKey)
|
|
||||||
|
|
||||||
assert.ErrorIs(t, err, testCase.errWrapped)
|
|
||||||
if err != nil {
|
|
||||||
assert.EqualError(t, err, testCase.errMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, testCase.id, id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
32
internal/configuration/sources/env/wireguard.go
vendored
32
internal/configuration/sources/env/wireguard.go
vendored
@@ -1,10 +1,6 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/netip"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/gosettings/sources/env"
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
)
|
)
|
||||||
@@ -15,11 +11,11 @@ func (s *Source) readWireguard() (wireguard settings.Wireguard, err error) {
|
|||||||
}()
|
}()
|
||||||
wireguard.PrivateKey = s.env.Get("WIREGUARD_PRIVATE_KEY", env.ForceLowercase(false))
|
wireguard.PrivateKey = s.env.Get("WIREGUARD_PRIVATE_KEY", env.ForceLowercase(false))
|
||||||
wireguard.PreSharedKey = s.env.Get("WIREGUARD_PRESHARED_KEY", env.ForceLowercase(false))
|
wireguard.PreSharedKey = s.env.Get("WIREGUARD_PRESHARED_KEY", env.ForceLowercase(false))
|
||||||
envKey, _ := s.getEnvWithRetro("VPN_INTERFACE",
|
wireguard.Interface = s.env.String("VPN_INTERFACE",
|
||||||
[]string{"WIREGUARD_INTERFACE"}, env.ForceLowercase(false))
|
env.RetroKeys("WIREGUARD_INTERFACE"), env.ForceLowercase(false))
|
||||||
wireguard.Interface = s.env.String(envKey)
|
|
||||||
wireguard.Implementation = s.env.String("WIREGUARD_IMPLEMENTATION")
|
wireguard.Implementation = s.env.String("WIREGUARD_IMPLEMENTATION")
|
||||||
wireguard.Addresses, err = s.readWireguardAddresses()
|
wireguard.Addresses, err = s.env.CSVNetipPrefixes("WIREGUARD_ADDRESSES",
|
||||||
|
env.RetroKeys("WIREGUARD_ADDRESS"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wireguard, err // already wrapped
|
return wireguard, err // already wrapped
|
||||||
}
|
}
|
||||||
@@ -31,23 +27,3 @@ func (s *Source) readWireguard() (wireguard settings.Wireguard, err error) {
|
|||||||
}
|
}
|
||||||
return wireguard, nil
|
return wireguard, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readWireguardAddresses() (addresses []netip.Prefix, err error) {
|
|
||||||
key, value := s.getEnvWithRetro("WIREGUARD_ADDRESSES",
|
|
||||||
[]string{"WIREGUARD_ADDRESS"})
|
|
||||||
if value == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
addressStrings := strings.Split(*value, ",")
|
|
||||||
addresses = make([]netip.Prefix, len(addressStrings))
|
|
||||||
for i, addressString := range addressStrings {
|
|
||||||
addressString = strings.TrimSpace(addressString)
|
|
||||||
addresses[i], err = netip.ParsePrefix(addressString)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("environment variable %s: %w", key, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return addresses, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/netip"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/gosettings/sources/env"
|
"github.com/qdm12/gosettings/sources/env"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readWireguardSelection() (
|
func (s *Source) readWireguardSelection() (
|
||||||
selection settings.WireguardSelection, err error) {
|
selection settings.WireguardSelection, err error) {
|
||||||
selection.EndpointIP, err = s.readWireguardEndpointIP()
|
selection.EndpointIP, err = s.env.NetipAddr("VPN_ENDPOINT_IP", env.RetroKeys("WIREGUARD_ENDPOINT_IP"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return selection, err
|
return selection, err
|
||||||
}
|
}
|
||||||
|
|
||||||
selection.EndpointPort, err = s.readWireguardCustomPort()
|
selection.EndpointPort, err = s.env.Uint16Ptr("VPN_ENDPOINT_PORT", env.RetroKeys("WIREGUARD_ENDPOINT_PORT"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return selection, err
|
return selection, err
|
||||||
}
|
}
|
||||||
@@ -24,22 +21,3 @@ func (s *Source) readWireguardSelection() (
|
|||||||
|
|
||||||
return selection, nil
|
return selection, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readWireguardEndpointIP() (endpointIP netip.Addr, err error) {
|
|
||||||
key, value := s.getEnvWithRetro("VPN_ENDPOINT_IP", []string{"WIREGUARD_ENDPOINT_IP"})
|
|
||||||
if value == nil {
|
|
||||||
return endpointIP, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointIP, err = netip.ParseAddr(*value)
|
|
||||||
if err != nil {
|
|
||||||
return endpointIP, fmt.Errorf("environment variable %s: %w", key, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return endpointIP, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Source) readWireguardCustomPort() (customPort *uint16, err error) {
|
|
||||||
envKey, _ := s.getEnvWithRetro("VPN_ENDPOINT_PORT", []string{"WIREGUARD_ENDPOINT_PORT"})
|
|
||||||
return s.env.Uint16Ptr(envKey)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func Test_readSecretFileAsStringPtr(t *testing.T) {
|
|||||||
source: func(tempDir string) Source {
|
source: func(tempDir string) Source {
|
||||||
secretFilepath := filepath.Join(tempDir, "secret_file")
|
secretFilepath := filepath.Join(tempDir, "secret_file")
|
||||||
environ := []string{"SECRET_FILE=" + secretFilepath}
|
environ := []string{"SECRET_FILE=" + secretFilepath}
|
||||||
return Source{env: *env.New(environ)}
|
return Source{env: *env.New(environ, nil)}
|
||||||
},
|
},
|
||||||
defaultSecretFileName: "default_secret_file",
|
defaultSecretFileName: "default_secret_file",
|
||||||
secretPathEnvKey: "SECRET_FILE",
|
secretPathEnvKey: "SECRET_FILE",
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ type Source struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New() *Source {
|
func New() *Source {
|
||||||
|
handleDeprecatedKey := (func(deprecatedKey, newKey string))(nil)
|
||||||
return &Source{
|
return &Source{
|
||||||
env: *env.New(os.Environ()),
|
env: *env.New(os.Environ(), handleDeprecatedKey),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user