Skip to content

Commit 031c146

Browse files
jkroepkewyattfryjackofallops
authored
azurerm_pim_active_role_assignment: add support for RBAC conditions. (hashicorp#27947)
* azurerm_pim_active_role_assignment: add support for RBAC conditions. * restore original test * Update internal/services/authorization/pim_eligible_role_assignment_resource.go Co-authored-by: Wyatt Fry <wyattfry@gmail.com> * Update website/docs/r/pim_eligible_role_assignment.html.markdown Co-authored-by: jackofallops <11830746+jackofallops@users.noreply.github.com> * Update internal/services/authorization/pim_eligible_role_assignment_resource_test.go Co-authored-by: Wyatt Fry <wyattfry@gmail.com> --------- Co-authored-by: Wyatt Fry <wyattfry@gmail.com> Co-authored-by: jackofallops <11830746+jackofallops@users.noreply.github.com>
1 parent 1127b8a commit 031c146

3 files changed

Lines changed: 108 additions & 9 deletions

File tree

internal/services/authorization/pim_eligible_role_assignment_resource.go

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ type PimEligibleRoleAssignmentModel struct {
4040
Justification string `tfschema:"justification"`
4141
TicketInfo []PimEligibleRoleAssignmentTicketInfo `tfschema:"ticket"`
4242
ScheduleInfo []PimEligibleRoleAssignmentScheduleInfo `tfschema:"schedule"`
43+
Condition string `tfschema:"condition"`
44+
ConditionVersion string `tfschema:"condition_version"`
4345
}
4446

4547
type PimEligibleRoleAssignmentTicketInfo struct {
@@ -114,6 +116,24 @@ func (PimEligibleRoleAssignmentResource) Arguments() map[string]*pluginsdk.Schem
114116
Description: "The justification for this eligible role assignment",
115117
},
116118

119+
"condition": {
120+
Type: pluginsdk.TypeString,
121+
Optional: true,
122+
ForceNew: true,
123+
RequiredWith: []string{"condition_version"},
124+
ValidateFunc: validation.StringIsNotEmpty,
125+
},
126+
127+
"condition_version": {
128+
Type: pluginsdk.TypeString,
129+
Optional: true,
130+
ForceNew: true,
131+
RequiredWith: []string{"condition"},
132+
ValidateFunc: validation.StringInSlice([]string{
133+
"2.0",
134+
}, false),
135+
},
136+
117137
"schedule": {
118138
Type: pluginsdk.TypeList,
119139
MaxItems: 1,
@@ -285,16 +305,26 @@ func (r PimEligibleRoleAssignmentResource) Create() sdk.ResourceFunc {
285305
return err
286306
}
287307

308+
properties := &roleeligibilityschedulerequests.RoleEligibilityScheduleRequestProperties{
309+
Justification: pointer.To(config.Justification),
310+
PrincipalId: id.PrincipalId,
311+
RequestType: roleeligibilityschedulerequests.RequestTypeAdminAssign,
312+
RoleDefinitionId: id.RoleDefinitionId,
313+
Scope: pointer.To(scopeId.ID()),
314+
ScheduleInfo: scheduleInfo,
315+
TicketInfo: ticketInfo,
316+
}
317+
318+
condition := config.Condition
319+
conditionVersion := config.ConditionVersion
320+
321+
if condition != "" && conditionVersion != "" {
322+
properties.Condition = pointer.To(condition)
323+
properties.ConditionVersion = pointer.To(conditionVersion)
324+
}
325+
288326
payload := roleeligibilityschedulerequests.RoleEligibilityScheduleRequest{
289-
Properties: &roleeligibilityschedulerequests.RoleEligibilityScheduleRequestProperties{
290-
Justification: pointer.To(config.Justification),
291-
PrincipalId: id.PrincipalId,
292-
RequestType: roleeligibilityschedulerequests.RequestTypeAdminAssign,
293-
RoleDefinitionId: id.RoleDefinitionId,
294-
Scope: pointer.To(scopeId.ID()),
295-
ScheduleInfo: scheduleInfo,
296-
TicketInfo: ticketInfo,
297-
},
327+
Properties: properties,
298328
}
299329

300330
roleEligibilityScheduleRequestName, err := uuid.GenerateUUID()
@@ -396,6 +426,9 @@ func (r PimEligibleRoleAssignmentResource) Read() sdk.ResourceFunc {
396426
state.PrincipalType = string(pointer.From(request.Properties.PrincipalType))
397427
state.RoleDefinitionId = request.Properties.RoleDefinitionId
398428

429+
state.Condition = pointer.From(request.Properties.Condition)
430+
state.ConditionVersion = pointer.From(request.Properties.ConditionVersion)
431+
399432
if ticketInfo := request.Properties.TicketInfo; ticketInfo != nil {
400433
if len(state.TicketInfo) == 0 {
401434
state.TicketInfo = make([]PimEligibleRoleAssignmentTicketInfo, 1)

internal/services/authorization/pim_eligible_role_assignment_resource_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,21 @@ func TestAccPimEligibleRoleAssignment_expirationByDate(t *testing.T) {
121121
})
122122
}
123123

124+
func TestAccPimEligibleRoleAssignment_condition(t *testing.T) {
125+
data := acceptance.BuildTestData(t, "azurerm_pim_eligible_role_assignment", "test")
126+
r := PimEligibleRoleAssignmentResource{}
127+
128+
data.ResourceTest(t, r, []acceptance.TestStep{
129+
{
130+
Config: r.condition(data),
131+
Check: acceptance.ComposeTestCheckFunc(
132+
check.That(data.ResourceName).ExistsInAzure(r),
133+
),
134+
},
135+
data.ImportStep("schedule.0.start_date_time"),
136+
})
137+
}
138+
124139
func (r PimEligibleRoleAssignmentResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
125140
id, err := parse.PimRoleAssignmentID(state.ID)
126141
if err != nil {
@@ -416,3 +431,47 @@ resource "azurerm_pim_eligible_role_assignment" "import" {
416431
}
417432
`, r.importSetup(data))
418433
}
434+
435+
func (r PimEligibleRoleAssignmentResource) condition(data acceptance.TestData) string {
436+
return fmt.Sprintf(`
437+
data "azurerm_subscription" "primary" {}
438+
439+
data "azurerm_client_config" "test" {}
440+
441+
data "azurerm_role_definition" "test" {
442+
name = "Storage Blob Data Contributor"
443+
}
444+
445+
%[1]s
446+
447+
resource "azurerm_resource_group" "test" {
448+
name = "acctestRG-%[2]d"
449+
location = "%[3]s"
450+
}
451+
452+
resource "time_static" "test" {}
453+
454+
resource "azurerm_pim_eligible_role_assignment" "test" {
455+
scope = data.azurerm_subscription.primary.id
456+
role_definition_id = "${data.azurerm_subscription.primary.id}${data.azurerm_role_definition.test.id}"
457+
principal_id = azuread_user.test.object_id
458+
459+
schedule {
460+
start_date_time = time_static.test.rfc3339
461+
expiration {
462+
duration_hours = 8
463+
}
464+
}
465+
466+
justification = "Expiration Duration Set"
467+
468+
condition_version = "2.0"
469+
condition = "((!(ActionMatches{'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read'})) OR (@Resource[Microsoft.Storage/storageAccounts/blobServices/containers:name] StringEquals 'test'))"
470+
471+
ticket {
472+
number = "1"
473+
system = "example ticket system"
474+
}
475+
}
476+
`, r.template(data), data.RandomInteger, data.Locations.Primary)
477+
}

website/docs/r/pim_eligible_role_assignment.html.markdown

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ The following arguments are supported:
9898

9999
* `ticket` - (Optional) A `ticket` block as defined below. Changing this forces a new resource to be created.
100100

101+
102+
* `condition` - (Optional) The condition that limits the resources that the role can be assigned to. See the [official conditions documentation](https://learn.microsoft.com/en-us/azure/role-based-access-control/conditions-overview#what-are-role-assignment-conditions) for details. Changing this forces a new resource to be created.
103+
104+
* `condition_version` - (Optional) The version of the condition. Supported values include `2.0`. Changing this forces a new resource to be created.
105+
106+
~> **NOTE:** `condition_version` is required when specifying `condition` and vice versa.
107+
101108
---
102109

103110
An `expiration` block supports the following:

0 commit comments

Comments
 (0)