This utility allows to automatically purchase Azure Reserved Instances via simplified PowerShell script.
There is one managed identity, one storage account, and 3 logic apps
The user-assigned managed identity (MI) is used across the utility to grant access to Azure. The MI is granted access as Reader on the Tenant Root Group level (to be able to find approved subscriptions), granted Storage Table Data Contributor to the storage account (to read and write approved subscriptions), granted 'Reservations Contributor' to the 'Reserveations' to be able to make RI purchases. On the other hand, the three logic apps have the 'Identities' set to use this MI so that they can impersonate the access the MI has.
The Azure Storage Account uses Azure Tables only. The storage account is used to keep a list of approved Azure Subscriptions that can be used by the client when providing billing scope. The Azure Storage Table has empty schema (with no data) and only the Partition Key and Row ID are used as the Subscription ID for each of the approved subscription.
The utility can be restricted to allow purchase of RIs under a specific billing scope only.
The list of approved subscriptions that can be used as an approved billing scope can be automatically maintained using another provided logic app, which takes argument of a parent Management Group and all subscriptions underneath are automatically added to the approved list of subscriptions where an RI purchase can be made.
The HTTP calls to the Logic App to invoke calculate/purchase API can be made using the provided PowerShell script.
In order to deploy, you can deploy using the ARM template using the button below. Then use the below steps to set it up.
- Grant managed identity RBAC of 'Reader' over Tenant Root Group.
- Grant managed identity RBAC of 'Reservations Contributor' under 'Reservations' blade.
- Open each of the 3 logic app and update the HTTP Request object to use the newly created managed identity under the HTTP Request step when authenticating.
.\AzureReservation.ps1 -Operation CreateReservation -SkuName "Standard_B1s" -Location "eastus" -Term "P1Y" -Quantity 1 -BillingScopeId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -AppliedScopeType "Shared" -AppliedScopes "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -logicAppUrl "https://xxxxxx.azure.com:443/workflows/xxxxxxxxxxxxxxxxxx2/triggers/When_a_HTTP_request_is_received/..." -Verbose Output is the Order ID. Take note of this and use it in the next command
Reservation Order ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.\AzureReservation.ps1 -Operation PurchaseReservation -ReservationOrderId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -SkuName "Standard_B1s" -Location "eastus" -Term "P1Y" -Quantity 1 -BillingScopeId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -AppliedScopeType "Shared" -AppliedScopes "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -logicAppUrl "https://xxxxxx.azure.com:443/workflows/xxxxxxxxxxxxxxxxxx2/triggers/When_a_HTTP_request_is_received/..." -VerboseConfirm purchase
Are you sure you want to purchase the reservation? (Y/N) y