From 46e97a2b91f1d94cfbf95c0e2a116529505e0fd8 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Wed, 1 Jun 2022 13:35:46 -0400 Subject: [PATCH] Update to new nodee lib bits (#2120) --- go.mod | 3 +- go.sum | 6 +- internal/cmd/commands/dev/dev.go | 20 +++-- internal/cmd/commands/server/server.go | 11 ++- .../cluster/handlers/multihop_service.go | 76 ++++++++++++++----- internal/daemon/controller/controller.go | 18 ++++- internal/daemon/controller/handler.go | 34 +-------- .../controller/intercepting_listener.go | 3 +- internal/daemon/controller/listeners.go | 34 +++++---- internal/daemon/controller/listeners_test.go | 4 + .../daemon/worker/controller_connection.go | 9 +-- internal/daemon/worker/listeners.go | 68 ++++++++++------- internal/daemon/worker/worker.go | 28 +++++-- 13 files changed, 179 insertions(+), 135 deletions(-) diff --git a/go.mod b/go.mod index 49f7063a59..c1d4fd75bf 100644 --- a/go.mod +++ b/go.mod @@ -92,7 +92,7 @@ require github.com/hashicorp/go-dbw v0.0.0-20220412153211-c470aec9369f // this i require ( github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220515130442-cac0b5ac133b - github.com/hashicorp/nodeenrollment v0.0.0-20220520141833-ad7323153acc + github.com/hashicorp/nodeenrollment v0.0.0-20220601055910-5718dde51fae ) require ( @@ -166,7 +166,6 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v1.0.2 // indirect - github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pierrec/lz4 v2.5.2+incompatible // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect diff --git a/go.sum b/go.sum index 7678a413e6..a1d9084db6 100644 --- a/go.sum +++ b/go.sum @@ -740,8 +740,8 @@ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+l github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/nodeenrollment v0.0.0-20220520141833-ad7323153acc h1:7RE6UxjVxa3uUS0A4RZwVRFnBJqNQnm5nzNwqPJy4VM= -github.com/hashicorp/nodeenrollment v0.0.0-20220520141833-ad7323153acc/go.mod h1:3054+zYuaQzgXjoy8kyd8whmx1dXUSomyMTRnWHzVXs= +github.com/hashicorp/nodeenrollment v0.0.0-20220601055910-5718dde51fae h1:A8JdiMkZuic8905EgiTDw9cKOb6v1BSrfDMNlS9oejo= +github.com/hashicorp/nodeenrollment v0.0.0-20220601055910-5718dde51fae/go.mod h1:8l3RSuZJAibZKnqX6tvLaeoFzPhDf4oCRVsyFjU5Soc= github.com/hashicorp/vault/api v1.3.1 h1:pkDkcgTh47PRjY1NEFeofqR4W/HkNUi9qIakESO2aRM= github.com/hashicorp/vault/api v1.3.1/go.mod h1:QeJoWxMFt+MsuWcYhmwRLwKEXrjwAFFywzhptMsTIUw= github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= @@ -1088,8 +1088,6 @@ github.com/ory/dockertest/v3 v3.7.0 h1:Bijzonc69Ont3OU0a3TWKJ1Rzlh3TsDXP1JrTAkSm github.com/ory/dockertest/v3 v3.7.0/go.mod h1:PvCCgnP7AfBZeVrzwiUTjZx/IUXlGLC1zQlUQrLIlUE= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= diff --git a/internal/cmd/commands/dev/dev.go b/internal/cmd/commands/dev/dev.go index 397dcb5317..0b70e32460 100644 --- a/internal/cmd/commands/dev/dev.go +++ b/internal/cmd/commands/dev/dev.go @@ -29,7 +29,6 @@ import ( "github.com/hashicorp/boundary/internal/types/scope" "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/go-secure-stdlib/strutil" - "github.com/hashicorp/nodeenrollment" "github.com/mitchellh/cli" "github.com/posener/complete" "go.uber.org/atomic" @@ -602,7 +601,7 @@ func (c *Command) Run(args []string) int { opts = append(opts, base.WithContainerImage(c.flagContainerImage)) } if err := c.CreateDevDatabase(c.Context, opts...); err != nil { - c.UI.Error(fmt.Errorf("Error creating dev database container %w", err).Error()) + c.UI.Error(fmt.Errorf("Error creating dev database container: %w", err).Error()) return base.CommandCliError } @@ -677,23 +676,22 @@ func (c *Command) Run(args []string) int { } if !c.flagUseEphemeralKmsWorkerAuthMethod { - if c.worker.NodeeKeyId == "" { - c.UI.Error("No worker key ID found at worker registration time") + req := c.worker.NodeeRegistrationRequest + if req == "" { + c.UI.Error("No worker registration request found at worker start time") return base.CommandCliError } - c.InfoKeys = append(c.InfoKeys, "worker key identifier") - c.Info["worker key identifier"] = c.worker.NodeeKeyId + c.InfoKeys = append(c.InfoKeys, "worker registration request") + c.Info["worker registration request"] = req + c.InfoKeys = append(c.InfoKeys, "worker current key id") + c.Info["worker current key id"] = c.worker.NodeeCurrentKeyId go func() { for { select { case <-c.Context.Done(): return case <-time.After(time.Second): - waitingNodes := nodeenrollment.DefaultRegistrationCache.Items() - if len(waitingNodes) == 0 { - continue - } - if err := c.controller.AuthorizeNodeeWorker(c.worker.NodeeKeyId); err != nil { + if err := c.controller.AuthorizeNodeeWorker(req); err != nil { c.UI.Error(fmt.Errorf("Error authorizing node: %w", err).Error()) errorEncountered.Store(true) return diff --git a/internal/cmd/commands/server/server.go b/internal/cmd/commands/server/server.go index ca2f182819..ca17036f44 100644 --- a/internal/cmd/commands/server/server.go +++ b/internal/cmd/commands/server/server.go @@ -464,8 +464,9 @@ func (c *Command) Run(args []string) int { return base.CommandCliError } if c.WorkerAuthKms == nil { - if c.worker.NodeeKeyId == "" { - retErr := fmt.Errorf("No worker key ID found at worker registration time") + req := c.worker.NodeeRegistrationRequest + if req == "" { + retErr := fmt.Errorf("No worker registration request found at worker startup time") if err := c.worker.Shutdown(); err != nil { c.UI.Error(retErr.Error()) retErr = fmt.Errorf("Error shutting down worker: %w", err) @@ -476,8 +477,10 @@ func (c *Command) Run(args []string) int { } return base.CommandCliError } - c.InfoKeys = append(c.InfoKeys, "worker key identifier") - c.Info["worker key identifier"] = c.worker.NodeeKeyId + c.InfoKeys = append(c.InfoKeys, "worker registration request") + c.Info["worker registration request"] = req + c.InfoKeys = append(c.InfoKeys, "worker current key id") + c.Info["worker current key id"] = c.worker.NodeeCurrentKeyId } } diff --git a/internal/daemon/cluster/handlers/multihop_service.go b/internal/daemon/cluster/handlers/multihop_service.go index ca1bde7620..2fe742f181 100644 --- a/internal/daemon/cluster/handlers/multihop_service.go +++ b/internal/daemon/cluster/handlers/multihop_service.go @@ -2,45 +2,81 @@ package handlers import ( "context" + "errors" "fmt" + "sync/atomic" - pbs "github.com/hashicorp/nodeenrollment/multihop" - "github.com/hashicorp/nodeenrollment/nodeauth" + "github.com/hashicorp/nodeenrollment" + "github.com/hashicorp/nodeenrollment/multihop" "github.com/hashicorp/nodeenrollment/registration" "github.com/hashicorp/nodeenrollment/tls" "github.com/hashicorp/nodeenrollment/types" + "github.com/hashicorp/nodeenrollment/util/temperror" ) type multihopServiceServer struct { - pbs.UnimplementedMultihopServiceServer + multihop.UnimplementedMultihopServiceServer - currentParams nodeauth.CurrentParameterFactory + storage nodeenrollment.Storage + direct bool + client *atomic.Value + options []nodeenrollment.Option } -func NewMultihopServiceServer( - currentParams nodeauth.CurrentParameterFactory, -) *multihopServiceServer { - return &multihopServiceServer{ - currentParams: currentParams, +func NewMultihopServiceServer(storage nodeenrollment.Storage, direct bool, client *atomic.Value, opt ...nodeenrollment.Option) (*multihopServiceServer, error) { + const op = "cluster.handlers.NewMultihopServiceServer" + + switch { + case direct && nodeenrollment.IsNil(storage): + return nil, fmt.Errorf("%s: running on controller and nil storage provided", op) + case !direct && client == nil: + return nil, fmt.Errorf("%s: running on worker and nil client provided", op) } + + return &multihopServiceServer{ + storage: storage, + direct: direct, + client: client, + options: opt, + }, nil } -var _ pbs.MultihopServiceServer = (*multihopServiceServer)(nil) +var _ multihop.MultihopServiceServer = (*multihopServiceServer)(nil) func (m *multihopServiceServer) FetchNodeCredentials(ctx context.Context, req *types.FetchNodeCredentialsRequest) (*types.FetchNodeCredentialsResponse, error) { - const op = "workers.(multihopServiceServer).FetchNodeCredentials" - _, storage, opt, err := m.currentParams() - if err != nil { - return nil, fmt.Errorf("%s: error getting current parameters: %w", op, err) + const op = "cluster.handlers.(multihopServiceServer).FetchNodeCredentials" + switch m.direct { + case true: + return registration.FetchNodeCredentials(ctx, m.storage, req, m.options...) + + default: + client := m.client.Load() + if client == nil { + return nil, fmt.Errorf("%s: error fetching multihop connection, client is nil", op) + } + multihopClient, ok := client.(multihop.MultihopServiceClient) + if !ok { + return nil, temperror.New(errors.New("client could not be understood as a multihop service client")) + } + return multihopClient.FetchNodeCredentials(ctx, req) } - return registration.FetchNodeCredentials(ctx, storage, req, opt...) } func (m *multihopServiceServer) GenerateServerCertificates(ctx context.Context, req *types.GenerateServerCertificatesRequest) (*types.GenerateServerCertificatesResponse, error) { - const op = "workers.(multihopServiceServer).GenerateServerCertificates" - _, storage, opt, err := m.currentParams() - if err != nil { - return nil, fmt.Errorf("%s: error getting current parameters: %w", op, err) + const op = "cluster.handlers.(multihopServiceServer).GenerateServerCertificates" + switch m.direct { + case true: + return tls.GenerateServerCertificates(ctx, m.storage, req, m.options...) + + default: + client := m.client.Load() + if client == nil { + return nil, fmt.Errorf("%s: error fetching multihop connection, client is nil", op) + } + multihopClient, ok := client.(multihop.MultihopServiceClient) + if !ok { + return nil, temperror.New(errors.New("client could not be understood as a multihop service client")) + } + return multihopClient.GenerateServerCertificates(ctx, req) } - return tls.GenerateServerCertificates(ctx, storage, req, opt...) } diff --git a/internal/daemon/controller/controller.go b/internal/daemon/controller/controller.go index a1da547a94..ae2955aedd 100644 --- a/internal/daemon/controller/controller.go +++ b/internal/daemon/controller/controller.go @@ -39,8 +39,11 @@ import ( "github.com/hashicorp/nodeenrollment/registration" "github.com/hashicorp/nodeenrollment/rotation" nodeefile "github.com/hashicorp/nodeenrollment/storage/file" + "github.com/hashicorp/nodeenrollment/types" + "github.com/mr-tron/base58" ua "go.uber.org/atomic" "google.golang.org/grpc" + "google.golang.org/protobuf/proto" ) type Controller struct { @@ -311,6 +314,7 @@ func (c *Controller) Start() error { event.WriteSysEvent(context.TODO(), op, "already started, skipping") return nil } + c.baseContext, c.baseCancel = context.WithCancel(context.Background()) var err error @@ -406,6 +410,16 @@ func (c *Controller) WorkerStatusUpdateTimes() *sync.Map { return c.workerStatusUpdateTimes } -func (c *Controller) AuthorizeNodeeWorker(keyId string) error { - return registration.AuthorizeNode(c.baseContext, c.NodeeFileStorage, keyId) +func (c *Controller) AuthorizeNodeeWorker(request string) error { + const op = "controller.(Controller).AuthorizeWorker" + reqBytes, err := base58.FastBase58Decoding(request) + if err != nil { + return fmt.Errorf("(%s) error base64-decoding fetch node creds next proto value", op) + } + // Decode the proto into the request + req := new(types.FetchNodeCredentialsRequest) + if err := proto.Unmarshal(reqBytes, req); err != nil { + return fmt.Errorf("(%s) error unmarshaling common name value: %w", op, err) + } + return registration.AuthorizeNode(c.baseContext, c.NodeeFileStorage, req) } diff --git a/internal/daemon/controller/handler.go b/internal/daemon/controller/handler.go index abdcfbbc40..d8ed85e48c 100644 --- a/internal/daemon/controller/handler.go +++ b/internal/daemon/controller/handler.go @@ -43,8 +43,6 @@ import ( "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/go-secure-stdlib/listenerutil" "github.com/hashicorp/go-secure-stdlib/strutil" - "github.com/hashicorp/nodeenrollment" - "github.com/hashicorp/nodeenrollment/types" "github.com/mr-tron/base58" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -568,34 +566,6 @@ func wrapHandlerWithCallbackInterceptor(h http.Handler, c *Controller) http.Hand func handleNodes(c *Controller) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { switch req.Method { - case http.MethodGet: - type vals struct { - WaitingNodes []string `json:"waiting_nodes"` - } - var err error - var currVals vals - waitingNodes := nodeenrollment.DefaultRegistrationCache.Items() - for keyId, val := range waitingNodes { - ni := val.(*types.NodeInformation) - if ni.Authorized { - continue - } - currVals.WaitingNodes = append(currVals.WaitingNodes, keyId) - } - ret, err := json.Marshal(currVals) - if err != nil { - _, _ = w.Write([]byte(err.Error())) - w.WriteHeader(500) - return - } - _, err = w.Write(ret) - if err != nil { - _, _ = w.Write([]byte(err.Error())) - w.WriteHeader(500) - return - } - w.WriteHeader(200) - return case http.MethodPost: body, err := io.ReadAll(req.Body) @@ -606,7 +576,7 @@ func handleNodes(c *Controller) http.Handler { return } type val struct { - KeyId string `json:"key_id"` + Request string `json:"request"` } var currVal val if err := json.Unmarshal(body, &currVal); err != nil { @@ -614,7 +584,7 @@ func handleNodes(c *Controller) http.Handler { w.WriteHeader(500) return } - if err := c.AuthorizeNodeeWorker(currVal.KeyId); err != nil { + if err := c.AuthorizeNodeeWorker(currVal.Request); err != nil { _, _ = w.Write([]byte(err.Error())) w.WriteHeader(500) return diff --git a/internal/daemon/controller/intercepting_listener.go b/internal/daemon/controller/intercepting_listener.go index cf97474d06..8d0d08c541 100644 --- a/internal/daemon/controller/intercepting_listener.go +++ b/internal/daemon/controller/intercepting_listener.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/boundary/internal/observability/event" nodee "github.com/hashicorp/nodeenrollment" - "github.com/hashicorp/nodeenrollment/nodeauth" ) // tempError is an error that satisfies the temporary error interface that is @@ -79,7 +78,7 @@ func (m *interceptingListener) Accept() (net.Conn, error) { tlsConn := conn.(*tls.Conn) switch { - case nodeauth.ContainsNodeAuthAlpnProto(tlsConn.ConnectionState().NegotiatedProtocol): + case nodee.ContainsKnownAlpnProto(tlsConn.ConnectionState().NegotiatedProtocol): keyId, err := nodee.KeyIdFromPkix(tlsConn.ConnectionState().PeerCertificates[0].SubjectKeyId) if err != nil { if err := conn.Close(); err != nil { diff --git a/internal/daemon/controller/listeners.go b/internal/daemon/controller/listeners.go index ddd53ed357..b4bd1046a6 100644 --- a/internal/daemon/controller/listeners.go +++ b/internal/daemon/controller/listeners.go @@ -17,9 +17,8 @@ import ( "github.com/hashicorp/boundary/internal/daemon/controller/internal/metric" pbs "github.com/hashicorp/boundary/internal/gen/controller/servers/services" "github.com/hashicorp/go-multierror" - nodee "github.com/hashicorp/nodeenrollment" "github.com/hashicorp/nodeenrollment/multihop" - "github.com/hashicorp/nodeenrollment/nodeauth" + "github.com/hashicorp/nodeenrollment/protocol" "google.golang.org/grpc" ) @@ -106,18 +105,16 @@ func (c *Controller) configureForApi(ln *base.ServerListener) ([]func(), error) } func (c *Controller) configureForCluster(ln *base.ServerListener) (func(), error) { - l, err := nodeauth.NewInterceptingListener( - ln.ClusterListener, - &tls.Config{ - GetConfigForClient: c.validateWorkerTls, - }, - nodeauth.MakeCurrentParametersFactory( - c.baseContext, - nodee.NopTransactionStorage(c.NodeeFileStorage), - ), - nil, - nil, - ) + const op = "controller.configureForCluster" + l, err := protocol.NewInterceptingListener( + &protocol.InterceptingListenerConfiguration{ + Context: c.baseContext, + Storage: c.NodeeFileStorage, + BaseListener: ln.ClusterListener, + BaseTlsConfiguration: &tls.Config{ + GetConfigForClient: c.validateWorkerTls, + }, + }) if err != nil { return nil, fmt.Errorf("error instantiating node auth listener: %w", err) } @@ -145,9 +142,14 @@ func (c *Controller) configureForCluster(ln *base.ServerListener) (func(), error pbs.RegisterServerCoordinationServiceServer(workerServer, workerService) pbs.RegisterSessionServiceServer(workerServer, workerService) - multihopService := handlers.NewMultihopServiceServer( - nodeauth.MakeCurrentParametersFactory(c.baseContext, nodee.NopTransactionStorage(c.NodeeFileStorage)), + multihopService, err := handlers.NewMultihopServiceServer( + c.NodeeFileStorage, + true, + nil, ) + if err != nil { + return nil, fmt.Errorf("%s: error creating multihop service handler: %w", op, err) + } multihop.RegisterMultihopServiceServer(workerServer, multihopService) metric.InitializeClusterCollectors(c.conf.PrometheusRegisterer, workerServer) diff --git a/internal/daemon/controller/listeners_test.go b/internal/daemon/controller/listeners_test.go index 30a3b769cd..db11192917 100644 --- a/internal/daemon/controller/listeners_test.go +++ b/internal/daemon/controller/listeners_test.go @@ -23,6 +23,7 @@ import ( "github.com/hashicorp/go-secure-stdlib/base62" "github.com/hashicorp/go-secure-stdlib/configutil/v2" "github.com/hashicorp/go-secure-stdlib/listenerutil" + nodeefile "github.com/hashicorp/nodeenrollment/storage/file" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/protobuf/proto" @@ -250,6 +251,9 @@ func TestStartListeners(t *testing.T) { c.baseContext = ctx c.baseCancel = cancel + c.NodeeFileStorage, err = nodeefile.NewFileStorage(c.baseContext) + require.NoError(t, err) + err = c.startListeners() require.NoError(t, err) diff --git a/internal/daemon/worker/controller_connection.go b/internal/daemon/worker/controller_connection.go index f235c82cc9..28dec4f0ca 100644 --- a/internal/daemon/worker/controller_connection.go +++ b/internal/daemon/worker/controller_connection.go @@ -23,9 +23,8 @@ import ( pbs "github.com/hashicorp/boundary/internal/gen/controller/servers/services" "github.com/hashicorp/boundary/internal/observability/event" "github.com/hashicorp/go-secure-stdlib/base62" - nodee "github.com/hashicorp/nodeenrollment" "github.com/hashicorp/nodeenrollment/multihop" - "github.com/hashicorp/nodeenrollment/nodeauth" + "github.com/hashicorp/nodeenrollment/protocol" "google.golang.org/grpc" "google.golang.org/grpc/backoff" "google.golang.org/grpc/credentials/insecure" @@ -74,11 +73,7 @@ func (w *Worker) controllerDialerFunc() func(context.Context, string) (net.Conn, case w.conf.WorkerAuthKms != nil: conn, err = w.v1KmsAuthDialFn(ctx, addr) default: - conn, err = nodeauth.AuthDialFn( - nodeauth.MakeCurrentParametersFactory( - ctx, - nodee.NopTransactionStorage(w.NodeeFileStorage), - ))(ctx, addr) + conn, err = protocol.Dial(ctx, w.NodeeFileStorage, addr) } if !w.everAuthenticated.Load() && err == nil && conn != nil { diff --git a/internal/daemon/worker/listeners.go b/internal/daemon/worker/listeners.go index 0da0f3a62e..ed98ac8431 100644 --- a/internal/daemon/worker/listeners.go +++ b/internal/daemon/worker/listeners.go @@ -19,8 +19,10 @@ import ( "github.com/hashicorp/go-multierror" nodee "github.com/hashicorp/nodeenrollment" "github.com/hashicorp/nodeenrollment/multihop" - "github.com/hashicorp/nodeenrollment/nodeauth" + "github.com/hashicorp/nodeenrollment/protocol" "github.com/hashicorp/nodeenrollment/types" + "github.com/hashicorp/nodeenrollment/util/splitlistener" + "github.com/hashicorp/nodeenrollment/util/temperror" "google.golang.org/grpc" ) @@ -50,6 +52,8 @@ func (w *Worker) startListeners() error { } func (w *Worker) configureForWorker(ln *base.ServerListener, logger *log.Logger) (func(), error) { + const op = "worker.configureForWorker" + handler, err := w.handler(HandlerProperties{ListenerConfig: ln.Config}) if err != nil { return nil, err @@ -88,12 +92,13 @@ func (w *Worker) configureForWorker(ln *base.ServerListener, logger *log.Logger) ) (*types.FetchNodeCredentialsResponse, error) { client := w.controllerMultihopConn.Load() if client == nil { - return nil, nodeauth.NewTempError(errors.New("error fetching controller connection, client is nil")) + return nil, temperror.New(errors.New("error fetching controller connection, client is nil")) } multihopClient, ok := client.(multihop.MultihopServiceClient) if !ok { - return nil, nodeauth.NewTempError(errors.New("client could not be understood as a multihop service client")) + return nil, temperror.New(errors.New("client could not be understood as a multihop service client")) } + // log.Println("proxying fetch node credentials request") return multihopClient.FetchNodeCredentials(ctx, req) } @@ -105,40 +110,45 @@ func (w *Worker) configureForWorker(ln *base.ServerListener, logger *log.Logger) ) (*types.GenerateServerCertificatesResponse, error) { client := w.controllerMultihopConn.Load() if client == nil { - return nil, nodeauth.NewTempError(errors.New("error fetching controller connection, client is nil")) + return nil, temperror.New(errors.New("error fetching controller connection, client is nil")) } multihopClient, ok := client.(multihop.MultihopServiceClient) if !ok { - return nil, nodeauth.NewTempError(errors.New("client could not be understood as a multihop service client")) + return nil, temperror.New(errors.New("client could not be understood as a multihop service client")) } + // log.Println("proxying generate server cert request") return multihopClient.GenerateServerCertificates(ctx, req) } - interceptingListener, err := nodeauth.NewInterceptingListener( - ln.ProxyListener, - &tls.Config{ - GetConfigForClient: w.getSessionTls, - }, - nodeauth.MakeCurrentParametersFactory( - w.baseContext, - nodee.NopTransactionStorage(w.NodeeFileStorage), - ), - fetchCredsFn, - generateServerCertificatesFn, - ) + interceptingListener, err := protocol.NewInterceptingListener( + &protocol.InterceptingListenerConfiguration{ + Context: w.baseContext, + Storage: w.NodeeFileStorage, + BaseListener: ln.ProxyListener, + BaseTlsConfiguration: &tls.Config{ + GetConfigForClient: w.getSessionTls, + }, + FetchCredsFunc: fetchCredsFn, + GenerateServerCertificatesFunc: generateServerCertificatesFn, + }) if err != nil { return nil, fmt.Errorf("error instantiating node auth listener: %w", err) } - w.nodeeTeeListener = nodeauth.NewTeeListener(interceptingListener) + w.nodeeSplitListener = splitlistener.New(interceptingListener) downstreamServer := grpc.NewServer( grpc.MaxRecvMsgSize(math.MaxInt32), grpc.MaxSendMsgSize(math.MaxInt32), ) - multihopService := handlers.NewMultihopServiceServer( - nodeauth.MakeCurrentParametersFactory(w.baseContext, nodee.NopTransactionStorage(w.NodeeFileStorage)), + multihopService, err := handlers.NewMultihopServiceServer( + w.NodeeFileStorage, + false, + w.controllerMultihopConn, ) + if err != nil { + return nil, fmt.Errorf("%s: error creating multihop service handler: %w", op, err) + } multihop.RegisterMultihopServiceServer(downstreamServer, multihopService) statusSessionService := NewWorkerProxyServiceServer(w.controllerStatusConn, w.controllerSessionConn) pbs.RegisterServerCoordinationServiceServer(downstreamServer, statusSessionService) @@ -147,9 +157,9 @@ func (w *Worker) configureForWorker(ln *base.ServerListener, logger *log.Logger) ln.GrpcServer = downstreamServer return func() { - go w.nodeeTeeListener.Start() - go httpServer.Serve(w.nodeeTeeListener.OtherListener()) - go ln.GrpcServer.Serve(w.nodeeTeeListener.NodeeListener()) + go w.nodeeSplitListener.Start() + go httpServer.Serve(w.nodeeSplitListener.OtherListener()) + go ln.GrpcServer.Serve(w.nodeeSplitListener.NodeEnrollmentListener()) }, nil } @@ -162,21 +172,21 @@ func (w *Worker) stopServersAndListeners() error { // really likes to hang on closing. Maybe because it's never served a // connection? This is a workaround to force it until I can dig in. var cancel context.CancelFunc - if w.nodeeTeeListener != nil { + if w.nodeeSplitListener != nil { var ctx context.Context ctx, cancel = context.WithTimeout(w.baseContext, 2*time.Second) go func() { <-ctx.Done() - w.nodeeTeeListener.Stop() + w.nodeeSplitListener.Stop() cancel() }() } stopErrors := mg.Wait() - if w.nodeeTeeListener != nil { + if w.nodeeSplitListener != nil { cancel() - err := w.nodeeTeeListener.Stop() + err := w.nodeeSplitListener.Stop() if err != nil { stopErrors = multierror.Append(stopErrors, err) } @@ -227,8 +237,8 @@ func (w *Worker) stopAnyListeners() error { } var closeErrors *multierror.Error var err error - if w.nodeeTeeListener != nil { - err = w.nodeeTeeListener.Stop() + if w.nodeeSplitListener != nil { + err = w.nodeeSplitListener.Stop() } else if w.proxyListener.ProxyListener != nil { err = w.proxyListener.ProxyListener.Close() } diff --git a/internal/daemon/worker/worker.go b/internal/daemon/worker/worker.go index 182c7832b4..7da2e46cb8 100644 --- a/internal/daemon/worker/worker.go +++ b/internal/daemon/worker/worker.go @@ -15,6 +15,8 @@ import ( "time" "github.com/hashicorp/boundary/internal/servers" + "github.com/hashicorp/nodeenrollment" + "github.com/mr-tron/base58" "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/cmd/base" @@ -26,13 +28,13 @@ import ( "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-secure-stdlib/base62" "github.com/hashicorp/go-secure-stdlib/mlock" - nodee "github.com/hashicorp/nodeenrollment" - "github.com/hashicorp/nodeenrollment/nodeauth" nodeefile "github.com/hashicorp/nodeenrollment/storage/file" "github.com/hashicorp/nodeenrollment/types" + "github.com/hashicorp/nodeenrollment/util/splitlistener" ua "go.uber.org/atomic" "google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver/manual" + "google.golang.org/protobuf/proto" ) type randFn func(length int) (string, error) @@ -73,9 +75,10 @@ type Worker struct { updateTags *ua.Bool // PoC: Testing bits for BYOW - NodeeFileStorage *nodeefile.FileStorage - NodeeKeyId string - nodeeTeeListener *nodeauth.TeeListener + NodeeFileStorage *nodeefile.FileStorage + NodeeCurrentKeyId string + NodeeRegistrationRequest string + nodeeSplitListener *splitlistener.SplitListener // Test-specific options TestOverrideX509VerifyDnsName string @@ -190,7 +193,20 @@ func (w *Worker) Start() error { if err != nil { return fmt.Errorf("error generating new node creds: %w", err) } - w.NodeeKeyId, err = nodee.KeyIdFromPkix(nodeCreds.CertificatePublicKeyPkix) + + req, err := nodeCreds.CreateFetchNodeCredentialsRequest(w.baseContext) + if err != nil { + return fmt.Errorf("error creating fetch credentials request: %w", err) + } + reqBytes, err := proto.Marshal(req) + if err != nil { + return fmt.Errorf("error marshaling fetch credentials request: %w", err) + } + w.NodeeRegistrationRequest = base58.FastBase58Encoding(reqBytes) + if err != nil { + return fmt.Errorf("error encoding registration request: %w", err) + } + w.NodeeCurrentKeyId, err = nodeenrollment.KeyIdFromPkix(nodeCreds.CertificatePublicKeyPkix) if err != nil { return fmt.Errorf("error deriving key id: %w", err) }