Are you looking to keep a vigilant eye on your Windows 365 environment? Good news! You can now send Windows 365 audit events to Azure Log Analytics, Splunk, or any other SIEM system that supports it.
Understanding the Scope of Windows 365 Audit Logs
When it comes to monitoring your Cloud PC environment, Windows 365 audit logs are an indispensable resource. These logs provide a comprehensive chronicle of significant activities that result in modifications within your Cloud PC setup (https://intune.microsoft.com/). Here’s what gets captured:
Creation Events: Every time a Cloud PC is provisioned, it’s meticulously logged.
Update Events: Any alterations or configurations changes made to an existing Cloud PC are recorded.
Deletion Events: If a Cloud PC is decommissioned, this action is also captured in the logs.
Assignment Events: The process of assigning Cloud PCs to users doesn’t go unnoticed; it’s all in the logs.
Remote Actions: Activities such as remote sign-outs or restarts are tracked for administrative oversight.
These audit events encompass most actions executed via the Microsoft Graph API, ensuring that administrators have visibility into the operations that affect their Cloud PC infrastructure. It’s important to note that audit logging is an always-on feature for Windows 365 customers. This means that from the moment you start using Cloud PCs, every eligible action is automatically logged without any additional configuration.
Windows 365 and Azure Log Analytics
Windows 365 has made it easier than ever to integrate with Azure Log Analytics. With a few simple PowerShell commands, you can create a diagnostic setting to send your logs directly to your Azure Log Analytics workspace.
Sign in to the Microsoft Intune admin center, select Reports > Diagnostic settings (under Azure monitor)> Add Diagnostic settings.
Under Logs, select Windows365AuditLogs.
Under Destination details, select the Azure Log Analytics and choose the Subscription & Workspace.
Select Save.
Query the Azure Log Analytics
Once your logs are safely stored in Azure Log Analytics, retrieving them is a breeze. You can use Kusto Query Language (KQL) to extract and analyze the data. Here’s a basic example of how you might query the logs:
Leverage Graph API to retrieve Windows 365 audit events
Connect to MS Graph API
Step 1 – Install the MS Graph Powershell Module
#Install Microsoft Graph Beta Module
PS C:WINDOWSsystem32> Install-Module Microsoft.Graph.Beta
Step 2 – Connect to scopes and specify which API you wish to authenticate to. If you are only doing read-only operations, I suggest you connect to “CloudPC.Read.All” in our case, we are creating the policy, so we need to change the scope to “CloudPC.ReadWrite.All”
#Read-only
PS C:WINDOWSsystem32> Connect-MgGraph -Scopes "CloudPC.Read.All" -NoWelcome
Welcome To Microsoft Graph!
OR
#Read-Write
PS C:WINDOWSsystem32> Connect-MgGraph -Scopes "CloudPC.ReadWrite.All" -NoWelcome
Welcome To Microsoft Graph!
Permissions for MS Graph API
Step 3 – Check the User account by running the following beta command.
Integrating Windows 365 with Azure Log Analytics is a smart move for any organization looking to bolster its security and compliance posture. With the added flexibility of forwarding to multiple endpoints, you’re well-equipped to handle whatever audit challenges come your way.
I hope you will find this helpful information for enabling and quering Windows 365 Audit Logs in Azure Logs Analytics or using Graph API with PowerShell. Please let me know if I have missed any steps or details, and I will be happy to update the post.
Note – The best method of assigning the DNS Servers is through the DHCP server. If you are setting the IP using DHCP, always make sure you add/remove additional DNS Client Servers from there. In my situation, there was no DHCP server, hence the detailed blog post.
Prerequsites
We are going to implement this configuration via Microsoft Intune using the Scripts:
The necessary Microsoft Intune permissions to create, the PowerShell Scripts.
A device group available within Microsoft Entra with all the devices you want to target this change.
PowerShell Script for DNSClient (Additional DNS Servers)
Save the below script and place on the desktop and we shall be uploading it to Microsft Intune portal – “AddDNSClient.ps1″
Please enter the proper DNS Server Address within the script based on your environment and requirement. In the example below the existing two DNS servers are 8.8.8.8 and 8.8.8.4. We are adding additional two DNS Servers 9.9.9.9 and 9.9.9.4.
Select Devices > Scripts > Add > Windows 10 and later.
In Basics, enter the following properties, and select Next:
Name: AddDNSClientServers
Description: Additional DNS Server 3 & 4
In Script settings, enter the following properties, and select Next:
Script location: Browse to the PowerShell script. saved previously and upload it (AddDNSClient.ps1)
Run this script using the logged on credentials: Select No.
Enforce script signature check: Select No
Run script in 64-bit PowerShell host: Select Yes to run the script in a 64-bit PowerShell host on a 64-bit client architecture.
Select Assignments > Select groups to include. Add the AAD group “Win11-P-DG”
Wait for approx. 15-20 minutes and the policy will apply to the managed devices. (Machine Win11-Intune-15)
Managed Device
You can validate that the settings have been applied to the client by going to the path – C:\ProgramData\Microsoft\IntuneManagementExtension\Logs and opening the file IntuneManagementExtension.txt. I copied the policy ID – cf09649b-78b7-4d98-8bcc-b122c29e5527 from the Intune portal hyperlink and searched within the log file. We can see the policy has been applied successfully.
I hope you will find this helpful information for applying additional DNS servers via Intune – Scripts and PowerShell. Please let me know if I have missed any steps or details, and I will be happy to update the post.
Let’s say you have the entire Windows member server fleet of Windows Server 2016/2019/2022, Windows 11 Pro/Enterprise etc., using DNS Server 1 and Server 2 within their TCP-IP properties and now you decide to add DNS Server address 3 and Server 4 to the member servers to increase resiliency.
In the blog post, I will demonstrate how you can add the additional DNS Server using Group Policy Object and PowerShell with your enterprise.
What doesn’t work?
It would be best if you didn’t waste time – The GPO Computer Configuration –> Administrative Templates –> Network –> DNS Client –> DNS Servers doesn’t work. The “Supported On” version doesn’t include Windows Server 2016\Windows 10 in the compatibility. Even if you apply this GPO, it will apply to the server within the registry, but there will be no visible change under the TCP-IP properties.
Prerequsites
We are going to implement this configuration via group policy object within the enterprise:
The necessary active directory permissions to create, apply and link the GPOs
Access to the Sysvol folder to store the script
WMI Filters to target the script\GPO to specific subnets (More details below)
PowerShell Script for DNSClient (Additional DNS Servers)
Save the below script and place it within the location – \\DOMAINNAME\SYSVOL\DOMAINNAME\scripts\SetDNSAddress.ps1″
Please enter the proper DNS Server Address within the script based on your environment and requirements.
On a member server with administrative privileges, press Win + R to open the Run box. Type gpmc.msc and press Enter to open the Group Policy Management Console.
In the GPMC, expand the forest and domain trees on the left pane to locate the domain you want to create the GPO in.
Right-click on “Group Policy Objects” under the domain and select “New” to create a new GPO.
In the “New GPO” dialog box, provide a name for the GPO (e.g., “Additional DNS Servers”) and click “OK”.
Right-click on the newly created GPO and select “Edit” to open the Group Policy Management Editor.
Navigate to Computer Configuration > Preferences > Control Panel Settings > Scheduled Tasks
Right Click on Scheduled Tasks > Configure the task as Immediate Task.
Give it a name – SetDNSClient
Set the user account as SYSTEM. It will automatically convert into NT Authority\system.
Set the check “run with highest privileges”
In the Actions tab, create a new “Start a program” action.
Set the Program as: PowerShell.exe
Set the Add Arguments point to this line, and modify including your network share and file: ExecutionPolicy Bypass -command “& \\DOMAINNAME\SYSVOL\DOMAINNAME\scripts\SetDNSAddress.ps1”
Set the following in common Tab. – “Apply once and do not reapply”
Bonus Tip – WMI Filters
You want to target the GPO to a specific set of member servers who’s IP range starts with a particular IP address. Then you can create a WMI filter such as the below to target particular computers that meet the below range. In the below example, the GPO will apply to the machine starting with IP Address 10.XX OR 10.XX.
Select * FROM Win32_IP4RouteTable
WHERE (Mask='255.255.255.255'
AND (Destination Like '192.168.%' OR Destination Like '192.169.%'))
Intune (Configuration Profiles – Doesn’t Work)
As of writing the blog post the Intune built-in setting\CSP is showing similar behaviour like the DNS Server GPO it doesn’t work.
CSP
Under both situations (CSP & ADMX templates), the report says the policy is applied successfully. However, there is no visible impact on the operating system’s TCP-IP properties. I am optimistic that using the Scripts method and PowerShell can achieve the same results in Intune. Please let me know in the comments sections if you got it working or/else if you would like to see a blog post on using Intune Scripts to set the DNS Client on member servers.
Reference Links
Following are the references and important links worth going through for more details:
I hope you will find this helpful information for applying additional DNS servers via the GPO and PoweShell. I want to thank my friend Eqbal Hussian for his assistance and additional rounds of testing\validations. Please let me know if I have missed any steps or details, and I will be happy to update the post.
Suppose you’ve ever had to search for a particular or a list of GPO settings across a large number of Group Policy Objects (GPOs) within your domain. In that case, you know how tedious it can be to find specific settings across hundreds or thousands of GPOs. PowerShell comes to the rescue with a powerful script that can search for GPO settings across all your existing GPOs and generate an organized CSV output. In this blog post, we’ll walk you through the process and ensure you have all the prerequisites to get started.
Usecase
You have approx. 50 to 60 GPO settings from the Center of Internet Security (CIS) benchmark policies document (CIS Microsoft Windows Desktop Benchmarks/CIS Microsoft Windows Server Benchmarks), which you may want to search against your domain, whether they are already preconfigured\existing available within a GPO or not present in the environment. Instead of searching manually one by one, you may want to use the below PowerShell to get results like a champion.
Prerequisites
Before using the PowerShell script, ensure you have the following prerequisites in place:
Windows PowerShell version 5.0 and above
Active Directory Module for Windows PowerShell
Permissions: Ensure you have sufficient permissions to access and analyze GPO settings. Typically, you need to be a member of the Domain Administrators group or have equivalent privileges.
Execute the script from a member server that is part of the domain and has the necessary permissions.
Prepare the input file (inputgpo.txt) and enter the GPO setting one per line and save the file. In my situation, it’s present in C:\Temp
Relax minimum password length limits
Allow Administrator account lockout
Generate security audits
Impersonate a client after authentication
Lock pages in memory
Replace a process level token
Accounts: Block Microsoft accounts
Interactive logon: Machine inactivity limit
Microsoft network server: Server SPN target name validation level
Network access: Remotely accessible registry paths
Network security: Configure encryption types allowed for Kerberos
Audit Security State Change
Do not allow password expiration time longer than required by policy
Password Settings: Password Complexity
Password Settings: Password Length
Password Settings: Password Age (Days)
#Domain
$DomainName = "askaresh.com"
# Initialize matchlist
$matchlist = @()
# Collect all GPOs
$GPOs = Get-GPO -All -Domain $DomainName
# Read search strings from text file
# A list of GPOs settings you want to search
$SearchStrings = Get-Content -Path "C:\Temp\inputgpo.txt"
# Hunt through each GPO XML for each search string
foreach ($searchString in $SearchStrings) {
$found = $false
foreach ($gpo in $GPOs) {
$GPOReport = Get-GPOReport -Guid $gpo.Id -ReportType Xml
if ($GPOReport -match $searchString) {
$match = New-Object PSObject -Property @{
"SearchString" = $searchString
"GPOName" = $gpo.DisplayName
}
$matchlist += $match
$found = $true
}
}
if (-not $found) {
$match = New-Object PSObject -Property @{
"SearchString" = $searchString
"GPOName" = "No results found"
}
$matchlist += $match
}
}
# Output results to CSV, Search results
# This step will take time depending how many 100's or 1000's policies present in the enviornment
$matchlist | Export-Csv -Path "C:\Temp\gposearch.csv" -NoTypeInformation
Output (Results)
The ouput will look like the following within CSV:
I hope you will find this helpful information for searching GPO settings across 100’s and 1000’s of GPOs within your domain. Please let me know if I have missed any steps or details, and I will be happy to update the post.
I have a blog post about creating a Windows 365 Cloud PC Provisioning Policy using PowerShell. In this post blog, I will demonstrate how to create the provisioning policy using PowerShell and MS Graph API with beta modules for Windows 365 Cloud PC – Frontline Workers.
Example – Each Windows 365 Frontline license can be shared with up to three employees. This means that if you have 30 employees, you only need to purchase 10 licenses to provision the CloudPC for all 30 employees with access over the day. However, note you are buying the frontline license based on the active sessions. You must purchase the license accordingly if you have more than 10 active workers in a shift.
What happens when license are exhausted?
In my demo tenant, I have two licenses for Frontline workers. When I try to log in to the third one (Note I have already logged into 2 active sessions and running them.) Get the following message.
Connect to MS Graph API
Step 1 – Install the MS Graph Powershell Module
#Install Microsoft Graph Beta Module
PS C:WINDOWSsystem32> Install-Module Microsoft.Graph.Beta
Step 2 – Connect to scopes and specify which API you wish to authenticate to. If you are only doing read-only operations, I suggest you connect to “CloudPC.Read.All” in our case, we are creating the policy, so we need to change the scope to “CloudPC.ReadWrite.All”
#Read-only
PS C:WINDOWSsystem32> Connect-MgGraph -Scopes "CloudPC.Read.All" -NoWelcome
Welcome To Microsoft Graph!
OR
#Read-Write
PS C:WINDOWSsystem32> Connect-MgGraph -Scopes "CloudPC.ReadWrite.All" -NoWelcome
Welcome To Microsoft Graph!
Permissions for MS Graph API
Step 3 – Check the User account by running the following beta command.
If you are doing on-premise network integration (Azure Network Connection) , then the following additional property and value is required. In my lab, I am leveraging the Microsoft Managed Network, so this is not required.
I hope you will find this helpful information for creating a frontline worker provisioning policy using PowerShell. Please let me know if I have missed any steps or details, and I will be happy to update the post.
Microsoft Security Response Center (MSRC) publishes a monthly consolidated report for all the Critical, Important, Moderate and Low security vulnerabilities affecting Microsoft products. The information posted there helps organizations manage security risks and keep their systems protected.
Looking at the overall release notes for all the affected products (30+ products) and filtering the OS you are interested in can become overwhelming. E.g. You are only interested in products Operating Systems – Windows 11 22h2 or Windows Server 2016/2019/2022. Not saying other information is not essential, but imagine you are only responsible for the Operating Sytems. In such situations, you can use the below script to get a monthly report of CVE (Critical & Important) for a particular OS over to you in an email.
Prerequsites
You will need the MSRCSecurity PowerShell module. Run the command to install the module; further, you can import the module within the script.
Following are the Operating System (OS) products you can fetch the information against. If you want details for any other operating systems, copy that value and, in my script, paste it under the variable $ClientOS_Type. In my demonstration, we used “Windows 11 Version 22H2 for x64-based Systems”
$ID = Get-MsrcCvrfDocument -ID $Month
$ID.ProductTree.FullProductName
ProductID Value
--------- -----
10049 Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation)
10051 Windows Server 2008 R2 for x64-based Systems Service Pack 1
10287 Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation)
10378 Windows Server 2012
10379 Windows Server 2012 (Server Core installation)
10407 Microsoft Outlook 2013 RT Service Pack 1
10483 Windows Server 2012 R2
10543 Windows Server 2012 R2 (Server Core installation)
10601 Microsoft Office 2013 Service Pack 1 (32-bit editions)
10602 Microsoft Office 2013 Service Pack 1 (64-bit editions)
10603 Microsoft Office 2013 RT Service Pack 1
10611 Microsoft Office Web Apps Server 2013 Service Pack 1
10612 Microsoft SharePoint Foundation 2013 Service Pack 1
10654 Microsoft Excel 2013 Service Pack 1 (32-bit editions)
10655 Microsoft Excel 2013 Service Pack 1 (64-bit editions)
10656 Microsoft Excel 2013 RT Service Pack 1
10729 Windows 10 for 32-bit Systems
10735 Windows 10 for x64-based Systems
10739 Microsoft Excel 2016 (32-bit edition)
10740 Microsoft Excel 2016 (64-bit edition)
10753 Microsoft Office 2016 (32-bit edition)
10754 Microsoft Office 2016 (64-bit edition)
10765 Microsoft Outlook 2016 (32-bit edition)
10766 Microsoft Outlook 2016 (64-bit edition)
10810 Microsoft Outlook 2013 Service Pack 1 (32-bit editions)
10811 Microsoft Outlook 2013 Service Pack 1 (64-bit editions)
10816 Windows Server 2016
10852 Windows 10 Version 1607 for 32-bit Systems
10853 Windows 10 Version 1607 for x64-based Systems
10855 Windows Server 2016 (Server Core installation)
10950 Microsoft SharePoint Enterprise Server 2016
11099 Microsoft SharePoint Enterprise Server 2013 Service Pack 1
11568 Windows 10 Version 1809 for 32-bit Systems
11569 Windows 10 Version 1809 for x64-based Systems
11570 Windows 10 Version 1809 for ARM64-based Systems
11571 Windows Server 2019
11572 Windows Server 2019 (Server Core installation)
11573 Microsoft Office 2019 for 32-bit editions
11574 Microsoft Office 2019 for 64-bit editions
11575 Microsoft Office 2019 for Mac
11585 Microsoft SharePoint Server 2019
11600 Microsoft Visual Studio 2017 version 15.9 (includes 15.0 - 15.8)
11605 Microsoft Office Online Server
11655 Microsoft Edge (Chromium-based)
11664 Microsoft Dynamics 365 (on-premises) version 9.0
11726 OneDrive for Android
11762 Microsoft 365 Apps for Enterprise for 32-bit Systems
11763 Microsoft 365 Apps for Enterprise for 64-bit Systems
11800 Windows 10 Version 20H2 for x64-based Systems
11801 Windows 10 Version 20H2 for 32-bit Systems
11802 Windows 10 Version 20H2 for ARM64-based Systems
11902 Microsoft Malware Protection Engine
11921 Microsoft Dynamics 365 (on-premises) version 9.1
11923 Windows Server 2022
11924 Windows Server 2022 (Server Core installation)
11926 Windows 11 version 21H2 for x64-based Systems
11927 Windows 11 version 21H2 for ARM64-based Systems
11929 Windows 10 Version 21H2 for 32-bit Systems
11930 Windows 10 Version 21H2 for ARM64-based Systems
11931 Windows 10 Version 21H2 for x64-based Systems
11935 Microsoft Visual Studio 2019 version 16.11 (includes 16.0 - 16.10)
11951 Microsoft Office LTSC for Mac 2021
11952 Microsoft Office LTSC 2021 for 64-bit editions
11953 Microsoft Office LTSC 2021 for 32-bit editions
11961 Microsoft SharePoint Server Subscription Edition
11969 Microsoft Visual Studio 2022 version 17.0
11987 Azure HDInsights
12051 Microsoft Visual Studio 2022 version 17.2
12085 Windows 11 Version 22H2 for ARM64-based Systems
12086 Windows 11 Version 22H2 for x64-based Systems
12097 Windows 10 Version 22H2 for x64-based Systems
12098 Windows 10 Version 22H2 for ARM64-based Systems
12099 Windows 10 Version 22H2 for 32-bit Systems
12129 Microsoft Visual Studio 2022 version 17.4
12137 CBL Mariner 1.0 x64
12138 CBL Mariner 1.0 ARM
12139 CBL Mariner 2.0 x64
12140 CBL Mariner 2.0 ARM
12142 Microsoft Edge (Chromium-based) Extended Stable
12155 Microsoft Office for Android
12156 Microsoft Office for Universal
12167 Microsoft Visual Studio 2022 version 17.5
12169 OneDrive for MacOS Installer
12170 OneDrive for iOS
12171 Azure Service Fabric 9.1 for Windows
12172 Azure Service Fabric 9.1 for Ubuntu
12173 Snipping Tool
12174 Snip & Sketch for Windows 10
9312 Windows Server 2008 for 32-bit Systems Service Pack 2
9318 Windows Server 2008 for x64-based Systems Service Pack 2
9344 Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation)
Variable Region
Delcare all the variable within this section. Lets take a look at what we are declaring within the script:
The MSRC website releases the montly report in the following yyyy-MM format
#Month Format for MSRC
$Month = Get-Date -Format 'yyyy-MMM'
The operating system we want to focus on and leave the rest. If you are interested in any other OS, change the value from the above prerequisites, and it will give you Critical/Import vulnerabilities for that OS or product.
# Enter the Operating System you specifically want to focus on
$ClientOS_Type = "Windows 11 Version 22H2 for x64-based Systems"
Enter the details for sending the email (subject line, to and from etc.) for the report
#Email Details
$Recipients = "askaresh@askaresh.com", "someone@askaresh.com"
$Sender = "cve-report@askaresh.com"
$SMTP_Server = "smtp.askaresh.com"
$Subject = 'CVE List for Windows 11 22H2 on '+$Month
HTML report formatting (CSS, Title of the report, Logo and Header) information
I hope you will find this helpful information to gather Microsoft Security vulnerability reports for a specific operating system using PowerShell. Please let me know if I have missed any steps or details, and I will be happy to update the post.
I have written various individual blog posts on PowerShell creation of all configurational task for Windows 365 Cloud PC under Microsoft Endpoint Portal (MEM).
Based on public demand, I want to create a consolidated post for all the scripts and configuration items that can get you started with Windows 365 Cloud PC using PowerShell: (Of course all the below features can also be configured using the UI, however below is the guidance strictly using PowerShell)
PowerShell links to my blog post
Following are the links to my blog post for each and individual task:
I promise you once you have done the hard work, you can get up and running in a few hours using all the above PowerShell scripts with Windows 365 Cloud PC.
GitHub Link
Here is the repo with all the scripts and more – askaresh/avdwin365mem (github.com). A big thanks to Andrew Taylor for collabrating and updating the Provisioning policy script with the SSO details that was release in late Nov 2022.
I hope you will find this helpful information for all things PowerShell w.r.t Windows 365 Cloud PC. I will update the post if I publish or update more information.
If you want to establish a network connection that allows communication between the Windows 365 Cloud PC and the existing Azure Virtual Network (ANC), then keep following this post. Today, I will demonstrate the Powershell method of creating the Azure Network Connection (ANC). Note that we need information from the Azure Portal to make sure you have all the necessary information handy or/or involve the necessary teams who can provide you with the information on Azure Networking.
Overview
Create the ANC first before creating the Win365 – Cloud Provisioning Policy (CPP)
If the ANC precreated then during the cloud provisioning of the Cloud PC desktops it will create them on the Azure VNET on your desired subnet
Make sure you have a working DNS configured on the VNET which can communicate with your on-premise network using express route or other Azure VNETs
Open necessary firewall ports based on your requirements on the NSG or Azure Firewall for the communication to your on-premise network using express route or other Azure VNETs
Permissions
Intune Administrator in Azure AD
Cloud PC Administrator
Global Administrator
If you decide to alter or change the ANC, you will have to reprovision the Cloud PC, and it’s a destructive activity. Make sure you architect it properly
You can delete your ANC however, you will have to update your cloud provisioning policy with the new ANC first, and then you can delete the existing ANC.
Connect to MS Graph API
Step 1 – Install the MS Graph Powershell Module
#Install Microsoft Graph Module
PS C:WINDOWSsystem32> Install-Module Microsoft.Graph.Beta
Step 2 – Connect to scopes and specify which API you want to authenticate. If you are only doing read-only operations, I suggest you connect to “CloudPC.Read.All” in our case, we are creating the ANC, so we need to change the scope to “CloudPC.ReadWrite.All”
#Read-only
PS C:WINDOWSsystem32> Connect-MgGraph -Scopes "CloudPC.Read.All" -NoWelcome
Welcome To Microsoft Graph!
OR
#Read-Write
PS C:WINDOWSsystem32> Connect-MgGraph -Scopes "CloudPC.ReadWrite.All" -NoWelcome
Welcome To Microsoft Graph!
Step 3 – Check the User account by running the following beta command.
#Beta User
PS C:WINDOWSsystem32> Get-MgBetaUser -UserId admin@wdomain.com
Connect to Azure & Grab Details (Variable Region)
We are logging into Azure to grab all the details regarding to Resource Group, Subscription ID/Name, VNET and Subnets
Connect to the Azure Portal using the necessary credentials
Select the Azure Subscription that holds all the networking information
A display name of the Azure Network Connection – ANC – (ANC-W365-Sub01)
What is the join type of the ANC of the golden image virtual machine (azureADJoin)
Resource Group ID of the existing resource group. You will have to enter the resource group name (W365-AVD-RG01), and it will get us the ID we need.
Name of the existing subnet within the vNET (W365Workload-Sub01), and it will get us the ID we need.
Name of the existing VNET used for the connection. You will have to enter the VNET name (W365-AVD-VNET01), and it will get us the ID we need.
Connection to the MS Graph API and ensure you have the necessary write permissions.
We are using the beta API for Cloud PC
# Connect to the Azure Subcription
Connect-AzAccount
# Get existing context
$currentAzContext = Get-AzContext
# Your subscription. This command gets your current subscription
$subscriptionID = $currentAzContext.Subscription.Id
# Your subscription. This command gets your current subscription name
$subscriptionName = $currentAzContext.Subscription.Name
# ANC Display Name
$ancdname = "ANC-W365-Sub01"
# Join Ype for the Azure Network Connection
# Two types Azure AD and Hyrbird "azureADJoin" or "hybridAzureADJoin"
$ancjointype = "azureADJoin"
# Get your Win365 Resouce Group id for RG Name - W365-AVD-RG01
# Put your RG Name
$win365RGID = Get-AzResourceGroup -Name "W365-AVD-RG01" | Select-Object -ExpandProperty ResourceId
# Get your Azure VNET id used for Windows 365 Cloud PC
# Put your VNET Name
$win365VNETID = Get-AzVirtualNetwork -Name "W365-AVD-VNET01" | Select-Object -ExpandProperty Id
# Get your Subnet ID within the Azure VNET for Windows 365 Cloud PC
# Put your VNET Name
$win365VNET = Get-AzVirtualNetwork -Name "W365-AVD-VNET01"
# Enter your Subnet Name
$win365SubID = Get-AzVirtualNetworkSubnetConfig -Name "W365Workload-Sub01" -VirtualNetwork $win365VNET | Select-Object -ExpandProperty Id
# Connec to MS Graph for Cloud PC W365
Connect-MgGraph -Scopes "CloudPC.ReadWrite.All"
We shall pass the above variable into the final ANC creation.
Create the Azure Network Connection
We are creating a Azure Network Connection that includes the following:
Display Name of the network – $ancdname
Azure Subscription ID – $subscriptionID
Azure Subscription Name – $subscriptionName
Type – There are two types we are selecting Azure AD join – azureADJoin
Resource Group ID – The resource group within Azure – $win365RGID
Virtual Network ID – The VNET within Azure – $win365VNETID
Subnet ID – The subnet for W365 within VNET – $win365SubID
# Create the ANC for Windows 365 with AAD join type
try
{
write-host "Create the ANC for Windows 365 with AAD join type"
$params = @{
displayName = "$ancdname"
subscriptionId = "$subscriptionID"
type = "$ancjointype"
subscriptionName = "$subscriptionName"
resourceGroupId = "$win365RGID"
virtualNetworkId = "$win365VNETID"
subnetId = "$win365SubID"
}
New-MgBetaDeviceManagementVirtualEndpointOnPremiseConnection -BodyParameter $params -Debug
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
# Import module Az and MS Graph
Import-Module Az.Accounts
Install-Module Microsoft.Graph
# Connect to the Azure Subcription
Connect-AzAccount
# Get existing context
$currentAzContext = Get-AzContext
# Your subscription. This command gets your current subscription
$subscriptionID = $currentAzContext.Subscription.Id
# Your subscription. This command gets your current subscription name
$subscriptionName = $currentAzContext.Subscription.Name
# ANC Display Name
$ancdname = "ANC-W365-Sub01"
# Join Ype for the Azure Network Connection
# Two types Azure AD and Hyrbird "azureADJoin" or "hybridAzureADJoin"
$ancjointype = "azureADJoin"
# Get your Win365 Resouce Group id for RG Name - W365-AVD-RG01
# Put your RG Name
$win365RGID = Get-AzResourceGroup -Name "W365-AVD-RG01" | Select-Object -ExpandProperty ResourceId
# Get your Azure VNET id used for Windows 365 Cloud PC
# Put your VNET Name
$win365VNETID = Get-AzVirtualNetwork -Name "W365-AVD-VNET01" | Select-Object -ExpandProperty Id
# Get your Subnet ID within the Azure VNET for Windows 365 Cloud PC
# Put your VNET Name
$win365VNET = Get-AzVirtualNetwork -Name "W365-AVD-VNET01"
# Enter your Subnet Name
$win365SubID = Get-AzVirtualNetworkSubnetConfig -Name "W365Workload-Sub01" -VirtualNetwork $win365VNET | Select-Object -ExpandProperty Id
# Connec to MS Graph for Cloud PC W365
Connect-MgGraph -Scopes "CloudPC.ReadWrite.All"
# Create the ANC for Windows 365 with AAD join type
try
{
write-host "Create the ANC for Windows 365 with AAD join type"
$params = @{
displayName = "$ancdname"
subscriptionId = "$subscriptionID"
type = "$ancjointype"
subscriptionName = "$subscriptionName"
resourceGroupId = "$win365RGID"
virtualNetworkId = "$win365VNETID"
subnetId = "$win365SubID"
}
New-MgBetaDeviceManagementVirtualEndpointOnPremiseConnection -BodyParameter $params -Debug
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
I hope you will find this helpful information for creating Azure Network Connection using PowerShell. Please let me know if I have missed any steps or details, and I will be happy to update the post.
The enterprise has been rolling out the application packages using various available methods (GPOs, SCCM, WS1 UEM etc.) in the industry. Today we are going to take a step further and see how to deploy the VMware Horizon Client using the new Micrososft Windows Package Manager (Winget)
Available Commands for various verison of Horizon Client
Following are the commands however, it’s recommended only to install the latest or the matching version based on your VMware Horizon environment.
VMware Horizon 8.x
VMware Horizon Client 8.x
VMware Horizon 7.x
VMware Horizon Client 5.x
# Latest GA version VMware Horizon Client version 8.7.0.31805
winget install -e --id VMware.HorizonClient
Installing, Listing, Upgrading and Un-installing the latest version HZ Client
Open the PowerShell with administrative privileges
Installing
winget install -e --id VMware.HorizonClient
Listing the installed package
List the package and its details of the previous installation step
winget list --name 'VMware Horizon Client'
Upgrading from version 5.5.4 to 8.7.0
winget upgrade --id VMware.HorizonClient
Un-installing
Following is the command to uninstall the Horizon Client.
winget uninstall --id VMware.HorizonClient
Note after running the above command, the Windows endpoint rebooted immediately. I am not whether the product team has included the /norestart switches to the packages. If you come across the same leave a comment down below.
I hope you will find this helpful post about the winget and VMware Horizon Client details. Give it a spin in your lab and production environment, if you find anything interesting. I hope you can share it back with me?
Assign the Azure Active Directory Group to the (AG)
I will break down the code block into smaller chunks first to explain the critical bits, and in the end, I will post the entire code block that can be run all at once. In this way, explaining block by block becomes easier than pasting one single block.
RemoteApp
RemoteApp – This is a way to provide end-users with the business applications alone without giving them an entire desktop. They can access their applications anywhere on any device.
Pre-requisites
Following are the pre-requisites before you begin
PowerShell 5.1 and above
Azure Subscription
Permissions within the Azure Subscription for the creation of AVD – Host Pools
To start working with Azure PowerShell, sign in with your Azure credentials.
Connect-AzAccount
Variable Region
Delcare all the variable within this section. Lets take a look at what we are declaring within the script:
Existing Resource Group within the Azure Subscription (AZ104-RG)
A location where you are deploying this Host Pool (Australia East)
Name of the Host Pool (RA-HP01)
Host Pool Type (Pooled) as it will be shared with multiple end-users
Load balancing method for the Host Pool (DepthFirst)
Maximum users per session host VM (10)
The type of Application Group (RailApplications). As we are only giving out end-users Apps
Application Group Name ($HPName-RAG)
Workspace grouping name ($HPName-WRK01)
Azure AD group that will be assigned to the application group (XXXX4b896-XXXX-XXXX-XXXX-33768d8XXXXX)
# Get existing context
$currentAzContext = Get-AzContext
# Your subscription. This command gets your current subscription
$subscriptionID = $currentAzContext.Subscription.Id
# Existing Resource Group to deploy the Host Pool
$rgName = "AZ104-RG"
# Geo Location to deploy the Host Pool
$location = "australiaeast"
# Host Pool name
$HPName = "RA-HP01"
# Host Pool Type Pooled|Personal
$HPType = "Pooled"
# Host Pool Load Balancing BreadthFirst|DepthFirst|Persistent
$HPLBType = "DepthFirst"
# Max number or users per session host
$Maxusers = "10"
# Preffered App group type Desktop|RailApplications
$AppGrpType = "RailApplications"
# ApplicationGroup Name
$AppGrpName = "$HPName-RAG"
# Workspace Name
$Wrkspace = "$HPName-WRK01"
# AAD Group used to assign the Application Group
# Copy the Object ID GUID from AAD Groups Blade
$AADGroupObjId = "XXXX4b896-XXXX-XXXX-XXXX-33768d8XXXXX"
Execution block
Execution code block within this section. Lets take a look at what we are we executing within the script:
Create the host pool with all the mentioned variables, tags and whether the validation enivornment yes/no.
Create the application group and tie it to the host pool
Finally, we create the workspace and tie it to the application group and hostpool
Last step, we assign the AAD group object ID to the Application Group for all entitlement purposes.
# Create the Host Pool with RemoteApp Configurations
try
{
write-host "Create the Host Pool with Pooled RemoteApp Configurations"
$DeployHPWRA = New-AzWvdHostPool -ResourceGroupName $rgName `
-SubscriptionId $subscriptionID `
-Name $HPName `
-Location $location `
-ValidationEnvironment:$true `
-HostPoolType $HPType `
-LoadBalancerType $HPLBType `
-MaxSessionLimit $Maxusers `
-PreferredAppGroupType $AppGrpType `
-Tag:@{"Billing" = "IT"; "Department" = "IT"; "Location" = "AUS-East" } `
-ErrorAction STOP
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
# Create the Application Group for the Remote App Host Pool
try
{
write-host "Create the Application Group for the Remote App Host Pool"
$CreateAppGroupRA = New-AzWvdApplicationGroup -ResourceGroupName $rgName `
-Name $AppGrpName `
-Location $location `
-HostPoolArmPath $DeployHPWRA.Id `
-ApplicationGroupType 'RemoteApp' `
-ErrorAction STOP
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
# Create the Workspace for the RemoteApp Host Pool
try
{
write-host "Create the Workspace for the RemoteApp Host Pool"
$CreateWorkspaceRA = New-AzWvdWorkspace -ResourceGroupName $rgName `
-Name $Wrkspace `
-Location $location `
-ApplicationGroupReference $CreateAppGroupRA.Id `
-ErrorAction STOP
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
# Assign the AAD group (Object ID) to the Application Group
try
{
write-host "Assigning the AAD Group to the Application Group"
$AssignAADGrpAG = New-AzRoleAssignment -ObjectId $AADGroupObjId `
-RoleDefinitionName "Desktop Virtualization User" `
-ResourceName $CreateAppGroupRA.Name `
-ResourceGroupName $rgName `
-ResourceType 'Microsoft.DesktopVirtualization/applicationGroups' `
-ErrorAction STOP
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
# Connect to the Azure Subcription
Connect-AzAccount
# Get existing context
$currentAzContext = Get-AzContext
# Your subscription. This command gets your current subscription
$subscriptionID = $currentAzContext.Subscription.Id
# Existing Resource Group to deploy the Host Pool
$rgName = "AZ104-RG"
# Geo Location to deploy the Host Pool
$location = "australiaeast"
# Host Pool name
$HPName = "RA-HP01"
# Host Pool Type Pooled|Personal
$HPType = "Pooled"
# Host Pool Load Balancing BreadthFirst|DepthFirst|Persistent
$HPLBType = "DepthFirst"
# Max number or users per session host
$Maxusers = "10"
# Preffered App group type Desktop|RailApplications
$AppGrpType = "RailApplications"
# ApplicationGroup Name
$AppGrpName = "$HPName-RAG"
# Workspace Name
$Wrkspace = "$HPName-WRK01"
# AAD Group used to assign the Application Group
# Copy the Object ID GUID from AAD Groups Blade
$AADGroupObjId = "dcc4b896-2f2d-49d9-9854-33768d8b65ba"
# Create the Host Pool with RemoteApp Configurations
try
{
write-host "Create the Host Pool with Pooled RemoteApp Configurations"
$DeployHPWRA = New-AzWvdHostPool -ResourceGroupName $rgName `
-SubscriptionId $subscriptionID `
-Name $HPName `
-Location $location `
-ValidationEnvironment:$true `
-HostPoolType $HPType `
-LoadBalancerType $HPLBType `
-MaxSessionLimit $Maxusers `
-PreferredAppGroupType $AppGrpType `
-Tag:@{"Billing" = "IT"; "Department" = "IT"; "Location" = "AUS-East" } `
-ErrorAction STOP
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
# Create the Application Group for the Remote App Host Pool
try
{
write-host "Create the Application Group for the Remote App Host Pool"
$CreateAppGroupRA = New-AzWvdApplicationGroup -ResourceGroupName $rgName `
-Name $AppGrpName `
-Location $location `
-HostPoolArmPath $DeployHPWRA.Id `
-ApplicationGroupType 'RemoteApp' `
-ErrorAction STOP
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
# Create the Workspace for the RemoteApp Host Pool
try
{
write-host "Create the Workspace for the RemoteApp Host Pool"
$CreateWorkspaceRA = New-AzWvdWorkspace -ResourceGroupName $rgName `
-Name $Wrkspace `
-Location $location `
-ApplicationGroupReference $CreateAppGroupRA.Id `
-ErrorAction STOP
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
# Assign the AAD group (Object ID) to the Application Group
try
{
write-host "Assigning the AAD Group to the Application Group"
$AssignAADGrpAG = New-AzRoleAssignment -ObjectId $AADGroupObjId `
-RoleDefinitionName "Desktop Virtualization User" `
-ResourceName $CreateAppGroupRA.Name `
-ResourceGroupName $rgName `
-ResourceType 'Microsoft.DesktopVirtualization/applicationGroups' `
-ErrorAction STOP
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Yellow
}
Next Steps on the Host Pool
Now that the host pool, application group and workspaces are ready following are the next steps involved:
Generate a registration token
Add the session host virtual machine to the host pool
Create Applications within the Application Group. You can create multiple Applications in single AG or 1 AG per Application.
I hope you will find this helpful information for deploying a host pools, application group and workspaces within Azure Virtual Desktop. If you want to see a Powershell version of the applications & session host activities, leave me a comment below or on my socials. Please let me know if I have missed any steps or details, and I will be happy to update the post.
Recent Comments