Skip to content

Commit

Permalink
Merge pull request #190 from Ethernal-Tech/feat/jsonrpc-cert-secret-m…
Browse files Browse the repository at this point in the history
…anager

Secret manager for json RPC TLS
  • Loading branch information
oliverbundalo authored Apr 8, 2024
2 parents 1b47a22 + 6cc373a commit aca4572
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 51 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/e2e-polybft-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,19 @@ jobs:
go-version: 1.21.x
check-latest: true
- name: Generate OpenSSL certificate
run: openssl req -x509 -out localhost.crt -keyout localhost.key -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' -extensions EXT -config <(printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
run: openssl req -x509 -out jsontls.crt -keyout jsontls.key -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' -extensions EXT -config <(printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
- name: Copy certificate key
run: sudo cp localhost.key /etc/ssl/private/localhost.key
run: sudo cp jsontls.key /etc/ssl/private/jsontls.key
- name: Copy certificate itself
run: sudo cp localhost.crt /usr/local/share/ca-certificates/localhost.crt
run: sudo cp jsontls.crt /usr/local/share/ca-certificates/jsontls.crt
- name: Add certificate to trusted list
run: sudo update-ca-certificates
- name: Update certificate key folder permissions
run: sudo chmod -R 755 /etc/ssl/private
- name: Update certificate key file permissions
run: sudo chmod 644 /etc/ssl/private/localhost.key
run: sudo chmod 644 /etc/ssl/private/jsontls.key
- name: Check certificate key permissions
run: ls -l /etc/ssl/private/localhost.key
run: ls -l /etc/ssl/private/jsontls.key
- name: Run tests
run: make test-e2e-polybft
- name: Run tests failed
Expand Down
6 changes: 2 additions & 4 deletions command/server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ type Config struct {
JSONRPCBlockRangeLimit uint64 `json:"json_rpc_block_range_limit" yaml:"json_rpc_block_range_limit"`
JSONLogFormat bool `json:"json_log_format" yaml:"json_log_format"`
CorsAllowedOrigins []string `json:"cors_allowed_origins" yaml:"cors_allowed_origins"`
TLSCertFile string `json:"tls_cert_file" yaml:"tls_cert_file"`
TLSKeyFile string `json:"tls_key_file" yaml:"tls_key_file"`
UseTLS bool `json:"use_tls" yaml:"use_tls"`

Relayer bool `json:"relayer" yaml:"relayer"`

Expand Down Expand Up @@ -146,8 +145,7 @@ func DefaultConfig() *Config {
AccessControlAllowOrigins: []string{"*"},
},
LogFilePath: "",
TLSCertFile: "",
TLSKeyFile: "",
UseTLS: false,
JSONRPCBatchRequestLimit: DefaultJSONRPCBatchRequestLimit,
JSONRPCBlockRangeLimit: DefaultJSONRPCBlockRangeLimit,
Relayer: false,
Expand Down
6 changes: 2 additions & 4 deletions command/server/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ const (
devFlag = "dev"
corsOriginFlag = "access-control-allow-origins"
logFileLocationFlag = "log-to"
tlsCertFileLocationFlag = "tls-cert-file"
tlsKeyFileLocationFlag = "tls-key-file"
useTLSFlag = "use-tls"

relayerFlag = "relayer"

Expand Down Expand Up @@ -185,8 +184,7 @@ func (p *serverParams) generateConfig() *server.Config {
LogLevel: hclog.LevelFromString(p.rawConfig.LogLevel),
JSONLogFormat: p.rawConfig.JSONLogFormat,
LogFilePath: p.logFileLocation,
TLSCertFile: p.rawConfig.TLSCertFile,
TLSKeyFile: p.rawConfig.TLSKeyFile,
UseTLS: p.rawConfig.UseTLS,

Relayer: p.relayer,
MetricsInterval: p.rawConfig.MetricsInterval,
Expand Down
17 changes: 5 additions & 12 deletions command/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,18 +214,11 @@ func setFlags(cmd *cobra.Command) {
"write all logs to the file at specified location instead of writing them to console",
)

cmd.Flags().StringVar(
&params.rawConfig.TLSCertFile,
tlsCertFileLocationFlag,
defaultConfig.TLSCertFile,
"path to TLS cert file, if no file is provided then TLS is not used",
)

cmd.Flags().StringVar(
&params.rawConfig.TLSKeyFile,
tlsKeyFileLocationFlag,
defaultConfig.TLSKeyFile,
"path to TLS key file, if no file is provided then TLS is not used",
cmd.Flags().BoolVar(
&params.rawConfig.UseTLS,
useTLSFlag,
defaultConfig.UseTLS,
"start json rpc endpoint with tls enabled",
)

cmd.Flags().BoolVar(
Expand Down
2 changes: 1 addition & 1 deletion e2e-polybft/e2e/jsonrpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestE2E_JsonRPC(t *testing.T) {
framework.WithEpochSize(int(epochSize)),
framework.WithPremine(preminedAcct.Address()),
framework.WithBurnContract(&polybft.BurnContractInfo{BlockNumber: 0, Address: types.ZeroAddress}),
framework.WithHTTPS("/etc/ssl/certs/localhost.pem", "/etc/ssl/private/localhost.key"),
framework.WithHTTPS(),
)
defer cluster.Stop()

Expand Down
11 changes: 4 additions & 7 deletions e2e-polybft/framework/test-cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,7 @@ type TestClusterConfig struct {

logsDirOnce sync.Once

TLSCertFile string
TLSKeyFile string
UseTLS bool
}

func (c *TestClusterConfig) Dir(name string) string {
Expand Down Expand Up @@ -464,10 +463,9 @@ func WithPredeploy(predeployString string) ClusterOption {
}
}

func WithHTTPS(certFile string, keyFile string) ClusterOption {
func WithHTTPS() ClusterOption {
return func(h *TestClusterConfig) {
h.TLSCertFile = certFile
h.TLSKeyFile = keyFile
h.UseTLS = true
}
}

Expand Down Expand Up @@ -813,8 +811,7 @@ func (c *TestCluster) InitTestServer(t *testing.T,
config.Relayer = nodeType.IsSet(Relayer)
config.NumBlockConfirmations = c.Config.NumBlockConfirmations
config.BridgeJSONRPC = bridgeJSONRPC
config.TLSCertFile = c.Config.TLSCertFile
config.TLSKeyFile = c.Config.TLSKeyFile
config.UseTLS = c.Config.UseTLS
})

// watch the server for stop signals. It is important to fix the specific
Expand Down
13 changes: 6 additions & 7 deletions e2e-polybft/framework/test-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ type TestServerConfig struct {
Relayer bool
NumBlockConfirmations uint64
BridgeJSONRPC string
TLSCertFile string
TLSKeyFile string
UseTLS bool
}

type TestServerConfigCallback func(*TestServerConfig)
Expand All @@ -67,7 +66,7 @@ func (t *TestServer) GrpcAddr() string {
}

func (t *TestServer) JSONRPCAddr() string {
if t.config.TLSCertFile != "" && t.config.TLSKeyFile != "" {
if t.config.UseTLS {
return fmt.Sprintf("https://localhost:%d", t.config.JSONRPCPort)
} else {
return fmt.Sprintf("http://%s:%d", hostIP, t.config.JSONRPCPort)
Expand Down Expand Up @@ -171,10 +170,6 @@ func (t *TestServer) Start() {
"--jsonrpc", fmt.Sprintf(":%d", config.JSONRPCPort),
// minimal number of child blocks required for the parent block to be considered final
"--num-block-confirmations", strconv.FormatUint(config.NumBlockConfirmations, 10),
// TLS certificate file
"--tls-cert-file", config.TLSCertFile,
// TLS key file
"--tls-key-file", config.TLSKeyFile,
}

if len(config.LogLevel) > 0 {
Expand All @@ -187,6 +182,10 @@ func (t *TestServer) Start() {
args = append(args, "--relayer")
}

if config.UseTLS {
args = append(args, "--use-tls")
}

// Start the server
stdout := t.clusterConfig.GetStdout(t.config.Name)

Expand Down
48 changes: 42 additions & 6 deletions jsonrpc/jsonrpc.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package jsonrpc

import (
"crypto/tls"
"encoding/json"
"fmt"
"io"
Expand All @@ -9,6 +10,7 @@ import (
"sync"
"time"

"github.com/0xPolygon/polygon-edge/secrets"
"github.com/0xPolygon/polygon-edge/versioning"
"github.com/gorilla/websocket"
"github.com/hashicorp/go-hclog"
Expand Down Expand Up @@ -50,8 +52,8 @@ type Config struct {

ConcurrentRequestsDebug uint64
WebSocketReadLimit uint64
TLSCertFile string
TLSKeyFile string
UseTLS bool
SecretsManager secrets.SecretsManager
}

// NewJSONRPC returns the JSONRPC http server
Expand Down Expand Up @@ -111,12 +113,23 @@ func (j *JSONRPC) setupHTTP() error {
ReadHeaderTimeout: 60 * time.Second,
}

if j.config.TLSCertFile != "" && j.config.TLSKeyFile != "" {
j.logger.Info("TLS", "cert file", j.config.TLSCertFile)
j.logger.Info("TLS", "key file", j.config.TLSKeyFile)
if j.config.UseTLS {
j.logger.Info("configuring http server with tls...")

cert, err := loadTLSCertificate(j.config.SecretsManager)
if err != nil {
j.logger.Error("loading tls certificate", "err", err)

return err
}

srv.TLSConfig = &tls.Config{
Certificates: []tls.Certificate{*cert},
MinVersion: tls.VersionTLS12,
}

go func() {
if err := srv.ServeTLS(lis, j.config.TLSCertFile, j.config.TLSKeyFile); err != nil {
if err := srv.ServeTLS(lis, "", ""); err != nil {
j.logger.Error("closed https connection", "err", err)
}
}()
Expand All @@ -133,6 +146,29 @@ func (j *JSONRPC) setupHTTP() error {
return nil
}

func loadTLSCertificate(manager secrets.SecretsManager) (*tls.Certificate, error) {
if manager.HasSecret(secrets.JSONTLSCert) && manager.HasSecret(secrets.JSONTLSKey) {
tlsCert, err := manager.GetSecret(secrets.JSONTLSCert)
if err != nil {
return nil, fmt.Errorf("unable to get a tls cert file from Secrets Manager, %w", err)
}

tlsKey, err := manager.GetSecret(secrets.JSONTLSKey)
if err != nil {
return nil, fmt.Errorf("unable to get a tls key file from Secrets Manager, %w", err)
}

cert, err := tls.X509KeyPair(tlsCert, tlsKey)
if err != nil {
return nil, fmt.Errorf("unable to create a tls certificate, %w", err)
}

return &cert, nil
}

return nil, secrets.ErrSecretNotFound
}

// The middlewareFactory builds a middleware which enables CORS using the provided config.
func middlewareFactory(config *Config) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
Expand Down
12 changes: 12 additions & 0 deletions secrets/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ func (l *LocalSecretsManager) Setup() error {
secrets.NetworkKeyLocal,
)

// /etc/ssl/certs/jsonrpc.pem
l.secretPathMap[secrets.JSONTLSCert] = filepath.Join(
secrets.JSONTLSFolderLocal,
secrets.JSONTLSCertLocal,
)

// /etc/ssl/private/jsonrpc.key
l.secretPathMap[secrets.JSONTLSKey] = filepath.Join(
secrets.JSONTLSFolderLocal,
secrets.JSONTLSKeyLocal,
)

return nil
}

Expand Down
9 changes: 9 additions & 0 deletions secrets/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,28 @@ const (

// NetworkKey is the libp2p private key secret used for networking
NetworkKey = "network-key"

// JSONTLSKey is the tls private key used for json rpc https endpoint
JSONTLSKey = "jsontls-key"

// JSONTLSCert is the tls certificate used for json rpc https endpoint
JSONTLSCert = "jsontls-pem"
)

// Define constant file names for the local StorageManager
const (
ValidatorKeyLocal = "validator.key"
ValidatorBLSKeyLocal = "validator-bls.key"
NetworkKeyLocal = "libp2p.key"
JSONTLSKeyLocal = "/private/jsontls.key"
JSONTLSCertLocal = "/certs/jsontls.pem"
)

// Define constant folder names for the local StorageManager
const (
ConsensusFolderLocal = "consensus"
NetworkFolderLocal = "libp2p"
JSONTLSFolderLocal = "/etc/ssl"
)

var (
Expand Down
4 changes: 1 addition & 3 deletions server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ type Config struct {

LogFilePath string

TLSCertFile string

TLSKeyFile string
UseTLS bool

Relayer bool

Expand Down
4 changes: 2 additions & 2 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,8 +869,8 @@ func (s *Server) setupJSONRPC() error {
BlockRangeLimit: s.config.JSONRPC.BlockRangeLimit,
ConcurrentRequestsDebug: s.config.JSONRPC.ConcurrentRequestsDebug,
WebSocketReadLimit: s.config.JSONRPC.WebSocketReadLimit,
TLSCertFile: s.config.TLSCertFile,
TLSKeyFile: s.config.TLSKeyFile,
UseTLS: s.config.UseTLS,
SecretsManager: s.secretsManager,
}

srv, err := jsonrpc.NewJSONRPC(s.logger, conf)
Expand Down

0 comments on commit aca4572

Please sign in to comment.