Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

Commit

Permalink
feat: enable tls on rpc endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
mrekucci committed Feb 13, 2024
1 parent 0c3aeca commit 6113ed3
Show file tree
Hide file tree
Showing 15 changed files with 343 additions and 180 deletions.
1 change: 1 addition & 0 deletions .github/workflows/go-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
uses: golangci/golangci-lint-action@v2
with:
version: v1.54.2
args: --timeout 5m

- name: Vet
run: go vet ./...
Expand Down
107 changes: 57 additions & 50 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log/slog"
"os"
"path/filepath"
"slices"
"strings"
"time"

Expand All @@ -21,9 +22,16 @@ import (
"github.com/urfave/cli/v2/altsrc"
)

// The following const block contains the name of the cli flags, especially
// for reuse purposes.
const (
serverTLSCertificateFlagName = "server-tls-certificate"
serverTLSPrivateKeyFlagName = "server-tls-private-key"
)

const (
defaultP2PPort = 13522
defaultP2PAddr = "0.0.0.0"
defaultP2PPort = 13522

defaultHTTPPort = 13523
defaultRPCPort = 13524
Expand All @@ -37,19 +45,17 @@ const (
var (
portCheck = func(c *cli.Context, p int) error {
if p < 0 || p > 65535 {
return fmt.Errorf("Invalid port number %d, expected 0 <= port <= 65535", p)
return fmt.Errorf("invalid port number %d, expected 0 <= port <= 65535", p)
}
return nil
}

stringInCheck = func(flag string, opts []string) func(c *cli.Context, p string) error {
return func(c *cli.Context, p string) error {
for _, opt := range opts {
if p == opt {
return nil
}
if !slices.Contains(opts, p) {
return fmt.Errorf("invalid %s option %q, expected one of %s", flag, p, strings.Join(opts, ", "))
}
return fmt.Errorf("Invalid %s option '%s', expected one of %s", flag, p, strings.Join(opts, ", "))
return nil
}
}
)
Expand Down Expand Up @@ -203,6 +209,18 @@ var (
EnvVars: []string{"MEV_COMMIT_NAT_PORT"},
Value: defaultP2PPort,
})

optionServerTLSCert = altsrc.NewStringFlag(&cli.StringFlag{
Name: serverTLSCertificateFlagName,
Usage: "Path to the server TLS certificate",
EnvVars: []string{"MEV_COMMIT_SERVER_TLS_CERTIFICATE"},
})

optionServerTLSPrivateKey = altsrc.NewStringFlag(&cli.StringFlag{
Name: serverTLSPrivateKeyFlagName,
Usage: "Path to the server TLS private key",
EnvVars: []string{"MEV_COMMIT_SERVER_TLS_PRIVATE_KEY"},
})
)

func main() {
Expand All @@ -228,6 +246,8 @@ func main() {
optionSettlementRPCEndpoint,
optionNATAddr,
optionNATPort,
optionServerTLSCert,
optionServerTLSPrivateKey,
}

app := &cli.App{
Expand All @@ -240,47 +260,34 @@ func main() {
}

if err := app.Run(os.Args); err != nil {
fmt.Fprintf(app.Writer, "exited with error: %v\n", err)
fmt.Fprintln(app.Writer, "exited with error:", err)
}
}

func createKeyIfNotExists(c *cli.Context, path string) error {
// check if key already exists
if _, err := os.Stat(path); err == nil {
fmt.Fprintf(c.App.Writer, "Using existing private key: %s\n", path)
fmt.Fprintln(c.App.Writer, "using existing private key:", path)
return nil
}

fmt.Fprintf(c.App.Writer, "Creating new private key: %s\n", path)

// check if parent directory exists
if _, err := os.Stat(filepath.Dir(path)); os.IsNotExist(err) {
// create parent directory
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
return err
}
}

privKey, err := crypto.GenerateKey()
if err != nil {
fmt.Fprintln(c.App.Writer, "creating new private key:", path)
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
return err
}

f, err := os.Create(path)
key, err := crypto.GenerateKey()
if err != nil {
return err
}

defer f.Close()

if err := crypto.SaveECDSA(path, privKey); err != nil {
if err := crypto.SaveECDSA(path, key); err != nil {
return err
}

wallet := libp2p.GetEthAddressFromPubKey(&privKey.PublicKey)
addr := libp2p.GetEthAddressFromPubKey(&key.PublicKey)

fmt.Fprintf(c.App.Writer, "Private key saved to file: %s\n", path)
fmt.Fprintf(c.App.Writer, "Wallet address: %s\n", wallet.Hex())
fmt.Fprintln(c.App.Writer, "private key saved to file:", path)
fmt.Fprintln(c.App.Writer, "wallet address:", addr.Hex())
return nil
}

Expand Down Expand Up @@ -343,6 +350,12 @@ func launchNodeWithConfig(c *cli.Context) error {
natAddr = fmt.Sprintf("%s:%d", c.String(optionNATAddr.Name), c.Int(optionNATPort.Name))
}

crtFile := c.String(serverTLSCertificateFlagName)
keyFile := c.String(serverTLSPrivateKeyFlagName)
if (crtFile == "") != (keyFile == "") {
return fmt.Errorf("both -%s and -%s must be provided to enable TLS", serverTLSCertificateFlagName, serverTLSPrivateKeyFlagName)
}

nd, err := node.NewNode(&node.Options{
KeySigner: keysigner,
Secret: c.String(optionSecret.Name),
Expand All @@ -358,13 +371,15 @@ func launchNodeWithConfig(c *cli.Context) error {
BidderRegistryContract: c.String(optionBidderRegistryAddr.Name),
RPCEndpoint: c.String(optionSettlementRPCEndpoint.Name),
NatAddr: natAddr,
TLSCertificateFile: crtFile,
TLSPrivateKeyFile: keyFile,
})
if err != nil {
return fmt.Errorf("failed starting node: %w", err)
}

<-c.Done()
fmt.Fprintf(c.App.Writer, "shutting down...\n")
fmt.Fprintln(c.App.Writer, "shutting down...")
closed := make(chan struct{})

go func() {
Expand All @@ -386,31 +401,23 @@ func launchNodeWithConfig(c *cli.Context) error {
}

func newLogger(lvl, logFmt string, sink io.Writer) (*slog.Logger, error) {
level := new(slog.LevelVar)
if err := level.UnmarshalText([]byte(lvl)); err != nil {
return nil, fmt.Errorf("invalid log level: %w", err)
}

var (
level = new(slog.LevelVar) // Info by default
handler slog.Handler
options = &slog.HandlerOptions{
AddSource: true,
Level: level,
}
)

switch lvl {
case "debug":
level.Set(slog.LevelDebug)
case "info":
level.Set(slog.LevelInfo)
case "warn":
level.Set(slog.LevelWarn)
case "error":
level.Set(slog.LevelError)
default:
return nil, fmt.Errorf("invalid log level: %s", lvl)
}

switch logFmt {
case "text":
handler = slog.NewTextHandler(sink, &slog.HandlerOptions{AddSource: true, Level: level})
case "none":
fallthrough
case "json":
handler = slog.NewJSONHandler(sink, &slog.HandlerOptions{AddSource: true, Level: level})
handler = slog.NewTextHandler(sink, options)
case "json", "none":
handler = slog.NewJSONHandler(sink, options)
default:
return nil, fmt.Errorf("invalid log format: %s", logFmt)
}
Expand Down
13 changes: 6 additions & 7 deletions examples/provideremulator/client/client.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// package client implements a simple gRPC client which is to be run by the provider
// in their environment to get a stream of bids that are being gossip'd in the
// Package client implements a simple gRPC client which is to be run by the provider
// in their environment to get a stream of bids that are being gossiped in the
// mev-commit network. The providers can then decide to accept or reject the bid.
// This status is sent back to the mev-commit node to further take action on the
// network. The client can be improved by handling connection failures or using
Expand Down Expand Up @@ -33,18 +33,17 @@ func NewProviderClient(
return nil, err
}

client := providerapiv1.NewProviderClient(conn)

b := &ProviderClient{
conn: conn,
client: client,
client: providerapiv1.NewProviderClient(conn),
logger: logger,
senderC: make(chan *providerapiv1.BidResponse),
senderClosed: make(chan struct{}),
}

b.startSender()

if err := b.startSender(); err != nil {
return nil, err
}
return b, nil
}

Expand Down
66 changes: 66 additions & 0 deletions gen-certificates.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env sh

# This script automates the creation of a Certificate Authority (CA) and a server
# certificate. It generates a private key and self-signed certificate for the CA,
# then creates a server private key and CSR, and signs the CSR with the CA's
# private key to produce a server certificate. The script requires OpenSSL and optionally
# accepts parameters for the CA subject, server subject, and a server extension config file.
# If the server extension config file is not provided, a default file (server-ext.cnf)
# will be generated with basic constraints and key usage. For more information about the
# configuration file, see: https://www.openssl.org/docs/manmaster/man5/x509v3_config.html

# Parameters:
# 1. CA Subject (optional): The subject details for the CA certificate. Default: "/C=US/O=Server's CA"
# 2. Server Subject (optional): The subject details for the server certificate. Default: "/C=US/O=Server"
# 3. Server Extension Config File (optional): Path to a configuration file with extensions
# for the server certificate. If not provided, a default configuration is used.

# Generated files:
# - CA private key (ca-key.pem)
# - CA self-signed certificate (ca-cert.pem)
# - Server private key (server-key.pem)
# - Server CSR (server-req.pem)
# - Server certificate (server-cert.pem)

# Usage:
# Execute this script with up to three optional arguments:
# ./script.sh [CA Subject] [Server Subject] [Server Extension Config File]
# Example: ./script.sh "/C=US/O=My CA" "/C=US/CN=myserver.example.com" "myserver-ext.cnf"

# Ensure OpenSSL is installed and accessible, prepare the optional server-ext.cnf file
# with necessary server certificate extensions if desired, and execute this script.
# Verify output for CA and server certificate details.

# Note: Designed for educational or development purposes. Adapt carefully for production use.


CA_KEY="ca-key.pem"
CA_CERT="ca-cert.pem"
SERVER_KEY="server-key.pem"
SERVER_REQ="server-req.pem"
SERVER_CERT="server-cert.pem"
CA_SUBJ=${1:-"/C=US/O=Server's CA"}
SERVER_SUBJ=${2:-"/C=US/O=Server"}
SERVER_EXT=${3:-"server-ext.cnf"}

# Generate a default server-ext.cnf file if not provided.
if [ ! -f "${SERVER_EXT}" ]; then
echo "No server extension conf provided; generating a default configuration:"
cat << EOH > "${SERVER_EXT}"
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
EOH
cat "${SERVER_EXT}"
fi

# Generate CA's private key and self-signed certificate.
openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout "${CA_KEY}" -out "${CA_CERT}" -subj "${CA_SUBJ}"
echo "CA's self-signed certificate:"
openssl x509 -in "${CA_CERT}" -noout -text

# Generate server's private key and certificate request (CSR).
openssl req -newkey rsa:4096 -nodes -keyout "${SERVER_KEY}" -out "${SERVER_REQ}" -subj "${SERVER_SUBJ}"
# Use CA's private key to sign server's CSR and generate the server's certificate.
openssl x509 -req -in "${SERVER_REQ}" -days 365 -CA "${CA_CERT}" -CAkey "${CA_KEY}" -CAcreateserial -out "${SERVER_CERT}" -extfile "${SERVER_EXT}"
echo "Server's CA signed certificate:"
openssl x509 -in "${SERVER_CERT}" -noout -text
9 changes: 9 additions & 0 deletions integration-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ services:
dockerfile: ./integrationtest/Dockerfile
args:
node_type: bootnode
service_name: bootnode
restart: always
volumes:
- ./integrationtest/keys/bootnode:/key
Expand Down Expand Up @@ -44,6 +45,7 @@ services:
dockerfile: ./integrationtest/Dockerfile
args:
node_type: provider
service_name: provider1
restart: always
depends_on:
- bootnode
Expand Down Expand Up @@ -110,6 +112,7 @@ services:
dockerfile: ./integrationtest/Dockerfile
args:
node_type: provider
service_name: provider2
restart: always
depends_on:
- bootnode
Expand Down Expand Up @@ -174,6 +177,7 @@ services:
dockerfile: ./integrationtest/Dockerfile
args:
node_type: provider
service_name: provider3
restart: always
depends_on:
- bootnode
Expand Down Expand Up @@ -238,6 +242,7 @@ services:
dockerfile: ./integrationtest/Dockerfile
args:
node_type: bidder
service_name: bidder1
restart: always
depends_on:
- bootnode
Expand Down Expand Up @@ -306,6 +311,7 @@ services:
dockerfile: ./integrationtest/Dockerfile
args:
node_type: bidder
service_name: bidder2
restart: always
depends_on:
- bootnode
Expand Down Expand Up @@ -372,6 +378,7 @@ services:
dockerfile: ./integrationtest/Dockerfile
args:
node_type: bidder
service_name: bidder3
restart: always
depends_on:
- bootnode
Expand Down Expand Up @@ -438,6 +445,7 @@ services:
dockerfile: ./integrationtest/Dockerfile
args:
node_type: bidder
service_name: bidder4
restart: always
depends_on:
- bootnode
Expand Down Expand Up @@ -504,6 +512,7 @@ services:
dockerfile: ./integrationtest/Dockerfile
args:
node_type: bidder
service_name: bidder5
restart: always
depends_on:
- bootnode
Expand Down
Loading

0 comments on commit 6113ed3

Please sign in to comment.