mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-08-15 19:56:12 +00:00
Populate internal GitHub IDP Config from CRD
This commit is contained in:
@@ -21,6 +21,8 @@ import (
|
||||
"go.pinniped.dev/test/testlib"
|
||||
)
|
||||
|
||||
const generateNamePrefix = "integration-test-github-idp-"
|
||||
|
||||
func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
adminClient := testlib.NewKubernetesClientset(t)
|
||||
|
||||
@@ -32,7 +34,7 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
|
||||
ns, err := namespaceClient.Create(ctx, &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "test-github-idp-",
|
||||
GenerateName: generateNamePrefix,
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
@@ -45,10 +47,10 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
inputSpec idpv1alpha1.GitHubIdentityProviderSpec
|
||||
expectedSpec idpv1alpha1.GitHubIdentityProviderSpec
|
||||
usesCELValidation bool
|
||||
expectedErr string
|
||||
inputSpec idpv1alpha1.GitHubIdentityProviderSpec
|
||||
wantSpec idpv1alpha1.GitHubIdentityProviderSpec
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "all fields set",
|
||||
@@ -78,7 +80,7 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
SecretName: "any-name-goes-here",
|
||||
},
|
||||
},
|
||||
expectedSpec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
wantSpec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
GitHubAPI: idpv1alpha1.GitHubAPIConfig{
|
||||
Host: ptr.To("some-host.example.com"),
|
||||
TLS: &idpv1alpha1.TLSSpec{
|
||||
@@ -115,7 +117,7 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
SecretName: "name-of-a-secret",
|
||||
},
|
||||
},
|
||||
expectedSpec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
wantSpec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
GitHubAPI: idpv1alpha1.GitHubAPIConfig{
|
||||
Host: ptr.To("github.com"),
|
||||
},
|
||||
@@ -137,6 +139,7 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
name: fmt.Sprintf(
|
||||
"cannot set AllowedOrganizationsPolicy=%s and set AllowedOrganizations",
|
||||
string(idpv1alpha1.GitHubAllowedAuthOrganizationsPolicyAllGitHubUsers)),
|
||||
usesCELValidation: true,
|
||||
inputSpec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
AllowAuthentication: idpv1alpha1.GitHubAllowAuthenticationSpec{
|
||||
Organizations: idpv1alpha1.GitHubOrganizationsSpec{
|
||||
@@ -150,11 +153,11 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
SecretName: "name-of-a-secret",
|
||||
},
|
||||
},
|
||||
usesCELValidation: true,
|
||||
expectedErr: "spec.allowAuthentication.organizations.policy must be 'OnlyUsersFromAllowedOrganizations' when spec.allowAuthentication.organizations.allowed has organizations listed",
|
||||
wantErr: "spec.allowAuthentication.organizations.policy must be 'OnlyUsersFromAllowedOrganizations' when spec.allowAuthentication.organizations.allowed has organizations listed",
|
||||
},
|
||||
{
|
||||
name: fmt.Sprintf("spec.allowAuthentication.organizations.policy must be '%s' when spec.allowAuthentication.organizations.allowed is empty (nil)", string(idpv1alpha1.GitHubAllowedAuthOrganizationsPolicyAllGitHubUsers)),
|
||||
name: fmt.Sprintf("spec.allowAuthentication.organizations.policy must be '%s' when spec.allowAuthentication.organizations.allowed is empty (nil)", string(idpv1alpha1.GitHubAllowedAuthOrganizationsPolicyAllGitHubUsers)),
|
||||
usesCELValidation: true,
|
||||
inputSpec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
AllowAuthentication: idpv1alpha1.GitHubAllowAuthenticationSpec{
|
||||
Organizations: idpv1alpha1.GitHubOrganizationsSpec{
|
||||
@@ -165,11 +168,11 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
SecretName: "name-of-a-secret",
|
||||
},
|
||||
},
|
||||
usesCELValidation: true,
|
||||
expectedErr: "spec.allowAuthentication.organizations.policy must be 'AllGitHubUsers' when spec.allowAuthentication.organizations.allowed is empty",
|
||||
wantErr: "spec.allowAuthentication.organizations.policy must be 'AllGitHubUsers' when spec.allowAuthentication.organizations.allowed is empty",
|
||||
},
|
||||
{
|
||||
name: fmt.Sprintf("spec.allowAuthentication.organizations.policy must be '%s' when spec.allowAuthentication.organizations.allowed is empty", string(idpv1alpha1.GitHubAllowedAuthOrganizationsPolicyAllGitHubUsers)),
|
||||
name: fmt.Sprintf("spec.allowAuthentication.organizations.policy must be '%s' when spec.allowAuthentication.organizations.allowed is empty", string(idpv1alpha1.GitHubAllowedAuthOrganizationsPolicyAllGitHubUsers)),
|
||||
usesCELValidation: true,
|
||||
inputSpec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
AllowAuthentication: idpv1alpha1.GitHubAllowAuthenticationSpec{
|
||||
Organizations: idpv1alpha1.GitHubOrganizationsSpec{
|
||||
@@ -181,13 +184,12 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
SecretName: "name-of-a-secret",
|
||||
},
|
||||
},
|
||||
usesCELValidation: true,
|
||||
expectedErr: "spec.allowAuthentication.organizations.policy must be 'AllGitHubUsers' when spec.allowAuthentication.organizations.allowed is empty",
|
||||
wantErr: "spec.allowAuthentication.organizations.policy must be 'AllGitHubUsers' when spec.allowAuthentication.organizations.allowed is empty",
|
||||
},
|
||||
{
|
||||
name: "spec.client.secretName in body should be at least 1 chars long",
|
||||
inputSpec: idpv1alpha1.GitHubIdentityProviderSpec{},
|
||||
expectedErr: "spec.client.secretName in body should be at least 1 chars long",
|
||||
name: "spec.client.secretName in body should be at least 1 chars long",
|
||||
inputSpec: idpv1alpha1.GitHubIdentityProviderSpec{},
|
||||
wantErr: "spec.client.secretName in body should be at least 1 chars long",
|
||||
},
|
||||
{
|
||||
name: "spec.githubAPI.host in body should be at least 1 chars long",
|
||||
@@ -204,7 +206,7 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
SecretName: "name-of-a-secret",
|
||||
},
|
||||
},
|
||||
expectedErr: "spec.githubAPI.host in body should be at least 1 chars long",
|
||||
wantErr: "spec.githubAPI.host in body should be at least 1 chars long",
|
||||
},
|
||||
{
|
||||
name: "duplicates not permitted in spec.allowAuthentication.organizations.allowed",
|
||||
@@ -222,7 +224,7 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
SecretName: "name-of-a-secret",
|
||||
},
|
||||
},
|
||||
expectedErr: `spec.allowAuthentication.organizations.allowed[1]: Duplicate value: "org1"`,
|
||||
wantErr: `spec.allowAuthentication.organizations.allowed[1]: Duplicate value: "org1"`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@@ -236,22 +238,370 @@ func TestGitHubIDPStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
|
||||
input := &idpv1alpha1.GitHubIdentityProvider{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "integration-test-",
|
||||
GenerateName: generateNamePrefix,
|
||||
},
|
||||
Spec: tt.inputSpec,
|
||||
}
|
||||
|
||||
outputGitHubIDP, err := gitHubIDPClient.Create(ctx, input, metav1.CreateOptions{})
|
||||
if tt.expectedErr == "" {
|
||||
if tt.wantErr == "" {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.expectedSpec, outputGitHubIDP.Spec)
|
||||
require.Equal(t, tt.wantSpec, outputGitHubIDP.Spec)
|
||||
} else {
|
||||
require.ErrorContains(t, err, tt.expectedErr)
|
||||
require.ErrorContains(t, err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitHubIDPPhaseAndConditions_Parallel(t *testing.T) {
|
||||
// These operations must be performed in the Supervisor's namespace so that the controller can find GitHubIdentityProvider
|
||||
supervisorNamespace := testlib.IntegrationEnv(t).SupervisorNamespace
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
kubernetesClient := testlib.NewKubernetesClientset(t)
|
||||
secretsClient := kubernetesClient.CoreV1().Secrets(supervisorNamespace)
|
||||
gitHubIDPClient := testlib.NewSupervisorClientset(t).IDPV1alpha1().GitHubIdentityProviders(supervisorNamespace)
|
||||
|
||||
happySecretName := generateNamePrefix + testlib.RandHex(t, 16)
|
||||
invalidSecretName := generateNamePrefix + testlib.RandHex(t, 16)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
secrets []*corev1.Secret // Secrets will be created first, and the first secret found will be listed as the configured GitHub Client secret
|
||||
idps []*idpv1alpha1.GitHubIdentityProvider
|
||||
wantPhase idpv1alpha1.GitHubIdentityProviderPhase
|
||||
wantConditions []*metav1.Condition
|
||||
}{
|
||||
{
|
||||
name: "Happy Path",
|
||||
secrets: []*corev1.Secret{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: happySecretName,
|
||||
},
|
||||
Type: "secrets.pinniped.dev/github-client",
|
||||
Data: map[string][]byte{
|
||||
"clientID": []byte("foo"),
|
||||
"clientSecret": []byte("bar"),
|
||||
},
|
||||
},
|
||||
},
|
||||
idps: []*idpv1alpha1.GitHubIdentityProvider{
|
||||
{
|
||||
Spec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
GitHubAPI: idpv1alpha1.GitHubAPIConfig{
|
||||
Host: ptr.To("github.com"),
|
||||
},
|
||||
AllowAuthentication: idpv1alpha1.GitHubAllowAuthenticationSpec{
|
||||
Organizations: idpv1alpha1.GitHubOrganizationsSpec{
|
||||
Policy: ptr.To(idpv1alpha1.GitHubAllowedAuthOrganizationsPolicyAllGitHubUsers),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantPhase: idpv1alpha1.GitHubPhaseReady,
|
||||
wantConditions: []*metav1.Condition{
|
||||
{
|
||||
Type: "ClientCredentialsObtained",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: fmt.Sprintf("clientID and clientSecret have been read from spec.client.SecretName (%q)", happySecretName),
|
||||
},
|
||||
{
|
||||
Type: "GitHubConnectionValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.githubAPI.host ("github.com:443") is reachable and TLS verification succeeds`,
|
||||
},
|
||||
{
|
||||
Type: "HostValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.githubAPI.host ("github.com") is valid`,
|
||||
},
|
||||
{
|
||||
Type: "OrganizationsPolicyValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.allowAuthentication.organizations.policy ("AllGitHubUsers") is valid`,
|
||||
},
|
||||
{
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: "spec.githubAPI.tls.certificateAuthorityData is valid",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Invalid Client Secret",
|
||||
secrets: []*corev1.Secret{
|
||||
{
|
||||
Type: "secrets.pinniped.dev/github-client",
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: invalidSecretName,
|
||||
},
|
||||
},
|
||||
},
|
||||
idps: []*idpv1alpha1.GitHubIdentityProvider{
|
||||
{
|
||||
Spec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
GitHubAPI: idpv1alpha1.GitHubAPIConfig{
|
||||
Host: ptr.To("github.com"),
|
||||
},
|
||||
AllowAuthentication: idpv1alpha1.GitHubAllowAuthenticationSpec{
|
||||
Organizations: idpv1alpha1.GitHubOrganizationsSpec{
|
||||
Policy: ptr.To(idpv1alpha1.GitHubAllowedAuthOrganizationsPolicyAllGitHubUsers),
|
||||
},
|
||||
},
|
||||
Client: idpv1alpha1.GitHubClientSpec{
|
||||
SecretName: invalidSecretName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantPhase: idpv1alpha1.GitHubPhaseError,
|
||||
wantConditions: []*metav1.Condition{
|
||||
{
|
||||
Type: "ClientCredentialsObtained",
|
||||
Status: metav1.ConditionFalse,
|
||||
Reason: "SecretNotFound",
|
||||
Message: fmt.Sprintf(`missing key "clientID": secret from spec.client.SecretName (%q) must be found in namespace %q with type "secrets.pinniped.dev/github-client" and keys "clientID" and "clientSecret"`,
|
||||
invalidSecretName,
|
||||
supervisorNamespace),
|
||||
},
|
||||
{
|
||||
Type: "GitHubConnectionValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.githubAPI.host ("github.com:443") is reachable and TLS verification succeeds`,
|
||||
},
|
||||
{
|
||||
Type: "HostValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.githubAPI.host ("github.com") is valid`,
|
||||
},
|
||||
{
|
||||
Type: "OrganizationsPolicyValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.allowAuthentication.organizations.policy ("AllGitHubUsers") is valid`,
|
||||
},
|
||||
{
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.githubAPI.tls.certificateAuthorityData is valid`,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var secretName string
|
||||
for _, secret := range tt.secrets {
|
||||
secret.GenerateName = generateNamePrefix
|
||||
|
||||
created, err := secretsClient.Create(ctx, secret, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
err := secretsClient.Delete(ctx, created.Name, metav1.DeleteOptions{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
if secretName == "" {
|
||||
secretName = created.Name
|
||||
}
|
||||
}
|
||||
|
||||
for _, idp := range tt.idps {
|
||||
idp.Name = ""
|
||||
idp.GenerateName = generateNamePrefix
|
||||
idp.Spec.Client.SecretName = secretName
|
||||
|
||||
created, err := gitHubIDPClient.Create(ctx, idp, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
err := gitHubIDPClient.Delete(ctx, created.Name, metav1.DeleteOptions{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
testlib.WaitForGitHubIDPPhase(ctx, t, gitHubIDPClient, created.Name, tt.wantPhase)
|
||||
testlib.WaitForGitHubIdentityProviderStatusConditions(ctx, t, gitHubIDPClient, created.Name, tt.wantConditions)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitHubIDPInWrongNamespace_Parallel(t *testing.T) {
|
||||
// The GitHubIdentityProvider must be in the same namespace as the controller
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
kubernetesClient := testlib.NewKubernetesClientset(t)
|
||||
|
||||
namespaceClient := kubernetesClient.CoreV1().Namespaces()
|
||||
otherNamespace, err := namespaceClient.Create(ctx, &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: generateNamePrefix,
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, namespaceClient.Delete(ctx, otherNamespace.Name, metav1.DeleteOptions{}))
|
||||
})
|
||||
|
||||
gitHubIDPClient := testlib.NewSupervisorClientset(t).IDPV1alpha1().GitHubIdentityProviders(otherNamespace.Name)
|
||||
|
||||
idp := &idpv1alpha1.GitHubIdentityProvider{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: generateNamePrefix,
|
||||
Namespace: otherNamespace.Name,
|
||||
},
|
||||
Spec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
GitHubAPI: idpv1alpha1.GitHubAPIConfig{
|
||||
Host: ptr.To("github.com"),
|
||||
},
|
||||
AllowAuthentication: idpv1alpha1.GitHubAllowAuthenticationSpec{
|
||||
Organizations: idpv1alpha1.GitHubOrganizationsSpec{
|
||||
Policy: ptr.To(idpv1alpha1.GitHubAllowedAuthOrganizationsPolicyAllGitHubUsers),
|
||||
},
|
||||
},
|
||||
Client: idpv1alpha1.GitHubClientSpec{
|
||||
SecretName: "does-not-matter",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
createdIDP, err := gitHubIDPClient.Create(ctx, idp, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
err := gitHubIDPClient.Delete(ctx, createdIDP.Name, metav1.DeleteOptions{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
// We require that there's never an error
|
||||
// ... and that the status phase is never anything but Pending
|
||||
// ... and that there are no status conditions
|
||||
require.Never(t, func() bool {
|
||||
idp, err := gitHubIDPClient.Get(ctx, createdIDP.Name, metav1.GetOptions{})
|
||||
return err != nil && idp.Status.Phase != idpv1alpha1.GitHubPhasePending && len(idp.Status.Conditions) > 0
|
||||
}, 2*time.Minute, 10*time.Second)
|
||||
}
|
||||
|
||||
func TestGitHubIDPSecretInOtherNamespace_Parallel(t *testing.T) {
|
||||
// The GitHubIdentityProvider must be in the same namespace as the controller
|
||||
supervisorNamespace := testlib.IntegrationEnv(t).SupervisorNamespace
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
kubernetesClient := testlib.NewKubernetesClientset(t)
|
||||
gitHubIDPClient := testlib.NewSupervisorClientset(t).IDPV1alpha1().GitHubIdentityProviders(supervisorNamespace)
|
||||
|
||||
namespaceClient := kubernetesClient.CoreV1().Namespaces()
|
||||
otherNamespace, err := namespaceClient.Create(ctx, &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: generateNamePrefix,
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, namespaceClient.Delete(ctx, otherNamespace.Name, metav1.DeleteOptions{}))
|
||||
})
|
||||
|
||||
secretsClient := kubernetesClient.CoreV1().Secrets(otherNamespace.Name)
|
||||
|
||||
secret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: generateNamePrefix,
|
||||
Namespace: otherNamespace.Name,
|
||||
},
|
||||
Type: "secrets.pinniped.dev/github-client",
|
||||
Data: map[string][]byte{
|
||||
"clientID": []byte("foo"),
|
||||
"clientSecret": []byte("bar"),
|
||||
},
|
||||
}
|
||||
|
||||
// This secret will be cleaned up when its namespace is deleted
|
||||
createdSecret, err := secretsClient.Create(ctx, secret, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
idp := &idpv1alpha1.GitHubIdentityProvider{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: generateNamePrefix,
|
||||
Namespace: supervisorNamespace,
|
||||
},
|
||||
Spec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
GitHubAPI: idpv1alpha1.GitHubAPIConfig{
|
||||
Host: ptr.To("github.com"),
|
||||
},
|
||||
AllowAuthentication: idpv1alpha1.GitHubAllowAuthenticationSpec{
|
||||
Organizations: idpv1alpha1.GitHubOrganizationsSpec{
|
||||
Policy: ptr.To(idpv1alpha1.GitHubAllowedAuthOrganizationsPolicyAllGitHubUsers),
|
||||
},
|
||||
},
|
||||
Client: idpv1alpha1.GitHubClientSpec{
|
||||
SecretName: createdSecret.Name,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
created, err := gitHubIDPClient.Create(ctx, idp, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
err := gitHubIDPClient.Delete(ctx, created.Name, metav1.DeleteOptions{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
testlib.WaitForGitHubIDPPhase(ctx, t, gitHubIDPClient, created.Name, idpv1alpha1.GitHubPhaseError)
|
||||
|
||||
testlib.WaitForGitHubIdentityProviderStatusConditions(ctx, t, gitHubIDPClient, created.Name, []*metav1.Condition{
|
||||
{
|
||||
Type: "ClientCredentialsObtained",
|
||||
Status: metav1.ConditionFalse,
|
||||
Reason: "SecretNotFound",
|
||||
Message: fmt.Sprintf(`secret %q not found: secret from spec.client.SecretName (%q) must be found in namespace %q with type "secrets.pinniped.dev/github-client" and keys "clientID" and "clientSecret"`,
|
||||
idp.Spec.Client.SecretName,
|
||||
idp.Spec.Client.SecretName,
|
||||
supervisorNamespace),
|
||||
},
|
||||
{
|
||||
Type: "GitHubConnectionValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.githubAPI.host ("github.com:443") is reachable and TLS verification succeeds`,
|
||||
},
|
||||
{
|
||||
Type: "HostValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.githubAPI.host ("github.com") is valid`,
|
||||
},
|
||||
{
|
||||
Type: "OrganizationsPolicyValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: `spec.allowAuthentication.organizations.policy ("AllGitHubUsers") is valid`,
|
||||
},
|
||||
{
|
||||
Type: "TLSConfigurationValid",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "Success",
|
||||
Message: "spec.githubAPI.tls.certificateAuthorityData is valid",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestGitHubIDPTooManyOrganizationsStaticValidationOnCreate_Parallel(t *testing.T) {
|
||||
adminClient := testlib.NewKubernetesClientset(t)
|
||||
|
||||
@@ -262,7 +612,7 @@ func TestGitHubIDPTooManyOrganizationsStaticValidationOnCreate_Parallel(t *testi
|
||||
|
||||
ns, err := namespaceClient.Create(ctx, &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "test-github-idp-",
|
||||
GenerateName: generateNamePrefix,
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
@@ -275,7 +625,7 @@ func TestGitHubIDPTooManyOrganizationsStaticValidationOnCreate_Parallel(t *testi
|
||||
|
||||
input := &idpv1alpha1.GitHubIdentityProvider{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "integration-test-",
|
||||
GenerateName: generateNamePrefix,
|
||||
},
|
||||
Spec: idpv1alpha1.GitHubIdentityProviderSpec{
|
||||
AllowAuthentication: idpv1alpha1.GitHubAllowAuthenticationSpec{
|
||||
@@ -298,10 +648,10 @@ func TestGitHubIDPTooManyOrganizationsStaticValidationOnCreate_Parallel(t *testi
|
||||
|
||||
_, err = gitHubIDPClient.Create(ctx, input, metav1.CreateOptions{})
|
||||
|
||||
expectedErr := "spec.allowAuthentication.organizations.allowed: Invalid value: 100: spec.allowAuthentication.organizations.allowed in body should have at most 64 items"
|
||||
wantErr := "spec.allowAuthentication.organizations.allowed: Invalid value: 100: spec.allowAuthentication.organizations.allowed in body should have at most 64 items"
|
||||
if testutil.KubeServerMinorVersionAtLeastInclusive(t, adminClient.Discovery(), 24) {
|
||||
expectedErr = "spec.allowAuthentication.organizations.allowed: Too many: 100: must have at most 64 items"
|
||||
wantErr = "spec.allowAuthentication.organizations.allowed: Too many: 100: must have at most 64 items"
|
||||
}
|
||||
|
||||
require.ErrorContains(t, err, expectedErr)
|
||||
require.ErrorContains(t, err, wantErr)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
idpv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
|
||||
conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
|
||||
supervisorclientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned"
|
||||
alpha1 "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1"
|
||||
"go.pinniped.dev/internal/groupsuffix"
|
||||
"go.pinniped.dev/internal/kubeclient"
|
||||
|
||||
@@ -836,6 +837,59 @@ func WaitForUserToHaveAccess(t *testing.T, user string, groups []string, shouldH
|
||||
}, time.Minute, 500*time.Millisecond)
|
||||
}
|
||||
|
||||
func WaitForGitHubIDPPhase(
|
||||
ctx context.Context,
|
||||
t *testing.T,
|
||||
client alpha1.GitHubIdentityProviderInterface,
|
||||
gitHubIDPName string,
|
||||
expectPhase idpv1alpha1.GitHubIdentityProviderPhase,
|
||||
) {
|
||||
t.Helper()
|
||||
|
||||
RequireEventuallyf(t, func(requireEventually *require.Assertions) {
|
||||
idp, err := client.Get(ctx, gitHubIDPName, metav1.GetOptions{})
|
||||
requireEventually.NoError(err)
|
||||
requireEventually.Equalf(expectPhase, idp.Status.Phase, "actual status conditions were: %#v", idp.Status.Conditions)
|
||||
}, 60*time.Second, 1*time.Second, "expected the GitHubIDP to have status %q", expectPhase)
|
||||
}
|
||||
|
||||
func WaitForGitHubIdentityProviderStatusConditions(
|
||||
ctx context.Context,
|
||||
t *testing.T,
|
||||
client alpha1.GitHubIdentityProviderInterface,
|
||||
gitHubIDPName string,
|
||||
expectConditions []*metav1.Condition,
|
||||
) {
|
||||
t.Helper()
|
||||
|
||||
RequireEventuallyf(t, func(requireEventually *require.Assertions) {
|
||||
idp, err := client.Get(ctx, gitHubIDPName, metav1.GetOptions{})
|
||||
requireEventually.NoError(err)
|
||||
|
||||
actualConditions := make([]*metav1.Condition, len(idp.Status.Conditions))
|
||||
for i, c := range idp.Status.Conditions {
|
||||
actualConditions[i] = c.DeepCopy()
|
||||
}
|
||||
|
||||
requireEventually.Lenf(actualConditions, len(expectConditions),
|
||||
"wanted status conditions: %#v", expectConditions)
|
||||
|
||||
for i, wantCond := range expectConditions {
|
||||
actualCond := actualConditions[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, &actualConditions, i)
|
||||
}
|
||||
}, 60*time.Second, 1*time.Second, "wanted conditions for GitHubIdentityProvider %q", gitHubIDPName)
|
||||
}
|
||||
|
||||
func testObjectMeta(t *testing.T, baseName string) metav1.ObjectMeta {
|
||||
return metav1.ObjectMeta{
|
||||
GenerateName: fmt.Sprintf("test-%s-", baseName),
|
||||
|
||||
Reference in New Issue
Block a user