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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_role_definition continually being replaced #7549

Open
dutsmiller opened this issue Jul 1, 2020 · 17 comments
Open

azurerm_role_definition continually being replaced #7549

dutsmiller opened this issue Jul 1, 2020 · 17 comments

Comments

@dutsmiller
Copy link
Contributor

dutsmiller commented Jul 1, 2020

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

Description

Since v2.16.0 I find that my azurerm_role_definition resources are always being replaced during any subsequent terraform apply. Here is some basic code that can demonstrate the issue:

provider "azurerm" {
  version = "=2.16.0"
  features {}
}
resource "azurerm_resource_group" "rg" {
  name     = "roletest216"
  location = "eastus2"
}
resource "azurerm_role_definition" "role" {
  name        = "roletest216"
  description = "testing roles"
  scope       = azurerm_resource_group.rg.id
  permissions {
    actions     = ["Microsoft.Network/dnszones/TXT/read"]
  }
  assignable_scopes = [azurerm_resource_group.rg.id]
}

When that is initially applied, everything is fine. On the next apply it wants to replace the role. This is repeated on subsequent apply thereafter.

 azurerm_role_definition.role must be replaced
-/+ resource "azurerm_role_definition" "role" {
        assignable_scopes  = [
            "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/roletest216",
        ]
        description        = "testing roles"
      ~ id                 = "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/00000000-0000-0000-0000-000000000000" -> (known after apply)
        name               = "roletest216"
      ~ role_definition_id = "00000000-0000-0000-0000-000000000000" -> (known after apply)
      ~ scope              = "/subscriptions/00000000-0000-0000-0000-000000000000" -> "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/roletest216" # forces replacement
      ~ permissions {
            actions          = [
                "Microsoft.Network/dnszones/TXT/read",
            ]
          - data_actions     = [] -> null
          - not_actions      = [] -> null
          - not_data_actions = [] -> null
        }
    }

Plan: 1 to add, 0 to change, 1 to destroy.
@logachev
Copy link
Contributor

logachev commented Jul 2, 2020

It looks like a side effect of this pr: #7424

Just looking at how Azure handles Role Definitions, it seems like they always belong to management group or subscription. Resource Groups or other resources can be configured via assignable scope, but the Role Definition itself belongs to the subscription level.

Looking at Role Definition ID, confirms this: /subscriptions/34193999-d592-4f14-8bb0-bba535d3731c/providers/Microsoft.Authorization/roleDefinitions/509845ef-15d6-9998-129c-cc7f2ca31211

So, the issue is that scope property allows to set something else..

@dutsmiller for your specific example, if you set scope="/subscriptions/00000000-0000-0000-0000-000000000000", it will fix the problem.

@juanjojulian
Copy link
Contributor

Very similar behaviour here since 2.16, in my case scope is a management group instead of a resource group but terraform tries to modify it anyway although its already configured in the state file with that same scope:

      + scope              = "/providers/Microsoft.Management/managementGroups/MyManagementGroup" # forces replacement
resource "azurerm_role_definition" "Network_Reader" {
  name        = "Network_Reader"
  scope       = azurerm_management_group.MyManagementGroup.id
  description = "Custom Network Reader, allowed to read all network resources"

  permissions {
    actions     = ["Microsoft.Network/*/read"]
    not_actions = []
  }

  assignable_scopes = [azurerm_management_group.MyManagementGroup.id]
}

Downgrading to 2.15 the problem disappears.

@jibonilla03
Copy link

I experience same problem, after successfully provisioning, if I run a plan it shows it will be replaced

Terraform v0.12.28
provider.azurerm v2.17.0

-/+ destroy and then create replacement

Terraform will perform the following actions:

  # azurerm_role_definition.custom must be replaced
