Skip to content

Commit 7219290

Browse files
authored
Merge pull request #4717 from k8s-infra-cherrypick-robot/cherry-pick-4712-to-release-1.14
[release-1.14] enable per-sub msi client
2 parents 25d1874 + 5c1bdc5 commit 7219290

File tree

7 files changed

+77
-11
lines changed

7 files changed

+77
-11
lines changed

azure/services/identities/client.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ func NewClient(auth azure.Authorizer) (Client, error) {
5151
return &AzureClient{factory.NewUserAssignedIdentitiesClient()}, nil
5252
}
5353

54+
// NewClientBySub creates a new MSI client with a given subscriptionID.
55+
func NewClientBySub(auth azure.Authorizer, subscriptionID string) (Client, error) {
56+
opts, err := azure.ARMClientOptions(auth.CloudEnvironment())
57+
if err != nil {
58+
return nil, errors.Wrap(err, "failed to create identities client options")
59+
}
60+
factory, err := armmsi.NewClientFactory(subscriptionID, auth.Token(), opts)
61+
if err != nil {
62+
return nil, errors.Wrap(err, "failed to create armmsi client factory")
63+
}
64+
return &AzureClient{factory.NewUserAssignedIdentitiesClient()}, nil
65+
}
66+
5467
// Get returns a managed service identity.
5568
func (ac *AzureClient) Get(ctx context.Context, resourceGroupName, name string) (armmsi.Identity, error) {
5669
ctx, _, done := tele.StartSpanWithLogger(ctx, "identities.AzureClient.Get")

azure/services/virtualmachines/virtualmachines.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,18 @@ func (s *Service) checkUserAssignedIdentities(ctx context.Context, specIdentitie
176176

177177
// Create a map of the expected identities. The ProviderID is converted to match the format of the VM identity.
178178
for _, expectedIdentity := range specIdentities {
179-
expectedClientID, err := s.identitiesGetter.GetClientID(ctx, expectedIdentity.ProviderID)
179+
identitiesClient := s.identitiesGetter
180+
parsed, err := azureutil.ParseResourceID(expectedIdentity.ProviderID)
181+
if err != nil {
182+
return err
183+
}
184+
if parsed.SubscriptionID != s.Scope.SubscriptionID() {
185+
identitiesClient, err = identities.NewClientBySub(s.Scope, parsed.SubscriptionID)
186+
if err != nil {
187+
return errors.Wrapf(err, "failed to create identities client from subscription ID %s", parsed.SubscriptionID)
188+
}
189+
}
190+
expectedClientID, err := identitiesClient.GetClientID(ctx, expectedIdentity.ProviderID)
180191
if err != nil {
181192
return errors.Wrap(err, "failed to get client ID")
182193
}

azure/services/virtualmachines/virtualmachines_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,10 @@ var (
114114
},
115115
}
116116
fakeUserAssignedIdentity = infrav1.UserAssignedIdentity{
117-
ProviderID: "fake-provider-id",
117+
ProviderID: "azure:///subscriptions/123/resourceGroups/test-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/fake-provider-id",
118118
}
119119
fakeUserAssignedIdentity2 = infrav1.UserAssignedIdentity{
120-
ProviderID: "fake-provider-id-2",
120+
ProviderID: "azure:///subscriptions/123/resourceGroups/test-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/fake-provider-id-2",
121121
}
122122
)
123123

@@ -335,6 +335,7 @@ func TestCheckUserAssignedIdentities(t *testing.T) {
335335
specIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity},
336336
actualIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity},
337337
expect: func(s *mock_virtualmachines.MockVMScopeMockRecorder, i *mock_identities.MockClientMockRecorder) {
338+
s.SubscriptionID().Return("123")
338339
i.GetClientID(gomockinternal.AContext(), fakeUserAssignedIdentity.ProviderID).AnyTimes().Return(fakeUserAssignedIdentity.ProviderID, nil)
339340
},
340341
expectedError: "",
@@ -344,6 +345,7 @@ func TestCheckUserAssignedIdentities(t *testing.T) {
344345
specIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity, fakeUserAssignedIdentity2},
345346
actualIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity},
346347
expect: func(s *mock_virtualmachines.MockVMScopeMockRecorder, i *mock_identities.MockClientMockRecorder) {
348+
s.SubscriptionID().AnyTimes().Return("123")
347349
i.GetClientID(gomockinternal.AContext(), fakeUserAssignedIdentity.ProviderID).AnyTimes().Return(fakeUserAssignedIdentity.ProviderID, nil)
348350
i.GetClientID(gomockinternal.AContext(), fakeUserAssignedIdentity2.ProviderID).AnyTimes().Return(fakeUserAssignedIdentity2.ProviderID, nil)
349351
s.SetConditionFalse(infrav1.VMIdentitiesReadyCondition, infrav1.UserAssignedIdentityMissingReason, clusterv1.ConditionSeverityWarning, vmMissingUAI+fakeUserAssignedIdentity2.ProviderID).Times(1)
@@ -355,6 +357,7 @@ func TestCheckUserAssignedIdentities(t *testing.T) {
355357
specIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity},
356358
actualIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity, fakeUserAssignedIdentity2},
357359
expect: func(s *mock_virtualmachines.MockVMScopeMockRecorder, i *mock_identities.MockClientMockRecorder) {
360+
s.SubscriptionID().Return("123")
358361
i.GetClientID(gomockinternal.AContext(), fakeUserAssignedIdentity.ProviderID).AnyTimes().Return(fakeUserAssignedIdentity.ProviderID, nil)
359362
},
360363
expectedError: "",
@@ -364,6 +367,7 @@ func TestCheckUserAssignedIdentities(t *testing.T) {
364367
specIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity},
365368
actualIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity2},
366369
expect: func(s *mock_virtualmachines.MockVMScopeMockRecorder, i *mock_identities.MockClientMockRecorder) {
370+
s.SubscriptionID().Return("123")
367371
i.GetClientID(gomockinternal.AContext(), fakeUserAssignedIdentity.ProviderID).AnyTimes().Return(fakeUserAssignedIdentity.ProviderID, nil)
368372
s.SetConditionFalse(infrav1.VMIdentitiesReadyCondition, infrav1.UserAssignedIdentityMissingReason, clusterv1.ConditionSeverityWarning, vmMissingUAI+fakeUserAssignedIdentity.ProviderID).Times(1)
369373
},
@@ -374,6 +378,7 @@ func TestCheckUserAssignedIdentities(t *testing.T) {
374378
specIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity, fakeUserAssignedIdentity},
375379
actualIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity},
376380
expect: func(s *mock_virtualmachines.MockVMScopeMockRecorder, i *mock_identities.MockClientMockRecorder) {
381+
s.SubscriptionID().AnyTimes().Return("123")
377382
i.GetClientID(gomockinternal.AContext(), fakeUserAssignedIdentity.ProviderID).AnyTimes().Return(fakeUserAssignedIdentity.ProviderID, nil)
378383
},
379384
expectedError: "",
@@ -383,6 +388,7 @@ func TestCheckUserAssignedIdentities(t *testing.T) {
383388
specIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity},
384389
actualIdentities: []infrav1.UserAssignedIdentity{fakeUserAssignedIdentity},
385390
expect: func(s *mock_virtualmachines.MockVMScopeMockRecorder, i *mock_identities.MockClientMockRecorder) {
391+
s.SubscriptionID().Return("123")
386392
i.GetClientID(gomockinternal.AContext(), fakeUserAssignedIdentity.ProviderID).AnyTimes().Return("", errors.New("failed to get client id"))
387393
},
388394
expectedError: "failed to get client id",

