mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2025-12-23 14:25:50 +00:00
Update webhook status integration tests
- total api fields test 260->261
This commit is contained in:
@@ -39,24 +39,24 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
controllerName = "webhookcachefiller-controller"
|
||||
typeReady = "Ready"
|
||||
typeTLSBundleValid = "TLSBundleValid"
|
||||
typeTLSConnetionNegotiationValid = "TLSConnetionNegotiationValid"
|
||||
typeEndpointURLValid = "EndpointURLValid"
|
||||
typeAuthenticatorValid = "AuthenticatorValid"
|
||||
reasonSuccess = "Success"
|
||||
reasonNotReady = "NotReady"
|
||||
reasonUnableToValidate = "UnableToValidate"
|
||||
reasonUnableToCreateTempFile = "UnableToCreateTempFile"
|
||||
reasonUnableToMarshallKubeconfig = "UnableToMarshallKubeconfig"
|
||||
reasonUnableToLoadKubeconfig = "UnableToLoadKubeconfig"
|
||||
reasonUnableToInstantiateWebhook = "UnableToInstantiateWebhook"
|
||||
reasonInvalidTLSConfiguration = "InvalidTLSConfiguration"
|
||||
reasonInvalidEndpointURL = "InvalidEndpointURL"
|
||||
reasonInvalidEndpointURLScheme = "InvalidEndpointURLScheme"
|
||||
reasonUnableToDialServer = "UnableToDialServer"
|
||||
msgUnableToValidate = "unable to validate; see other conditions for details"
|
||||
controllerName = "webhookcachefiller-controller"
|
||||
typeReady = "Ready"
|
||||
typeTLSConfigurationValid = "TLSConfigurationValid"
|
||||
typeTLSConnectionNegotiationValid = "TLSConnectionNegotiationValid"
|
||||
typeEndpointURLValid = "EndpointURLValid"
|
||||
typeAuthenticatorValid = "AuthenticatorValid"
|
||||
reasonSuccess = "Success"
|
||||
reasonNotReady = "NotReady"
|
||||
reasonUnableToValidate = "UnableToValidate"
|
||||
reasonUnableToCreateTempFile = "UnableToCreateTempFile"
|
||||
reasonUnableToMarshallKubeconfig = "UnableToMarshallKubeconfig"
|
||||
reasonUnableToLoadKubeconfig = "UnableToLoadKubeconfig"
|
||||
reasonUnableToInstantiateWebhook = "UnableToInstantiateWebhook"
|
||||
reasonInvalidTLSConfiguration = "InvalidTLSConfiguration"
|
||||
reasonInvalidEndpointURL = "InvalidEndpointURL"
|
||||
reasonInvalidEndpointURLScheme = "InvalidEndpointURLScheme"
|
||||
reasonUnableToDialServer = "UnableToDialServer"
|
||||
msgUnableToValidate = "unable to validate; see other conditions for details"
|
||||
)
|
||||
|
||||
// New instantiates a new controllerlib.Controller which will populate the provided authncache.Cache.
|
||||
@@ -281,7 +281,7 @@ func newWebhookAuthenticator(
|
||||
func (c *webhookCacheFillerController) validateTLSNegotiation(certPool *x509.CertPool, endpointURL *url.URL, conditions []*metav1.Condition, prereqOk bool) ([]*metav1.Condition, error) {
|
||||
if !prereqOk {
|
||||
conditions = append(conditions, &metav1.Condition{
|
||||
Type: typeTLSConnetionNegotiationValid,
|
||||
Type: typeTLSConnectionNegotiationValid,
|
||||
Status: metav1.ConditionUnknown,
|
||||
Reason: reasonUnableToValidate,
|
||||
Message: msgUnableToValidate,
|
||||
@@ -307,7 +307,7 @@ func (c *webhookCacheFillerController) validateTLSNegotiation(certPool *x509.Cer
|
||||
errText := "cannot dial server"
|
||||
msg := fmt.Sprintf("%s: %s", errText, dialErr.Error())
|
||||
conditions = append(conditions, &metav1.Condition{
|
||||
Type: typeTLSConnetionNegotiationValid,
|
||||
Type: typeTLSConnectionNegotiationValid,
|
||||
Status: metav1.ConditionFalse,
|
||||
Reason: reasonUnableToDialServer,
|
||||
Message: msg,
|
||||
@@ -322,7 +322,7 @@ func (c *webhookCacheFillerController) validateTLSNegotiation(certPool *x509.Cer
|
||||
}
|
||||
|
||||
conditions = append(conditions, &metav1.Condition{
|
||||
Type: typeTLSConnetionNegotiationValid,
|
||||
Type: typeTLSConnectionNegotiationValid,
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: reasonSuccess,
|
||||
Message: "tls verified",
|
||||
@@ -335,7 +335,7 @@ func (c *webhookCacheFillerController) validateTLSBundle(tlsSpec *auth1alpha1.TL
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("%s: %s", "invalid TLS configuration", err.Error())
|
||||
conditions = append(conditions, &metav1.Condition{
|
||||
Type: typeTLSBundleValid,
|
||||
Type: typeTLSConfigurationValid,
|
||||
Status: metav1.ConditionFalse,
|
||||
Reason: reasonInvalidTLSConfiguration,
|
||||
Message: msg,
|
||||
@@ -347,7 +347,7 @@ func (c *webhookCacheFillerController) validateTLSBundle(tlsSpec *auth1alpha1.TL
|
||||
msg = "no CA bundle specified"
|
||||
}
|
||||
conditions = append(conditions, &metav1.Condition{
|
||||
Type: typeTLSBundleValid,
|
||||
Type: typeTLSConfigurationValid,
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: reasonSuccess,
|
||||
Message: msg,
|
||||
|
||||
@@ -240,9 +240,9 @@ func TestController(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
happyTLSBundleValidCAParsed := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
happyTLSConfigurationValidCAParsed := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
return metav1.Condition{
|
||||
Type: "TLSBundleValid",
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: "True",
|
||||
ObservedGeneration: observedGeneration,
|
||||
LastTransitionTime: time,
|
||||
@@ -250,9 +250,9 @@ func TestController(t *testing.T) {
|
||||
Message: "successfully parsed specified CA bundle",
|
||||
}
|
||||
}
|
||||
happyTLSBundleValidNoCA := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
happyTLSConfigurationValidNoCA := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
return metav1.Condition{
|
||||
Type: "TLSBundleValid",
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: "True",
|
||||
ObservedGeneration: observedGeneration,
|
||||
LastTransitionTime: time,
|
||||
@@ -260,9 +260,9 @@ func TestController(t *testing.T) {
|
||||
Message: "no CA bundle specified",
|
||||
}
|
||||
}
|
||||
sadTLSBundleValid := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
sadTLSConfigurationValid := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
return metav1.Condition{
|
||||
Type: "TLSBundleValid",
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: "False",
|
||||
ObservedGeneration: observedGeneration,
|
||||
LastTransitionTime: time,
|
||||
@@ -271,9 +271,9 @@ func TestController(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
happyTLSConnetionNegotiationValid := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
happyTLSConnectionNegotiationValid := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
return metav1.Condition{
|
||||
Type: "TLSConnetionNegotiationValid",
|
||||
Type: "TLSConnectionNegotiationValid",
|
||||
Status: "True",
|
||||
ObservedGeneration: observedGeneration,
|
||||
LastTransitionTime: time,
|
||||
@@ -281,9 +281,9 @@ func TestController(t *testing.T) {
|
||||
Message: "tls verified",
|
||||
}
|
||||
}
|
||||
unknownTLSConnetionNegotiationValid := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
unknownTLSConnectionNegotiationValid := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
return metav1.Condition{
|
||||
Type: "TLSConnetionNegotiationValid",
|
||||
Type: "TLSConnectionNegotiationValid",
|
||||
Status: "Unknown",
|
||||
ObservedGeneration: observedGeneration,
|
||||
LastTransitionTime: time,
|
||||
@@ -291,9 +291,9 @@ func TestController(t *testing.T) {
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}
|
||||
}
|
||||
sadTLSConnetionNegotiationValid := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
sadTLSConnectionNegotiationValid := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
return metav1.Condition{
|
||||
Type: "TLSConnetionNegotiationValid",
|
||||
Type: "TLSConnectionNegotiationValid",
|
||||
Status: "False",
|
||||
ObservedGeneration: observedGeneration,
|
||||
LastTransitionTime: time,
|
||||
@@ -301,9 +301,9 @@ func TestController(t *testing.T) {
|
||||
Message: "cannot dial server: tls: failed to verify certificate: x509: certificate signed by unknown authority",
|
||||
}
|
||||
}
|
||||
sadTLSConnetionNegotiationNoIPSANs := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
sadTLSConnectionNegotiationNoIPSANs := func(time metav1.Time, observedGeneration int64) metav1.Condition {
|
||||
return metav1.Condition{
|
||||
Type: "TLSConnetionNegotiationValid",
|
||||
Type: "TLSConnectionNegotiationValid",
|
||||
Status: "False",
|
||||
ObservedGeneration: observedGeneration,
|
||||
LastTransitionTime: time,
|
||||
@@ -345,9 +345,9 @@ func TestController(t *testing.T) {
|
||||
|
||||
allHappyConditionsSuccess := func(endpoint string, someTime metav1.Time, observedGeneration int64) []metav1.Condition {
|
||||
return conditionstestutil.SortByType([]metav1.Condition{
|
||||
happyTLSBundleValidCAParsed(someTime, observedGeneration),
|
||||
happyTLSConfigurationValidCAParsed(someTime, observedGeneration),
|
||||
happyEndpointURLValid(someTime, observedGeneration),
|
||||
happyTLSConnetionNegotiationValid(someTime, observedGeneration),
|
||||
happyTLSConnectionNegotiationValid(someTime, observedGeneration),
|
||||
happyAuthenticatorValid(someTime, observedGeneration),
|
||||
happyReadyCondition(someTime, observedGeneration),
|
||||
})
|
||||
@@ -551,8 +551,8 @@ func TestController(t *testing.T) {
|
||||
Conditions: conditionstestutil.Replace(
|
||||
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
|
||||
[]metav1.Condition{
|
||||
happyTLSBundleValidNoCA(frozenMetav1Now, 0),
|
||||
sadTLSConnetionNegotiationValid(frozenMetav1Now, 0),
|
||||
happyTLSConfigurationValidNoCA(frozenMetav1Now, 0),
|
||||
sadTLSConnectionNegotiationValid(frozenMetav1Now, 0),
|
||||
sadReadyCondition(frozenMetav1Now, 0),
|
||||
unknownAuthenticatorValid(frozenMetav1Now, 0),
|
||||
},
|
||||
@@ -591,8 +591,8 @@ func TestController(t *testing.T) {
|
||||
Conditions: conditionstestutil.Replace(
|
||||
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
|
||||
[]metav1.Condition{
|
||||
sadTLSBundleValid(frozenMetav1Now, 0),
|
||||
unknownTLSConnetionNegotiationValid(frozenMetav1Now, 0),
|
||||
sadTLSConfigurationValid(frozenMetav1Now, 0),
|
||||
unknownTLSConnectionNegotiationValid(frozenMetav1Now, 0),
|
||||
unknownAuthenticatorValid(frozenMetav1Now, 0),
|
||||
sadReadyCondition(frozenMetav1Now, 0),
|
||||
},
|
||||
@@ -634,9 +634,9 @@ func TestController(t *testing.T) {
|
||||
Conditions: conditionstestutil.Replace(
|
||||
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
|
||||
[]metav1.Condition{
|
||||
happyTLSBundleValidNoCA(frozenMetav1Now, 0),
|
||||
happyTLSConfigurationValidNoCA(frozenMetav1Now, 0),
|
||||
sadEndpointURLValid("https://.café .com/café/café/café/coffee", frozenMetav1Now, 0),
|
||||
unknownTLSConnetionNegotiationValid(frozenMetav1Now, 0),
|
||||
unknownTLSConnectionNegotiationValid(frozenMetav1Now, 0),
|
||||
unknownAuthenticatorValid(frozenMetav1Now, 0),
|
||||
sadReadyCondition(frozenMetav1Now, 0),
|
||||
},
|
||||
@@ -677,9 +677,9 @@ func TestController(t *testing.T) {
|
||||
Conditions: conditionstestutil.Replace(
|
||||
allHappyConditionsSuccess(goodEndpoint, frozenMetav1Now, 0),
|
||||
[]metav1.Condition{
|
||||
happyTLSBundleValidNoCA(frozenMetav1Now, 0),
|
||||
happyTLSConfigurationValidNoCA(frozenMetav1Now, 0),
|
||||
sadEndpointURLValidHTTPS("http://localhost", frozenMetav1Now, 0),
|
||||
unknownTLSConnetionNegotiationValid(frozenMetav1Now, 0),
|
||||
unknownTLSConnectionNegotiationValid(frozenMetav1Now, 0),
|
||||
unknownAuthenticatorValid(frozenMetav1Now, 0),
|
||||
sadReadyCondition(frozenMetav1Now, 0),
|
||||
},
|
||||
@@ -720,7 +720,7 @@ func TestController(t *testing.T) {
|
||||
[]metav1.Condition{
|
||||
unknownAuthenticatorValid(frozenMetav1Now, 0),
|
||||
sadReadyCondition(frozenMetav1Now, 0),
|
||||
sadTLSConnetionNegotiationValid(frozenMetav1Now, 0),
|
||||
sadTLSConnectionNegotiationValid(frozenMetav1Now, 0),
|
||||
},
|
||||
),
|
||||
Phase: "Error",
|
||||
@@ -878,7 +878,7 @@ func TestController(t *testing.T) {
|
||||
Conditions: conditionstestutil.Replace(
|
||||
allHappyConditionsSuccess(localWithExampleDotComCertServer.URL, frozenMetav1Now, 0),
|
||||
[]metav1.Condition{
|
||||
sadTLSConnetionNegotiationNoIPSANs(frozenMetav1Now, 0),
|
||||
sadTLSConnectionNegotiationNoIPSANs(frozenMetav1Now, 0),
|
||||
unknownAuthenticatorValid(frozenMetav1Now, 0),
|
||||
sadReadyCondition(frozenMetav1Now, 0),
|
||||
},
|
||||
|
||||
28
internal/testutil/conciergetestutil/tlstestutil.go
Normal file
28
internal/testutil/conciergetestutil/tlstestutil.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package conciergetestutil
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
|
||||
auth1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
)
|
||||
|
||||
func TlsSpecFromTLSConfig(tls *tls.Config) *auth1alpha1.TLSSpec {
|
||||
pemData := make([]byte, 0)
|
||||
for _, certificate := range tls.Certificates {
|
||||
// this is the public part of the certificate, the private is the certificate.PrivateKey
|
||||
for _, reallyCertificate := range certificate.Certificate {
|
||||
pemData = append(pemData, pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: reallyCertificate,
|
||||
})...)
|
||||
}
|
||||
}
|
||||
return &auth1alpha1.TLSSpec{
|
||||
CertificateAuthorityData: base64.StdEncoding.EncodeToString(pemData),
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package integration
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
identityv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/identity/v1alpha1"
|
||||
conciergescheme "go.pinniped.dev/internal/concierge/scheme"
|
||||
"go.pinniped.dev/pkg/oidcclient"
|
||||
@@ -42,7 +43,7 @@ func TestCLIGetKubeconfigStaticToken_Parallel(t *testing.T) {
|
||||
ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||
defer cancelFunc()
|
||||
|
||||
authenticator := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||
authenticator := testlib.CreateTestWebhookAuthenticator(ctx, t, nil, v1alpha1.WebhookAuthenticatorPhaseReady)
|
||||
|
||||
// Build pinniped CLI.
|
||||
pinnipedExe := testlib.PinnipedCLIPath(t)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package integration
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1"
|
||||
"go.pinniped.dev/internal/testutil"
|
||||
"go.pinniped.dev/test/testlib"
|
||||
@@ -83,7 +84,7 @@ func TestAPIServingCertificateAutoCreationAndRotation_Disruptive(t *testing.T) {
|
||||
|
||||
// Create a testWebhook so we have a legitimate authenticator to pass to the
|
||||
// TokenCredentialRequest API.
|
||||
testWebhook := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||
testWebhook := testlib.CreateTestWebhookAuthenticator(ctx, t, nil, v1alpha1.WebhookAuthenticatorPhaseReady)
|
||||
|
||||
// Get the initial auto-generated version of the Secret.
|
||||
secret, err := kubeClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package integration
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/pkg/conciergeclient"
|
||||
"go.pinniped.dev/test/testlib"
|
||||
@@ -58,7 +59,7 @@ func TestClient(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
webhook := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||
webhook := testlib.CreateTestWebhookAuthenticator(ctx, t, nil, v1alpha1.WebhookAuthenticatorPhaseReady)
|
||||
|
||||
// Use an invalid certificate/key to validate that the ServerVersion API fails like we assume.
|
||||
invalidClient := testlib.NewClientsetWithCertAndKey(t, testCert, testKey)
|
||||
|
||||
@@ -60,8 +60,15 @@ func TestSuccessfulCredentialRequest_Browser(t *testing.T) {
|
||||
token func(t *testing.T) (token string, username string, groups []string)
|
||||
}{
|
||||
{
|
||||
name: "webhook",
|
||||
authenticator: testlib.CreateTestWebhookAuthenticator,
|
||||
name: "webhook",
|
||||
authenticator: func(ctx context.Context, t *testing.T) corev1.TypedLocalObjectReference {
|
||||
authenticator := testlib.CreateTestWebhookAuthenticator(ctx, t, nil, auth1alpha1.WebhookAuthenticatorPhaseReady)
|
||||
return corev1.TypedLocalObjectReference{
|
||||
APIGroup: &auth1alpha1.SchemeGroupVersion.Group,
|
||||
Kind: "WebhookAuthenticator",
|
||||
Name: authenticator.Name,
|
||||
}
|
||||
},
|
||||
token: func(t *testing.T) (string, string, []string) {
|
||||
return testlib.IntegrationEnv(t).TestUser.Token, env.TestUser.ExpectedUsername, env.TestUser.ExpectedGroups
|
||||
},
|
||||
@@ -148,7 +155,7 @@ func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthentic
|
||||
// TokenCredentialRequest API.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
testWebhook := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||
testWebhook := testlib.CreateTestWebhookAuthenticator(ctx, t, nil, auth1alpha1.WebhookAuthenticatorPhaseReady)
|
||||
|
||||
response, err := testlib.CreateTokenCredentialRequest(context.Background(), t,
|
||||
loginv1alpha1.TokenCredentialRequestSpec{Token: "not a good token", Authenticator: testWebhook},
|
||||
@@ -169,7 +176,7 @@ func TestCredentialRequest_ShouldFailWhenRequestDoesNotIncludeToken_Parallel(t *
|
||||
// TokenCredentialRequest API.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
testWebhook := testlib.CreateTestWebhookAuthenticator(ctx, t)
|
||||
testWebhook := testlib.CreateTestWebhookAuthenticator(ctx, t, nil, auth1alpha1.WebhookAuthenticatorPhaseReady)
|
||||
|
||||
response, err := testlib.CreateTokenCredentialRequest(context.Background(), t,
|
||||
loginv1alpha1.TokenCredentialRequestSpec{Token: "", Authenticator: testWebhook},
|
||||
|
||||
@@ -61,6 +61,7 @@ import (
|
||||
"k8s.io/client-go/util/retry"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
conciergev1alpha "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
identityv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/identity/v1alpha1"
|
||||
loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1"
|
||||
@@ -120,7 +121,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
||||
// Create a WebhookAuthenticator and prepare a TokenCredentialRequestSpec using the authenticator for use later.
|
||||
credentialRequestSpecWithWorkingCredentials := loginv1alpha1.TokenCredentialRequestSpec{
|
||||
Token: env.TestUser.Token,
|
||||
Authenticator: testlib.CreateTestWebhookAuthenticator(ctx, t),
|
||||
Authenticator: testlib.CreateTestWebhookAuthenticator(ctx, t, nil, v1alpha1.WebhookAuthenticatorPhaseReady),
|
||||
}
|
||||
|
||||
// The address of the ClusterIP service that points at the impersonation proxy's port (used when there is no load balancer).
|
||||
|
||||
@@ -3,8 +3,294 @@
|
||||
|
||||
package integration
|
||||
|
||||
// TODO: for integration tests, not unit tests....
|
||||
// env.APIGroupSuffix for log messages/conditions when relevant, ie if "pinniped.dev" appears
|
||||
// env.CLIUpstreamOIDC.Issuer if a real endpoint is needed as we shouldn't actually make requests
|
||||
// to example.com
|
||||
// goodEndpoint := "https://example.com"
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
"go.pinniped.dev/test/testlib"
|
||||
)
|
||||
|
||||
func TestConciergeWebhookAuthenticatorStatus_Parallel(t *testing.T) {
|
||||
testEnv := testlib.IntegrationEnv(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
run func(t *testing.T)
|
||||
}{
|
||||
{
|
||||
name: "Basic test to see if the WebhookAuthenticator wakes up or not.",
|
||||
run: func(t *testing.T) {
|
||||
webhookAuthenticator := testlib.CreateTestWebhookAuthenticator(
|
||||
ctx,
|
||||
t,
|
||||
nil,
|
||||
v1alpha1.WebhookAuthenticatorPhaseReady)
|
||||
|
||||
testlib.WaitForWebhookAuthenticatorStatusConditions(
|
||||
ctx, t,
|
||||
webhookAuthenticator.Name,
|
||||
allSuccessfulWebhookAuthenticatorConditions())
|
||||
},
|
||||
}, {
|
||||
name: "valid spec with invalid CA in TLS config will result in a WebhookAuthenticator that is not ready",
|
||||
run: func(t *testing.T) {
|
||||
caBundleString := "invalid base64-encoded data"
|
||||
webhookSpec := testEnv.TestWebhook.DeepCopy()
|
||||
webhookSpec.TLS = &v1alpha1.TLSSpec{
|
||||
CertificateAuthorityData: caBundleString,
|
||||
}
|
||||
|
||||
webhookAuthenticator := testlib.CreateTestWebhookAuthenticator(
|
||||
ctx,
|
||||
t,
|
||||
webhookSpec,
|
||||
v1alpha1.WebhookAuthenticatorPhaseError)
|
||||
|
||||
testlib.WaitForWebhookAuthenticatorStatusConditions(
|
||||
ctx, t,
|
||||
webhookAuthenticator.Name,
|
||||
replaceSomeConditions(
|
||||
allSuccessfulWebhookAuthenticatorConditions(),
|
||||
[]metav1.Condition{
|
||||
{
|
||||
Type: "Ready",
|
||||
Status: "False",
|
||||
Reason: "NotReady",
|
||||
Message: "the WebhookAuthenticator is not ready: see other conditions for details",
|
||||
}, {
|
||||
Type: "AuthenticatorValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: "False",
|
||||
Reason: "InvalidTLSConfiguration",
|
||||
Message: "invalid TLS configuration: illegal base64 data at input byte 7",
|
||||
}, {
|
||||
Type: "TLSConnectionNegotiationValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
},
|
||||
},
|
||||
))
|
||||
},
|
||||
}, {
|
||||
name: "valid spec with valid CA in TLS config but does not match issuer server will result in a WebhookAuthenticator that is not ready",
|
||||
run: func(t *testing.T) {
|
||||
caBundleSomePivotalCA := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURVVENDQWptZ0F3SUJBZ0lWQUpzNStTbVRtaTJXeUI0bGJJRXBXaUs5a1RkUE1BMEdDU3FHU0liM0RRRUIKQ3dVQU1COHhDekFKQmdOVkJBWVRBbFZUTVJBd0RnWURWUVFLREFkUWFYWnZkR0ZzTUI0WERUSXdNRFV3TkRFMgpNamMxT0ZvWERUSTBNRFV3TlRFMk1qYzFPRm93SHpFTE1Ba0dBMVVFQmhNQ1ZWTXhFREFPQmdOVkJBb01CMUJwCmRtOTBZV3d3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRERZWmZvWGR4Z2NXTEMKZEJtbHB5a0tBaG9JMlBuUWtsVFNXMno1cGcwaXJjOGFRL1E3MXZzMTRZYStmdWtFTGlvOTRZYWw4R01DdVFrbApMZ3AvUEE5N1VYelhQNDBpK25iNXcwRGpwWWd2dU9KQXJXMno2MFRnWE5NSFh3VHk4ME1SZEhpUFVWZ0VZd0JpCmtkNThzdEFVS1Y1MnBQTU1reTJjNy9BcFhJNmRXR2xjalUvaFBsNmtpRzZ5dEw2REtGYjJQRWV3MmdJM3pHZ2IKOFVVbnA1V05DZDd2WjNVY0ZHNXlsZEd3aGc3cnZ4U1ZLWi9WOEhCMGJmbjlxamlrSVcxWFM4dzdpUUNlQmdQMApYZWhKZmVITlZJaTJtZlczNlVQbWpMdnVKaGpqNDIrdFBQWndvdDkzdWtlcEgvbWpHcFJEVm9wamJyWGlpTUYrCkYxdnlPNGMxQWdNQkFBR2pnWU13Z1lBd0hRWURWUjBPQkJZRUZNTWJpSXFhdVkwajRVWWphWDl0bDJzby9LQ1IKTUI4R0ExVWRJd1FZTUJhQUZNTWJpSXFhdVkwajRVWWphWDl0bDJzby9LQ1JNQjBHQTFVZEpRUVdNQlFHQ0NzRwpBUVVGQndNQ0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01BNEdBMVVkRHdFQi93UUVBd0lCCkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFYbEh4M2tIMDZwY2NDTDlEVE5qTnBCYnlVSytGd2R6T2IwWFYKcmpNaGtxdHVmdEpUUnR5T3hKZ0ZKNXhUR3pCdEtKamcrVU1pczBOV0t0VDBNWThVMU45U2c5SDl0RFpHRHBjVQpxMlVRU0Y4dXRQMVR3dnJIUzIrdzB2MUoxdHgrTEFiU0lmWmJCV0xXQ21EODUzRlVoWlFZekkvYXpFM28vd0p1CmlPUklMdUpNUk5vNlBXY3VLZmRFVkhaS1RTWnk3a25FcHNidGtsN3EwRE91eUFWdG9HVnlkb3VUR0FOdFhXK2YKczNUSTJjKzErZXg3L2RZOEJGQTFzNWFUOG5vZnU3T1RTTzdiS1kzSkRBUHZOeFQzKzVZUXJwNGR1Nmh0YUFMbAppOHNaRkhidmxpd2EzdlhxL3p1Y2JEaHEzQzBhZnAzV2ZwRGxwSlpvLy9QUUFKaTZLQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
|
||||
webhookSpec := testEnv.TestWebhook.DeepCopy()
|
||||
webhookSpec.TLS = &v1alpha1.TLSSpec{
|
||||
CertificateAuthorityData: caBundleSomePivotalCA,
|
||||
}
|
||||
|
||||
webhookAuthenticator := testlib.CreateTestWebhookAuthenticator(
|
||||
ctx,
|
||||
t,
|
||||
webhookSpec,
|
||||
v1alpha1.WebhookAuthenticatorPhaseError)
|
||||
|
||||
testlib.WaitForWebhookAuthenticatorStatusConditions(
|
||||
ctx, t,
|
||||
webhookAuthenticator.Name,
|
||||
replaceSomeConditions(
|
||||
allSuccessfulWebhookAuthenticatorConditions(),
|
||||
[]metav1.Condition{
|
||||
{
|
||||
Type: "Ready",
|
||||
Status: "False",
|
||||
Reason: "NotReady",
|
||||
Message: "the WebhookAuthenticator is not ready: see other conditions for details",
|
||||
}, {
|
||||
Type: "AuthenticatorValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "TLSConnectionNegotiationValid",
|
||||
Status: "False",
|
||||
Reason: "UnableToDialServer",
|
||||
Message: "cannot dial server: tls: failed to verify certificate: x509: certificate signed by unknown authority",
|
||||
},
|
||||
},
|
||||
))
|
||||
},
|
||||
}, {
|
||||
name: "invalid with unresponsive endpoint will result in a WebhookAuthenticator that is not ready",
|
||||
run: func(t *testing.T) {
|
||||
caBundleSomePivotalCA := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURVVENDQWptZ0F3SUJBZ0lWQUpzNStTbVRtaTJXeUI0bGJJRXBXaUs5a1RkUE1BMEdDU3FHU0liM0RRRUIKQ3dVQU1COHhDekFKQmdOVkJBWVRBbFZUTVJBd0RnWURWUVFLREFkUWFYWnZkR0ZzTUI0WERUSXdNRFV3TkRFMgpNamMxT0ZvWERUSTBNRFV3TlRFMk1qYzFPRm93SHpFTE1Ba0dBMVVFQmhNQ1ZWTXhFREFPQmdOVkJBb01CMUJwCmRtOTBZV3d3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRERZWmZvWGR4Z2NXTEMKZEJtbHB5a0tBaG9JMlBuUWtsVFNXMno1cGcwaXJjOGFRL1E3MXZzMTRZYStmdWtFTGlvOTRZYWw4R01DdVFrbApMZ3AvUEE5N1VYelhQNDBpK25iNXcwRGpwWWd2dU9KQXJXMno2MFRnWE5NSFh3VHk4ME1SZEhpUFVWZ0VZd0JpCmtkNThzdEFVS1Y1MnBQTU1reTJjNy9BcFhJNmRXR2xjalUvaFBsNmtpRzZ5dEw2REtGYjJQRWV3MmdJM3pHZ2IKOFVVbnA1V05DZDd2WjNVY0ZHNXlsZEd3aGc3cnZ4U1ZLWi9WOEhCMGJmbjlxamlrSVcxWFM4dzdpUUNlQmdQMApYZWhKZmVITlZJaTJtZlczNlVQbWpMdnVKaGpqNDIrdFBQWndvdDkzdWtlcEgvbWpHcFJEVm9wamJyWGlpTUYrCkYxdnlPNGMxQWdNQkFBR2pnWU13Z1lBd0hRWURWUjBPQkJZRUZNTWJpSXFhdVkwajRVWWphWDl0bDJzby9LQ1IKTUI4R0ExVWRJd1FZTUJhQUZNTWJpSXFhdVkwajRVWWphWDl0bDJzby9LQ1JNQjBHQTFVZEpRUVdNQlFHQ0NzRwpBUVVGQndNQ0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01BNEdBMVVkRHdFQi93UUVBd0lCCkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFYbEh4M2tIMDZwY2NDTDlEVE5qTnBCYnlVSytGd2R6T2IwWFYKcmpNaGtxdHVmdEpUUnR5T3hKZ0ZKNXhUR3pCdEtKamcrVU1pczBOV0t0VDBNWThVMU45U2c5SDl0RFpHRHBjVQpxMlVRU0Y4dXRQMVR3dnJIUzIrdzB2MUoxdHgrTEFiU0lmWmJCV0xXQ21EODUzRlVoWlFZekkvYXpFM28vd0p1CmlPUklMdUpNUk5vNlBXY3VLZmRFVkhaS1RTWnk3a25FcHNidGtsN3EwRE91eUFWdG9HVnlkb3VUR0FOdFhXK2YKczNUSTJjKzErZXg3L2RZOEJGQTFzNWFUOG5vZnU3T1RTTzdiS1kzSkRBUHZOeFQzKzVZUXJwNGR1Nmh0YUFMbAppOHNaRkhidmxpd2EzdlhxL3p1Y2JEaHEzQzBhZnAzV2ZwRGxwSlpvLy9QUUFKaTZLQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
|
||||
webhookSpec := testEnv.TestWebhook.DeepCopy()
|
||||
webhookSpec.TLS = &v1alpha1.TLSSpec{
|
||||
CertificateAuthorityData: caBundleSomePivotalCA,
|
||||
}
|
||||
webhookSpec.Endpoint = "https://127.0.0.1:443/some-fake-endpoint"
|
||||
|
||||
webhookAuthenticator := testlib.CreateTestWebhookAuthenticator(
|
||||
ctx,
|
||||
t,
|
||||
webhookSpec,
|
||||
v1alpha1.WebhookAuthenticatorPhaseError)
|
||||
|
||||
testlib.WaitForWebhookAuthenticatorStatusConditions(
|
||||
ctx, t,
|
||||
webhookAuthenticator.Name,
|
||||
replaceSomeConditions(
|
||||
allSuccessfulWebhookAuthenticatorConditions(),
|
||||
[]metav1.Condition{
|
||||
{
|
||||
Type: "Ready",
|
||||
Status: "False",
|
||||
Reason: "NotReady",
|
||||
Message: "the WebhookAuthenticator is not ready: see other conditions for details",
|
||||
}, {
|
||||
Type: "AuthenticatorValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "TLSConnectionNegotiationValid",
|
||||
Status: "False",
|
||||
Reason: "UnableToDialServer",
|
||||
Message: "cannot dial server: dial tcp 127.0.0.1:443: connect: connection refused",
|
||||
},
|
||||
},
|
||||
))
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
tt := test
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tt.run(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConciergeWebhookAuthenticatorCRDValidations_Parallel(t *testing.T) {
|
||||
env := testlib.IntegrationEnv(t)
|
||||
webhookAuthenticatorClient := testlib.NewConciergeClientset(t).AuthenticationV1alpha1().WebhookAuthenticators()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
objectMeta := testlib.ObjectMetaWithRandomName(t, "webhook-authenticator")
|
||||
tests := []struct {
|
||||
name string
|
||||
webhookAuthenticator *v1alpha1.WebhookAuthenticator
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "endpoint can not be empty string",
|
||||
webhookAuthenticator: &v1alpha1.WebhookAuthenticator{
|
||||
ObjectMeta: objectMeta,
|
||||
Spec: v1alpha1.WebhookAuthenticatorSpec{
|
||||
Endpoint: "",
|
||||
},
|
||||
},
|
||||
wantErr: `WebhookAuthenticator.authentication.concierge.` + env.APIGroupSuffix + ` "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.endpoint: Invalid value: "": spec.endpoint in body should be at least 1 chars long`,
|
||||
},
|
||||
{
|
||||
name: "endpoint must be https",
|
||||
webhookAuthenticator: &v1alpha1.WebhookAuthenticator{
|
||||
ObjectMeta: objectMeta,
|
||||
Spec: v1alpha1.WebhookAuthenticatorSpec{
|
||||
Endpoint: "http://www.example.com",
|
||||
},
|
||||
},
|
||||
wantErr: `WebhookAuthenticator.authentication.concierge.` + env.APIGroupSuffix + ` "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.endpoint: Invalid value: "http://www.example.com": spec.endpoint in body should match '^https://'`,
|
||||
},
|
||||
{
|
||||
name: "minimum valid authenticator",
|
||||
webhookAuthenticator: &v1alpha1.WebhookAuthenticator{
|
||||
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "webhook"),
|
||||
Spec: v1alpha1.WebhookAuthenticatorSpec{
|
||||
Endpoint: "https://localhost/webhook-isnt-actually-here",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid authenticator can have empty TLS block",
|
||||
webhookAuthenticator: &v1alpha1.WebhookAuthenticator{
|
||||
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "webhook"),
|
||||
Spec: v1alpha1.WebhookAuthenticatorSpec{
|
||||
Endpoint: "https://localhost/webhook-isnt-actually-here",
|
||||
TLS: &v1alpha1.TLSSpec{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid authenticator can have empty TLS CertificateAuthorityData",
|
||||
webhookAuthenticator: &v1alpha1.WebhookAuthenticator{
|
||||
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "jwtauthenticator"),
|
||||
Spec: v1alpha1.WebhookAuthenticatorSpec{
|
||||
Endpoint: "https://localhost/webhook-isnt-actually-here",
|
||||
TLS: &v1alpha1.TLSSpec{
|
||||
CertificateAuthorityData: "pretend-this-is-a-certificate",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
tt := test
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, createErr := webhookAuthenticatorClient.Create(ctx, tt.webhookAuthenticator, metav1.CreateOptions{})
|
||||
|
||||
t.Cleanup(func() {
|
||||
// delete if it exists
|
||||
delErr := webhookAuthenticatorClient.Delete(ctx, tt.webhookAuthenticator.Name, metav1.DeleteOptions{})
|
||||
if !errors.IsNotFound(delErr) {
|
||||
require.NoError(t, delErr)
|
||||
}
|
||||
})
|
||||
|
||||
if tt.wantErr != "" {
|
||||
wantErr := tt.wantErr
|
||||
require.EqualError(t, createErr, wantErr)
|
||||
} else {
|
||||
require.NoError(t, createErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func allSuccessfulWebhookAuthenticatorConditions() []metav1.Condition {
|
||||
return []metav1.Condition{{
|
||||
Type: "AuthenticatorValid",
|
||||
Status: "True",
|
||||
Reason: "Success",
|
||||
Message: "authenticator initialized",
|
||||
}, {
|
||||
Type: "EndpointURLValid",
|
||||
Status: "True",
|
||||
Reason: "Success",
|
||||
Message: "endpoint is a valid URL",
|
||||
}, {
|
||||
Type: "Ready",
|
||||
Status: "True",
|
||||
Reason: "Success",
|
||||
Message: "the WebhookAuthenticator is ready",
|
||||
}, {
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: "True",
|
||||
Reason: "Success",
|
||||
Message: "successfully parsed specified CA bundle",
|
||||
}, {
|
||||
Type: "TLSConnectionNegotiationValid",
|
||||
Status: "True",
|
||||
Reason: "Success",
|
||||
Message: "tls verified",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -438,7 +438,7 @@ func TestGetAPIResourceList(t *testing.T) { //nolint:gocyclo // each t.Run is pr
|
||||
}
|
||||
|
||||
// manually update this value whenever you add additional fields to an API resource and then run the generator
|
||||
totalExpectedAPIFields := 260
|
||||
totalExpectedAPIFields := 261
|
||||
|
||||
// Because we are parsing text from `kubectl explain` and because the format of that text can change
|
||||
// over time, make a rudimentary assertion that this test exercised the whole tree of all fields of all
|
||||
|
||||
@@ -36,7 +36,6 @@ import (
|
||||
supervisorclientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned"
|
||||
"go.pinniped.dev/internal/groupsuffix"
|
||||
"go.pinniped.dev/internal/kubeclient"
|
||||
|
||||
// Import to initialize client auth plugins - the kubeconfig that we use for
|
||||
// testing may use gcloud, az, oidc, etc.
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||
@@ -171,7 +170,11 @@ func NewKubeclient(t *testing.T, config *rest.Config) *kubeclient.Client {
|
||||
// CreateTestWebhookAuthenticator creates and returns a test WebhookAuthenticator in $PINNIPED_TEST_CONCIERGE_NAMESPACE, which will be
|
||||
// automatically deleted at the end of the current test's lifetime. It returns a corev1.TypedLocalObjectReference which
|
||||
// describes the test webhook authenticator within the test namespace.
|
||||
func CreateTestWebhookAuthenticator(ctx context.Context, t *testing.T) corev1.TypedLocalObjectReference {
|
||||
func CreateTestWebhookAuthenticator(
|
||||
ctx context.Context,
|
||||
t *testing.T,
|
||||
webhookSpec *auth1alpha1.WebhookAuthenticatorSpec,
|
||||
expectedStatus auth1alpha1.WebhookAuthenticatorPhase) corev1.TypedLocalObjectReference {
|
||||
t.Helper()
|
||||
testEnv := IntegrationEnv(t)
|
||||
|
||||
@@ -181,9 +184,13 @@ func CreateTestWebhookAuthenticator(ctx context.Context, t *testing.T) corev1.Ty
|
||||
createContext, cancel := context.WithTimeout(ctx, time.Minute)
|
||||
defer cancel()
|
||||
|
||||
if webhookSpec == nil {
|
||||
webhookSpec = &testEnv.TestWebhook
|
||||
}
|
||||
|
||||
webhook, err := webhooks.Create(createContext, &auth1alpha1.WebhookAuthenticator{
|
||||
ObjectMeta: testObjectMeta(t, "webhook"),
|
||||
Spec: testEnv.TestWebhook,
|
||||
Spec: *webhookSpec,
|
||||
}, metav1.CreateOptions{})
|
||||
require.NoError(t, err, "could not create test WebhookAuthenticator")
|
||||
t.Logf("created test WebhookAuthenticator %s", webhook.Name)
|
||||
@@ -197,6 +204,10 @@ func CreateTestWebhookAuthenticator(ctx context.Context, t *testing.T) corev1.Ty
|
||||
require.NoErrorf(t, err, "could not cleanup test WebhookAuthenticator %s/%s", webhook.Namespace, webhook.Name)
|
||||
})
|
||||
|
||||
if expectedStatus != "" {
|
||||
WaitForWebhookAuthenticatorStatusPhase(ctx, t, webhook.Name, expectedStatus)
|
||||
}
|
||||
|
||||
return corev1.TypedLocalObjectReference{
|
||||
APIGroup: &auth1alpha1.SchemeGroupVersion.Group,
|
||||
Kind: "WebhookAuthenticator",
|
||||
@@ -204,6 +215,47 @@ func CreateTestWebhookAuthenticator(ctx context.Context, t *testing.T) corev1.Ty
|
||||
}
|
||||
}
|
||||
|
||||
func WaitForWebhookAuthenticatorStatusPhase(
|
||||
ctx context.Context,
|
||||
t *testing.T,
|
||||
webhookName string,
|
||||
expectPhase auth1alpha1.WebhookAuthenticatorPhase) {
|
||||
t.Helper()
|
||||
webhookAuthenticatorClientSet := NewConciergeClientset(t).AuthenticationV1alpha1().WebhookAuthenticators()
|
||||
|
||||
RequireEventuallyf(t, func(requireEventually *require.Assertions) {
|
||||
webhookA, err := webhookAuthenticatorClientSet.Get(ctx, webhookName, metav1.GetOptions{})
|
||||
requireEventually.NoError(err)
|
||||
requireEventually.Equalf(expectPhase, webhookA.Status.Phase, "actual status conditions were: %#v", webhookA.Status.Conditions)
|
||||
}, 60*time.Second, 1*time.Second, "expected the WebhookAuthenticator to have status %q", expectPhase)
|
||||
}
|
||||
|
||||
func WaitForWebhookAuthenticatorStatusConditions(ctx context.Context, t *testing.T, webhookName string, expectConditions []metav1.Condition) {
|
||||
t.Helper()
|
||||
webhookClient := NewConciergeClientset(t).AuthenticationV1alpha1().WebhookAuthenticators()
|
||||
RequireEventuallyf(t, func(requireEventually *require.Assertions) {
|
||||
fd, err := webhookClient.Get(ctx, webhookName, metav1.GetOptions{})
|
||||
requireEventually.NoError(err)
|
||||
|
||||
requireEventually.Lenf(fd.Status.Conditions, len(expectConditions),
|
||||
"wanted status conditions: %#v", expectConditions)
|
||||
|
||||
for i, wantCond := range expectConditions {
|
||||
actualCond := fd.Status.Conditions[i]
|
||||
|
||||
// This is a cheat to avoid needing to make equality assertions on these fields.
|
||||
requireEventually.NotZero(actualCond.LastTransitionTime)
|
||||
wantCond.LastTransitionTime = actualCond.LastTransitionTime
|
||||
requireEventually.NotZero(actualCond.ObservedGeneration)
|
||||
wantCond.ObservedGeneration = actualCond.ObservedGeneration
|
||||
|
||||
requireEventually.Equalf(wantCond, actualCond,
|
||||
"wanted status conditions: %#v\nactual status conditions were: %#v\nnot equal at index %d",
|
||||
expectConditions, fd.Status.Conditions, i)
|
||||
}
|
||||
}, 60*time.Second, 1*time.Second, "wanted WebhookAuthenticator conditions")
|
||||
}
|
||||
|
||||
// CreateTestJWTAuthenticatorForCLIUpstream creates and returns a test JWTAuthenticator which will be automatically
|
||||
// deleted at the end of the current test's lifetime.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user