diff --git a/go/worker/common/config.go b/go/worker/common/config.go index 9937c25b0d8..02beb0416d3 100644 --- a/go/worker/common/config.go +++ b/go/worker/common/config.go @@ -1,6 +1,7 @@ package common import ( + "crypto/x509" "fmt" flag "github.com/spf13/pflag" @@ -8,6 +9,8 @@ import ( "github.com/oasislabs/oasis-core/go/common" "github.com/oasislabs/oasis-core/go/common/crypto/signature" + memorySigner "github.com/oasislabs/oasis-core/go/common/crypto/signature/signers/memory" + "github.com/oasislabs/oasis-core/go/common/identity" "github.com/oasislabs/oasis-core/go/common/logging" "github.com/oasislabs/oasis-core/go/common/node" "github.com/oasislabs/oasis-core/go/worker/common/configparser" @@ -19,6 +22,12 @@ var ( cfgClientAddresses = "worker.client.addresses" + // CfgSentryAddresses configures addresses of the worker's sentry nodes. + CfgSentryAddresses = "worker.sentry.addresses" + // CfgSentryCertFiles configures paths to certificates of the worker's + // sentry nodes. + CfgSentryCertFiles = "worker.sentry.cert_files" + // CfgRuntimeID configures the worker runtime ID(s). CfgRuntimeID = "worker.runtime.id" // CfgRuntimeBackend configures the runtime backend. @@ -34,9 +43,11 @@ var ( // Config contains common worker config. type Config struct { // nolint: maligned - ClientPort uint16 - ClientAddresses []node.Address - Runtimes []signature.PublicKey + ClientPort uint16 + ClientAddresses []node.Address + SentryAddresses []node.Address + SentryCertificates []*x509.Certificate + Runtimes []signature.PublicKey // RuntimeHost contains configuration for a worker that hosts // runtimes. It may be nil if the worker is not configured to @@ -91,16 +102,42 @@ func newConfig() (*Config, error) { if err != nil { return nil, err } + // Parse sentry nodes' addresses. + sentryAddresses, err := configparser.ParseAddressList(viper.GetStringSlice(CfgSentryAddresses)) + if err != nil { + return nil, err + } + // Parse sentry nodes' certificate files. + sentryCertFiles := viper.GetStringSlice(CfgSentryCertFiles) + // TODO: Check if the number of sentry addresses correspond to the number of sentry cert files. + sentryCerts := []*x509.Certificate{} + for _, certFile := range sentryCertFiles { + ident, err := identity.Load(certFile, memorySigner.NewFactory()) + if err != nil { + return nil, err + } + if len(ident.TLSCertificate.Certificate) != 1 { + return nil, fmt.Errorf("sentry certificate file %v should contain exactly 1 certificate in the chain", certFile) + } + x509Cert, err := x509.ParseCertificate(ident.TLSCertificate.Certificate[0]) + if err != nil { + return nil, err + } + sentryCerts = append(sentryCerts, x509Cert) + } + runtimes, err := configparser.GetRuntimes(viper.GetStringSlice(CfgRuntimeID)) if err != nil { return nil, err } cfg := Config{ - ClientPort: uint16(viper.GetInt(CfgClientPort)), - ClientAddresses: clientAddresses, - Runtimes: runtimes, - logger: logging.GetLogger("worker/config"), + ClientPort: uint16(viper.GetInt(CfgClientPort)), + ClientAddresses: clientAddresses, + SentryAddresses: sentryAddresses, + SentryCertificates: sentryCerts, + Runtimes: runtimes, + logger: logging.GetLogger("worker/config"), } // Check if runtime host is configured for the runtimes. diff --git a/go/worker/registration/registration.go b/go/worker/registration/registration.go index 0bf7dc55224..42d3b821a1e 100644 --- a/go/worker/registration/registration.go +++ b/go/worker/registration/registration.go @@ -20,6 +20,7 @@ import ( epochtime "github.com/oasislabs/oasis-core/go/epochtime/api" "github.com/oasislabs/oasis-core/go/oasis-node/cmd/common/flags" registry "github.com/oasislabs/oasis-core/go/registry/api" + sentryClient "github.com/oasislabs/oasis-core/go/sentry/client" workerCommon "github.com/oasislabs/oasis-core/go/worker/common" "github.com/oasislabs/oasis-core/go/worker/common/p2p" ) @@ -225,9 +226,33 @@ func (r *Registration) registerNode(epoch epochtime.EpochTime) error { } func (r *Registration) consensusValidatorHook(n *node.Node) error { - addrs, err := r.consensus.GetAddresses() - if err != nil { - return errors.Wrap(err, "worker/registration: failed to get consensus validator addresses") + sentryAddrs := r.workerCommonCfg.SentryAddresses + addrs := []node.Address{} + if len(sentryAddrs) > 0 { + sentryCerts := r.workerCommonCfg.SentryCertificates + // Query sentry nodes for their addresses + for i, sentryAddr := range sentryAddrs { + client, err := sentryClient.New(sentryAddr, sentryCerts[i], r.identity) + if err != nil { + r.logger.Error("failed to create sentry client to node", + "err", err, + "sentry_node_addr", addr, + ) + } + sentryPubAddrs, err := client.GetPublicAddresses() + if err != nil { + // XXX: Should this be a warning instead of an error? + r.logger.Error("failed to obtain public addresses of a sentry node") + return err + } + addrs = append(addrs, sentryPubAddrs) + // TODO: Close the client. + } + } else { + addrs, err := r.consensus.GetAddresses() + if err != nil { + return errors.Wrap(err, "worker/registration: failed to get consensus validator addresses") + } } if len(addrs) == 0 {