storj/pkg/overlay/service_test.go
Bryan White 5b913c45b9
Transport security (#63)
* wip initial transport security

* wip: transport security (add tests / refactor)

* wip tests

* refactoring - still wip

* refactor, improve tests

* wip tls testing

* fix typo

* wip testing

* wip testing

* wip

* tls_test passing

* code-style improvemente / refactor; service and tls tests passing!

* code-style auto-format

* add TestNewServer_LoadTLS

* refactor; test improvements

* refactor

* add client cert

* port changes

* Merge remote-tracking branch 'upstream/master'

* Merge remote-tracking branch 'upstream/master'

* Merge remote-tracking branch 'upstream/master'

* files created

* Merge remote-tracking branch 'upstream/master' into coyle/kad-tests

* wip

* add separate `Process` tests for bolt and redis-backed overlay

* more testing

* fix gitignore

* fix linter error

* goimports goimports GOIMPORTS GoImPortS!!!!

* wip

* fix port madness

* forgot to add

* add `mux` as handler and shorten context timeouts

* gofreakingimports

* fix comments

* refactor test & add logger/monkit registry

* debugging travis

* add comment

* Set redisAddress to empty string for bolt-test

* Merge remote-tracking branch 'upstream/master' into coyle/kad-tests

* Merge branch 'tls' into tls-upstream

* tls:
  add client cert
  refactor
  refactor; test improvements
  add TestNewServer_LoadTLS
  code-style auto-format
  code-style improvemente / refactor; service and tls tests passing!
  tls_test passing
  wip
  wip testing
  wip testing
  fix typo
  wip tls testing
  refactor, improve tests
  refactoring - still wip
  wip tests
  wip: transport security (add tests / refactor)
  wip initial transport security

* fixing linter things

* wip

* remove bkad dependencie from tests

* wip

* wip

* wip

* wip

* wip

* updated coyle/kademlia

* wip

* cleanup

* ports

* overlay upgraded

* linter fixes

* piecestore kademlia newID

* Merge branch 'master' into tls-upstream

* master:
  Add error to the return values of Ranger.Range method (#90)
  udp-forwarding: demo week work! (#84)

* Merge branch 'kad-tests' into tls-upstream

* kad-tests:
  piecestore kademlia newID
  linter fixes
  overlay upgraded
  ports
  cleanup
  wip
  updated coyle/kademlia
  wip
  wip
  wip
  wip
  wip
  remove bkad dependencie from tests
  wip
  wip
  files created
  port changes

* wip

* finish merging service tests

* add test for different client/server certs

* wip

* Merge branch 'master' into tls-upstream

* master:
  Add context to Ranger.Range method (#99)
  Coyle/kad client (#91)

* wip

* wip; refactoring/cleanup

* wip

* Merge branch 'master' into tls

* master:
  Bolt backed overlay cache (#94)
  internal/test: switch errors to error classes (#96)

* wip - test passing

* cleanup

* remove port.go

* cleanup

* Merge branch 'master' into tls

* master:
  hardcode version (#111)
  Coyle/docker fix (#109)
  pkg/kademlia tests and restructuring (#97)
  Use continue instead of return in table tests (#106)
  prepend storjlabs to docker tag (#108)
  Automatically build, tag and push docker images on merge to master (#103)

* more belated merging

* more belated merging

* more belated merging

* add copyrights

* cleanup

* goimports

* refactoring

* wip

* wip

* implement `TLSFileOptions#loadTLS`, refactoring:

`peertls.TestNewClient_LoadTLS` is the failing holdout; Still trying to figure out why I'm getting ECDSA verification is failing.

* not sure if actually working:

Tests are now passing (no more "ECDSA verification failed"); however,
`len(*tls.Certificates.Certificate) == 1` which I don't think should be
the case if the root and leaf are being created correctly.

* Experimenting/bugfixing?:

I think leaf certs should be properly signed by the parent now but not
entirely certain. It's also unclear to me why in
`VerifyPeerCertificate`, `len(rawCerts) == 1` when the certs should
contain both the root and leaf afaik.

* Properly write/read certificate chain (root/leaf):

I think I'm now properly reading and writing the root and leaf
certificate chain such that they're both being received by
`VerifyPeerCertificate`.

The next step is to parse the certificates with `x509.ParseCertificate`
(or similar) and verify that the public keys and signatures match.

* Add tls certificate chain signature veification (spike):

+ `VerifyPeerCertificate` verifies signatures of certificates using the
key of it's parent if there is one; otherwise, it verifies the
certificate is self-signed
+ TODO: refactor
+ TODO: test

* refactoring `VerifyPeerCertificate`

* cleanup

* refactor

* Merge branch 'master' into tls

* master:
  Remove some structural folders we don't seem to be using. (#125)
  license code with agplv3 (#126)
  Update .clabot (#124)
  added team memebers (#123)
  clabot file added (#121)
  ECClient (#110)
  docker image issue fixed (#118)
  Piecestore Farmer CLI  (#92)
  Define Path type (#101)
  adds netstate pagination (#95)
  Transport Client (#89)
  Implement psclient interface (#107)
  pkg/process: start replacing pkg/process with cobra helpers (#98)
  protos/netstate: remove stuff we're not using (#100)
  adding coveralls / code coverage  (#112)

* responding to review feedback / cleanup / add copywrite headers

* suggestions

* realitive

* Merge pull request #1 from coyle/coyle/tls

suggestions

* remove unnecessary `_`s

* Merge branch 'tls' of github.com:bryanchriswhite/storj into tls

* 'tls' of github.com:bryanchriswhite/storj:
  realitive
  suggestions

* Responding to review feedback:

+ refactor `VerifyPeerCertificate`

* remove tls expiration

* remove "hosts" and "clien option" from tls options

* goimports

* linter fixes
2018-07-09 19:43:13 +02:00

227 lines
5.3 KiB
Go

// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package overlay
import (
"context"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/zeebo/errs"
"go.uber.org/zap"
"google.golang.org/grpc"
"gopkg.in/spacemonkeygo/monkit.v2"
"storj.io/storj/internal/test"
"storj.io/storj/pkg/peertls"
"storj.io/storj/pkg/process"
proto "storj.io/storj/protos/overlay" // naming proto to avoid confusion with this package
)
func newTestService(t *testing.T) Service {
return Service{
logger: zap.NewNop(),
metrics: monkit.Default,
}
}
func TestNewServer(t *testing.T) {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 0))
assert.NoError(t, err)
srv := newMockServer()
assert.NotNil(t, srv)
go srv.Serve(lis)
srv.Stop()
}
func TestNewClient_CreateTLS(t *testing.T) {
var err error
tmpPath, err := ioutil.TempDir("", "TestNewClient")
assert.NoError(t, err)
defer os.RemoveAll(tmpPath)
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 0))
assert.NoError(t, err)
basePath := filepath.Join(tmpPath, "TestNewClient_CreateTLS")
srv, tlsOpts := newMockTLSServer(t, basePath, true)
go srv.Serve(lis)
defer srv.Stop()
address := lis.Addr().String()
c, err := NewClient(&address, tlsOpts.DialOption())
assert.NoError(t, err)
r, err := c.Lookup(context.Background(), &proto.LookupRequest{})
assert.NoError(t, err)
assert.NotNil(t, r)
}
func TestNewClient_LoadTLS(t *testing.T) {
var err error
tmpPath, err := ioutil.TempDir("", "TestNewClient")
assert.NoError(t, err)
defer os.RemoveAll(tmpPath)
basePath := filepath.Join(tmpPath, "TestNewClient_LoadTLS")
_, err = peertls.NewTLSFileOptions(
basePath,
basePath,
true,
false,
)
assert.NoError(t, err)
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 0))
assert.NoError(t, err)
// NB: do NOT create a cert, it should be loaded from disk
srv, tlsOpts := newMockTLSServer(t, basePath, false)
go srv.Serve(lis)
defer srv.Stop()
address := lis.Addr().String()
c, err := NewClient(&address, tlsOpts.DialOption())
assert.NoError(t, err)
r, err := c.Lookup(context.Background(), &proto.LookupRequest{})
assert.NoError(t, err)
assert.NotNil(t, r)
}
func TestNewClient_IndependentTLS(t *testing.T) {
var err error
tmpPath, err := ioutil.TempDir("", "TestNewClient_IndependentTLS")
assert.NoError(t, err)
defer os.RemoveAll(tmpPath)
clientBasePath := filepath.Join(tmpPath, "client")
serverBasePath := filepath.Join(tmpPath, "server")
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 0))
assert.NoError(t, err)
srv, _ := newMockTLSServer(t, serverBasePath, true)
go srv.Serve(lis)
defer srv.Stop()
clientTLSOps, err := peertls.NewTLSFileOptions(
clientBasePath,
clientBasePath,
true,
false,
)
assert.NoError(t, err)
address := lis.Addr().String()
c, err := NewClient(&address, clientTLSOps.DialOption())
assert.NoError(t, err)
r, err := c.Lookup(context.Background(), &proto.LookupRequest{})
assert.NoError(t, err)
assert.NotNil(t, r)
}
func TestProcess_redis(t *testing.T) {
tempPath, err := ioutil.TempDir("", "TestProcess_redis")
assert.NoError(t, err)
defer os.RemoveAll(tempPath)
flag.Set("localPort", "0")
done := test.EnsureRedis(t)
defer done()
o := newTestService(t)
ctx, _ := context.WithTimeout(context.Background(), 500*time.Millisecond)
err = o.Process(ctx, nil, nil)
assert.NoError(t, err)
}
func TestProcess_bolt(t *testing.T) {
tempPath, err := ioutil.TempDir("", "TestProcess_bolt")
assert.NoError(t, err)
defer os.RemoveAll(tempPath)
flag.Set("localPort", "0")
flag.Set("redisAddress", "")
boltdbPath, err := filepath.Abs("test_bolt.db")
assert.NoError(t, err)
if err != nil {
defer func() {
if err := os.Remove(boltdbPath); err != nil {
log.Printf("%s\n", errs.New("error while removing test bolt db: %s", err))
}
}()
}
flag.Set("boltdbPath", boltdbPath)
o := newTestService(t)
ctx, _ := context.WithTimeout(context.Background(), 500*time.Millisecond)
err = o.Process(ctx, nil, nil)
assert.NoError(t, err)
}
func TestProcess_error(t *testing.T) {
tempPath, err := ioutil.TempDir("", "TestProcess_error")
assert.NoError(t, err)
defer os.RemoveAll(tempPath)
flag.Set("localPort", "0")
flag.Set("boltdbPath", "")
flag.Set("redisAddress", "")
o := newTestService(t)
ctx, _ := context.WithTimeout(context.Background(), 500*time.Millisecond)
err = o.Process(ctx, nil, nil)
assert.True(t, process.ErrUsage.Has(err))
}
func newMockServer(opts ...grpc.ServerOption) *grpc.Server {
grpcServer := grpc.NewServer(opts...)
proto.RegisterOverlayServer(grpcServer, &MockOverlay{})
return grpcServer
}
func newMockTLSServer(t *testing.T, tlsBasePath string, create bool) (*grpc.Server, *peertls.TLSFileOptions) {
tlsOpts, err := peertls.NewTLSFileOptions(
tlsBasePath,
tlsBasePath,
create,
false,
)
assert.NoError(t, err)
assert.NotNil(t, tlsOpts)
grpcServer := newMockServer(tlsOpts.ServerOption())
return grpcServer, tlsOpts
}
type MockOverlay struct{}
func (o *MockOverlay) FindStorageNodes(ctx context.Context, req *proto.FindStorageNodesRequest) (*proto.FindStorageNodesResponse, error) {
return &proto.FindStorageNodesResponse{}, nil
}
func (o *MockOverlay) Lookup(ctx context.Context, req *proto.LookupRequest) (*proto.LookupResponse, error) {
return &proto.LookupResponse{}, nil
}