92213090fe
Replace the (unconfirmed) iplocate API expander with a database-backed one that reads the iplocate ip-to-asn CSV (network,asn,...) proxied through the artifactapi github remote. It downloads and indexes the whole DB once (ASN -> CIDRs), serves every asn address group from the in-memory index, and rebuilds on a 24h TTL; refresh failures keep the last-good index (fail-safe). No API key needed. - Add IPLocateDB expander (zip + CSV parsing, ASN normalization). - Wire it in main (TOMSWALLAPI_IPLOCATE_DB_URL overrides the default artifactapi URL); remove the dead API client. - Unit tests: CSV indexing (incl. quoted org fields), zip extraction, missing columns, and ASN normalization.
75 lines
2.2 KiB
Go
75 lines
2.2 KiB
Go
// Package config loads tomswallapi runtime configuration from the environment.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"os"
|
|
)
|
|
|
|
// Config holds all runtime configuration, sourced from environment variables.
|
|
type Config struct {
|
|
ListenAddr string
|
|
|
|
DBHost string
|
|
DBPort string
|
|
DBUser string
|
|
DBPassword string
|
|
DBName string
|
|
DBSSLMode string
|
|
|
|
// WriteToken guards all mutating API endpoints (used by the Terraform provider).
|
|
WriteToken string
|
|
// AgentToken guards the per-device config endpoint (used by tomswall agents).
|
|
AgentToken string
|
|
|
|
// IPLocateAPIKey is used to expand ASN address groups into prefixes via the
|
|
// iplocate API (legacy path). The DB expander below is preferred.
|
|
IPLocateAPIKey string
|
|
// IPLocateDBURL points at the iplocate ip-to-asn CSV database (proxied via
|
|
// artifactapi). Empty uses the built-in default.
|
|
IPLocateDBURL string
|
|
}
|
|
|
|
// Load reads configuration from the environment, applying defaults.
|
|
func Load() (*Config, error) {
|
|
c := &Config{
|
|
ListenAddr: env("TOMSWALLAPI_LISTEN_ADDR", ":8000"),
|
|
DBHost: env("TOMSWALLAPI_DB_HOST", "localhost"),
|
|
DBPort: env("TOMSWALLAPI_DB_PORT", "5432"),
|
|
DBUser: env("TOMSWALLAPI_DB_USER", "tomswallapi"),
|
|
DBPassword: os.Getenv("TOMSWALLAPI_DB_PASSWORD"),
|
|
DBName: env("TOMSWALLAPI_DB_NAME", "tomswallapi"),
|
|
DBSSLMode: env("TOMSWALLAPI_DB_SSLMODE", "disable"),
|
|
WriteToken: os.Getenv("TOMSWALLAPI_WRITE_TOKEN"),
|
|
AgentToken: os.Getenv("TOMSWALLAPI_AGENT_TOKEN"),
|
|
IPLocateAPIKey: os.Getenv("TOMSWALLAPI_IPLOCATE_API_KEY"),
|
|
IPLocateDBURL: os.Getenv("TOMSWALLAPI_IPLOCATE_DB_URL"),
|
|
}
|
|
if c.DBName == "" {
|
|
return nil, fmt.Errorf("TOMSWALLAPI_DB_NAME must not be empty")
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
// DatabaseDSN builds a libpq-style connection string.
|
|
func (c *Config) DatabaseDSN() string {
|
|
u := url.URL{
|
|
Scheme: "postgres",
|
|
User: url.UserPassword(c.DBUser, c.DBPassword),
|
|
Host: fmt.Sprintf("%s:%s", c.DBHost, c.DBPort),
|
|
Path: c.DBName,
|
|
}
|
|
q := u.Query()
|
|
q.Set("sslmode", c.DBSSLMode)
|
|
u.RawQuery = q.Encode()
|
|
return u.String()
|
|
}
|
|
|
|
func env(key, def string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return def
|
|
}
|