Files
tomswallapi/cmd/tomswallapi/main.go
T
benvin 92213090fe
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Expand ASN groups from the iplocate ip-to-asn database
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.
2026-07-21 22:36:19 +10:00

79 lines
2.2 KiB
Go

// Command tomswallapi is the fleet control-plane HTTP server for tomswall.
//
// It stores the fleet-global model (zones, address groups, portgroups, policies,
// rules, fabrics) and the per-device layer (devices, zone->interface bindings),
// compiles intents into per-device tomswall configs, and serves those configs to
// tomswall agents. The read/write API backs a Terraform provider and the agents.
package main
import (
"context"
"log/slog"
"os"
"os/signal"
"syscall"
"git.unkin.net/unkin/tomswallapi/internal/asnexpand"
"git.unkin.net/unkin/tomswallapi/internal/config"
"git.unkin.net/unkin/tomswallapi/internal/database"
"git.unkin.net/unkin/tomswallapi/internal/server"
"git.unkin.net/unkin/tomswallapi/internal/store"
)
var version = "dev"
func main() {
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil)))
slog.Info("starting tomswallapi", "version", version)
cfg, err := config.Load()
if err != nil {
slog.Error("load config", "err", err)
os.Exit(1)
}
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
db, err := database.New(ctx, cfg.DatabaseDSN())
if err != nil {
slog.Error("connect database", "err", err)
os.Exit(1)
}
defer db.Close()
if err := db.Migrate(ctx); err != nil {
slog.Error("migrate database", "err", err)
os.Exit(1)
}
if cfg.WriteToken == "" {
slog.Warn("TOMSWALLAPI_WRITE_TOKEN is not set; write endpoints are disabled")
}
if cfg.AgentToken == "" {
slog.Warn("TOMSWALLAPI_AGENT_TOKEN is not set; agent config endpoint is disabled")
}
// Start the central ASN expander, which reads the iplocate ip-to-asn database
// (proxied via artifactapi) and expands asn address groups into prefixes.
expander := asnexpand.NewIPLocateDB(cfg.IPLocateDBURL)
refresher := &asnexpand.Refresher{
Store: store.New(db.Pool),
Expander: expander,
}
go refresher.Run(ctx)
slog.Info("started ASN expander", "source", "iplocate-db", "url", expander.URL)
srv := server.New(server.Options{
DB: db,
WriteToken: cfg.WriteToken,
AgentToken: cfg.AgentToken,
Version: version,
})
if err := srv.ListenAndServe(ctx, cfg.ListenAddr); err != nil {
slog.Error("server", "err", err)
os.Exit(1)
}
}