-/+ resource "azurerm_role_definition" "custom" {
        assignable_scopes  = [
            "/providers/Microsoft.Management/managementGroups/GBSCloud",
        ]
        description        = "This is a custom role created via Terraform"
      ~ id                 = "/providers/Microsoft.Authorization/roleDefinitions/0701d53f-a29b-3947-4183-7e65d17f3636" -> (known after apply)
        name               = "Custom Log Analytics"
        role_definition_id = "0701d53f-a29b-3947-4183-7e65d17f3636"
      + scope              = "/providers/Microsoft.Management/managementGroups/GBSCloud" # forces replacement

      ~ permissions {
            actions          = [
                "*/read",
                "Microsoft.OperationalInsights/workspaces/analytics/query/action",
                "Microsoft.OperationalInsights/workspaces/search/action",
                "Microsoft.Insights/AlertRules/Throttled/Action",
                "Microsoft.Insights/AlertRules/Resolved/Action",
                "Microsoft.Insights/AlertRules/Activated/Action",
                "Microsoft.Insights/AlertRules/Read",
                "Microsoft.Insights/AlertRules/Delete",
                "Microsoft.Insights/AlertRules/Write",
            ]
          - data_actions     = [] -> null
            not_actions      = [
                "Microsoft.OperationalInsights/workspaces/sharedKeys/read",
            ]
          - not_data_actions = [] -> null
        }
    }

Plan: 1 to add, 0 to change, 1 to destroy.
resource "random_uuid" "role_definition_id" { }

// Manages a custom Role Definition, used to assign Roles to Users/Principals. Example: Custom Log Analytics Reader and Alert
resource "azurerm_role_definition" "custom" {
  role_definition_id = random_uuid.role_definition_id.result
  name               = var.role_definition_name
  scope              = data.azurerm_management_group.gbs_cloud.id
  description        = var.role_definition_description

  permissions {
    actions     = var.role_actions
    not_actions = var.role_not_actions
  }

  assignable_scopes = [
    data.azurerm_management_group.gbs_cloud.id, # /providers/Microsoft.Management/managementGroups/myGroup
  ]

   lifecycle {
    ignore_changes = [
      role_definition_id,
    ]
  }
}

@ukphillips
Copy link

ukphillips commented Jul 14, 2020

Also experiencing this issue with 2.16 +

Terraform v0.12.28
provider.azurerm v2.17.0

With no changes to the resource it appears to be changing the scope, both assignable scopes and scope property are set to the same value which is a data resource for a resource group and the id property. It looks like the scope previously was missing the removing the resource group portion of the id!?

-/+ resource "azurerm_role_definition" "cool-role" {
        assignable_scopes  = [
            "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myrg",
        ]
        description        = "My Cool Role"
      ~ id                 = "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/roleDefinitions/00000000-0000-0000-0000-000000000000" -> (known after apply)
        name               = "my-role"
      ~ role_definition_id = "00000000-0000-0000-0000-000000000000" -> (known after apply)
      ~ scope              = "/subscriptions/00000000-0000-0000-0000-000000000000" -> "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myrg" # forces replacement

      ~ permissions {
            actions          = [
                "Microsoft.Resources/deployments/*",
                "Microsoft.Resources/subscriptions/resourceGroups/read",
                "Microsoft.ApiManagement/service/apis/write",
            ]
          - data_actions     = [] -> null
            not_actions      = []
          - not_data_actions = [] -> null
        }
    }

Incidentally the scope in the state file is already /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myrg, so I'm not sure why it thinks it needs to update it FROM /subscriptions/00000000-0000-0000-0000-000000000000

@matthias50
Copy link

Taking the hint from @logachev, I was able to work around this by explicitly setting the scope to match the reality that role definitions are at the subscription scope. So something like:

scope       = data.azurerm_subscription.primary.id

Note that there is no suffix for the resource group. This is what I had before and I am guessing azurerm just ignored everything after the subscription in the scope field. The assignable_scopes I left alone and reference, in my case a single resource group. After I made this change, with azurerm v2.18.0, I no longer saw any references to spurious role changes in the plan output.

