Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_pim_eligible_role_assignment 400 error when using null or empty schedule block #22766

Closed
1 task done
MohnJadden opened this issue Aug 1, 2023 · 24 comments · Fixed by #25900
Closed
1 task done

Comments

@MohnJadden
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment and review the contribution guide to help.

Terraform Version

1.5.3

AzureRM Provider Version

3.67.0

Affected Resource(s)/Data Source(s)

azurerm_pim_eligible_role_assignment

Terraform Configuration Files

variable "teams" {
  type = map(object({
    team_name            = string
    location             = string
    Owner                = string
    TechnicalContact     = string
    SecurityGroup        = string
    DepartmentName       = string
    City                 = string
    ApplicationGroupType = string
    ApplicationType      = string
    LoadBalancerType     = string
    VDIType = string
    MaximumSessions      = number
  }))
}

resource "azurerm_resource_group" "vdi-rg" {
  for_each = var.teams
  name     = "${each.value.team_name}-VDI"
  location = coalesce(each.value.location, each.key)
  tags = {
    Owner            = coalesce(each.value.Owner, each.key)
    TechnicalContact = coalesce(each.value.TechnicalContact, each.key)
    Location         = coalesce(each.value.City, each.key)
    DepartmentName   = coalesce(each.value.DepartmentName, each.key)
    TeamName         = coalesce(each.value.team_name, each.key)
  }
}

resource "azurerm_pim_eligible_role_assignment" "role-vdi-vmadminpim" {
    for_each             = var.teams
  scope                = "/subscriptions/3f51eae4-8db3-468d-a09d-cb67d67630b4/resourceGroups/${azurerm_resource_group.vdi-rg[each.key].name}"
  role_definition_id = "/subscriptions/3f51eae4-8db3-468d-a09d-cb67d67630b4/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4"
  principal_id       = coalesce(each.value.SecurityGroup, each.key)

  timeouts {
    create = "10m"
    delete = "10m"
  }
     lifecycle {
    ignore_changes = [
      # Ignore changes to the Schedule block.  It won't take nulls as inputs and we assume that these PIM assignments are meant to live as long as the VDI environment.
      schedule
    ]
  }
}

Debug Output/Panic Output

