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 = \
github.com/golang/dep/cmd/dep \
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 \
GOTOOLS_CHECK = dep gometalinter.v2 protoc protoc-gen-gogo
@ -66,8 +67,21 @@ get_vendor_deps:
########################################
### 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)
make clean_certs
test100:
@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
# unless there is a reason not to.
# 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:
protoc -I proto/ proto/defs.proto --go_out=plugins=grpc:proto

View File

@ -2,6 +2,7 @@ package grpcdb
import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
protodb "github.com/tendermint/tmlibs/proto"
)
@ -16,12 +17,12 @@ const (
// 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.
func NewClient(serverAddr string, kind Security) (protodb.DBClient, error) {
var opts []grpc.DialOption
if kind == Insecure {
opts = append(opts, grpc.WithInsecure())
func NewClient(serverAddr string, serverCert string) (protodb.DBClient, error) {
creds, err := credentials.NewClientTLSFromFile(serverCert, "")
if err != nil {
return nil, err
}
cc, err := grpc.Dial(serverAddr, opts...)
cc, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds))
if err != nil {
return nil, err
}

View File

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

View File

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

View File

@ -7,6 +7,7 @@ import (
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"github.com/tendermint/tmlibs/db"
protodb "github.com/tendermint/tmlibs/proto"
@ -15,19 +16,27 @@ import (
// ListenAndServe is a blocking function that sets up a gRPC based
// 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.
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)
if err != nil {
return err
}
srv := NewServer(opts...)
srv, err := NewServer(cert, key, opts...)
if err != nil {
return err
}
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...)
protodb.RegisterDBServer(srv, new(server))
return srv
return srv, nil
}
type server struct {

View File

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

View File

@ -11,9 +11,12 @@ import (
)
func TestRemoteDB(t *testing.T) {
cert := "::.crt"
key := "::.key"
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")
srv := grpcdb.NewServer()
srv, err := grpcdb.NewServer(cert, key)
require.Nil(t, err)
defer srv.Stop()
go func() {
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, client.InitRemote(&remotedb.Init{Name: "test-remote-db", Type: "leveldb"}))