Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0
github.com/Azure/go-autorest/autorest v0.11.27
github.com/aws/aws-sdk-go v1.37.8
github.com/fsnotify/fsnotify v1.7.0
github.com/google/uuid v1.6.0
github.com/gophercloud/gophercloud v0.25.1-0.20220718160629-0721d75e876f
github.com/gophercloud/utils v0.0.0-20220307143606-8e7800759d16
Expand Down Expand Up @@ -52,7 +53,6 @@ require (
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.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
Expand Down
33 changes: 27 additions & 6 deletions pkg/cloudprovider/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/jongio/azidext/go/azidext"
v1 "github.com/openshift/api/cloudnetwork/v1"
configv1 "github.com/openshift/api/config/v1"
"github.com/openshift/cloud-network-config-controller/pkg/filewatcher"
corev1 "k8s.io/api/core/v1"
"k8s.io/klog/v2"
utilnet "k8s.io/utils/net"
Expand Down Expand Up @@ -586,17 +587,37 @@ func (a *Azure) getAuthorizer(env azureapi.Environment, cfg *azureCredentialsCon
err error
)

// MSI Override for ARO HCP
msi := os.Getenv("AZURE_MSI_AUTHENTICATION")
if msi == "true" {
options := azidentity.ManagedIdentityCredentialOptions{
// Managed Identity Override for ARO HCP
managedIdentityClientID := os.Getenv("ARO_HCP_MI_CLIENT_ID")
if managedIdentityClientID != "" {
klog.Info("Using client certification Azure authentication for ARO HCP")
options := &azidentity.ClientCertificateCredentialOptions{
ClientOptions: azcore.ClientOptions{
Cloud: cloudConfig,
},
SendCertificateChain: true,
Comment thread
bryan-cox marked this conversation as resolved.
}

var err error
cred, err = azidentity.NewManagedIdentityCredential(&options)
tenantID := os.Getenv("ARO_HCP_TENANT_ID")
certPath := os.Getenv("ARO_HCP_CLIENT_CERTIFICATE_PATH")

certData, err := os.ReadFile(certPath)
if err != nil {
return nil, fmt.Errorf(`failed to read certificate file "%s": %v`, certPath, err)
}

certs, key, err := azidentity.ParseCertificates(certData, []byte{})
if err != nil {
return nil, fmt.Errorf(`failed to parse certificate data "%s": %v`, certPath, err)
}

// Watch the certificate for changes; if the certificate changes, the pod will be restarted
err = filewatcher.WatchFileForChanges(certPath)
if err != nil {
return nil, err
}

cred, err = azidentity.NewClientCertificateCredential(tenantID, managedIdentityClientID, certs, key, options)
if err != nil {
return nil, err
}
Expand Down
68 changes: 68 additions & 0 deletions pkg/filewatcher/filewatcher.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
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() {
Comment thread
bryan-cox marked this conversation as resolved.
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)
klog.Errorf("Error checking for file changes: %v", err)
}()
})
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() {
Copy link
Copy Markdown
Contributor

@kyrtapz kyrtapz Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you run checkForFileChanges as a go routine but it starts one inside with the done channel waiting for it, why?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I didn't need the second goroutine so I removed it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently this is needed. The pod does not restart when I removed this.

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
}