Accountant: Inventar, where, Checkmk, Abrechnung
This commit is contained in:
1 parent
9f16148cde
commit
dd93277750
59 files changed
+7522
-113
No files matched your search
+48
-2
@@ -32,6 +32,7 @@ import (
|
||||
"sultan/pkg/lander"
|
||||
"sultan/pkg/notify"
|
||||
"sultan/pkg/policy"
|
||||
"sultan/pkg/ratelimit"
|
||||
"sultan/pkg/registry"
|
||||
"sultan/pkg/store"
|
||||
"sultan/pkg/stream"
|
||||
@@ -67,6 +68,16 @@ type Config struct {
|
||||
// -1 = unbegrenzt) – gegen das Durchprobieren von Einladungen.
|
||||
EnrollLimit int
|
||||
|
||||
// Accountant (Spec 5.3): Einladung (nur beim ersten Start) bzw.
|
||||
// Adress-Override; ohne beides und ohne accountant.json meldet der
|
||||
// Server nichts. Interval: Prüfen auf Änderungen (Default 10s),
|
||||
// Heartbeat: Lebenszeichen ohne Änderung (Default 1h).
|
||||
AccountantToken string
|
||||
AccountantURL string
|
||||
AccountantInterval time.Duration
|
||||
AccountantHeartbeat time.Duration
|
||||
Version string // für den Bericht (sultan version)
|
||||
|
||||
interceptorDerived bool // InterceptorURL folgt der gebundenen Lander-Adresse
|
||||
}
|
||||
|
||||
@@ -99,6 +110,12 @@ func (c Config) withDefaults() Config {
|
||||
if c.EnrollLimit == 0 {
|
||||
c.EnrollLimit = 10
|
||||
}
|
||||
if c.AccountantInterval <= 0 {
|
||||
c.AccountantInterval = 10 * time.Second
|
||||
}
|
||||
if c.AccountantHeartbeat <= 0 {
|
||||
c.AccountantHeartbeat = time.Hour
|
||||
}
|
||||
if c.Logger == nil {
|
||||
c.Logger = slog.New(slog.NewTextHandler(os.Stderr, nil))
|
||||
}
|
||||
@@ -141,7 +158,8 @@ type Server struct {
|
||||
registry *registry.Registry
|
||||
lander *lander.Lander
|
||||
notifier notify.Target // nil = keine Benachrichtigungen
|
||||
enrollRL *rateLimiter
|
||||
enrollRL *ratelimit.Limiter
|
||||
payee *payee // nil = meldet nicht an einen Accountant
|
||||
|
||||
vmu sync.Mutex
|
||||
violations []time.Time // Zeitpunkte der Policy-Verstöße (für Checkmk)
|
||||
@@ -151,6 +169,7 @@ type Server struct {
|
||||
providerAddr string
|
||||
landerAddr string
|
||||
agentSrv *http.Server
|
||||
payeeRunning bool
|
||||
providerSrv *http.Server
|
||||
landerSrv *http.Server
|
||||
serveErr chan error
|
||||
@@ -199,6 +218,11 @@ func New(ctx context.Context, cfg Config) (*Server, error) {
|
||||
st.Close()
|
||||
return nil, err
|
||||
}
|
||||
pay, err := newPayee(cfg, cfg.Logger)
|
||||
if err != nil {
|
||||
st.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := &Server{
|
||||
cfg: cfg,
|
||||
@@ -209,9 +233,13 @@ func New(ctx context.Context, cfg Config) (*Server, error) {
|
||||
verifier: &auth.Verifier{Directory: st},
|
||||
serveErr: make(chan error, 3),
|
||||
stopRefresh: make(chan struct{}),
|
||||
payee: pay,
|
||||
}
|
||||
if pay != nil {
|
||||
pay.s = s
|
||||
}
|
||||
s.hub = &stream.Hub{OnConnect: s.nodeOnline, OnDisconnect: s.nodeOffline, SigningKey: master}
|
||||
s.enrollRL = &rateLimiter{limit: cfg.EnrollLimit, window: time.Minute}
|
||||
s.enrollRL = &ratelimit.Limiter{Limit: cfg.EnrollLimit, Window: time.Minute}
|
||||
s.notifier = cfg.Notify
|
||||
if s.notifier == nil {
|
||||
var targets notify.Multi
|
||||
@@ -260,6 +288,12 @@ func loadOrCreateMasterKey(path string) (ed25519.PrivateKey, error) {
|
||||
// Fingerprint ist der Fingerprint des TLS-Zertifikats (für Enrollment-Tokens).
|
||||
func (s *Server) Fingerprint() crypto.Fingerprint { return s.cert.Fingerprint }
|
||||
|
||||
// NodeState liefert den zuletzt gemeldeten Zustand eines verbundenen
|
||||
// Knotens (Kopie, inkl. Zusatzdaten für das Inventar).
|
||||
func (s *Server) NodeState(nodeID string) (registry.NodeState, bool) {
|
||||
return s.registry.State(nodeID)
|
||||
}
|
||||
|
||||
// MasterPublicKey ist der Schlüssel, mit dem Lizenzen geprüft werden.
|
||||
func (s *Server) MasterPublicKey() ed25519.PublicKey {
|
||||
return s.master.Public().(ed25519.PublicKey)
|
||||
@@ -338,6 +372,12 @@ func (s *Server) Start() error {
|
||||
go s.serve(func() error { return landerSrv.Serve(landerLn) })
|
||||
}
|
||||
go s.refreshLoop()
|
||||
if s.payee != nil {
|
||||
s.mu.Lock()
|
||||
s.payeeRunning = true
|
||||
s.mu.Unlock()
|
||||
go s.payee.run()
|
||||
}
|
||||
|
||||
s.log.Info("Sultan-Server gestartet",
|
||||
"agent", s.AgentAddr(), "provider", s.ProviderAddr(), "lander", s.LanderAddr(),
|
||||
@@ -405,6 +445,12 @@ func (s *Server) Shutdown(ctx context.Context) error {
|
||||
errs = append(errs, srv.Shutdown(ctx))
|
||||
}
|
||||
}
|
||||
s.mu.Lock()
|
||||
payeeRunning := s.payeeRunning
|
||||
s.mu.Unlock()
|
||||
if payeeRunning {
|
||||
s.payee.shutdown() // vor dem Schließen der Datenbank
|
||||
}
|
||||
errs = append(errs, s.store.Close())
|
||||
s.shutdownErr = errors.Join(errs...)
|
||||
s.log.Info("Sultan-Server beendet")
|
||||
|
||||
Reference in new issue
Block a user