diff --git a/internal/controller/authenticator/webhookcachefiller/webhookcachefiller.go b/internal/controller/authenticator/webhookcachefiller/webhookcachefiller.go index f9400db4b..ef13bef0d 100644 --- a/internal/controller/authenticator/webhookcachefiller/webhookcachefiller.go +++ b/internal/controller/authenticator/webhookcachefiller/webhookcachefiller.go @@ -21,6 +21,7 @@ import ( k8snetutil "k8s.io/apimachinery/pkg/util/net" "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/plugin/pkg/authenticator/token/webhook" + corev1informers "k8s.io/client-go/informers/core/v1" "k8s.io/client-go/rest" "k8s.io/klog/v2" "k8s.io/utils/clock" @@ -31,6 +32,7 @@ import ( pinnipedcontroller "go.pinniped.dev/internal/controller" "go.pinniped.dev/internal/controller/authenticator/authncache" "go.pinniped.dev/internal/controller/conditionsutil" + "go.pinniped.dev/internal/controller/tlsconfigutil" "go.pinniped.dev/internal/controllerlib" "go.pinniped.dev/internal/crypto/ptls" "go.pinniped.dev/internal/endpointaddr" @@ -67,6 +69,8 @@ func New( cache *authncache.Cache, client conciergeclientset.Interface, webhooks authinformers.WebhookAuthenticatorInformer, + secretInformer corev1informers.SecretInformer, + configMapInformer corev1informers.ConfigMapInformer, clock clock.Clock, log plog.Logger, ) controllerlib.Controller { @@ -74,11 +78,13 @@ func New( controllerlib.Config{ Name: controllerName, Syncer: &webhookCacheFillerController{ - cache: cache, - client: client, - webhooks: webhooks, - clock: clock, - log: log.WithName(controllerName), + cache: cache, + client: client, + webhooks: webhooks, + secretInformer: secretInformer, + configMapInformer: configMapInformer, + clock: clock, + log: log.WithName(controllerName), }, }, controllerlib.WithInformer( @@ -90,11 +96,13 @@ func New( } type webhookCacheFillerController struct { - cache *authncache.Cache - webhooks authinformers.WebhookAuthenticatorInformer - client conciergeclientset.Interface - clock clock.Clock - log plog.Logger + cache *authncache.Cache + webhooks authinformers.WebhookAuthenticatorInformer + secretInformer corev1informers.SecretInformer + configMapInformer corev1informers.ConfigMapInformer + client conciergeclientset.Interface + clock clock.Clock + log plog.Logger } // Sync implements controllerlib.Syncer. @@ -136,7 +144,7 @@ func (c *webhookCacheFillerController) Sync(ctx controllerlib.Context) error { conditions := make([]*metav1.Condition, 0) var errs []error - certPool, pemBytes, conditions, tlsBundleOk := c.validateTLSBundle(obj.Spec.TLS, conditions) + certPool, pemBytes, conditions, tlsBundleOk := c.validateTLSBundle(obj.Spec.TLS, obj.Namespace, conditions) endpointHostPort, conditions, endpointOk := c.validateEndpoint(obj.Spec.Endpoint, conditions) okSoFar := tlsBundleOk && endpointOk @@ -312,29 +320,16 @@ func (c *webhookCacheFillerController) validateConnection(certPool *x509.CertPoo return conditions, nil } -func (c *webhookCacheFillerController) validateTLSBundle(tlsSpec *authenticationv1alpha1.TLSSpec, conditions []*metav1.Condition) (*x509.CertPool, []byte, []*metav1.Condition, bool) { - rootCAs, pemBytes, err := pinnipedcontroller.BuildCertPoolAuth(tlsSpec) - if err != nil { - msg := fmt.Sprintf("%s: %s", "invalid TLS configuration", err.Error()) - conditions = append(conditions, &metav1.Condition{ - Type: typeTLSConfigurationValid, - Status: metav1.ConditionFalse, - Reason: reasonInvalidTLSConfiguration, - Message: msg, - }) - return rootCAs, pemBytes, conditions, false - } - msg := "successfully parsed specified CA bundle" - if rootCAs == nil { - msg = "no CA bundle specified" - } - conditions = append(conditions, &metav1.Condition{ - Type: typeTLSConfigurationValid, - Status: metav1.ConditionTrue, - Reason: reasonSuccess, - Message: msg, - }) - return rootCAs, pemBytes, conditions, true +func (c *webhookCacheFillerController) validateTLSBundle(tlsSpec *authenticationv1alpha1.TLSSpec, namespace string, conditions []*metav1.Condition) (*x509.CertPool, []byte, []*metav1.Condition, bool) { + condition, pemBytes, rootCAs, _ := tlsconfigutil.ValidateTLSConfig( + tlsconfigutil.TlsSpecForConcierge(tlsSpec), + "spec.tls", + namespace, + c.secretInformer, + c.configMapInformer) + + conditions = append(conditions, condition) + return rootCAs, pemBytes, conditions, condition.Status == metav1.ConditionTrue } func (c *webhookCacheFillerController) validateEndpoint(endpoint string, conditions []*metav1.Condition) (*endpointaddr.HostPort, []*metav1.Condition, bool) { diff --git a/internal/controller/authenticator/webhookcachefiller/webhookcachefiller_test.go b/internal/controller/authenticator/webhookcachefiller/webhookcachefiller_test.go index b2c60418c..bc6157adb 100644 --- a/internal/controller/authenticator/webhookcachefiller/webhookcachefiller_test.go +++ b/internal/controller/authenticator/webhookcachefiller/webhookcachefiller_test.go @@ -25,6 +25,8 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/authentication/authenticator" + kubeinformers "k8s.io/client-go/informers" + kubernetesfake "k8s.io/client-go/kubernetes/fake" coretesting "k8s.io/client-go/testing" clocktesting "k8s.io/utils/clock/testing" "k8s.io/utils/ptr" @@ -221,7 +223,7 @@ func TestController(t *testing.T) { ObservedGeneration: observedGeneration, LastTransitionTime: time, Reason: "Success", - Message: "successfully parsed specified CA bundle", + Message: "spec.tls is valid: loaded TLS configuration", } } happyTLSConfigurationValidNoCA := func(time metav1.Time, observedGeneration int64) metav1.Condition { @@ -231,7 +233,7 @@ func TestController(t *testing.T) { ObservedGeneration: observedGeneration, LastTransitionTime: time, Reason: "Success", - Message: "no CA bundle specified", + Message: "spec.tls is valid: no TLS configuration provided", } } sadTLSConfigurationValid := func(time metav1.Time, observedGeneration int64) metav1.Condition { @@ -240,8 +242,8 @@ func TestController(t *testing.T) { Status: "False", ObservedGeneration: observedGeneration, LastTransitionTime: time, - Reason: "InvalidTLSConfiguration", - Message: "invalid TLS configuration: illegal base64 data at input byte 7", + Reason: "InvalidTLSConfig", + Message: "spec.tls.certificateAuthorityData is invalid: illegal base64 data at input byte 7", } } @@ -1488,6 +1490,7 @@ func TestController(t *testing.T) { tt.configClient(pinnipedAPIClient) } informers := conciergeinformers.NewSharedInformerFactory(pinnipedAPIClient, 0) + kubeInformers := kubeinformers.NewSharedInformerFactory(kubernetesfake.NewSimpleClientset(), 0) cache := authncache.New() var log bytes.Buffer @@ -1501,6 +1504,8 @@ func TestController(t *testing.T) { cache, pinnipedAPIClient, informers.Authentication().V1alpha1().WebhookAuthenticators(), + kubeInformers.Core().V1().Secrets(), + kubeInformers.Core().V1().ConfigMaps(), frozenClock, logger) diff --git a/internal/controllermanager/prepare_controllers.go b/internal/controllermanager/prepare_controllers.go index a7edc4fd4..274aebcec 100644 --- a/internal/controllermanager/prepare_controllers.go +++ b/internal/controllermanager/prepare_controllers.go @@ -238,6 +238,8 @@ func PrepareControllers(c *Config) (controllerinit.RunnerBuilder, error) { //nol c.AuthenticatorCache, client.PinnipedConcierge, informers.pinniped.Authentication().V1alpha1().WebhookAuthenticators(), + informers.installationNamespaceK8s.Core().V1().Secrets(), + informers.installationNamespaceK8s.Core().V1().ConfigMaps(), clock.RealClock{}, plog.New(), ),