Skip to content

Commit

Permalink
Changing address format
Browse files Browse the repository at this point in the history
This commit changes the address format of the nodes, to disambiguate
between the grpc over http, over self-signed certificates, and grpc over
public-CA signed certificates.
  • Loading branch information
ineiti committed Nov 30, 2023
1 parent 227b86b commit 66fcdb6
Show file tree
Hide file tree
Showing 15 changed files with 372 additions and 255 deletions.
4 changes: 2 additions & 2 deletions cli/node/memcoin/mod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func TestMemcoin_Scenario_SetupAndTransactions(t *testing.T) {
// Run a few transactions.
for i := 0; i < 5; i++ {
err = runWithCfg(args, config{})
require.EqualError(t, err, "command error: transaction refused: duplicate in roster: 127.0.0.1:2115")
require.EqualError(t, err, "command error: transaction refused: duplicate in roster: grpcs://127.0.0.1:2115")
}

// Test a timeout waiting for a transaction.
Expand Down Expand Up @@ -151,7 +151,7 @@ func TestMemcoin_Scenario_RestartNode(t *testing.T) {
)

err = run(args)
require.EqualError(t, err, "command error: transaction refused: duplicate in roster: 127.0.0.1:2210")
require.EqualError(t, err, "command error: transaction refused: duplicate in roster: grpcs://127.0.0.1:2210")
}

// -----------------------------------------------------------------------------
Expand Down
15 changes: 15 additions & 0 deletions mino/mino.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ type Mino interface {
CreateRPC(name string, h Handler, f serde.Factory) (RPC, error)
}

// AddressConnectionType indicates how to connect to the remote end.
type AddressConnectionType int32

const (
// ACTgRPC is a plain text connection
ACTgRPC AddressConnectionType = iota
// ACTgRPCS is a self-signed TLS secured grpc connection
ACTgRPCS
// ACThttps is a publicly signed TLS secured grpc connection
ACThttps
)

// Address is a representation of a node's address.
type Address interface {
encoding.TextMarshaler
Expand All @@ -47,6 +59,9 @@ type Address interface {

// String returns a string representation of the address.
String() string

// ConnectionType returns the type of connection for this Address
ConnectionType() AddressConnectionType
}

// AddressFactory is the factory to deserialize addresses.
Expand Down
5 changes: 5 additions & 0 deletions mino/minoch/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ func (a address) String() string {
return a.id
}

// ConnectionType always returns plain connection
func (a address) ConnectionType() mino.AddressConnectionType {
return mino.ACTgRPCS
}

// AddressFactory is a factory to deserialize Minoch addresses.
//
// - implements mino.AddressFactory
Expand Down
19 changes: 13 additions & 6 deletions mino/minogrpc/controller/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ type tokenAction struct{}

// Execute implements node.ActionTemplate. It generates a token that will be
// valid for the amount of time given in the request.
// If this node serves TLS itself, a hash of the certificate will be
// printed, too.
func (a tokenAction) Execute(req node.Context) error {
exp := req.Flags.Duration("expiration")

Expand All @@ -108,15 +110,20 @@ func (a tokenAction) Execute(req node.Context) error {

token := m.GenerateToken(exp)

chain := m.GetCertificateChain()
var certHash string
if m.ServeTLS() {
chain := m.GetCertificateChain()

digest, err := m.GetCertificateStore().Hash(chain)
if err != nil {
return xerrors.Errorf("couldn't hash certificate: %v", err)
digest, err := m.GetCertificateStore().Hash(chain)
if err != nil {
return xerrors.Errorf("couldn't hash certificate: %v", err)
}

certHash = fmt.Sprintf(" --cert-hash %s", base64.StdEncoding.EncodeToString(digest))
}

fmt.Fprintf(req.Out, "--token %s --cert-hash %s\n",
token, base64.StdEncoding.EncodeToString(digest))
fmt.Fprintf(req.Out, "--token %s%s\n",
token, certHash)

return nil
}
Expand Down
4 changes: 4 additions & 0 deletions mino/minogrpc/controller/actions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ type fakeJoinable struct {
err error
}

func (j fakeJoinable) ServeTLS() bool {
return true
}

func (j fakeJoinable) GetCertificateChain() certs.CertChain {
cert, _ := j.certs.Load(fake.NewAddress(0))

Expand Down
36 changes: 14 additions & 22 deletions mino/minogrpc/controller/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"net"
"net/url"
Expand Down Expand Up @@ -77,17 +76,17 @@ func (m miniController) SetCommands(builder node.Builder) {
},
cli.StringFlag{
Name: "certKey",
Usage: "provides the certificate private key path",
Usage: "provides the certificate private key path - requires that --certChain is given, too",
Required: false,
},
cli.StringFlag{
Name: "certChain",
Usage: "provides the chain certificate file path",
Usage: "provides the chain certificate file path - requires that --certKey is given, too",
Required: false,
},
cli.BoolFlag{
Name: "noTLS",
Usage: "disables TLS on gRPC connections",
Usage: "dont't serve TLS on the grpc endpoint",
Required: false,
Value: false,
},
Expand Down Expand Up @@ -136,7 +135,7 @@ func (m miniController) SetCommands(builder node.Builder) {
cli.StringFlag{
Name: "cert-hash",
Usage: "certificate hash of the distant server",
Required: true,
Required: false,
},
)
sub.SetAction(builder.MakeAction(joinAction{}))
Expand Down Expand Up @@ -167,14 +166,13 @@ func (m miniController) OnStart(ctx cli.Flags, inj node.Injector) error {
}

var opts []minogrpc.Option

if !ctx.Bool("noTLS") {
if ctx.Bool("noTLS") {
opts = append(opts, minogrpc.NoTLS())
} else {
opts, err = m.getOptionCert(ctx, inj)
if err != nil {
return xerrors.Errorf("failed to get cert option: %v", err)
}
} else {
opts = []minogrpc.Option{minogrpc.DisableTLS()}
}

var public *url.URL
Expand Down Expand Up @@ -228,31 +226,25 @@ func (m miniController) getOptionCert(ctx cli.Flags, inj node.Injector) ([]minog
return nil, xerrors.Errorf("injector: %v", err)
}

certs := certs.NewDiskStore(db, session.AddressFactory{})
certificate := certs.NewDiskStore(db, session.AddressFactory{})

key, err := m.getKey(ctx)
if err != nil {
return nil, xerrors.Errorf("cert private key: %v", err)
}

certKey := ctx.Path("certKey")
if certKey == "" {
certKey = filepath.Join(ctx.Path("config"), certKeyName)
}

type extendedKey interface {
Public() crypto.PublicKey
}

opts := []minogrpc.Option{
minogrpc.WithCertificateKey(key, key.(extendedKey).Public()),
minogrpc.WithStorage(certs),
minogrpc.WithCertificateKey(key, key.(interface{ Public() crypto.PublicKey }).Public()),
minogrpc.WithStorage(certificate),
}

certKey := ctx.Path("certKey")
certChain := ctx.Path("certChain")
if certKey == "" {
certKey = filepath.Join(ctx.Path("config"), certKeyName)
}

if certChain != "" {
fmt.Println("certChain:", certChain, "certKey:", certKey)
cert, err := tls.LoadX509KeyPair(certChain, certKey)
if err != nil {
return nil, xerrors.Errorf("failed to load certificate: %v", err)
Expand Down
Loading

0 comments on commit 66fcdb6

Please sign in to comment.