Last Update: Sep 04, 2024 | Published: Dec 06, 2016
In this post, I will show you how you can prevent delegated administrators from deploying unwanted & expensive large virtual machine sizes, which granting them access to deploy smaller machines.
One of the dangers, and understandable fears, about cloud services such as Azure is that IT as a utility makes it possible for IT people to go wild. I’ve seen it personally in my training courses, where a typical course should use maybe $50 of credit, but an attendee goes nuts and runs up a bill for hundreds of dollars. There are a few things we can do to control this, including:
But how do you enforce policies? Maybe you want to restrict people to certain kinds and sizes of virtual machines? For example, for a light workload, do people genuinely need to deploy D14 or GS5 virtual machines?
Azure Resource Manager (ARM) has a feature called ARM Policy; this can be used in a variety of ways, including:
It’s that last option that is the focus of this post. We can create a JSON file that describes what specs & sizes of virtual machines that can be deployed, and we can assign that policy to an Azure subscription or to a resource group.
The method for taking control of a subscription or a resource group is based on Azure Resource Manager JSON. A JSON can be build to describe what a user can or cannot do, or even to enforce certain configurations or naming standards. In this example, we want to limit what virtual machines can be deployed in the rg-accounting resource group to:
How did I get those naming standards? I ran an (Azure Resource Manager) PowerShell cmdlet specifying the Azure region that I want to work in:
Get-AzureRMVMSize -Location WestUS
Next we will build a JSON template using a tool such as the free VSCode. Open File > Preferences > User Settings, and enter the JSON schema details there.
{ "$schema": "http://schema.management.azure.com/schemas/2015-10-01-preview/policyDefinition.json" }
In VSCode, create a new file and type/paste in the below JSON. The file tells Azure:
{ "if": { "allOf": [ { "field": "type", "equals": "Microsoft.Compute/virtualMachines" }, { "not": { "field": "Microsoft.Compute/virtualMachines/sku.name", "in": ["Standard_A1","Standard_A2","Standard_D1_v2","Standard_F1"] } } ] }, "then": { "effect": "deny" } }
Save the file as a JSON file type –I saved my file as C:TempRestrictAzureVMs.json.
We need to upload the JSON file into Azure to define a new policy. Open a PowerShell prompt. Sign into Azure Resource Manager:
Login-AzureRMAccount
List your Azure subscriptions using the following:
Get-AzureRmSubscription
Note the ID of the Azure subscription that you want to work with, and select it. The subscription ID will be reused later, so I’m storing it in a variable:
$SubID = (Get-AzureRmSubscription -SubscriptionId 12345678-1234-1a34-abcd-a123bcd12345).SubscriptionId Select-AzureRmSubscription -SubscriptionId $SubID
Now we can upload the JSON file to define a new ARM policy called RestrictVMSizes:
$Policy = New-AzureRmPolicyDefinition -Name RestrictVMSizes -Description “Policy to restrict VM sizes to predefined SKUs” -Policy C:TempRestrictAzureVMs.json
You can view your new policy by running:
Get-AzureRmPolicyDefinition -Name RestrictVMSizes
It is possible to delegate administrative rights to non-subscription administrators. You can create a resource group, add users to a group, and then assign that group rights to the resource group. When the users sign into the Azure Portal, all that they can see is the resource group and its contents, and all they can do is what you have allowed them to do. But they can do it at any scale, unless you assign an ARM policy definition to the resource group.
Assigning a policy is easy; first, you will need the unique identifier of the resource group that you want to assign the policy to. In my example, I am working with a resource group called rg-accounting:
$RGID = (Get-AzureRmResourceGroup -Name "rg-accounting").ResourceID
Now I can use the resource group ID ($RDID) to assign the previous policy definition ($Policy) to the resource group:
New-AzureRmPolicyAssignment -Name RestrictVMSizes -PolicyDefinition $Policy -Scope $RGID
Now if I try to create a virtual machine that is not listed in my policy (see the above JSON file), the process will fail (note that other resources such as storage accounts, NICs, etc. will be created first). The below screenshot is of such a failed deployment in the Azure Portal.
Larger businesses might have more than one Azure subscription, with the intention to assign subscriptions as a way to assign IT budgets. They may have a scenario, like I have with my training classes, where they need to control consumption at a subscription level instead of at a resource group level. We can assign an ARM policy to a subscription.
We already have the subscription ID ($SubID) from when we logged in to the subscription using Azure. Now we can assign the policy ($Policy) to the subscription using the following. Please note the use of /subscriptions/ before $SubID:
New-AzureRmPolicyAssignment -Name RestrictVMsizes -PolicyDefinition $Policy -Scope /subscriptions/$SubID
This policy now affects every administrator that tries to create virtual machines in the subscription and limits users to creating only machines that are listed in the policy.