From 736e2472c60661136f10c051032cb872e3d1125c Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Thu, 22 Jan 2026 12:53:11 -0800 Subject: [PATCH] integration tests decide if cluster supports anon auth more dynamically --- test/cluster_capabilities/aks.yaml | 14 ++-- test/cluster_capabilities/eks.yaml | 15 ++-- test/cluster_capabilities/gke.yaml | 15 ++-- test/cluster_capabilities/kind.yaml | 14 ++-- test/cluster_capabilities/tkgs.yaml | 14 ++-- .../concierge_credentialrequest_test.go | 10 +-- .../concierge_impersonation_proxy_test.go | 77 +++++++++++++------ test/integration/concierge_whoami_test.go | 4 +- .../supervisor_oidcclientsecret_test.go | 10 +-- test/testlib/env.go | 64 ++++++++++++--- 10 files changed, 166 insertions(+), 71 deletions(-) diff --git a/test/cluster_capabilities/aks.yaml b/test/cluster_capabilities/aks.yaml index 8bdfa98ef..f03a44b96 100644 --- a/test/cluster_capabilities/aks.yaml +++ b/test/cluster_capabilities/aks.yaml @@ -1,4 +1,4 @@ -# Copyright 2021 the Pinniped contributors. All Rights Reserved. +# Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 # The name of the cluster type. @@ -13,9 +13,13 @@ capabilities: # Will the cluster successfully provision a load balancer if requested? hasExternalLoadBalancerProvider: true - # Does the cluster allow requests without authentication? - # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests - anonymousAuthenticationSupported: false - # Are LDAP ports on the Internet reachable without interference from network firewalls or proxies? canReachInternetLDAPPorts: true + + # Does the cluster allow requests without authentication? + # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests + anonymousAuthentication: + healthEndpoints: + allowed: false + otherEndpoints: + allowed: false diff --git a/test/cluster_capabilities/eks.yaml b/test/cluster_capabilities/eks.yaml index 304922f87..f13f15100 100644 --- a/test/cluster_capabilities/eks.yaml +++ b/test/cluster_capabilities/eks.yaml @@ -1,4 +1,4 @@ -# Copyright 2021 the Pinniped contributors. All Rights Reserved. +# Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 # The name of the cluster type. @@ -13,9 +13,14 @@ capabilities: # Will the cluster successfully provision a load balancer if requested? hasExternalLoadBalancerProvider: true - # Does the cluster allow requests without authentication? - # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests - anonymousAuthenticationSupported: true - # Are LDAP ports on the Internet reachable without interference from network firewalls or proxies? canReachInternetLDAPPorts: true + + # Does the cluster allow requests without authentication? + # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests + # Amazon disabled anonymous authentication in EKS clusters starting with k8s 1.32. + anonymousAuthentication: + healthEndpoints: + allowed: true + otherEndpoints: + allowedIfK8sMinorVersionLessThan: 32 diff --git a/test/cluster_capabilities/gke.yaml b/test/cluster_capabilities/gke.yaml index a1247788c..be5a56d79 100644 --- a/test/cluster_capabilities/gke.yaml +++ b/test/cluster_capabilities/gke.yaml @@ -1,4 +1,4 @@ -# Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +# Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 # The name of the cluster type. @@ -13,9 +13,14 @@ capabilities: # Will the cluster successfully provision a load balancer if requested? hasExternalLoadBalancerProvider: true - # Does the cluster allow requests without authentication? - # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests - anonymousAuthenticationSupported: true - # Are LDAP ports on the Internet reachable without interference from network firewalls or proxies? canReachInternetLDAPPorts: true + + # Does the cluster allow requests without authentication? + # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests + # Google disabled anonymous authentication in GKE clusters by default starting with k8s 1.35. + anonymousAuthentication: + healthEndpoints: + allowed: true + otherEndpoints: + allowedIfK8sMinorVersionLessThan: 35 diff --git a/test/cluster_capabilities/kind.yaml b/test/cluster_capabilities/kind.yaml index 485ba5060..7a707fd02 100644 --- a/test/cluster_capabilities/kind.yaml +++ b/test/cluster_capabilities/kind.yaml @@ -1,4 +1,4 @@ -# Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +# Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 # The name of the cluster type. @@ -13,9 +13,13 @@ capabilities: # Will the cluster successfully provision a load balancer if requested? hasExternalLoadBalancerProvider: false - # Does the cluster allow requests without authentication? - # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests - anonymousAuthenticationSupported: true - # Are LDAP ports on the Internet reachable without interference from network firewalls or proxies? canReachInternetLDAPPorts: true + + # Does the cluster allow requests without authentication? + # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests + anonymousAuthentication: + healthEndpoints: + allowed: true + otherEndpoints: + allowed: true diff --git a/test/cluster_capabilities/tkgs.yaml b/test/cluster_capabilities/tkgs.yaml index 86220291e..8361bea24 100644 --- a/test/cluster_capabilities/tkgs.yaml +++ b/test/cluster_capabilities/tkgs.yaml @@ -1,4 +1,4 @@ -# Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +# Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 # The name of the cluster type. @@ -13,9 +13,13 @@ capabilities: # Will the cluster successfully provision a load balancer if requested? hasExternalLoadBalancerProvider: true - # Does the cluster allow requests without authentication? - # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests - anonymousAuthenticationSupported: true - # Are LDAP ports on the Internet reachable without interference from network firewalls or proxies? canReachInternetLDAPPorts: true + + # Does the cluster allow requests without authentication? + # https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests + anonymousAuthentication: + healthEndpoints: + allowed: true + otherEndpoints: + allowed: true diff --git a/test/integration/concierge_credentialrequest_test.go b/test/integration/concierge_credentialrequest_test.go index 91a3a90b9..bbac52338 100644 --- a/test/integration/concierge_credentialrequest_test.go +++ b/test/integration/concierge_credentialrequest_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package integration @@ -218,7 +218,7 @@ func TestCredentialRequest_Browser(t *testing.T) { // for its localhost listener via --listen-port=env.CLIUpstreamOIDC.CallbackURL.Port() per oidcLoginCommand. // Since ports are global to the process, tests using oidcLoginCommand must be run serially. func TestCredentialRequest_JWTAuthenticatorRulesToDisallowLogin_Browser(t *testing.T) { - env := testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupported) + env := testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) basicSpec := &authenticationv1alpha1.JWTAuthenticatorSpec{ Issuer: env.CLIUpstreamOIDC.Issuer, @@ -321,7 +321,7 @@ func TestCredentialRequest_JWTAuthenticatorRulesToDisallowLogin_Browser(t *testi // TCRs are non-mutating and safe to run in parallel with serial tests, see main_test.go. func TestCredentialRequest_ShouldFailWhenTheAuthenticatorDoesNotExist_Parallel(t *testing.T) { - env := testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupported) + env := testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) ctx, cancel := context.WithTimeout(context.Background(), time.Minute) t.Cleanup(cancel) @@ -344,7 +344,7 @@ func TestCredentialRequest_ShouldFailWhenTheAuthenticatorDoesNotExist_Parallel(t // TCRs are non-mutating and safe to run in parallel with serial tests, see main_test.go. func TestCredentialRequest_ShouldFailWhenTheRequestIsValidButTheTokenDoesNotAuthenticateTheUser_Parallel(t *testing.T) { - env := testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupported) + env := testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) // Create a testWebhook so we have a legitimate authenticator to pass to the TokenCredentialRequest API. ctx, cancel := context.WithTimeout(context.Background(), time.Minute) @@ -365,7 +365,7 @@ func TestCredentialRequest_ShouldFailWhenTheRequestIsValidButTheTokenDoesNotAuth // TCRs are non-mutating and safe to run in parallel with serial tests, see main_test.go. func TestCredentialRequest_ShouldFailWhenRequestDoesNotIncludeToken_Parallel(t *testing.T) { - env := testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupported) + env := testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) // Create a testWebhook so we have a legitimate authenticator to pass to the TokenCredentialRequest API. ctx, cancel := context.WithTimeout(context.Background(), time.Minute) diff --git a/test/integration/concierge_impersonation_proxy_test.go b/test/integration/concierge_impersonation_proxy_test.go index a4abb9e61..b4f6ab55e 100644 --- a/test/integration/concierge_impersonation_proxy_test.go +++ b/test/integration/concierge_impersonation_proxy_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package integration @@ -902,8 +902,8 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl whoAmI, err = impersonationProxyAnonymousPinnipedConciergeClient.IdentityV1alpha1().WhoAmIRequests(). Create(ctx, &identityv1alpha1.WhoAmIRequest{}, metav1.CreateOptions{}) - // we expect the impersonation proxy to match the behavior of KAS in regards to anonymous requests - if env.HasCapability(testlib.AnonymousAuthenticationSupported) { + // we expect the impersonation proxy to match the behavior of KAS in regard to anonymous requests + if env.HasCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) { require.NoError(t, err, testlib.Sdump(err)) require.Equal(t, expectedWhoAmIRequestResponse( @@ -1409,8 +1409,8 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl }) }) - t.Run("anonymous authentication enabled", func(t *testing.T) { - testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupported) + t.Run("anonymous authentication enabled for health checks", func(t *testing.T) { + testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupportedForHealthEndpoints) parallelIfNotEKS(t) // anonymous auth enabled @@ -1421,11 +1421,50 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl t.Run("non-resource request", func(t *testing.T) { parallelIfNotEKS(t) - healthz, errHealth := impersonationProxyAnonymousRestClient.Get().AbsPath("/healthz").DoRaw(ctx) - require.NoError(t, errHealth, testlib.Sdump(errHealth)) - require.Equal(t, "ok", string(healthz)) - }) + response, err := impersonationProxyAnonymousRestClient.Get().AbsPath("/healthz").DoRaw(ctx) + require.NoError(t, err, testlib.Sdump(err)) + require.Equal(t, "ok", string(response)) + response, err = impersonationProxyAnonymousRestClient.Get().AbsPath("/readyz").DoRaw(ctx) + require.NoError(t, err, testlib.Sdump(err)) + require.Equal(t, "ok", string(response)) + + response, err = impersonationProxyAnonymousRestClient.Get().AbsPath("/livez").DoRaw(ctx) + require.NoError(t, err, testlib.Sdump(err)) + require.Equal(t, "ok", string(response)) + }) + }) + + t.Run("anonymous authentication disabled for health checks", func(t *testing.T) { + testlib.IntegrationEnv(t).WithoutCapability(testlib.AnonymousAuthenticationSupportedForHealthEndpoints) + parallelIfNotEKS(t) + + // anonymous auth disabled + // - hit the healthz endpoint (non-resource endpoint) + // - through the impersonation proxy + // - should fail Unauthorized + t.Run("non-resource request", func(t *testing.T) { + parallelIfNotEKS(t) + + expectedResponse := `{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}` + "\n" + + response, err := impersonationProxyAnonymousRestClient.Get().AbsPath("/healthz").DoRaw(ctx) + require.True(t, apierrors.IsUnauthorized(err), testlib.Sdump(err)) + require.Equal(t, expectedResponse, string(response)) + + response, err = impersonationProxyAnonymousRestClient.Get().AbsPath("/readyz").DoRaw(ctx) + require.True(t, apierrors.IsUnauthorized(err), testlib.Sdump(err)) + require.Equal(t, expectedResponse, string(response)) + + response, err = impersonationProxyAnonymousRestClient.Get().AbsPath("/livez").DoRaw(ctx) + require.True(t, apierrors.IsUnauthorized(err), testlib.Sdump(err)) + require.Equal(t, expectedResponse, string(response)) + }) + }) + + t.Run("anonymous authentication enabled for other endpoints", func(t *testing.T) { + testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) + parallelIfNotEKS(t) // - hit the pods endpoint (a resource endpoint) // - through the impersonation proxy // - should fail forbidden @@ -1462,22 +1501,10 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl }) }) - t.Run("anonymous authentication disabled", func(t *testing.T) { - testlib.IntegrationEnv(t).WithoutCapability(testlib.AnonymousAuthenticationSupported) + t.Run("anonymous authentication disabled for other endpoints", func(t *testing.T) { + testlib.IntegrationEnv(t).WithoutCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) parallelIfNotEKS(t) - // - hit the healthz endpoint (non-resource endpoint) - // - through the impersonation proxy - // - should fail unauthorized - // - kube api server should reject it - t.Run("non-resource request", func(t *testing.T) { - parallelIfNotEKS(t) - - healthz, err := impersonationProxyAnonymousRestClient.Get().AbsPath("/healthz").DoRaw(ctx) - require.True(t, apierrors.IsUnauthorized(err), testlib.Sdump(err)) - require.Equal(t, `{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}`+"\n", string(healthz)) - }) - // - hit the pods endpoint (a resource endpoint) // - through the impersonation proxy // - should fail unauthorized @@ -1491,7 +1518,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl require.Equal(t, &corev1.Pod{}, pod) }) - // - request to whoami (pinniped resource endpoing) + // - request to whoami (pinniped resource endpoint) // - through the impersonation proxy // - should fail unauthorized // - kube api server should reject it @@ -1982,7 +2009,7 @@ 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. requireDisabledStrategy(ctx, t, env, adminConciergeClient) - if !env.HasCapability(testlib.ClusterSigningKeyIsAvailable) && env.HasCapability(testlib.AnonymousAuthenticationSupported) { + if !env.HasCapability(testlib.ClusterSigningKeyIsAvailable) && env.HasCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) { // 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. // Given that there are no working strategies, a TokenCredentialRequest which would otherwise work should now diff --git a/test/integration/concierge_whoami_test.go b/test/integration/concierge_whoami_test.go index af80f0852..fa22cb6ad 100644 --- a/test/integration/concierge_whoami_test.go +++ b/test/integration/concierge_whoami_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package integration @@ -394,7 +394,7 @@ func maybeNeedsExtraWithSHA256( // whoami requests are non-mutating and safe to run in parallel with serial tests, see main_test.go. func TestWhoAmI_Anonymous_Parallel(t *testing.T) { - _ = testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupported) + _ = testlib.IntegrationEnv(t).WithCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() diff --git a/test/integration/supervisor_oidcclientsecret_test.go b/test/integration/supervisor_oidcclientsecret_test.go index 610a8b12a..139becd1c 100644 --- a/test/integration/supervisor_oidcclientsecret_test.go +++ b/test/integration/supervisor_oidcclientsecret_test.go @@ -1,4 +1,4 @@ -// Copyright 2022-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2022-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package integration @@ -1040,11 +1040,11 @@ func TestOIDCClientSecretRequestUnauthenticated_Parallel(t *testing.T) { }, metav1.CreateOptions{}) require.Error(t, err) - if env.KubernetesDistribution == testlib.AKSDistro { - // On AKS the error just says "Unauthorized". - require.Contains(t, err.Error(), "Unauthorized") - } else { + if env.HasCapability(testlib.AnonymousAuthenticationSupportedForOtherEndpoints) { // Clusters which allow anonymous auth will give a more detailed error. require.Contains(t, err.Error(), `User "system:anonymous" cannot create resource "oidcclientsecretrequests"`) + } else { + // On AKS and any other cluster which disallows anonymous auth, the error just says "Unauthorized". + require.Contains(t, err.Error(), "Unauthorized") } } diff --git a/test/testlib/env.go b/test/testlib/env.go index bb55ff06a..0c4ea0310 100644 --- a/test/testlib/env.go +++ b/test/testlib/env.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package testlib @@ -9,6 +9,7 @@ import ( "net/url" "os" "sort" + "strconv" "strings" "sync" "testing" @@ -17,16 +18,18 @@ import ( "sigs.k8s.io/yaml" authenticationv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1" + "go.pinniped.dev/internal/testutil" ) type Capability string type KubeDistro string const ( - ClusterSigningKeyIsAvailable Capability = "clusterSigningKeyIsAvailable" - AnonymousAuthenticationSupported Capability = "anonymousAuthenticationSupported" - HasExternalLoadBalancerProvider Capability = "hasExternalLoadBalancerProvider" - CanReachInternetLDAPPorts Capability = "canReachInternetLDAPPorts" + ClusterSigningKeyIsAvailable Capability = "clusterSigningKeyIsAvailable" + HasExternalLoadBalancerProvider Capability = "hasExternalLoadBalancerProvider" + CanReachInternetLDAPPorts Capability = "canReachInternetLDAPPorts" + AnonymousAuthenticationSupportedForHealthEndpoints Capability = "anonymousAuthenticationSupportedForHealthEndpoints" + AnonymousAuthenticationSupportedForOtherEndpoints Capability = "anonymousAuthenticationSupportedForOtherEndpoints" KindDistro KubeDistro = "Kind" GKEDistro KubeDistro = "GKE" @@ -35,6 +38,24 @@ const ( TKGSDistro KubeDistro = "TKGS" ) +type Capabilities struct { + ClusterSigningKeyIsAvailable bool `json:"clusterSigningKeyIsAvailable"` + HasExternalLoadBalancerProvider bool `json:"hasExternalLoadBalancerProvider"` + CanReachInternetLDAPPorts bool `json:"canReachInternetLDAPPorts"` + + AnonymousAuthentication AnonymousAuthenticationCapabilities `json:"anonymousAuthentication"` +} + +type AnonymousAuthenticationCapabilities struct { + HealthEndpoints AnonymousAuthenticationEndpointCapability `json:"healthEndpoints"` + OtherEndpoints AnonymousAuthenticationEndpointCapability `json:"otherEndpoints"` +} + +type AnonymousAuthenticationEndpointCapability struct { + Allowed bool `json:"allowed"` + AllowedIfK8sMinorVersionLessThan string `json:"allowedIfK8sMinorVersionLessThan"` +} + // TestEnv captures all the external parameters consumed by our integration tests. type TestEnv struct { t *testing.T @@ -50,7 +71,7 @@ type TestEnv struct { SupervisorCustomLabels map[string]string `json:"supervisorCustomLabels"` ConciergeCustomLabels map[string]string `json:"conciergeCustomLabels"` KubernetesDistribution KubeDistro `json:"kubernetesDistribution"` - Capabilities map[Capability]bool `json:"capabilities"` + Capabilities Capabilities `json:"capabilities"` TestWebhook authenticationv1alpha1.WebhookAuthenticatorSpec `json:"testWebhook"` SupervisorHTTPSAddress string `json:"supervisorHttpsAddress"` SupervisorHTTPSIngressAddress string `json:"supervisorHttpsIngressAddress"` @@ -400,9 +421,34 @@ func loadEnvVars(t *testing.T, result *TestEnv) { func (e *TestEnv) HasCapability(cap Capability) bool { e.t.Helper() - isCapable, capabilityWasDescribed := e.Capabilities[cap] - require.Truef(e.t, capabilityWasDescribed, "the %q capability of the test environment was not described", cap) - return isCapable + + switch cap { + case AnonymousAuthenticationSupportedForHealthEndpoints: + versionLessThan := e.Capabilities.AnonymousAuthentication.HealthEndpoints.AllowedIfK8sMinorVersionLessThan + if versionLessThan == "" { + return e.Capabilities.AnonymousAuthentication.HealthEndpoints.Allowed + } + minorVersionNumber, err := strconv.Atoi(versionLessThan) + require.NoError(e.t, err, "could not parse minor version number from AnonymousAuthentication HealthEndpoints capability as int") + return !testutil.KubeServerMinorVersionAtLeastInclusive(e.t, NewKubernetesClientset(e.t).Discovery(), minorVersionNumber) + case AnonymousAuthenticationSupportedForOtherEndpoints: + versionLessThan := e.Capabilities.AnonymousAuthentication.OtherEndpoints.AllowedIfK8sMinorVersionLessThan + if versionLessThan == "" { + return e.Capabilities.AnonymousAuthentication.OtherEndpoints.Allowed + } + minorVersionNumber, err := strconv.Atoi(versionLessThan) + require.NoError(e.t, err, "could not parse minor version number from AnonymousAuthentication OtherEndpoints capability as int") + return !testutil.KubeServerMinorVersionAtLeastInclusive(e.t, NewKubernetesClientset(e.t).Discovery(), minorVersionNumber) + case ClusterSigningKeyIsAvailable: + return e.Capabilities.ClusterSigningKeyIsAvailable + case HasExternalLoadBalancerProvider: + return e.Capabilities.HasExternalLoadBalancerProvider + case CanReachInternetLDAPPorts: + return e.Capabilities.CanReachInternetLDAPPorts + default: + require.Failf(e.t, "unknown capability type", "name: %s", cap) + return false + } } func (e *TestEnv) WithCapability(cap Capability) *TestEnv {