Add integration test to verify that the impersonation proxy will use an external TLS serving cert

This commit is contained in:
Joshua Casey 2023-07-24 09:37:45 -05:00
parent ee75a63057
commit 959f18b67b
2 changed files with 81 additions and 2 deletions

View File

@ -267,7 +267,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
const clusterIPServiceName = "some-cluster-ip-resource-name" const clusterIPServiceName = "some-cluster-ip-resource-name"
const internallyGeneratedTLSServingCertSecretName = "some-tls-secret-name" //nolint:gosec // this is not a credential const internallyGeneratedTLSServingCertSecretName = "some-tls-secret-name" //nolint:gosec // this is not a credential
const internallyGeneratedTLSServingCASecretName = "some-ca-secret-name" const internallyGeneratedTLSServingCASecretName = "some-ca-secret-name"
const mTLSClientCertCASecretName = "some-ca-signer-name" const mTLSClientCertCASecretName = "some-ca-signer-name" //nolint:gosec // this is not a credential
const localhostIP = "127.0.0.1" const localhostIP = "127.0.0.1"
const httpsPort = ":443" const httpsPort = ":443"
const fakeServerResponseBody = "hello, world!" const fakeServerResponseBody = "hello, world!"
@ -1346,7 +1346,6 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
}) })
}) })
}) })
}) })
when("the configuration is auto mode", func() { when("the configuration is auto mode", func() {

View File

@ -37,6 +37,7 @@ import (
certificatesv1 "k8s.io/api/certificates/v1" certificatesv1 "k8s.io/api/certificates/v1"
certificatesv1beta1 "k8s.io/api/certificates/v1beta1" certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/equality"
k8serrors "k8s.io/apimachinery/pkg/api/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors"
@ -65,6 +66,7 @@ import (
identityv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/identity/v1alpha1" identityv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/identity/v1alpha1"
loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1" loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1"
pinnipedconciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned" pinnipedconciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
"go.pinniped.dev/internal/certauthority"
"go.pinniped.dev/internal/crypto/ptls" "go.pinniped.dev/internal/crypto/ptls"
"go.pinniped.dev/internal/httputil/roundtripper" "go.pinniped.dev/internal/httputil/roundtripper"
"go.pinniped.dev/internal/kubeclient" "go.pinniped.dev/internal/kubeclient"
@ -1776,6 +1778,84 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
) )
}) })
t.Run("using externally provided TLS serving cert", func(t *testing.T) {
var externallyProvidedCA *certauthority.CA
externallyProvidedCA, err = certauthority.New("Impersonation Proxy Integration Test CA", 1*time.Hour)
require.NoError(t, err)
var externallyProvidedTLSServingCertPEM, externallyProvidedTLSServingKeyPEM []byte
externallyProvidedTLSServingCertPEM, externallyProvidedTLSServingKeyPEM, err = externallyProvidedCA.IssueServerCertPEM([]string{proxyServiceEndpoint}, nil, 1*time.Hour)
require.NoError(t, err)
externallyProvidedTLSServingCertSecretName := "external-tls-cert-secret-name" //nolint:gosec // this is not a credential
externallyProvidedTLSServingCertSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: externallyProvidedTLSServingCertSecretName,
Namespace: env.ConciergeNamespace,
},
Type: corev1.SecretTypeTLS,
Data: map[string][]byte{
v1.TLSCertKey: externallyProvidedTLSServingCertPEM,
v1.TLSPrivateKeyKey: externallyProvidedTLSServingKeyPEM,
},
}
_, err = adminClient.CoreV1().Secrets(env.ConciergeNamespace).Create(ctx, externallyProvidedTLSServingCertSecret, metav1.CreateOptions{})
require.NoError(t, err)
t.Cleanup(func() {
err := adminClient.CoreV1().Secrets(env.ConciergeNamespace).Delete(ctx, externallyProvidedTLSServingCertSecretName, metav1.DeleteOptions{})
require.NoError(t, err)
})
_, originalInternallyGeneratedCAPEM := performImpersonatorDiscoveryURL(ctx, t, env, adminConciergeClient)
updateCredentialIssuer(ctx, t, env, adminConciergeClient, conciergev1alpha.CredentialIssuerSpec{
ImpersonationProxy: &conciergev1alpha.ImpersonationProxySpec{
Mode: conciergev1alpha.ImpersonationProxyModeEnabled,
ExternalEndpoint: proxyServiceEndpoint,
Service: conciergev1alpha.ImpersonationProxyServiceSpec{
Type: conciergev1alpha.ImpersonationProxyServiceTypeClusterIP,
},
TLS: &conciergev1alpha.ImpersonationProxyTLSSpec{
CertificateAuthorityData: base64.StdEncoding.EncodeToString(externallyProvidedCA.Bundle()),
SecretName: externallyProvidedTLSServingCertSecretName,
},
},
})
// Wait for the CredentialIssuer's impersonation proxy frontend strategy to be updated with the right CA bundle
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
_, impersonationProxyCACertPEM = performImpersonatorDiscoveryURL(ctx, t, env, adminConciergeClient)
return bytes.Equal(impersonationProxyCACertPEM, externallyProvidedCA.Bundle()), nil
}, 2*time.Minute, 500*time.Millisecond)
// Do a login via performImpersonatorDiscovery
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
_, newImpersonationProxyCACertPEM := performImpersonatorDiscovery(ctx, t, env, adminClient, adminConciergeClient, refreshCredential)
return bytes.Equal(newImpersonationProxyCACertPEM, externallyProvidedCA.Bundle()), err
}, 2*time.Minute, 500*time.Millisecond)
// Remove the TLS block from the CredentialIssuer, which should revert the ImpersonationProxy to using an
// internally generated TLS serving cert derived from the original CA.
updateCredentialIssuer(ctx, t, env, adminConciergeClient, conciergev1alpha.CredentialIssuerSpec{
ImpersonationProxy: &conciergev1alpha.ImpersonationProxySpec{
Mode: conciergev1alpha.ImpersonationProxyModeEnabled,
ExternalEndpoint: proxyServiceEndpoint,
Service: conciergev1alpha.ImpersonationProxyServiceSpec{
Type: conciergev1alpha.ImpersonationProxyServiceTypeClusterIP,
},
},
})
// Wait for the CredentialIssuer's impersonation proxy frontend strategy to be updated to the original CA bundle
testlib.RequireEventuallyWithoutError(t, func() (bool, error) {
_, impersonationProxyCACertPEM = performImpersonatorDiscoveryURL(ctx, t, env, adminConciergeClient)
return bytes.Equal(impersonationProxyCACertPEM, originalInternallyGeneratedCAPEM), nil
}, 2*time.Minute, 500*time.Millisecond)
})
t.Run("manually disabling the impersonation proxy feature", func(t *testing.T) { t.Run("manually disabling the impersonation proxy feature", func(t *testing.T) {
// Update configuration to force the proxy to disabled mode // Update configuration to force the proxy to disabled mode
updateCredentialIssuer(ctx, t, env, adminConciergeClient, conciergev1alpha.CredentialIssuerSpec{ updateCredentialIssuer(ctx, t, env, adminConciergeClient, conciergev1alpha.CredentialIssuerSpec{