{"error":{"code":"RoleAssignmentRequestPolicyValidationFailed","message":"The following policy rules failed: [\"ExpirationRule\"]"}}: timestamp=2023-08-01T14:39:22.604-0400
2023-08-01T14:39:22.604-0400 [ERROR] provider.terraform-provider-azurerm_v3.67.0_x5.exe: Response contains error diagnostic: tf_req_id=15f63ca5-4bae-bb46-8ed2-2225d57fce01 diagnostic_detail="waiting for Role Management Policy: (Principal Id "01b95094-3727-42de-9bfe-f1bd55734554" / Scope "/subscriptions/ourSubscriptionGUID/resourceGroups/rgName" / Role Definition Id "/subscriptions/ourSubscriptionGUID/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4") to be created: creating Scoped Role Eligibility Schedule Request (Scope: "/subscriptions/ourSubscriptionGUID/resourceGroups/rgName"
Role Eligibility Schedule Request Name: "596b4579-6944-e996-1f2b-e1b5fbdcb67a"): unexpected status 400 with error: RoleAssignmentRequestPolicyValidationFailed: The following policy rules failed: ["ExpirationRule"]" diagnostic_severity=ERROR tf_proto_version=5.3 tf_provider_addr=provider tf_resource_type=azurerm_pim_eligible_role_assignment tf_rpc=ApplyResourceChange @caller=github.com/hashicorp/terraform-plugin-go@v0.14.3/tfprotov5/internal/diag/diagnostics.go:55 @module=sdk.proto diagnostic_summary="waiting for Role Management Policy: (Principal Id "01b95094-3727-42de-9bfe-f1bd55734554" / Scope "/subscriptions/ourSubscriptionGUID/resourceGroups/rgName" / Role Definition Id "/subscriptions/ourSubscriptionGUID/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4") to be created: creating Scoped Role Eligibility Schedule Request (Scope: "/subscriptions/ourSubscriptionGUID/resourceGroups/rgName"
Role Eligibility Schedule Request Name: "596b4579-6944-e996-1f2b-e1b5fbdcb67a"): unexpected status 400 with error: RoleAssignmentRequestPolicyValidationFailed: The following policy rules failed: ["ExpirationRule"]" timestamp=2023-08-01T14:39:22.604-0400
2023-08-01T14:39:22.606-0400 [DEBUG] State storage *remote.State declined to persist a state snapshot
2023-08-01T14:39:22.606-0400 [ERROR] vertex "azurerm_pim_eligible_role_assignment.role-vdi-vmadminpim[\"Team12\"]" error: waiting for Role Management Policy: (Principal Id "01b95094-3727-42de-9bfe-f1bd55734554" / Scope "/subscriptions/ourSubscriptionGUID/resourceGroups/rgName" / Role Definition Id "/subscriptions/ourSubscriptionGUID/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4") to be created: creating Scoped Role Eligibility Schedule Request (Scope: "/subscriptions/ourSubscriptionGUID/resourceGroups/rgName"
Role Eligibility Schedule Request Name: "596b4579-6944-e996-1f2b-e1b5fbdcb67a"): unexpected status 400 with error: RoleAssignmentRequestPolicyValidationFailed: The following policy rules failed: ["ExpirationRule"]
2023-08-01T14:39:22.609-0400 [DEBUG] provider.terraform-provider-azurerm_v3.67.0_x5.exe: AzureRM Response for https://management.azure.com/subscriptions/ourSubscriptionGUID/resourceGroups/rgName/providers/Microsoft.DesktopVirtualization/workspaces/MTDJumpbox-workspace?api-version=2022-02-10-preview: 
HTTP/2.0 200 OK
Cache-Control: no-cache
Content-Type: application/json; charset=utf-8
Date: Tue, 01 Aug 2023 18:39:22 GMT
Expires: -1
Pragma: no-cache
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=70e38c1ed72db5f7ffb204484a71ad78c423ea1a8a3bd749fefcc9c77560a9e4;Path=/;HttpOnly;Secure;Domain=rdarmprovider-g-us-r0.wvd.microsoft.com
Set-Cookie: ARRAffinitySameSite=70e38c1ed72db5f7ffb204484a71ad78c423ea1a8a3bd749fefcc9c77560a9e4;Path=/;HttpOnly;SameSite=None;Secure;Domain=rdarmprovider-g-us-r0.wvd.microsoft.com
Strict-Transport-Security: max-age=31536000; includeSubDomains
Vary: Accept-Encoding,Accept-Encoding
X-Content-Type-Options: nosniff
X-Ms-Correlation-Id: 1d896bed-0d5a-45f7-ae79-c4d750973911
X-Ms-Correlation-Request-Id: 659d0fb3-bdf6-95a8-8b49-f1a84a113662
X-Ms-Lamport-Ts: 4474978300
X-Ms-Opsarmpath64: L3N1YnNjcmlwdGlvbnMvM2Y1MWVhZTQtOGRiMy00NjhkLWEwOWQtY2I2N2Q2NzYzMGI0L3Jlc291cmNlR3JvdXBzL01UREp1bXBib3gtVkRJL3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVza3RvcFZpcnR1YWxpemF0aW9uL3dvcmtzcGFjZXMvTVRESnVtcGJveC13b3Jrc3BhY2U=
X-Ms-Ratelimit-Remaining-Subscription-Reads: 11999
X-Ms-Request-Id: 15593fae-ccf4-4bc6-9040-2e4a9c4f28f8
X-Ms-Routing-Request-Id: EASTUS:20230801T183922Z:ec7d62d7-3fa1-45ab-bb1b-2d2983b2620c
X-Powered-By: ASP.NET
X-Rate-Limit-Limit: 0
X-Rate-Limit-Remaining: 9223372036854775807
X-Rate-Limit-Reset: 0

Expected Behaviour

Terraform should create an Azure AD PIM eligible role with no expiration date/time.

Actual Behaviour

Terraform throws an error:
│ Role Eligibility Schedule Request Name: "596b4579-6944-e996-1f2b-e1b5fbdcb67a"): unexpected status 400 with error: RoleAssignmentRequestPolicyValidationFailed: The following policy rules failed: ["ExpirationRule"]

