TLS Support (#252)

* begin adding tls

* remove incomplete line in gw/main.go

* identity fixes+:

+ fix `peertls.NewCert` public key issue
+ fix `peertls.verfiyChain` issue
+ fix identity dial option
+ rename `GenerateCA` to `NewCA` and `generateCAWorker` to `newCAWorker` for better consistency/convention

* use pdbclient instead of pointerdb in miniogw

* fix tests

* go fmt

* make review changes

* modify how context.Background() is used

* more context stuff
This commit is contained in:
Maximillian von Briesen 2018-08-24 00:01:03 -04:00 committed by JT Olio
parent fdfa6e85c8
commit 553def620a
10 changed files with 129 additions and 49 deletions

View File

@ -16,12 +16,14 @@ import (
p "storj.io/storj/pkg/paths"
client "storj.io/storj/pkg/pointerdb/pdbclient"
"storj.io/storj/pkg/provider"
"storj.io/storj/pkg/storage/meta"
proto "storj.io/storj/protos/pointerdb"
)
var (
pointerdbClientPort string
ctx = context.Background()
)
func initializeFlags() {
@ -35,8 +37,18 @@ func main() {
logger, _ := zap.NewDevelopment()
defer logger.Sync()
ca, err := provider.NewCA(ctx, 12, 4)
if err != nil {
logger.Error("Failed to create certificate authority: ", zap.Error(err))
os.Exit(1)
}
identity, err := ca.NewIdentity()
if err != nil {
logger.Error("Failed to create full identity: ", zap.Error(err))
os.Exit(1)
}
APIKey := []byte("abc123")
pdbclient, err := client.NewClient(pointerdbClientPort, APIKey)
pdbclient, err := client.NewClient(identity, pointerdbClientPort, APIKey)
if err != nil {
logger.Error("Failed to dial: ", zap.Error(err))

View File

@ -116,23 +116,15 @@ func (c Config) NewGateway(ctx context.Context,
identity *provider.FullIdentity) (gw minio.Gateway, err error) {
defer mon.Task()(&ctx)(&err)
// TODO(jt): the transport client should use tls and should use the identity
// defined in this function.
t := transport.NewClient()
t := transport.NewClient(identity)
// TODO(jt): overlay.NewClient should dial the overlay server with the
// transport client. probably should use the same connection as the
// pointerdb client
var oc overlay.Client
oc, err = overlay.NewOverlayClient(c.OverlayAddr)
oc, err = overlay.NewOverlayClient(identity, c.OverlayAddr)
if err != nil {
return nil, err
}
// TODO(jt): pdbclient.NewClient should dial the pointerdb server with the
// transport client. probably should use the same connection as the
// overlay client
pdb, err := pdbclient.NewClient(c.PointerDBAddr, []byte(c.APIKey))
pdb, err := pdbclient.NewClient(identity, c.PointerDBAddr, []byte(c.APIKey))
if err != nil {
return nil, err
}

View File

@ -9,6 +9,7 @@ import (
"github.com/zeebo/errs"
"storj.io/storj/pkg/pool"
"storj.io/storj/pkg/provider"
"storj.io/storj/pkg/transport"
proto "storj.io/storj/protos/overlay"
)
@ -17,10 +18,11 @@ import (
var NodeClientErr = errs.Class("node client error")
// NewNodeClient instantiates a node client
func NewNodeClient(self proto.Node) (Client, error) {
func NewNodeClient(identity *provider.FullIdentity, self proto.Node) (Client, error) {
client := transport.NewClient(identity)
return &Node{
self: self,
tc: transport.NewClient(),
tc: client,
cache: pool.NewConnectionPool(),
}, nil
}

View File

@ -13,9 +13,12 @@ import (
"google.golang.org/grpc"
"storj.io/storj/internal/test"
"storj.io/storj/pkg/provider"
proto "storj.io/storj/protos/overlay"
)
var ctx = context.Background()
func TestLookup(t *testing.T) {
cases := []struct {
self proto.Node
@ -36,26 +39,45 @@ func TestLookup(t *testing.T) {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 8080))
assert.NoError(t, err)
srv, mock := newTestServer()
srv, mock, err := newTestServer(ctx)
assert.NoError(t, err)
go srv.Serve(lis)
defer srv.Stop()
nc, err := NewNodeClient(v.self)
ca, err := provider.NewCA(ctx, 12, 4)
assert.NoError(t, err)
identity, err := ca.NewIdentity()
assert.NoError(t, err)
_, err = nc.Lookup(context.Background(), v.to, v.find)
nc, err := NewNodeClient(identity, v.self)
assert.NoError(t, err)
_, err = nc.Lookup(ctx, v.to, v.find)
assert.Equal(t, v.expectedErr, err)
assert.Equal(t, 1, mock.queryCalled)
}
}
func newTestServer() (*grpc.Server, *mockNodeServer) {
grpcServer := grpc.NewServer()
func newTestServer(ctx context.Context) (*grpc.Server, *mockNodeServer, error) {
ca, err := provider.NewCA(ctx, 12, 4)
if err != nil {
return nil, nil, err
}
identity, err := ca.NewIdentity()
if err != nil {
return nil, nil, err
}
identOpt, err := identity.ServerOption()
if err != nil {
return nil, nil, err
}
grpcServer := grpc.NewServer(identOpt)
mn := &mockNodeServer{queryCalled: 0}
proto.RegisterNodesServer(grpcServer, mn)
return grpcServer, mn
return grpcServer, mn, nil
}

View File

@ -6,9 +6,8 @@ package overlay
import (
"context"
"google.golang.org/grpc"
"storj.io/storj/pkg/dht"
"storj.io/storj/pkg/provider"
proto "storj.io/storj/protos/overlay"
)
@ -30,8 +29,12 @@ type Overlay struct {
}
// NewOverlayClient returns a new intialized Overlay Client
func NewOverlayClient(address string) (*Overlay, error) {
c, err := NewClient(address, grpc.WithInsecure())
func NewOverlayClient(identity *provider.FullIdentity, address string) (*Overlay, error) {
dialOpt, err := identity.DialOption()
if err != nil {
return nil, err
}
c, err := NewClient(address, dialOpt)
if err != nil {
return nil, err
}

View File

@ -13,6 +13,7 @@ import (
"google.golang.org/grpc"
"storj.io/storj/pkg/dht"
"storj.io/storj/pkg/provider"
proto "storj.io/storj/protos/overlay"
)
@ -37,7 +38,12 @@ func TestNewOverlayClient(t *testing.T) {
}
for _, v := range cases {
oc, err := NewOverlayClient(v.address)
ca, err := provider.NewCA(ctx, 12, 4)
assert.NoError(t, err)
identity, err := ca.NewIdentity()
assert.NoError(t, err)
oc, err := NewOverlayClient(identity, v.address)
assert.NoError(t, err)
assert.NotNil(t, oc)
@ -63,17 +69,23 @@ func TestChoose(t *testing.T) {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 0))
assert.NoError(t, err)
srv, mock := NewTestServer()
srv, mock, err := NewTestServer(ctx)
assert.NoError(t, err)
go srv.Serve(lis)
defer srv.Stop()
oc, err := NewOverlayClient(lis.Addr().String())
ca, err := provider.NewCA(ctx, 12, 4)
assert.NoError(t, err)
identity, err := ca.NewIdentity()
assert.NoError(t, err)
oc, err := NewOverlayClient(identity, lis.Addr().String())
assert.NoError(t, err)
assert.NotNil(t, oc)
assert.NotEmpty(t, oc.client)
_, err = oc.Choose(context.Background(), v.limit, v.space)
_, err = oc.Choose(ctx, v.limit, v.space)
assert.NoError(t, err)
assert.Equal(t, mock.FindStorageNodesCalled, v.expectedCalls)
}
@ -94,30 +106,49 @@ func TestLookup(t *testing.T) {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 0))
assert.NoError(t, err)
srv, mock := NewTestServer()
srv, mock, err := NewTestServer(ctx)
assert.NoError(t, err)
go srv.Serve(lis)
defer srv.Stop()
oc, err := NewOverlayClient(lis.Addr().String())
ca, err := provider.NewCA(ctx, 12, 4)
assert.NoError(t, err)
identity, err := ca.NewIdentity()
assert.NoError(t, err)
oc, err := NewOverlayClient(identity, lis.Addr().String())
assert.NoError(t, err)
assert.NotNil(t, oc)
assert.NotEmpty(t, oc.client)
_, err = oc.Lookup(context.Background(), v.nodeID)
_, err = oc.Lookup(ctx, v.nodeID)
assert.NoError(t, err)
assert.Equal(t, mock.lookupCalled, v.expectedCalls)
}
}
func NewTestServer() (*grpc.Server, *mockOverlayServer) {
grpcServer := grpc.NewServer()
func NewTestServer(ctx context.Context) (*grpc.Server, *mockOverlayServer, error) {
ca, err := provider.NewCA(ctx, 12, 4)
if err != nil {
return nil, nil, err
}
identity, err := ca.NewIdentity()
if err != nil {
return nil, nil, err
}
identOpt, err := identity.ServerOption()
if err != nil {
return nil, nil, err
}
grpcServer := grpc.NewServer(identOpt)
mo := &mockOverlayServer{lookupCalled: 0, FindStorageNodesCalled: 0}
proto.RegisterOverlayServer(grpcServer, mo)
return grpcServer, mo
return grpcServer, mo, nil
}

View File

@ -13,6 +13,7 @@ import (
monkit "gopkg.in/spacemonkeygo/monkit.v2"
p "storj.io/storj/pkg/paths"
"storj.io/storj/pkg/provider"
pb "storj.io/storj/protos/pointerdb"
"storj.io/storj/storage"
)
@ -47,8 +48,12 @@ type Client interface {
}
// NewClient initializes a new pointerdb client
func NewClient(address string, APIKey []byte) (*PointerDB, error) {
c, err := clientConnection(address, grpc.WithInsecure())
func NewClient(identity *provider.FullIdentity, address string, APIKey []byte) (*PointerDB, error) {
dialOpt, err := identity.DialOption()
if err != nil {
return nil, err
}
c, err := clientConnection(address, dialOpt)
if err != nil {
return nil, err

View File

@ -48,15 +48,12 @@ func NewProvider(identity *FullIdentity, lis net.Listener,
return nil, err
}
// TODO: use ident
_ = ident
return &Provider{
lis: lis,
g: grpc.NewServer(
grpc.StreamInterceptor(streamInterceptor),
grpc.UnaryInterceptor(unaryInterceptor),
// ident, TODO
ident,
),
next: responsibilities,
identity: identity,

View File

@ -8,27 +8,33 @@ import (
"google.golang.org/grpc"
"storj.io/storj/pkg/provider"
proto "storj.io/storj/protos/overlay"
)
// Transport interface structure
type Transport struct {
identity *provider.FullIdentity
}
// NewClient returns a newly instantiated Transport Client
func NewClient() *Transport {
return &Transport{}
func NewClient(identity *provider.FullIdentity) *Transport {
return &Transport{identity: identity}
}
// DialNode using the authenticated mode
func (o *Transport) DialNode(ctx context.Context, node *proto.Node) (conn *grpc.ClientConn, err error) {
defer mon.Task()(&ctx)(&err)
if node.Address == nil {
if node.Address == nil || node.Address.Address == "" {
return nil, Error.New("no address")
}
/* TODO@ASK security feature under development */
return o.DialUnauthenticated(ctx, *node.Address)
dialOpt, err := o.identity.DialOption()
if err != nil {
return nil, err
}
return grpc.Dial(node.Address.Address, dialOpt)
}
// DialUnauthenticated using unauthenticated mode

View File

@ -8,11 +8,21 @@ import (
"github.com/stretchr/testify/assert"
"storj.io/storj/pkg/provider"
proto "storj.io/storj/protos/overlay"
)
var ctx = context.Background()
func TestDialNode(t *testing.T) {
oc := Transport{}
ca, err := provider.NewCA(ctx, 12, 4)
assert.NoError(t, err)
identity, err := ca.NewIdentity()
assert.NoError(t, err)
oc := Transport{
identity: identity,
}
// node.Address.Address == "" condition test
node := proto.Node{
@ -22,7 +32,7 @@ func TestDialNode(t *testing.T) {
Address: "",
},
}
conn, err := oc.DialNode(context.Background(), &node)
conn, err := oc.DialNode(ctx, &node)
assert.Error(t, err)
assert.Nil(t, conn)
@ -31,7 +41,7 @@ func TestDialNode(t *testing.T) {
Id: "DUMMYID2",
Address: nil,
}
conn, err = oc.DialNode(context.Background(), &node)
conn, err = oc.DialNode(ctx, &node)
assert.Error(t, err)
assert.Nil(t, conn)
@ -43,7 +53,7 @@ func TestDialNode(t *testing.T) {
Address: "127.0.0.0:9000",
},
}
conn, err = oc.DialNode(context.Background(), &node)
conn, err = oc.DialNode(ctx, &node)
assert.NoError(t, err)
assert.NotNil(t, conn)
}