mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-01-03 11:45:45 +00:00
Update jwk authenticator status integration tests
This commit is contained in:
committed by
Ryan Richard
parent
42acf8dcce
commit
868ff9ed2b
@@ -29,7 +29,7 @@ func TestConciergeJWTAuthenticatorStatus_Disruptive(t *testing.T) {
|
||||
run func(t *testing.T)
|
||||
}{
|
||||
{
|
||||
name: "valid spec with no errors and all good status conditions and phase",
|
||||
name: "valid spec with no errors and all good status conditions and phase will result in a jwt authenticator that is ready",
|
||||
run: func(t *testing.T) {
|
||||
jwtAuthenticator := testlib.CreateTestJWTAuthenticator(ctx, t, v1alpha1.JWTAuthenticatorSpec{
|
||||
Issuer: env.SupervisorUpstreamOIDC.Issuer,
|
||||
@@ -44,8 +44,116 @@ func TestConciergeJWTAuthenticatorStatus_Disruptive(t *testing.T) {
|
||||
jwtAuthenticator.Name,
|
||||
allSuccessfulJWTAuthenticatorConditions())
|
||||
},
|
||||
}, {
|
||||
name: "invalid with bad issuer",
|
||||
},
|
||||
{
|
||||
name: "valid spec with invalid CA in TLS config will result in a jwt authenticator that is not ready",
|
||||
run: func(t *testing.T) {
|
||||
jwtAuthenticator := testlib.CreateTestJWTAuthenticator(ctx, t, v1alpha1.JWTAuthenticatorSpec{
|
||||
Issuer: env.SupervisorUpstreamOIDC.Issuer,
|
||||
Audience: "some-fake-audience",
|
||||
TLS: &v1alpha1.TLSSpec{
|
||||
CertificateAuthorityData: "invalid base64-encoded data",
|
||||
},
|
||||
}, v1alpha1.JWTAuthenticatorPhaseError)
|
||||
|
||||
testlib.WaitForJWTAuthenticatorStatusConditions(
|
||||
ctx, t,
|
||||
jwtAuthenticator.Name,
|
||||
replaceSomeConditions(
|
||||
allSuccessfulJWTAuthenticatorConditions(),
|
||||
[]metav1.Condition{
|
||||
{
|
||||
Type: "Ready",
|
||||
Status: "False",
|
||||
Reason: "NotReady",
|
||||
Message: "the JWTAuthenticator is not ready: see other conditions for details",
|
||||
}, {
|
||||
Type: "AuthenticatorValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "JWKSURLValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "JWKSFetchValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "DiscoveryURLValid",
|
||||
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",
|
||||
},
|
||||
},
|
||||
))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid spec with valid CA in TLS config but does not match issuer server will result in a jwt authenticator that is not ready",
|
||||
run: func(t *testing.T) {
|
||||
jwtAuthenticator := testlib.CreateTestJWTAuthenticator(ctx, t, v1alpha1.JWTAuthenticatorSpec{
|
||||
Issuer: env.SupervisorUpstreamOIDC.Issuer,
|
||||
Audience: "some-fake-audience",
|
||||
// Some random generated cert
|
||||
// Issuer: C=US, O=Pivotal
|
||||
// No SAN provided
|
||||
TLS: &v1alpha1.TLSSpec{
|
||||
CertificateAuthorityData: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURVVENDQWptZ0F3SUJBZ0lWQUpzNStTbVRtaTJXeUI0bGJJRXBXaUs5a1RkUE1BMEdDU3FHU0liM0RRRUIKQ3dVQU1COHhDekFKQmdOVkJBWVRBbFZUTVJBd0RnWURWUVFLREFkUWFYWnZkR0ZzTUI0WERUSXdNRFV3TkRFMgpNamMxT0ZvWERUSTBNRFV3TlRFMk1qYzFPRm93SHpFTE1Ba0dBMVVFQmhNQ1ZWTXhFREFPQmdOVkJBb01CMUJwCmRtOTBZV3d3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRERZWmZvWGR4Z2NXTEMKZEJtbHB5a0tBaG9JMlBuUWtsVFNXMno1cGcwaXJjOGFRL1E3MXZzMTRZYStmdWtFTGlvOTRZYWw4R01DdVFrbApMZ3AvUEE5N1VYelhQNDBpK25iNXcwRGpwWWd2dU9KQXJXMno2MFRnWE5NSFh3VHk4ME1SZEhpUFVWZ0VZd0JpCmtkNThzdEFVS1Y1MnBQTU1reTJjNy9BcFhJNmRXR2xjalUvaFBsNmtpRzZ5dEw2REtGYjJQRWV3MmdJM3pHZ2IKOFVVbnA1V05DZDd2WjNVY0ZHNXlsZEd3aGc3cnZ4U1ZLWi9WOEhCMGJmbjlxamlrSVcxWFM4dzdpUUNlQmdQMApYZWhKZmVITlZJaTJtZlczNlVQbWpMdnVKaGpqNDIrdFBQWndvdDkzdWtlcEgvbWpHcFJEVm9wamJyWGlpTUYrCkYxdnlPNGMxQWdNQkFBR2pnWU13Z1lBd0hRWURWUjBPQkJZRUZNTWJpSXFhdVkwajRVWWphWDl0bDJzby9LQ1IKTUI4R0ExVWRJd1FZTUJhQUZNTWJpSXFhdVkwajRVWWphWDl0bDJzby9LQ1JNQjBHQTFVZEpRUVdNQlFHQ0NzRwpBUVVGQndNQ0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01BNEdBMVVkRHdFQi93UUVBd0lCCkJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFYbEh4M2tIMDZwY2NDTDlEVE5qTnBCYnlVSytGd2R6T2IwWFYKcmpNaGtxdHVmdEpUUnR5T3hKZ0ZKNXhUR3pCdEtKamcrVU1pczBOV0t0VDBNWThVMU45U2c5SDl0RFpHRHBjVQpxMlVRU0Y4dXRQMVR3dnJIUzIrdzB2MUoxdHgrTEFiU0lmWmJCV0xXQ21EODUzRlVoWlFZekkvYXpFM28vd0p1CmlPUklMdUpNUk5vNlBXY3VLZmRFVkhaS1RTWnk3a25FcHNidGtsN3EwRE91eUFWdG9HVnlkb3VUR0FOdFhXK2YKczNUSTJjKzErZXg3L2RZOEJGQTFzNWFUOG5vZnU3T1RTTzdiS1kzSkRBUHZOeFQzKzVZUXJwNGR1Nmh0YUFMbAppOHNaRkhidmxpd2EzdlhxL3p1Y2JEaHEzQzBhZnAzV2ZwRGxwSlpvLy9QUUFKaTZLQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
||||
},
|
||||
}, v1alpha1.JWTAuthenticatorPhaseError)
|
||||
|
||||
testlib.WaitForJWTAuthenticatorStatusConditions(
|
||||
ctx, t,
|
||||
jwtAuthenticator.Name,
|
||||
replaceSomeConditions(
|
||||
allSuccessfulJWTAuthenticatorConditions(),
|
||||
[]metav1.Condition{
|
||||
{
|
||||
Type: "Ready",
|
||||
Status: "False",
|
||||
Reason: "NotReady",
|
||||
Message: "the JWTAuthenticator is not ready: see other conditions for details",
|
||||
}, {
|
||||
Type: "AuthenticatorValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "JWKSURLValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "JWKSFetchValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "DiscoveryURLValid",
|
||||
Status: "False",
|
||||
Reason: "InvalidDiscoveryProbe",
|
||||
Message: `could not perform oidc discovery on provider issuer: Get "` + env.SupervisorUpstreamOIDC.Issuer + `/.well-known/openid-configuration": tls: failed to verify certificate: x509: certificate signed by unknown authority`,
|
||||
}, {
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: "True",
|
||||
Reason: "Success",
|
||||
Message: "successfully parsed specified CA bundle",
|
||||
},
|
||||
},
|
||||
))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid with bad issuer will result in a jwt authenticator that is not ready",
|
||||
run: func(t *testing.T) {
|
||||
fakeIssuerURL := "https://127.0.0.1:443/some-fake-issuer"
|
||||
jwtAuthenticator := testlib.CreateTestJWTAuthenticator(ctx, t, v1alpha1.JWTAuthenticatorSpec{
|
||||
@@ -71,12 +179,17 @@ func TestConciergeJWTAuthenticatorStatus_Disruptive(t *testing.T) {
|
||||
Type: "AuthenticatorValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; other issues present",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "JWKSURLValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; other issues present",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "JWKSFetchValid",
|
||||
Status: "Unknown",
|
||||
Reason: "UnableToValidate",
|
||||
Message: "unable to validate; see other conditions for details",
|
||||
}, {
|
||||
Type: "DiscoveryURLValid",
|
||||
Status: "False",
|
||||
@@ -91,12 +204,14 @@ func TestConciergeJWTAuthenticatorStatus_Disruptive(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
tt := test
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tt.run(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConciergeJWTAuthenticatorCRDValidations_Parallel(t *testing.T) {
|
||||
env := testlib.IntegrationEnv(t)
|
||||
jwtAuthenticatorClient := testlib.NewConciergeClientset(t).AuthenticationV1alpha1().JWTAuthenticators()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
@@ -107,9 +222,6 @@ func TestConciergeJWTAuthenticatorCRDValidations_Parallel(t *testing.T) {
|
||||
name string
|
||||
jwtAuthenticator *v1alpha1.JWTAuthenticator
|
||||
wantErr string
|
||||
// some tests change the environment (api group suffix pinniped.dev->walrus.tld) so
|
||||
// we need to be able to compare against several error strings
|
||||
wantOneOfErr []string
|
||||
}{
|
||||
{
|
||||
name: "issuer can not be empty string",
|
||||
@@ -120,12 +232,8 @@ func TestConciergeJWTAuthenticatorCRDValidations_Parallel(t *testing.T) {
|
||||
Audience: "fake-audience",
|
||||
},
|
||||
},
|
||||
wantOneOfErr: []string{
|
||||
`JWTAuthenticator.authentication.concierge.pinniped.dev "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`,
|
||||
`JWTAuthenticator.authentication.concierge.walrus.tld "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`,
|
||||
},
|
||||
wantErr: `JWTAuthenticator.authentication.concierge.` + env.APIGroupSuffix + ` "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.issuer: Invalid value: "": spec.issuer in body should be at least 1 chars long`,
|
||||
},
|
||||
{
|
||||
name: "audience can not be empty string",
|
||||
@@ -136,12 +244,8 @@ func TestConciergeJWTAuthenticatorCRDValidations_Parallel(t *testing.T) {
|
||||
Audience: "",
|
||||
},
|
||||
},
|
||||
wantOneOfErr: []string{
|
||||
`JWTAuthenticator.authentication.concierge.pinniped.dev "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.audience: Invalid value: "": spec.audience in body should be at least 1 chars long`,
|
||||
`JWTAuthenticator.authentication.concierge.walrus.tld "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.audience: Invalid value: "": spec.audience in body should be at least 1 chars long`,
|
||||
},
|
||||
wantErr: `JWTAuthenticator.authentication.concierge.` + env.APIGroupSuffix + ` "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.audience: Invalid value: "": spec.audience in body should be at least 1 chars long`,
|
||||
},
|
||||
{
|
||||
name: "issuer must be https",
|
||||
@@ -152,40 +256,36 @@ func TestConciergeJWTAuthenticatorCRDValidations_Parallel(t *testing.T) {
|
||||
Audience: "foo",
|
||||
},
|
||||
},
|
||||
wantOneOfErr: []string{
|
||||
`JWTAuthenticator.authentication.concierge.pinniped.dev "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.issuer: Invalid value: "http://www.example.com": spec.issuer in body should match '^https://'`,
|
||||
`JWTAuthenticator.authentication.concierge.walrus.tld "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.issuer: Invalid value: "http://www.example.com": spec.issuer in body should match '^https://'`,
|
||||
},
|
||||
wantErr: `JWTAuthenticator.authentication.concierge.` + env.APIGroupSuffix + ` "` + objectMeta.Name + `" is invalid: ` +
|
||||
`spec.issuer: Invalid value: "http://www.example.com": spec.issuer in body should match '^https://'`,
|
||||
},
|
||||
{
|
||||
name: "minimum valid authenticator",
|
||||
jwtAuthenticator: &v1alpha1.JWTAuthenticator{
|
||||
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "jwtauthenticator"),
|
||||
Spec: v1alpha1.JWTAuthenticatorSpec{
|
||||
Issuer: "https://www.example.com",
|
||||
Issuer: env.CLIUpstreamOIDC.Issuer,
|
||||
Audience: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "minimum valid authenticator can have empty claims block",
|
||||
name: "valid authenticator can have empty claims block",
|
||||
jwtAuthenticator: &v1alpha1.JWTAuthenticator{
|
||||
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "jwtauthenticator"),
|
||||
Spec: v1alpha1.JWTAuthenticatorSpec{
|
||||
Issuer: "https://www.example.com",
|
||||
Issuer: env.CLIUpstreamOIDC.Issuer,
|
||||
Audience: "foo",
|
||||
Claims: v1alpha1.JWTTokenClaims{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "minimum valid authenticator can have empty group claim and empty username claim",
|
||||
name: "valid authenticator can have empty group claim and empty username claim",
|
||||
jwtAuthenticator: &v1alpha1.JWTAuthenticator{
|
||||
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "jwtauthenticator"),
|
||||
Spec: v1alpha1.JWTAuthenticatorSpec{
|
||||
Issuer: "https://www.example.com",
|
||||
Issuer: env.CLIUpstreamOIDC.Issuer,
|
||||
Audience: "foo",
|
||||
Claims: v1alpha1.JWTTokenClaims{
|
||||
Groups: "",
|
||||
@@ -195,11 +295,11 @@ func TestConciergeJWTAuthenticatorCRDValidations_Parallel(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "minimum valid authenticator can have empty TLS block",
|
||||
name: "valid authenticator can have empty TLS block",
|
||||
jwtAuthenticator: &v1alpha1.JWTAuthenticator{
|
||||
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "jwtauthenticator"),
|
||||
Spec: v1alpha1.JWTAuthenticatorSpec{
|
||||
Issuer: "https://www.example.com",
|
||||
Issuer: env.CLIUpstreamOIDC.Issuer,
|
||||
Audience: "foo",
|
||||
Claims: v1alpha1.JWTTokenClaims{
|
||||
Groups: "",
|
||||
@@ -210,11 +310,11 @@ func TestConciergeJWTAuthenticatorCRDValidations_Parallel(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "minimum valid authenticator can have empty TLS CertificateAuthorityData",
|
||||
name: "valid authenticator can have empty TLS CertificateAuthorityData",
|
||||
jwtAuthenticator: &v1alpha1.JWTAuthenticator{
|
||||
ObjectMeta: testlib.ObjectMetaWithRandomName(t, "jwtauthenticator"),
|
||||
Spec: v1alpha1.JWTAuthenticatorSpec{
|
||||
Issuer: "https://www.example.com",
|
||||
Issuer: env.CLIUpstreamOIDC.Issuer,
|
||||
Audience: "foo",
|
||||
Claims: v1alpha1.JWTTokenClaims{
|
||||
Groups: "",
|
||||
@@ -241,22 +341,13 @@ func TestConciergeJWTAuthenticatorCRDValidations_Parallel(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
if tt.wantErr != "" && tt.wantOneOfErr != nil {
|
||||
require.NoError(t, fmt.Errorf("test '%s' should not use both tt.wantErr and tt.wantOneOfErr", tt.name))
|
||||
}
|
||||
|
||||
if tt.wantErr == "" && tt.wantOneOfErr == nil {
|
||||
require.NoError(t, createErr)
|
||||
}
|
||||
|
||||
if tt.wantErr != "" {
|
||||
wantErr := tt.wantErr
|
||||
require.EqualError(t, createErr, wantErr)
|
||||
} else {
|
||||
require.NoError(t, createErr)
|
||||
}
|
||||
if tt.wantOneOfErr != nil {
|
||||
wantOneOfErr := tt.wantOneOfErr
|
||||
require.Contains(t, wantOneOfErr, createErr.Error())
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -278,7 +369,11 @@ func allSuccessfulJWTAuthenticatorConditions() []metav1.Condition {
|
||||
Reason: "Success",
|
||||
Message: "issuer is a valid URL",
|
||||
}, {
|
||||
|
||||
Type: "JWKSFetchValid",
|
||||
Status: "True",
|
||||
Reason: "Success",
|
||||
Message: "successfully fetched jwks",
|
||||
}, {
|
||||
Type: "JWKSURLValid",
|
||||
Status: "True",
|
||||
Reason: "Success",
|
||||
@@ -292,6 +387,6 @@ func allSuccessfulJWTAuthenticatorConditions() []metav1.Condition {
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: "True",
|
||||
Reason: "Success",
|
||||
Message: "valid TLS configuration",
|
||||
Message: "successfully parsed specified CA bundle",
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -111,7 +111,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
|
||||
)
|
||||
|
||||
// Create a JWTAuthenticator that will validate the tokens from the downstream issuer.
|
||||
// if the FederationDomain is not Ready, the JWTAuthenticator cannot be ready, either.
|
||||
// If the FederationDomain is not Ready, the JWTAuthenticator cannot be ready, either.
|
||||
clusterAudience := "test-cluster-" + testlib.RandHex(t, 8)
|
||||
authenticator := testlib.CreateTestJWTAuthenticator(topSetupCtx, t, authv1alpha.JWTAuthenticatorSpec{
|
||||
Issuer: federationDomain.Spec.Issuer,
|
||||
|
||||
@@ -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 testlib
|
||||
@@ -205,8 +205,7 @@ func CreateTestWebhookAuthenticator(ctx context.Context, t *testing.T) corev1.Ty
|
||||
}
|
||||
|
||||
// CreateTestJWTAuthenticatorForCLIUpstream creates and returns a test JWTAuthenticator which will be automatically
|
||||
// deleted at the end of the current test's lifetime. It returns a corev1.TypedLocalObjectReference which describes
|
||||
// the test JWT authenticator within the test namespace.
|
||||
// deleted at the end of the current test's lifetime.
|
||||
//
|
||||
// CreateTestJWTAuthenticatorForCLIUpstream gets the OIDC issuer info from IntegrationEnv().CLIUpstreamOIDC.
|
||||
func CreateTestJWTAuthenticatorForCLIUpstream(ctx context.Context, t *testing.T) *auth1alpha1.JWTAuthenticator {
|
||||
@@ -232,8 +231,7 @@ func CreateTestJWTAuthenticatorForCLIUpstream(ctx context.Context, t *testing.T)
|
||||
}
|
||||
|
||||
// CreateTestJWTAuthenticator creates and returns a test JWTAuthenticator which will be automatically deleted
|
||||
// at the end of the current test's lifetime. It returns a corev1.TypedLocalObjectReference which describes the test JWT
|
||||
// authenticator within the test namespace.
|
||||
// at the end of the current test's lifetime.
|
||||
func CreateTestJWTAuthenticator(
|
||||
ctx context.Context,
|
||||
t *testing.T,
|
||||
|
||||
Reference in New Issue
Block a user