controllers/azurejson_machine_controller.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
3232
"sigs.k8s.io/cluster-api-provider-azure/azure/scope"
3333
"sigs.k8s.io/cluster-api-provider-azure/azure/services/identities"
34+
azureutil "sigs.k8s.io/cluster-api-provider-azure/util/azure"
3435
"sigs.k8s.io/cluster-api-provider-azure/util/reconciler"
3536
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
3637
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
@@ -215,11 +216,22 @@ func (r *AzureJSONMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req
215216
// Construct secret for this machine
216217
userAssignedIdentityIfExists := ""
217218
if len(azureMachine.Spec.UserAssignedIdentities) > 0 {
218-
idsClient, err := identities.NewClient(clusterScope)
219+
var identitiesClient identities.Client
220+
identitiesClient, err := identities.NewClient(clusterScope)
219221
if err != nil {
220222
return reconcile.Result{}, errors.Wrap(err, "failed to create identities client")
221223
}
222-
userAssignedIdentityIfExists, err = idsClient.GetClientID(
224+
parsed, err := azureutil.ParseResourceID(azureMachine.Spec.UserAssignedIdentities[0].ProviderID)
225+
if err != nil {
226+
return reconcile.Result{}, errors.Wrapf(err, "failed to parse ProviderID %s", azureMachine.Spec.UserAssignedIdentities[0].ProviderID)
227+
}
228+
if parsed.SubscriptionID != clusterScope.SubscriptionID() {
229+
identitiesClient, err = identities.NewClientBySub(clusterScope, parsed.SubscriptionID)
230+
if err != nil {
231+
return reconcile.Result{}, errors.Wrapf(err, "failed to create identities client from subscription ID %s", parsed.SubscriptionID)
232+
}
233+
}
234+
userAssignedIdentityIfExists, err = identitiesClient.GetClientID(
223235
ctx, azureMachine.Spec.UserAssignedIdentities[0].ProviderID)
224236
if err != nil {
225237
return reconcile.Result{}, errors.Wrap(err, "failed to get user-assigned identity ClientID")

controllers/azurejson_machinepool_controller.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
3030
"sigs.k8s.io/cluster-api-provider-azure/azure/services/identities"
3131
infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1beta1"
32+
azureutil "sigs.k8s.io/cluster-api-provider-azure/util/azure"
3233
"sigs.k8s.io/cluster-api-provider-azure/util/reconciler"
3334
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
3435
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
@@ -148,11 +149,22 @@ func (r *AzureJSONMachinePoolReconciler) Reconcile(ctx context.Context, req ctrl
148149
// Construct secret for this machine
149150
userAssignedIdentityIfExists := ""
150151
if len(azureMachinePool.Spec.UserAssignedIdentities) > 0 {
151-
idsClient, err := getClient(clusterScope)
152+
var identitiesClient identities.Client
153+
identitiesClient, err := getClient(clusterScope)
152154
if err != nil {
153155
return reconcile.Result{}, errors.Wrap(err, "failed to create identities client")
154156
}
155-
userAssignedIdentityIfExists, err = idsClient.GetClientID(
157+
parsed, err := azureutil.ParseResourceID(azureMachinePool.Spec.UserAssignedIdentities[0].ProviderID)
158+
if err != nil {
159+
return reconcile.Result{}, errors.Wrapf(err, "failed to parse ProviderID %s", azureMachinePool.Spec.UserAssignedIdentities[0].ProviderID)
160+
}
161+
if parsed.SubscriptionID != clusterScope.SubscriptionID() {
162+
identitiesClient, err = identities.NewClientBySub(clusterScope, parsed.SubscriptionID)
163+
if err != nil {
164+
return reconcile.Result{}, errors.Wrapf(err, "failed to create identities client from subscription ID %s", parsed.SubscriptionID)
165+
}
166+
}
167+
userAssignedIdentityIfExists, err = identitiesClient.GetClientID(
156168
ctx, azureMachinePool.Spec.UserAssignedIdentities[0].ProviderID)
157169
if err != nil {
158170
return reconcile.Result{}, errors.Wrap(err, "failed to get user-assigned identity ClientID")

controllers/azurejson_machinepool_controller_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func TestAzureJSONPoolReconcilerUserAssignedIdentities(t *testing.T) {
271271
Spec: infrav1exp.AzureMachinePoolSpec{
272272
UserAssignedIdentities: []infrav1.UserAssignedIdentity{
273273
{
274-
ProviderID: "fake-id",
274+
ProviderID: "azure:///subscriptions/123/resourceGroups/test-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/fake-provider-id",
275275
},
276276
},
277277
},
@@ -378,7 +378,7 @@ func TestAzureJSONPoolReconcilerUserAssignedIdentities(t *testing.T) {
378378
Recorder: record.NewFakeRecorder(42),
379379
Timeouts: reconciler.Timeouts{},
380380
}
381-
id := "fake-id"
381+
id := "azure:///subscriptions/123/resourceGroups/test-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/fake-provider-id"
382382
getClient = func(auth azure.Authorizer) (identities.Client, error) {
383383
mockClient := mock_identities.NewMockClient(ctrlr)
384384
mockClient.EXPECT().GetClientID(gomock.Any(), gomock.Any()).Return(id, nil)

controllers/azurejson_machinetemplate_controller.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
3131
"sigs.k8s.io/cluster-api-provider-azure/azure/scope"
3232
"sigs.k8s.io/cluster-api-provider-azure/azure/services/identities"
33+
azureutil "sigs.k8s.io/cluster-api-provider-azure/util/azure"
3334
"sigs.k8s.io/cluster-api-provider-azure/util/reconciler"
3435
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
3536
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
@@ -175,11 +176,22 @@ func (r *AzureJSONTemplateReconciler) Reconcile(ctx context.Context, req ctrl.Re
175176
// Construct secret for this machine template
176177
userAssignedIdentityIfExists := ""
177178
if len(azureMachineTemplate.Spec.Template.Spec.UserAssignedIdentities) > 0 {
178-
idsClient, err := identities.NewClient(clusterScope)
179+
var identitiesClient identities.Client
180+
identitiesClient, err := identities.NewClient(clusterScope)
179181
if err != nil {
180182
return reconcile.Result{}, errors.Wrap(err, "failed to create identities client")
181183
}
182-
userAssignedIdentityIfExists, err = idsClient.GetClientID(
184+
parsed, err := azureutil.ParseResourceID(azureMachineTemplate.Spec.Template.Spec.UserAssignedIdentities[0].ProviderID)
185+
if err != nil {
186+
return reconcile.Result{}, errors.Wrapf(err, "failed to parse ProviderID %s", azureMachineTemplate.Spec.Template.Spec.UserAssignedIdentities[0].ProviderID)
187+
}
188+
if parsed.SubscriptionID != clusterScope.SubscriptionID() {
189+
identitiesClient, err = identities.NewClientBySub(clusterScope, parsed.SubscriptionID)
190+
if err != nil {
191+
return reconcile.Result{}, errors.Wrapf(err, "failed to create identities client from subscription ID %s", parsed.SubscriptionID)
192+
}
193+
}
194+
userAssignedIdentityIfExists, err = identitiesClient.GetClientID(
183195
ctx, azureMachineTemplate.Spec.Template.Spec.UserAssignedIdentities[0].ProviderID)
184196
if err != nil {
185197
return reconcile.Result{}, errors.Wrap(err, "failed to get user-assigned identity ClientID")

0 commit comments

Comments
 (0)