From f5c5035fde01f88e5aaaf4b7305ac1ccbe5a4a2e Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Thu, 19 Oct 2023 16:50:38 -0400 Subject: [PATCH] testutil: add ACL bootstrapping to test server configuration (#18811) Some of our `api` package tests have ACLs enabled, but none of those tests also run clients and the "wait for the clients to be live" code reads from the Node API. The caller can't bootstrap ACLs until `NewTestServer` returns, and this makes for a circular dependency. Allow developers to provide a bootstrap token to the test server config, and if it's available, have the server bootstrap the ACL system with it before checking for live clients. --- testutil/server.go | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/testutil/server.go b/testutil/server.go index 72a0664f2..9bb9e7c14 100644 --- a/testutil/server.go +++ b/testutil/server.go @@ -93,7 +93,8 @@ type VaultConfig struct { // ACLConfig is used to configure ACLs type ACLConfig struct { - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled"` + BootstrapToken string `json:"-"` // not in the real config } // ServerConfigCallback is a function interface which can be @@ -195,6 +196,7 @@ func NewTestServer(t testing.T, cb ServerConfigCallback) *TestServer { if nomadConfig.Stderr != nil { stderr = nomadConfig.Stderr } + t.Logf("CONFIG JSON: %s", string(configContent)) args := []string{"agent", "-config", configFile.Name()} if nomadConfig.DevMode { @@ -228,6 +230,10 @@ func NewTestServer(t testing.T, cb ServerConfigCallback) *TestServer { server.waitForAPI() } + if nomadConfig.ACL.Enabled && nomadConfig.ACL.BootstrapToken != "" { + server.bootstrapSelf() + } + // Wait for the client to be ready if nomadConfig.DevMode { server.waitForClient() @@ -272,6 +278,28 @@ func (s *TestServer) Stop() { } +// bootstrapSelf bootstraps the ACL system from the provided token. +func (s *TestServer) bootstrapSelf() { + + contentType := "application/json" + + rootToken := s.Config.ACL.BootstrapToken + body := struct{ BootstrapSecret string }{rootToken} + buf, err := json.Marshal(body) + if err != nil { + s.t.Fatalf("err: %s", err) + } + + resp, err := s.HTTPClient.Post(s.url("/v1/acl/bootstrap"), contentType, bytes.NewBuffer(buf)) + if err != nil { + s.t.Fatalf("err: %s", err) + } + defer resp.Body.Close() + if err := s.requireOK(resp); err != nil { + s.t.Fatalf("err: %s", err) + } +} + // waitForAPI waits for only the agent HTTP endpoint to start // responding. This is an indication that the agent has started, // but will likely return before a leader is elected. @@ -324,7 +352,14 @@ func (s *TestServer) waitForClient() { } WaitForResult(func() (bool, error) { - resp, err := s.HTTPClient.Get(s.url("/v1/nodes")) + req, err := http.NewRequest(http.MethodGet, s.url("/v1/nodes"), nil) + if err != nil { + return false, err + } + if s.Config.ACL.BootstrapToken != "" { + req.Header.Set("X-Nomad-Token", s.Config.ACL.BootstrapToken) + } + resp, err := s.HTTPClient.Do(req) if err != nil { return false, err }