feat(publicip/ipinfo): add PUBLICIP_API_TOKEN variable

This commit is contained in:
Quentin McGaw
2024-02-13 10:55:06 +00:00
parent 72b5afc771
commit 6a6337b98f
6 changed files with 29 additions and 4 deletions

View File

@@ -190,6 +190,7 @@ ENV VPN_SERVICE_PROVIDER=pia \
# Public IP
PUBLICIP_FILE="/tmp/gluetun/ip" \
PUBLICIP_PERIOD=12h \
PUBLICIP_API_TOKEN= \
# Pprof
PPROF_ENABLED=no \
PPROF_BLOCK_PROFILE_RATE=0 \

View File

@@ -396,7 +396,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
go unboundLooper.RunRestartTicker(dnsTickerCtx, dnsTickerDone)
controlGroupHandler.Add(dnsTickerHandler)
ipFetcher := ipinfo.New(httpClient)
ipFetcher := ipinfo.New(httpClient, *allSettings.PublicIP.APIToken)
publicIPLooper := publicip.NewLoop(ipFetcher,
logger.New(log.SetComponent("ip getter")),
allSettings.PublicIP, puid, pgid)

View File

@@ -35,7 +35,7 @@ type UpdaterLogger interface {
func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) error {
options := settings.Updater{}
var endUserMode, maintainerMode, updateAll bool
var csvProviders string
var csvProviders, ipToken string
flagSet := flag.NewFlagSet("update", flag.ExitOnError)
flagSet.BoolVar(&endUserMode, "enduser", false, "Write results to /gluetun/servers.json (for end users)")
flagSet.BoolVar(&maintainerMode, "maintainer", false,
@@ -46,6 +46,7 @@ func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) e
"Minimum ratio of servers to find for the update to succeed")
flagSet.BoolVar(&updateAll, "all", false, "Update servers for all VPN providers")
flagSet.StringVar(&csvProviders, "providers", "", "CSV string of VPN providers to update server data for")
flagSet.StringVar(&ipToken, "ip-token", "", "IP data service token (e.g. ipinfo.io) to use")
if err := flagSet.Parse(args); err != nil {
return err
}
@@ -79,7 +80,7 @@ func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) e
httpClient := &http.Client{Timeout: clientTimeout}
unzipper := unzip.New(httpClient)
parallelResolver := resolver.NewParallelResolver(options.DNSAddress)
ipFetcher := ipinfo.New(httpClient)
ipFetcher := ipinfo.New(httpClient, ipToken)
openvpnFileExtractor := extract.New()
providers := provider.NewProviders(storage, time.Now, logger, httpClient,

View File

@@ -21,6 +21,11 @@ type PublicIP struct {
// to write to a file. It cannot be nil for the
// internal state
IPFilepath *string
// APIToken is the token to use for the IP data service
// such as ipinfo.io. It can be the empty string to
// indicate not to use a token. It cannot be nil for the
// internal state.
APIToken *string
}
// UpdateWith deep copies the receiving settings, overrides the copy with
@@ -58,23 +63,27 @@ func (p *PublicIP) copy() (copied PublicIP) {
return PublicIP{
Period: gosettings.CopyPointer(p.Period),
IPFilepath: gosettings.CopyPointer(p.IPFilepath),
APIToken: gosettings.CopyPointer(p.APIToken),
}
}
func (p *PublicIP) mergeWith(other PublicIP) {
p.Period = gosettings.MergeWithPointer(p.Period, other.Period)
p.IPFilepath = gosettings.MergeWithPointer(p.IPFilepath, other.IPFilepath)
p.APIToken = gosettings.MergeWithPointer(p.APIToken, other.APIToken)
}
func (p *PublicIP) overrideWith(other PublicIP) {
p.Period = gosettings.OverrideWithPointer(p.Period, other.Period)
p.IPFilepath = gosettings.OverrideWithPointer(p.IPFilepath, other.IPFilepath)
p.APIToken = gosettings.OverrideWithPointer(p.APIToken, other.APIToken)
}
func (p *PublicIP) setDefaults() {
const defaultPeriod = 12 * time.Hour
p.Period = gosettings.DefaultPointer(p.Period, defaultPeriod)
p.IPFilepath = gosettings.DefaultPointer(p.IPFilepath, "/tmp/gluetun/ip")
p.APIToken = gosettings.DefaultPointer(p.APIToken, "")
}
func (p PublicIP) String() string {
@@ -99,5 +108,9 @@ func (p PublicIP) toLinesNode() (node *gotree.Node) {
node.Appendf("IP file path: %s", *p.IPFilepath)
}
if *p.APIToken != "" {
node.Appendf("API token: %s", gosettings.ObfuscateKey(*p.APIToken))
}
return node
}

View File

@@ -14,5 +14,7 @@ func (s *Source) readPublicIP() (publicIP settings.PublicIP, err error) {
publicIP.IPFilepath = s.env.Get("PUBLICIP_FILE",
env.ForceLowercase(false), env.RetroKeys("IP_STATUS_FILE"))
publicIP.APIToken = s.env.Get("PUBLICIP_API_TOKEN")
return publicIP, nil
}

View File

@@ -14,15 +14,18 @@ import (
type Fetch struct {
client *http.Client
token string
}
func New(client *http.Client) *Fetch {
func New(client *http.Client, token string) *Fetch {
return &Fetch{
client: client,
token: token,
}
}
var (
ErrTokenNotValid = errors.New("token is not valid")
ErrTooManyRequests = errors.New("too many requests sent for this month")
ErrBadHTTPStatus = errors.New("bad HTTP status received")
)
@@ -44,6 +47,7 @@ func (f *Fetch) FetchInfo(ctx context.Context, ip netip.Addr) (
if err != nil {
return result, err
}
request.Header.Set("Authorization", "Bearer "+f.token)
response, err := f.client.Do(request)
if err != nil {
@@ -51,6 +55,10 @@ func (f *Fetch) FetchInfo(ctx context.Context, ip netip.Addr) (
}
defer response.Body.Close()
if f.token != "" && response.StatusCode == http.StatusUnauthorized {
return result, fmt.Errorf("%w: %s", ErrTokenNotValid, response.Status)
}
switch response.StatusCode {
case http.StatusOK:
case http.StatusTooManyRequests, http.StatusForbidden: