Implement TLS/SSL

This commit is contained in:
Christopher Goes 2018-05-07 23:16:06 +02:00
parent bf16d6453c
commit 2cca5a7a4c
No known key found for this signature in database
GPG Key ID: E828D98232D328D3
7 changed files with 50 additions and 23 deletions

View File

@ -1,7 +1,8 @@
GOTOOLS = \ GOTOOLS = \
github.com/golang/dep/cmd/dep \ github.com/golang/dep/cmd/dep \
github.com/gogo/protobuf/protoc-gen-gogo \ github.com/gogo/protobuf/protoc-gen-gogo \
github.com/gogo/protobuf/gogoproto github.com/gogo/protobuf/gogoproto \
github.com/square/certstrap
# github.com/alecthomas/gometalinter.v2 \ # github.com/alecthomas/gometalinter.v2 \
GOTOOLS_CHECK = dep gometalinter.v2 protoc protoc-gen-gogo GOTOOLS_CHECK = dep gometalinter.v2 protoc protoc-gen-gogo
@ -66,8 +67,21 @@ get_vendor_deps:
######################################## ########################################
### Testing ### Testing
test: gen_certs: clean_certs
## Generating certificates for TLS testing...
certstrap init --common-name "tendermint.com" --passphrase ""
certstrap request-cert -ip "::" --passphrase ""
certstrap sign "::" --CA "tendermint.com" --passphrase ""
mv out/{::.crt,::.key} remotedb
clean_certs:
## Cleaning TLS testing certificates...
rm -rf out
rm -f remotedb/{::.crt,::.key}
test: gen_certs
go test -tags gcc $(shell go list ./... | grep -v vendor) go test -tags gcc $(shell go list ./... | grep -v vendor)
make clean_certs
test100: test100:
@for i in {1..100}; do make test; done @for i in {1..100}; do make test; done
@ -118,7 +132,7 @@ metalinter_all:
# To avoid unintended conflicts with file names, always add to .PHONY # To avoid unintended conflicts with file names, always add to .PHONY
# unless there is a reason not to. # unless there is a reason not to.
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
.PHONY: check protoc build check_tools get_tools get_protoc update_tools get_vendor_deps test fmt metalinter metalinter_all .PHONY: check protoc build check_tools get_tools get_protoc update_tools get_vendor_deps test fmt metalinter metalinter_all gen_certs clean_certs
grpc_dbserver: grpc_dbserver:
protoc -I proto/ proto/defs.proto --go_out=plugins=grpc:proto protoc -I proto/ proto/defs.proto --go_out=plugins=grpc:proto

View File

