From d8baa4390380f649d809f6f673c378a9d942e38b Mon Sep 17 00:00:00 2001 From: Margo Crawford Date: Mon, 29 Mar 2021 09:30:20 -0700 Subject: [PATCH] Add new non-idle timeout integration test for impersonation proxy Signed-off-by: Ryan Richard --- .../concierge_impersonation_proxy_test.go | 90 +++++++++++++++---- 1 file changed, 73 insertions(+), 17 deletions(-) diff --git a/test/integration/concierge_impersonation_proxy_test.go b/test/integration/concierge_impersonation_proxy_test.go index 2938c08f..fee7e4df 100644 --- a/test/integration/concierge_impersonation_proxy_test.go +++ b/test/integration/concierge_impersonation_proxy_test.go @@ -316,7 +316,64 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl ) } - t.Run("kubectl port-forward and keeping the connection open for over a minute", func(t *testing.T) { + t.Run("kubectl port-forward and keeping the connection open for over a minute (non-idle)", func(t *testing.T) { + kubeconfigPath, envVarsWithProxy, _ := getImpersonationKubeconfig(t, env, impersonationProxyURL, impersonationProxyCACertPEM, credentialRequestSpecWithWorkingCredentials.Authenticator) + + // Run the kubectl port-forward command. + timeout, cancelFunc := context.WithTimeout(ctx, 2*time.Minute) + defer cancelFunc() + portForwardCmd, _, portForwardStderr := kubectlCommand(timeout, t, kubeconfigPath, envVarsWithProxy, "port-forward", "--namespace", env.ConciergeNamespace, conciergePod.Name, "8443:8443") + portForwardCmd.Env = envVarsWithProxy + + // Start, but don't wait for the command to finish. + err := portForwardCmd.Start() + require.NoError(t, err, `"kubectl port-forward" failed`) + go func() { + assert.EqualErrorf(t, portForwardCmd.Wait(), "signal: killed", `wanted "kubectl port-forward" to get signaled because context was cancelled (stderr: %q)`, portForwardStderr.String()) + }() + + // The server should recognize this this + // is going to be a long-running command and keep the connection open as long as the client stays connected. + + // curl the endpoint as many times as we can within 70 seconds. + // this will ensure that we don't run into idle timeouts. + var curlStdOut, curlStdErr bytes.Buffer + timeout, cancelFunc = context.WithTimeout(ctx, 75*time.Second) + defer cancelFunc() + startTime := time.Now() + for time.Now().Before(startTime.Add(70 * time.Second)) { + curlCmd := exec.CommandContext(timeout, "curl", "-k", "-sS", "https://127.0.0.1:8443") // -sS turns off the progressbar but still prints errors + curlCmd.Stdout = &curlStdOut + curlCmd.Stderr = &curlStdErr + curlErr := curlCmd.Run() + if curlErr != nil { + t.Log("curl error: " + curlErr.Error()) + t.Log("curlStdErr: " + curlStdErr.String()) + t.Log("stdout: " + curlStdOut.String()) + } + t.Log("time: ", time.Now()) + time.Sleep(1 * time.Second) + } + + // curl the endpoint once more, once 70 seconds has elapsed, to make sure the connection is still open. + timeout, cancelFunc = context.WithTimeout(ctx, 30*time.Second) + defer cancelFunc() + curlCmd := exec.CommandContext(timeout, "curl", "-k", "-sS", "https://127.0.0.1:8443") // -sS turns off the progressbar but still prints errors + curlCmd.Stdout = &curlStdOut + curlCmd.Stderr = &curlStdErr + curlErr := curlCmd.Run() + + if curlErr != nil { + t.Log("curl error: " + curlErr.Error()) + t.Log("curlStdErr: " + curlStdErr.String()) + t.Log("stdout: " + curlStdOut.String()) + } + // We expect this to 403, but all we care is that it gets through. + require.NoError(t, curlErr) + require.Contains(t, curlStdOut.String(), "\"forbidden: User \\\"system:anonymous\\\" cannot get path \\\"/\\\"\"") + }) + + t.Run("kubectl port-forward and keeping the connection open for over a minute (idle)", func(t *testing.T) { kubeconfigPath, envVarsWithProxy, _ := getImpersonationKubeconfig(t, env, impersonationProxyURL, impersonationProxyCACertPEM, credentialRequestSpecWithWorkingCredentials.Authenticator) // Run the kubectl port-forward command. @@ -336,22 +393,21 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl // is going to be a long-running command and keep the connection open as long as the client stays connected. time.Sleep(70 * time.Second) - require.Eventually(t, func() bool { - timeout, cancelFunc = context.WithTimeout(ctx, 2*time.Minute) - defer cancelFunc() - curlCmd := exec.CommandContext(timeout, "curl", "-k", "-sS", "https://127.0.0.1:8443") // -sS turns off the progressbar but still prints errors - var curlStdOut, curlStdErr bytes.Buffer - curlCmd.Stdout = &curlStdOut - curlCmd.Stderr = &curlStdErr - err = curlCmd.Run() - if err != nil { - t.Log("curl error: " + err.Error()) - t.Log("curlStdErr: " + curlStdErr.String()) - t.Log("stdout: " + curlStdOut.String()) - } - // We expect this to 403, but all we care is that it gets through. - return err == nil && strings.Contains(curlStdOut.String(), "\"forbidden: User \\\"system:anonymous\\\" cannot get path \\\"/\\\"\"") - }, 1*time.Minute, 500*time.Millisecond) + timeout, cancelFunc = context.WithTimeout(ctx, 2*time.Minute) + defer cancelFunc() + curlCmd := exec.CommandContext(timeout, "curl", "-k", "-sS", "https://127.0.0.1:8443") // -sS turns off the progressbar but still prints errors + var curlStdOut, curlStdErr bytes.Buffer + curlCmd.Stdout = &curlStdOut + curlCmd.Stderr = &curlStdErr + err = curlCmd.Run() + if err != nil { + t.Log("curl error: " + err.Error()) + t.Log("curlStdErr: " + curlStdErr.String()) + t.Log("stdout: " + curlStdOut.String()) + } + // We expect this to 403, but all we care is that it gets through. + require.NoError(t, err) + require.Contains(t, curlStdOut.String(), "\"forbidden: User \\\"system:anonymous\\\" cannot get path \\\"/\\\"\"") }) t.Run("using and watching all the basic verbs", func(t *testing.T) {