Skip to content

Commit

Permalink
Added Azure.VM.MultiTenantHosting (#3023)
Browse files Browse the repository at this point in the history
* Added Azure.VM.MultiTenantHosting

* Additional updates

* Fix

---------

Co-authored-by: Bernie White <bewhite@microsoft.com>
  • Loading branch information
BenjaminEngeset and BernieWhite committed Aug 28, 2024
1 parent 1f2cc28 commit 4cb06a4
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 89 deletions.
5 changes: 5 additions & 0 deletions docs/CHANGELOG-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers

## Unreleased

- New rules:
- Virtual Machine:
- Verify that Multitenant Hosting Rights are used for Windows client VMs by @BenjaminEngeset.
[#432](https://github.com/Azure/PSRule.Rules.Azure/issues/432)

## v1.39.0-B0055 (pre-release)

What's changed since pre-release v1.39.0-B0029:
Expand Down
154 changes: 154 additions & 0 deletions docs/en/rules/Azure.VM.MultiTenantHosting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
---
severity: Awareness
pillar: Cost Optimization
category: CO:05 Rate optimization
resource: Virtual Machine
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.VM.MultiTenantHosting/
---

# Multi-tenant Hosting Rights

## SYNOPSIS

Deploy Windows 10 and 11 virtual machines in Azure using Multi-tenant Hosting Rights to leverage your existing Windows licenses.

## DESCRIPTION

Multi-tenant Hosting Rights allow you to bring your Windows 10 and 11 licenses to the cloud, enabling you to run virtual machines (VMs) on Azure without incurring additional licensing costs.
This benefit is applicable if you have Windows licenses with Software Assurance or qualifying subscription licenses, making it a cost-effective option for your Azure deployments.

By utilizing Multi-tenant Hosting Rights, you can reduce the total cost of ownership when running Windows VMs in Azure.
This is particularly advantageous for organizations that already have on-premises Windows licenses covered under Software Assurance or eligible subscription plans.

Please note that this benefit is available exclusively for Windows 10 Enterprise and Windows 11 Enterprise editions.

## RECOMMENDATION

Consider using Multi-tenant Hosting Rights to maximize your existing licensing investments when deploying Windows VMs in Azure.

### Configure with Azure template

To deploy virtual machines that pass this rule:

- Set the `properties.licenseType` property to `Windows_Client`.

For example:

```json
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2024-07-01",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"properties": {
"hardwareProfile": {
"vmSize": "Standard_D2s_v3"
},
"osProfile": {
"computerName": "[parameters('name')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "MicrosoftWindowsDesktop",
"offer": "windows-11",
"sku": "win11-23h2-ent",
"version": "latest"
},
"osDisk": {
"name": "[format('{0}-disk0', parameters('name'))]",
"caching": "ReadWrite",
"createOption": "FromImage",
"managedDisk": {
"storageAccountType": "Premium_LRS"
}
}
},
"licenseType": "Windows_Client",
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', format('{0}-nic0', parameters('name')))]"
}
]
}
},
"dependsOn": [
"[resourceId('Microsoft.Network/networkInterfaces', format('{0}-nic0', parameters('name')))]"
]
}
```

### Configure with Bicep

To deploy virtual machines that pass this rule:

- Set the `properties.licenseType` property to `Windows_Client`.

For example:

```bicep
resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' = {
name: name
location: location
properties: {
hardwareProfile: {
vmSize: 'Standard_D2s_v3'
}
osProfile: {
computerName: name
adminUsername: adminUsername
adminPassword: adminPassword
}
storageProfile: {
imageReference: {
publisher: 'MicrosoftWindowsDesktop'
offer: 'windows-11'
sku: 'win11-23h2-ent'
version: 'latest'
}
osDisk: {
name: '${name}-disk0'
caching: 'ReadWrite'
createOption: 'FromImage'
managedDisk: {
storageAccountType: 'Premium_LRS'
}
}
}
licenseType: 'Windows_Client'
networkProfile: {
networkInterfaces: [
{
id: nic.id
}
]
}
}
}
```

## NOTES

This rule may produce false negatives because it does not verify whether the installed Windows OS is an Enterprise edition.

### Rule configuration

<!-- module:config rule AZURE_VM_USE_MULTI_TENANT_HOSTING_RIGHTS -->

By default, this rule is ignored.
For this rule to apply, set the `AZURE_VM_USE_MULTI_TENANT_HOSTING_RIGHTS` configuration value to `true`.

For example:

```yaml
configuration:
AZURE_VM_USE_MULTI_TENANT_HOSTING_RIGHTS: true
```
## LINKS
- [CO:05 Rate optimization](https://learn.microsoft.com/azure/well-architected/cost-optimization/get-best-rates)
- [Multi-tenant Hosting Rights](https://learn.microsoft.com/azure/virtual-machines/windows/windows-desktop-multitenant-hosting-deployment)
- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.compute/virtualmachinescalesets/virtualmachines)
34 changes: 33 additions & 1 deletion docs/setup/configuring-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,39 @@ Example:
```yaml title="ps-rule.yaml"
# Set the configuration option to enabled.
configuration:
AZURE_VNET_DNS_WITH_IDENTITY: true
AZURE_VM_USE_AZURE_HYBRID_BENEFIT: true
```

### AZURE_VM_USE_MULTI_TENANT_HOSTING_RIGHTS

<!-- module:version v1.39.0 -->
<!-- module:rule Azure.VM.MultiTenantHosting -->

This configuration option determines weather to check for Multi-tenant Hosting Rights when deploying Windows VMs.
When enabled, rules that check for MHR fail when a client VM is not configured to use MHR.

By default, this configuration option is set to `false`.

Syntax:

```yaml title="ps-rule.yaml"
configuration:
AZURE_VM_USE_MULTI_TENANT_HOSTING_RIGHTS: boolean
```

Default:

```yaml title="ps-rule.yaml"
configuration:
AZURE_VM_USE_MULTI_TENANT_HOSTING_RIGHTS: false
```

Example:

```yaml title="ps-rule.yaml"
# Set the configuration option to enabled.
configuration:
AZURE_VM_USE_MULTI_TENANT_HOSTING_RIGHTS: true
```

### AZURE_VNET_DNS_WITH_IDENTITY
Expand Down
3 changes: 2 additions & 1 deletion src/PSRule.Rules.Azure/en/PSRule-rules.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,5 @@
PrivateSubnet = "The subnet ({0}) should disable default outbound access."
VMPublicIPAttached = "The virtual machine with the NIC ({0}) should not have a public IP address attached."
VMSSPublicIPAttached = "The virtual machine scale set instances should not have public IP addresses directly attached to their network interfaces."
}
VMMultiTenantHostingRights = "The Windows 0S installed on the virtual machine ({0}) should use multi-tenant hosting rights."
}
21 changes: 18 additions & 3 deletions src/PSRule.Rules.Azure/rules/Azure.VM.Rule.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,21 @@ Rule 'Azure.VM.PublicIPAttached' -Ref 'AZR-000449' -Type 'Microsoft.Network/netw

#endregion Public IP

#region Multitenant Hosting Rights

# Synopsis: Deploy Windows 10 and 11 virtual machines in Azure using Multitenant Hosting Rights to leverage your existing Windows licenses.
Rule 'Azure.VM.MultiTenantHosting' -Ref 'AZR-000452' -Type 'Microsoft.Compute/virtualMachines' -If { $Configuration.GetBoolOrDefault('AZURE_VM_USE_MULTI_TENANT_HOSTING_RIGHTS', $False) } -Tag @{ release = 'GA'; ruleSet = '2024_09'; 'Azure.WAF/pillar' = 'Cost Optimization'; } {
if (($TargetObject.properties.storageProfile.imageReference.publisher -ne 'MicrosoftWindowsDesktop' -and
$TargetObject.properties.storageProfile.imageReference.offer -notmatch 'windows-10|windows-11') -or $TargetObject.Properties.storageProfile.osDisk.osType -ne 'Windows') {

return $Assert.Pass()
}

$Assert.HasFieldValue($TargetObject, 'properties.licenseType', 'Windows_Client').Reason($LocalizedData.VMMultiTenantHostingRights, $PSRule.TargetName)
}

#endregion Multitenant Hosting Rights

#region Helper functions

function global:HasPublisherMicrosoftSQLServer {
Expand All @@ -321,9 +336,9 @@ function global:GetOSAndDataDisks {
process {
$allowedSkuTypes = @('UltraSSD_LRS', 'PremiumV2_LRS', 'Premium_ZRS', 'Premium_LRS')
$TargetObject.properties.storageProfile.osDisk.managedDisk |
Where-Object { $_.storageAccountType -and $_.storageAccountType -notin $allowedSkuTypes }
$TargetObject.properties.storageProfile.dataDisks |
Where-Object { $_.managedDisk.storageAccountType -and $_.managedDisk.storageAccountType -notin $allowedSkuTypes }
Where-Object { $_.storageAccountType -and $_.storageAccountType -notin $allowedSkuTypes }
$TargetObject.properties.storageProfile.dataDisks |
Where-Object { $_.managedDisk.storageAccountType -and $_.managedDisk.storageAccountType -notin $allowedSkuTypes }
}
}

Expand Down
9 changes: 6 additions & 3 deletions src/PSRule.Rules.Azure/rules/Config.Rule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,18 @@ spec:
# Configure Container Apps external ingress.
AZURE_CONTAINERAPPS_RESTRICT_INGRESS: false

# Enable checks when Azure Firewall is deployed in a zonal configuration.
# Enables checks when Azure Firewall is deployed in a zonal configuration.
AZURE_FIREWALL_IS_ZONAL: false

# Enabled resource level checks for Defender for Storage.
# Enables resource level checks for Defender for Storage.
AZURE_STORAGE_DEFENDER_PER_ACCOUNT: false

# Enabled check for supported VMs use Azure Hybrid Benefit.
# Enables check for supported VMs use Azure Hybrid Benefit.
AZURE_VM_USE_AZURE_HYBRID_BENEFIT: false

# Enables checks for Multi-tenant Hosting Rights.
AZURE_VM_USE_MULTI_TENANT_HOSTING_RIGHTS: false

# Configure DNS is within the identity subscription.
AZURE_VNET_DNS_WITH_IDENTITY: false

Expand Down
Loading

0 comments on commit 4cb06a4

Please sign in to comment.