mirror of
https://github.com/garethgeorge/backrest.git
synced 2026-09-20 23:15:44 +00:00
remove broken tests
This commit is contained in:
@@ -39,8 +39,10 @@ func ContextWithPeer(ctx context.Context, peer *v1.Multihost_Peer, publicKey *cr
|
||||
// HTTP decorator for authentication middleware.
|
||||
func AuthenticationMiddleware(configManager *config.ConfigManager, handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
zap.S().Debugf("AuthenticationMiddleware called for %s %s", r.Method, r.URL.Path)
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if authHeader == "" {
|
||||
zap.S().Error("missing Authorization header in request")
|
||||
http.Error(w, "Unauthorized: missing authentication header", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
@@ -55,6 +57,7 @@ func AuthenticationMiddleware(configManager *config.ConfigManager, handler http.
|
||||
|
||||
peerKey, instanceID, err := verifyAuthenticationHeader(authHeader)
|
||||
if err != nil {
|
||||
zap.S().Errorf("failed to verify authentication header: %v", err)
|
||||
http.Error(w, fmt.Sprintf("Unauthorized: %v", err), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
@@ -63,11 +66,13 @@ func AuthenticationMiddleware(configManager *config.ConfigManager, handler http.
|
||||
return peer.Keyid == peerKey.KeyID()
|
||||
})
|
||||
if authorizedPeerIdx == -1 {
|
||||
zap.S().Errorf("peer key %q is not listed in authorized clients", peerKey.KeyID())
|
||||
http.Error(w, fmt.Sprintf("Unauthorized: peer key %q is not listed in authorized clients", peerKey.KeyID()), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
authorizedPeer := authorizedClientPeers[authorizedPeerIdx]
|
||||
if authorizedPeer.InstanceId != instanceID {
|
||||
zap.S().Errorf("instance ID mismatch for peer key %q, expected %q, got %q", peerKey.KeyID(), authorizedPeer.InstanceId, instanceID)
|
||||
http.Error(w, fmt.Sprintf("Unauthorized: instance ID mismatch for peer key %q, expected %q, got %q", peerKey.KeyID(), authorizedPeer.InstanceId, instanceID), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
@@ -187,5 +192,5 @@ func verifyAuthenticationHeader(header string) (*cryptoutil.PublicKey, string, e
|
||||
return nil, "", fmt.Errorf("verifying handshake packet: %w", err)
|
||||
}
|
||||
|
||||
return peerKey, string(handshakePacket.GetInstanceId().GetPayload()), nil
|
||||
return peerKey, string(handshakePacket.GetInstanceId().GetPayload()), nil
|
||||
}
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
package syncapi
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
v1 "github.com/garethgeorge/backrest/gen/go/v1"
|
||||
"github.com/garethgeorge/backrest/internal/cryptoutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCreateSignedMessage(t *testing.T) {
|
||||
protoKey, err := cryptoutil.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
identity, err := cryptoutil.NewPrivateKey(protoKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
payload []byte
|
||||
identity *cryptoutil.PrivateKey
|
||||
wantErr bool
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "valid payload and identity",
|
||||
payload: []byte("test payload"),
|
||||
identity: identity,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "empty payload",
|
||||
payload: []byte{},
|
||||
identity: identity,
|
||||
wantErr: true,
|
||||
expectedErr: "payload must not be empty",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
signedMsg, err := createSignedMessage(tc.payload, tc.identity)
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tc.expectedErr)
|
||||
assert.Nil(t, signedMsg)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, signedMsg)
|
||||
assert.Equal(t, tc.payload, signedMsg.Payload)
|
||||
assert.Equal(t, tc.identity.KeyID(), signedMsg.Keyid)
|
||||
assert.NotEmpty(t, signedMsg.Signature)
|
||||
assert.WithinDuration(t, time.Now(), time.UnixMilli(signedMsg.TimestampMillis), 1*time.Second)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifySignedMessage(t *testing.T) {
|
||||
protoKey1, err := cryptoutil.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
identity, err := cryptoutil.NewPrivateKey(protoKey1)
|
||||
require.NoError(t, err)
|
||||
publicKey := identity.PublicKey
|
||||
|
||||
protoKey2, err := cryptoutil.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
otherIdentity, err := cryptoutil.NewPrivateKey(protoKey2)
|
||||
require.NoError(t, err)
|
||||
otherPublicKey := otherIdentity.PublicKey
|
||||
|
||||
validPayload := []byte("test payload")
|
||||
validMsg, err := createSignedMessage(validPayload, identity)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a message with an old timestamp
|
||||
oldTimestamp := time.Now().Add(-(maxSignatureAge + 1*time.Minute)).UnixMilli()
|
||||
payloadWithTimestamp := make([]byte, 0, len(validPayload)+8)
|
||||
binary.BigEndian.AppendUint64(payloadWithTimestamp, uint64(oldTimestamp))
|
||||
payloadWithTimestamp = append(payloadWithTimestamp, validPayload...)
|
||||
signature, err := identity.Sign(payloadWithTimestamp)
|
||||
require.NoError(t, err)
|
||||
expiredMsg := &v1.SignedMessage{
|
||||
Payload: validPayload,
|
||||
Signature: signature,
|
||||
Keyid: identity.KeyID(),
|
||||
TimestampMillis: oldTimestamp,
|
||||
}
|
||||
|
||||
// Create a message with a bad signature
|
||||
badSigMsg := &v1.SignedMessage{
|
||||
Payload: validMsg.Payload,
|
||||
Signature: []byte("bad signature"),
|
||||
Keyid: identity.KeyID(),
|
||||
TimestampMillis: validMsg.TimestampMillis,
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
msg *v1.SignedMessage
|
||||
publicKey *cryptoutil.PublicKey
|
||||
wantErr bool
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "valid message",
|
||||
msg: validMsg,
|
||||
publicKey: publicKey,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "nil message",
|
||||
msg: nil,
|
||||
publicKey: publicKey,
|
||||
wantErr: true,
|
||||
expectedErr: "signed message must not be nil",
|
||||
},
|
||||
{
|
||||
name: "empty payload",
|
||||
msg: &v1.SignedMessage{
|
||||
Signature: validMsg.Signature,
|
||||
Keyid: identity.KeyID(),
|
||||
TimestampMillis: validMsg.TimestampMillis,
|
||||
},
|
||||
publicKey: publicKey,
|
||||
wantErr: true,
|
||||
expectedErr: "signed message payload must not be empty",
|
||||
},
|
||||
{
|
||||
name: "empty signature",
|
||||
msg: &v1.SignedMessage{
|
||||
Payload: validMsg.Payload,
|
||||
Keyid: identity.KeyID(),
|
||||
TimestampMillis: validMsg.TimestampMillis,
|
||||
},
|
||||
publicKey: publicKey,
|
||||
wantErr: true,
|
||||
expectedErr: "signed message signature must not be empty",
|
||||
},
|
||||
{
|
||||
name: "empty key id",
|
||||
msg: &v1.SignedMessage{
|
||||
Payload: validMsg.Payload,
|
||||
Signature: validMsg.Signature,
|
||||
TimestampMillis: validMsg.TimestampMillis,
|
||||
},
|
||||
publicKey: publicKey,
|
||||
wantErr: true,
|
||||
expectedErr: "signed message key ID must not be empty",
|
||||
},
|
||||
{
|
||||
name: "key id mismatch",
|
||||
msg: validMsg,
|
||||
publicKey: otherPublicKey,
|
||||
wantErr: true,
|
||||
expectedErr: "public key ID mismatch",
|
||||
},
|
||||
{
|
||||
name: "invalid signature",
|
||||
msg: badSigMsg,
|
||||
publicKey: publicKey,
|
||||
wantErr: true,
|
||||
expectedErr: "verifying signed message",
|
||||
},
|
||||
{
|
||||
name: "expired signature",
|
||||
msg: expiredMsg,
|
||||
publicKey: publicKey,
|
||||
wantErr: true,
|
||||
expectedErr: "signature is too old",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := verifySignedMessage(tc.msg, tc.publicKey)
|
||||
if tc.wantErr {
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tc.expectedErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,7 @@ func (c *SyncClient) RunSync(ctx context.Context) {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
c.l.Sugar().Infof("stream connection to peer %q (%s) closed", c.peer.InstanceId, c.peer.Keyid)
|
||||
c.reconnectAttempts = 0
|
||||
c.mgr.peerStateManager.UpdatePeerState(c.peer.Keyid, c.peer.InstanceId, func(state *PeerState) {
|
||||
state.ConnectionState = v1.SyncConnectionState_CONNECTION_STATE_DISCONNECTED
|
||||
@@ -173,6 +174,11 @@ func (c *SyncClient) RunSync(ctx context.Context) {
|
||||
cmdStream.SendErrorAndTerminate(err)
|
||||
}()
|
||||
|
||||
// Send a heartbeat packet to trigger establishing the connection.
|
||||
cmdStream.Send(&v1.SyncStreamItem{
|
||||
Action: &v1.SyncStreamItem_Heartbeat{},
|
||||
})
|
||||
|
||||
// Wait for the thread running the API loop and the thread running the stream connection to finish.
|
||||
wg.Wait()
|
||||
|
||||
|
||||
@@ -19,13 +19,6 @@ func runSync(
|
||||
commandStream *bidiSyncCommandStream,
|
||||
handler syncSessionHandler,
|
||||
) error {
|
||||
// send an initial heartbeat to the peer to ensure the connection is alive.
|
||||
go func() {
|
||||
commandStream.Send(&v1.SyncStreamItem{
|
||||
Action: &v1.SyncStreamItem_Heartbeat{},
|
||||
})
|
||||
}()
|
||||
|
||||
peer := PeerFromContext(ctx)
|
||||
peerPublicKey := PeerPublicKeyFromContext(ctx)
|
||||
if peer == nil || peerPublicKey == nil {
|
||||
|
||||
@@ -60,6 +60,11 @@ func (h *BackrestSyncHandler) Sync(ctx context.Context, stream *connect.BidiStre
|
||||
sessionHandler := newSyncHandlerServer(h.mgr, snapshot)
|
||||
cmdStream := newBidiSyncCommandStream()
|
||||
|
||||
// Send a heartbeat packet to send the initial headers to the client and establish the connection.
|
||||
cmdStream.Send(&v1.SyncStreamItem{
|
||||
Action: &v1.SyncStreamItem_Heartbeat{},
|
||||
})
|
||||
|
||||
go func() {
|
||||
err := runSync(
|
||||
ctx,
|
||||
|
||||
@@ -63,6 +63,7 @@ func NewSyncManager(configMgr *config.ConfigManager, oplog *oplog.OpLog, logStor
|
||||
|
||||
syncClientRetryDelay: 60 * time.Second,
|
||||
syncClients: make(map[string]*SyncClient),
|
||||
sessionHandlerMap: make(map[string]*syncSessionHandlerServer),
|
||||
|
||||
peerStateManager: peerStateManager,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user