@arnefromsa
Copy link

We are experience this same issue.

Our definitions lives in the top management group, thsu we need to scope to be a management group. Even though the scope is the same in state file and in the submitted apply, it still does a "#forces replacement" on the scope attribute.

Even changing to 2.15 does not work.

@arnefromsa
Copy link

We are experience this same issue.

Our definitions lives in the top management group, thsu we need to scope to be a management group. Even though the scope is the same in state file and in the submitted apply, it still does a "#forces replacement" on the scope attribute.

Even changing to 2.15 does not work.

Hi guys, I actually managed to fix this and working. Remember Custom Roles live at a global scope.
By setting scope="" (empty string) it worked and I am now able to update the custom roles successfully.

scope = ""

@juanjojulian
Copy link
Contributor

Thanks @arnefromsa

This workaround works for me, now I can make use of azurerm version past 2.15.

@MarkBooks
Copy link

Thanks @arnefromsa! Setting scope = "" worked for us to prevent the role being destroyed & recreated every time.

@rapster83
Copy link

rapster83 commented Sep 7, 2020

Thx guy, that worked for me as well for permissions on Azure Management Groups!

@DanielFrei64
Copy link

Although leaving the scope blank did work for me running it manually as my user account, when I run it via a service principal, which is assigned owner permissions on the tenant root management group, which is the same permission level my account is, I receive this message:
Error: authorization.RoleDefinitionsClient#CreateOrUpdate: Failure responding to request: StatusCode=403 -- Original Error: autorest/azure: Service returned an error. Status=403 Code="AuthorizationFailed" Message="The client 'xxxxxxxx-8e4e-4431-b245-1e00ee264b17' with object id 'xxxxxxxx-8e4e-4431-b245-1e00ee264b17' does not have authorization to perform action 'Microsoft.Authorization/roleDefinitions/write' over scope '/providers/Microsoft.Authorization/roleDefinitions/35c24ff0-b3f4-4563-aee0-0c9805459702' or the scope is invalid. If access was recently granted, please refresh your credentials."

on modules/rbac/roles.tf line 3, in resource "azurerm_role_definition" "roleoscmp":
3: resource "azurerm_role_definition" "roleoscmp" {

If I add the scope back in, the service principal is able to add the role definition, but we get stuck in the same loop where it wants to remove and re-add the definition on every run. Which from a permission standpoint, the service principal can do without a problem, but is obviously not ideal.

@rapster83
Copy link

On MG level I have the same issue. But I cannot offer you a solution. I don't know why on MG there is an issue to delete and recreate the role definition. The service principal has "full access" permissions. Any ideas?

@juanjojulian
Copy link
Contributor

Well, now with new provider version 2.27.0 all azurerm_role_definition where the scope was empty are failing with the following error when refreshing state during plan:

Error: failed to migrate state: scope missing

I don't see a way to fix it.

@DanielFrei64
Copy link

Yeah, this is still an issue for me, but @juanjojulian This is what I'd doing to get past this.. for me, the scope where the role assignment is located is really never going to change, so I simply put
lifecycle {
ignore_changes = [
scope
]
}
in the role definition block and that allowed me to get past this. Not the best but it gets me past it.

@petr-stupka
Copy link
Contributor

Error: failed to migrate state: scope missing

I solved it by editing the state where azurerm_role_definition have scope = ""

As per docu, it is recommended to use the first entry of the assignable_scopes.

@rapster83
Copy link

I am still having the same issue:

Terraform v0.13.2
+ provider registry.terraform.io/hashicorp/azurerm v2.32.0

Using the following parameter values:
Json-Exmaple

Still getting the following error: Error: failed to migrate state: scope missing

Any ideas or recommenations? Thx

@torbendury
Copy link

Getting the same behavior with azurerm_role_assignment, azurerm 2.93.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests