2020-01-10 01:58:59 +00:00
|
|
|
// Copyright (C) 2020 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package preflight_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net"
|
|
|
|
"strconv"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.uber.org/zap/zaptest"
|
2020-01-23 19:47:34 +00:00
|
|
|
"golang.org/x/sync/errgroup"
|
2020-01-10 01:58:59 +00:00
|
|
|
|
2020-01-20 15:29:53 +00:00
|
|
|
"storj.io/common/identity/testidentity"
|
2020-01-10 01:58:59 +00:00
|
|
|
"storj.io/common/pb"
|
2020-02-26 13:59:46 +00:00
|
|
|
"storj.io/common/pb/pbgrpc"
|
2020-01-20 15:29:53 +00:00
|
|
|
"storj.io/common/peertls/extensions"
|
2020-01-10 01:58:59 +00:00
|
|
|
"storj.io/common/peertls/tlsopts"
|
|
|
|
"storj.io/common/rpc"
|
|
|
|
"storj.io/common/testcontext"
|
2020-01-20 15:29:53 +00:00
|
|
|
"storj.io/storj/pkg/server"
|
2020-01-10 01:58:59 +00:00
|
|
|
"storj.io/storj/private/testplanet"
|
2020-01-23 19:47:34 +00:00
|
|
|
"storj.io/storj/storagenode"
|
2020-01-10 01:58:59 +00:00
|
|
|
"storj.io/storj/storagenode/preflight"
|
|
|
|
"storj.io/storj/storagenode/trust"
|
|
|
|
)
|
|
|
|
|
|
|
|
type mockServer struct {
|
|
|
|
localTime time.Time
|
2020-02-26 13:59:46 +00:00
|
|
|
pbgrpc.NodeServer
|
2020-01-10 01:58:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestLocalTime_InSync(t *testing.T) {
|
|
|
|
testplanet.Run(t, testplanet.Config{
|
|
|
|
SatelliteCount: 1, StorageNodeCount: 1, UplinkCount: 0,
|
2020-01-23 19:47:34 +00:00
|
|
|
Reconfigure: testplanet.Reconfigure{
|
|
|
|
StorageNode: func(index int, config *storagenode.Config) {
|
|
|
|
config.Preflight.LocalTimeCheck = true
|
|
|
|
},
|
|
|
|
},
|
2020-01-10 01:58:59 +00:00
|
|
|
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
|
|
|
storagenode := planet.StorageNodes[0]
|
|
|
|
err := storagenode.Preflight.LocalTime.Check(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLocalTime_OutOfSync(t *testing.T) {
|
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
|
|
|
|
|
|
|
log := zaptest.NewLogger(t)
|
|
|
|
|
|
|
|
// set up mock satellite server configuration
|
|
|
|
mockSatID, err := testidentity.NewTestIdentity(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
config := server.Config{
|
|
|
|
Address: "127.0.0.1:0",
|
|
|
|
PrivateAddress: "127.0.0.1:0",
|
|
|
|
|
|
|
|
Config: tlsopts.Config{
|
|
|
|
PeerIDVersions: "*",
|
|
|
|
Extensions: extensions.Config{
|
|
|
|
Revocation: false,
|
|
|
|
WhitelistSignedLeaf: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
mockSatTLSOptions, err := tlsopts.NewOptions(mockSatID, config.Config, nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-01-24 16:11:31 +00:00
|
|
|
t.Run("Less than 30m", func(t *testing.T) {
|
2020-01-10 01:58:59 +00:00
|
|
|
// register mock GetTime endpoint to mock server
|
2020-01-23 19:47:34 +00:00
|
|
|
var group errgroup.Group
|
|
|
|
defer ctx.Check(group.Wait)
|
|
|
|
|
2020-01-10 01:58:59 +00:00
|
|
|
contactServer, err := server.New(log, mockSatTLSOptions, config.Address, config.PrivateAddress, nil)
|
|
|
|
require.NoError(t, err)
|
2020-01-23 19:47:34 +00:00
|
|
|
defer ctx.Check(contactServer.Close)
|
|
|
|
|
2020-01-10 01:58:59 +00:00
|
|
|
pb.DRPCRegisterNode(contactServer.DRPC(), &mockServer{
|
2020-03-10 22:05:01 +00:00
|
|
|
localTime: time.Now().Add(-25 * time.Minute),
|
2020-01-10 01:58:59 +00:00
|
|
|
})
|
|
|
|
|
2020-01-23 19:47:34 +00:00
|
|
|
group.Go(func() error {
|
|
|
|
return contactServer.Run(ctx)
|
|
|
|
})
|
2020-01-10 01:58:59 +00:00
|
|
|
|
|
|
|
// get mock server address
|
|
|
|
_, portStr, err := net.SplitHostPort(contactServer.Addr().String())
|
|
|
|
require.NoError(t, err)
|
|
|
|
port, err := strconv.Atoi(portStr)
|
|
|
|
require.NoError(t, err)
|
|
|
|
url := trust.SatelliteURL{
|
|
|
|
ID: mockSatID.ID,
|
|
|
|
Host: "127.0.0.1",
|
|
|
|
Port: port,
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// set up storagenode client
|
|
|
|
source, err := trust.NewStaticURLSource(url.String())
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
identity, err := testidentity.NewTestIdentity(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
tlsOptions, err := tlsopts.NewOptions(identity, config.Config, nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
dialer := rpc.NewDefaultDialer(tlsOptions)
|
|
|
|
pool, err := trust.NewPool(log, trust.Dialer(dialer), trust.Config{
|
|
|
|
Sources: []trust.Source{source},
|
|
|
|
CachePath: ctx.File("trust-cache.json"),
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = pool.Refresh(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-01-24 16:11:31 +00:00
|
|
|
// should not return any error when node's clock is off no more than 30m
|
2020-01-10 01:58:59 +00:00
|
|
|
localtime := preflight.NewLocalTime(log, preflight.Config{
|
2020-01-17 15:02:33 +00:00
|
|
|
LocalTimeCheck: true,
|
2020-01-10 01:58:59 +00:00
|
|
|
}, pool, dialer)
|
|
|
|
err = localtime.Check(ctx)
|
|
|
|
require.NoError(t, err)
|
2020-01-23 19:47:34 +00:00
|
|
|
|
2020-01-10 01:58:59 +00:00
|
|
|
})
|
|
|
|
|
2020-01-24 16:11:31 +00:00
|
|
|
t.Run("More than 30m", func(t *testing.T) {
|
2020-01-10 01:58:59 +00:00
|
|
|
// register mock GetTime endpoint to mock server
|
2020-01-23 19:47:34 +00:00
|
|
|
var group errgroup.Group
|
|
|
|
defer ctx.Check(group.Wait)
|
|
|
|
|
2020-01-10 01:58:59 +00:00
|
|
|
contactServer, err := server.New(log, mockSatTLSOptions, config.Address, config.PrivateAddress, nil)
|
|
|
|
require.NoError(t, err)
|
2020-01-23 19:47:34 +00:00
|
|
|
defer ctx.Check(contactServer.Close)
|
2020-01-10 01:58:59 +00:00
|
|
|
|
|
|
|
pb.DRPCRegisterNode(contactServer.DRPC(), &mockServer{
|
2020-03-10 22:05:01 +00:00
|
|
|
localTime: time.Now().Add(-31 * time.Minute),
|
2020-01-10 01:58:59 +00:00
|
|
|
})
|
|
|
|
|
2020-01-23 19:47:34 +00:00
|
|
|
group.Go(func() error {
|
|
|
|
return contactServer.Run(ctx)
|
|
|
|
})
|
2020-01-10 01:58:59 +00:00
|
|
|
|
|
|
|
// get mock server address
|
|
|
|
_, portStr, err := net.SplitHostPort(contactServer.Addr().String())
|
|
|
|
require.NoError(t, err)
|
|
|
|
port, err := strconv.Atoi(portStr)
|
|
|
|
require.NoError(t, err)
|
|
|
|
url := trust.SatelliteURL{
|
|
|
|
ID: mockSatID.ID,
|
|
|
|
Host: "127.0.0.1",
|
|
|
|
Port: port,
|
|
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// set up storagenode client
|
|
|
|
source, err := trust.NewStaticURLSource(url.String())
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
identity, err := testidentity.NewTestIdentity(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
tlsOptions, err := tlsopts.NewOptions(identity, config.Config, nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
dialer := rpc.NewDefaultDialer(tlsOptions)
|
|
|
|
pool, err := trust.NewPool(log, trust.Dialer(dialer), trust.Config{
|
|
|
|
Sources: []trust.Source{source},
|
|
|
|
CachePath: ctx.File("trust-cache.json"),
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = pool.Refresh(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-01-24 16:11:31 +00:00
|
|
|
// should return an error when node's clock is off by more than 30m with all trusted satellites
|
2020-01-10 01:58:59 +00:00
|
|
|
localtime := preflight.NewLocalTime(log, preflight.Config{
|
2020-01-17 15:02:33 +00:00
|
|
|
LocalTimeCheck: true,
|
2020-01-10 01:58:59 +00:00
|
|
|
}, pool, dialer)
|
|
|
|
err = localtime.Check(ctx)
|
|
|
|
require.Error(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mock *mockServer) GetTime(ctx context.Context, req *pb.GetTimeRequest) (*pb.GetTimeResponse, error) {
|
|
|
|
return &pb.GetTimeResponse{
|
|
|
|
Timestamp: mock.localTime,
|
|
|
|
}, nil
|
|
|
|
}
|