│ with azurerm_pim_eligible_role_assignment.role-vdi-vmadminpim["Team12"],
│ on AzureVDI.tf line 56, in resource "azurerm_pim_eligible_role_assignment" "role-vdi-vmadminpim":
│ 56: resource "azurerm_pim_eligible_role_assignment" "role-vdi-vmadminpim" {

│ waiting for Role Management Policy: (Principal Id "01b95094-3727-42de-9bfe-f1bd55734554" / Scope "/subscriptions/ourSubscriptionGUID/resourceGroups/rgName" / Role Definition Id
│ "/subscriptions/ourSubscriptionGUID/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4") to be created: creating Scoped Role Eligibility Schedule
│ Request (Scope: "/subscriptions/ourSubscriptionGUID/resourceGroups/rgName"
│ Role Eligibility Schedule Request Name: "596b4579-6944-e996-1f2b-e1b5fbdcb67a"): unexpected status 400 with error: RoleAssignmentRequestPolicyValidationFailed: The following policy rules failed:
│ ["ExpirationRule"]

Steps to Reproduce

  1. Run terraform apply
  2. Error occurs

Important Factoids

No response

References

Possibly related to #22608 - that threw a 400 error but with different error text.

@MohnJadden
Copy link
Author

The issue still occurs in 3.68.

@MohnJadden
Copy link
Author

The issue is still occurring in 3.70.

@MohnJadden
Copy link
Author

Still occurring in 3.71.

@MohnJadden
Copy link
Author

Still occurring in 3.72.

@MohnJadden
Copy link
Author

Still occurring in 3.73. @manicminer could I trouble you for a rough idea on when this will be worked on?

@IntergalacticBVBA
Copy link

Hi @MohnJadden
If you configure the PIM elegible assignment via the Azure Portal, you get the following restriction.
"Maximum allowed eligible duration is 1 year(s)."

@MohnJadden
Copy link
Author

@IntergalacticBVBA By default, it's 1 year, but in the settings for a scope, you can allow permanent membership. In our case, all the resource groups we're trying to have TF manage are already enabled for permanent membership - example of one below.

image

@ynden
Copy link

ynden commented Oct 4, 2023

@IntergalacticBVBA By default, it's 1 year, but in the settings for a scope, you can allow permanent membership. In our case, all the resource groups we're trying to have TF manage are already enabled for permanent membership - example of one below.

image

Hey @MohnJadden,

I think this is why you are experiencing this issue.
Reading your terraform code, I see that you are creating a resource group and then applying a PIM eligible assignment on that resource group.

What @IntergalacticBVBA was mentioning is true, and what you were showing in the screenshot is also true. The question is how could you still have the issue then?

What's happening is that you are creating a new resource group, and then try to apply a PIM on that scope. But that scope (i.e: resource group scope) doesn't have the "Permanent eligible assigment" enabled. What you were showing on your screenshot, was probably at the subscription level, but it should be at the resource group level.

If you go check on the PIM, filter by resource group, then you can check the "Allow permanent eligible" should be disabled, hence why the terraform is failing; because at the creation of the resource group, the option is not enabled.

When you enable the option at the subscription level, the resources below don't inherit it. It's really a 1 x 1 relation. If you create a PIM assignment at the subscription level, only that specific subscription has that option enabled, but not the resources below it (i,.e: resource, or resource group).

If you enable "Permanent eligibility" at the subscription level, and add a PIM at the resource group level, the resource group won't have that option, unless you enable it explicitly.

Hope that makes sense, you can confirm once you check please.

Thanks

@MohnJadden
Copy link
Author

@ynden That nailed it on the head. In the past I'd enabled permanent assignments for other resource groups, but the test RG did not have permanent assignment enabled.

After enabling permanent assignment, the error did not persist, and the PIM eligible role assignment completed successfully.

Unfortunately this reveals a bit of a flaw in that we now have to create the RG, navigate manually to it in the Azure portal (there is no support for this in the CLI as far as I can tell), enable permanent assignment, and then create the azurerm_pim_eligible_role. Since the default maximum time limit is 1 year, we'd have to do something to configure the azurerm_pim_eligible_role schedule block to operate on an end date of current date + 364 days and have it update the role every time we run terraform apply, or configure some other form of automation to keep extending the renewal date.

Would this be a separate issue to request the role settings eligibility to be added to TF or is this issue enough to cover it?

@ynden
Copy link

ynden commented Oct 4, 2023

@ynden That nailed it on the head. In the past I'd enabled permanent assignments for other resource groups, but the test RG did not have permanent assignment enabled.

After enabling permanent assignment, the error did not persist, and the PIM eligible role assignment completed successfully.

Unfortunately this reveals a bit of a flaw in that we now have to create the RG, navigate manually to it in the Azure portal (there is no support for this in the CLI as far as I can tell), enable permanent assignment, and then create the azurerm_pim_eligible_role. Since the default maximum time limit is 1 year, we'd have to do something to configure the azurerm_pim_eligible_role schedule block to operate on an end date of current date + 364 days and have it update the role every time we run terraform apply, or configure some other form of automation to keep extending the renewal date.

Would this be a separate issue to request the role settings eligibility to be added to TF or is this issue enough to cover it?

Amazing, glad it worked!

Yeah this is true, there would be a need to do it manually for every scope. When we talk about subscription, it's ok, but at the resource group level, it's when it becomes problematic.

Would this be a separate issue to request the role settings eligibility to be added to TF or is this issue enough to cover it?

I think it's another issue, because this needs to be done at a scope level, for a specific role. Like:

  1. Create the resource group
  2. Enable the permanent eligible for the resource group for a specific role
  3. Enable PIM for resource group

So the way I see it, is that it needs to have its own resource type.

@MohnJadden
Copy link
Author

@ynden You're right, this does merit having a separate TF resource. I opened a request; hopefully it gets considered quickly.

Failing that, @manicminer - as a stopgap/bridge fix, would there possibly be a way to implement more clarification on the TF error for this issue? The 400/ExpirationRule error doesn't say why the expiration rule failed; maybe a generic error that says "please make sure you are assigning a PIM eligible role within the settings for the scope" or otherwise would help other folks that might get the issue in the future.

@Darkfogel
Copy link

Doing some piggyback on what @MohnJadden is experiencing, we are currently doing our PIM assignements / enabling elligilibity through a null resource and api calls. For each PIM call, we check is the isExpirationRequired is configured, if not, we change it. Then we do the PIM assignment.

@ynden Can you explain why it'd be better to have a new ressource type for this? The way I see it, using the PIM assignment resource block, having a option block for the role/resource to configure the PIM policy would make sense.

By seperating them, you would have to create multiple resource for each role configured for a particular resource and have the PIM assignment resource block depends on the specific PIMPolicy.

Example of a possible terraform resource block :

resource "azurerm_pim_eligible_role_assignment" "role_rg_owner" {
  scope                = ## Scope
  role_definition_id   = ##ID of the owner role##
  principal_id         = ## Principal ID

  pim_policy_block {
    isExpirationRequired = false
  }
}

Additionals options from the API could be added if needed.

@MohnJadden
Copy link
Author

@Darkfogel I could see a situation where the same people who are setting PIM role settings aren't the same people creating PIM eligible role assignments. I've been in megacorps where the decision/permission to change PIM settings for an Azure subscriptions rests with Team X, while Team Y has permissions to add new PIM users or groups to the subscription. Team X's responsibility is risk management/security, Team Y is engineering, and it's logical in this case that Team Y shouldn't be dictating what happens to Team X's resources without approval.

Team Y's accounts or TF service principals/app registrations/pipelines may not have User Access Administrator or equivalent rights to change settings (likely through some horrible custom role) or they may get flagged if they take actions which attempt to change the settings in logs. Thus, if Terraform says "this PIM assignment needs to last for 3 years" and company policy is "max assignment length is 1 year with annual review", Team Y's TF would have a fixed assignment start/end which would need to be updated every year.

It's a really awful use case and I can't stand that I'm advocating for it, but to me it makes sense to have separate TF resources for this: one that says what you can/cannot do with PIM as policy, and one that creates PIM assignments.

@ynden
Copy link

ynden commented Oct 5, 2023

@ynden Can you explain why it'd be better to have a new ressource type for this? The way I see it, using the PIM assignment resource block, having a option block for the role/resource to configure the PIM policy would make sense.

By seperating them, you would have to create multiple resource for each role configured for a particular resource and have the PIM assignment resource block depends on the specific PIMPolicy.

Example of a possible terraform resource block :

resource "azurerm_pim_eligible_role_assignment" "role_rg_owner" {
  scope                = ## Scope
  role_definition_id   = ##ID of the owner role##
  principal_id         = ## Principal ID

  pim_policy_block {
    isExpirationRequired = false
  }
}

Additionals options from the API could be added if needed.

Hey @Darkfogel,

It's a great question, and you might be right actually. The reason I suggested two resources, is because Azure separates them at the API & ARM level.

The azurerm_pim_eligible_role_assignment terraform resource is mapped to Microsoft.Authorization/roleEligibilityScheduleRequests in Azure API.

The isExpirationRequired property would be coming from the Azure API resource called: Microsoft.Authorization/roleManagementPolicies (which is a different resource).

For practical reason we can have the azurerm_pim_eligible_role_assignment terraform resource update the roleManagementPolicies associated to the scope of the resource & role definition behind the scenes.

And/Or have a specific terraform resource, something like: azurerm_pim_role_management_policy where you can modify the PIM role policy.

@NasoA
Copy link

NasoA commented Nov 9, 2023

Still a problem, will this be fixed in any upcoming releases?

@rstewart89
Copy link

navigate manually to it in the Azure portal (there is no support for this in the CLI as far as I can tell)

Is there any other option to enable this other than manually navigating to the portal? you mentioned nothing in the CLI but is there any API calls we could use?

@MohnJadden
Copy link
Author

Is there any other option to enable this other than manually navigating to the portal? you mentioned nothing in the CLI but is there any API calls we could use?

It's buried in here: https://learn.microsoft.com/en-us/graph/api/unifiedrolemanagementpolicy-update?view=graph-rest-1.0&tabs=http Look for unifiedRoleManagementPolicyExpirationRule

Now the trick is getting TF to do this using modules and not a hodgepodge of API calls.

@manicminer
Copy link
Contributor

Is there any other option to enable this other than manually navigating to the portal? you mentioned nothing in the CLI but is there any API calls we could use?

It's buried in here: https://learn.microsoft.com/en-us/graph/api/unifiedrolemanagementpolicy-update?view=graph-rest-1.0&tabs=http Look for unifiedRoleManagementPolicyExpirationRule

Now the trick is getting TF to do this using modules and not a hodgepodge of API calls.

This functionality would need to go into the AzureAD provider as it uses MS Graph.

@MohnJadden
Copy link
Author

Is there any other option to enable this other than manually navigating to the portal? you mentioned nothing in the CLI but is there any API calls we could use?

It's buried in here: https://learn.microsoft.com/en-us/graph/api/unifiedrolemanagementpolicy-update?view=graph-rest-1.0&tabs=http Look for unifiedRoleManagementPolicyExpirationRule
Now the trick is getting TF to do this using modules and not a hodgepodge of API calls.

This functionality would need to go into the AzureAD provider as it uses MS Graph.

Counterpoint: this is an Azure resource role, and the PIM setting affects Azure resource roles. It's functionality that should be related to the azurerm provider; without trying to sound like a jerk, it shouldn't matter to me what has to be called as long as Terraform can manage it.

Since it's stopping azurerm_pim_eligible_role_assignment from functioning in a usable way if we want any roles to be eligible for longer than 365 days, it merits fixing in some way. Is there some way to bring this issue and #23458 to the attention of the team who works on AzureAD or is there an internal process that TF/MS uses to put it on the roadmap?

@xuzhang3
Copy link
Contributor

xuzhang3 commented Dec 4, 2023

@MohnJadden you need to update the role policy to allow permeant assignments. You can check the role setting details:

image

@MohnJadden
Copy link
Author

@xuzhang3 The problem is there's no way to do that with Terraform yet. If we're using PIM just for a resource group which is being created by Terraform, we have to create the RG, manually edit the role assignment policy at the RG scope, and then add the PIM role via Terraform.

@xuzhang3
Copy link
Contributor

xuzhang3 commented Dec 6, 2023

@manicminer #23295 will support manage role polies.

@drdamour
Copy link
Contributor

fwiw, IMO it seems like the issue reported here isn't actually an issue and its' working exactly as it should. and this should probably be closed.

but the feature request spawned from this convo #23458 (so close to 23456 :D) def has merit and appears to have a proposed solution with #23295

thanks for having this thread and being vigilant about it @MohnJadden it really caught me up with my ability to leverage PIM in our terraform only azure stuff which is as of now...a no u can't.

Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants