Skip to content

Commit 2194fb7

Browse files
committed
Authenticate to Azure only once in CPO
This commit changes image registry to look for a stored Azure credential to reuse to authenticate with Azure. If there is no stored Azure credential, authenticate to Azure with UAMI and store the credentials. Prior to this commit, image registry was getting new credentials every continually; this led to an issue where image registry would open too many filewatchers as NewUserAssignedIdentityCredential opens a new filewatcher on every call. Signed-off-by: Bryan Cox <[email protected]>
1 parent f27308c commit 2194fb7

File tree

2 files changed

+52
-19
lines changed

2 files changed

+52
-19
lines changed

pkg/storage/azure/azure.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"reflect"
1010
"regexp"
1111
"strings"
12+
"sync"
1213
"time"
1314

1415
"github.com/Azure/azure-pipeline-go/pipeline"
@@ -53,6 +54,7 @@ const (
5354
storageExistsReasonContainerDeleted = "ContainerDeleted"
5455
storageExistsReasonAccountDeleted = "AccountDeleted"
5556
storageExistsReasonAccountNotFound = "AccountNotFound"
57+
azureCredentialsKey = "AzureCredentials"
5658
)
5759

5860
// storageAccountInvalidCharRe is a regular expression for characters that
@@ -316,6 +318,10 @@ type driver struct {
316318
// policies is for new Azure Client Pipeline execution.
317319
// Added as a member to the struct to allow injection for testing.
318320
policies []policy.Policy
321+
322+
// azureCredentials keeps track if we have already loaded an Azure
323+
// credentials token when using UAMI for managed Azure on HCP.
324+
azureCredentials sync.Map
319325
}
320326

321327
// NewDriver creates a new storage driver for Azure Blob Storage.
@@ -371,16 +377,29 @@ func (d *driver) storageAccountsClient(cfg *Azure, environment autorestazure.Env
371377
cred azcore.TokenCredential
372378
err error
373379
)
380+
381+
// UserAssignedIdentityCredentials is specifically for managed Azure HCP
374382
userAssignedIdentityCredentialsFilePath := os.Getenv("MANAGED_AZURE_HCP_CREDENTIALS_FILE_PATH")
375383
if userAssignedIdentityCredentialsFilePath != "" {
376-
// UserAssignedIdentityCredentials for managed Azure HCP
377-
klog.V(2).Info("Using UserAssignedIdentityCredentials for Azure authentication for managed Azure HCP")
378-
clientOptions := azcore.ClientOptions{
379-
Cloud: cloudConfig,
380-
}
381-
cred, err = dataplane.NewUserAssignedIdentityCredential(context.Background(), userAssignedIdentityCredentialsFilePath, dataplane.WithClientOpts(clientOptions))
382-
if err != nil {
383-
return storage.AccountsClient{}, err
384+
var ok bool
385+
386+
// We need to only store the Azure credentials once and reuse them after that.
387+
storedCreds, found := d.azureCredentials.Load(userAssignedIdentityCredentialsFilePath)
388+
if !found {
389+
klog.V(2).Info("Using UserAssignedIdentityCredentials for Azure authentication for managed Azure HCP")
390+
clientOptions := azcore.ClientOptions{
391+
Cloud: cloudConfig,
392+
}
393+
cred, err = dataplane.NewUserAssignedIdentityCredential(context.Background(), userAssignedIdentityCredentialsFilePath, dataplane.WithClientOpts(clientOptions))
394+
if err != nil {
395+
return storage.AccountsClient{}, err
396+
}
397+
d.azureCredentials.Store(azureCredentialsKey, cred)
398+
} else {
399+
cred, ok = storedCreds.(azcore.TokenCredential)
400+
if !ok {
401+
return storage.AccountsClient{}, fmt.Errorf("expected %T to be a TokenCredential", storedCreds)
402+
}
384403
}
385404
} else if strings.TrimSpace(cfg.ClientSecret) == "" {
386405
options := azidentity.WorkloadIdentityCredentialOptions{

pkg/storage/azure/azureclient/azureclient.go

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"os"
99
"strings"
10+
"sync"
1011

1112
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
1213
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
@@ -30,12 +31,14 @@ const (
3031
defaultPrivateZoneName = "privatelink.blob.core.windows.net"
3132
defaultPrivateZoneLocation = "global"
3233
defaultRecordSetTTL = 10
34+
azureCredentialsKey = "AzureCredentials"
3335
)
3436

3537
type Client struct {
36-
creds azcore.TokenCredential
37-
clientOpts *policy.ClientOptions
38-
opts *Options
38+
creds azcore.TokenCredential
39+
clientOpts *policy.ClientOptions
40+
opts *Options
41+
azureCredentials sync.Map
3942
}
4043

4144
type Options struct {
@@ -105,14 +108,25 @@ func (c *Client) getCreds(ctx context.Context) (azcore.TokenCredential, error) {
105108
)
106109
userAssignedIdentityCredentialsFilePath := os.Getenv("MANAGED_AZURE_HCP_CREDENTIALS_FILE_PATH")
107110
if userAssignedIdentityCredentialsFilePath != "" {
108-
// UserAssignedIdentityCredentials for managed Azure HCP
109-
klog.V(2).Info("Using UserAssignedIdentityCredentials for Azure authentication for managed Azure HCP")
110-
clientOptions := azcore.ClientOptions{
111-
Cloud: c.clientOpts.Cloud,
112-
}
113-
creds, err = dataplane.NewUserAssignedIdentityCredential(ctx, userAssignedIdentityCredentialsFilePath, dataplane.WithClientOpts(clientOptions))
114-
if err != nil {
115-
return nil, err
111+
var ok bool
112+
113+
// We need to only store the Azure credentials once and reuse them after that.
114+
storedCreds, found := c.azureCredentials.Load(userAssignedIdentityCredentialsFilePath)
115+
if !found {
116+
klog.V(2).Info("Using UserAssignedIdentityCredentials for Azure authentication for managed Azure HCP")
117+
clientOptions := azcore.ClientOptions{
118+
Cloud: c.clientOpts.Cloud,
119+
}
120+
creds, err = dataplane.NewUserAssignedIdentityCredential(ctx, userAssignedIdentityCredentialsFilePath, dataplane.WithClientOpts(clientOptions))
121+
if err != nil {
122+
return nil, err
123+
}
124+
c.azureCredentials.Store(azureCredentialsKey, creds)
125+
} else {
126+
creds, ok = storedCreds.(azcore.TokenCredential)
127+
if !ok {
128+
return nil, fmt.Errorf("expected %T to be a TokenCredential", storedCreds)
129+
}
116130
}
117131
} else if strings.TrimSpace(c.opts.ClientSecret) == "" {
118132
options := azidentity.WorkloadIdentityCredentialOptions{

0 commit comments

Comments
 (0)