Skip to content

Commit

Permalink
Allow the integration tests to set an IP address for the Supervisor i…
Browse files Browse the repository at this point in the history
…ssuer

Co-authored-by: Ryan Richard <richardry@vmware.com>
  • Loading branch information
joshuatcasey and cfryanr committed Aug 30, 2024
1 parent c0bab69 commit 557dee0
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 31 deletions.
54 changes: 44 additions & 10 deletions test/integration/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"errors"
"fmt"
"io"
"net"
"net/url"
"os"
"os/exec"
Expand Down Expand Up @@ -71,6 +72,11 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
pinnipedExe := testlib.PinnipedCLIPath(t)

issuerURL, _ := env.InferSupervisorIssuerURL(t)
isIssuerAnIPAddress := net.ParseIP(issuerURL.Hostname()) != nil
var issuerIPs []net.IP
if isIssuerAnIPAddress {
issuerIPs = append(issuerIPs, net.ParseIP(issuerURL.Hostname()))
}

// Generate a CA bundle with which to serve this provider.
t.Logf("generating test CA")
Expand All @@ -85,24 +91,52 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
// Use the CA to issue a TLS server cert.
t.Logf("issuing test certificate")
federationDomainTLSServingCert, err := federationDomainSelfSignedCA.IssueServerCert(
[]string{issuerURL.Hostname()}, nil, 1*time.Hour)
[]string{issuerURL.Hostname()}, issuerIPs, 1*time.Hour)
require.NoError(t, err)
federationDomainTLSServingCertPEM, federationDomainTLSServingCertKeyPEM, err := certauthority.ToPEM(federationDomainTLSServingCert)
require.NoError(t, err)

// Write the serving cert to a secret.
federationDomainTLSServingCertSecret := testlib.CreateTestSecret(t,
supervisorClient := testlib.NewSupervisorClientset(t)
temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(
topSetupCtx,
t,
env.SupervisorNamespace,
"oidc-provider-tls",
corev1.SecretTypeTLS,
map[string]string{"tls.crt": string(federationDomainTLSServingCertPEM), "tls.key": string(federationDomainTLSServingCertKeyPEM)},
env.DefaultTLSCertSecretName(),
supervisorClient,
testlib.NewKubernetesClientset(t),
)

// Create the downstream FederationDomain and expect it to go into the success status condition.
var tlsSpecForFederationDomain *supervisorconfigv1alpha1.FederationDomainTLSSpec
if isIssuerAnIPAddress {
testlib.CreateTestSecretWithName(
t,
env.SupervisorNamespace,
env.DefaultTLSCertSecretName(),
corev1.SecretTypeTLS,
map[string]string{
"tls.crt": string(federationDomainTLSServingCertPEM),
"tls.key": string(federationDomainTLSServingCertKeyPEM),
},
)
} else {
// Write the serving cert to a secret.
federationDomainTLSServingCertSecret := testlib.CreateTestSecret(t,
env.SupervisorNamespace,
"oidc-provider-tls",
corev1.SecretTypeTLS,
map[string]string{
"tls.crt": string(federationDomainTLSServingCertPEM),
"tls.key": string(federationDomainTLSServingCertKeyPEM),
},
)
tlsSpecForFederationDomain = &supervisorconfigv1alpha1.FederationDomainTLSSpec{SecretName: federationDomainTLSServingCertSecret.Name}
}

// Create the downstream FederationDomain.
federationDomain := testlib.CreateTestFederationDomain(topSetupCtx, t,
supervisorconfigv1alpha1.FederationDomainSpec{
Issuer: issuerURL.String(),
TLS: &supervisorconfigv1alpha1.FederationDomainTLSSpec{SecretName: federationDomainTLSServingCertSecret.Name},
TLS: tlsSpecForFederationDomain,
},
supervisorconfigv1alpha1.FederationDomainPhaseError, // in phase error until there is an IDP created
)
Expand Down Expand Up @@ -1416,7 +1450,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady)

// Update the FederationDomain to use the two IDPs.
federationDomainsClient := testlib.NewSupervisorClientset(t).ConfigV1alpha1().FederationDomains(env.SupervisorNamespace)
federationDomainsClient := supervisorClient.ConfigV1alpha1().FederationDomains(env.SupervisorNamespace)
gotFederationDomain, err := federationDomainsClient.Get(testCtx, federationDomain.Name, metav1.GetOptions{})
require.NoError(t, err)

