Add more validation and update tests for impersonationProxy as pointer.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
parent
13372a43e6
commit
297a484948
@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -23,6 +24,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
corev1informers "k8s.io/client-go/informers/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
@ -262,23 +264,28 @@ func (c *impersonatorConfigController) doSync(syncCtx controllerlib.Context) (*v
|
||||
|
||||
func (c *impersonatorConfigController) loadImpersonationProxyConfiguration() (*v1alpha1.ImpersonationProxySpec, error) {
|
||||
credIssuer, err := c.credIssuerInformer.Lister().Get(c.credentialIssuerResourceName)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get %s CredentialIssuer: %w", c.credentialIssuerResourceName, err)
|
||||
}
|
||||
|
||||
credIssuer = credIssuer.DeepCopy()
|
||||
err = validateCredentialIssuerSpec(credIssuer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid impersonator configuration: %v", err)
|
||||
// Make a copy of the spec since we got this object from informer cache.
|
||||
spec := credIssuer.Spec.DeepCopy().ImpersonationProxy
|
||||
if spec == nil {
|
||||
return nil, fmt.Errorf("could not load CredentialIssuer: spec.impersonationProxy is nil")
|
||||
}
|
||||
|
||||
// Default service type to LoadBalancer (this is normally already done via CRD defaulting).
|
||||
if spec.Service.Type == "" {
|
||||
spec.Service.Type = v1alpha1.ImpersonationProxyServiceTypeLoadBalancer
|
||||
}
|
||||
|
||||
if err := validateCredentialIssuerSpec(spec); err != nil {
|
||||
return nil, fmt.Errorf("could not load CredentialIssuer spec.impersonationProxy: %w", err)
|
||||
}
|
||||
plog.Info("Read impersonation proxy config",
|
||||
"credentialIssuer", c.credentialIssuerResourceName,
|
||||
)
|
||||
if credIssuer.Spec.ImpersonationProxy.Service.Type == "" {
|
||||
credIssuer.Spec.ImpersonationProxy.Service.Type = v1alpha1.ImpersonationProxyServiceTypeLoadBalancer
|
||||
}
|
||||
return &credIssuer.Spec.ImpersonationProxy, nil
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
func (c *impersonatorConfigController) shouldHaveImpersonator(config *v1alpha1.ImpersonationProxySpec) bool {
|
||||
@ -455,7 +462,7 @@ func (c *impersonatorConfigController) ensureLoadBalancerIsStarted(ctx context.C
|
||||
"service", c.generatedLoadBalancerServiceName,
|
||||
"namespace", c.namespace)
|
||||
_, err = c.k8sClient.CoreV1().Services(c.namespace).Update(ctx, &loadBalancer, metav1.UpdateOptions{})
|
||||
|
||||
// TODO: make sure this error is handled if necessary
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -894,19 +901,80 @@ func (c *impersonatorConfigController) doSyncResult(nameInfo *certNameInfo, conf
|
||||
}
|
||||
}
|
||||
|
||||
func validateCredentialIssuerSpec(credIssuer *v1alpha1.CredentialIssuer) error {
|
||||
// TODO check external endpoint for valid ip or hostname
|
||||
impersonationProxySpec := credIssuer.Spec.ImpersonationProxy
|
||||
if impersonationProxySpec.Mode != v1alpha1.ImpersonationProxyModeDisabled &&
|
||||
impersonationProxySpec.ExternalEndpoint == "" && impersonationProxySpec.Service.Type == v1alpha1.ImpersonationProxyServiceTypeNone {
|
||||
return fmt.Errorf("invalid impersonation proxy configuration: must specify an external endpoint or set a service type")
|
||||
}
|
||||
switch mode := credIssuer.Spec.ImpersonationProxy.Mode; mode {
|
||||
case v1alpha1.ImpersonationProxyModeAuto:
|
||||
func validateCredentialIssuerSpec(spec *v1alpha1.ImpersonationProxySpec) error {
|
||||
// Validate that the mode is one of our known values.
|
||||
switch spec.Mode {
|
||||
case v1alpha1.ImpersonationProxyModeDisabled:
|
||||
case v1alpha1.ImpersonationProxyModeAuto:
|
||||
case v1alpha1.ImpersonationProxyModeEnabled:
|
||||
default:
|
||||
return fmt.Errorf("invalid impersonation proxy mode %q, valid values are auto, disabled, or enabled", mode)
|
||||
return fmt.Errorf("invalid proxy mode %q (expected auto, disabled, or enabled)", spec.Mode)
|
||||
}
|
||||
|
||||
// If disabled, ignore all other fields and consider the configuration valid.
|
||||
if spec.Mode == v1alpha1.ImpersonationProxyModeDisabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate that the service type is one of our known values.
|
||||
switch spec.Service.Type {
|
||||
case v1alpha1.ImpersonationProxyServiceTypeNone:
|
||||
case v1alpha1.ImpersonationProxyServiceTypeLoadBalancer:
|
||||
case v1alpha1.ImpersonationProxyServiceTypeClusterIP:
|
||||
default:
|
||||
return fmt.Errorf("invalid service type %q (expected None, LoadBalancer, or ClusterIP)", spec.Service.Type)
|
||||
}
|
||||
|
||||
// If specified, validate that the LoadBalancerIP is a valid IPv4 or IPv6 address.
|
||||
if ip := spec.Service.LoadBalancerIP; ip != "" && len(validation.IsValidIP(ip)) > 0 {
|
||||
return fmt.Errorf("invalid LoadBalancerIP %q", spec.Service.LoadBalancerIP)
|
||||
}
|
||||
|
||||
// If service is type "None", a non-empty external endpoint must be specified.
|
||||
if spec.ExternalEndpoint == "" && spec.Service.Type == v1alpha1.ImpersonationProxyServiceTypeNone {
|
||||
return fmt.Errorf("externalEndpoint must be set when service.type is None")
|
||||
}
|
||||
|
||||
if err := validateExternalEndpoint(spec.ExternalEndpoint); err != nil {
|
||||
return fmt.Errorf("invalid ExternalEndpoint %q: %w", spec.ExternalEndpoint, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateExternalEndpoint(endpoint string) error {
|
||||
// Empty string is valid (no external endpoint, default to service name)
|
||||
if endpoint == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Try parsing it both with and without an implicit port 443 at the end.
|
||||
host, port, err := net.SplitHostPort(endpoint)
|
||||
|
||||
// If we got an error parsing the raw input, try adding an implicit port 443.
|
||||
if err != nil {
|
||||
host, port, err = net.SplitHostPort(net.JoinHostPort(endpoint, "443"))
|
||||
}
|
||||
|
||||
// If there's still an error, fail now.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
portInt, _ := strconv.Atoi(port)
|
||||
if len(validation.IsValidPortNum(portInt)) > 0 {
|
||||
return fmt.Errorf("invalid port %q", port)
|
||||
}
|
||||
|
||||
// Check if the host part is a valid IP address.
|
||||
if len(validation.IsValidIP(host)) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if the host part is a valid hostname according to RFC 1123.
|
||||
if len(validation.IsDNS1123Subdomain(host)) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("host %q is not a valid hostname or IP address", host)
|
||||
}
|
||||
|
@ -1019,7 +1019,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
ExternalEndpoint: localhostIP,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1068,7 +1068,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -1360,14 +1360,13 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
requireSigningCertProviderIsEmpty()
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
when("the configuration is disabled mode", func() {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeDisabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -1392,7 +1391,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("no load balancer", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -1423,7 +1422,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("a loadbalancer already exists", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -1456,7 +1455,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
var caCrt []byte
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -1486,7 +1485,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
annotations := map[string]string{"some-annotation-key": "some-annotation-value"}
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
Type: v1alpha1.ImpersonationProxyServiceTypeLoadBalancer,
|
||||
@ -1515,7 +1514,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeHostname = "fake.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1544,7 +1543,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeHostname = "fake.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1574,7 +1573,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeIPWithPort = "127.0.0.1:3000"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeIPWithPort,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1603,7 +1602,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeHostnameWithPort = "fake.example.com:3000"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostnameWithPort,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1632,7 +1631,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeHostnameWithPort = "fake.example.com:3000"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostnameWithPort,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1665,7 +1664,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeIP = "127.0.0.42"
|
||||
|
||||
var hostnameConfig = v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1674,7 +1673,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
},
|
||||
}
|
||||
var ipAddressConfig = v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeIP,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1739,7 +1738,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeHostname = "fake.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1784,7 +1783,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeHostname = "fake.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1832,7 +1831,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
var caCrt []byte
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1904,7 +1903,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -1929,7 +1928,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
// Update the CredentialIssuer.
|
||||
updateCredentialIssuerInInformerAndWait(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeDisabled,
|
||||
},
|
||||
}, pinnipedInformers.Config().V1alpha1().CredentialIssuers())
|
||||
@ -1946,7 +1945,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
// Update the CredentialIssuer again.
|
||||
updateCredentialIssuerInInformerAndWait(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformers.Config().V1alpha1().CredentialIssuers())
|
||||
@ -1964,7 +1963,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: localhostIP,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -1994,7 +1993,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
// Switch to "enabled" mode without an "endpoint", so a load balancer is needed now.
|
||||
updateCredentialIssuerInInformerAndWait(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformers.Config().V1alpha1().CredentialIssuers())
|
||||
@ -2035,7 +2034,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
// Now switch back to having the "endpoint" specified and explicitly saying that we don't want the load balancer service.
|
||||
updateCredentialIssuerInInformerAndWait(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: localhostIP,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -2059,7 +2058,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: localhostIP,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -2093,7 +2092,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
// Add annotations to the spec.
|
||||
annotations := map[string]string{"my-annotation-key": "my-annotation-val"}
|
||||
updateCredentialIssuerInInformerAndWait(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: localhostIP,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -2118,7 +2117,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2236,7 +2235,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2263,7 +2262,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("getting the control plane nodes returns an error, e.g. when there are no nodes", func() {
|
||||
it("returns an error", func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2280,7 +2279,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
impersonatorFuncReturnedFuncError = errors.New("some immediate impersonator startup error")
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2340,7 +2339,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2393,10 +2392,27 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
when("the CredentialIssuer is invalid", func() {
|
||||
when("the CredentialIssuer has nil impersonation spec", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: nil,
|
||||
}, pinnipedInformerClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
startInformersAndController()
|
||||
errString := `could not load CredentialIssuer: spec.impersonationProxy is nil`
|
||||
r.EqualError(runControllerSync(), errString)
|
||||
requireCredentialIssuer(newErrorStrategy(errString))
|
||||
requireSigningCertProviderIsEmpty()
|
||||
requireTLSServerWasNeverStarted()
|
||||
})
|
||||
})
|
||||
|
||||
when("the CredentialIssuer has invalid mode", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: "not-valid",
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2404,7 +2420,71 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
it("returns an error", func() {
|
||||
startInformersAndController()
|
||||
errString := `invalid impersonator configuration: invalid impersonation proxy mode "not-valid", valid values are auto, disabled, or enabled`
|
||||
errString := `could not load CredentialIssuer spec.impersonationProxy: invalid proxy mode "not-valid" (expected auto, disabled, or enabled)`
|
||||
r.EqualError(runControllerSync(), errString)
|
||||
requireCredentialIssuer(newErrorStrategy(errString))
|
||||
requireSigningCertProviderIsEmpty()
|
||||
requireTLSServerWasNeverStarted()
|
||||
})
|
||||
})
|
||||
|
||||
when("the CredentialIssuer has invalid service type", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
Type: "not-valid",
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
startInformersAndController()
|
||||
errString := `could not load CredentialIssuer spec.impersonationProxy: invalid service type "not-valid" (expected None, LoadBalancer, or ClusterIP)`
|
||||
r.EqualError(runControllerSync(), errString)
|
||||
requireCredentialIssuer(newErrorStrategy(errString))
|
||||
requireSigningCertProviderIsEmpty()
|
||||
requireTLSServerWasNeverStarted()
|
||||
})
|
||||
})
|
||||
|
||||
when("the CredentialIssuer has invalid LoadBalancerIP", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
LoadBalancerIP: "invalid-ip-address",
|
||||
},
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
startInformersAndController()
|
||||
errString := `could not load CredentialIssuer spec.impersonationProxy: invalid LoadBalancerIP "invalid-ip-address"`
|
||||
r.EqualError(runControllerSync(), errString)
|
||||
requireCredentialIssuer(newErrorStrategy(errString))
|
||||
requireSigningCertProviderIsEmpty()
|
||||
requireTLSServerWasNeverStarted()
|
||||
})
|
||||
})
|
||||
|
||||
when("the CredentialIssuer has invalid ExternalEndpoint", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "[invalid",
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
})
|
||||
|
||||
it("returns an error", func() {
|
||||
startInformersAndController()
|
||||
errString := `could not load CredentialIssuer spec.impersonationProxy: invalid ExternalEndpoint "[invalid": address [invalid:443: missing ']' in address`
|
||||
r.EqualError(runControllerSync(), errString)
|
||||
requireCredentialIssuer(newErrorStrategy(errString))
|
||||
requireSigningCertProviderIsEmpty()
|
||||
@ -2419,7 +2499,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
return true, nil, fmt.Errorf("error on create")
|
||||
})
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2437,7 +2517,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("there is an error creating the tls secret", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "example.com",
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -2471,7 +2551,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
when("there is an error creating the CA secret", func() {
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "example.com",
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -2505,7 +2585,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addNodeWithRoleToTracker("control-plane", kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "example.com",
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -2535,7 +2615,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
addLoadBalancerServiceToTracker(loadBalancerServiceName, kubeAPIClient)
|
||||
addSecretToTrackers(newEmptySecret(tlsSecretName), kubeAPIClient, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2562,7 +2642,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
addNodeWithRoleToTracker("control-plane", kubeAPIClient)
|
||||
addSecretToTrackers(newEmptySecret(tlsSecretName), kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeDisabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2584,7 +2664,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: localhostIP,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -2647,7 +2727,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2710,7 +2790,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
addLoadBalancerServiceWithIngressToTracker(loadBalancerServiceName, []corev1.LoadBalancerIngress{{IP: localhostIP}}, kubeInformerClient)
|
||||
addLoadBalancerServiceWithIngressToTracker(loadBalancerServiceName, []corev1.LoadBalancerIngress{{IP: localhostIP}}, kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2755,7 +2835,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addNodeWithRoleToTracker("worker", kubeAPIClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeAuto,
|
||||
},
|
||||
}, pinnipedInformerClient)
|
||||
@ -2787,7 +2867,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
const fakeHostname = "foo.example.com"
|
||||
it.Before(func() {
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: fakeHostname,
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -2879,7 +2959,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
it.Before(func() {
|
||||
addSecretToTrackers(signingCASecret, kubeInformerClient)
|
||||
addCredentialIssuerToTracker(credentialIssuerResourceName, v1alpha1.CredentialIssuerSpec{
|
||||
ImpersonationProxy: v1alpha1.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &v1alpha1.ImpersonationProxySpec{
|
||||
Mode: v1alpha1.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: "",
|
||||
Service: v1alpha1.ImpersonationProxyServiceSpec{
|
||||
@ -2892,7 +2972,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
it("returns a validation error", func() {
|
||||
startInformersAndController()
|
||||
r.EqualError(runControllerSync(), "invalid impersonator configuration: invalid impersonation proxy configuration: must specify an external endpoint or set a service type")
|
||||
r.EqualError(runControllerSync(), "could not load CredentialIssuer spec.impersonationProxy: externalEndpoint must be set when service.type is None")
|
||||
r.Len(kubeAPIClient.Actions(), 0)
|
||||
})
|
||||
})
|
||||
@ -2921,3 +3001,53 @@ func (q *testQueue) AddRateLimited(key controllerlib.Key) {
|
||||
|
||||
q.key = key
|
||||
}
|
||||
|
||||
func TestValidateExternalEndpoint(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tt := range []struct {
|
||||
input string
|
||||
expectErr string
|
||||
}{
|
||||
{input: ""},
|
||||
{input: "127.0.0.1"},
|
||||
{input: "127.0.0.1:8443"},
|
||||
{input: "[127.0.0.1]:8443"},
|
||||
{input: "2001:db8::ffff"},
|
||||
{input: "[2001:db8::ffff]:8443"},
|
||||
{input: "host.example.com"},
|
||||
{input: "host-dev.example.com"},
|
||||
{input: "host.example.com:8443"},
|
||||
{input: "[host.example.com]:8443"},
|
||||
{
|
||||
input: "https://host.example.com",
|
||||
expectErr: `invalid port "//host.example.com"`,
|
||||
},
|
||||
{
|
||||
input: "host.example.com/some/path",
|
||||
expectErr: `host "host.example.com/some/path" is not a valid hostname or IP address`,
|
||||
},
|
||||
{
|
||||
input: "[host.example.com",
|
||||
expectErr: "address [host.example.com:443: missing ']' in address",
|
||||
},
|
||||
{
|
||||
input: "___.example.com:1234",
|
||||
expectErr: `host "___.example.com" is not a valid hostname or IP address`,
|
||||
},
|
||||
{
|
||||
input: "HOST.EXAMPLE.COM",
|
||||
expectErr: `host "HOST.EXAMPLE.COM" is not a valid hostname or IP address`,
|
||||
},
|
||||
} {
|
||||
tt := tt
|
||||
t.Run(fmt.Sprintf("parse %q", tt.input), func(t *testing.T) {
|
||||
got := validateExternalEndpoint(tt.input)
|
||||
if tt.expectErr == "" {
|
||||
require.NoError(t, got)
|
||||
} else {
|
||||
require.EqualError(t, got, tt.expectErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
||||
case impersonatorShouldHaveStartedAutomaticallyByDefault && clusterSupportsLoadBalancers:
|
||||
// configure the credential issuer spec to have the impersonation proxy in auto mode
|
||||
updateCredentialIssuer(ctx, t, env, adminConciergeClient, conciergev1alpha.CredentialIssuerSpec{
|
||||
ImpersonationProxy: conciergev1alpha.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &conciergev1alpha.ImpersonationProxySpec{
|
||||
Mode: conciergev1alpha.ImpersonationProxyModeAuto,
|
||||
Service: conciergev1alpha.ImpersonationProxyServiceSpec{
|
||||
Type: conciergev1alpha.ImpersonationProxyServiceTypeLoadBalancer,
|
||||
@ -223,7 +223,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
||||
|
||||
// Create configuration to make the impersonation proxy turn on with no endpoint (i.e. automatically create a load balancer).
|
||||
updateCredentialIssuer(ctx, t, env, adminConciergeClient, conciergev1alpha.CredentialIssuerSpec{
|
||||
ImpersonationProxy: conciergev1alpha.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &conciergev1alpha.ImpersonationProxySpec{
|
||||
Mode: conciergev1alpha.ImpersonationProxyModeEnabled,
|
||||
},
|
||||
})
|
||||
@ -249,7 +249,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
||||
|
||||
// Create configuration to make the impersonation proxy turn on with a hard coded endpoint (without a load balancer).
|
||||
updateCredentialIssuer(ctx, t, env, adminConciergeClient, conciergev1alpha.CredentialIssuerSpec{
|
||||
ImpersonationProxy: conciergev1alpha.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &conciergev1alpha.ImpersonationProxySpec{
|
||||
Mode: conciergev1alpha.ImpersonationProxyModeEnabled,
|
||||
ExternalEndpoint: proxyServiceEndpoint,
|
||||
},
|
||||
@ -1185,7 +1185,7 @@ func TestImpersonationProxy(t *testing.T) { //nolint:gocyclo // yeah, it's compl
|
||||
t.Run("manually disabling the impersonation proxy feature", func(t *testing.T) {
|
||||
// Update configuration to force the proxy to disabled mode
|
||||
updateCredentialIssuer(ctx, t, env, adminConciergeClient, conciergev1alpha.CredentialIssuerSpec{
|
||||
ImpersonationProxy: conciergev1alpha.ImpersonationProxySpec{
|
||||
ImpersonationProxy: &conciergev1alpha.ImpersonationProxySpec{
|
||||
Mode: conciergev1alpha.ImpersonationProxyModeDisabled,
|
||||
},
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user