Refactor RDP proxy handling and update related tests
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package webingress
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ErrFabricEnvelopeSigningKeyInvalid = errors.New("web ingress fabric envelope signing key invalid")
|
||||
|
||||
type Ed25519EnvelopeSigner struct {
|
||||
PrivateKey ed25519.PrivateKey
|
||||
KeyID string
|
||||
Now func() time.Time
|
||||
}
|
||||
|
||||
func NewEd25519EnvelopeSigner(privateKeyB64, keyID string) (Ed25519EnvelopeSigner, error) {
|
||||
privateKey, err := decodeEd25519PrivateKey(privateKeyB64)
|
||||
if err != nil {
|
||||
return Ed25519EnvelopeSigner{}, err
|
||||
}
|
||||
keyID = strings.TrimSpace(keyID)
|
||||
if keyID == "" {
|
||||
publicKey, ok := privateKey.Public().(ed25519.PublicKey)
|
||||
if !ok {
|
||||
return Ed25519EnvelopeSigner{}, ErrFabricEnvelopeSigningKeyInvalid
|
||||
}
|
||||
keyID = ed25519EnvelopeKeyID(publicKey)
|
||||
}
|
||||
return Ed25519EnvelopeSigner{PrivateKey: privateKey, KeyID: keyID}, nil
|
||||
}
|
||||
|
||||
func (s Ed25519EnvelopeSigner) Sign(_ context.Context, canonical []byte) (FabricEnvelopeSignature, error) {
|
||||
if len(s.PrivateKey) != ed25519.PrivateKeySize {
|
||||
return FabricEnvelopeSignature{}, ErrFabricEnvelopeSigningKeyInvalid
|
||||
}
|
||||
if len(canonical) == 0 {
|
||||
return FabricEnvelopeSignature{}, fmt.Errorf("%w: canonical envelope empty", ErrFabricEnvelopeSigningKeyInvalid)
|
||||
}
|
||||
keyID := strings.TrimSpace(s.KeyID)
|
||||
if keyID == "" {
|
||||
publicKey, ok := s.PrivateKey.Public().(ed25519.PublicKey)
|
||||
if !ok {
|
||||
return FabricEnvelopeSignature{}, ErrFabricEnvelopeSigningKeyInvalid
|
||||
}
|
||||
keyID = ed25519EnvelopeKeyID(publicKey)
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
if s.Now != nil {
|
||||
now = s.Now().UTC()
|
||||
}
|
||||
return FabricEnvelopeSignature{
|
||||
KeyID: keyID,
|
||||
Alg: "ed25519",
|
||||
Signature: base64.StdEncoding.EncodeToString(ed25519.Sign(s.PrivateKey, canonical)),
|
||||
SignedAt: now.Format(time.RFC3339Nano),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func decodeEd25519PrivateKey(value string) (ed25519.PrivateKey, error) {
|
||||
decoded, err := decodeEnvelopeBase64(strings.TrimSpace(value))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: private key must be base64 encoded", ErrFabricEnvelopeSigningKeyInvalid)
|
||||
}
|
||||
if len(decoded) != ed25519.PrivateKeySize {
|
||||
return nil, fmt.Errorf("%w: private key must decode to %d bytes", ErrFabricEnvelopeSigningKeyInvalid, ed25519.PrivateKeySize)
|
||||
}
|
||||
return ed25519.PrivateKey(decoded), nil
|
||||
}
|
||||
|
||||
func decodeEnvelopeBase64(value string) ([]byte, error) {
|
||||
if value == "" {
|
||||
return nil, errors.New("empty base64 value")
|
||||
}
|
||||
decoded, err := base64.StdEncoding.DecodeString(value)
|
||||
if err == nil {
|
||||
return decoded, nil
|
||||
}
|
||||
decoded, err = base64.RawStdEncoding.DecodeString(value)
|
||||
if err == nil {
|
||||
return decoded, nil
|
||||
}
|
||||
return base64.RawURLEncoding.DecodeString(value)
|
||||
}
|
||||
|
||||
func ed25519EnvelopeKeyID(publicKey ed25519.PublicKey) string {
|
||||
sum := sha256.Sum256(publicKey)
|
||||
return "rap-node-ed25519-" + hex.EncodeToString(sum[:16])
|
||||
}
|
||||
Reference in New Issue
Block a user