Expand Down Expand Up @@ -1736,7 +1770,7 @@ func TestE2EFullIntegration_Browser(t *testing.T) {
testlib.WaitForJWTAuthenticatorStatusPhase(testCtx, t, authenticator.Name, authenticationv1alpha1.JWTAuthenticatorPhaseReady)

// Update the FederationDomain to use the two IDPs.
federationDomainsClient := testlib.NewSupervisorClientset(t).ConfigV1alpha1().FederationDomains(env.SupervisorNamespace)
federationDomainsClient := supervisorClient.ConfigV1alpha1().FederationDomains(env.SupervisorNamespace)
gotFederationDomain, err := federationDomainsClient.Get(testCtx, federationDomain.Name, metav1.GetOptions{})
require.NoError(t, err)

Expand Down
14 changes: 5 additions & 9 deletions test/integration/supervisor_discovery_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ func TestSupervisorOIDCDiscovery_Disruptive(t *testing.T) {
ips = append(ips, ip)
}

temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, defaultTLSCertSecretName(env), client, testlib.NewKubernetesClientset(t))
defaultCA := createTLSCertificateSecret(ctx, t, ns, httpsAddress, ips, defaultTLSCertSecretName(env), kubeClient)
temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, env.DefaultTLSCertSecretName(), client, testlib.NewKubernetesClientset(t))
defaultCA := createTLSCertificateSecret(ctx, t, ns, httpsAddress, ips, env.DefaultTLSCertSecretName(), kubeClient)

tests := []struct {
Name string
Expand Down Expand Up @@ -182,7 +182,7 @@ func TestSupervisorTLSTerminationWithSNI_Disruptive(t *testing.T) {
Client: idpv1alpha1.OIDCClient{SecretName: "this-will-not-exist-but-does-not-matter"},
}, idpv1alpha1.PhaseError)

temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, defaultTLSCertSecretName(env), pinnipedClient, kubeClient)
temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, env.DefaultTLSCertSecretName(), pinnipedClient, kubeClient)

scheme := "https"
address := env.SupervisorHTTPSAddress // hostname and port for direct access to the supervisor's port 8443
Expand Down Expand Up @@ -268,7 +268,7 @@ func TestSupervisorTLSTerminationWithDefaultCerts_Disruptive(t *testing.T) {
Client: idpv1alpha1.OIDCClient{SecretName: "this-will-not-exist-but-does-not-matter"},
}, idpv1alpha1.PhaseError)

temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, defaultTLSCertSecretName(env), pinnipedClient, kubeClient)
temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, env.DefaultTLSCertSecretName(), pinnipedClient, kubeClient)