@ -2,6 +2,7 @@ package grpcdb
import ( import (
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
protodb "github.com/tendermint/tmlibs/proto" protodb "github.com/tendermint/tmlibs/proto"
) )
@ -16,12 +17,12 @@ const (
// NewClient creates a gRPC client connected to the bound gRPC server at serverAddr. // NewClient creates a gRPC client connected to the bound gRPC server at serverAddr.
// Use kind to set the level of security to either Secure or Insecure. // Use kind to set the level of security to either Secure or Insecure.
func NewClient(serverAddr string, kind Security) (protodb.DBClient, error) { func NewClient(serverAddr string, serverCert string) (protodb.DBClient, error) {
var opts []grpc.DialOption creds, err := credentials.NewClientTLSFromFile(serverCert, "")
if kind == Insecure { if err != nil {
opts = append(opts, grpc.WithInsecure()) return nil, err
} }
cc, err := grpc.Dial(serverAddr, opts...) cc, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -21,8 +21,10 @@ should use it, for functionality such as:
or or
addr := ":8998" addr := ":8998"
cert := "server.crt"
key := "server.key"
go func() { go func() {
if err := grpcdb.ListenAndServe(addr); err != nil { if err := grpcdb.ListenAndServe(addr, cert, key); err != nil {
log.Fatalf("BindServer: %v", err) log.Fatalf("BindServer: %v", err)
} }
}() }()

View File

@ -11,13 +11,15 @@ import (
func Example() { func Example() {
addr := ":8998" addr := ":8998"
cert := "server.crt"
key := "server.key"
go func() { go func() {
if err := grpcdb.ListenAndServe(addr); err != nil { if err := grpcdb.ListenAndServe(addr, cert, key); err != nil {
log.Fatalf("BindServer: %v", err) log.Fatalf("BindServer: %v", err)
} }
}() }()
client, err := grpcdb.NewClient(addr, grpcdb.Insecure) client, err := grpcdb.NewClient(addr, cert)
if err != nil { if err != nil {
log.Fatalf("Failed to create grpcDB client: %v", err) log.Fatalf("Failed to create grpcDB client: %v", err)
} }

View File

@ -7,6 +7,7 @@ import (
"time" "time"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/db"
protodb "github.com/tendermint/tmlibs/proto" protodb "github.com/tendermint/tmlibs/proto"
@ -15,19 +16,27 @@ import (
// ListenAndServe is a blocking function that sets up a gRPC based // ListenAndServe is a blocking function that sets up a gRPC based
// server at the address supplied, with the gRPC options passed in. // server at the address supplied, with the gRPC options passed in.
// Normally in usage, invoke it in a goroutine like you would for http.ListenAndServe. // Normally in usage, invoke it in a goroutine like you would for http.ListenAndServe.
func ListenAndServe(addr string, opts ...grpc.ServerOption) error { func ListenAndServe(addr string, cert string, key string, opts ...grpc.ServerOption) error {
ln, err := net.Listen("tcp", addr) ln, err := net.Listen("tcp", addr)
if err != nil { if err != nil {
return err return err
} }
srv := NewServer(opts...) srv, err := NewServer(cert, key, opts...)
if err != nil {
return err
}
return srv.Serve(ln) return srv.Serve(ln)
} }
func NewServer(opts ...grpc.ServerOption) *grpc.Server { func NewServer(cert string, key string, opts ...grpc.ServerOption) (*grpc.Server, error) {
creds, err := credentials.NewServerTLSFromFile(cert, key)
if err != nil {
return nil, err
}
opts = append(opts, grpc.Creds(creds))
srv := grpc.NewServer(opts...) srv := grpc.NewServer(opts...)
protodb.RegisterDBServer(srv, new(server)) protodb.RegisterDBServer(srv, new(server))
return srv return srv, nil
} }
type server struct { type server struct {

View File

@ -14,12 +14,8 @@ type RemoteDB struct {
dc protodb.DBClient dc protodb.DBClient
} }
func NewSecure(serverAddr string) (*RemoteDB, error) { func NewRemoteDB(serverAddr string, serverKey string) (*RemoteDB, error) {
return newRemoteDB(grpcdb.NewClient(serverAddr, grpcdb.Secure)) return newRemoteDB(grpcdb.NewClient(serverAddr, serverKey))
}
func NewInsecure(serverAddr string) (*RemoteDB, error) {
return newRemoteDB(grpcdb.NewClient(serverAddr, grpcdb.Insecure))
} }
func newRemoteDB(gdc protodb.DBClient, err error) (*RemoteDB, error) { func newRemoteDB(gdc protodb.DBClient, err error) (*RemoteDB, error) {

View File

@ -11,9 +11,12 @@ import (
) )
func TestRemoteDB(t *testing.T) { func TestRemoteDB(t *testing.T) {
cert := "::.crt"
key := "::.key"
ln, err := net.Listen("tcp", "0.0.0.0:0") ln, err := net.Listen("tcp", "0.0.0.0:0")
require.Nil(t, err, "expecting a port to have been assigned on which we can listen") require.Nil(t, err, "expecting a port to have been assigned on which we can listen")
srv := grpcdb.NewServer() srv, err := grpcdb.NewServer(cert, key)
require.Nil(t, err)
defer srv.Stop() defer srv.Stop()
go func() { go func() {
if err := srv.Serve(ln); err != nil { if err := srv.Serve(ln); err != nil {
@ -21,7 +24,7 @@ func TestRemoteDB(t *testing.T) {
} }
}() }()
client, err := remotedb.NewInsecure(ln.Addr().String()) client, err := remotedb.NewRemoteDB(ln.Addr().String(), cert)
require.Nil(t, err, "expecting a successful client creation") require.Nil(t, err, "expecting a successful client creation")
require.Nil(t, client.InitRemote(&remotedb.Init{Name: "test-remote-db", Type: "leveldb"})) require.Nil(t, client.InitRemote(&remotedb.Init{Name: "test-remote-db", Type: "leveldb"}))