erste module drin.
zwischenstand: Architektur aktualisiert, TOFU implementiert,
This commit is contained in:
1 parent
9d5789c5d7
commit
c8df9d7651
41 files changed
+6455
-36
No files matched your search
@@ -0,0 +1,65 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TokenPrefix kennzeichnet Enrollment-Tokens.
|
||||
const TokenPrefix = "sltn_enroll_"
|
||||
|
||||
// ErrInvalidToken: Der Token-String hat nicht das Format
|
||||
// sltn_enroll_<secret>.<fingerprint>.
|
||||
var ErrInvalidToken = errors.New("crypto: ungültiger Enrollment-Token")
|
||||
|
||||
// EnrollmentToken ist die Einladung für einen neuen Agenten.
|
||||
//
|
||||
// Secret (inkl. Präfix) ist der geheime Teil: Der Server speichert davon nur
|
||||
// den Hash (store.AddEnrollmentToken), der Agent schickt es beim Enrollment.
|
||||
// Fingerprint ist nicht geheim; er sagt dem Agenten, welches
|
||||
// Server-Zertifikat er beim Erstkontakt erwarten muss.
|
||||
type EnrollmentToken struct {
|
||||
Secret string
|
||||
Fingerprint Fingerprint
|
||||
}
|
||||
|
||||
// String liefert die Form, die der Admin an den Agenten weitergibt.
|
||||
func (t EnrollmentToken) String() string { return t.Secret + "." + string(t.Fingerprint) }
|
||||
|
||||
// NewEnrollmentToken erzeugt einen Token mit 256 Bit Zufall für den Server
|
||||
// mit Fingerprint fp.
|
||||
func NewEnrollmentToken(fp Fingerprint) (EnrollmentToken, error) {
|
||||
if _, err := ParseFingerprint(string(fp)); err != nil {
|
||||
return EnrollmentToken{}, err
|
||||
}
|
||||
var b [32]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
return EnrollmentToken{}, err
|
||||
}
|
||||
return EnrollmentToken{Secret: TokenPrefix + base64.RawURLEncoding.EncodeToString(b[:]), Fingerprint: fp}, nil
|
||||
}
|
||||
|
||||
// ParseEnrollmentToken zerlegt einen Token-String. Leerraum am Rand (beim
|
||||
// Kopieren) wird ignoriert.
|
||||
func ParseEnrollmentToken(s string) (EnrollmentToken, error) {
|
||||
parts := strings.Split(strings.TrimSpace(s), ".")
|
||||
if len(parts) != 2 {
|
||||
return EnrollmentToken{}, fmt.Errorf("%w: erwartet %s<secret>.<fingerprint>", ErrInvalidToken, TokenPrefix)
|
||||
}
|
||||
secret, rawFP := parts[0], parts[1]
|
||||
body, ok := strings.CutPrefix(secret, TokenPrefix)
|
||||
if !ok {
|
||||
return EnrollmentToken{}, fmt.Errorf("%w: Präfix %s fehlt", ErrInvalidToken, TokenPrefix)
|
||||
}
|
||||
if b, err := base64.RawURLEncoding.DecodeString(body); err != nil || len(b) != 32 {
|
||||
return EnrollmentToken{}, fmt.Errorf("%w: Secret beschädigt", ErrInvalidToken)
|
||||
}
|
||||
fp, err := ParseFingerprint(rawFP)
|
||||
if err != nil {
|
||||
return EnrollmentToken{}, fmt.Errorf("%w: %w", ErrInvalidToken, err)
|
||||
}
|
||||
return EnrollmentToken{Secret: secret, Fingerprint: fp}, nil
|
||||
}
|
||||
Reference in new issue
Block a user