Implement TLS/SSL
This commit is contained in:
parent
bf16d6453c
commit
2cca5a7a4c
20
Makefile
20
Makefile
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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"}))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue