Skip to content

Commit ed330be

Browse files
Merge pull request #1194 from bryan-cox/CNTRLPLANE-112
CNTRLPLANE-112: Authenticate to Azure only once in CPO
2 parents f27308c + 2194fb7 commit ed330be

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)