diff --git a/go.mod b/go.mod index 43197bddf7..983bb10930 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/Azure/go-autorest/autorest v0.11.29 github.com/Azure/go-autorest/autorest/mocks v0.4.2 github.com/container-storage-interface/spec v1.9.0 + github.com/fsnotify/fsnotify v1.8.0 github.com/golang/protobuf v1.5.4 github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 github.com/kubernetes-csi/csi-lib-utils v0.17.0 @@ -80,7 +81,6 @@ require ( github.com/distribution/reference v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect diff --git a/pkg/azureutils/azure_disk_utils.go b/pkg/azureutils/azure_disk_utils.go index f4c785d172..c77426466f 100644 --- a/pkg/azureutils/azure_disk_utils.go +++ b/pkg/azureutils/azure_disk_utils.go @@ -42,6 +42,7 @@ import ( "k8s.io/mount-utils" "k8s.io/utils/ptr" consts "sigs.k8s.io/azuredisk-csi-driver/pkg/azureconstants" + "sigs.k8s.io/azuredisk-csi-driver/pkg/filewatcher" "sigs.k8s.io/azuredisk-csi-driver/pkg/optimization" "sigs.k8s.io/azuredisk-csi-driver/pkg/util" "sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader" @@ -244,6 +245,11 @@ func GetCloudProviderFromClient(ctx context.Context, kubeClient clientset.Interf config.AADFederatedTokenFile = federatedTokenFile config.UseFederatedWorkloadIdentityExtension = true } + if len(config.AADClientCertPath) > 0 { + // Watch the certificate for changes; if the certificate changes, the pod will be restarted + err = filewatcher.WatchFileForChanges(config.AADClientCertPath) + klog.Warningf("Failed to watch certificate file for changes: %v", err) + } if err = az.InitializeCloudFromConfig(ctx, config, fromSecret, false); err != nil { klog.Warningf("InitializeCloudFromConfig failed with error: %v", err) } diff --git a/pkg/filewatcher/filewatcher.go b/pkg/filewatcher/filewatcher.go new file mode 100644 index 0000000000..9638d5278a --- /dev/null +++ b/pkg/filewatcher/filewatcher.go @@ -0,0 +1,83 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package filewatcher + +import ( + "os" + "path/filepath" + "sync" + + "github.com/fsnotify/fsnotify" + "k8s.io/klog/v2" +) + +var watchCertificateFileOnce sync.Once + +// WatchFileForChanges watches the file, fileToWatch, for changes. If the file contents have changed, the pod this +// function is running on will be restarted. +func WatchFileForChanges(fileToWatch string) error { + var err error + + // This starts only one occurrence of the file watcher, which watches the file, fileToWatch. + watchCertificateFileOnce.Do(func() { + klog.Infof("Starting the file change watcher on file, %s", fileToWatch) + + // Update the file path to watch in case this is a symlink + fileToWatch, err = filepath.EvalSymlinks(fileToWatch) + if err != nil { + return + } + klog.Infof("Watching file, %s", fileToWatch) + + // Start the file watcher to monitor file changes + go func() { + err = checkForFileChanges(fileToWatch) + }() + }) + return err +} + +// checkForFileChanges starts a new file watcher. If the file is changed, the pod running this function will exit. +func checkForFileChanges(path string) error { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return err + } + + go func() { + for { + select { + case event, ok := <-watcher.Events: + if ok && (event.Has(fsnotify.Write) || event.Has(fsnotify.Chmod) || event.Has(fsnotify.Remove)) { + klog.Infof("file, %s, was modified, exiting...", event.Name) + os.Exit(0) + } + case err, ok := <-watcher.Errors: + if ok { + klog.Errorf("file watcher error: %v", err) + } + } + } + }() + + err = watcher.Add(path) + if err != nil { + return err + } + + return nil +}