diff --git a/command/agent.go b/command/agent.go index 4afeefd3a5..bf153c8529 100644 --- a/command/agent.go +++ b/command/agent.go @@ -729,7 +729,12 @@ func (c *AgentCommand) Run(args []string) int { proxyVaultToken = !config.APIProxy.ForceAutoAuthToken } - muxHandler := cache.ProxyHandler(ctx, apiProxyLogger, apiProxy, inmemSink, proxyVaultToken) + var muxHandler http.Handler + if leaseCache != nil { + muxHandler = cache.ProxyHandler(ctx, apiProxyLogger, leaseCache, inmemSink, proxyVaultToken) + } else { + muxHandler = cache.ProxyHandler(ctx, apiProxyLogger, apiProxy, inmemSink, proxyVaultToken) + } // Parse 'require_request_header' listener config option, and wrap // the request handler if necessary diff --git a/command/agent_test.go b/command/agent_test.go index e9d737628b..9cf4b47048 100644 --- a/command/agent_test.go +++ b/command/agent_test.go @@ -5,7 +5,7 @@ import ( "crypto/x509" "encoding/json" "fmt" - "io/ioutil" + "io" "net" "net/http" "os" @@ -146,7 +146,7 @@ func testAgentExitAfterAuth(t *testing.T, viaFlag bool) { t.Fatal(err) } - inf, err := ioutil.TempFile("", "auth.jwt.test.") + inf, err := os.CreateTemp("", "auth.jwt.test.") if err != nil { t.Fatal(err) } @@ -155,7 +155,7 @@ func testAgentExitAfterAuth(t *testing.T, viaFlag bool) { os.Remove(in) t.Logf("input: %s", in) - sink1f, err := ioutil.TempFile("", "sink1.jwt.test.") + sink1f, err := os.CreateTemp("", "sink1.jwt.test.") if err != nil { t.Fatal(err) } @@ -164,7 +164,7 @@ func testAgentExitAfterAuth(t *testing.T, viaFlag bool) { os.Remove(sink1) t.Logf("sink1: %s", sink1) - sink2f, err := ioutil.TempFile("", "sink2.jwt.test.") + sink2f, err := os.CreateTemp("", "sink2.jwt.test.") if err != nil { t.Fatal(err) } @@ -173,7 +173,7 @@ func testAgentExitAfterAuth(t *testing.T, viaFlag bool) { os.Remove(sink2) t.Logf("sink2: %s", sink2) - conff, err := ioutil.TempFile("", "conf.jwt.test.") + conff, err := os.CreateTemp("", "conf.jwt.test.") if err != nil { t.Fatal(err) } @@ -183,7 +183,7 @@ func testAgentExitAfterAuth(t *testing.T, viaFlag bool) { t.Logf("config: %s", conf) jwtToken, _ := agent.GetTestJWT(t) - if err := ioutil.WriteFile(in, []byte(jwtToken), 0o600); err != nil { + if err := os.WriteFile(in, []byte(jwtToken), 0o600); err != nil { t.Fatal(err) } else { logger.Trace("wrote test jwt", "path", in) @@ -222,7 +222,7 @@ auto_auth { ` config = fmt.Sprintf(config, exitAfterAuthTemplText, in, sink1, sink2) - if err := ioutil.WriteFile(conf, []byte(config), 0o600); err != nil { + if err := os.WriteFile(conf, []byte(config), 0o600); err != nil { t.Fatal(err) } else { logger.Trace("wrote test config", "path", conf) @@ -254,7 +254,7 @@ auto_auth { t.Fatal("timeout reached while waiting for agent to exit") } - sink1Bytes, err := ioutil.ReadFile(sink1) + sink1Bytes, err := os.ReadFile(sink1) if err != nil { t.Fatal(err) } @@ -262,7 +262,7 @@ auto_auth { t.Fatal("got no output from sink 1") } - sink2Bytes, err := ioutil.ReadFile(sink2) + sink2Bytes, err := os.ReadFile(sink2) if err != nil { t.Fatal(err) } @@ -612,7 +612,7 @@ func TestAgent_Template_Basic(t *testing.T) { // make a temp directory to hold renders. Each test will create a temp dir // inside this one - tmpDirRoot, err := ioutil.TempDir("", "agent-test-renders") + tmpDirRoot, err := os.MkdirTemp("", "agent-test-renders") if err != nil { t.Fatal(err) } @@ -642,7 +642,7 @@ func TestAgent_Template_Basic(t *testing.T) { for tcname, tc := range testCases { t.Run(tcname, func(t *testing.T) { // create temp dir for this test run - tmpDir, err := ioutil.TempDir(tmpDirRoot, tcname) + tmpDir, err := os.MkdirTemp(tmpDirRoot, tcname) if err != nil { t.Fatal(err) } @@ -651,7 +651,7 @@ func TestAgent_Template_Basic(t *testing.T) { var templatePaths []string for i := 0; i < tc.templateCount; i++ { fileName := filepath.Join(tmpDir, fmt.Sprintf("render_%d.tmpl", i)) - if err := ioutil.WriteFile(fileName, []byte(templateContents(i)), 0o600); err != nil { + if err := os.WriteFile(fileName, []byte(templateContents(i)), 0o600); err != nil { t.Fatal(err) } templatePaths = append(templatePaths, fileName) @@ -765,7 +765,7 @@ auto_auth { for i := range templatePaths { fileName := filepath.Join(tmpDir, fmt.Sprintf("render_%d.json", i)) var c []byte - c, err = ioutil.ReadFile(fileName) + c, err = os.ReadFile(fileName) if err != nil { continue } @@ -782,7 +782,7 @@ auto_auth { for i := 0; i < tc.templateCount; i++ { fileName := filepath.Join(tmpDir, fmt.Sprintf("render_%d.tmpl", i)) - if err := ioutil.WriteFile(fileName, []byte(templateContents(i)+"{}"), 0o600); err != nil { + if err := os.WriteFile(fileName, []byte(templateContents(i)+"{}"), 0o600); err != nil { t.Fatal(err) } } @@ -795,7 +795,7 @@ auto_auth { func testListFiles(t *testing.T, dir, extension string) int { t.Helper() - files, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) if err != nil { t.Fatal(err) } @@ -925,14 +925,14 @@ func TestAgent_Template_ExitCounter(t *testing.T) { // make a temp directory to hold renders. Each test will create a temp dir // inside this one - tmpDirRoot, err := ioutil.TempDir("", "agent-test-renders") + tmpDirRoot, err := os.MkdirTemp("", "agent-test-renders") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpDirRoot) // create temp dir for this test run - tmpDir, err := ioutil.TempDir(tmpDirRoot, "agent-test") + tmpDir, err := os.MkdirTemp(tmpDirRoot, "agent-test") if err != nil { t.Fatal(err) } @@ -1014,7 +1014,7 @@ exit_after_auth = true // Perform the tests //---------------------------------------------------- - files, err := ioutil.ReadDir(tmpDir) + files, err := os.ReadDir(tmpDir) if err != nil { t.Fatal(err) } @@ -1077,7 +1077,7 @@ func request(t *testing.T, client *api.Client, req *api.Request, expectedStatusC t.Fatalf("expected status code %d, not %d", expectedStatusCode, resp.StatusCode) } - bytes, err := ioutil.ReadAll(resp.Body) + bytes, err := io.ReadAll(resp.Body) if err != nil { t.Fatalf("err: %s", err) } @@ -1096,7 +1096,7 @@ func request(t *testing.T, client *api.Client, req *api.Request, expectedStatusC // makeTempFile creates a temp file and populates it. func makeTempFile(t *testing.T, name, contents string) string { t.Helper() - f, err := ioutil.TempFile("", name) + f, err := os.CreateTemp("", name) if err != nil { t.Fatal(err) } @@ -1211,7 +1211,7 @@ func TestAgent_Template_Retry(t *testing.T) { // make a temp directory to hold renders. Each test will create a temp dir // inside this one - tmpDirRoot, err := ioutil.TempDir("", "agent-test-renders") + tmpDirRoot, err := os.MkdirTemp("", "agent-test-renders") if err != nil { t.Fatal(err) } @@ -1259,14 +1259,14 @@ func TestAgent_Template_Retry(t *testing.T) { h.failCount = 6 // create temp dir for this test run - tmpDir, err := ioutil.TempDir(tmpDirRoot, tcname) + tmpDir, err := os.MkdirTemp(tmpDirRoot, tcname) if err != nil { t.Fatal(err) } // make some template files templatePath := filepath.Join(tmpDir, "render_0.tmpl") - if err := ioutil.WriteFile(templatePath, []byte(templateContents(0)), 0o600); err != nil { + if err := os.WriteFile(templatePath, []byte(templateContents(0)), 0o600); err != nil { t.Fatal(err) } templateConfig := fmt.Sprintf(templateConfigString, templatePath, tmpDir, "render_0.json") @@ -1340,7 +1340,7 @@ template_config { fileName := filepath.Join(tmpDir, "render_0.json") var c []byte - c, err = ioutil.ReadFile(fileName) + c, err = os.ReadFile(fileName) if err != nil { continue } @@ -1438,7 +1438,112 @@ auto_auth { return config, cleanup } -func TestAgent_Cache_Retry(t *testing.T) { +func TestAgent_Cache_DynamicSecret(t *testing.T) { + logger := logging.NewVaultLogger(hclog.Trace) + cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{ + HandlerFunc: vaulthttp.Handler, + }) + cluster.Start() + defer cluster.Cleanup() + + serverClient := cluster.Cores[0].Client + + // Unset the environment variable so that agent picks up the right test + // cluster address + defer os.Setenv(api.EnvVaultAddress, os.Getenv(api.EnvVaultAddress)) + os.Unsetenv(api.EnvVaultAddress) + + cacheConfig := ` +cache { +} +` + listenAddr := generateListenerAddress(t) + listenConfig := fmt.Sprintf(` +listener "tcp" { + address = "%s" + tls_disable = true +} +`, listenAddr) + + config := fmt.Sprintf(` +vault { + address = "%s" + tls_skip_verify = true +} +%s +%s +`, serverClient.Address(), cacheConfig, listenConfig) + configPath := makeTempFile(t, "config.hcl", config) + defer os.Remove(configPath) + + // Start the agent + _, cmd := testAgentCommand(t, logger) + cmd.startedCh = make(chan struct{}) + + wg := &sync.WaitGroup{} + wg.Add(1) + go func() { + cmd.Run([]string{"-config", configPath}) + wg.Done() + }() + + select { + case <-cmd.startedCh: + case <-time.After(5 * time.Second): + t.Errorf("timeout") + } + + agentClient, err := api.NewClient(api.DefaultConfig()) + if err != nil { + t.Fatal(err) + } + agentClient.SetToken(serverClient.Token()) + agentClient.SetMaxRetries(0) + err = agentClient.SetAddress("http://" + listenAddr) + if err != nil { + t.Fatal(err) + } + + renewable := true + tokenCreateRequest := &api.TokenCreateRequest{ + Policies: []string{"default"}, + TTL: "30m", + Renewable: &renewable, + } + + // This was the simplest test I could find to trigger the caching behaviour, + // i.e. the most concise I could make the test that I can tell + // creating an orphan token returns Auth, is renewable, and isn't a token + // that's managed elsewhere (since it's an orphan) + secret, err := agentClient.Auth().Token().CreateOrphan(tokenCreateRequest) + if err != nil { + t.Fatal(err) + } + if secret == nil || secret.Auth == nil { + t.Fatalf("secret not as expected: %v", secret) + } + + token := secret.Auth.ClientToken + + secret, err = agentClient.Auth().Token().CreateOrphan(tokenCreateRequest) + if err != nil { + t.Fatal(err) + } + if secret == nil || secret.Auth == nil { + t.Fatalf("secret not as expected: %v", secret) + } + + token2 := secret.Auth.ClientToken + + if token != token2 { + t.Fatalf("token create response not cached when it should have been, as tokens differ") + } + + close(cmd.ShutdownCh) + wg.Wait() +} + +func TestAgent_ApiProxy_Retry(t *testing.T) { //---------------------------------------------------- // Start the server and agent //---------------------------------------------------- @@ -1646,7 +1751,7 @@ func TestAgent_TemplateConfig_ExitOnRetryFailure(t *testing.T) { // make a temp directory to hold renders. Each test will create a temp dir // inside this one - tmpDirRoot, err := ioutil.TempDir("", "agent-test-renders") + tmpDirRoot, err := os.MkdirTemp("", "agent-test-renders") if err != nil { t.Fatal(err) } @@ -1750,7 +1855,7 @@ func TestAgent_TemplateConfig_ExitOnRetryFailure(t *testing.T) { for tcName, tc := range testCases { t.Run(tcName, func(t *testing.T) { // create temp dir for this test run - tmpDir, err := ioutil.TempDir(tmpDirRoot, tcName) + tmpDir, err := os.MkdirTemp(tmpDirRoot, tcName) if err != nil { t.Fatal(err) } @@ -1859,7 +1964,7 @@ vault { fileName := filepath.Join(tmpDir, "render_0.json") var c []byte - c, err = ioutil.ReadFile(fileName) + c, err = os.ReadFile(fileName) if err != nil { continue }