scheme := "https"
address := env.SupervisorHTTPSAddress // hostname and port for direct access to the supervisor's port 8443
Expand Down Expand Up @@ -297,7 +297,7 @@ func TestSupervisorTLSTerminationWithDefaultCerts_Disruptive(t *testing.T) {
requireEndpointHasBootstrapTLSErrorBecauseCertificatesAreNotReady(t, issuerUsingIPAddress)

// Create a Secret at the special name which represents the default TLS cert.
defaultCA := createTLSCertificateSecret(ctx, t, ns, "cert-hostname-doesnt-matter", []net.IP{ips[0]}, defaultTLSCertSecretName(env), kubeClient)
defaultCA := createTLSCertificateSecret(ctx, t, ns, "cert-hostname-doesnt-matter", []net.IP{ips[0]}, env.DefaultTLSCertSecretName(), kubeClient)

// Now that the Secret exists, we should be able to access the endpoints by IP address using the CA.
_ = requireStandardDiscoveryEndpointsAreWorking(t, scheme, ipWithPort, string(defaultCA.Bundle()), issuerUsingIPAddress, nil)
Expand All @@ -323,10 +323,6 @@ func TestSupervisorTLSTerminationWithDefaultCerts_Disruptive(t *testing.T) {
_ = requireStandardDiscoveryEndpointsAreWorking(t, scheme, ipWithPort, string(defaultCA.Bundle()), issuerUsingIPAddress, nil)
}

func defaultTLSCertSecretName(env *testlib.TestEnv) string {
return env.SupervisorAppName + "-default-tls-certificate"
}

func createTLSCertificateSecret(ctx context.Context, t *testing.T, ns string, hostname string, ips []net.IP, secretName string, kubeClient kubernetes.Interface) *certauthority.CA {
// Create a CA.
ca, err := certauthority.New("Acme Corp", 1000*time.Hour)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestSupervisorFederationDomainStatus_Disruptive(t *testing.T) {
t.Cleanup(cancel)

temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t,
env.SupervisorNamespace, defaultTLSCertSecretName(env), supervisorClient, testlib.NewKubernetesClientset(t))
env.SupervisorNamespace, env.DefaultTLSCertSecretName(), supervisorClient, testlib.NewKubernetesClientset(t))

tests := []struct {
name string
Expand Down
4 changes: 2 additions & 2 deletions test/integration/supervisor_healthz_test.go
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -27,7 +27,7 @@ func TestSupervisorHealthzBootstrap_Disruptive(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()

temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, defaultTLSCertSecretName(env), pinnipedClient, kubeClient)
temporarilyRemoveAllFederationDomainsAndDefaultTLSCertSecret(ctx, t, ns, env.DefaultTLSCertSecretName(), pinnipedClient, kubeClient)

httpClient := &http.Client{
Transport: &http.Transport{
Expand Down
27 changes: 21 additions & 6 deletions test/testlib/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,17 +474,13 @@ func CreateTestConfigMap(t *testing.T, namespace string, baseName string, string
return created
}

func CreateTestSecret(t *testing.T, namespace string, baseName string, secretType corev1.SecretType, stringData map[string]string) *corev1.Secret {
func createTestSecret(t *testing.T, namespace string, secret *corev1.Secret) *corev1.Secret {

Check warning on line 477 in test/testlib/client.go

View check run for this annotation

Codecov / codecov/patch

test/testlib/client.go#L477

Added line #L477 was not covered by tests
t.Helper()
client := NewKubernetesClientset(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

created, err := client.CoreV1().Secrets(namespace).Create(ctx, &corev1.Secret{
ObjectMeta: TestObjectMeta(t, baseName),
Type: secretType,
StringData: stringData,
}, metav1.CreateOptions{})
created, err := client.CoreV1().Secrets(namespace).Create(ctx, secret, metav1.CreateOptions{})

Check warning on line 483 in test/testlib/client.go

View check run for this annotation

Codecov / codecov/patch

test/testlib/client.go#L483

Added line #L483 was not covered by tests
require.NoError(t, err)

t.Cleanup(func() {
Expand All @@ -496,6 +492,25 @@ func CreateTestSecret(t *testing.T, namespace string, baseName string, secretTyp
return created
}

func CreateTestSecret(t *testing.T, namespace string, baseName string, secretType corev1.SecretType, stringData map[string]string) *corev1.Secret {
return createTestSecret(t, namespace, &corev1.Secret{
ObjectMeta: TestObjectMeta(t, baseName),
Type: secretType,
StringData: stringData,
})

Check warning on line 500 in test/testlib/client.go

View check run for this annotation

Codecov / codecov/patch

test/testlib/client.go#L495-L500

Added lines #L495 - L500 were not covered by tests
}

func CreateTestSecretWithName(t *testing.T, namespace string, name string, secretType corev1.SecretType, stringData map[string]string) *corev1.Secret {
secret := &corev1.Secret{
ObjectMeta: TestObjectMeta(t, ""),
Type: secretType,
StringData: stringData,
}
secret.GenerateName = ""
secret.Name = name
return createTestSecret(t, namespace, secret)

Check warning on line 511 in test/testlib/client.go

View check run for this annotation

Codecov / codecov/patch

test/testlib/client.go#L503-L511

Added lines #L503 - L511 were not covered by tests
}

func CreateTestSecretBytes(t *testing.T, namespace string, baseName string, secretType corev1.SecretType, data map[string][]byte) *corev1.Secret {
t.Helper()
client := NewKubernetesClientset(t)
Expand Down
7 changes: 4 additions & 3 deletions test/testlib/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ func (e *TestEnv) InferSupervisorIssuerURL(t *testing.T) (*url.URL, string) {
return issuerURL, issuerAsString
}

func (e *TestEnv) DefaultTLSCertSecretName() string {
return e.SupervisorAppName + "-default-tls-certificate"

Check warning on line 102 in test/testlib/env.go

View check run for this annotation

Codecov / codecov/patch

test/testlib/env.go#L101-L102

Added lines #L101 - L102 were not covered by tests
}

type TestLDAPUpstream struct {
Host string `json:"host"`
Domain string `json:"domain"`
Expand Down Expand Up @@ -262,9 +266,6 @@ func loadEnvVars(t *testing.T, result *TestEnv) {

result.SupervisorHTTPSIngressAddress = os.Getenv("PINNIPED_TEST_SUPERVISOR_HTTPS_INGRESS_ADDRESS")
result.SupervisorHTTPSAddress = needEnv(t, "PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS")
require.NotRegexp(t, "^[0-9]", result.SupervisorHTTPSAddress,
"PINNIPED_TEST_SUPERVISOR_HTTPS_ADDRESS must be a hostname with an optional port and cannot be an IP address",
)
result.SupervisorHTTPSIngressCABundle = base64Decoded(t, os.Getenv("PINNIPED_TEST_SUPERVISOR_HTTPS_INGRESS_CA_BUNDLE"))

conciergeCustomLabelsYAML := needEnv(t, "PINNIPED_TEST_CONCIERGE_CUSTOM_LABELS")
Expand Down

0 comments on commit 557dee0

Please sign in to comment.