From a75c2194bcea677bb1204a9e404b4c4cc82d69d9 Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Tue, 2 Mar 2021 09:31:24 -0800 Subject: [PATCH] Read the names of the impersonation-related resources from the config They were previously temporarily hardcoded. Now they are set at deploy time via the static ConfigMap in deployment.yaml --- deploy/concierge/deployment.yaml | 4 + internal/config/concierge/config.go | 33 +++-- internal/config/concierge/config_test.go | 140 ++++++++++++++++-- internal/config/concierge/types.go | 10 +- .../controllermanager/prepare_controllers.go | 14 +- .../concierge_impersonation_proxy_test.go | 71 +++++---- 6 files changed, 211 insertions(+), 61 deletions(-) diff --git a/deploy/concierge/deployment.yaml b/deploy/concierge/deployment.yaml index 8e3b67f7..41119243 100644 --- a/deploy/concierge/deployment.yaml +++ b/deploy/concierge/deployment.yaml @@ -42,6 +42,10 @@ data: servingCertificateSecret: (@= defaultResourceNameWithSuffix("api-tls-serving-certificate") @) credentialIssuer: (@= defaultResourceNameWithSuffix("config") @) apiService: (@= defaultResourceNameWithSuffix("api") @) + impersonationConfigMap: (@= defaultResourceNameWithSuffix("impersonation-proxy-config") @) + impersonationLoadBalancerService: (@= defaultResourceNameWithSuffix("impersonation-proxy-load-balancer") @) + impersonationTLSCertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-tls-serving-certificate") @) + impersonationCACertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-ca-certificate") @) labels: (@= json.encode(labels()).rstrip() @) kubeCertAgent: namePrefix: (@= defaultResourceNameWithSuffix("kube-cert-agent-") @) diff --git a/internal/config/concierge/config.go b/internal/config/concierge/config.go index 88d8fe06..b6720cea 100644 --- a/internal/config/concierge/config.go +++ b/internal/config/concierge/config.go @@ -96,17 +96,28 @@ func maybeSetKubeCertAgentDefaults(cfg *KubeCertAgentSpec) { func validateNames(names *NamesConfigSpec) error { missingNames := []string{} if names == nil { - missingNames = append(missingNames, "servingCertificateSecret", "credentialIssuer", "apiService") - } else { - if names.ServingCertificateSecret == "" { - missingNames = append(missingNames, "servingCertificateSecret") - } - if names.CredentialIssuer == "" { - missingNames = append(missingNames, "credentialIssuer") - } - if names.APIService == "" { - missingNames = append(missingNames, "apiService") - } + names = &NamesConfigSpec{} + } + if names.ServingCertificateSecret == "" { + missingNames = append(missingNames, "servingCertificateSecret") + } + if names.CredentialIssuer == "" { + missingNames = append(missingNames, "credentialIssuer") + } + if names.APIService == "" { + missingNames = append(missingNames, "apiService") + } + if names.ImpersonationConfigMap == "" { + missingNames = append(missingNames, "impersonationConfigMap") + } + if names.ImpersonationLoadBalancerService == "" { + missingNames = append(missingNames, "impersonationLoadBalancerService") + } + if names.ImpersonationTLSCertificateSecret == "" { + missingNames = append(missingNames, "impersonationTLSCertificateSecret") + } + if names.ImpersonationCACertificateSecret == "" { + missingNames = append(missingNames, "impersonationCACertificateSecret") } if len(missingNames) > 0 { return constable.Error("missing required names: " + strings.Join(missingNames, ", ")) diff --git a/internal/config/concierge/config_test.go b/internal/config/concierge/config_test.go index 4073d96d..5b8177ff 100644 --- a/internal/config/concierge/config_test.go +++ b/internal/config/concierge/config_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "go.pinniped.dev/internal/here" + "go.pinniped.dev/internal/plog" ) func TestFromPath(t *testing.T) { @@ -21,7 +22,7 @@ func TestFromPath(t *testing.T) { wantError string }{ { - name: "Happy", + name: "Fully filled out", yaml: here.Doc(` --- discovery: @@ -36,13 +37,18 @@ func TestFromPath(t *testing.T) { credentialIssuer: pinniped-config apiService: pinniped-api kubeCertAgentPrefix: kube-cert-agent-prefix + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value labels: myLabelKey1: myLabelValue1 myLabelKey2: myLabelValue2 - KubeCertAgent: + kubeCertAgent: namePrefix: kube-cert-agent-name-prefix- image: kube-cert-agent-image imagePullSecrets: [kube-cert-agent-image-pull-secret] + logLevel: debug `), wantConfig: &Config{ DiscoveryInfo: DiscoveryInfoSpec{ @@ -56,9 +62,13 @@ func TestFromPath(t *testing.T) { }, APIGroupSuffix: stringPtr("some.suffix.com"), NamesConfig: NamesConfigSpec{ - ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate", - CredentialIssuer: "pinniped-config", - APIService: "pinniped-api", + ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate", + CredentialIssuer: "pinniped-config", + APIService: "pinniped-api", + ImpersonationConfigMap: "impersonationConfigMap-value", + ImpersonationLoadBalancerService: "impersonationLoadBalancerService-value", + ImpersonationTLSCertificateSecret: "impersonationTLSCertificateSecret-value", + ImpersonationCACertificateSecret: "impersonationCACertificateSecret-value", }, Labels: map[string]string{ "myLabelKey1": "myLabelValue1", @@ -69,6 +79,7 @@ func TestFromPath(t *testing.T) { Image: stringPtr("kube-cert-agent-image"), ImagePullSecrets: []string{"kube-cert-agent-image-pull-secret"}, }, + LogLevel: plog.LevelDebug, }, }, { @@ -79,6 +90,10 @@ func TestFromPath(t *testing.T) { servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate credentialIssuer: pinniped-config apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value `), wantConfig: &Config{ DiscoveryInfo: DiscoveryInfoSpec{ @@ -92,9 +107,13 @@ func TestFromPath(t *testing.T) { }, }, NamesConfig: NamesConfigSpec{ - ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate", - CredentialIssuer: "pinniped-config", - APIService: "pinniped-api", + ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate", + CredentialIssuer: "pinniped-config", + APIService: "pinniped-api", + ImpersonationConfigMap: "impersonationConfigMap-value", + ImpersonationLoadBalancerService: "impersonationLoadBalancerService-value", + ImpersonationTLSCertificateSecret: "impersonationTLSCertificateSecret-value", + ImpersonationCACertificateSecret: "impersonationCACertificateSecret-value", }, Labels: map[string]string{}, KubeCertAgentConfig: KubeCertAgentSpec{ @@ -104,9 +123,11 @@ func TestFromPath(t *testing.T) { }, }, { - name: "Empty", - yaml: here.Doc(``), - wantError: "validate names: missing required names: servingCertificateSecret, credentialIssuer, apiService", + name: "Empty", + yaml: here.Doc(``), + wantError: "validate names: missing required names: servingCertificateSecret, credentialIssuer, " + + "apiService, impersonationConfigMap, impersonationLoadBalancerService, " + + "impersonationTLSCertificateSecret, impersonationCACertificateSecret", }, { name: "Missing apiService name", @@ -115,6 +136,10 @@ func TestFromPath(t *testing.T) { names: servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate credentialIssuer: pinniped-config + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value `), wantError: "validate names: missing required names: apiService", }, @@ -125,6 +150,10 @@ func TestFromPath(t *testing.T) { names: servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value `), wantError: "validate names: missing required names: credentialIssuer", }, @@ -135,9 +164,82 @@ func TestFromPath(t *testing.T) { names: credentialIssuer: pinniped-config apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value `), wantError: "validate names: missing required names: servingCertificateSecret", }, + { + name: "Missing impersonationConfigMap name", + yaml: here.Doc(` + --- + names: + servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate + credentialIssuer: pinniped-config + apiService: pinniped-api + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value + `), + wantError: "validate names: missing required names: impersonationConfigMap", + }, + { + name: "Missing impersonationLoadBalancerService name", + yaml: here.Doc(` + --- + names: + servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate + credentialIssuer: pinniped-config + apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value + `), + wantError: "validate names: missing required names: impersonationLoadBalancerService", + }, + { + name: "Missing impersonationTLSCertificateSecret name", + yaml: here.Doc(` + --- + names: + servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate + credentialIssuer: pinniped-config + apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value + `), + wantError: "validate names: missing required names: impersonationTLSCertificateSecret", + }, + { + name: "Missing impersonationCACertificateSecret name", + yaml: here.Doc(` + --- + names: + servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate + credentialIssuer: pinniped-config + apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + `), + wantError: "validate names: missing required names: impersonationCACertificateSecret", + }, + { + name: "Missing several required names", + yaml: here.Doc(` + --- + names: + servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate + credentialIssuer: pinniped-config + apiService: pinniped-api + impersonationLoadBalancerService: impersonationLoadBalancerService-value + `), + wantError: "validate names: missing required names: impersonationConfigMap, " + + "impersonationTLSCertificateSecret, impersonationCACertificateSecret", + }, { name: "InvalidDurationRenewBefore", yaml: here.Doc(` @@ -150,6 +252,10 @@ func TestFromPath(t *testing.T) { servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate credentialIssuer: pinniped-config apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value `), wantError: "validate api: durationSeconds cannot be smaller than renewBeforeSeconds", }, @@ -165,6 +271,10 @@ func TestFromPath(t *testing.T) { servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate credentialIssuer: pinniped-config apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value `), wantError: "validate api: renewBefore must be positive", }, @@ -180,6 +290,10 @@ func TestFromPath(t *testing.T) { servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate credentialIssuer: pinniped-config apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value `), wantError: "validate api: renewBefore must be positive", }, @@ -196,6 +310,10 @@ func TestFromPath(t *testing.T) { servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate credentialIssuer: pinniped-config apiService: pinniped-api + impersonationConfigMap: impersonationConfigMap-value + impersonationLoadBalancerService: impersonationLoadBalancerService-value + impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value + impersonationCACertificateSecret: impersonationCACertificateSecret-value `), wantError: "validate apiGroupSuffix: a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')", }, diff --git a/internal/config/concierge/types.go b/internal/config/concierge/types.go index 1f402a34..2a151274 100644 --- a/internal/config/concierge/types.go +++ b/internal/config/concierge/types.go @@ -33,9 +33,13 @@ type APIConfigSpec struct { // NamesConfigSpec configures the names of some Kubernetes resources for the Concierge. type NamesConfigSpec struct { - ServingCertificateSecret string `json:"servingCertificateSecret"` - CredentialIssuer string `json:"credentialIssuer"` - APIService string `json:"apiService"` + ServingCertificateSecret string `json:"servingCertificateSecret"` + CredentialIssuer string `json:"credentialIssuer"` + APIService string `json:"apiService"` + ImpersonationConfigMap string `json:"impersonationConfigMap"` + ImpersonationLoadBalancerService string `json:"impersonationLoadBalancerService"` + ImpersonationTLSCertificateSecret string `json:"impersonationTLSCertificateSecret"` + ImpersonationCACertificateSecret string `json:"impersonationCACertificateSecret"` } // ServingCertificateConfigSpec contains the configuration knobs for the API's diff --git a/internal/controllermanager/prepare_controllers.go b/internal/controllermanager/prepare_controllers.go index ce63fc91..de1e5a30 100644 --- a/internal/controllermanager/prepare_controllers.go +++ b/internal/controllermanager/prepare_controllers.go @@ -292,20 +292,24 @@ func PrepareControllers(c *Config) (func(ctx context.Context), error) { WithController( impersonatorconfig.NewImpersonatorConfigController( c.ServerInstallationInfo.Namespace, - "pinniped-concierge-impersonation-proxy-config", // TODO this string should come from `c.NamesConfig` + c.NamesConfig.ImpersonationConfigMap, client.Kubernetes, informers.installationNamespaceK8s.Core().V1().ConfigMaps(), informers.installationNamespaceK8s.Core().V1().Services(), informers.installationNamespaceK8s.Core().V1().Secrets(), controllerlib.WithInformer, controllerlib.WithInitialEvent, - "pinniped-concierge-impersonation-proxy-load-balancer", // TODO this string should come from `c.NamesConfig` - "pinniped-concierge-impersonation-proxy-tls-serving-certificate", // TODO this string should come from `c.NamesConfig` - "pinniped-concierge-impersonation-proxy-ca-certificate", // TODO this string should come from `c.NamesConfig` + c.NamesConfig.ImpersonationLoadBalancerService, + c.NamesConfig.ImpersonationTLSCertificateSecret, + c.NamesConfig.ImpersonationCACertificateSecret, c.Labels, tls.Listen, func() (http.Handler, error) { - impersonationProxyHandler, err := impersonator.New(c.AuthenticatorCache, c.LoginJSONDecoder, klogr.New().WithName("impersonation-proxy")) + impersonationProxyHandler, err := impersonator.New( + c.AuthenticatorCache, + c.LoginJSONDecoder, + klogr.New().WithName("impersonation-proxy"), + ) if err != nil { return nil, fmt.Errorf("could not create impersonation proxy: %w", err) } diff --git a/test/integration/concierge_impersonation_proxy_test.go b/test/integration/concierge_impersonation_proxy_test.go index 437a3f0d..ab67037b 100644 --- a/test/integration/concierge_impersonation_proxy_test.go +++ b/test/integration/concierge_impersonation_proxy_test.go @@ -29,14 +29,6 @@ import ( "go.pinniped.dev/test/library" ) -const ( - // TODO don't hard code "pinniped-concierge-" in these strings. It should be constructed from the env app name. - impersonationProxyConfigMapName = "pinniped-concierge-impersonation-proxy-config" - impersonationProxyTLSSecretName = "pinniped-concierge-impersonation-proxy-tls-serving-certificate" //nolint:gosec // this is not a credential - impersonationProxyCASecretName = "pinniped-concierge-impersonation-proxy-ca-certificate" //nolint:gosec // this is not a credential - impersonationProxyLoadBalancerName = "pinniped-concierge-impersonation-proxy-load-balancer" -) - // Note that this test supports being run on all of our integration test cluster types: // - load balancers not supported, has squid proxy (e.g. kind) // - load balancers supported, has squid proxy (e.g. EKS) @@ -94,11 +86,11 @@ func TestImpersonationProxy(t *testing.T) { return impersonationProxyClient } - oldConfigMap, err := adminClient.CoreV1().ConfigMaps(env.ConciergeNamespace).Get(ctx, impersonationProxyConfigMapName, metav1.GetOptions{}) + oldConfigMap, err := adminClient.CoreV1().ConfigMaps(env.ConciergeNamespace).Get(ctx, impersonationProxyConfigMapName(env), metav1.GetOptions{}) if !k8serrors.IsNotFound(err) { require.NoError(t, err) // other errors aside from NotFound are unexpected t.Logf("stashing a pre-existing configmap %s", oldConfigMap.Name) - require.NoError(t, adminClient.CoreV1().ConfigMaps(env.ConciergeNamespace).Delete(ctx, impersonationProxyConfigMapName, metav1.DeleteOptions{})) + require.NoError(t, adminClient.CoreV1().ConfigMaps(env.ConciergeNamespace).Delete(ctx, impersonationProxyConfigMapName(env), metav1.DeleteOptions{})) } impersonationProxyLoadBalancerIngress := "" @@ -106,13 +98,14 @@ func TestImpersonationProxy(t *testing.T) { if env.HasCapability(library.HasExternalLoadBalancerProvider) { //nolint:nestif // come on... it's just a test // Check that load balancer has been created. library.RequireEventuallyWithoutError(t, func() (bool, error) { - return hasImpersonationProxyLoadBalancerService(ctx, adminClient, env.ConciergeNamespace) + return hasImpersonationProxyLoadBalancerService(ctx, env, adminClient) }, 10*time.Second, 500*time.Millisecond) + // TODO this information should come from the CredentialIssuer status once that is implemented // Wait for the load balancer to get an ingress and make a note of its address. var ingress *corev1.LoadBalancerIngress library.RequireEventuallyWithoutError(t, func() (bool, error) { - ingress, err = getImpersonationProxyLoadBalancerIngress(ctx, adminClient, env.ConciergeNamespace) + ingress, err = getImpersonationProxyLoadBalancerIngress(ctx, env, adminClient) if err != nil { return false, err } @@ -131,7 +124,7 @@ func TestImpersonationProxy(t *testing.T) { // Check that no load balancer has been created. library.RequireNeverWithoutError(t, func() (bool, error) { - return hasImpersonationProxyLoadBalancerService(ctx, adminClient, env.ConciergeNamespace) + return hasImpersonationProxyLoadBalancerService(ctx, env, adminClient) }, 10*time.Second, 500*time.Millisecond) // Check that we can't use the impersonation proxy to execute kubectl commands yet. @@ -139,7 +132,7 @@ func TestImpersonationProxy(t *testing.T) { require.EqualError(t, err, serviceUnavailableViaSquidError) // Create configuration to make the impersonation proxy turn on with a hard coded endpoint (without a LoadBalancer). - configMap := configMapForConfig(t, impersonator.Config{ + configMap := configMapForConfig(t, env, impersonator.Config{ Mode: impersonator.ModeEnabled, Endpoint: proxyServiceEndpoint, TLS: nil, @@ -152,8 +145,8 @@ func TestImpersonationProxy(t *testing.T) { t.Cleanup(func() { ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - t.Logf("cleaning up configmap at end of test %s", impersonationProxyConfigMapName) - err = adminClient.CoreV1().ConfigMaps(env.ConciergeNamespace).Delete(ctx, impersonationProxyConfigMapName, metav1.DeleteOptions{}) + t.Logf("cleaning up configmap at end of test %s", impersonationProxyConfigMapName(env)) + err = adminClient.CoreV1().ConfigMaps(env.ConciergeNamespace).Delete(ctx, impersonationProxyConfigMapName(env), metav1.DeleteOptions{}) require.NoError(t, err) if len(oldConfigMap.Data) != 0 { @@ -171,7 +164,7 @@ func TestImpersonationProxy(t *testing.T) { // TODO We should be getting the CA data from the CredentialIssuer's status instead, once that is implemented. var caSecret *corev1.Secret require.Eventually(t, func() bool { - caSecret, err = adminClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyCASecretName, metav1.GetOptions{}) + caSecret, err = adminClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyCASecretName(env), metav1.GetOptions{}) return err == nil && caSecret != nil && caSecret.Data["ca.crt"] != nil }, 10*time.Second, 250*time.Millisecond) impersonationProxyCACertPEM := caSecret.Data["ca.crt"] @@ -180,7 +173,7 @@ func TestImpersonationProxy(t *testing.T) { // This could take a while if we are waiting for the load balancer to get an IP or hostname assigned to it, and it // should be fast when we are not waiting for a load balancer (e.g. on kind). require.Eventually(t, func() bool { - _, err = adminClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName, metav1.GetOptions{}) + _, err = adminClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName(env), metav1.GetOptions{}) return err == nil }, 5*time.Minute, 250*time.Millisecond) @@ -209,7 +202,7 @@ func TestImpersonationProxy(t *testing.T) { // Try more Kube API verbs through the impersonation proxy. t.Run("watching all the basic verbs", func(t *testing.T) { - // Create a namespace, because it will be easier to exercise deletecollection if we have a namespace. + // Create a namespace, because it will be easier to exercise "deletecollection" if we have a namespace. namespace, err := adminClient.CoreV1().Namespaces().Create(ctx, &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{GenerateName: "impersonation-integration-test-"}, }, metav1.CreateOptions{}) @@ -369,19 +362,19 @@ func TestImpersonationProxy(t *testing.T) { // We already know that this Secret exists because we checked above. Now see that we can get it through // the impersonation proxy without any impersonation headers on the request. - _, err = impersonationProxyClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName, metav1.GetOptions{}) + _, err = impersonationProxyClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName(env), metav1.GetOptions{}) require.NoError(t, err) // Now we'll see what happens when we add an impersonation header to the request. This should generate a // request similar to the one above, except that it will have an impersonation header. - _, err = doubleImpersonationClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName, metav1.GetOptions{}) + _, err = doubleImpersonationClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName(env), metav1.GetOptions{}) // Double impersonation is not supported yet, so we should get an error. - expectedErr := fmt.Sprintf("the server rejected our request for an unknown reason (get secrets %s)", impersonationProxyTLSSecretName) + expectedErr := fmt.Sprintf("the server rejected our request for an unknown reason (get secrets %s)", impersonationProxyTLSSecretName(env)) require.EqualError(t, err, expectedErr) }) // Update configuration to force the proxy to disabled mode - configMap := configMapForConfig(t, impersonator.Config{Mode: impersonator.ModeDisabled}) + configMap := configMapForConfig(t, env, impersonator.Config{Mode: impersonator.ModeDisabled}) if env.HasCapability(library.HasExternalLoadBalancerProvider) { t.Logf("creating configmap %s", configMap.Name) _, err = adminClient.CoreV1().ConfigMaps(env.ConciergeNamespace).Create(ctx, &configMap, metav1.CreateOptions{}) @@ -396,7 +389,7 @@ func TestImpersonationProxy(t *testing.T) { // The load balancer should not exist after we disable the impersonation proxy. // Note that this can take kind of a long time on real cloud providers (e.g. ~22 seconds on EKS). library.RequireEventuallyWithoutError(t, func() (bool, error) { - hasService, err := hasImpersonationProxyLoadBalancerService(ctx, adminClient, env.ConciergeNamespace) + hasService, err := hasImpersonationProxyLoadBalancerService(ctx, env, adminClient) return !hasService, err }, time.Minute, 500*time.Millisecond) } @@ -417,17 +410,17 @@ func TestImpersonationProxy(t *testing.T) { // Check that the generated TLS cert Secret was deleted by the controller. require.Eventually(t, func() bool { - _, err = adminClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName, metav1.GetOptions{}) + _, err = adminClient.CoreV1().Secrets(env.ConciergeNamespace).Get(ctx, impersonationProxyTLSSecretName(env), metav1.GetOptions{}) return k8serrors.IsNotFound(err) }, 10*time.Second, 250*time.Millisecond) } -func configMapForConfig(t *testing.T, config impersonator.Config) corev1.ConfigMap { +func configMapForConfig(t *testing.T, env *library.TestEnv, config impersonator.Config) corev1.ConfigMap { configString, err := yaml.Marshal(config) require.NoError(t, err) configMap := corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: impersonationProxyConfigMapName, + Name: impersonationProxyConfigMapName(env), }, Data: map[string]string{ "config.yaml": string(configString), @@ -435,8 +428,8 @@ func configMapForConfig(t *testing.T, config impersonator.Config) corev1.ConfigM return configMap } -func hasImpersonationProxyLoadBalancerService(ctx context.Context, client kubernetes.Interface, namespace string) (bool, error) { - service, err := client.CoreV1().Services(namespace).Get(ctx, impersonationProxyLoadBalancerName, metav1.GetOptions{}) +func hasImpersonationProxyLoadBalancerService(ctx context.Context, env *library.TestEnv, client kubernetes.Interface) (bool, error) { + service, err := client.CoreV1().Services(env.ConciergeNamespace).Get(ctx, impersonationProxyLoadBalancerName(env), metav1.GetOptions{}) if k8serrors.IsNotFound(err) { return false, nil } @@ -446,8 +439,8 @@ func hasImpersonationProxyLoadBalancerService(ctx context.Context, client kubern return service.Spec.Type == corev1.ServiceTypeLoadBalancer, nil } -func getImpersonationProxyLoadBalancerIngress(ctx context.Context, client kubernetes.Interface, namespace string) (*corev1.LoadBalancerIngress, error) { - service, err := client.CoreV1().Services(namespace).Get(ctx, impersonationProxyLoadBalancerName, metav1.GetOptions{}) +func getImpersonationProxyLoadBalancerIngress(ctx context.Context, env *library.TestEnv, client kubernetes.Interface) (*corev1.LoadBalancerIngress, error) { + service, err := client.CoreV1().Services(env.ConciergeNamespace).Get(ctx, impersonationProxyLoadBalancerName(env), metav1.GetOptions{}) if err != nil { return nil, err } @@ -460,3 +453,19 @@ func getImpersonationProxyLoadBalancerIngress(ctx context.Context, client kubern } return &ingresses[0], nil } + +func impersonationProxyConfigMapName(env *library.TestEnv) string { + return env.ConciergeAppName + "-impersonation-proxy-config" +} + +func impersonationProxyTLSSecretName(env *library.TestEnv) string { + return env.ConciergeAppName + "-impersonation-proxy-tls-serving-certificate" +} + +func impersonationProxyCASecretName(env *library.TestEnv) string { + return env.ConciergeAppName + "-impersonation-proxy-ca-certificate" +} + +func impersonationProxyLoadBalancerName(env *library.TestEnv) string { + return env.ConciergeAppName + "-impersonation-proxy-load-balancer" +}