Files
br ca6cdcca63 software steht so weit.
jetzt build + docker build und testen
2026-10-02 13:25:34 +02:00

79 lines
2.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package stream
import (
"crypto/ed25519"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
)
var (
// ErrUnsigned: Das Event trägt keine Signatur.
ErrUnsigned = errors.New("stream: Event nicht signiert")
// ErrBadSignature: Die Signatur passt nicht (fremder Schlüssel oder verändertes Event).
ErrBadSignature = errors.New("stream: Event-Signatur ungültig")
)
const eventSignatureVersion = "SULTAN-EVENT-V1\n"
func eventMessage(ev Event) []byte {
ev.Signature = ""
b, _ := json.Marshal(ev)
return append([]byte(eventSignatureVersion), b...)
}
// SignEvent signiert ev (alle Felder außer der Signatur) mit dem Master-Key.
func SignEvent(ev Event, key ed25519.PrivateKey) Event {
ev.Signature = base64.StdEncoding.EncodeToString(ed25519.Sign(key, eventMessage(ev)))
return ev
}
// VerifyEvent prüft die Signatur mit dem Public Key des Master-Keys.
func VerifyEvent(ev Event, pub ed25519.PublicKey) error {
if ev.Signature == "" {
return ErrUnsigned
}
sig, err := base64.StdEncoding.DecodeString(ev.Signature)
if err != nil || len(sig) != ed25519.SignatureSize || len(pub) != ed25519.PublicKeySize {
return ErrBadSignature
}
if !ed25519.Verify(pub, eventMessage(ev), sig) {
return ErrBadSignature
}
return nil
}
// Befehle in node_command – eine feste Liste, keine beliebigen Kommandos.
const (
CmdResync = "resync" // Agent sendet sofort seinen Zustand
CmdRotateKey = "rotate_key" // Agent erzeugt einen neuen node.key
CmdDrain = "drain" // Hinweis: Routen entfernt
CmdMaintenance = "maintenance" // Hinweis: Wartung angemeldet
CmdResume = "resume" // Hinweis: Wartung/drain beendet
CmdConfig = "config" // Server-Adressen (ServerURLs) für den Ausweichweg
)
// Commands sind alle bekannten Befehle.
var Commands = []string{CmdResync, CmdRotateKey, CmdDrain, CmdMaintenance, CmdResume, CmdConfig}
// NodeCommand ist die Payload eines node_command-Events.
type NodeCommand struct {
Command string `json:"command"`
Reason string `json:"reason,omitempty"`
// ServerURLs: bei config die Adressen, unter denen der Server erreichbar ist.
ServerURLs []string `json:"server_urls,omitempty"`
}
// ParseNodeCommand liest die Payload eines node_command-Events.
func ParseNodeCommand(ev Event) (NodeCommand, error) {
if ev.Type != EventNodeCommand {
return NodeCommand{}, fmt.Errorf("%w: kein node_command", ErrInvalidEvent)
}
var c NodeCommand
if err := json.Unmarshal(ev.Payload, &c); err != nil || c.Command == "" {
return NodeCommand{}, fmt.Errorf("%w: Befehl fehlt", ErrInvalidEvent)
}
return c, nil
}