Fix bad test package name
Signed-off-by: Monis Khan <mok@vmware.com>
This commit is contained in:
parent
1929b47dda
commit
d78b845575
@ -16,13 +16,13 @@ import (
|
|||||||
|
|
||||||
"go.pinniped.dev/internal/controllerlib/test/integration/examplecontroller/api"
|
"go.pinniped.dev/internal/controllerlib/test/integration/examplecontroller/api"
|
||||||
examplestart "go.pinniped.dev/internal/controllerlib/test/integration/examplecontroller/starter"
|
examplestart "go.pinniped.dev/internal/controllerlib/test/integration/examplecontroller/starter"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExampleController(t *testing.T) {
|
func TestExampleController(t *testing.T) {
|
||||||
library.SkipUnlessIntegration(t)
|
testlib.SkipUnlessIntegration(t)
|
||||||
|
|
||||||
config := library.NewClientConfig(t)
|
config := testlib.NewClientConfig(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -93,7 +93,7 @@ done:
|
|||||||
expectedData := map[string][]byte{
|
expectedData := map[string][]byte{
|
||||||
api.SecretDataKey: []byte(secretData),
|
api.SecretDataKey: []byte(secretData),
|
||||||
}
|
}
|
||||||
require.Equal(t, expectedData, secret.Data, "expected to see new secret data: %s", library.Sdump(secret))
|
require.Equal(t, expectedData, secret.Data, "expected to see new secret data: %s", testlib.Sdump(secret))
|
||||||
break done // immediately stop consuming events because we want to check for updated events below
|
break done // immediately stop consuming events because we want to check for updated events below
|
||||||
|
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
@ -132,7 +132,7 @@ done2:
|
|||||||
expectedData := map[string][]byte{
|
expectedData := map[string][]byte{
|
||||||
api.SecretDataKey: []byte(secretData2),
|
api.SecretDataKey: []byte(secretData2),
|
||||||
}
|
}
|
||||||
require.Equal(t, expectedData, secret.Data, "expected to see updated secret data: %s", library.Sdump(secret))
|
require.Equal(t, expectedData, secret.Data, "expected to see updated secret data: %s", testlib.Sdump(secret))
|
||||||
break done2 // immediately stop consuming events because we want to check for hot loops below
|
break done2 // immediately stop consuming events because we want to check for hot loops below
|
||||||
|
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
@ -154,7 +154,7 @@ done3:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this assumes that no other actor in the system is trying to mutate this secret
|
// this assumes that no other actor in the system is trying to mutate this secret
|
||||||
t.Errorf("unexpected event seen for secret: %s", library.Sdump(event))
|
t.Errorf("unexpected event seen for secret: %s", testlib.Sdump(event))
|
||||||
|
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
break done3 // we saw no events matching our secret meaning that we are not hot looping
|
break done3 // we saw no events matching our secret meaning that we are not hot looping
|
||||||
|
@ -18,7 +18,7 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/storage/names"
|
"k8s.io/apiserver/pkg/storage/names"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/certauthority"
|
"go.pinniped.dev/internal/certauthority"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestProviderWithDynamicServingCertificateController(t *testing.T) {
|
func TestProviderWithDynamicServingCertificateController(t *testing.T) {
|
||||||
@ -205,12 +205,12 @@ func TestProviderWithDynamicServingCertificateController(t *testing.T) {
|
|||||||
if err != nil && lastTLSConfig != nil {
|
if err != nil && lastTLSConfig != nil {
|
||||||
// for debugging failures
|
// for debugging failures
|
||||||
t.Log("diff between client CAs:\n", cmp.Diff(
|
t.Log("diff between client CAs:\n", cmp.Diff(
|
||||||
library.Sdump(wantClientCASubjects),
|
testlib.Sdump(wantClientCASubjects),
|
||||||
library.Sdump(poolSubjects(lastTLSConfig.ClientCAs)),
|
testlib.Sdump(poolSubjects(lastTLSConfig.ClientCAs)),
|
||||||
))
|
))
|
||||||
t.Log("diff between serving certs:\n", cmp.Diff(
|
t.Log("diff between serving certs:\n", cmp.Diff(
|
||||||
library.Sdump(wantCerts),
|
testlib.Sdump(wantCerts),
|
||||||
library.Sdump(lastTLSConfig.Certificates),
|
testlib.Sdump(lastTLSConfig.Certificates),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -12,13 +12,13 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runTestKubectlCommand(t *testing.T, args ...string) (string, string) {
|
func runTestKubectlCommand(t *testing.T, args ...string) (string, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
var stdOut, stdErr bytes.Buffer
|
var stdOut, stdErr bytes.Buffer
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
stdOut.Reset()
|
stdOut.Reset()
|
||||||
stdErr.Reset()
|
stdErr.Reset()
|
||||||
cmd := exec.Command("kubectl", args...)
|
cmd := exec.Command("kubectl", args...)
|
||||||
@ -47,7 +47,7 @@ func requireCleanKubectlStderr(t *testing.T, stderr string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetPinnipedCategory(t *testing.T) {
|
func TestGetPinnipedCategory(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
dotSuffix := "." + env.APIGroupSuffix
|
dotSuffix := "." + env.APIGroupSuffix
|
||||||
|
|
||||||
t.Run("category, no special params", func(t *testing.T) {
|
t.Run("category, no special params", func(t *testing.T) {
|
||||||
|
@ -33,21 +33,21 @@ import (
|
|||||||
"go.pinniped.dev/internal/testutil"
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/pkg/oidcclient"
|
"go.pinniped.dev/pkg/oidcclient"
|
||||||
"go.pinniped.dev/pkg/oidcclient/filesession"
|
"go.pinniped.dev/pkg/oidcclient/filesession"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
"go.pinniped.dev/test/library/browsertest"
|
"go.pinniped.dev/test/testlib/browsertest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCLIGetKubeconfigStaticToken(t *testing.T) {
|
func TestCLIGetKubeconfigStaticToken(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
|
env := testlib.IntegrationEnv(t).WithCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
|
|
||||||
// Create a test webhook configuration to use with the CLI.
|
// Create a test webhook configuration to use with the CLI.
|
||||||
ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancelFunc()
|
defer cancelFunc()
|
||||||
|
|
||||||
authenticator := library.CreateTestWebhookAuthenticator(ctx, t)
|
authenticator := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||||
|
|
||||||
// Build pinniped CLI.
|
// Build pinniped CLI.
|
||||||
pinnipedExe := library.PinnipedCLIPath(t)
|
pinnipedExe := testlib.PinnipedCLIPath(t)
|
||||||
|
|
||||||
credCacheDir := testutil.TempDir(t)
|
credCacheDir := testutil.TempDir(t)
|
||||||
stdout, stderr := runPinnipedCLI(t, nil, pinnipedExe, "get", "kubeconfig",
|
stdout, stderr := runPinnipedCLI(t, nil, pinnipedExe, "get", "kubeconfig",
|
||||||
@ -63,7 +63,7 @@ func TestCLIGetKubeconfigStaticToken(t *testing.T) {
|
|||||||
assert.Contains(t, stderr, "validated connection to the cluster")
|
assert.Contains(t, stderr, "validated connection to the cluster")
|
||||||
|
|
||||||
// Even the deprecated command should now generate a kubeconfig with the new "pinniped login static" command.
|
// Even the deprecated command should now generate a kubeconfig with the new "pinniped login static" command.
|
||||||
restConfig := library.NewRestConfigFromKubeconfig(t, stdout)
|
restConfig := testlib.NewRestConfigFromKubeconfig(t, stdout)
|
||||||
require.NotNil(t, restConfig.ExecProvider)
|
require.NotNil(t, restConfig.ExecProvider)
|
||||||
require.Equal(t, []string{"login", "static"}, restConfig.ExecProvider.Args[:2])
|
require.Equal(t, []string{"login", "static"}, restConfig.ExecProvider.Args[:2])
|
||||||
|
|
||||||
@ -71,24 +71,24 @@ func TestCLIGetKubeconfigStaticToken(t *testing.T) {
|
|||||||
// with kubectl to validate that it works.
|
// with kubectl to validate that it works.
|
||||||
t.Run(
|
t.Run(
|
||||||
"access as user with kubectl",
|
"access as user with kubectl",
|
||||||
library.AccessAsUserWithKubectlTest(stdout, env.TestUser.ExpectedUsername, env.ConciergeNamespace),
|
testlib.AccessAsUserWithKubectlTest(stdout, env.TestUser.ExpectedUsername, env.ConciergeNamespace),
|
||||||
)
|
)
|
||||||
for _, group := range env.TestUser.ExpectedGroups {
|
for _, group := range env.TestUser.ExpectedGroups {
|
||||||
group := group
|
group := group
|
||||||
t.Run(
|
t.Run(
|
||||||
"access as group "+group+" with kubectl",
|
"access as group "+group+" with kubectl",
|
||||||
library.AccessAsGroupWithKubectlTest(stdout, group, env.ConciergeNamespace),
|
testlib.AccessAsGroupWithKubectlTest(stdout, group, env.ConciergeNamespace),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Kubernetes client with kubeconfig from pinniped CLI.
|
// Create Kubernetes client with kubeconfig from pinniped CLI.
|
||||||
kubeClient := library.NewClientsetForKubeConfig(t, stdout)
|
kubeClient := testlib.NewClientsetForKubeConfig(t, stdout)
|
||||||
|
|
||||||
// Validate that we can auth to the API via our user.
|
// Validate that we can auth to the API via our user.
|
||||||
t.Run("access as user with client-go", library.AccessAsUserTest(ctx, env.TestUser.ExpectedUsername, kubeClient))
|
t.Run("access as user with client-go", testlib.AccessAsUserTest(ctx, env.TestUser.ExpectedUsername, kubeClient))
|
||||||
for _, group := range env.TestUser.ExpectedGroups {
|
for _, group := range env.TestUser.ExpectedGroups {
|
||||||
group := group
|
group := group
|
||||||
t.Run("access as group "+group+" with client-go", library.AccessAsGroupTest(ctx, group, kubeClient))
|
t.Run("access as group "+group+" with client-go", testlib.AccessAsGroupTest(ctx, group, kubeClient))
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("whoami", func(t *testing.T) {
|
t.Run("whoami", func(t *testing.T) {
|
||||||
@ -116,14 +116,14 @@ func runPinnipedCLI(t *testing.T, envVars []string, pinnipedExe string, args ...
|
|||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
cmd.Env = envVars
|
cmd.Env = envVars
|
||||||
require.NoErrorf(t, cmd.Run(), "stderr:\n%s\n\nstdout:\n%s\n\n", stderr.String(), stdout.String())
|
require.NoErrorf(t, cmd.Run(), "stderr:\n%s\n\nstdout:\n%s\n\n", stderr.String(), stdout.String())
|
||||||
t.Logf("ran %q in %s", library.MaskTokens("pinniped "+strings.Join(args, " ")), time.Since(start).Round(time.Millisecond))
|
t.Logf("ran %q in %s", testlib.MaskTokens("pinniped "+strings.Join(args, " ")), time.Since(start).Round(time.Millisecond))
|
||||||
return stdout.String(), stderr.String()
|
return stdout.String(), stderr.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertWhoami(ctx context.Context, t *testing.T, useProxy bool, pinnipedExe, kubeconfigPath, wantUsername string, wantGroups []string) {
|
func assertWhoami(ctx context.Context, t *testing.T, useProxy bool, pinnipedExe, kubeconfigPath, wantUsername string, wantGroups []string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
apiGroupSuffix := library.IntegrationEnv(t).APIGroupSuffix
|
apiGroupSuffix := testlib.IntegrationEnv(t).APIGroupSuffix
|
||||||
|
|
||||||
var stdout, stderr bytes.Buffer
|
var stdout, stderr bytes.Buffer
|
||||||
cmd := exec.CommandContext(
|
cmd := exec.CommandContext(
|
||||||
@ -138,7 +138,7 @@ func assertWhoami(ctx context.Context, t *testing.T, useProxy bool, pinnipedExe,
|
|||||||
apiGroupSuffix,
|
apiGroupSuffix,
|
||||||
)
|
)
|
||||||
if useProxy {
|
if useProxy {
|
||||||
cmd.Env = append(os.Environ(), library.IntegrationEnv(t).ProxyEnv()...)
|
cmd.Env = append(os.Environ(), testlib.IntegrationEnv(t).ProxyEnv()...)
|
||||||
}
|
}
|
||||||
cmd.Stdout = &stdout
|
cmd.Stdout = &stdout
|
||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
@ -164,13 +164,13 @@ func deserializeWhoAmIRequest(t *testing.T, data string, apiGroupSuffix string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCLILoginOIDC(t *testing.T) {
|
func TestCLILoginOIDC(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Build pinniped CLI.
|
// Build pinniped CLI.
|
||||||
pinnipedExe := library.PinnipedCLIPath(t)
|
pinnipedExe := testlib.PinnipedCLIPath(t)
|
||||||
|
|
||||||
// Run "pinniped login oidc" to get an ExecCredential struct with an OIDC ID token.
|
// Run "pinniped login oidc" to get an ExecCredential struct with an OIDC ID token.
|
||||||
credOutput, sessionCachePath := runPinnipedLoginOIDC(ctx, t, pinnipedExe)
|
credOutput, sessionCachePath := runPinnipedLoginOIDC(ctx, t, pinnipedExe)
|
||||||
@ -268,7 +268,7 @@ func runPinnipedLoginOIDC(
|
|||||||
) (clientauthenticationv1beta1.ExecCredential, string) {
|
) (clientauthenticationv1beta1.ExecCredential, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
// Make a temp directory to hold the session cache for this test.
|
// Make a temp directory to hold the session cache for this test.
|
||||||
sessionCachePath := testutil.TempDir(t) + "/sessions.yaml"
|
sessionCachePath := testutil.TempDir(t) + "/sessions.yaml"
|
||||||
@ -304,7 +304,7 @@ func runPinnipedLoginOIDC(
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
reader := bufio.NewReader(library.NewLoggerReader(t, "stderr", stderr))
|
reader := bufio.NewReader(testlib.NewLoggerReader(t, "stderr", stderr))
|
||||||
|
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
const prompt = "Please log in: "
|
const prompt = "Please log in: "
|
||||||
@ -331,7 +331,7 @@ func runPinnipedLoginOIDC(
|
|||||||
err = fmt.Errorf("stdout stream closed with error: %w", closeErr)
|
err = fmt.Errorf("stdout stream closed with error: %w", closeErr)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
reader := bufio.NewReader(library.NewLoggerReader(t, "stdout", stdout))
|
reader := bufio.NewReader(testlib.NewLoggerReader(t, "stdout", stdout))
|
||||||
var out clientauthenticationv1beta1.ExecCredential
|
var out clientauthenticationv1beta1.ExecCredential
|
||||||
if err := json.NewDecoder(reader).Decode(&out); err != nil {
|
if err := json.NewDecoder(reader).Decode(&out); err != nil {
|
||||||
return fmt.Errorf("could not read ExecCredential from stdout: %w", err)
|
return fmt.Errorf("could not read ExecCredential from stdout: %w", err)
|
||||||
@ -401,7 +401,7 @@ func spawnTestGoroutine(t *testing.T, f func() error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func oidcLoginCommand(ctx context.Context, t *testing.T, pinnipedExe string, sessionCachePath string) *exec.Cmd {
|
func oidcLoginCommand(ctx context.Context, t *testing.T, pinnipedExe string, sessionCachePath string) *exec.Cmd {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
callbackURL, err := url.Parse(env.CLIUpstreamOIDC.CallbackURL)
|
callbackURL, err := url.Parse(env.CLIUpstreamOIDC.CallbackURL)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
cmd := exec.CommandContext(ctx, pinnipedExe, "login", "oidc",
|
cmd := exec.CommandContext(ctx, pinnipedExe, "login", "oidc",
|
||||||
|
@ -14,11 +14,11 @@ import (
|
|||||||
|
|
||||||
loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1"
|
loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1"
|
||||||
"go.pinniped.dev/internal/testutil"
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
defaultServingCertResourceName := env.ConciergeAppName + "-api-tls-serving-certificate"
|
defaultServingCertResourceName := env.ConciergeAppName + "-api-tls-serving-certificate"
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@ -72,9 +72,9 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
|||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
test := test
|
test := test
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
kubeClient := library.NewKubernetesClientset(t)
|
kubeClient := testlib.NewKubernetesClientset(t)
|
||||||
aggregatedClient := library.NewAggregatedClientset(t)
|
aggregatedClient := testlib.NewAggregatedClientset(t)
|
||||||
conciergeClient := library.NewConciergeClientset(t)
|
conciergeClient := testlib.NewConciergeClientset(t)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
|||||||
|
|
||||||
// Create a testWebhook so we have a legitimate authenticator to pass to the
|
// Create a testWebhook so we have a legitimate authenticator to pass to the
|
||||||
// TokenCredentialRequest API.
|
// TokenCredentialRequest API.
|
||||||
testWebhook := library.CreateTestWebhookAuthenticator(ctx, t)
|
testWebhook := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||||
|
|
||||||
// Get the initial auto-generated version of the Secret.
|
// Get the initial auto-generated version of the Secret.
|
||||||
secret, err := kubeClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
|
secret, err := kubeClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
|
||||||
@ -107,7 +107,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
|||||||
require.NoError(t, test.forceRotation(ctx, kubeClient, env.ConciergeNamespace))
|
require.NoError(t, test.forceRotation(ctx, kubeClient, env.ConciergeNamespace))
|
||||||
|
|
||||||
// Expect that the Secret comes back right away with newly minted certs.
|
// Expect that the Secret comes back right away with newly minted certs.
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
var err error
|
var err error
|
||||||
secret, err = kubeClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
|
secret, err = kubeClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
@ -127,7 +127,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
|||||||
require.Equal(t, env.ConciergeAppName, secret.Labels["app"])
|
require.Equal(t, env.ConciergeAppName, secret.Labels["app"])
|
||||||
|
|
||||||
// Expect that the APIService was also updated with the new CA.
|
// Expect that the APIService was also updated with the new CA.
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
apiService, err := aggregatedClient.ApiregistrationV1().APIServices().Get(ctx, apiServiceName, metav1.GetOptions{})
|
apiService, err := aggregatedClient.ApiregistrationV1().APIServices().Get(ctx, apiServiceName, metav1.GetOptions{})
|
||||||
requireEventually.NoErrorf(err, "get for APIService %q returned error", apiServiceName)
|
requireEventually.NoErrorf(err, "get for APIService %q returned error", apiServiceName)
|
||||||
requireEventually.Equalf(regeneratedCACert, apiService.Spec.CABundle, "CA bundle in APIService %q does not yet have the expected value", apiServiceName)
|
requireEventually.Equalf(regeneratedCACert, apiService.Spec.CABundle, "CA bundle in APIService %q does not yet have the expected value", apiServiceName)
|
||||||
@ -141,7 +141,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
|||||||
//
|
//
|
||||||
// our code changes all the certs immediately thus this should be healthy fairly quickly
|
// our code changes all the certs immediately thus this should be healthy fairly quickly
|
||||||
// if this starts flaking, check for bugs in our dynamiccertificates.Notifier implementation
|
// if this starts flaking, check for bugs in our dynamiccertificates.Notifier implementation
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
_, err := conciergeClient.LoginV1alpha1().TokenCredentialRequests().Create(ctx, &loginv1alpha1.TokenCredentialRequest{
|
_, err := conciergeClient.LoginV1alpha1().TokenCredentialRequests().Create(ctx, &loginv1alpha1.TokenCredentialRequest{
|
||||||
TypeMeta: metav1.TypeMeta{},
|
TypeMeta: metav1.TypeMeta{},
|
||||||
|
@ -13,12 +13,12 @@ import (
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetDeployment(t *testing.T) {
|
func TestGetDeployment(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
client := library.NewKubernetesClientset(t)
|
client := testlib.NewKubernetesClientset(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -28,7 +28,7 @@ func TestGetDeployment(t *testing.T) {
|
|||||||
|
|
||||||
cond := getDeploymentCondition(appDeployment.Status, appsv1.DeploymentAvailable)
|
cond := getDeploymentCondition(appDeployment.Status, appsv1.DeploymentAvailable)
|
||||||
require.NotNil(t, cond)
|
require.NotNil(t, cond)
|
||||||
require.Equalf(t, corev1.ConditionTrue, cond.Status, "app should be available: %s", library.Sdump(appDeployment))
|
require.Equalf(t, corev1.ConditionTrue, cond.Status, "app should be available: %s", testlib.Sdump(appDeployment))
|
||||||
}
|
}
|
||||||
|
|
||||||
// getDeploymentCondition returns the condition with the provided type.
|
// getDeploymentCondition returns the condition with the provided type.
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
"go.pinniped.dev/pkg/conciergeclient"
|
"go.pinniped.dev/pkg/conciergeclient"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test certificate and private key that should get an authentication error. Generated with cfssl [1], like this:
|
// Test certificate and private key that should get an authentication error. Generated with cfssl [1], like this:
|
||||||
@ -53,20 +53,20 @@ var (
|
|||||||
var maskKey = func(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
|
var maskKey = func(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
|
||||||
|
|
||||||
func TestClient(t *testing.T) {
|
func TestClient(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
|
env := testlib.IntegrationEnv(t).WithCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
webhook := library.CreateTestWebhookAuthenticator(ctx, t)
|
webhook := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||||
|
|
||||||
// Use an invalid certificate/key to validate that the ServerVersion API fails like we assume.
|
// Use an invalid certificate/key to validate that the ServerVersion API fails like we assume.
|
||||||
invalidClient := library.NewClientsetWithCertAndKey(t, testCert, testKey)
|
invalidClient := testlib.NewClientsetWithCertAndKey(t, testCert, testKey)
|
||||||
_, err := invalidClient.Discovery().ServerVersion()
|
_, err := invalidClient.Discovery().ServerVersion()
|
||||||
require.EqualError(t, err, "the server has asked for the client to provide credentials")
|
require.EqualError(t, err, "the server has asked for the client to provide credentials")
|
||||||
|
|
||||||
// Using the CA bundle and host from the current (admin) kubeconfig, do the token exchange.
|
// Using the CA bundle and host from the current (admin) kubeconfig, do the token exchange.
|
||||||
clientConfig := library.NewClientConfig(t)
|
clientConfig := testlib.NewClientConfig(t)
|
||||||
client, err := conciergeclient.New(
|
client, err := conciergeclient.New(
|
||||||
conciergeclient.WithCABundle(string(clientConfig.CAData)),
|
conciergeclient.WithCABundle(string(clientConfig.CAData)),
|
||||||
conciergeclient.WithEndpoint(clientConfig.Host),
|
conciergeclient.WithEndpoint(clientConfig.Host),
|
||||||
@ -75,14 +75,14 @@ func TestClient(t *testing.T) {
|
|||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
resp, err := client.ExchangeToken(ctx, env.TestUser.Token)
|
resp, err := client.ExchangeToken(ctx, env.TestUser.Token)
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
requireEventually.NotNil(resp.Status.ExpirationTimestamp)
|
requireEventually.NotNil(resp.Status.ExpirationTimestamp)
|
||||||
requireEventually.InDelta(5*time.Minute, time.Until(resp.Status.ExpirationTimestamp.Time), float64(time.Minute))
|
requireEventually.InDelta(5*time.Minute, time.Until(resp.Status.ExpirationTimestamp.Time), float64(time.Minute))
|
||||||
|
|
||||||
// Create a client using the certificate and key returned by the token exchange.
|
// Create a client using the certificate and key returned by the token exchange.
|
||||||
validClient := library.NewClientsetWithCertAndKey(t, resp.Status.ClientCertificateData, resp.Status.ClientKeyData)
|
validClient := testlib.NewClientsetWithCertAndKey(t, resp.Status.ClientCertificateData, resp.Status.ClientKeyData)
|
||||||
|
|
||||||
// Make a version request, which should succeed even without any authorization.
|
// Make a version request, which should succeed even without any authorization.
|
||||||
_, err = validClient.Discovery().ServerVersion()
|
_, err = validClient.Discovery().ServerVersion()
|
||||||
|
@ -14,14 +14,14 @@ import (
|
|||||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||||
|
|
||||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCredentialIssuer(t *testing.T) {
|
func TestCredentialIssuer(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
config := library.NewClientConfig(t)
|
config := testlib.NewClientConfig(t)
|
||||||
client := library.NewConciergeClientset(t)
|
client := testlib.NewConciergeClientset(t)
|
||||||
aggregatedClientset := library.NewAggregatedClientset(t)
|
aggregatedClientset := testlib.NewAggregatedClientset(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -66,7 +66,7 @@ func TestCredentialIssuer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
require.NotNil(t, actualStatusStrategy)
|
require.NotNil(t, actualStatusStrategy)
|
||||||
|
|
||||||
if env.HasCapability(library.ClusterSigningKeyIsAvailable) {
|
if env.HasCapability(testlib.ClusterSigningKeyIsAvailable) {
|
||||||
require.Equal(t, configv1alpha1.SuccessStrategyStatus, actualStatusStrategy.Status)
|
require.Equal(t, configv1alpha1.SuccessStrategyStatus, actualStatusStrategy.Status)
|
||||||
require.Equal(t, configv1alpha1.FetchedKeyStrategyReason, actualStatusStrategy.Reason)
|
require.Equal(t, configv1alpha1.FetchedKeyStrategyReason, actualStatusStrategy.Reason)
|
||||||
require.Equal(t, "key was fetched successfully", actualStatusStrategy.Message)
|
require.Equal(t, "key was fetched successfully", actualStatusStrategy.Message)
|
||||||
|
@ -19,16 +19,16 @@ import (
|
|||||||
|
|
||||||
auth1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
auth1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||||
loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1"
|
loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUnsuccessfulCredentialRequest(t *testing.T) {
|
func TestUnsuccessfulCredentialRequest(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t).WithCapability(library.AnonymousAuthenticationSupported)
|
env := testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupported)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
response, err := library.CreateTokenCredentialRequest(ctx, t,
|
response, err := testlib.CreateTokenCredentialRequest(ctx, t,
|
||||||
loginv1alpha1.TokenCredentialRequestSpec{
|
loginv1alpha1.TokenCredentialRequestSpec{
|
||||||
Token: env.TestUser.Token,
|
Token: env.TestUser.Token,
|
||||||
Authenticator: corev1.TypedLocalObjectReference{
|
Authenticator: corev1.TypedLocalObjectReference{
|
||||||
@ -45,7 +45,7 @@ func TestUnsuccessfulCredentialRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSuccessfulCredentialRequest(t *testing.T) {
|
func TestSuccessfulCredentialRequest(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
|
env := testlib.IntegrationEnv(t).WithCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -57,16 +57,16 @@ func TestSuccessfulCredentialRequest(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "webhook",
|
name: "webhook",
|
||||||
authenticator: library.CreateTestWebhookAuthenticator,
|
authenticator: testlib.CreateTestWebhookAuthenticator,
|
||||||
token: func(t *testing.T) (string, string, []string) {
|
token: func(t *testing.T) (string, string, []string) {
|
||||||
return library.IntegrationEnv(t).TestUser.Token, env.TestUser.ExpectedUsername, env.TestUser.ExpectedGroups
|
return testlib.IntegrationEnv(t).TestUser.Token, env.TestUser.ExpectedUsername, env.TestUser.ExpectedGroups
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "jwt authenticator",
|
name: "jwt authenticator",
|
||||||
authenticator: library.CreateTestJWTAuthenticatorForCLIUpstream,
|
authenticator: testlib.CreateTestJWTAuthenticatorForCLIUpstream,
|
||||||
token: func(t *testing.T) (string, string, []string) {
|
token: func(t *testing.T) (string, string, []string) {
|
||||||
pinnipedExe := library.PinnipedCLIPath(t)
|
pinnipedExe := testlib.PinnipedCLIPath(t)
|
||||||
credOutput, _ := runPinnipedLoginOIDC(ctx, t, pinnipedExe)
|
credOutput, _ := runPinnipedLoginOIDC(ctx, t, pinnipedExe)
|
||||||
token := credOutput.Status.Token
|
token := credOutput.Status.Token
|
||||||
|
|
||||||
@ -87,9 +87,9 @@ func TestSuccessfulCredentialRequest(t *testing.T) {
|
|||||||
token, username, groups := test.token(t)
|
token, username, groups := test.token(t)
|
||||||
|
|
||||||
var response *loginv1alpha1.TokenCredentialRequest
|
var response *loginv1alpha1.TokenCredentialRequest
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
var err error
|
var err error
|
||||||
response, err = library.CreateTokenCredentialRequest(ctx, t,
|
response, err = testlib.CreateTokenCredentialRequest(ctx, t,
|
||||||
loginv1alpha1.TokenCredentialRequestSpec{Token: token, Authenticator: authenticator},
|
loginv1alpha1.TokenCredentialRequestSpec{Token: token, Authenticator: authenticator},
|
||||||
)
|
)
|
||||||
requireEventually.NoError(err, "the request should never fail at the HTTP level")
|
requireEventually.NoError(err, "the request should never fail at the HTTP level")
|
||||||
@ -108,7 +108,7 @@ func TestSuccessfulCredentialRequest(t *testing.T) {
|
|||||||
}, 10*time.Second, 500*time.Millisecond)
|
}, 10*time.Second, 500*time.Millisecond)
|
||||||
|
|
||||||
// Create a client using the certificate from the CredentialRequest.
|
// Create a client using the certificate from the CredentialRequest.
|
||||||
clientWithCertFromCredentialRequest := library.NewClientsetWithCertAndKey(
|
clientWithCertFromCredentialRequest := testlib.NewClientsetWithCertAndKey(
|
||||||
t,
|
t,
|
||||||
response.Status.Credential.ClientCertificateData,
|
response.Status.Credential.ClientCertificateData,
|
||||||
response.Status.Credential.ClientKeyData,
|
response.Status.Credential.ClientKeyData,
|
||||||
@ -116,13 +116,13 @@ func TestSuccessfulCredentialRequest(t *testing.T) {
|
|||||||
|
|
||||||
t.Run(
|
t.Run(
|
||||||
"access as user",
|
"access as user",
|
||||||
library.AccessAsUserTest(ctx, username, clientWithCertFromCredentialRequest),
|
testlib.AccessAsUserTest(ctx, username, clientWithCertFromCredentialRequest),
|
||||||
)
|
)
|
||||||
for _, group := range groups {
|
for _, group := range groups {
|
||||||
group := group
|
group := group
|
||||||
t.Run(
|
t.Run(
|
||||||
"access as group "+group,
|
"access as group "+group,
|
||||||
library.AccessAsGroupTest(ctx, group, clientWithCertFromCredentialRequest),
|
testlib.AccessAsGroupTest(ctx, group, clientWithCertFromCredentialRequest),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -130,15 +130,15 @@ func TestSuccessfulCredentialRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthenticateTheUser(t *testing.T) {
|
func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthenticateTheUser(t *testing.T) {
|
||||||
_ = library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
|
_ = testlib.IntegrationEnv(t).WithCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
|
|
||||||
// Create a testWebhook so we have a legitimate authenticator to pass to the
|
// Create a testWebhook so we have a legitimate authenticator to pass to the
|
||||||
// TokenCredentialRequest API.
|
// TokenCredentialRequest API.
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
testWebhook := library.CreateTestWebhookAuthenticator(ctx, t)
|
testWebhook := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||||
|
|
||||||
response, err := library.CreateTokenCredentialRequest(context.Background(), t,
|
response, err := testlib.CreateTokenCredentialRequest(context.Background(), t,
|
||||||
loginv1alpha1.TokenCredentialRequestSpec{Token: "not a good token", Authenticator: testWebhook},
|
loginv1alpha1.TokenCredentialRequestSpec{Token: "not a good token", Authenticator: testWebhook},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -150,15 +150,15 @@ func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthentic
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCredentialRequest_ShouldFailWhenRequestDoesNotIncludeToken(t *testing.T) {
|
func TestCredentialRequest_ShouldFailWhenRequestDoesNotIncludeToken(t *testing.T) {
|
||||||
_ = library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
|
_ = testlib.IntegrationEnv(t).WithCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
|
|
||||||
// Create a testWebhook so we have a legitimate authenticator to pass to the
|
// Create a testWebhook so we have a legitimate authenticator to pass to the
|
||||||
// TokenCredentialRequest API.
|
// TokenCredentialRequest API.
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
testWebhook := library.CreateTestWebhookAuthenticator(ctx, t)
|
testWebhook := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||||
|
|
||||||
response, err := library.CreateTokenCredentialRequest(context.Background(), t,
|
response, err := testlib.CreateTokenCredentialRequest(context.Background(), t,
|
||||||
loginv1alpha1.TokenCredentialRequestSpec{Token: "", Authenticator: testWebhook},
|
loginv1alpha1.TokenCredentialRequestSpec{Token: "", Authenticator: testWebhook},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/httputil/roundtripper"
|
"go.pinniped.dev/internal/httputil/roundtripper"
|
||||||
"go.pinniped.dev/internal/kubeclient"
|
"go.pinniped.dev/internal/kubeclient"
|
||||||
"go.pinniped.dev/internal/testutil"
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// syncBuffer wraps bytes.Buffer with a mutex so we don't have races in our test code.
|
// syncBuffer wraps bytes.Buffer with a mutex so we don't have races in our test code.
|
||||||
@ -100,22 +100,22 @@ func (sb *syncBuffer) Write(b []byte) (int, error) {
|
|||||||
// - AKS ephemeral clusters: auto mode will choose enabled, supports LBs, has squid.
|
// - AKS ephemeral clusters: auto mode will choose enabled, supports LBs, has squid.
|
||||||
// - EKS ephemeral clusters: auto mode will choose enabled, supports LBs, has squid.
|
// - EKS ephemeral clusters: auto mode will choose enabled, supports LBs, has squid.
|
||||||
func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's complex.
|
func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's complex.
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
impersonatorShouldHaveStartedAutomaticallyByDefault := !env.HasCapability(library.ClusterSigningKeyIsAvailable)
|
impersonatorShouldHaveStartedAutomaticallyByDefault := !env.HasCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
clusterSupportsLoadBalancers := env.HasCapability(library.HasExternalLoadBalancerProvider)
|
clusterSupportsLoadBalancers := env.HasCapability(testlib.HasExternalLoadBalancerProvider)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Create a client using the admin kubeconfig.
|
// Create a client using the admin kubeconfig.
|
||||||
adminClient := library.NewKubernetesClientset(t)
|
adminClient := testlib.NewKubernetesClientset(t)
|
||||||
adminConciergeClient := library.NewConciergeClientset(t)
|
adminConciergeClient := testlib.NewConciergeClientset(t)
|
||||||
|
|
||||||
// Create a WebhookAuthenticator and prepare a TokenCredentialRequestSpec using the authenticator for use later.
|
// Create a WebhookAuthenticator and prepare a TokenCredentialRequestSpec using the authenticator for use later.
|
||||||
credentialRequestSpecWithWorkingCredentials := loginv1alpha1.TokenCredentialRequestSpec{
|
credentialRequestSpecWithWorkingCredentials := loginv1alpha1.TokenCredentialRequestSpec{
|
||||||
Token: env.TestUser.Token,
|
Token: env.TestUser.Token,
|
||||||
Authenticator: library.CreateTestWebhookAuthenticator(ctx, t),
|
Authenticator: testlib.CreateTestWebhookAuthenticator(ctx, t),
|
||||||
}
|
}
|
||||||
|
|
||||||
// The address of the ClusterIP service that points at the impersonation proxy's port (used when there is no load balancer).
|
// The address of the ClusterIP service that points at the impersonation proxy's port (used when there is no load balancer).
|
||||||
@ -139,13 +139,13 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
// However, we issue short-lived certs, so this cert will only be valid for a few minutes.
|
// However, we issue short-lived certs, so this cert will only be valid for a few minutes.
|
||||||
// Cache it until it is almost expired and then refresh it whenever it is close to expired.
|
// Cache it until it is almost expired and then refresh it whenever it is close to expired.
|
||||||
//
|
//
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
resp, err := createTokenCredentialRequest(credentialRequestSpecWithWorkingCredentials, client)
|
resp, err := createTokenCredentialRequest(credentialRequestSpecWithWorkingCredentials, client)
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
requireEventually.NotNil(resp)
|
requireEventually.NotNil(resp)
|
||||||
requireEventually.NotNil(resp.Status)
|
requireEventually.NotNil(resp.Status)
|
||||||
requireEventually.NotNil(resp.Status.Credential)
|
requireEventually.NotNil(resp.Status.Credential)
|
||||||
requireEventually.Nilf(resp.Status.Message, "expected no error message but got: %s", library.Sdump(resp.Status.Message))
|
requireEventually.Nilf(resp.Status.Message, "expected no error message but got: %s", testlib.Sdump(resp.Status.Message))
|
||||||
requireEventually.NotEmpty(resp.Status.Credential.ClientCertificateData)
|
requireEventually.NotEmpty(resp.Status.Credential.ClientCertificateData)
|
||||||
requireEventually.NotEmpty(resp.Status.Credential.ClientKeyData)
|
requireEventually.NotEmpty(resp.Status.Credential.ClientKeyData)
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
// Auto mode should have decided that the impersonator will run and should have started a load balancer,
|
// Auto mode should have decided that the impersonator will run and should have started a load balancer,
|
||||||
// and we will be able to use the load balancer to access the impersonator. (e.g. GKE, AKS, EKS)
|
// and we will be able to use the load balancer to access the impersonator. (e.g. GKE, AKS, EKS)
|
||||||
// Check that load balancer has been automatically created by the impersonator's "auto" mode.
|
// Check that load balancer has been automatically created by the impersonator's "auto" mode.
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
return hasImpersonationProxyLoadBalancerService(ctx, env, adminClient)
|
return hasImpersonationProxyLoadBalancerService(ctx, env, adminClient)
|
||||||
}, 30*time.Second, 500*time.Millisecond)
|
}, 30*time.Second, 500*time.Millisecond)
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that no load balancer has been created by the impersonator's "auto" mode.
|
// Check that no load balancer has been created by the impersonator's "auto" mode.
|
||||||
library.RequireNeverWithoutError(t, func() (bool, error) {
|
testlib.RequireNeverWithoutError(t, func() (bool, error) {
|
||||||
return hasImpersonationProxyLoadBalancerService(ctx, env, adminClient)
|
return hasImpersonationProxyLoadBalancerService(ctx, env, adminClient)
|
||||||
}, 10*time.Second, 500*time.Millisecond)
|
}, 10*time.Second, 500*time.Millisecond)
|
||||||
|
|
||||||
@ -290,12 +290,12 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
t.Run("positive tests", func(t *testing.T) {
|
t.Run("positive tests", func(t *testing.T) {
|
||||||
// Create an RBAC rule to allow this user to read/write everything.
|
// Create an RBAC rule to allow this user to read/write everything.
|
||||||
library.CreateTestClusterRoleBinding(t,
|
testlib.CreateTestClusterRoleBinding(t,
|
||||||
rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: env.TestUser.ExpectedUsername},
|
rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: env.TestUser.ExpectedUsername},
|
||||||
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "edit"},
|
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "edit"},
|
||||||
)
|
)
|
||||||
// Wait for the above RBAC rule to take effect.
|
// Wait for the above RBAC rule to take effect.
|
||||||
library.WaitForUserToHaveAccess(t, env.TestUser.ExpectedUsername, []string{}, &authorizationv1.ResourceAttributes{
|
testlib.WaitForUserToHaveAccess(t, env.TestUser.ExpectedUsername, []string{}, &authorizationv1.ResourceAttributes{
|
||||||
Verb: "get", Group: "", Version: "v1", Resource: "namespaces",
|
Verb: "get", Group: "", Version: "v1", Resource: "namespaces",
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -318,13 +318,13 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
// influencing RBAC checks correctly.
|
// influencing RBAC checks correctly.
|
||||||
t.Run(
|
t.Run(
|
||||||
"access as user",
|
"access as user",
|
||||||
library.AccessAsUserTest(ctx, env.TestUser.ExpectedUsername, impersonationProxyKubeClient(t)),
|
testlib.AccessAsUserTest(ctx, env.TestUser.ExpectedUsername, impersonationProxyKubeClient(t)),
|
||||||
)
|
)
|
||||||
for _, group := range env.TestUser.ExpectedGroups {
|
for _, group := range env.TestUser.ExpectedGroups {
|
||||||
group := group
|
group := group
|
||||||
t.Run(
|
t.Run(
|
||||||
"access as group "+group,
|
"access as group "+group,
|
||||||
library.AccessAsGroupTest(ctx, group, impersonationProxyKubeClient(t)),
|
testlib.AccessAsGroupTest(ctx, group, impersonationProxyKubeClient(t)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,7 +447,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
// Use labels on our created ConfigMaps to avoid accidentally listing other ConfigMaps that might
|
// Use labels on our created ConfigMaps to avoid accidentally listing other ConfigMaps that might
|
||||||
// exist in the namespace. In Kube 1.20+ there is a default ConfigMap in every namespace.
|
// exist in the namespace. In Kube 1.20+ there is a default ConfigMap in every namespace.
|
||||||
configMapLabels := labels.Set{
|
configMapLabels := labels.Set{
|
||||||
"pinniped.dev/testConfigMap": library.RandHex(t, 8),
|
"pinniped.dev/testConfigMap": testlib.RandHex(t, 8),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test "create" verb through the impersonation proxy.
|
// Test "create" verb through the impersonation proxy.
|
||||||
@ -469,7 +469,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
// Make sure that all of the created ConfigMaps show up in the informer's cache to
|
// Make sure that all of the created ConfigMaps show up in the informer's cache to
|
||||||
// demonstrate that the informer's "watch" verb is working through the impersonation proxy.
|
// demonstrate that the informer's "watch" verb is working through the impersonation proxy.
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
_, err := informer.Lister().ConfigMaps(namespaceName).Get("configmap-1")
|
_, err := informer.Lister().ConfigMaps(namespaceName).Get("configmap-1")
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
_, err = informer.Lister().ConfigMaps(namespaceName).Get("configmap-2")
|
_, err = informer.Lister().ConfigMaps(namespaceName).Get("configmap-2")
|
||||||
@ -496,7 +496,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
require.Equal(t, "bar", updateResult.Data["foo"])
|
require.Equal(t, "bar", updateResult.Data["foo"])
|
||||||
|
|
||||||
// Make sure that the updated ConfigMap shows up in the informer's cache.
|
// Make sure that the updated ConfigMap shows up in the informer's cache.
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
configMap, err := informer.Lister().ConfigMaps(namespaceName).Get("configmap-3")
|
configMap, err := informer.Lister().ConfigMaps(namespaceName).Get("configmap-3")
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
requireEventually.Equal("bar", configMap.Data["foo"])
|
requireEventually.Equal("bar", configMap.Data["foo"])
|
||||||
@ -514,7 +514,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
require.Equal(t, "42", patchResult.Data["baz"])
|
require.Equal(t, "42", patchResult.Data["baz"])
|
||||||
|
|
||||||
// Make sure that the patched ConfigMap shows up in the informer's cache.
|
// Make sure that the patched ConfigMap shows up in the informer's cache.
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
configMap, err := informer.Lister().ConfigMaps(namespaceName).Get("configmap-3")
|
configMap, err := informer.Lister().ConfigMaps(namespaceName).Get("configmap-3")
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
requireEventually.Equal("bar", configMap.Data["foo"])
|
requireEventually.Equal("bar", configMap.Data["foo"])
|
||||||
@ -526,7 +526,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Make sure that the deleted ConfigMap shows up in the informer's cache.
|
// Make sure that the deleted ConfigMap shows up in the informer's cache.
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
_, err := informer.Lister().ConfigMaps(namespaceName).Get("configmap-3")
|
_, err := informer.Lister().ConfigMaps(namespaceName).Get("configmap-3")
|
||||||
requireEventually.Truef(k8serrors.IsNotFound(err), "expected a NotFound error from get, got %v", err)
|
requireEventually.Truef(k8serrors.IsNotFound(err), "expected a NotFound error from get, got %v", err)
|
||||||
|
|
||||||
@ -540,7 +540,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Make sure that the deleted ConfigMaps shows up in the informer's cache.
|
// Make sure that the deleted ConfigMaps shows up in the informer's cache.
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
list, err := informer.Lister().ConfigMaps(namespaceName).List(configMapLabels.AsSelector())
|
list, err := informer.Lister().ConfigMaps(namespaceName).List(configMapLabels.AsSelector())
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
requireEventually.Empty(list)
|
requireEventually.Empty(list)
|
||||||
@ -630,7 +630,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
t.Run("nested impersonation as a cluster admin user is allowed", func(t *testing.T) {
|
t.Run("nested impersonation as a cluster admin user is allowed", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// Copy the admin credentials from the admin kubeconfig.
|
// Copy the admin credentials from the admin kubeconfig.
|
||||||
adminClientRestConfig := library.NewClientConfig(t)
|
adminClientRestConfig := testlib.NewClientConfig(t)
|
||||||
clusterAdminCredentials := getCredForConfig(t, adminClientRestConfig)
|
clusterAdminCredentials := getCredForConfig(t, adminClientRestConfig)
|
||||||
|
|
||||||
// figure out who the admin user is
|
// figure out who the admin user is
|
||||||
@ -705,7 +705,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
t.Run("nested impersonation as a cluster admin fails on reserved key", func(t *testing.T) {
|
t.Run("nested impersonation as a cluster admin fails on reserved key", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
adminClientRestConfig := library.NewClientConfig(t)
|
adminClientRestConfig := testlib.NewClientConfig(t)
|
||||||
clusterAdminCredentials := getCredForConfig(t, adminClientRestConfig)
|
clusterAdminCredentials := getCredForConfig(t, adminClientRestConfig)
|
||||||
|
|
||||||
nestedImpersonationClient := newImpersonationProxyClientWithCredentials(t,
|
nestedImpersonationClient := newImpersonationProxyClientWithCredentials(t,
|
||||||
@ -762,11 +762,11 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
time.Sleep(15 * time.Second)
|
time.Sleep(15 * time.Second)
|
||||||
|
|
||||||
// allow the test SA to impersonate any SA
|
// allow the test SA to impersonate any SA
|
||||||
library.CreateTestClusterRoleBinding(t,
|
testlib.CreateTestClusterRoleBinding(t,
|
||||||
rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Name: saName, Namespace: namespaceName},
|
rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Name: saName, Namespace: namespaceName},
|
||||||
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "edit"},
|
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "edit"},
|
||||||
)
|
)
|
||||||
library.WaitForUserToHaveAccess(t, serviceaccount.MakeUsername(namespaceName, saName), []string{}, &authorizationv1.ResourceAttributes{
|
testlib.WaitForUserToHaveAccess(t, serviceaccount.MakeUsername(namespaceName, saName), []string{}, &authorizationv1.ResourceAttributes{
|
||||||
Verb: "impersonate", Group: "", Version: "v1", Resource: "serviceaccounts",
|
Verb: "impersonate", Group: "", Version: "v1", Resource: "serviceaccounts",
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -817,7 +817,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
|
|
||||||
// we expect the impersonation proxy to match the behavior of KAS in regards to anonymous requests
|
// we expect the impersonation proxy to match the behavior of KAS in regards to anonymous requests
|
||||||
if env.HasCapability(library.AnonymousAuthenticationSupported) {
|
if env.HasCapability(testlib.AnonymousAuthenticationSupported) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t,
|
require.Equal(t,
|
||||||
expectedWhoAmIRequestResponse(
|
expectedWhoAmIRequestResponse(
|
||||||
@ -828,7 +828,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
whoAmI,
|
whoAmI,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
require.True(t, k8serrors.IsUnauthorized(err), library.Sdump(err))
|
require.True(t, k8serrors.IsUnauthorized(err), testlib.Sdump(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test using a service account token.
|
// Test using a service account token.
|
||||||
@ -895,7 +895,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
_, badAudErr := impersonationProxySABadAudPinnipedConciergeClient.IdentityV1alpha1().WhoAmIRequests().
|
_, badAudErr := impersonationProxySABadAudPinnipedConciergeClient.IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.True(t, k8serrors.IsUnauthorized(badAudErr), library.Sdump(badAudErr))
|
require.True(t, k8serrors.IsUnauthorized(badAudErr), testlib.Sdump(badAudErr))
|
||||||
|
|
||||||
tokenRequest, err := kubeClient.ServiceAccounts(namespaceName).CreateToken(ctx, saName, &authenticationv1.TokenRequest{
|
tokenRequest, err := kubeClient.ServiceAccounts(namespaceName).CreateToken(ctx, saName, &authenticationv1.TokenRequest{
|
||||||
Spec: authenticationv1.TokenRequestSpec{
|
Spec: authenticationv1.TokenRequestSpec{
|
||||||
@ -932,11 +932,11 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
)
|
)
|
||||||
|
|
||||||
// allow the test SA to create CSRs
|
// allow the test SA to create CSRs
|
||||||
library.CreateTestClusterRoleBinding(t,
|
testlib.CreateTestClusterRoleBinding(t,
|
||||||
rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Name: saName, Namespace: namespaceName},
|
rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Name: saName, Namespace: namespaceName},
|
||||||
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "system:node-bootstrapper"},
|
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "system:node-bootstrapper"},
|
||||||
)
|
)
|
||||||
library.WaitForUserToHaveAccess(t, serviceaccount.MakeUsername(namespaceName, saName), []string{}, &authorizationv1.ResourceAttributes{
|
testlib.WaitForUserToHaveAccess(t, serviceaccount.MakeUsername(namespaceName, saName), []string{}, &authorizationv1.ResourceAttributes{
|
||||||
Verb: "create", Group: certificatesv1.GroupName, Version: "*", Resource: "certificatesigningrequests",
|
Verb: "create", Group: certificatesv1.GroupName, Version: "*", Resource: "certificatesigningrequests",
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1007,7 +1007,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
// run the kubectl attach command
|
// run the kubectl attach command
|
||||||
namespaceName := createTestNamespace(t, adminClient)
|
namespaceName := createTestNamespace(t, adminClient)
|
||||||
attachPod := library.CreatePod(ctx, t, "impersonation-proxy-attach", namespaceName, corev1.PodSpec{
|
attachPod := testlib.CreatePod(ctx, t, "impersonation-proxy-attach", namespaceName, corev1.PodSpec{
|
||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{
|
{
|
||||||
Name: "impersonation-proxy-attach",
|
Name: "impersonation-proxy-attach",
|
||||||
@ -1040,7 +1040,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
// see that we can read stdout and it spits out stdin output back to us
|
// see that we can read stdout and it spits out stdin output back to us
|
||||||
wantAttachStdout := fmt.Sprintf("VAR: %s\n", echoString)
|
wantAttachStdout := fmt.Sprintf("VAR: %s\n", echoString)
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
requireEventually.Equal(
|
requireEventually.Equal(
|
||||||
wantAttachStdout,
|
wantAttachStdout,
|
||||||
attachStdout.String(),
|
attachStdout.String(),
|
||||||
@ -1084,7 +1084,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
dialer.Proxy = func(req *http.Request) (*url.URL, error) {
|
dialer.Proxy = func(req *http.Request) (*url.URL, error) {
|
||||||
proxyURL, err := url.Parse(env.Proxy)
|
proxyURL, err := url.Parse(env.Proxy)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Logf("passing request for %s through proxy %s", library.RedactURLParams(req.URL), proxyURL.String())
|
t.Logf("passing request for %s through proxy %s", testlib.RedactURLParams(req.URL), proxyURL.String())
|
||||||
return proxyURL, nil
|
return proxyURL, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1163,7 +1163,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
httpTransport.Proxy = func(req *http.Request) (*url.URL, error) {
|
httpTransport.Proxy = func(req *http.Request) (*url.URL, error) {
|
||||||
proxyURL, err := url.Parse(env.Proxy)
|
proxyURL, err := url.Parse(env.Proxy)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Logf("passing request for %s through proxy %s", library.RedactURLParams(req.URL), proxyURL.String())
|
t.Logf("passing request for %s through proxy %s", testlib.RedactURLParams(req.URL), proxyURL.String())
|
||||||
return proxyURL, nil
|
return proxyURL, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1237,7 +1237,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
impersonationProxyAnonymousRestClient, err := rest.RESTClientFor(copyConfig)
|
impersonationProxyAnonymousRestClient, err := rest.RESTClientFor(copyConfig)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
adminClientRestConfig := library.NewClientConfig(t)
|
adminClientRestConfig := testlib.NewClientConfig(t)
|
||||||
clusterAdminCredentials := getCredForConfig(t, adminClientRestConfig)
|
clusterAdminCredentials := getCredForConfig(t, adminClientRestConfig)
|
||||||
impersonationProxyAdminClientAsAnonymousConfig := newImpersonationProxyClientWithCredentials(t,
|
impersonationProxyAdminClientAsAnonymousConfig := newImpersonationProxyClientWithCredentials(t,
|
||||||
clusterAdminCredentials,
|
clusterAdminCredentials,
|
||||||
@ -1266,7 +1266,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
Authenticator: corev1.TypedLocalObjectReference{APIGroup: pointer.String("anything.pinniped.dev")},
|
Authenticator: corev1.TypedLocalObjectReference{APIGroup: pointer.String("anything.pinniped.dev")},
|
||||||
},
|
},
|
||||||
}, metav1.CreateOptions{})
|
}, metav1.CreateOptions{})
|
||||||
require.True(t, k8serrors.IsInvalid(err), library.Sdump(err))
|
require.True(t, k8serrors.IsInvalid(err), testlib.Sdump(err))
|
||||||
require.Equal(t, `.login.concierge.pinniped.dev "" is invalid: spec.token.value: Required value: token must be supplied`, err.Error())
|
require.Equal(t, `.login.concierge.pinniped.dev "" is invalid: spec.token.value: Required value: token must be supplied`, err.Error())
|
||||||
require.Equal(t, &loginv1alpha1.TokenCredentialRequest{}, tkr)
|
require.Equal(t, &loginv1alpha1.TokenCredentialRequest{}, tkr)
|
||||||
})
|
})
|
||||||
@ -1282,21 +1282,21 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
whoami, errWho := impersonationProxyAdminRestClientAsAnonymous.Post().Body([]byte(`{}`)).AbsPath("/apis/identity.concierge." + env.APIGroupSuffix + "/v1alpha1/whoamirequests").DoRaw(ctx)
|
whoami, errWho := impersonationProxyAdminRestClientAsAnonymous.Post().Body([]byte(`{}`)).AbsPath("/apis/identity.concierge." + env.APIGroupSuffix + "/v1alpha1/whoamirequests").DoRaw(ctx)
|
||||||
require.NoError(t, errWho, library.Sdump(errWho))
|
require.NoError(t, errWho, testlib.Sdump(errWho))
|
||||||
require.True(t, strings.HasPrefix(string(whoami), `{"kind":"WhoAmIRequest","apiVersion":"identity.concierge.`+env.APIGroupSuffix+`/v1alpha1","metadata":{"creationTimestamp":null},"spec":{},"status":{"kubernetesUserInfo":{"user":{"username":"system:anonymous","groups":["system:unauthenticated"],"extra":{"original-user-info.impersonation-proxy.concierge.pinniped.dev":["{\"username\":`), string(whoami))
|
require.True(t, strings.HasPrefix(string(whoami), `{"kind":"WhoAmIRequest","apiVersion":"identity.concierge.`+env.APIGroupSuffix+`/v1alpha1","metadata":{"creationTimestamp":null},"spec":{},"status":{"kubernetesUserInfo":{"user":{"username":"system:anonymous","groups":["system:unauthenticated"],"extra":{"original-user-info.impersonation-proxy.concierge.pinniped.dev":["{\"username\":`), string(whoami))
|
||||||
|
|
||||||
healthz, errHealth := impersonationProxyAdminRestClientAsAnonymous.Get().AbsPath("/healthz").DoRaw(ctx)
|
healthz, errHealth := impersonationProxyAdminRestClientAsAnonymous.Get().AbsPath("/healthz").DoRaw(ctx)
|
||||||
require.NoError(t, errHealth, library.Sdump(errHealth))
|
require.NoError(t, errHealth, testlib.Sdump(errHealth))
|
||||||
require.Equal(t, "ok", string(healthz))
|
require.Equal(t, "ok", string(healthz))
|
||||||
|
|
||||||
healthzLog, errHealthzLog := impersonationProxyAdminRestClientAsAnonymous.Get().AbsPath("/healthz/log").DoRaw(ctx)
|
healthzLog, errHealthzLog := impersonationProxyAdminRestClientAsAnonymous.Get().AbsPath("/healthz/log").DoRaw(ctx)
|
||||||
require.True(t, k8serrors.IsForbidden(errHealthzLog), "%s\n%s", library.Sdump(errHealthzLog), string(healthzLog))
|
require.True(t, k8serrors.IsForbidden(errHealthzLog), "%s\n%s", testlib.Sdump(errHealthzLog), string(healthzLog))
|
||||||
require.Equal(t, `{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User \"system:anonymous\" cannot get path \"/healthz/log\": decision made by impersonation-proxy.concierge.pinniped.dev","reason":"Forbidden","details":{},"code":403}`+"\n", string(healthzLog))
|
require.Equal(t, `{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User \"system:anonymous\" cannot get path \"/healthz/log\": decision made by impersonation-proxy.concierge.pinniped.dev","reason":"Forbidden","details":{},"code":403}`+"\n", string(healthzLog))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("anonymous authentication enabled", func(t *testing.T) {
|
t.Run("anonymous authentication enabled", func(t *testing.T) {
|
||||||
library.IntegrationEnv(t).WithCapability(library.AnonymousAuthenticationSupported)
|
testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupported)
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// anonymous auth enabled
|
// anonymous auth enabled
|
||||||
@ -1308,7 +1308,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
healthz, errHealth := impersonationProxyAnonymousRestClient.Get().AbsPath("/healthz").DoRaw(ctx)
|
healthz, errHealth := impersonationProxyAnonymousRestClient.Get().AbsPath("/healthz").DoRaw(ctx)
|
||||||
require.NoError(t, errHealth, library.Sdump(errHealth))
|
require.NoError(t, errHealth, testlib.Sdump(errHealth))
|
||||||
require.Equal(t, "ok", string(healthz))
|
require.Equal(t, "ok", string(healthz))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1321,9 +1321,9 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
pod, err := impersonationProxyAnonymousClient.Kubernetes.CoreV1().Pods(metav1.NamespaceSystem).
|
pod, err := impersonationProxyAnonymousClient.Kubernetes.CoreV1().Pods(metav1.NamespaceSystem).
|
||||||
Get(ctx, "does-not-matter", metav1.GetOptions{})
|
Get(ctx, "does-not-matter", metav1.GetOptions{})
|
||||||
require.True(t, k8serrors.IsForbidden(err), library.Sdump(err))
|
require.True(t, k8serrors.IsForbidden(err), testlib.Sdump(err))
|
||||||
require.EqualError(t, err, `pods "does-not-matter" is forbidden: User "system:anonymous" cannot get resource "pods" in API group "" in the namespace "kube-system": `+
|
require.EqualError(t, err, `pods "does-not-matter" is forbidden: User "system:anonymous" cannot get resource "pods" in API group "" in the namespace "kube-system": `+
|
||||||
`decision made by impersonation-proxy.concierge.pinniped.dev`, library.Sdump(err))
|
`decision made by impersonation-proxy.concierge.pinniped.dev`, testlib.Sdump(err))
|
||||||
require.Equal(t, &corev1.Pod{}, pod)
|
require.Equal(t, &corev1.Pod{}, pod)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1349,7 +1349,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("anonymous authentication disabled", func(t *testing.T) {
|
t.Run("anonymous authentication disabled", func(t *testing.T) {
|
||||||
library.IntegrationEnv(t).WithoutCapability(library.AnonymousAuthenticationSupported)
|
testlib.IntegrationEnv(t).WithoutCapability(testlib.AnonymousAuthenticationSupported)
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// - hit the healthz endpoint (non-resource endpoint)
|
// - hit the healthz endpoint (non-resource endpoint)
|
||||||
@ -1360,7 +1360,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
healthz, err := impersonationProxyAnonymousRestClient.Get().AbsPath("/healthz").DoRaw(ctx)
|
healthz, err := impersonationProxyAnonymousRestClient.Get().AbsPath("/healthz").DoRaw(ctx)
|
||||||
require.True(t, k8serrors.IsUnauthorized(err), library.Sdump(err))
|
require.True(t, k8serrors.IsUnauthorized(err), testlib.Sdump(err))
|
||||||
require.Equal(t, `{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}`+"\n", string(healthz))
|
require.Equal(t, `{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}`+"\n", string(healthz))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1373,7 +1373,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
pod, err := impersonationProxyAnonymousClient.Kubernetes.CoreV1().Pods(metav1.NamespaceSystem).
|
pod, err := impersonationProxyAnonymousClient.Kubernetes.CoreV1().Pods(metav1.NamespaceSystem).
|
||||||
Get(ctx, "does-not-matter", metav1.GetOptions{})
|
Get(ctx, "does-not-matter", metav1.GetOptions{})
|
||||||
require.True(t, k8serrors.IsUnauthorized(err), library.Sdump(err))
|
require.True(t, k8serrors.IsUnauthorized(err), testlib.Sdump(err))
|
||||||
require.Equal(t, &corev1.Pod{}, pod)
|
require.Equal(t, &corev1.Pod{}, pod)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1386,7 +1386,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
whoAmI, err := impersonationProxyAnonymousClient.PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
whoAmI, err := impersonationProxyAnonymousClient.PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.True(t, k8serrors.IsUnauthorized(err), library.Sdump(err))
|
require.True(t, k8serrors.IsUnauthorized(err), testlib.Sdump(err))
|
||||||
require.Equal(t, &identityv1alpha1.WhoAmIRequest{}, whoAmI)
|
require.Equal(t, &identityv1alpha1.WhoAmIRequest{}, whoAmI)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1404,7 +1404,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
// sanity check default expected error message
|
// sanity check default expected error message
|
||||||
_, err := impersonationProxySSRRClient.Create(ctx, invalidSSRR, metav1.CreateOptions{})
|
_, err := impersonationProxySSRRClient.Create(ctx, invalidSSRR, metav1.CreateOptions{})
|
||||||
require.True(t, k8serrors.IsBadRequest(err), library.Sdump(err))
|
require.True(t, k8serrors.IsBadRequest(err), testlib.Sdump(err))
|
||||||
require.EqualError(t, err, "no namespace on request")
|
require.EqualError(t, err, "no namespace on request")
|
||||||
|
|
||||||
// remove the impersonation proxy SA's permissions
|
// remove the impersonation proxy SA's permissions
|
||||||
@ -1434,14 +1434,14 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
_, errUpdate := crbClient.Update(ctx, crbEnd, metav1.UpdateOptions{})
|
_, errUpdate := crbClient.Update(ctx, crbEnd, metav1.UpdateOptions{})
|
||||||
require.NoError(t, errUpdate)
|
require.NoError(t, errUpdate)
|
||||||
|
|
||||||
library.WaitForUserToHaveAccess(t, saFullName, nil, &authorizationv1.ResourceAttributes{
|
testlib.WaitForUserToHaveAccess(t, saFullName, nil, &authorizationv1.ResourceAttributes{
|
||||||
Verb: "impersonate",
|
Verb: "impersonate",
|
||||||
Resource: "users",
|
Resource: "users",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// assert that the impersonation proxy stops working when we remove its permissions
|
// assert that the impersonation proxy stops working when we remove its permissions
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
_, errCreate := impersonationProxySSRRClient.Create(ctx, invalidSSRR, metav1.CreateOptions{})
|
_, errCreate := impersonationProxySSRRClient.Create(ctx, invalidSSRR, metav1.CreateOptions{})
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@ -1491,7 +1491,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
}
|
}
|
||||||
|
|
||||||
waitForServiceAnnotations := func(annotations map[string]string) {
|
waitForServiceAnnotations := func(annotations map[string]string) {
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
service, err := adminClient.CoreV1().Services(env.ConciergeNamespace).Get(ctx, impersonationProxyLoadBalancerName(env), metav1.GetOptions{})
|
service, err := adminClient.CoreV1().Services(env.ConciergeNamespace).Get(ctx, impersonationProxyLoadBalancerName(env), metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -1509,8 +1509,8 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Set a new annotation in the CredentialIssuer spec.impersonationProxy.service.annotations field.
|
// Set a new annotation in the CredentialIssuer spec.impersonationProxy.service.annotations field.
|
||||||
newAnnotationKey := "pinniped.dev/test-" + library.RandHex(t, 8)
|
newAnnotationKey := "pinniped.dev/test-" + testlib.RandHex(t, 8)
|
||||||
newAnnotationValue := "test-" + library.RandHex(t, 8)
|
newAnnotationValue := "test-" + testlib.RandHex(t, 8)
|
||||||
updatedAnnotations := previous.Spec.ImpersonationProxy.Service.DeepCopy().Annotations
|
updatedAnnotations := previous.Spec.ImpersonationProxy.Service.DeepCopy().Annotations
|
||||||
updatedAnnotations[newAnnotationKey] = newAnnotationValue
|
updatedAnnotations[newAnnotationKey] = newAnnotationValue
|
||||||
applyCredentialIssuerAnnotations(updatedAnnotations)
|
applyCredentialIssuerAnnotations(updatedAnnotations)
|
||||||
@ -1535,7 +1535,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
})
|
})
|
||||||
|
|
||||||
// wait until the credential issuer is updated with the new url
|
// wait until the credential issuer is updated with the new url
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
newImpersonationProxyURL, _ := performImpersonatorDiscovery(ctx, t, env, adminConciergeClient)
|
newImpersonationProxyURL, _ := performImpersonatorDiscovery(ctx, t, env, adminConciergeClient)
|
||||||
return newImpersonationProxyURL == "https://"+clusterIPServiceURL, nil
|
return newImpersonationProxyURL == "https://"+clusterIPServiceURL, nil
|
||||||
}, 30*time.Second, 500*time.Millisecond)
|
}, 30*time.Second, 500*time.Millisecond)
|
||||||
@ -1549,7 +1549,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
// everything should work properly through the cluster ip service
|
// everything should work properly through the cluster ip service
|
||||||
t.Run(
|
t.Run(
|
||||||
"access as user",
|
"access as user",
|
||||||
library.AccessAsUserTest(ctx, env.TestUser.ExpectedUsername, client),
|
testlib.AccessAsUserTest(ctx, env.TestUser.ExpectedUsername, client),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1564,7 +1564,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
if clusterSupportsLoadBalancers {
|
if clusterSupportsLoadBalancers {
|
||||||
// The load balancer should have been deleted when we disabled the impersonation proxy.
|
// The load balancer should have been deleted when we disabled the impersonation proxy.
|
||||||
// Note that this can take kind of a long time on real cloud providers (e.g. ~22 seconds on EKS).
|
// Note that this can take kind of a long time on real cloud providers (e.g. ~22 seconds on EKS).
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
hasService, err := hasImpersonationProxyLoadBalancerService(ctx, env, adminClient)
|
hasService, err := hasImpersonationProxyLoadBalancerService(ctx, env, adminClient)
|
||||||
return !hasService, err
|
return !hasService, err
|
||||||
}, 2*time.Minute, 500*time.Millisecond)
|
}, 2*time.Minute, 500*time.Millisecond)
|
||||||
@ -1576,7 +1576,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
// so we'll skip this check on clusters which have load balancers but don't run the squid proxy.
|
// so we'll skip this check on clusters which have load balancers but don't run the squid proxy.
|
||||||
// The other cluster types that do run the squid proxy will give us sufficient coverage here.
|
// The other cluster types that do run the squid proxy will give us sufficient coverage here.
|
||||||
if env.Proxy != "" {
|
if env.Proxy != "" {
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
// It's okay if this returns RBAC errors because this user has no role bindings.
|
// It's okay if this returns RBAC errors because this user has no role bindings.
|
||||||
// What we want to see is that the proxy eventually shuts down entirely.
|
// What we want to see is that the proxy eventually shuts down entirely.
|
||||||
_, err := impersonationProxyViaSquidKubeClientWithoutCredential(t, proxyServiceEndpoint).CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
|
_, err := impersonationProxyViaSquidKubeClientWithoutCredential(t, proxyServiceEndpoint).CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
|
||||||
@ -1587,7 +1587,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
|
|
||||||
// Check that the generated TLS cert Secret was deleted by the controller because it's supposed to clean this up
|
// Check that the generated TLS cert Secret was deleted by the controller because it's supposed to clean this up
|
||||||
// when we disable the impersonator.
|
// when we disable the impersonator.
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
_, err := adminClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName(env), metav1.GetOptions{})
|
_, err := adminClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName(env), metav1.GetOptions{})
|
||||||
requireEventually.Truef(k8serrors.IsNotFound(err), "expected NotFound error, got %v", err)
|
requireEventually.Truef(k8serrors.IsNotFound(err), "expected NotFound error, got %v", err)
|
||||||
}, 10*time.Second, 250*time.Millisecond)
|
}, 10*time.Second, 250*time.Millisecond)
|
||||||
@ -1602,14 +1602,14 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
|||||||
// include an unsuccessful impersonation strategy saying that it was manually configured to be disabled.
|
// include an unsuccessful impersonation strategy saying that it was manually configured to be disabled.
|
||||||
requireDisabledStrategy(ctx, t, env, adminConciergeClient)
|
requireDisabledStrategy(ctx, t, env, adminConciergeClient)
|
||||||
|
|
||||||
if !env.HasCapability(library.ClusterSigningKeyIsAvailable) && env.HasCapability(library.AnonymousAuthenticationSupported) {
|
if !env.HasCapability(testlib.ClusterSigningKeyIsAvailable) && env.HasCapability(testlib.AnonymousAuthenticationSupported) {
|
||||||
// This cluster does not support the cluster signing key strategy, so now that we've manually disabled the
|
// This cluster does not support the cluster signing key strategy, so now that we've manually disabled the
|
||||||
// impersonation strategy, we should be left with no working strategies.
|
// impersonation strategy, we should be left with no working strategies.
|
||||||
// Given that there are no working strategies, a TokenCredentialRequest which would otherwise work should now
|
// Given that there are no working strategies, a TokenCredentialRequest which would otherwise work should now
|
||||||
// fail, because there is no point handing out credentials that are not going to work for any strategy.
|
// fail, because there is no point handing out credentials that are not going to work for any strategy.
|
||||||
// Note that library.CreateTokenCredentialRequest makes an unauthenticated request, so we can't meaningfully
|
// Note that library.CreateTokenCredentialRequest makes an unauthenticated request, so we can't meaningfully
|
||||||
// perform this part of the test on a cluster which does not allow anonymous authentication.
|
// perform this part of the test on a cluster which does not allow anonymous authentication.
|
||||||
tokenCredentialRequestResponse, err := library.CreateTokenCredentialRequest(ctx, t, credentialRequestSpecWithWorkingCredentials)
|
tokenCredentialRequestResponse, err := testlib.CreateTokenCredentialRequest(ctx, t, credentialRequestSpecWithWorkingCredentials)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.NotNil(t, tokenCredentialRequestResponse.Status.Message, "expected an error message but got nil")
|
require.NotNil(t, tokenCredentialRequestResponse.Status.Message, "expected an error message but got nil")
|
||||||
@ -1666,7 +1666,7 @@ func createServiceAccountToken(ctx context.Context, t *testing.T, adminClient ku
|
|||||||
Delete(context.Background(), secret.Name, metav1.DeleteOptions{}))
|
Delete(context.Background(), secret.Name, metav1.DeleteOptions{}))
|
||||||
})
|
})
|
||||||
|
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
secret, err = adminClient.CoreV1().Secrets(namespaceName).Get(ctx, secret.Name, metav1.GetOptions{})
|
secret, err = adminClient.CoreV1().Secrets(namespaceName).Get(ctx, secret.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -1692,7 +1692,7 @@ func expectedWhoAmIRequestResponse(username string, groups []string, extra map[s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func performImpersonatorDiscovery(ctx context.Context, t *testing.T, env *library.TestEnv, adminConciergeClient pinnipedconciergeclientset.Interface) (string, []byte) {
|
func performImpersonatorDiscovery(ctx context.Context, t *testing.T, env *testlib.TestEnv, adminConciergeClient pinnipedconciergeclientset.Interface) (string, []byte) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
var impersonationProxyURL string
|
var impersonationProxyURL string
|
||||||
@ -1700,7 +1700,7 @@ func performImpersonatorDiscovery(ctx context.Context, t *testing.T, env *librar
|
|||||||
|
|
||||||
t.Log("Waiting for CredentialIssuer strategy to be successful")
|
t.Log("Waiting for CredentialIssuer strategy to be successful")
|
||||||
|
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
credentialIssuer, err := adminConciergeClient.ConfigV1alpha1().CredentialIssuers().Get(ctx, credentialIssuerName(env), metav1.GetOptions{})
|
credentialIssuer, err := adminConciergeClient.ConfigV1alpha1().CredentialIssuers().Get(ctx, credentialIssuerName(env), metav1.GetOptions{})
|
||||||
if err != nil || credentialIssuer.Status.Strategies == nil {
|
if err != nil || credentialIssuer.Status.Strategies == nil {
|
||||||
t.Log("Did not find any CredentialIssuer with any strategies")
|
t.Log("Did not find any CredentialIssuer with any strategies")
|
||||||
@ -1738,10 +1738,10 @@ func performImpersonatorDiscovery(ctx context.Context, t *testing.T, env *librar
|
|||||||
return impersonationProxyURL, impersonationProxyCACertPEM
|
return impersonationProxyURL, impersonationProxyCACertPEM
|
||||||
}
|
}
|
||||||
|
|
||||||
func requireDisabledStrategy(ctx context.Context, t *testing.T, env *library.TestEnv, adminConciergeClient pinnipedconciergeclientset.Interface) {
|
func requireDisabledStrategy(ctx context.Context, t *testing.T, env *testlib.TestEnv, adminConciergeClient pinnipedconciergeclientset.Interface) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
credentialIssuer, err := adminConciergeClient.ConfigV1alpha1().CredentialIssuers().Get(ctx, credentialIssuerName(env), metav1.GetOptions{})
|
credentialIssuer, err := adminConciergeClient.ConfigV1alpha1().CredentialIssuers().Get(ctx, credentialIssuerName(env), metav1.GetOptions{})
|
||||||
if err != nil || credentialIssuer.Status.Strategies == nil {
|
if err != nil || credentialIssuer.Status.Strategies == nil {
|
||||||
t.Log("Did not find any CredentialIssuer with any strategies")
|
t.Log("Did not find any CredentialIssuer with any strategies")
|
||||||
@ -1812,12 +1812,12 @@ func kubeconfigProxyFunc(t *testing.T, squidProxyURL string) func(req *http.Requ
|
|||||||
|
|
||||||
parsedSquidProxyURL, err := url.Parse(squidProxyURL)
|
parsedSquidProxyURL, err := url.Parse(squidProxyURL)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Logf("passing request for %s through proxy %s", library.RedactURLParams(req.URL), parsedSquidProxyURL.String())
|
t.Logf("passing request for %s through proxy %s", testlib.RedactURLParams(req.URL), parsedSquidProxyURL.String())
|
||||||
return parsedSquidProxyURL, nil
|
return parsedSquidProxyURL, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateCredentialIssuer(ctx context.Context, t *testing.T, env *library.TestEnv, adminConciergeClient pinnipedconciergeclientset.Interface, spec conciergev1alpha.CredentialIssuerSpec) {
|
func updateCredentialIssuer(ctx context.Context, t *testing.T, env *testlib.TestEnv, adminConciergeClient pinnipedconciergeclientset.Interface, spec conciergev1alpha.CredentialIssuerSpec) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||||
@ -1832,7 +1832,7 @@ func updateCredentialIssuer(ctx context.Context, t *testing.T, env *library.Test
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasImpersonationProxyLoadBalancerService(ctx context.Context, env *library.TestEnv, client kubernetes.Interface) (bool, error) {
|
func hasImpersonationProxyLoadBalancerService(ctx context.Context, env *testlib.TestEnv, client kubernetes.Interface) (bool, error) {
|
||||||
service, err := client.CoreV1().Services(env.ConciergeNamespace).Get(ctx, impersonationProxyLoadBalancerName(env), metav1.GetOptions{})
|
service, err := client.CoreV1().Services(env.ConciergeNamespace).Get(ctx, impersonationProxyLoadBalancerName(env), metav1.GetOptions{})
|
||||||
if k8serrors.IsNotFound(err) {
|
if k8serrors.IsNotFound(err) {
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -1843,34 +1843,34 @@ func hasImpersonationProxyLoadBalancerService(ctx context.Context, env *library.
|
|||||||
return service.Spec.Type == corev1.ServiceTypeLoadBalancer, nil
|
return service.Spec.Type == corev1.ServiceTypeLoadBalancer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func impersonationProxyTLSSecretName(env *library.TestEnv) string {
|
func impersonationProxyTLSSecretName(env *testlib.TestEnv) string {
|
||||||
return env.ConciergeAppName + "-impersonation-proxy-tls-serving-certificate"
|
return env.ConciergeAppName + "-impersonation-proxy-tls-serving-certificate"
|
||||||
}
|
}
|
||||||
|
|
||||||
func impersonationProxyCASecretName(env *library.TestEnv) string {
|
func impersonationProxyCASecretName(env *testlib.TestEnv) string {
|
||||||
return env.ConciergeAppName + "-impersonation-proxy-ca-certificate"
|
return env.ConciergeAppName + "-impersonation-proxy-ca-certificate"
|
||||||
}
|
}
|
||||||
|
|
||||||
func impersonationProxyLoadBalancerName(env *library.TestEnv) string {
|
func impersonationProxyLoadBalancerName(env *testlib.TestEnv) string {
|
||||||
return env.ConciergeAppName + "-impersonation-proxy-load-balancer"
|
return env.ConciergeAppName + "-impersonation-proxy-load-balancer"
|
||||||
}
|
}
|
||||||
|
|
||||||
func impersonationProxyClusterIPName(env *library.TestEnv) string {
|
func impersonationProxyClusterIPName(env *testlib.TestEnv) string {
|
||||||
return env.ConciergeAppName + "-impersonation-proxy-cluster-ip"
|
return env.ConciergeAppName + "-impersonation-proxy-cluster-ip"
|
||||||
}
|
}
|
||||||
|
|
||||||
func credentialIssuerName(env *library.TestEnv) string {
|
func credentialIssuerName(env *testlib.TestEnv) string {
|
||||||
return env.ConciergeAppName + "-config"
|
return env.ConciergeAppName + "-config"
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImpersonationKubeconfig(t *testing.T, env *library.TestEnv, impersonationProxyURL string, impersonationProxyCACertPEM []byte, authenticator corev1.TypedLocalObjectReference) (string, []string, string) {
|
func getImpersonationKubeconfig(t *testing.T, env *testlib.TestEnv, impersonationProxyURL string, impersonationProxyCACertPEM []byte, authenticator corev1.TypedLocalObjectReference) (string, []string, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
pinnipedExe := library.PinnipedCLIPath(t)
|
pinnipedExe := testlib.PinnipedCLIPath(t)
|
||||||
tempDir := testutil.TempDir(t)
|
tempDir := testutil.TempDir(t)
|
||||||
|
|
||||||
var envVarsWithProxy []string
|
var envVarsWithProxy []string
|
||||||
if !env.HasCapability(library.HasExternalLoadBalancerProvider) {
|
if !env.HasCapability(testlib.HasExternalLoadBalancerProvider) {
|
||||||
// Only if you don't have a load balancer, use the squid proxy when it's available.
|
// Only if you don't have a load balancer, use the squid proxy when it's available.
|
||||||
envVarsWithProxy = append(os.Environ(), env.ProxyEnv()...)
|
envVarsWithProxy = append(os.Environ(), env.ProxyEnv()...)
|
||||||
}
|
}
|
||||||
@ -1991,8 +1991,8 @@ func createTokenCredentialRequest(
|
|||||||
func newImpersonationProxyClientWithCredentials(t *testing.T, credentials *loginv1alpha1.ClusterCredential, impersonationProxyURL string, impersonationProxyCACertPEM []byte, nestedImpersonationConfig *rest.ImpersonationConfig) *kubeclient.Client {
|
func newImpersonationProxyClientWithCredentials(t *testing.T, credentials *loginv1alpha1.ClusterCredential, impersonationProxyURL string, impersonationProxyCACertPEM []byte, nestedImpersonationConfig *rest.ImpersonationConfig) *kubeclient.Client {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
clusterSupportsLoadBalancers := env.HasCapability(library.HasExternalLoadBalancerProvider)
|
clusterSupportsLoadBalancers := env.HasCapability(testlib.HasExternalLoadBalancerProvider)
|
||||||
|
|
||||||
kubeconfig := impersonationProxyRestConfig(credentials, impersonationProxyURL, impersonationProxyCACertPEM, nestedImpersonationConfig)
|
kubeconfig := impersonationProxyRestConfig(credentials, impersonationProxyURL, impersonationProxyCACertPEM, nestedImpersonationConfig)
|
||||||
if !clusterSupportsLoadBalancers {
|
if !clusterSupportsLoadBalancers {
|
||||||
@ -2000,7 +2000,7 @@ func newImpersonationProxyClientWithCredentials(t *testing.T, credentials *login
|
|||||||
// Prefer to go through a load balancer because that's how the impersonator is intended to be used in the real world.
|
// Prefer to go through a load balancer because that's how the impersonator is intended to be used in the real world.
|
||||||
kubeconfig.Proxy = kubeconfigProxyFunc(t, env.Proxy)
|
kubeconfig.Proxy = kubeconfigProxyFunc(t, env.Proxy)
|
||||||
}
|
}
|
||||||
return library.NewKubeclient(t, kubeconfig)
|
return testlib.NewKubeclient(t, kubeconfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAnonymousImpersonationProxyClient(t *testing.T, impersonationProxyURL string, impersonationProxyCACertPEM []byte, nestedImpersonationConfig *rest.ImpersonationConfig) *kubeclient.Client {
|
func newAnonymousImpersonationProxyClient(t *testing.T, impersonationProxyURL string, impersonationProxyCACertPEM []byte, nestedImpersonationConfig *rest.ImpersonationConfig) *kubeclient.Client {
|
||||||
@ -2013,34 +2013,34 @@ func newAnonymousImpersonationProxyClient(t *testing.T, impersonationProxyURL st
|
|||||||
func newImpersonationProxyClientWithCredentialsAndProxy(t *testing.T, credentials *loginv1alpha1.ClusterCredential, impersonationProxyURL string, impersonationProxyCACertPEM []byte, nestedImpersonationConfig *rest.ImpersonationConfig) *kubeclient.Client {
|
func newImpersonationProxyClientWithCredentialsAndProxy(t *testing.T, credentials *loginv1alpha1.ClusterCredential, impersonationProxyURL string, impersonationProxyCACertPEM []byte, nestedImpersonationConfig *rest.ImpersonationConfig) *kubeclient.Client {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
kubeconfig := impersonationProxyRestConfig(credentials, impersonationProxyURL, impersonationProxyCACertPEM, nestedImpersonationConfig)
|
kubeconfig := impersonationProxyRestConfig(credentials, impersonationProxyURL, impersonationProxyCACertPEM, nestedImpersonationConfig)
|
||||||
kubeconfig.Proxy = kubeconfigProxyFunc(t, env.Proxy)
|
kubeconfig.Proxy = kubeconfigProxyFunc(t, env.Proxy)
|
||||||
return library.NewKubeclient(t, kubeconfig)
|
return testlib.NewKubeclient(t, kubeconfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// this uses a proxy in all cases, the other will only use it if you don't have load balancer capabilities.
|
// this uses a proxy in all cases, the other will only use it if you don't have load balancer capabilities.
|
||||||
func newAnonymousImpersonationProxyClientWithProxy(t *testing.T, impersonationProxyURL string, impersonationProxyCACertPEM []byte, nestedImpersonationConfig *rest.ImpersonationConfig) *kubeclient.Client {
|
func newAnonymousImpersonationProxyClientWithProxy(t *testing.T, impersonationProxyURL string, impersonationProxyCACertPEM []byte, nestedImpersonationConfig *rest.ImpersonationConfig) *kubeclient.Client {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
emptyCredentials := &loginv1alpha1.ClusterCredential{}
|
emptyCredentials := &loginv1alpha1.ClusterCredential{}
|
||||||
kubeconfig := impersonationProxyRestConfig(emptyCredentials, impersonationProxyURL, impersonationProxyCACertPEM, nestedImpersonationConfig)
|
kubeconfig := impersonationProxyRestConfig(emptyCredentials, impersonationProxyURL, impersonationProxyCACertPEM, nestedImpersonationConfig)
|
||||||
|
|
||||||
kubeconfig.Proxy = kubeconfigProxyFunc(t, env.Proxy)
|
kubeconfig.Proxy = kubeconfigProxyFunc(t, env.Proxy)
|
||||||
|
|
||||||
return library.NewKubeclient(t, kubeconfig)
|
return testlib.NewKubeclient(t, kubeconfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func impersonationProxyViaSquidKubeClientWithoutCredential(t *testing.T, proxyServiceEndpoint string) kubernetes.Interface {
|
func impersonationProxyViaSquidKubeClientWithoutCredential(t *testing.T, proxyServiceEndpoint string) kubernetes.Interface {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
proxyURL := "https://" + proxyServiceEndpoint
|
proxyURL := "https://" + proxyServiceEndpoint
|
||||||
kubeconfig := impersonationProxyRestConfig(&loginv1alpha1.ClusterCredential{}, proxyURL, nil, nil)
|
kubeconfig := impersonationProxyRestConfig(&loginv1alpha1.ClusterCredential{}, proxyURL, nil, nil)
|
||||||
kubeconfig.Proxy = kubeconfigProxyFunc(t, env.Proxy)
|
kubeconfig.Proxy = kubeconfigProxyFunc(t, env.Proxy)
|
||||||
return library.NewKubeclient(t, kubeconfig).Kubernetes
|
return testlib.NewKubeclient(t, kubeconfig).Kubernetes
|
||||||
}
|
}
|
||||||
|
|
||||||
func newImpersonationProxyClient(
|
func newImpersonationProxyClient(
|
||||||
|
@ -17,18 +17,18 @@ import (
|
|||||||
"k8s.io/utils/pointer"
|
"k8s.io/utils/pointer"
|
||||||
|
|
||||||
conciergev1alpha "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
conciergev1alpha "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestKubeCertAgent(t *testing.T) {
|
func TestKubeCertAgent(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
|
env := testlib.IntegrationEnv(t).WithCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
kubeClient := library.NewKubernetesClientset(t)
|
kubeClient := testlib.NewKubernetesClientset(t)
|
||||||
adminConciergeClient := library.NewConciergeClientset(t)
|
adminConciergeClient := testlib.NewConciergeClientset(t)
|
||||||
|
|
||||||
// Expect there to be at least on healthy kube-cert-agent pod on this cluster.
|
// Expect there to be at least on healthy kube-cert-agent pod on this cluster.
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
agentPods, err := kubeClient.CoreV1().Pods(env.ConciergeNamespace).List(ctx, metav1.ListOptions{
|
agentPods, err := kubeClient.CoreV1().Pods(env.ConciergeNamespace).List(ctx, metav1.ListOptions{
|
||||||
@ -50,7 +50,7 @@ func TestKubeCertAgent(t *testing.T) {
|
|||||||
}, 1*time.Minute, 2*time.Second, "never saw a healthy kube-cert-agent Pod running")
|
}, 1*time.Minute, 2*time.Second, "never saw a healthy kube-cert-agent Pod running")
|
||||||
|
|
||||||
// Expect that the CredentialIssuer will have a healthy KubeClusterSigningCertificate strategy.
|
// Expect that the CredentialIssuer will have a healthy KubeClusterSigningCertificate strategy.
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
credentialIssuer, err := adminConciergeClient.ConfigV1alpha1().CredentialIssuers().Get(ctx, credentialIssuerName(env), metav1.GetOptions{})
|
credentialIssuer, err := adminConciergeClient.ConfigV1alpha1().CredentialIssuers().Get(ctx, credentialIssuerName(env), metav1.GetOptions{})
|
||||||
@ -94,10 +94,10 @@ func findSuccessfulStrategy(credentialIssuer *conciergev1alpha.CredentialIssuer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLegacyPodCleaner(t *testing.T) {
|
func TestLegacyPodCleaner(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
|
env := testlib.IntegrationEnv(t).WithCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
kubeClient := library.NewKubernetesClientset(t)
|
kubeClient := testlib.NewKubernetesClientset(t)
|
||||||
|
|
||||||
// Pick the same labels that the legacy code would have used to run the kube-cert-agent pod.
|
// Pick the same labels that the legacy code would have used to run the kube-cert-agent pod.
|
||||||
legacyAgentLabels := map[string]string{}
|
legacyAgentLabels := map[string]string{}
|
||||||
@ -137,7 +137,7 @@ func TestLegacyPodCleaner(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Expect the legacy-pod-cleaner controller to delete the pod.
|
// Expect the legacy-pod-cleaner controller to delete the pod.
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
_, err := kubeClient.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
|
_, err := kubeClient.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
|
||||||
if k8serrors.IsNotFound(err) {
|
if k8serrors.IsNotFound(err) {
|
||||||
t.Logf("fake legacy agent pod %s/%s was deleted as expected", pod.Namespace, pod.Name)
|
t.Logf("fake legacy agent pod %s/%s was deleted as expected", pod.Namespace, pod.Name)
|
||||||
|
@ -10,12 +10,12 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Smoke test to see if the kubeconfig works and the cluster is reachable.
|
// Smoke test to see if the kubeconfig works and the cluster is reachable.
|
||||||
func TestGetNodes(t *testing.T) {
|
func TestGetNodes(t *testing.T) {
|
||||||
library.SkipUnlessIntegration(t)
|
testlib.SkipUnlessIntegration(t)
|
||||||
cmd := exec.Command("kubectl", "get", "nodes")
|
cmd := exec.Command("kubectl", "get", "nodes")
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
@ -42,19 +42,19 @@ import (
|
|||||||
"go.pinniped.dev/internal/testutil"
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/pkg/oidcclient"
|
"go.pinniped.dev/pkg/oidcclient"
|
||||||
"go.pinniped.dev/pkg/oidcclient/filesession"
|
"go.pinniped.dev/pkg/oidcclient/filesession"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
"go.pinniped.dev/test/library/browsertest"
|
"go.pinniped.dev/test/testlib/browsertest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestE2EFullIntegration tests a full integration scenario that combines the supervisor, concierge, and CLI.
|
// TestE2EFullIntegration tests a full integration scenario that combines the supervisor, concierge, and CLI.
|
||||||
func TestE2EFullIntegration(t *testing.T) {
|
func TestE2EFullIntegration(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithTimeout(context.Background(), 15*time.Minute)
|
ctx, cancelFunc := context.WithTimeout(context.Background(), 15*time.Minute)
|
||||||
defer cancelFunc()
|
defer cancelFunc()
|
||||||
|
|
||||||
// Build pinniped CLI.
|
// Build pinniped CLI.
|
||||||
pinnipedExe := library.PinnipedCLIPath(t)
|
pinnipedExe := testlib.PinnipedCLIPath(t)
|
||||||
tempDir := testutil.TempDir(t)
|
tempDir := testutil.TempDir(t)
|
||||||
|
|
||||||
// Start the browser driver.
|
// Start the browser driver.
|
||||||
@ -86,7 +86,7 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Write the serving cert to a secret.
|
// Write the serving cert to a secret.
|
||||||
certSecret := library.CreateTestSecret(t,
|
certSecret := testlib.CreateTestSecret(t,
|
||||||
env.SupervisorNamespace,
|
env.SupervisorNamespace,
|
||||||
"oidc-provider-tls",
|
"oidc-provider-tls",
|
||||||
corev1.SecretTypeTLS,
|
corev1.SecretTypeTLS,
|
||||||
@ -94,15 +94,15 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Create the downstream FederationDomain and expect it to go into the success status condition.
|
// Create the downstream FederationDomain and expect it to go into the success status condition.
|
||||||
downstream := library.CreateTestFederationDomain(ctx, t,
|
downstream := testlib.CreateTestFederationDomain(ctx, t,
|
||||||
issuerURL.String(),
|
issuerURL.String(),
|
||||||
certSecret.Name,
|
certSecret.Name,
|
||||||
configv1alpha1.SuccessFederationDomainStatusCondition,
|
configv1alpha1.SuccessFederationDomainStatusCondition,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create a JWTAuthenticator that will validate the tokens from the downstream issuer.
|
// Create a JWTAuthenticator that will validate the tokens from the downstream issuer.
|
||||||
clusterAudience := "test-cluster-" + library.RandHex(t, 8)
|
clusterAudience := "test-cluster-" + testlib.RandHex(t, 8)
|
||||||
authenticator := library.CreateTestJWTAuthenticator(ctx, t, authv1alpha.JWTAuthenticatorSpec{
|
authenticator := testlib.CreateTestJWTAuthenticator(ctx, t, authv1alpha.JWTAuthenticatorSpec{
|
||||||
Issuer: downstream.Spec.Issuer,
|
Issuer: downstream.Spec.Issuer,
|
||||||
Audience: clusterAudience,
|
Audience: clusterAudience,
|
||||||
TLS: &authv1alpha.TLSSpec{CertificateAuthorityData: testCABundleBase64},
|
TLS: &authv1alpha.TLSSpec{CertificateAuthorityData: testCABundleBase64},
|
||||||
@ -114,11 +114,11 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
expectedGroups := env.SupervisorUpstreamOIDC.ExpectedGroups
|
expectedGroups := env.SupervisorUpstreamOIDC.ExpectedGroups
|
||||||
|
|
||||||
// Create a ClusterRoleBinding to give our test user from the upstream read-only access to the cluster.
|
// Create a ClusterRoleBinding to give our test user from the upstream read-only access to the cluster.
|
||||||
library.CreateTestClusterRoleBinding(t,
|
testlib.CreateTestClusterRoleBinding(t,
|
||||||
rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: expectedUsername},
|
rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: expectedUsername},
|
||||||
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "view"},
|
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "view"},
|
||||||
)
|
)
|
||||||
library.WaitForUserToHaveAccess(t, expectedUsername, []string{}, &authorizationv1.ResourceAttributes{
|
testlib.WaitForUserToHaveAccess(t, expectedUsername, []string{}, &authorizationv1.ResourceAttributes{
|
||||||
Verb: "get",
|
Verb: "get",
|
||||||
Group: "",
|
Group: "",
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
@ -126,7 +126,7 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Create upstream OIDC provider and wait for it to become ready.
|
// Create upstream OIDC provider and wait for it to become ready.
|
||||||
library.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{
|
testlib.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{
|
||||||
Issuer: env.SupervisorUpstreamOIDC.Issuer,
|
Issuer: env.SupervisorUpstreamOIDC.Issuer,
|
||||||
TLS: &idpv1alpha1.TLSSpec{
|
TLS: &idpv1alpha1.TLSSpec{
|
||||||
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamOIDC.CABundle)),
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamOIDC.CABundle)),
|
||||||
@ -139,7 +139,7 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
Groups: env.SupervisorUpstreamOIDC.GroupsClaim,
|
Groups: env.SupervisorUpstreamOIDC.GroupsClaim,
|
||||||
},
|
},
|
||||||
Client: idpv1alpha1.OIDCClient{
|
Client: idpv1alpha1.OIDCClient{
|
||||||
SecretName: library.CreateClientCredsSecret(t, env.SupervisorUpstreamOIDC.ClientID, env.SupervisorUpstreamOIDC.ClientSecret).Name,
|
SecretName: testlib.CreateClientCredsSecret(t, env.SupervisorUpstreamOIDC.ClientID, env.SupervisorUpstreamOIDC.ClientSecret).Name,
|
||||||
},
|
},
|
||||||
}, idpv1alpha1.PhaseReady)
|
}, idpv1alpha1.PhaseReady)
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
reader := bufio.NewReader(library.NewLoggerReader(t, "stderr", stderrPipe))
|
reader := bufio.NewReader(testlib.NewLoggerReader(t, "stderr", stderrPipe))
|
||||||
line, err := reader.ReadString('\n')
|
line, err := reader.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not read login URL line from stderr: %w", err)
|
return fmt.Errorf("could not read login URL line from stderr: %w", err)
|
||||||
@ -277,7 +277,7 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
|
|
||||||
// Add an LDAP upstream IDP and try using it to authenticate during kubectl commands.
|
// Add an LDAP upstream IDP and try using it to authenticate during kubectl commands.
|
||||||
t.Run("with Supervisor LDAP upstream IDP", func(t *testing.T) {
|
t.Run("with Supervisor LDAP upstream IDP", func(t *testing.T) {
|
||||||
if len(env.ToolsNamespace) == 0 && !env.HasCapability(library.CanReachInternetLDAPPorts) {
|
if len(env.ToolsNamespace) == 0 && !env.HasCapability(testlib.CanReachInternetLDAPPorts) {
|
||||||
t.Skip("LDAP integration test requires connectivity to an LDAP server")
|
t.Skip("LDAP integration test requires connectivity to an LDAP server")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,11 +285,11 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
expectedGroups := env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs
|
expectedGroups := env.SupervisorUpstreamLDAP.TestUserDirectGroupsDNs
|
||||||
|
|
||||||
// Create a ClusterRoleBinding to give our test user from the upstream read-only access to the cluster.
|
// Create a ClusterRoleBinding to give our test user from the upstream read-only access to the cluster.
|
||||||
library.CreateTestClusterRoleBinding(t,
|
testlib.CreateTestClusterRoleBinding(t,
|
||||||
rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: expectedUsername},
|
rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: expectedUsername},
|
||||||
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "view"},
|
rbacv1.RoleRef{Kind: "ClusterRole", APIGroup: rbacv1.GroupName, Name: "view"},
|
||||||
)
|
)
|
||||||
library.WaitForUserToHaveAccess(t, expectedUsername, []string{}, &authorizationv1.ResourceAttributes{
|
testlib.WaitForUserToHaveAccess(t, expectedUsername, []string{}, &authorizationv1.ResourceAttributes{
|
||||||
Verb: "get",
|
Verb: "get",
|
||||||
Group: "",
|
Group: "",
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
@ -297,7 +297,7 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Put the bind service account's info into a Secret.
|
// Put the bind service account's info into a Secret.
|
||||||
bindSecret := library.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", corev1.SecretTypeBasicAuth,
|
bindSecret := testlib.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", corev1.SecretTypeBasicAuth,
|
||||||
map[string]string{
|
map[string]string{
|
||||||
corev1.BasicAuthUsernameKey: env.SupervisorUpstreamLDAP.BindUsername,
|
corev1.BasicAuthUsernameKey: env.SupervisorUpstreamLDAP.BindUsername,
|
||||||
corev1.BasicAuthPasswordKey: env.SupervisorUpstreamLDAP.BindPassword,
|
corev1.BasicAuthPasswordKey: env.SupervisorUpstreamLDAP.BindPassword,
|
||||||
@ -305,7 +305,7 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Create upstream LDAP provider and wait for it to become ready.
|
// Create upstream LDAP provider and wait for it to become ready.
|
||||||
library.CreateTestLDAPIdentityProvider(t, idpv1alpha1.LDAPIdentityProviderSpec{
|
testlib.CreateTestLDAPIdentityProvider(t, idpv1alpha1.LDAPIdentityProviderSpec{
|
||||||
Host: env.SupervisorUpstreamLDAP.Host,
|
Host: env.SupervisorUpstreamLDAP.Host,
|
||||||
TLS: &idpv1alpha1.TLSSpec{
|
TLS: &idpv1alpha1.TLSSpec{
|
||||||
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.CABundle)),
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.CABundle)),
|
||||||
@ -379,7 +379,7 @@ func TestE2EFullIntegration(t *testing.T) {
|
|||||||
func readFromFileUntilStringIsSeen(t *testing.T, f *os.File, until string) {
|
func readFromFileUntilStringIsSeen(t *testing.T, f *os.File, until string) {
|
||||||
readFromFile := ""
|
readFromFile := ""
|
||||||
|
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
someOutput, foundEOF := readAvailableOutput(t, f)
|
someOutput, foundEOF := readAvailableOutput(t, f)
|
||||||
readFromFile += someOutput
|
readFromFile += someOutput
|
||||||
if strings.Contains(readFromFile, until) {
|
if strings.Contains(readFromFile, until) {
|
||||||
@ -407,7 +407,7 @@ func readAvailableOutput(t *testing.T, r io.Reader) (string, bool) {
|
|||||||
func requireUserCanUseKubectlWithoutAuthenticatingAgain(
|
func requireUserCanUseKubectlWithoutAuthenticatingAgain(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
env *library.TestEnv,
|
env *testlib.TestEnv,
|
||||||
downstream *configv1alpha1.FederationDomain,
|
downstream *configv1alpha1.FederationDomain,
|
||||||
kubeconfigPath string,
|
kubeconfigPath string,
|
||||||
sessionCachePath string,
|
sessionCachePath string,
|
||||||
@ -485,7 +485,7 @@ func requireGCAnnotationsOnSessionStorage(ctx context.Context, t *testing.T, sup
|
|||||||
// check that the access token is new (since it's just been refreshed) and has close to two minutes left.
|
// check that the access token is new (since it's just been refreshed) and has close to two minutes left.
|
||||||
testutil.RequireTimeInDelta(t, startTime.Add(2*time.Minute), token.AccessToken.Expiry.Time, 15*time.Second)
|
testutil.RequireTimeInDelta(t, startTime.Add(2*time.Minute), token.AccessToken.Expiry.Time, 15*time.Second)
|
||||||
|
|
||||||
kubeClient := library.NewKubernetesClientset(t).CoreV1()
|
kubeClient := testlib.NewKubernetesClientset(t).CoreV1()
|
||||||
|
|
||||||
// get the access token secret that matches the signature from the cache
|
// get the access token secret that matches the signature from the cache
|
||||||
accessTokenSignature := strings.Split(token.AccessToken.Token, ".")[1]
|
accessTokenSignature := strings.Split(token.AccessToken.Token, ".")[1]
|
||||||
@ -515,14 +515,14 @@ func requireGCAnnotationsOnSessionStorage(ctx context.Context, t *testing.T, sup
|
|||||||
testutil.RequireTimeInDelta(t, accessTokenGCTime, refreshTokenGCTime, 1*time.Minute)
|
testutil.RequireTimeInDelta(t, accessTokenGCTime, refreshTokenGCTime, 1*time.Minute)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPinnipedGetKubeconfig(t *testing.T, env *library.TestEnv, pinnipedExe string, tempDir string, pinnipedCLICommand []string) string {
|
func runPinnipedGetKubeconfig(t *testing.T, env *testlib.TestEnv, pinnipedExe string, tempDir string, pinnipedCLICommand []string) string {
|
||||||
// Run "pinniped get kubeconfig" to get a kubeconfig YAML.
|
// Run "pinniped get kubeconfig" to get a kubeconfig YAML.
|
||||||
envVarsWithProxy := append(os.Environ(), env.ProxyEnv()...)
|
envVarsWithProxy := append(os.Environ(), env.ProxyEnv()...)
|
||||||
kubeconfigYAML, stderr := runPinnipedCLI(t, envVarsWithProxy, pinnipedExe, pinnipedCLICommand...)
|
kubeconfigYAML, stderr := runPinnipedCLI(t, envVarsWithProxy, pinnipedExe, pinnipedCLICommand...)
|
||||||
t.Logf("stderr output from 'pinniped get kubeconfig':\n%s\n\n", stderr)
|
t.Logf("stderr output from 'pinniped get kubeconfig':\n%s\n\n", stderr)
|
||||||
t.Logf("test kubeconfig:\n%s\n\n", kubeconfigYAML)
|
t.Logf("test kubeconfig:\n%s\n\n", kubeconfigYAML)
|
||||||
|
|
||||||
restConfig := library.NewRestConfigFromKubeconfig(t, kubeconfigYAML)
|
restConfig := testlib.NewRestConfigFromKubeconfig(t, kubeconfigYAML)
|
||||||
require.NotNil(t, restConfig.ExecProvider)
|
require.NotNil(t, restConfig.ExecProvider)
|
||||||
require.Equal(t, []string{"login", "oidc"}, restConfig.ExecProvider.Args[:2])
|
require.Equal(t, []string{"login", "oidc"}, restConfig.ExecProvider.Args[:2])
|
||||||
|
|
||||||
|
@ -16,13 +16,13 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/client-go/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
|
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetAPIResourceList(t *testing.T) {
|
func TestGetAPIResourceList(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
client := library.NewKubernetesClientset(t)
|
client := testlib.NewKubernetesClientset(t)
|
||||||
groups, resources, err := client.Discovery().ServerGroupsAndResources()
|
groups, resources, err := client.Discovery().ServerGroupsAndResources()
|
||||||
|
|
||||||
// discovery can have partial failures when an API service is unavailable (i.e. because of TestAPIServingCertificateAutoCreationAndRotation)
|
// discovery can have partial failures when an API service is unavailable (i.e. because of TestAPIServingCertificateAutoCreationAndRotation)
|
||||||
|
@ -22,14 +22,14 @@ import (
|
|||||||
"go.pinniped.dev/internal/groupsuffix"
|
"go.pinniped.dev/internal/groupsuffix"
|
||||||
"go.pinniped.dev/internal/kubeclient"
|
"go.pinniped.dev/internal/kubeclient"
|
||||||
"go.pinniped.dev/internal/ownerref"
|
"go.pinniped.dev/internal/ownerref"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestKubeClientOwnerRef(t *testing.T) {
|
func TestKubeClientOwnerRef(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
regularClient := library.NewKubernetesClientset(t)
|
regularClient := testlib.NewKubernetesClientset(t)
|
||||||
regularAggregationClient := library.NewAggregatedClientset(t)
|
regularAggregationClient := testlib.NewAggregatedClientset(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -75,7 +75,7 @@ func TestKubeClientOwnerRef(t *testing.T) {
|
|||||||
UID: parentSecret.UID,
|
UID: parentSecret.UID,
|
||||||
}
|
}
|
||||||
|
|
||||||
snorlaxAPIGroup := fmt.Sprintf("%s.snorlax.dev", library.RandHex(t, 8))
|
snorlaxAPIGroup := fmt.Sprintf("%s.snorlax.dev", testlib.RandHex(t, 8))
|
||||||
parentAPIService, err := regularAggregationClient.ApiregistrationV1().APIServices().Create(
|
parentAPIService, err := regularAggregationClient.ApiregistrationV1().APIServices().Create(
|
||||||
ctx,
|
ctx,
|
||||||
&apiregistrationv1.APIService{
|
&apiregistrationv1.APIService{
|
||||||
@ -114,7 +114,7 @@ func TestKubeClientOwnerRef(t *testing.T) {
|
|||||||
UID: parentAPIService.UID,
|
UID: parentAPIService.UID,
|
||||||
}
|
}
|
||||||
|
|
||||||
apiServiceRef, err := apiserviceref.New(parentAPIService.Name, kubeclient.WithConfig(library.NewClientConfig(t)))
|
apiServiceRef, err := apiserviceref.New(parentAPIService.Name, kubeclient.WithConfig(testlib.NewClientConfig(t)))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// create a client that should set an owner ref back to parent on create
|
// create a client that should set an owner ref back to parent on create
|
||||||
@ -122,7 +122,7 @@ func TestKubeClientOwnerRef(t *testing.T) {
|
|||||||
kubeclient.WithMiddleware(ownerref.New(parentSecret)), // secret owner ref first when possible
|
kubeclient.WithMiddleware(ownerref.New(parentSecret)), // secret owner ref first when possible
|
||||||
apiServiceRef, // api service for everything else
|
apiServiceRef, // api service for everything else
|
||||||
kubeclient.WithMiddleware(groupsuffix.New(env.APIGroupSuffix)),
|
kubeclient.WithMiddleware(groupsuffix.New(env.APIGroupSuffix)),
|
||||||
kubeclient.WithConfig(library.NewClientConfig(t)),
|
kubeclient.WithConfig(testlib.NewClientConfig(t)),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ func TestKubeClientOwnerRef(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// cluster scoped API service should be owned by the other one we created above
|
// cluster scoped API service should be owned by the other one we created above
|
||||||
pandasAPIGroup := fmt.Sprintf("%s.pandas.dev", library.RandHex(t, 8))
|
pandasAPIGroup := fmt.Sprintf("%s.pandas.dev", testlib.RandHex(t, 8))
|
||||||
apiService, err := ownerRefClient.Aggregation.ApiregistrationV1().APIServices().Create(
|
apiService, err := ownerRefClient.Aggregation.ApiregistrationV1().APIServices().Create(
|
||||||
ctx,
|
ctx,
|
||||||
&apiregistrationv1.APIService{
|
&apiregistrationv1.APIService{
|
||||||
@ -305,7 +305,7 @@ func hasOwnerRef(t *testing.T, obj metav1.Object, ref metav1.OwnerReference) {
|
|||||||
func isEventuallyDeleted(t *testing.T, f func() error) {
|
func isEventuallyDeleted(t *testing.T, f func() error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
err := f()
|
err := f()
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
|
@ -21,11 +21,11 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/upstreamldap"
|
"go.pinniped.dev/internal/upstreamldap"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLDAPSearch(t *testing.T) {
|
func TestLDAPSearch(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
// Note that these tests depend on the values hard-coded in the LDIF file in test/deploy/tools/ldap.yaml.
|
// Note that these tests depend on the values hard-coded in the LDIF file in test/deploy/tools/ldap.yaml.
|
||||||
// It requires the test LDAP server from the tools deployment.
|
// It requires the test LDAP server from the tools deployment.
|
||||||
@ -613,7 +613,7 @@ func TestLDAPSearch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSimultaneousLDAPRequestsOnSingleProvider(t *testing.T) {
|
func TestSimultaneousLDAPRequestsOnSingleProvider(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
// Note that these tests depend on the values hard-coded in the LDIF file in test/deploy/tools/ldap.yaml.
|
// Note that these tests depend on the values hard-coded in the LDIF file in test/deploy/tools/ldap.yaml.
|
||||||
// It requires the test LDAP server from the tools deployment.
|
// It requires the test LDAP server from the tools deployment.
|
||||||
@ -673,7 +673,7 @@ type authUserResult struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultProviderConfig(env *library.TestEnv, port string) *upstreamldap.ProviderConfig {
|
func defaultProviderConfig(env *testlib.TestEnv, port string) *upstreamldap.ProviderConfig {
|
||||||
return &upstreamldap.ProviderConfig{
|
return &upstreamldap.ProviderConfig{
|
||||||
Name: "test-ldap-provider",
|
Name: "test-ldap-provider",
|
||||||
Host: "127.0.0.1:" + port,
|
Host: "127.0.0.1:" + port,
|
||||||
@ -775,7 +775,7 @@ func startLongRunningCommandAndWaitForInitialOutput(
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
t.Logf(`Waiting for %s to emit output: "%s"`, command, waitForOutputToContain)
|
t.Logf(`Waiting for %s to emit output: "%s"`, command, waitForOutputToContain)
|
||||||
requireEventually.Equal(-1, cmd.ProcessState.ExitCode(), "subcommand ended sooner than expected")
|
requireEventually.Equal(-1, cmd.ProcessState.ExitCode(), "subcommand ended sooner than expected")
|
||||||
requireEventually.Contains(watchOn.String(), waitForOutputToContain, "expected process to emit output")
|
requireEventually.Contains(watchOn.String(), waitForOutputToContain, "expected process to emit output")
|
||||||
|
@ -19,20 +19,20 @@ import (
|
|||||||
v1 "k8s.io/client-go/kubernetes/typed/authorization/v1"
|
v1 "k8s.io/client-go/kubernetes/typed/authorization/v1"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
|
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServiceAccountPermissions(t *testing.T) {
|
func TestServiceAccountPermissions(t *testing.T) {
|
||||||
// TODO: update this test to check the permissions of all service accounts
|
// TODO: update this test to check the permissions of all service accounts
|
||||||
// For now it just checks the permissions of the impersonation proxy SA
|
// For now it just checks the permissions of the impersonation proxy SA
|
||||||
|
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// impersonate the SA since it is easier than fetching a token and lets us control the group memberships
|
// impersonate the SA since it is easier than fetching a token and lets us control the group memberships
|
||||||
config := rest.CopyConfig(library.NewClientConfig(t))
|
config := rest.CopyConfig(testlib.NewClientConfig(t))
|
||||||
config.Impersonate = rest.ImpersonationConfig{
|
config.Impersonate = rest.ImpersonationConfig{
|
||||||
UserName: serviceaccount.MakeUsername(env.ConciergeNamespace, env.ConciergeAppName+"-impersonation-proxy"),
|
UserName: serviceaccount.MakeUsername(env.ConciergeNamespace, env.ConciergeAppName+"-impersonation-proxy"),
|
||||||
// avoid permissions assigned to system:serviceaccounts by explicitly impersonating system:serviceaccounts:<namespace>
|
// avoid permissions assigned to system:serviceaccounts by explicitly impersonating system:serviceaccounts:<namespace>
|
||||||
@ -42,7 +42,7 @@ func TestServiceAccountPermissions(t *testing.T) {
|
|||||||
Groups: []string{serviceaccount.MakeNamespaceGroupName(env.ConciergeNamespace), user.AllAuthenticated},
|
Groups: []string{serviceaccount.MakeNamespaceGroupName(env.ConciergeNamespace), user.AllAuthenticated},
|
||||||
}
|
}
|
||||||
|
|
||||||
ssrrClient := library.NewKubeclient(t, config).Kubernetes.AuthorizationV1().SelfSubjectRulesReviews()
|
ssrrClient := testlib.NewKubeclient(t, config).Kubernetes.AuthorizationV1().SelfSubjectRulesReviews()
|
||||||
|
|
||||||
// the impersonation proxy SA has the same permissions for all checks because it should only be authorized via cluster role bindings
|
// the impersonation proxy SA has the same permissions for all checks because it should only be authorized via cluster role bindings
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ func TestServiceAccountPermissions(t *testing.T) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
crbs, err := library.NewKubernetesClientset(t).RbacV1().ClusterRoleBindings().List(ctx, metav1.ListOptions{LabelSelector: "eks.amazonaws.com/component=pod-security-policy"})
|
crbs, err := testlib.NewKubernetesClientset(t).RbacV1().ClusterRoleBindings().List(ctx, metav1.ListOptions{LabelSelector: "eks.amazonaws.com/component=pod-security-policy"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if len(crbs.Items) > 0 {
|
if len(crbs.Items) > 0 {
|
||||||
expectedResourceRules = append(expectedResourceRules,
|
expectedResourceRules = append(expectedResourceRules,
|
||||||
@ -121,14 +121,14 @@ func testPermissionsInNamespace(ctx context.Context, t *testing.T, ssrrClient v1
|
|||||||
func getOtherPinnipedGroupSuffix(t *testing.T) string {
|
func getOtherPinnipedGroupSuffix(t *testing.T) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
var resources []*metav1.APIResourceList
|
var resources []*metav1.APIResourceList
|
||||||
|
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
// we need a complete discovery listing for the check we are trying to make below
|
// we need a complete discovery listing for the check we are trying to make below
|
||||||
// loop since tests like TestAPIServingCertificateAutoCreationAndRotation can break discovery
|
// loop since tests like TestAPIServingCertificateAutoCreationAndRotation can break discovery
|
||||||
_, r, err := library.NewKubernetesClientset(t).Discovery().ServerGroupsAndResources()
|
_, r, err := testlib.NewKubernetesClientset(t).Discovery().ServerGroupsAndResources()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("retrying due to partial discovery failure: %v", err)
|
t.Logf("retrying due to partial discovery failure: %v", err)
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
pinnipedclientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned"
|
pinnipedclientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned"
|
||||||
"go.pinniped.dev/internal/certauthority"
|
"go.pinniped.dev/internal/certauthority"
|
||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This test is intended to exercise the supervisor's HTTP port 8080. It can either access it directly via
|
// This test is intended to exercise the supervisor's HTTP port 8080. It can either access it directly via
|
||||||
@ -40,15 +40,15 @@ import (
|
|||||||
// Testing talking to the supervisor's port 8443 where the supervisor is terminating TLS itself is
|
// Testing talking to the supervisor's port 8443 where the supervisor is terminating TLS itself is
|
||||||
// handled by the others tests in this file.
|
// handled by the others tests in this file.
|
||||||
func TestSupervisorOIDCDiscovery(t *testing.T) {
|
func TestSupervisorOIDCDiscovery(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
client := library.NewSupervisorClientset(t)
|
client := testlib.NewSupervisorClientset(t)
|
||||||
|
|
||||||
ns := env.SupervisorNamespace
|
ns := env.SupervisorNamespace
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, defaultTLSCertSecretName(env), client, library.NewKubernetesClientset(t))
|
temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, defaultTLSCertSecretName(env), client, testlib.NewKubernetesClientset(t))
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Scheme string
|
Scheme string
|
||||||
@ -111,7 +111,7 @@ func TestSupervisorOIDCDiscovery(t *testing.T) {
|
|||||||
|
|
||||||
// When the same issuer is added twice, both issuers are marked as duplicates, and neither provider is serving.
|
// When the same issuer is added twice, both issuers are marked as duplicates, and neither provider is serving.
|
||||||
config6Duplicate1, _ := requireCreatingFederationDomainCausesDiscoveryEndpointsToAppear(ctx, t, scheme, addr, caBundle, issuer6, client)
|
config6Duplicate1, _ := requireCreatingFederationDomainCausesDiscoveryEndpointsToAppear(ctx, t, scheme, addr, caBundle, issuer6, client)
|
||||||
config6Duplicate2 := library.CreateTestFederationDomain(ctx, t, issuer6, "", "")
|
config6Duplicate2 := testlib.CreateTestFederationDomain(ctx, t, issuer6, "", "")
|
||||||
requireStatus(t, client, ns, config6Duplicate1.Name, v1alpha1.DuplicateFederationDomainStatusCondition)
|
requireStatus(t, client, ns, config6Duplicate1.Name, v1alpha1.DuplicateFederationDomainStatusCondition)
|
||||||
requireStatus(t, client, ns, config6Duplicate2.Name, v1alpha1.DuplicateFederationDomainStatusCondition)
|
requireStatus(t, client, ns, config6Duplicate2.Name, v1alpha1.DuplicateFederationDomainStatusCondition)
|
||||||
requireDiscoveryEndpointsAreNotFound(t, scheme, addr, caBundle, issuer6)
|
requireDiscoveryEndpointsAreNotFound(t, scheme, addr, caBundle, issuer6)
|
||||||
@ -136,7 +136,7 @@ func TestSupervisorOIDCDiscovery(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// When we create a provider with an invalid issuer, the status is set to invalid.
|
// When we create a provider with an invalid issuer, the status is set to invalid.
|
||||||
badConfig := library.CreateTestFederationDomain(ctx, t, badIssuer, "", "")
|
badConfig := testlib.CreateTestFederationDomain(ctx, t, badIssuer, "", "")
|
||||||
requireStatus(t, client, ns, badConfig.Name, v1alpha1.InvalidFederationDomainStatusCondition)
|
requireStatus(t, client, ns, badConfig.Name, v1alpha1.InvalidFederationDomainStatusCondition)
|
||||||
requireDiscoveryEndpointsAreNotFound(t, scheme, addr, caBundle, badIssuer)
|
requireDiscoveryEndpointsAreNotFound(t, scheme, addr, caBundle, badIssuer)
|
||||||
requireDeletingFederationDomainCausesDiscoveryEndpointsToDisappear(t, badConfig, client, ns, scheme, addr, caBundle, badIssuer)
|
requireDeletingFederationDomainCausesDiscoveryEndpointsToDisappear(t, badConfig, client, ns, scheme, addr, caBundle, badIssuer)
|
||||||
@ -144,9 +144,9 @@ func TestSupervisorOIDCDiscovery(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSupervisorTLSTerminationWithSNI(t *testing.T) {
|
func TestSupervisorTLSTerminationWithSNI(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
pinnipedClient := library.NewSupervisorClientset(t)
|
pinnipedClient := testlib.NewSupervisorClientset(t)
|
||||||
kubeClient := library.NewKubernetesClientset(t)
|
kubeClient := testlib.NewKubernetesClientset(t)
|
||||||
|
|
||||||
ns := env.SupervisorNamespace
|
ns := env.SupervisorNamespace
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||||
@ -162,7 +162,7 @@ func TestSupervisorTLSTerminationWithSNI(t *testing.T) {
|
|||||||
certSecretName1 := "integration-test-cert-1"
|
certSecretName1 := "integration-test-cert-1"
|
||||||
|
|
||||||
// Create an FederationDomain with a spec.tls.secretName.
|
// Create an FederationDomain with a spec.tls.secretName.
|
||||||
federationDomain1 := library.CreateTestFederationDomain(ctx, t, issuer1, certSecretName1, "")
|
federationDomain1 := testlib.CreateTestFederationDomain(ctx, t, issuer1, certSecretName1, "")
|
||||||
requireStatus(t, pinnipedClient, federationDomain1.Namespace, federationDomain1.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
requireStatus(t, pinnipedClient, federationDomain1.Namespace, federationDomain1.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
||||||
|
|
||||||
// The spec.tls.secretName Secret does not exist, so the endpoints should fail with TLS errors.
|
// The spec.tls.secretName Secret does not exist, so the endpoints should fail with TLS errors.
|
||||||
@ -202,7 +202,7 @@ func TestSupervisorTLSTerminationWithSNI(t *testing.T) {
|
|||||||
certSecretName2 := "integration-test-cert-2"
|
certSecretName2 := "integration-test-cert-2"
|
||||||
|
|
||||||
// Create an FederationDomain with a spec.tls.secretName.
|
// Create an FederationDomain with a spec.tls.secretName.
|
||||||
federationDomain2 := library.CreateTestFederationDomain(ctx, t, issuer2, certSecretName2, "")
|
federationDomain2 := testlib.CreateTestFederationDomain(ctx, t, issuer2, certSecretName2, "")
|
||||||
requireStatus(t, pinnipedClient, federationDomain2.Namespace, federationDomain2.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
requireStatus(t, pinnipedClient, federationDomain2.Namespace, federationDomain2.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
||||||
|
|
||||||
// Create the Secret.
|
// Create the Secret.
|
||||||
@ -215,9 +215,9 @@ func TestSupervisorTLSTerminationWithSNI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSupervisorTLSTerminationWithDefaultCerts(t *testing.T) {
|
func TestSupervisorTLSTerminationWithDefaultCerts(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
pinnipedClient := library.NewSupervisorClientset(t)
|
pinnipedClient := testlib.NewSupervisorClientset(t)
|
||||||
kubeClient := library.NewKubernetesClientset(t)
|
kubeClient := testlib.NewKubernetesClientset(t)
|
||||||
|
|
||||||
ns := env.SupervisorNamespace
|
ns := env.SupervisorNamespace
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||||
@ -236,7 +236,7 @@ func TestSupervisorTLSTerminationWithDefaultCerts(t *testing.T) {
|
|||||||
port = hostAndPortSegments[1]
|
port = hostAndPortSegments[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
ips, err := library.LookupIP(ctx, hostname)
|
ips, err := testlib.LookupIP(ctx, hostname)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, ips)
|
require.NotEmpty(t, ips)
|
||||||
ipWithPort := ips[0].String() + ":" + port
|
ipWithPort := ips[0].String() + ":" + port
|
||||||
@ -245,7 +245,7 @@ func TestSupervisorTLSTerminationWithDefaultCerts(t *testing.T) {
|
|||||||
issuerUsingHostname := fmt.Sprintf("%s://%s/issuer1", scheme, address)
|
issuerUsingHostname := fmt.Sprintf("%s://%s/issuer1", scheme, address)
|
||||||
|
|
||||||
// Create an FederationDomain without a spec.tls.secretName.
|
// Create an FederationDomain without a spec.tls.secretName.
|
||||||
federationDomain1 := library.CreateTestFederationDomain(ctx, t, issuerUsingIPAddress, "", "")
|
federationDomain1 := testlib.CreateTestFederationDomain(ctx, t, issuerUsingIPAddress, "", "")
|
||||||
requireStatus(t, pinnipedClient, federationDomain1.Namespace, federationDomain1.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
requireStatus(t, pinnipedClient, federationDomain1.Namespace, federationDomain1.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
||||||
|
|
||||||
// There is no default TLS cert and the spec.tls.secretName was not set, so the endpoints should fail with TLS errors.
|
// There is no default TLS cert and the spec.tls.secretName was not set, so the endpoints should fail with TLS errors.
|
||||||
@ -259,7 +259,7 @@ func TestSupervisorTLSTerminationWithDefaultCerts(t *testing.T) {
|
|||||||
|
|
||||||
// Create an FederationDomain with a spec.tls.secretName.
|
// Create an FederationDomain with a spec.tls.secretName.
|
||||||
certSecretName := "integration-test-cert-1"
|
certSecretName := "integration-test-cert-1"
|
||||||
federationDomain2 := library.CreateTestFederationDomain(ctx, t, issuerUsingHostname, certSecretName, "")
|
federationDomain2 := testlib.CreateTestFederationDomain(ctx, t, issuerUsingHostname, certSecretName, "")
|
||||||
requireStatus(t, pinnipedClient, federationDomain2.Namespace, federationDomain2.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
requireStatus(t, pinnipedClient, federationDomain2.Namespace, federationDomain2.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
||||||
|
|
||||||
// Create the Secret.
|
// Create the Secret.
|
||||||
@ -274,7 +274,7 @@ func TestSupervisorTLSTerminationWithDefaultCerts(t *testing.T) {
|
|||||||
_ = requireDiscoveryEndpointsAreWorking(t, scheme, ipWithPort, string(defaultCA.Bundle()), issuerUsingIPAddress, nil)
|
_ = requireDiscoveryEndpointsAreWorking(t, scheme, ipWithPort, string(defaultCA.Bundle()), issuerUsingIPAddress, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultTLSCertSecretName(env *library.TestEnv) string {
|
func defaultTLSCertSecretName(env *testlib.TestEnv) string {
|
||||||
return env.SupervisorAppName + "-default-tls-certificate" //nolint:gosec // this is not a hardcoded credential
|
return env.SupervisorAppName + "-default-tls-certificate" //nolint:gosec // this is not a hardcoded credential
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ func requireEndpointNotFound(t *testing.T, url, host, caBundle string) {
|
|||||||
|
|
||||||
requestNonExistentPath.Host = host
|
requestNonExistentPath.Host = host
|
||||||
|
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
response, err := httpClient.Do(requestNonExistentPath)
|
response, err := httpClient.Do(requestNonExistentPath)
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
requireEventually.NoError(response.Body.Close())
|
requireEventually.NoError(response.Body.Close())
|
||||||
@ -411,7 +411,7 @@ func requireEndpointHasTLSErrorBecauseCertificatesAreNotReady(t *testing.T, url
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
|
|
||||||
@ -432,7 +432,7 @@ func requireCreatingFederationDomainCausesDiscoveryEndpointsToAppear(
|
|||||||
client pinnipedclientset.Interface,
|
client pinnipedclientset.Interface,
|
||||||
) (*v1alpha1.FederationDomain, *ExpectedJWKSResponseFormat) {
|
) (*v1alpha1.FederationDomain, *ExpectedJWKSResponseFormat) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
newFederationDomain := library.CreateTestFederationDomain(ctx, t, issuerName, "", "")
|
newFederationDomain := testlib.CreateTestFederationDomain(ctx, t, issuerName, "", "")
|
||||||
jwksResult := requireDiscoveryEndpointsAreWorking(t, supervisorScheme, supervisorAddress, supervisorCABundle, issuerName, nil)
|
jwksResult := requireDiscoveryEndpointsAreWorking(t, supervisorScheme, supervisorAddress, supervisorCABundle, issuerName, nil)
|
||||||
requireStatus(t, client, newFederationDomain.Namespace, newFederationDomain.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
requireStatus(t, client, newFederationDomain.Namespace, newFederationDomain.Name, v1alpha1.SuccessFederationDomainStatusCondition)
|
||||||
return newFederationDomain, jwksResult
|
return newFederationDomain, jwksResult
|
||||||
@ -552,7 +552,7 @@ func requireSuccessEndpointResponse(t *testing.T, endpointURL, issuer, caBundle
|
|||||||
// Fetch that discovery endpoint. Give it some time for the endpoint to come into existence.
|
// Fetch that discovery endpoint. Give it some time for the endpoint to come into existence.
|
||||||
var response *http.Response
|
var response *http.Response
|
||||||
var responseBody []byte
|
var responseBody []byte
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
var err error
|
var err error
|
||||||
response, err = httpClient.Do(requestDiscoveryEndpoint)
|
response, err = httpClient.Do(requestDiscoveryEndpoint)
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
@ -603,7 +603,7 @@ func requireDelete(t *testing.T, client pinnipedclientset.Interface, ns, name st
|
|||||||
func requireStatus(t *testing.T, client pinnipedclientset.Interface, ns, name string, status v1alpha1.FederationDomainStatusCondition) {
|
func requireStatus(t *testing.T, client pinnipedclientset.Interface, ns, name string, status v1alpha1.FederationDomainStatusCondition) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The Supervisor health endpoint is public because that makes it easier
|
// The Supervisor health endpoint is public because that makes it easier
|
||||||
@ -23,7 +23,7 @@ import (
|
|||||||
// happen on a private container port at this time.
|
// happen on a private container port at this time.
|
||||||
// This test checks that it is working and that it is public.
|
// This test checks that it is working and that it is public.
|
||||||
func TestSupervisorHealthz(t *testing.T) {
|
func TestSupervisorHealthz(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
if env.SupervisorHTTPAddress == "" {
|
if env.SupervisorHTTPAddress == "" {
|
||||||
t.Skip("PINNIPED_TEST_SUPERVISOR_HTTP_ADDRESS not defined")
|
t.Skip("PINNIPED_TEST_SUPERVISOR_HTTP_ADDRESS not defined")
|
||||||
|
@ -32,12 +32,12 @@ import (
|
|||||||
"go.pinniped.dev/pkg/oidcclient/nonce"
|
"go.pinniped.dev/pkg/oidcclient/nonce"
|
||||||
"go.pinniped.dev/pkg/oidcclient/pkce"
|
"go.pinniped.dev/pkg/oidcclient/pkce"
|
||||||
"go.pinniped.dev/pkg/oidcclient/state"
|
"go.pinniped.dev/pkg/oidcclient/state"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
"go.pinniped.dev/test/library/browsertest"
|
"go.pinniped.dev/test/testlib/browsertest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSupervisorLogin(t *testing.T) {
|
func TestSupervisorLogin(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -55,13 +55,13 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
},
|
},
|
||||||
createIDP: func(t *testing.T) {
|
createIDP: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
library.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{
|
testlib.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{
|
||||||
Issuer: env.SupervisorUpstreamOIDC.Issuer,
|
Issuer: env.SupervisorUpstreamOIDC.Issuer,
|
||||||
TLS: &idpv1alpha1.TLSSpec{
|
TLS: &idpv1alpha1.TLSSpec{
|
||||||
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamOIDC.CABundle)),
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamOIDC.CABundle)),
|
||||||
},
|
},
|
||||||
Client: idpv1alpha1.OIDCClient{
|
Client: idpv1alpha1.OIDCClient{
|
||||||
SecretName: library.CreateClientCredsSecret(t, env.SupervisorUpstreamOIDC.ClientID, env.SupervisorUpstreamOIDC.ClientSecret).Name,
|
SecretName: testlib.CreateClientCredsSecret(t, env.SupervisorUpstreamOIDC.ClientID, env.SupervisorUpstreamOIDC.ClientSecret).Name,
|
||||||
},
|
},
|
||||||
}, idpv1alpha1.PhaseReady)
|
}, idpv1alpha1.PhaseReady)
|
||||||
},
|
},
|
||||||
@ -78,13 +78,13 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
},
|
},
|
||||||
createIDP: func(t *testing.T) {
|
createIDP: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
library.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{
|
testlib.CreateTestOIDCIdentityProvider(t, idpv1alpha1.OIDCIdentityProviderSpec{
|
||||||
Issuer: env.SupervisorUpstreamOIDC.Issuer,
|
Issuer: env.SupervisorUpstreamOIDC.Issuer,
|
||||||
TLS: &idpv1alpha1.TLSSpec{
|
TLS: &idpv1alpha1.TLSSpec{
|
||||||
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamOIDC.CABundle)),
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamOIDC.CABundle)),
|
||||||
},
|
},
|
||||||
Client: idpv1alpha1.OIDCClient{
|
Client: idpv1alpha1.OIDCClient{
|
||||||
SecretName: library.CreateClientCredsSecret(t, env.SupervisorUpstreamOIDC.ClientID, env.SupervisorUpstreamOIDC.ClientSecret).Name,
|
SecretName: testlib.CreateClientCredsSecret(t, env.SupervisorUpstreamOIDC.ClientID, env.SupervisorUpstreamOIDC.ClientSecret).Name,
|
||||||
},
|
},
|
||||||
Claims: idpv1alpha1.OIDCClaims{
|
Claims: idpv1alpha1.OIDCClaims{
|
||||||
Username: env.SupervisorUpstreamOIDC.UsernameClaim,
|
Username: env.SupervisorUpstreamOIDC.UsernameClaim,
|
||||||
@ -104,19 +104,19 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
name: "ldap with email as username and groups names as DNs and using an LDAP provider which supports TLS",
|
name: "ldap with email as username and groups names as DNs and using an LDAP provider which supports TLS",
|
||||||
maybeSkip: func(t *testing.T) {
|
maybeSkip: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if len(env.ToolsNamespace) == 0 && !env.HasCapability(library.CanReachInternetLDAPPorts) {
|
if len(env.ToolsNamespace) == 0 && !env.HasCapability(testlib.CanReachInternetLDAPPorts) {
|
||||||
t.Skip("LDAP integration test requires connectivity to an LDAP server")
|
t.Skip("LDAP integration test requires connectivity to an LDAP server")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
createIDP: func(t *testing.T) {
|
createIDP: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
secret := library.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", v1.SecretTypeBasicAuth,
|
secret := testlib.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", v1.SecretTypeBasicAuth,
|
||||||
map[string]string{
|
map[string]string{
|
||||||
v1.BasicAuthUsernameKey: env.SupervisorUpstreamLDAP.BindUsername,
|
v1.BasicAuthUsernameKey: env.SupervisorUpstreamLDAP.BindUsername,
|
||||||
v1.BasicAuthPasswordKey: env.SupervisorUpstreamLDAP.BindPassword,
|
v1.BasicAuthPasswordKey: env.SupervisorUpstreamLDAP.BindPassword,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
ldapIDP := library.CreateTestLDAPIdentityProvider(t, idpv1alpha1.LDAPIdentityProviderSpec{
|
ldapIDP := testlib.CreateTestLDAPIdentityProvider(t, idpv1alpha1.LDAPIdentityProviderSpec{
|
||||||
Host: env.SupervisorUpstreamLDAP.Host,
|
Host: env.SupervisorUpstreamLDAP.Host,
|
||||||
TLS: &idpv1alpha1.TLSSpec{
|
TLS: &idpv1alpha1.TLSSpec{
|
||||||
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.CABundle)),
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.CABundle)),
|
||||||
@ -169,19 +169,19 @@ func TestSupervisorLogin(t *testing.T) {
|
|||||||
name: "ldap with CN as username and group names as CNs and using an LDAP provider which only supports StartTLS", // try another variation of configuration options
|
name: "ldap with CN as username and group names as CNs and using an LDAP provider which only supports StartTLS", // try another variation of configuration options
|
||||||
maybeSkip: func(t *testing.T) {
|
maybeSkip: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if len(env.ToolsNamespace) == 0 && !env.HasCapability(library.CanReachInternetLDAPPorts) {
|
if len(env.ToolsNamespace) == 0 && !env.HasCapability(testlib.CanReachInternetLDAPPorts) {
|
||||||
t.Skip("LDAP integration test requires connectivity to an LDAP server")
|
t.Skip("LDAP integration test requires connectivity to an LDAP server")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
createIDP: func(t *testing.T) {
|
createIDP: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
secret := library.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", v1.SecretTypeBasicAuth,
|
secret := testlib.CreateTestSecret(t, env.SupervisorNamespace, "ldap-service-account", v1.SecretTypeBasicAuth,
|
||||||
map[string]string{
|
map[string]string{
|
||||||
v1.BasicAuthUsernameKey: env.SupervisorUpstreamLDAP.BindUsername,
|
v1.BasicAuthUsernameKey: env.SupervisorUpstreamLDAP.BindUsername,
|
||||||
v1.BasicAuthPasswordKey: env.SupervisorUpstreamLDAP.BindPassword,
|
v1.BasicAuthPasswordKey: env.SupervisorUpstreamLDAP.BindPassword,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
ldapIDP := library.CreateTestLDAPIdentityProvider(t, idpv1alpha1.LDAPIdentityProviderSpec{
|
ldapIDP := testlib.CreateTestLDAPIdentityProvider(t, idpv1alpha1.LDAPIdentityProviderSpec{
|
||||||
Host: env.SupervisorUpstreamLDAP.StartTLSOnlyHost,
|
Host: env.SupervisorUpstreamLDAP.StartTLSOnlyHost,
|
||||||
TLS: &idpv1alpha1.TLSSpec{
|
TLS: &idpv1alpha1.TLSSpec{
|
||||||
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.CABundle)),
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte(env.SupervisorUpstreamLDAP.CABundle)),
|
||||||
@ -278,7 +278,7 @@ func testSupervisorLogin(
|
|||||||
requestAuthorization func(t *testing.T, downstreamAuthorizeURL, downstreamCallbackURL string, httpClient *http.Client),
|
requestAuthorization func(t *testing.T, downstreamAuthorizeURL, downstreamCallbackURL string, httpClient *http.Client),
|
||||||
wantDownstreamIDTokenSubjectToMatch, wantDownstreamIDTokenUsernameToMatch string, wantDownstreamIDTokenGroups []string,
|
wantDownstreamIDTokenSubjectToMatch, wantDownstreamIDTokenUsernameToMatch string, wantDownstreamIDTokenGroups []string,
|
||||||
) {
|
) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -305,12 +305,12 @@ func testSupervisorLogin(
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
if env.Proxy == "" {
|
if env.Proxy == "" {
|
||||||
t.Logf("passing request for %s with no proxy", library.RedactURLParams(req.URL))
|
t.Logf("passing request for %s with no proxy", testlib.RedactURLParams(req.URL))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
proxyURL, err := url.Parse(env.Proxy)
|
proxyURL, err := url.Parse(env.Proxy)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Logf("passing request for %s through proxy %s", library.RedactURLParams(req.URL), proxyURL.String())
|
t.Logf("passing request for %s through proxy %s", testlib.RedactURLParams(req.URL), proxyURL.String())
|
||||||
return proxyURL, nil
|
return proxyURL, nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -329,7 +329,7 @@ func testSupervisorLogin(
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Write the serving cert to a secret.
|
// Write the serving cert to a secret.
|
||||||
certSecret := library.CreateTestSecret(t,
|
certSecret := testlib.CreateTestSecret(t,
|
||||||
env.SupervisorNamespace,
|
env.SupervisorNamespace,
|
||||||
"oidc-provider-tls",
|
"oidc-provider-tls",
|
||||||
v1.SecretTypeTLS,
|
v1.SecretTypeTLS,
|
||||||
@ -337,7 +337,7 @@ func testSupervisorLogin(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Create the downstream FederationDomain and expect it to go into the success status condition.
|
// Create the downstream FederationDomain and expect it to go into the success status condition.
|
||||||
downstream := library.CreateTestFederationDomain(ctx, t,
|
downstream := testlib.CreateTestFederationDomain(ctx, t,
|
||||||
issuerURL.String(),
|
issuerURL.String(),
|
||||||
certSecret.Name,
|
certSecret.Name,
|
||||||
configv1alpha1.SuccessFederationDomainStatusCondition,
|
configv1alpha1.SuccessFederationDomainStatusCondition,
|
||||||
@ -354,7 +354,7 @@ func testSupervisorLogin(
|
|||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
rsp, err := httpClient.Do(requestJWKSEndpoint)
|
rsp, err := httpClient.Do(requestJWKSEndpoint)
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
requireEventually.NoError(rsp.Body.Close())
|
requireEventually.NoError(rsp.Body.Close())
|
||||||
@ -366,7 +366,7 @@ func testSupervisorLogin(
|
|||||||
|
|
||||||
// Perform OIDC discovery for our downstream.
|
// Perform OIDC discovery for our downstream.
|
||||||
var discovery *coreosoidc.Provider
|
var discovery *coreosoidc.Provider
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
var err error
|
var err error
|
||||||
discovery, err = coreosoidc.NewProvider(oidcHTTPClientContext, downstream.Spec.Issuer)
|
discovery, err = coreosoidc.NewProvider(oidcHTTPClientContext, downstream.Spec.Issuer)
|
||||||
requireEventually.NoError(err)
|
requireEventually.NoError(err)
|
||||||
@ -403,7 +403,7 @@ func testSupervisorLogin(
|
|||||||
|
|
||||||
// Expect that our callback handler was invoked.
|
// Expect that our callback handler was invoked.
|
||||||
callback := localCallbackServer.waitForCallback(10 * time.Second)
|
callback := localCallbackServer.waitForCallback(10 * time.Second)
|
||||||
t.Logf("got callback request: %s", library.MaskTokens(callback.URL.String()))
|
t.Logf("got callback request: %s", testlib.MaskTokens(callback.URL.String()))
|
||||||
require.Equal(t, stateParam.String(), callback.URL.Query().Get("state"))
|
require.Equal(t, stateParam.String(), callback.URL.Query().Get("state"))
|
||||||
require.ElementsMatch(t, []string{"openid", "pinniped:request-audience", "offline_access"}, strings.Split(callback.URL.Query().Get("scope"), " "))
|
require.ElementsMatch(t, []string{"openid", "pinniped:request-audience", "offline_access"}, strings.Split(callback.URL.Query().Get("scope"), " "))
|
||||||
authcode := callback.URL.Query().Get("code")
|
authcode := callback.URL.Query().Get("code")
|
||||||
@ -497,7 +497,7 @@ func verifyTokenResponse(
|
|||||||
|
|
||||||
func requestAuthorizationUsingOIDCIdentityProvider(t *testing.T, downstreamAuthorizeURL, downstreamCallbackURL string, httpClient *http.Client) {
|
func requestAuthorizationUsingOIDCIdentityProvider(t *testing.T, downstreamAuthorizeURL, downstreamCallbackURL string, httpClient *http.Client) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancelFunc()
|
defer cancelFunc()
|
||||||
@ -512,7 +512,7 @@ func requestAuthorizationUsingOIDCIdentityProvider(t *testing.T, downstreamAutho
|
|||||||
|
|
||||||
// Open the web browser and navigate to the downstream authorize URL.
|
// Open the web browser and navigate to the downstream authorize URL.
|
||||||
page := browsertest.Open(t)
|
page := browsertest.Open(t)
|
||||||
t.Logf("opening browser to downstream authorize URL %s", library.MaskTokens(downstreamAuthorizeURL))
|
t.Logf("opening browser to downstream authorize URL %s", testlib.MaskTokens(downstreamAuthorizeURL))
|
||||||
require.NoError(t, page.Navigate(downstreamAuthorizeURL))
|
require.NoError(t, page.Navigate(downstreamAuthorizeURL))
|
||||||
|
|
||||||
// Expect to be redirected to the upstream provider and log in.
|
// Expect to be redirected to the upstream provider and log in.
|
||||||
@ -542,7 +542,7 @@ func requestAuthorizationUsingLDAPIdentityProvider(t *testing.T, downstreamAutho
|
|||||||
// to retry this request multiple times until we get the expected 302 status response.
|
// to retry this request multiple times until we get the expected 302 status response.
|
||||||
var authResponse *http.Response
|
var authResponse *http.Response
|
||||||
var responseBody []byte
|
var responseBody []byte
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
authResponse, err = httpClient.Do(authRequest)
|
authResponse, err = httpClient.Do(authRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("got authorization response with error %v", err)
|
t.Logf("got authorization response with error %v", err)
|
||||||
|
@ -15,19 +15,19 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSupervisorSecrets(t *testing.T) {
|
func TestSupervisorSecrets(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
kubeClient := library.NewKubernetesClientset(t)
|
kubeClient := testlib.NewKubernetesClientset(t)
|
||||||
supervisorClient := library.NewSupervisorClientset(t)
|
supervisorClient := testlib.NewSupervisorClientset(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Create our FederationDomain under test.
|
// Create our FederationDomain under test.
|
||||||
federationDomain := library.CreateTestFederationDomain(ctx, t, "", "", "")
|
federationDomain := testlib.CreateTestFederationDomain(ctx, t, "", "", "")
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -75,7 +75,7 @@ func TestSupervisorSecrets(t *testing.T) {
|
|||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
// Ensure a secret is created with the FederationDomain's JWKS.
|
// Ensure a secret is created with the FederationDomain's JWKS.
|
||||||
var updatedFederationDomain *configv1alpha1.FederationDomain
|
var updatedFederationDomain *configv1alpha1.FederationDomain
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
resp, err := supervisorClient.
|
resp, err := supervisorClient.
|
||||||
ConfigV1alpha1().
|
ConfigV1alpha1().
|
||||||
FederationDomains(env.SupervisorNamespace).
|
FederationDomains(env.SupervisorNamespace).
|
||||||
@ -107,7 +107,7 @@ func TestSupervisorSecrets(t *testing.T) {
|
|||||||
Secrets(env.SupervisorNamespace).
|
Secrets(env.SupervisorNamespace).
|
||||||
Delete(ctx, test.secretName(updatedFederationDomain), metav1.DeleteOptions{})
|
Delete(ctx, test.secretName(updatedFederationDomain), metav1.DeleteOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
var err error
|
var err error
|
||||||
secret, err = kubeClient.
|
secret, err = kubeClient.
|
||||||
CoreV1().
|
CoreV1().
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/crud"
|
"go.pinniped.dev/internal/crud"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStorageGarbageCollection(t *testing.T) {
|
func TestStorageGarbageCollection(t *testing.T) {
|
||||||
@ -24,8 +24,8 @@ func TestStorageGarbageCollection(t *testing.T) {
|
|||||||
// and will not impact other tests, or be impacted by other tests, when run in parallel.
|
// and will not impact other tests, or be impacted by other tests, when run in parallel.
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
client := library.NewKubernetesClientset(t)
|
client := testlib.NewKubernetesClientset(t)
|
||||||
secrets := client.CoreV1().Secrets(env.SupervisorNamespace)
|
secrets := client.CoreV1().Secrets(env.SupervisorNamespace)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -55,12 +55,12 @@ func TestStorageGarbageCollection(t *testing.T) {
|
|||||||
// in practice we should only need to wait about 30 seconds, which is the GC controller's self-imposed
|
// in practice we should only need to wait about 30 seconds, which is the GC controller's self-imposed
|
||||||
// rate throttling time period.
|
// rate throttling time period.
|
||||||
slightlyLongerThanGCControllerFullResyncPeriod := 3*time.Minute + 30*time.Second
|
slightlyLongerThanGCControllerFullResyncPeriod := 3*time.Minute + 30*time.Second
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
_, err := secrets.Get(ctx, secretAlreadyExpired.Name, metav1.GetOptions{})
|
_, err := secrets.Get(ctx, secretAlreadyExpired.Name, metav1.GetOptions{})
|
||||||
requireEventually.Truef(k8serrors.IsNotFound(err), "wanted a NotFound error but got %v", err)
|
requireEventually.Truef(k8serrors.IsNotFound(err), "wanted a NotFound error but got %v", err)
|
||||||
}, slightlyLongerThanGCControllerFullResyncPeriod, 250*time.Millisecond)
|
}, slightlyLongerThanGCControllerFullResyncPeriod, 250*time.Millisecond)
|
||||||
|
|
||||||
library.RequireEventually(t, func(requireEventually *require.Assertions) {
|
testlib.RequireEventually(t, func(requireEventually *require.Assertions) {
|
||||||
_, err := secrets.Get(ctx, secretWhichWillExpireBeforeTheTestEnds.Name, metav1.GetOptions{})
|
_, err := secrets.Get(ctx, secretWhichWillExpireBeforeTheTestEnds.Name, metav1.GetOptions{})
|
||||||
requireEventually.Truef(k8serrors.IsNotFound(err), "wanted a NotFound error but got %v", err)
|
requireEventually.Truef(k8serrors.IsNotFound(err), "wanted a NotFound error but got %v", err)
|
||||||
}, slightlyLongerThanGCControllerFullResyncPeriod, 250*time.Millisecond)
|
}, slightlyLongerThanGCControllerFullResyncPeriod, 250*time.Millisecond)
|
||||||
|
@ -20,12 +20,12 @@ import (
|
|||||||
|
|
||||||
"go.pinniped.dev/internal/fositestorage/authorizationcode"
|
"go.pinniped.dev/internal/fositestorage/authorizationcode"
|
||||||
"go.pinniped.dev/internal/testutil"
|
"go.pinniped.dev/internal/testutil"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAuthorizeCodeStorage(t *testing.T) {
|
func TestAuthorizeCodeStorage(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
client := library.NewKubernetesClientset(t)
|
client := testlib.NewKubernetesClientset(t)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// randomly generated HMAC authorization code (see below)
|
// randomly generated HMAC authorization code (see below)
|
||||||
|
@ -11,11 +11,11 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
|
"go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSupervisorUpstreamOIDCDiscovery(t *testing.T) {
|
func TestSupervisorUpstreamOIDCDiscovery(t *testing.T) {
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
t.Run("invalid missing secret and bad issuer", func(t *testing.T) {
|
t.Run("invalid missing secret and bad issuer", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
@ -25,7 +25,7 @@ func TestSupervisorUpstreamOIDCDiscovery(t *testing.T) {
|
|||||||
SecretName: "does-not-exist",
|
SecretName: "does-not-exist",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
upstream := library.CreateTestOIDCIdentityProvider(t, spec, v1alpha1.PhaseError)
|
upstream := testlib.CreateTestOIDCIdentityProvider(t, spec, v1alpha1.PhaseError)
|
||||||
expectUpstreamConditions(t, upstream, []v1alpha1.Condition{
|
expectUpstreamConditions(t, upstream, []v1alpha1.Condition{
|
||||||
{
|
{
|
||||||
Type: "ClientCredentialsValid",
|
Type: "ClientCredentialsValid",
|
||||||
@ -54,10 +54,10 @@ Get "https://127.0.0.1:444444/issuer/.well-known/openid-configuration": dial tcp
|
|||||||
AdditionalScopes: []string{"email", "profile"},
|
AdditionalScopes: []string{"email", "profile"},
|
||||||
},
|
},
|
||||||
Client: v1alpha1.OIDCClient{
|
Client: v1alpha1.OIDCClient{
|
||||||
SecretName: library.CreateClientCredsSecret(t, "test-client-id", "test-client-secret").Name,
|
SecretName: testlib.CreateClientCredsSecret(t, "test-client-id", "test-client-secret").Name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
upstream := library.CreateTestOIDCIdentityProvider(t, spec, v1alpha1.PhaseError)
|
upstream := testlib.CreateTestOIDCIdentityProvider(t, spec, v1alpha1.PhaseError)
|
||||||
expectUpstreamConditions(t, upstream, []v1alpha1.Condition{
|
expectUpstreamConditions(t, upstream, []v1alpha1.Condition{
|
||||||
{
|
{
|
||||||
Type: "ClientCredentialsValid",
|
Type: "ClientCredentialsValid",
|
||||||
@ -86,10 +86,10 @@ oidc: issuer did not match the issuer returned by provider, expected "` + env.Su
|
|||||||
AdditionalScopes: []string{"email", "profile"},
|
AdditionalScopes: []string{"email", "profile"},
|
||||||
},
|
},
|
||||||
Client: v1alpha1.OIDCClient{
|
Client: v1alpha1.OIDCClient{
|
||||||
SecretName: library.CreateClientCredsSecret(t, "test-client-id", "test-client-secret").Name,
|
SecretName: testlib.CreateClientCredsSecret(t, "test-client-id", "test-client-secret").Name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
upstream := library.CreateTestOIDCIdentityProvider(t, spec, v1alpha1.PhaseReady)
|
upstream := testlib.CreateTestOIDCIdentityProvider(t, spec, v1alpha1.PhaseReady)
|
||||||
expectUpstreamConditions(t, upstream, []v1alpha1.Condition{
|
expectUpstreamConditions(t, upstream, []v1alpha1.Condition{
|
||||||
{
|
{
|
||||||
Type: "ClientCredentialsValid",
|
Type: "ClientCredentialsValid",
|
||||||
|
@ -26,18 +26,18 @@ import (
|
|||||||
"k8s.io/client-go/util/keyutil"
|
"k8s.io/client-go/util/keyutil"
|
||||||
|
|
||||||
identityv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/identity/v1alpha1"
|
identityv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/identity/v1alpha1"
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWhoAmI_Kubeadm(t *testing.T) {
|
func TestWhoAmI_Kubeadm(t *testing.T) {
|
||||||
// use the cluster signing key being available as a proxy for this being a kubeadm cluster
|
// use the cluster signing key being available as a proxy for this being a kubeadm cluster
|
||||||
// we should add more robust logic around skipping clusters based on vendor
|
// we should add more robust logic around skipping clusters based on vendor
|
||||||
_ = library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
|
_ = testlib.IntegrationEnv(t).WithCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
whoAmI, err := library.NewConciergeClientset(t).IdentityV1alpha1().WhoAmIRequests().
|
whoAmI, err := testlib.NewConciergeClientset(t).IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -61,12 +61,12 @@ func TestWhoAmI_Kubeadm(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWhoAmI_ServiceAccount_Legacy(t *testing.T) {
|
func TestWhoAmI_ServiceAccount_Legacy(t *testing.T) {
|
||||||
_ = library.IntegrationEnv(t)
|
_ = testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
kubeClient := library.NewKubernetesClientset(t).CoreV1()
|
kubeClient := testlib.NewKubernetesClientset(t).CoreV1()
|
||||||
|
|
||||||
ns, err := kubeClient.Namespaces().Create(ctx, &corev1.Namespace{
|
ns, err := kubeClient.Namespaces().Create(ctx, &corev1.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -97,7 +97,7 @@ func TestWhoAmI_ServiceAccount_Legacy(t *testing.T) {
|
|||||||
}, metav1.CreateOptions{})
|
}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
library.RequireEventuallyWithoutError(t, func() (bool, error) {
|
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
|
||||||
secret, err = kubeClient.Secrets(ns.Name).Get(ctx, secret.Name, metav1.GetOptions{})
|
secret, err = kubeClient.Secrets(ns.Name).Get(ctx, secret.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -105,10 +105,10 @@ func TestWhoAmI_ServiceAccount_Legacy(t *testing.T) {
|
|||||||
return len(secret.Data[corev1.ServiceAccountTokenKey]) > 0, nil
|
return len(secret.Data[corev1.ServiceAccountTokenKey]) > 0, nil
|
||||||
}, time.Minute, time.Second)
|
}, time.Minute, time.Second)
|
||||||
|
|
||||||
saConfig := library.NewAnonymousClientRestConfig(t)
|
saConfig := testlib.NewAnonymousClientRestConfig(t)
|
||||||
saConfig.BearerToken = string(secret.Data[corev1.ServiceAccountTokenKey])
|
saConfig.BearerToken = string(secret.Data[corev1.ServiceAccountTokenKey])
|
||||||
|
|
||||||
whoAmI, err := library.NewKubeclient(t, saConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
whoAmI, err := testlib.NewKubeclient(t, saConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -134,12 +134,12 @@ func TestWhoAmI_ServiceAccount_Legacy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWhoAmI_ServiceAccount_TokenRequest(t *testing.T) {
|
func TestWhoAmI_ServiceAccount_TokenRequest(t *testing.T) {
|
||||||
_ = library.IntegrationEnv(t)
|
_ = testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
kubeClient := library.NewKubernetesClientset(t).CoreV1()
|
kubeClient := testlib.NewKubernetesClientset(t).CoreV1()
|
||||||
|
|
||||||
ns, err := kubeClient.Namespaces().Create(ctx, &corev1.Namespace{
|
ns, err := kubeClient.Namespaces().Create(ctx, &corev1.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -193,12 +193,12 @@ func TestWhoAmI_ServiceAccount_TokenRequest(t *testing.T) {
|
|||||||
}, metav1.CreateOptions{})
|
}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
saBadAudConfig := library.NewAnonymousClientRestConfig(t)
|
saBadAudConfig := testlib.NewAnonymousClientRestConfig(t)
|
||||||
saBadAudConfig.BearerToken = tokenRequestBadAudience.Status.Token
|
saBadAudConfig.BearerToken = tokenRequestBadAudience.Status.Token
|
||||||
|
|
||||||
_, badAudErr := library.NewKubeclient(t, saBadAudConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
_, badAudErr := testlib.NewKubeclient(t, saBadAudConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.True(t, errors.IsUnauthorized(badAudErr), library.Sdump(badAudErr))
|
require.True(t, errors.IsUnauthorized(badAudErr), testlib.Sdump(badAudErr))
|
||||||
|
|
||||||
tokenRequest, err := kubeClient.ServiceAccounts(ns.Name).CreateToken(ctx, sa.Name, &authenticationv1.TokenRequest{
|
tokenRequest, err := kubeClient.ServiceAccounts(ns.Name).CreateToken(ctx, sa.Name, &authenticationv1.TokenRequest{
|
||||||
Spec: authenticationv1.TokenRequestSpec{
|
Spec: authenticationv1.TokenRequestSpec{
|
||||||
@ -213,10 +213,10 @@ func TestWhoAmI_ServiceAccount_TokenRequest(t *testing.T) {
|
|||||||
}, metav1.CreateOptions{})
|
}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
saTokenReqConfig := library.NewAnonymousClientRestConfig(t)
|
saTokenReqConfig := testlib.NewAnonymousClientRestConfig(t)
|
||||||
saTokenReqConfig.BearerToken = tokenRequest.Status.Token
|
saTokenReqConfig.BearerToken = tokenRequest.Status.Token
|
||||||
|
|
||||||
whoAmITokenReq, err := library.NewKubeclient(t, saTokenReqConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
whoAmITokenReq, err := testlib.NewKubeclient(t, saTokenReqConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -248,12 +248,12 @@ func TestWhoAmI_ServiceAccount_TokenRequest(t *testing.T) {
|
|||||||
func TestWhoAmI_CSR(t *testing.T) {
|
func TestWhoAmI_CSR(t *testing.T) {
|
||||||
// use the cluster signing key being available as a proxy for this not being an EKS cluster
|
// use the cluster signing key being available as a proxy for this not being an EKS cluster
|
||||||
// we should add more robust logic around skipping clusters based on vendor
|
// we should add more robust logic around skipping clusters based on vendor
|
||||||
_ = library.IntegrationEnv(t).WithCapability(library.ClusterSigningKeyIsAvailable)
|
_ = testlib.IntegrationEnv(t).WithCapability(testlib.ClusterSigningKeyIsAvailable)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
kubeClient := library.NewKubernetesClientset(t)
|
kubeClient := testlib.NewKubernetesClientset(t)
|
||||||
|
|
||||||
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -305,11 +305,11 @@ func TestWhoAmI_CSR(t *testing.T) {
|
|||||||
crtPEM, err := csr.WaitForCertificate(ctx, kubeClient, csrName, csrUID)
|
crtPEM, err := csr.WaitForCertificate(ctx, kubeClient, csrName, csrUID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
csrConfig := library.NewAnonymousClientRestConfig(t)
|
csrConfig := testlib.NewAnonymousClientRestConfig(t)
|
||||||
csrConfig.CertData = crtPEM
|
csrConfig.CertData = crtPEM
|
||||||
csrConfig.KeyData = keyPEM
|
csrConfig.KeyData = keyPEM
|
||||||
|
|
||||||
whoAmI, err := library.NewKubeclient(t, csrConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
whoAmI, err := testlib.NewKubeclient(t, csrConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -333,14 +333,14 @@ func TestWhoAmI_CSR(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWhoAmI_Anonymous(t *testing.T) {
|
func TestWhoAmI_Anonymous(t *testing.T) {
|
||||||
_ = library.IntegrationEnv(t).WithCapability(library.AnonymousAuthenticationSupported)
|
_ = testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupported)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
anonymousConfig := library.NewAnonymousClientRestConfig(t)
|
anonymousConfig := testlib.NewAnonymousClientRestConfig(t)
|
||||||
|
|
||||||
whoAmI, err := library.NewKubeclient(t, anonymousConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
whoAmI, err := testlib.NewKubeclient(t, anonymousConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -363,12 +363,12 @@ func TestWhoAmI_Anonymous(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWhoAmI_ImpersonateDirectly(t *testing.T) {
|
func TestWhoAmI_ImpersonateDirectly(t *testing.T) {
|
||||||
_ = library.IntegrationEnv(t)
|
_ = testlib.IntegrationEnv(t)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
impersonationConfig := library.NewClientConfig(t)
|
impersonationConfig := testlib.NewClientConfig(t)
|
||||||
impersonationConfig.Impersonate = rest.ImpersonationConfig{
|
impersonationConfig.Impersonate = rest.ImpersonationConfig{
|
||||||
UserName: "solaire",
|
UserName: "solaire",
|
||||||
// need to impersonate system:authenticated directly to support older clusters otherwise we will get RBAC errors below
|
// need to impersonate system:authenticated directly to support older clusters otherwise we will get RBAC errors below
|
||||||
@ -379,7 +379,7 @@ func TestWhoAmI_ImpersonateDirectly(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
whoAmI, err := library.NewKubeclient(t, impersonationConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
whoAmI, err := testlib.NewKubeclient(t, impersonationConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -406,12 +406,12 @@ func TestWhoAmI_ImpersonateDirectly(t *testing.T) {
|
|||||||
whoAmI,
|
whoAmI,
|
||||||
)
|
)
|
||||||
|
|
||||||
impersonationAnonymousConfig := library.NewClientConfig(t)
|
impersonationAnonymousConfig := testlib.NewClientConfig(t)
|
||||||
impersonationAnonymousConfig.Impersonate.UserName = "system:anonymous"
|
impersonationAnonymousConfig.Impersonate.UserName = "system:anonymous"
|
||||||
// need to impersonate system:unauthenticated directly to support older clusters otherwise we will get RBAC errors below
|
// need to impersonate system:unauthenticated directly to support older clusters otherwise we will get RBAC errors below
|
||||||
impersonationAnonymousConfig.Impersonate.Groups = []string{"system:unauthenticated"}
|
impersonationAnonymousConfig.Impersonate.Groups = []string{"system:unauthenticated"}
|
||||||
|
|
||||||
whoAmIAnonymous, err := library.NewKubeclient(t, impersonationAnonymousConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
whoAmIAnonymous, err := testlib.NewKubeclient(t, impersonationAnonymousConfig).PinnipedConcierge.IdentityV1alpha1().WhoAmIRequests().
|
||||||
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/sclevine/agouti"
|
"github.com/sclevine/agouti"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"go.pinniped.dev/test/library"
|
"go.pinniped.dev/test/testlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -25,7 +25,7 @@ const (
|
|||||||
// in a mode that ignore certificate errors.
|
// in a mode that ignore certificate errors.
|
||||||
func Open(t *testing.T) *agouti.Page {
|
func Open(t *testing.T) *agouti.Page {
|
||||||
t.Logf("opening browser driver")
|
t.Logf("opening browser driver")
|
||||||
env := library.IntegrationEnv(t)
|
env := testlib.IntegrationEnv(t)
|
||||||
caps := agouti.NewCapabilities()
|
caps := agouti.NewCapabilities()
|
||||||
if env.Proxy != "" {
|
if env.Proxy != "" {
|
||||||
t.Logf("configuring Chrome to use proxy %q", env.Proxy)
|
t.Logf("configuring Chrome to use proxy %q", env.Proxy)
|
||||||
@ -59,7 +59,7 @@ func Open(t *testing.T) *agouti.Page {
|
|||||||
func WaitForVisibleElements(t *testing.T, page *agouti.Page, selectors ...string) {
|
func WaitForVisibleElements(t *testing.T, page *agouti.Page, selectors ...string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
library.RequireEventuallyf(t,
|
testlib.RequireEventuallyf(t,
|
||||||
func(requireEventually *require.Assertions) {
|
func(requireEventually *require.Assertions) {
|
||||||
for _, sel := range selectors {
|
for _, sel := range selectors {
|
||||||
vis, err := page.First(sel).Visible()
|
vis, err := page.First(sel).Visible()
|
||||||
@ -78,7 +78,7 @@ func WaitForVisibleElements(t *testing.T, page *agouti.Page, selectors ...string
|
|||||||
// to occur and times out, failing the test, if it never does.
|
// to occur and times out, failing the test, if it never does.
|
||||||
func WaitForURL(t *testing.T, page *agouti.Page, pat *regexp.Regexp) {
|
func WaitForURL(t *testing.T, page *agouti.Page, pat *regexp.Regexp) {
|
||||||
var lastURL string
|
var lastURL string
|
||||||
library.RequireEventuallyf(t,
|
testlib.RequireEventuallyf(t,
|
||||||
func(requireEventually *require.Assertions) {
|
func(requireEventually *require.Assertions) {
|
||||||
url, err := page.URL()
|
url, err := page.URL()
|
||||||
if url != lastURL {
|
if url != lastURL {
|
||||||
@ -97,7 +97,7 @@ func WaitForURL(t *testing.T, page *agouti.Page, pat *regexp.Regexp) {
|
|||||||
|
|
||||||
// LoginToUpstream expects the page to be redirected to one of several known upstream IDPs.
|
// LoginToUpstream expects the page to be redirected to one of several known upstream IDPs.
|
||||||
// It knows how to enter the test username/password and submit the upstream login form.
|
// It knows how to enter the test username/password and submit the upstream login form.
|
||||||
func LoginToUpstream(t *testing.T, page *agouti.Page, upstream library.TestOIDCUpstream) {
|
func LoginToUpstream(t *testing.T, page *agouti.Page, upstream testlib.TestOIDCUpstream) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
// +build !go1.14
|
// +build !go1.14
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
// +build go1.14
|
// +build go1.14
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package library
|
package testlib
|
||||||
|
|
||||||
import "github.com/davecgh/go-spew/spew"
|
import "github.com/davecgh/go-spew/spew"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user