mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-10 23:49:09 +02:00
Renewal was timed against the window in two different ways: the period derived from it, the sweep interval did not. Shortening the window to watch a renewal in an end-to-end run would have left the refresher still looking for due accounts every quarter of an hour, so nothing would have been renewed in time and the test would have reported the feature broken. Derive the sweep from the period, within bounds that keep a very short window from spinning and a normal one from checking less often than is useful, and allow the window itself to be set through the environment so a run can take seconds instead of half a day. A value that cannot be parsed or falls outside the bounds keeps the default, because a window nobody intended is a security property nobody chose, and an override is logged at warning level since it sets how long a device keeps passing the check after its key is gone. Every instance has to be given the same value: the window is part of the nonce, so instances that disagree reject each other's.
54 lines
1.8 KiB
Go
54 lines
1.8 KiB
Go
package certposture
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestResolveWindow(t *testing.T) {
|
|
// An end-to-end run shortens the window so a renewal can be watched in seconds
|
|
// rather than half a day. Anything it cannot make sense of leaves the default in
|
|
// place, because a window nobody intended is a security property nobody chose.
|
|
tests := []struct {
|
|
name string
|
|
env string
|
|
want time.Duration
|
|
}{
|
|
{name: "unset keeps the default", env: "", want: Window},
|
|
{name: "a test-sized window is taken", env: "30s", want: 30 * time.Second},
|
|
{name: "garbage keeps the default", env: "soon", want: Window},
|
|
{name: "below the floor keeps the default", env: "10ms", want: Window},
|
|
{name: "above the ceiling keeps the default", env: "100h", want: Window},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Setenv(EnvWindow, tt.env)
|
|
if tt.env == "" {
|
|
require.NoError(t, os.Unsetenv(EnvWindow))
|
|
}
|
|
assert.Equal(t, tt.want, resolveWindow())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestChallenger_HonoursAShortenedWindow(t *testing.T) {
|
|
// The window is what a nonce is stamped with, so a shortened one has to make a
|
|
// nonce expire sooner, not just change a number in a log line.
|
|
short := 2 * time.Second
|
|
c := &Challenger{secret: []byte("secret"), window: short}
|
|
peerKey := []byte("peer-key")
|
|
|
|
issued := time.Unix(1_790_000_000, 0)
|
|
nonce := c.Nonce(peerKey, issued)
|
|
|
|
require.NoError(t, c.verifyNonce(nonce, peerKey, issued), "a nonce is valid when issued")
|
|
require.NoError(t, c.verifyNonce(nonce, peerKey, issued.Add(short)), "and through the window after it")
|
|
assert.ErrorIs(t, c.verifyNonce(nonce, peerKey, issued.Add(3*short)), ErrNonceExpired,
|
|
"a shortened window must actually expire the nonce sooner")
|
|
}
|