Skip to content

Commit

Permalink
fixup! Inject certificate to http client from a configmap referenced …
Browse files Browse the repository at this point in the history
…in the config

Signed-off-by: ivinokur <[email protected]>
  • Loading branch information
vinokurig committed May 6, 2024
1 parent a13aa5a commit a523bd8
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 41 deletions.
15 changes: 11 additions & 4 deletions controllers/workspace/devworkspace_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package controllers
import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -667,14 +668,20 @@ func (r *DevWorkspaceReconciler) getWorkspaceId(ctx context.Context, workspace *
}
}

func (r *DevWorkspaceReconciler) SetupWithManager(mgr ctrl.Manager, k8s client.Client) error {
setupHttpClients(k8s)
func (r *DevWorkspaceReconciler) SetupWithManager(mgr ctrl.Manager) error {
setupHttpClients(mgr.GetClient(), r.Log)
maxConcurrentReconciles, err := wkspConfig.GetMaxConcurrentReconciles()
if err != nil {
return err
}

var emptyMapper = func(obj client.Object) []reconcile.Request {
var certificatesHandler = func(obj client.Object) []reconcile.Request {
certs, ok := readCertificates(mgr.GetClient(), r.Log)
if ok {
for _, certsPem := range certs {
injectCertificates([]byte(certsPem), httpClient.Transport.(*http.Transport))
}
}
return []reconcile.Request{}
}

Expand Down Expand Up @@ -702,7 +709,7 @@ func (r *DevWorkspaceReconciler) SetupWithManager(mgr ctrl.Manager, k8s client.C
Watches(&source.Kind{Type: &corev1.ConfigMap{}}, handler.EnqueueRequestsFromMapFunc(r.runningWorkspacesHandler), automountWatcher).
Watches(&source.Kind{Type: &corev1.ConfigMap{}}, handler.EnqueueRequestsFromMapFunc(r.certificateHandler), certificateWatcher).
Watches(&source.Kind{Type: &corev1.PersistentVolumeClaim{}}, handler.EnqueueRequestsFromMapFunc(r.runningWorkspacesHandler), automountWatcher).
Watches(&source.Kind{Type: &controllerv1alpha1.DevWorkspaceOperatorConfig{}}, handler.EnqueueRequestsFromMapFunc(emptyMapper), configWatcher).
Watches(&source.Kind{Type: &controllerv1alpha1.DevWorkspaceOperatorConfig{}}, handler.EnqueueRequestsFromMapFunc(certificatesHandler), configWatcher).
WithEventFilter(devworkspacePredicates).
WithEventFilter(podPredicates).
Complete(r)
Expand Down
3 changes: 1 addition & 2 deletions controllers/workspace/eventhandlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,7 @@ func (r *DevWorkspaceReconciler) runningWorkspacesHandler(obj client.Object) []r
}

func (r *DevWorkspaceReconciler) certificateHandler(obj client.Object) []reconcile.Request {
certsPem, ok := obj.(*corev1.ConfigMap).Data["custom-ca-certificates.pem"]
if ok {
for _, certsPem := range obj.(*corev1.ConfigMap).Data {
injectCertificates([]byte(certsPem), httpClient.Transport.(*http.Transport))
}
return []reconcile.Request{}
Expand Down
20 changes: 11 additions & 9 deletions controllers/workspace/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"context"
"crypto/tls"
"crypto/x509"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"net/http"
Expand All @@ -33,11 +34,13 @@ var (
healthCheckHttpClient *http.Client
)

func setupHttpClients(k8s client.Client) {
func setupHttpClients(k8s client.Client, logger logr.Logger) {
transport := http.DefaultTransport.(*http.Transport).Clone()
certs, ok := readCertificates(k8s)
certs, ok := readCertificates(k8s, logger)
if ok {
injectCertificates(certs, transport)
for _, certsPem := range certs {
injectCertificates([]byte(certsPem), transport)
}
}
healthCheckTransport := http.DefaultTransport.(*http.Transport).Clone()
healthCheckTransport.TLSClientConfig = &tls.Config{
Expand Down Expand Up @@ -74,7 +77,7 @@ func setupHttpClients(k8s client.Client) {
}
}

func readCertificates(k8s client.Client) ([]byte, bool) {
func readCertificates(k8s client.Client, logger logr.Logger) (map[string]string, bool) {
configmapRef := config.GetGlobalConfig().Routing.TLSCertificateConfigmapRef
if configmapRef == nil {
return nil, false
Expand All @@ -86,12 +89,11 @@ func readCertificates(k8s client.Client) ([]byte, bool) {
}
err := k8s.Get(context.Background(), *namespacedName, configMap)
if err == nil {
certificates, ok := configMap.Data["custom-ca-certificates.pem"]
if ok {
return []byte(certificates), true
}
return configMap.Data, true
} else {
logger.Error(err, "Failed to read configmap with certificates")
}
return []byte{}, false
return map[string]string{}, false
}

func injectCertificates(certsPem []byte, transport *http.Transport) {
Expand Down
6 changes: 3 additions & 3 deletions controllers/workspace/predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ func objectIsAutomountResource(obj client.Object) bool {
}

func objectIsCertificateConfigmap(obj client.Object) bool {
configmapRef := config.GetGlobalConfig().Routing.TLSCertificateConfigmapRef
if configmapRef == nil {
routing := config.GetGlobalConfig().Routing
if routing == nil || routing.TLSCertificateConfigmapRef == nil {
return false
} else {
return configmapRef.Name == obj.GetName() && configmapRef.Namespace == obj.GetNamespace()
return routing.TLSCertificateConfigmapRef.Name == obj.GetName() && routing.TLSCertificateConfigmapRef.Namespace == obj.GetNamespace()
}
}
2 changes: 1 addition & 1 deletion controllers/workspace/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ var _ = BeforeSuite(func() {
NonCachingClient: nonCachingClient,
Log: ctrl.Log.WithName("controllers").WithName("DevWorkspace"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr, nonCachingClient)
}).SetupWithManager(mgr)
Expect(err).NotTo(HaveOccurred())

// Set HTTP client to fail all requests by default; tests that require HTTP must set this up directly
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func main() {
NonCachingClient: nonCachingClient,
Log: ctrl.Log.WithName("controllers").WithName("DevWorkspace"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr, nonCachingClient); err != nil {
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "DevWorkspace")
os.Exit(1)
}
Expand Down
9 changes: 7 additions & 2 deletions pkg/config/predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ import (
func Predicates() predicate.Predicate {
return predicate.Funcs{
UpdateFunc: func(evt event.UpdateEvent) bool {
if config, ok := evt.ObjectNew.(*dw.DevWorkspaceOperatorConfig); ok {
syncConfigFrom(config)
if newConfig, ok := evt.ObjectNew.(*dw.DevWorkspaceOperatorConfig); ok {
syncConfigFrom(newConfig)
if oldConfig, ok := evt.ObjectOld.(*dw.DevWorkspaceOperatorConfig); ok {
if *oldConfig.Config.Routing.TLSCertificateConfigmapRef != *newConfig.Config.Routing.TLSCertificateConfigmapRef {
return true
}
}
}
return false
},
Expand Down
18 changes: 0 additions & 18 deletions pkg/config/proxy/openshift.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,6 @@ func GetClusterProxyConfig(nonCachedClient crclient.Client) (*controller.Proxy,
return proxyConfig, nil
}

// MergeTLSCertificateConfigmapRef merges tls certificate configmap reference configurations
// from the operator and the cluster and merges them, with the operator configuration taking precedence.
func MergeTLSCertificateConfigmapRef(operatorConfig, clusterConfig *controller.ConfigmapReference) *controller.ConfigmapReference {
mergedConfigmapReference := &controller.ConfigmapReference{
Name: operatorConfig.Name,
Namespace: operatorConfig.Namespace,
}

if mergedConfigmapReference.Name == "" {
mergedConfigmapReference.Name = clusterConfig.Name
}
if mergedConfigmapReference.Namespace == "" {
mergedConfigmapReference.Namespace = clusterConfig.Namespace
}

return mergedConfigmapReference
}

// MergeProxyConfigs merges proxy configurations from the operator and the cluster and merges them, with the
// operator configuration taking precedence. Accepts nil arguments. If both arguments are nil, returns nil.
func MergeProxyConfigs(operatorConfig, clusterConfig *controller.Proxy) *controller.Proxy {
Expand Down
18 changes: 17 additions & 1 deletion pkg/config/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ func mergeConfig(from, to *controller.OperatorConfiguration) {
if to.Routing.TLSCertificateConfigmapRef == nil {
to.Routing.TLSCertificateConfigmapRef = &controller.ConfigmapReference{}
}
to.Routing.TLSCertificateConfigmapRef = proxy.MergeTLSCertificateConfigmapRef(from.Routing.TLSCertificateConfigmapRef, defaultConfig.Routing.TLSCertificateConfigmapRef)
to.Routing.TLSCertificateConfigmapRef = mergeTLSCertificateConfigmapRef(from.Routing.TLSCertificateConfigmapRef, defaultConfig.Routing.TLSCertificateConfigmapRef)
}
}
if from.Workspace != nil {
Expand Down Expand Up @@ -432,6 +432,22 @@ func mergeContainerSecurityContext(base, patch *corev1.SecurityContext) *corev1.
return patched
}

func mergeTLSCertificateConfigmapRef(operatorConfig, clusterConfig *controller.ConfigmapReference) *controller.ConfigmapReference {
mergedConfigmapReference := &controller.ConfigmapReference{
Name: operatorConfig.Name,
Namespace: operatorConfig.Namespace,
}

if mergedConfigmapReference.Name == "" {
mergedConfigmapReference.Name = clusterConfig.Name
}
if mergedConfigmapReference.Namespace == "" {
mergedConfigmapReference.Namespace = clusterConfig.Namespace
}

return mergedConfigmapReference
}

func mergeResources(from, to *corev1.ResourceRequirements) *corev1.ResourceRequirements {
result := to.DeepCopy()
if from.Limits != nil {
Expand Down

0 comments on commit a523bd8

Please sign in to comment.