Azure / terraform-azurerm-lz-vending

Terraform module to deploy landing zone subscriptions (and much more) in Azure
https://registry.terraform.io/modules/Azure/lz-vending/azurerm
MIT License
152 stars 66 forks source link

bug: Budgets provisioning fails with "RBACAccessDenied" #394

Open nekdima opened 1 week ago

nekdima commented 1 week ago

Community Note

Versions

Please paste the output of terraform version command from within the initialized directory:

Terraform v1.8.5 on darwin_arm64

Please enter the module version that you are using:

Module 4.2.1

Description

Steps to Reproduce

Use this config in main.tf:

  budget_enabled = true
  budgets        = var.subscription_budgets

variables.tf file content(default one, from example):

variable "subscription_budgets" {
  type = map(object({
    amount            = number
    time_grain        = string
    time_period_start = string
    time_period_end   = string
    relative_scope    = optional(string, "")
    notifications = optional(map(object({
      enabled        = bool
      operator       = string
      threshold      = number
      threshold_type = optional(string, "Actual")
      contact_emails = optional(list(string), [])
      contact_roles  = optional(list(string), [])
      contact_groups = optional(list(string), [])
      locale         = optional(string, "en-us")
    })), {})
  }))
  default = {
    budget1 = {
      amount            = 150
      time_grain        = "Monthly"
      time_period_start = "2024-06-01T00:00:00Z"
      time_period_end   = "2027-12-31T23:59:59Z"
      notifications = {
        eightypercent = {
          enabled        = true
          operator       = "GreaterThan"
          threshold      = 80
          threshold_type = "Actual"
          contact_emails = ["john@contoso.com"]
        }
        budgetexceeded = {
          enabled        = true
          operator       = "GreaterThan"
          threshold      = 120
          threshold_type = "Forecasted"
          contact_groups = ["Owner"]
        }
      }
    }
  }
}

Screenshots

image

Additional context

SPN roles config: RBAC Owner on the parent MG EA: Subscription Creator as described here: https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/assign-roles-azure-service-principals#permissions-that-can-be-assigned-to-the-service-principal

Vending is being used on top of the latest ESLZ 6.0.0

matt-FFFFFF commented 1 week ago

Please can you log in using that SPN using az cli and try and create the budget:

https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?tabs=clibudget#create-and-edit-budgets

Many thanks

nekdima commented 1 week ago

@matt-FFFFFF Az Cli and Poweshell based instructions for budgets deployments are outdated. I've ended up deploying using ARM template (while being logged in using SPN) and it worked.

deployment screenshot image

ARM template used(no filter option): https://learn.microsoft.com/en-gb/azure/cost-management-billing/costs/quick-create-budget-template?tabs=no-filter%2CPowerShell#review-and-deploy-the-template

matt-FFFFFF commented 1 week ago

What do you mean the instructions are outdated?

An ARM template deployment isn't the same as a REST API call to create a budget resource. Hence the ask.

Please could you post the contents of the ARM template?

nekdima commented 1 week ago

What do you mean the instructions are outdated?

The PowerShell cmdlets and CLI commands used in the script are outdated, the script provided in the article doesn't work. Despite puzzling for some time I didn't manage to get it working.

Please could you post the contents of the ARM template?

ARM template used(no filter option): https://learn.microsoft.com/en-gb/azure/cost-management-billing/costs/quick-create-budget-template?tabs=no-filter%2CPowerShell#review-and-deploy-the-template Please see below as well.

An ARM template deployment isn't the same as a REST API call to create a budget resource

Sure, it's not the same but in the end permissions utilised by SPN will be the same regardless of doing an ARM template deployment, CLI or anything else afaik. I think that's the most important in this case since the initial error message was referring to the missing RBAC permissions when running azapi resource creation.

Many thanks for the troubleshooting assistance!

ARM Template:

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.26.54.24096",
      "templateHash": "10216192224502761212"
    }
  },
  "parameters": {
    "budgetName": {
      "type": "string",
      "defaultValue": "MyBudget",
      "metadata": {
        "description": "Name of the Budget. It should be unique within a resource group."
      }
    },
    "amount": {
      "type": "int",
      "defaultValue": 1000,
      "metadata": {
        "description": "The total amount of cost or usage to track with the budget"
      }
    },
    "timeGrain": {
      "type": "string",
      "defaultValue": "Monthly",
      "allowedValues": [
        "Monthly",
        "Quarterly",
        "Annually"
      ],
      "metadata": {
        "description": "The time covered by a budget. Tracking of the amount will be reset based on the time grain."
      }
    },
    "startDate": {
      "type": "string",
      "metadata": {
        "description": "The start date must be first of the month in YYYY-MM-DD format. Future start date should not be more than three months. Past start date should be selected within the timegrain preiod."
      }
    },
    "endDate": {
      "type": "string",
      "metadata": {
        "description": "The end date for the budget in YYYY-MM-DD format. If not provided, we default this to 10 years from the start date."
      }
    },
    "firstThreshold": {
      "type": "int",
      "defaultValue": 90,
      "metadata": {
        "description": "Threshold value associated with a notification. Notification is sent when the cost exceeded the threshold. It is always percent and has to be between 0.01 and 1000."
      }
    },
    "secondThreshold": {
      "type": "int",
      "defaultValue": 110,
      "metadata": {
        "description": "Threshold value associated with a notification. Notification is sent when the cost exceeded the threshold. It is always percent and has to be between 0.01 and 1000."
      }
    },
    "contactEmails": {
      "type": "array",
      "metadata": {
        "description": "The list of email addresses to send the budget notification to when the threshold is exceeded."
      }
    }
  },
  "resources": [
    {
      "type": "Microsoft.Consumption/budgets",
      "apiVersion": "2023-11-01",
      "name": "[parameters('budgetName')]",
      "properties": {
        "timePeriod": {
          "startDate": "[parameters('startDate')]",
          "endDate": "[parameters('endDate')]"
        },
        "timeGrain": "[parameters('timeGrain')]",
        "amount": "[parameters('amount')]",
        "category": "Cost",
        "notifications": {
          "NotificationForExceededBudget1": {
            "enabled": true,
            "operator": "GreaterThan",
            "threshold": "[parameters('firstThreshold')]",
            "contactEmails": "[parameters('contactEmails')]"
          },
          "NotificationForExceededBudget2": {
            "enabled": true,
            "operator": "GreaterThan",
            "threshold": "[parameters('secondThreshold')]",
            "contactEmails": "[parameters('contactEmails')]"
          }
        }
      }
    }
  ],
  "outputs": {
    "name": {
      "type": "string",
      "value": "[parameters('budgetName')]"
    },
    "resourceId": {
      "type": "string",
      "value": "[subscriptionResourceId('Microsoft.Consumption/budgets', parameters('budgetName'))]"
    }
  }
}