Skip to content

Commit

Permalink
Merge pull request #34 from linki/tls-cert
Browse files Browse the repository at this point in the history
Allow to specify TLS cert for secure GRPC connection to Beacon Chain

Many thanks to @linki
  • Loading branch information
tzapu authored Jul 8, 2020
2 parents a1cc94b + f08721a commit 99731d3
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 7 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ docker run -d --name eth2stats --restart always --network="host" \

You should now be able to see your node and it's stats on [eth2stats](https://eth2stats.io).

### Securing your gRPC connection to the Beacon Chain

If your Beacon node uses a TLS connection for its GRPC endpoint you need to provide a valid certificate to `eth2stats-client` via the `--beacon.tls-cert` flag:

```shell script
docker run -d --name eth2stats --restart always --network="host" \
-v ~/eth2stats/data:/data \
... # omitted for brevity
--beacon.type="prysm" --beacon.addr="localhost:4000" --beacon.tls-cert "/data/cert.pem"
```

Have a look at Prysm's documentation to learn [how to start their Beacon Chain with enabled TLS](https://docs.prylabs.network/docs/prysm-usage/secure-grpc) and how to [generate and use self-signed certificates](https://docs.prylabs.network/docs/prysm-usage/secure-grpc#generating-self-signed-tls-certificates).

## Building from source
### Prerequisites
Expand Down
16 changes: 15 additions & 1 deletion beacon/prysm/prysm.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
prysmAPI "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"

"github.com/alethio/eth2stats-client/beacon"
"github.com/alethio/eth2stats-client/types"
Expand All @@ -19,6 +20,7 @@ var ClientMaxReceiveMessageSize = 67108864

type Config struct {
GRPCAddr string
TLSCert string
}

type PrysmGRPCClient struct {
Expand All @@ -31,9 +33,21 @@ type PrysmGRPCClient struct {
func New(config Config) *PrysmGRPCClient {
log.Info("setting up beacon client connection")

var dialOpt grpc.DialOption
if config.TLSCert != "" {
creds, err := credentials.NewClientTLSFromFile(config.TLSCert, "")
if err != nil {
log.Fatalf("failed to create tls credentials: %v", err)
}
dialOpt = grpc.WithTransportCredentials(creds)
} else {
dialOpt = grpc.WithInsecure()
log.Warn("no tls certificate provided; will use insecure connection to beacon chain")
}

conn, err := grpc.Dial(
config.GRPCAddr,
grpc.WithInsecure(),
dialOpt,
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(ClientMaxReceiveMessageSize)),
)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions commands/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var runCmd = &cobra.Command{
BeaconNode: core.BeaconNodeConfig{
Type: viper.GetString("beacon.type"),
Addr: viper.GetString("beacon.addr"),
TLSCert: viper.GetString("beacon.tls-cert"),
MetricsAddr: viper.GetString("beacon.metrics-addr"),
},
DataFolder: viper.GetString("data.folder"),
Expand Down Expand Up @@ -75,6 +76,9 @@ func init() {
runCmd.Flags().String("beacon.addr", "", "Beacon node endpoint address")
viper.BindPFlag("beacon.addr", runCmd.Flag("beacon.addr"))

runCmd.Flags().String("beacon.tls-cert", "", "Beacon node certificate to secure gRPC connection")
viper.BindPFlag("beacon.tls-cert", runCmd.Flag("beacon.tls-cert"))

runCmd.Flags().String("beacon.metrics-addr", "", "The url where the beacon client exposes metrics (used for memory usage)")
viper.BindPFlag("beacon.metrics-addr", runCmd.Flag("beacon.metrics-addr"))

Expand Down
15 changes: 10 additions & 5 deletions core/beacon.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package core

import (
"github.com/alethio/eth2stats-client/beacon/lighthouse"
"github.com/alethio/eth2stats-client/beacon/nimbus"
"github.com/alethio/eth2stats-client/beacon/teku"
"net"
"net/http"
"net/url"
"time"

"github.com/alethio/eth2stats-client/beacon"
"github.com/alethio/eth2stats-client/beacon/lighthouse"
"github.com/alethio/eth2stats-client/beacon/nimbus"
"github.com/alethio/eth2stats-client/beacon/prysm"
"github.com/alethio/eth2stats-client/beacon/teku"
)

func initBeaconClient(nodeType, nodeAddr string) beacon.Client {
func initBeaconClient(nodeType, nodeAddr, nodeCert string) beacon.Client {
// check GRPC clients
switch nodeType {
case "prysm":
return prysm.New(prysm.Config{GRPCAddr: nodeAddr})
return prysm.New(prysm.Config{GRPCAddr: nodeAddr, TLSCert: nodeCert})
default:
break
}
Expand All @@ -27,6 +27,11 @@ func initBeaconClient(nodeType, nodeAddr string) beacon.Client {
if !IsURL(nodeAddr) {
log.Fatalf("invalid node URL: %s", nodeAddr)
}
// Custom TLS certificates have only been tested with GRPC connections.
// Fail early here to avoid mistakes. This can be implemented later if needed.
if nodeCert != "" {
log.Fatal("custom TLS certificates are currently only supported for GRPC connections")
}
var netTransport = &http.Transport{
Dial: (&net.Dialer{
Timeout: 15 * time.Second,
Expand Down
3 changes: 2 additions & 1 deletion core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Eth2statsConfig struct {
type BeaconNodeConfig struct {
Type string
Addr string
TLSCert string
MetricsAddr string
}

Expand All @@ -49,7 +50,7 @@ type Core struct {
func New(config Config) *Core {
c := Core{
config: config,
beaconClient: initBeaconClient(config.BeaconNode.Type, config.BeaconNode.Addr),
beaconClient: initBeaconClient(config.BeaconNode.Type, config.BeaconNode.Addr, config.BeaconNode.TLSCert),
}

c.initEth2statsClient()
Expand Down

0 comments on commit 99731d3

Please sign in to comment.