CI / changes (push) Successful in 12s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 25s
CI / web (push) Successful in 46s
CI / go (push) Successful in 1m15s
CI / bird2 (push) Successful in 18s
CI / release (push) Successful in 3m59s
Introduced a comprehensive firewall blocklist feature, allowing for the management of firewall clients and their associated rules. This includes endpoints for enrolling clients, listing clients and rules, and reporting apply statuses. Enhanced the API to support firewall operations, including the ability to handle block/accept policies. Updated the documentation to reflect these changes and added necessary components in the web UI for better user interaction. Additionally, modified the agent server to support firewall failover and integrated firewall functionality into the existing architecture.
149 lines
4.4 KiB
Go
149 lines
4.4 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"context"
|
|
"crypto/ed25519"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"errors"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"evobgp/internal/jobs"
|
|
"evobgp/internal/maintenance"
|
|
"evobgp/internal/pgmonitor"
|
|
"evobgp/internal/runtimelogs"
|
|
"evobgp/internal/store"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
// Server implements EvoBGP control-plane HTTP API.
|
|
type Server struct {
|
|
store store.Backend
|
|
pgPool *pgxpool.Pool
|
|
pgMonitor *pgmonitor.Service
|
|
maintConfig *maintenance.ConfigProvider
|
|
maintStats *maintenance.DBStatsProvider
|
|
jobs *jobs.Registry
|
|
bundlePriv ed25519.PrivateKey
|
|
keyResolver *apiKeyResolver
|
|
firewallResolver *firewallTokenResolver
|
|
bundleSeedHex string
|
|
corsOrigins []string
|
|
cdnHTTP *http.Client
|
|
runtimeLogs *runtimelogs.Service
|
|
runtimeLogsPolicyTenant string
|
|
mux *http.ServeMux
|
|
}
|
|
|
|
// Options configures the API server.
|
|
type Options struct {
|
|
APIKeys string
|
|
// DatabaseURL enables PostgreSQL-backed store (migrations applied on connect).
|
|
DatabaseURL string
|
|
InsecureDev bool
|
|
SeedDemo bool
|
|
BundleSeedHex string
|
|
CORSAllowedOrigins string
|
|
// RuntimeLogsPolicyTenant overrides tenant for auto-cleanup scheduler settings (optional).
|
|
RuntimeLogsPolicyTenant string
|
|
}
|
|
|
|
// New constructs Server and wiring for async jobs.
|
|
func New(opts Options) (*Server, error) {
|
|
backend, reg, pool, err := BootstrapWorkers(context.Background(), opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var priv ed25519.PrivateKey
|
|
if strings.TrimSpace(opts.BundleSeedHex) != "" {
|
|
seed, err := hex.DecodeString(strings.TrimSpace(opts.BundleSeedHex))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(seed) != ed25519.SeedSize {
|
|
return nil, errors.New("httpapi: BundleSeedHex must decode to 32 bytes")
|
|
}
|
|
priv = ed25519.NewKeyFromSeed(seed)
|
|
} else {
|
|
_, priv, _ = ed25519.GenerateKey(rand.Reader)
|
|
}
|
|
|
|
resolver, err := newAPIKeyResolver(opts.APIKeys, backend)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fwResolver, err := newFirewallTokenResolver(backend)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pgMon *pgmonitor.Service
|
|
var maintCfg *maintenance.ConfigProvider
|
|
var maintStats *maintenance.DBStatsProvider
|
|
if pool != nil {
|
|
pgMon = pgmonitor.NewService(pool)
|
|
maintCfg = maintenance.NewConfigProvider(backend)
|
|
_ = maintCfg.Reload(context.Background())
|
|
maintStats = maintenance.NewDBStatsProvider(pgMon)
|
|
}
|
|
s := &Server{
|
|
store: backend,
|
|
pgPool: pool,
|
|
pgMonitor: pgMon,
|
|
maintConfig: maintCfg,
|
|
maintStats: maintStats,
|
|
jobs: reg,
|
|
bundlePriv: priv,
|
|
keyResolver: resolver,
|
|
firewallResolver: fwResolver,
|
|
bundleSeedHex: strings.TrimSpace(opts.BundleSeedHex),
|
|
corsOrigins: parseCORSOrigins(opts.CORSAllowedOrigins),
|
|
cdnHTTP: NewCDNHTTPClient(),
|
|
runtimeLogs: runtimelogs.NewService(runtimelogs.ConfigFromEnv()),
|
|
runtimeLogsPolicyTenant: strings.TrimSpace(opts.RuntimeLogsPolicyTenant),
|
|
}
|
|
s.mux = http.NewServeMux()
|
|
s.registerRoutes()
|
|
return s, nil
|
|
}
|
|
|
|
// Close releases database resources.
|
|
func (s *Server) Close() {
|
|
if s.pgPool != nil {
|
|
s.pgPool.Close()
|
|
}
|
|
}
|
|
|
|
// Store exposes the backing store (for operators / tests).
|
|
func (s *Server) Store() store.Backend { return s.store }
|
|
|
|
// Jobs exposes the in-process async job registry (for scheduler / evobgp-all).
|
|
func (s *Server) Jobs() *jobs.Registry { return s.jobs }
|
|
|
|
// StartBackground starts PostgreSQL monitoring and maintenance schedulers until ctx is cancelled.
|
|
func (s *Server) StartBackground(ctx context.Context) {
|
|
if s != nil && s.pgPool != nil {
|
|
pgmonitor.StartScheduler(ctx, s.pgPool)
|
|
}
|
|
if s != nil && s.maintConfig != nil && s.jobs != nil {
|
|
maintenance.StartScheduler(ctx, s.maintConfig, func(policyID string, dryRun bool, idem string) {
|
|
key := idem
|
|
_, _, _ = s.jobs.Enqueue("", jobs.KindMaintenancePolicyRun, &key, nil, map[string]any{
|
|
"policy_id": policyID,
|
|
"dry_run": dryRun,
|
|
"trigger": "scheduler",
|
|
})
|
|
}, 30*time.Second)
|
|
}
|
|
if s != nil && s.runtimeLogs != nil && s.store != nil {
|
|
runtimelogs.StartAutoCleanupScheduler(ctx, runtimelogs.SchedulerDeps{
|
|
Service: s.runtimeLogs,
|
|
Store: s.store,
|
|
PolicyTenant: s.runtimeLogsPolicyTenant,
|
|
}, 30*time.Second)
|
|
}
|
|
}
|