@@ -8,10 +8,12 @@ import (
8
8
"time"
9
9
10
10
"github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2020-04-01-preview/authorization"
11
+ "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-11-01/subscriptions"
11
12
"github.com/hashicorp/go-uuid"
12
13
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
13
14
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
14
15
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
16
+ "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/authorization/parse"
15
17
billingValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/billing/validate"
16
18
managementGroupValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/managementgroup/validate"
17
19
resourceValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/resource/validate"
@@ -96,6 +98,13 @@ func resourceArmRoleAssignment() *pluginsdk.Resource {
96
98
Computed : true ,
97
99
},
98
100
101
+ "delegated_managed_identity_resource_id" : {
102
+ Type : pluginsdk .TypeString ,
103
+ Optional : true ,
104
+ ForceNew : true ,
105
+ ValidateFunc : azure .ValidateResourceID ,
106
+ },
107
+
99
108
"description" : {
100
109
Type : pluginsdk .TypeString ,
101
110
Optional : true ,
@@ -128,6 +137,8 @@ func resourceArmRoleAssignment() *pluginsdk.Resource {
128
137
func resourceArmRoleAssignmentCreate (d * pluginsdk.ResourceData , meta interface {}) error {
129
138
roleAssignmentsClient := meta .(* clients.Client ).Authorization .RoleAssignmentsClient
130
139
roleDefinitionsClient := meta .(* clients.Client ).Authorization .RoleDefinitionsClient
140
+ subscriptionClient := meta .(* clients.Client ).Subscription .Client
141
+ subscriptionId := meta .(* clients.Client ).Account .SubscriptionId
131
142
ctx , cancel := timeouts .ForCreate (meta .(* clients.Client ).StopContext , d )
132
143
defer cancel ()
133
144
@@ -163,7 +174,17 @@ func resourceArmRoleAssignmentCreate(d *pluginsdk.ResourceData, meta interface{}
163
174
name = uuid
164
175
}
165
176
166
- existing , err := roleAssignmentsClient .Get (ctx , scope , name , "" )
177
+ tenantId := ""
178
+ delegatedManagedIdentityResourceID := d .Get ("delegated_managed_identity_resource_id" ).(string )
179
+ if len (delegatedManagedIdentityResourceID ) > 0 {
180
+ var err error
181
+ tenantId , err = getTenantIdBySubscriptionId (ctx , subscriptionClient , subscriptionId )
182
+ if err != nil {
183
+ return err
184
+ }
185
+ }
186
+
187
+ existing , err := roleAssignmentsClient .Get (ctx , scope , name , tenantId )
167
188
if err != nil {
168
189
if ! utils .ResponseWasNotFound (existing .Response ) {
169
190
return fmt .Errorf ("Error checking for presence of existing Role Assignment ID for %q (Scope %q): %+v" , name , scope , err )
@@ -182,6 +203,10 @@ func resourceArmRoleAssignmentCreate(d *pluginsdk.ResourceData, meta interface{}
182
203
},
183
204
}
184
205
206
+ if len (delegatedManagedIdentityResourceID ) > 0 {
207
+ properties .RoleAssignmentProperties .DelegatedManagedIdentityResourceID = utils .String (delegatedManagedIdentityResourceID )
208
+ }
209
+
185
210
condition := d .Get ("condition" ).(string )
186
211
conditionVersion := d .Get ("condition_version" ).(string )
187
212
@@ -197,19 +222,19 @@ func resourceArmRoleAssignmentCreate(d *pluginsdk.ResourceData, meta interface{}
197
222
properties .RoleAssignmentProperties .PrincipalType = authorization .ServicePrincipal
198
223
}
199
224
200
- if err := pluginsdk .Retry (d .Timeout (pluginsdk .TimeoutCreate ), retryRoleAssignmentsClient (d , scope , name , properties , meta )); err != nil {
225
+ if err := pluginsdk .Retry (d .Timeout (pluginsdk .TimeoutCreate ), retryRoleAssignmentsClient (d , scope , name , properties , meta , tenantId )); err != nil {
201
226
return err
202
227
}
203
228
204
- read , err := roleAssignmentsClient .Get (ctx , scope , name , "" )
229
+ read , err := roleAssignmentsClient .Get (ctx , scope , name , tenantId )
205
230
if err != nil {
206
231
return err
207
232
}
208
233
if read .ID == nil {
209
234
return fmt .Errorf ("Cannot read Role Assignment ID for %q (Scope %q)" , name , scope )
210
235
}
211
236
212
- d .SetId (* read .ID )
237
+ d .SetId (parse . ConstructRoleAssignmentId ( * read .ID , tenantId ) )
213
238
return resourceArmRoleAssignmentRead (d , meta )
214
239
}
215
240
@@ -219,7 +244,11 @@ func resourceArmRoleAssignmentRead(d *pluginsdk.ResourceData, meta interface{})
219
244
ctx , cancel := timeouts .ForRead (meta .(* clients.Client ).StopContext , d )
220
245
defer cancel ()
221
246
222
- resp , err := client .GetByID (ctx , d .Id (), "" )
247
+ id , err := parse .RoleAssignmentID (d .Id ())
248
+ if err != nil {
249
+ return err
250
+ }
251
+ resp , err := client .GetByID (ctx , id .AzureResourceID (), id .TenantId )
223
252
if err != nil {
224
253
if utils .ResponseWasNotFound (resp .Response ) {
225
254
log .Printf ("[DEBUG] Role Assignment ID %q was not found - removing from state" , d .Id ())
@@ -237,6 +266,7 @@ func resourceArmRoleAssignmentRead(d *pluginsdk.ResourceData, meta interface{})
237
266
d .Set ("role_definition_id" , props .RoleDefinitionID )
238
267
d .Set ("principal_id" , props .PrincipalID )
239
268
d .Set ("principal_type" , props .PrincipalType )
269
+ d .Set ("delegated_managed_identity_resource_id" , props .DelegatedManagedIdentityResourceID )
240
270
d .Set ("description" , props .Description )
241
271
d .Set ("condition" , props .Condition )
242
272
d .Set ("condition_version" , props .ConditionVersion )
@@ -267,7 +297,7 @@ func resourceArmRoleAssignmentDelete(d *pluginsdk.ResourceData, meta interface{}
267
297
return err
268
298
}
269
299
270
- resp , err := client .Delete (ctx , id .scope , id .name , "" )
300
+ resp , err := client .Delete (ctx , id .scope , id .name , id . tenantId )
271
301
if err != nil {
272
302
if ! utils .ResponseWasNotFound (resp .Response ) {
273
303
return err
@@ -277,7 +307,7 @@ func resourceArmRoleAssignmentDelete(d *pluginsdk.ResourceData, meta interface{}
277
307
return nil
278
308
}
279
309
280
- func retryRoleAssignmentsClient (d * pluginsdk.ResourceData , scope string , name string , properties authorization.RoleAssignmentCreateParameters , meta interface {}) func () * pluginsdk.RetryError {
310
+ func retryRoleAssignmentsClient (d * pluginsdk.ResourceData , scope string , name string , properties authorization.RoleAssignmentCreateParameters , meta interface {}, tenantId string ) func () * pluginsdk.RetryError {
281
311
return func () * pluginsdk.RetryError {
282
312
roleAssignmentsClient := meta .(* clients.Client ).Authorization .RoleAssignmentsClient
283
313
ctx , cancel := timeouts .ForCreate (meta .(* clients.Client ).StopContext , d )
@@ -306,7 +336,7 @@ func retryRoleAssignmentsClient(d *pluginsdk.ResourceData, scope string, name st
306
336
Target : []string {
307
337
"ready" ,
308
338
},
309
- Refresh : roleAssignmentCreateStateRefreshFunc (ctx , roleAssignmentsClient , * resp .ID ),
339
+ Refresh : roleAssignmentCreateStateRefreshFunc (ctx , roleAssignmentsClient , * resp .ID , tenantId ),
310
340
MinTimeout : 5 * time .Second ,
311
341
ContinuousTargetOccurence : 5 ,
312
342
Timeout : d .Timeout (pluginsdk .TimeoutCreate ),
@@ -321,27 +351,36 @@ func retryRoleAssignmentsClient(d *pluginsdk.ResourceData, scope string, name st
321
351
}
322
352
323
353
type roleAssignmentId struct {
324
- scope string
325
- name string
354
+ scope string
355
+ name string
356
+ tenantId string
326
357
}
327
358
328
359
func parseRoleAssignmentId (input string ) (* roleAssignmentId , error ) {
329
- segments := strings .Split (input , "/providers/Microsoft.Authorization/roleAssignments/" )
360
+ tenantId := ""
361
+ segments := strings .Split (input , "|" )
362
+ if len (segments ) == 2 {
363
+ tenantId = segments [1 ]
364
+ input = segments [0 ]
365
+ }
366
+
367
+ segments = strings .Split (input , "/providers/Microsoft.Authorization/roleAssignments/" )
330
368
if len (segments ) != 2 {
331
369
return nil , fmt .Errorf ("Expected Role Assignment ID to be in the format `{scope}/providers/Microsoft.Authorization/roleAssignments/{name}` but got %q" , input )
332
370
}
333
371
334
372
// /{scope}/providers/Microsoft.Authorization/roleAssignments/{roleAssignmentName}
335
373
id := roleAssignmentId {
336
- scope : strings .TrimPrefix (segments [0 ], "/" ),
337
- name : segments [1 ],
374
+ scope : strings .TrimPrefix (segments [0 ], "/" ),
375
+ name : segments [1 ],
376
+ tenantId : tenantId ,
338
377
}
339
378
return & id , nil
340
379
}
341
380
342
- func roleAssignmentCreateStateRefreshFunc (ctx context.Context , client * authorization.RoleAssignmentsClient , roleID string ) pluginsdk.StateRefreshFunc {
381
+ func roleAssignmentCreateStateRefreshFunc (ctx context.Context , client * authorization.RoleAssignmentsClient , roleID string , tenantId string ) pluginsdk.StateRefreshFunc {
343
382
return func () (interface {}, string , error ) {
344
- resp , err := client .GetByID (ctx , roleID , "" )
383
+ resp , err := client .GetByID (ctx , roleID , tenantId )
345
384
if err != nil {
346
385
if utils .ResponseWasNotFound (resp .Response ) {
347
386
return resp , "pending" , nil
@@ -351,3 +390,14 @@ func roleAssignmentCreateStateRefreshFunc(ctx context.Context, client *authoriza
351
390
return resp , "ready" , nil
352
391
}
353
392
}
393
+
394
+ func getTenantIdBySubscriptionId (ctx context.Context , client * subscriptions.Client , subscriptionId string ) (string , error ) {
395
+ resp , err := client .Get (ctx , subscriptionId )
396
+ if err != nil {
397
+ return "" , fmt .Errorf ("get tenant Id by Subscription %s: %+v" , subscriptionId , err )
398
+ }
399
+ if resp .TenantID == nil {
400
+ return "" , fmt .Errorf ("tenant Id is nil by Subscription %s: %+v" , subscriptionId , resp )
401
+ }
402
+ return * resp .TenantID , nil
403
+ }
0 commit comments