PowerShellCrack / PSAIBDeploymentToolkit

A project for managing process for Azure Image Builder using PowerShell

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

A project to manage multiple images for AIB

The original idea was to replicate a standard on-premise MDT build and capture Task sequence and it's deploymentshare into a supported AIB deployment template. The structure is similar to MDT's and each defined "sequenced" process is within the Control folder. Each "sequence" contains an aib.json file. This file is not a schema that follows the Azure Image builder schema, however with this file in conjunction with a basic template file (within the Template folder), the Scripts\Sequence.ps1 will generate a supported ARM template file for AIB. The next process is to create an automated process that will copy applications, templates and configurations into a blob containers for AIB to consume.

THIS IS A WORK IN PROGRESS

Image Tests

These are the images that have been planned or have been tested with this toolkit and the results

Image Description Included Tested Results Comments
Win10avdMarketImage Gen2 Marketplace VM no updates. Just to see if AIB worked 21h2 Yes Success 30minutes
Win10avdLatestUpdates Gen2 Marketplace VM with updates set to run. 21h2, Updates Yes Success
Win10avdO365Image Gen2 Marketplace VM with M365 apps and updates set to run. 21h2, Office 365, Updates Yes Success
Win10avdTestImage Gen2 Marketplace VM with two apps (Foxit and Notepad++) 21h2, Foxit, Notepad++ Yes Success 32min build time
Win10avdTest2Image Gen2 Marketplace VM with branding and multiple apps and updates set to run. 21h2, Branding, Foxit, Notepad++, Adobe Reader, LAPS, Microsoft News Appx, Updates Yes Success but failed 11min build time. Image completed with no errors, but the distribution timed out.
Win10avdSimpleImage Gen2 Marketplace VM with branding script (wallpaper and lockscreen) and updates set to run. 21h2, Branding, Updates Yes Success Needs work on branding script
Win10avdBaseImage Gen2 Marketplace VM; added scripts to install Microsoft 365 apps to latest version in Multisession mode with policy configured 21h2, Office 365, Teams, Fslogix, Onedrive, Updates, Optimizations, VM Preparation Yes Failed: Operation timed out Some issues with application scripts and installer for modules; added PSGallery trust and Nuget update for anything PowerShell calls. Manually running scripts on AVD reference Image using psexec to simulate SYSTEM works just fine
Win10avdBaselineImage Gen2 Marketplace VM; added scripts to install Microsoft 365 apps to latest version in Multisession mode with policy configured, and baseline software 21h2, Office 365, Teams, Fslogix, Onedrive, Adobe Acrobat DC, Laps, Microsoft News app, Updates, Optimizations, VM Preparation
Win10avdHardenedImage Gen2 Marketplace VM; added scripts to install Microsoft 365 apps to latest version in Multisession mode with STIG policy configured 21h2, Office 365, Teams, Fslogix, Onedrive, Updates, Optimizations, VM Preparation, STIGS No Working on STIG scripts

Apps tested

Name Version Image Association Install Type Results Comments
Office365 Latest Win10avdBaselineImage setup.exe Downloads the setup and builds the configuration and installed with settings
Teams Machine Wide Installer Latest Win10avdBaselineImage Teams_windows_x64.msi Downloads the setup and builds the installed with AVD mode
Onedrive Latest Win10avdBaselineImage OnedriveSetup.msi Downloads the setup and install in all users
Fslogix Latest Win10avdBaselineImage FslogixAppsSetup.exe Downloads, extracts the setup and install and configures
LAPS Win10avdTestImage Laps.x64.msi Used inline command with sas token for zip download
Adobe Acrobat Reader DC Win10avdBaselineImage Used inline command with sas token for zip download and extract locally and installs
AzureMonitor Win10avdTestImage Laps.x64.msi Used inline command with sas token for zip download and extract locally and installs
FoxitPDFReader 1201 Win10avdTestImage FoxitPDFReader1201_enu_Setup.msi Used inline command with sas token for zip download
Notepad Plus Plus 8.4.4 Win10avdTestImage npp.8.4.4.Installer.x64.exe Used inline command with sas token for zip download

TODOs

  • Develop a MDT-like User Interface to allow easier configurations.

  • Build language pack support using the Packages folder (https://docs.microsoft.com/en-us/azure/virtual-desktop/language-packs)

  • Build a script to convert MDT environment to AIB environment. Basically convert TS.xml into a aib.json and copy the applications,templates,and scripts to a blob storage. Structure would be in a format like:

    eg. <type>-<productname>-<version | latest>

    • Storage Account
      • Blob Storage Containers
        • scripts
        • templates
        • application-customizations
        • application-fslogix-latest
        • application-lgpo-latest
        • application-office365-latest
        • application-onedrive-latest
        • application-teams-latest
  • Develop a method to document definition version (after each build) using custom table in log analytics.

  • Azure Image Version cleanup

Prereqs

  • Azure Image Builder registered in tenant (Azure GCCH specifically)
  • Azure Managed Identity
  • Blob Container with Anonymous & public access or SAS token

contributing

If you are contributing or using the code. Please create a copy of the Settings.json file in control folder and name it something like Settings-<user>.json. (keep the Settings- in the filename); this file will be ignored during pull request.

You don't want your secrets to be public.

Scripts

  • BuildAIBTemplate.ps1 <-- Main script to build aib template
  • InvokeScriptsOnAzureVM.ps1 <-- designed to run post configs using Powershell extension. NOT WORKING / TESTING
  • PrepareAIBMDTEnv.ps1 <-- Starting to work AIB configurator. NOT WORKING / TESTING

Examples

.\BuildAIBTemplate.ps1 -Template Win10avdSimpleImage -ControlSetting Settings.json -BuildImage

Output

There is a Logs folder that will contain a dated transcript of the AIB sequence called and the json arm template is generated there for reference.

aib.json auto formatting

There is an aib.json (...kind of like the TS.xml in MDT. 😁) file in each control sequence. It is in a custom format designed to simplify the complex deployment of scripts & applications for AIB.

  1. Example: To deploy a branding customization that has both theme, wallpaper, and lockscreen requires several customize steps will need to be set:
    • 3x copy steps
    • inline script step
    • inline clean up script (optional)

It would look something like this in an actual ARM template for AIB:

"customize":  [
      {
          "type":  "file",
          "name":  "Copying aero.theme",
          "sourceUri":  "https://devicecustomizations.blob.core.windows.net/application-customizations/aero.theme",
          "destination":  "C:\\windows\\temp\\aero.theme"
      },
      {
          "type":  "file",
          "name":  "Copying Lockscreen.jpg",
          "sourceUri":  "https://devicecustomizations.blob.core.windows.net/application-customizations/Lockscreen.jpg",
          "destination":  "C:\\windows\\temp\\Lockscreen.jpg"
      },
      {
          "type":  "file",
          "name":  "Copying Wallpaper.jpg",
          "sourceUri":  "https://devicecustomizations.blob.core.windows.net/application-customizations/Wallpaper.jpg",
          "destination":  "C:\\windows\\temp\\Wallpaper.jpg"
      },
      {
          "type":  "file",
          "name":  "Copying DefaultAppAssociations.xml",
          "sourceUri":  "https://devicecustomizations.blob.core.windows.net/application-customizations/DefaultAppAssociations.xml",
          "destination":  "C:\\windows\\temp\\DefaultAppAssociations.xml"
      },
      {
          "type":  "PowerShell",
          "name":  "customizesystem",
          "runElevated":  true,
          "runAsSystem":  true,
          "scriptUri":  "https://devicecustomizations.blob.core.windows.net/application-customizations/BrandWindows10.ps1"
      },
      {
          "type":  "WindowsRestart",
          "restartCheckCommand":  "write-host 'restarting after Customize System'",
          "restartTimeout":  "5m"
      }
  ],

Where the aib.json file just needs a single application with file dependencies and the sequencer.ps1 will generate the code above during deployment

"customSequence":  [
        {
            "type": "Application",
            "name": "Customize System",
            "workingDirectory": "Customizations",
            "executable": "BrandWindows10.ps1",
            "fileDependency": [
                "aero.theme",
                "Lockscreen.jpg",
                "Wallpaper.jpg",
                "DefaultAppAssociations.xml"
            ],
            "restart": "true"
        }
    ],
  1. Example: to install an application from blob source and say it requires a reboot step while dealing with file dependency like the example 1. In the aib.json you can specify items like:
  • arguments
  • restart

In the customsequence it would look like:

 {
            "type": "Application",
            "name": "Install Office365 for MultiSession",
            "workingDirectory": "Office365",
            "executable": "setup.exe",
            "arguments": "/configure <destination>\\Customization.xml",
            "fileDependency": [
                "Customization.xml"
            ],
            "restart": "True"
        },

When ran with sequencer.ps1, it will produce the needed customizations for azure image builder

 {
    "type":  "PowerShell",
    "name":  "Creating folder 'C:\\Windows\\AIB\\Office365'",
    "runElevated":  true,
    "runAsSystem":  true,
    "inline":  [
                  "New-Item 'C:\\Windows\\AIB\\Office365' -ItemType Directory -ErrorAction SilentlyContinue"
              ]
},
{
    "type":  "file",
    "name":  "Copying Customization.xml",
    "sourceUri":  "https://devicecustomizations.blob.core.windows.net/application-office365/Customization.xml",
    "destination":  "C:\\Windows\\AIB\\Office365\\Customization.xml"
},
{
    "type":  "file",
    "name":  "Copying Office365",
    "sourceUri":  "https://devicecustomizations.blob.core.windows.net/application-office365/setup.exe",
    "destination":  "C:\\Windows\\AIB\\Office365\\setup.exe"
},
{
    "type":  "PowerShell",
    "name":  "Installing Office365",
    "runElevated":  true,
    "runAsSystem":  true,
    "inline":  [
                  "$result = Start-Process -FilePath C:\\Windows\\AIB\\Office365\\setup.exe -ArgumentList '/configure C:\\Windows\\AIB\\Office365\\Customization.xml' -Wait -PassThru",
                  "Return $result.ExitCode"
              ]
},
{
    "type":  "WindowsRestart",
    "restartCheckCommand":  "write-host 'restarting after Install Office365 for MultiSession'",
    "restartTimeout":  "5m"
},

CustomSequence properties

The AIB Deployment Toolkit supports multiple customsequences. A customSequence is the order of how to install items such as script, apps, modules, updates and even reboots. It simplifies the need to call multiple customize property found here

Here are the many customsequences types that can be used:

All types support restart Boolean property

Type: Applications

All applications and scripts are elevated and run as system.

Supported parameters are:

  • Name - Name of the process
  • workingDirectory – Folder at which the application is installed from. The root starts with c:\temp
  • executable – The executable to run. This can be [ps1, exe or msi]
  • arguments – Optional, Provide the parameters need to run silently. The <destination> designated allows for additional path support
  • fileDependency - Optional, array, triggers the File copy customization.
  • sasToken – Optional, Provide Sas token from blob container. Do not provide full URI, it is built from this

When using sastoken in conjunction with fileDependency, only one file is supported

Example one

Install application using script from blob uri (no file download)

"customSequence":  [
      {
            "type": "Application",
            "name": "Install LGPO",
            "workingDirectory": "LGPO",
            "executable": "Install-LGPO.ps1",
            "arguments": "",
            "restart": "False"
        }
    ]

Example two

download all files and install application using script from blob uri, then reboot when complete

"customSequence":  [
        {
            "type": "Application",
            "name": "Customize System",
            "workingDirectory": "Customizations",
            "executable": "BrandWindows10.ps1",
            "fileDependency": [
                "aero.theme",
                "Lockscreen.jpg",
                "Wallpaper.jpg"
            ],
            "restart": "true"
        }
    ]

Example three

Download zipped file using a SaS token and extract, then install application using command and argument

"customSequence":  [
        {
            "type": "Application",
            "name": "Install Foxit PDF Reader",
            "workingDirectory": "FoxitPDFReader",
            "fileDependency": [
                "FoxitPDFReader.zip"
            ],
            "sasToken": "sp=r&st=2022-09-06T15:11:06Z&se=2022-09-06T23:11:06Z&spr=https&sv=2021-06-08&sr=b&sig=o0Y3SZ9jJBakVyxtIb8rhbEzJFiCcc5K%2FxvRWsTaS8U%3D",
            "executable": "FoxitPDFReader1201_enu_Setup.msi",
            "arguments": "/quiet ADDLOCAL=\"FX_PDFVIEWER\""
        },
    ]

Type: ModernApp

Uses the Inline customization in AIB, but specifically designed to install appx bundles offline.

Supported parameters are:

  • Name - Name of the process
  • workingDirectory – Folder at which the zip files is extracted to. The root starts with c:\temp
  • appxDependency - Optional, array, triggers the File copy customization
  • appxBundle – the Appx bundle to install.
  • appxLicense – the License file to load during install
  • sasToken – Optional, Provide Sas token from blob container. Do not provide full URI, it is built from this

When using sastoken in conjunction with appxDependency, only one zip file is supported. Include all appx, bundle, and license files in zip

Example 1

download each appx dependency include license and bundle, and install

"customSequence":  [
        {
            "type": "ModernApp",
            "name": "Install Microsoft News App",
            "workingDirectory": "NewsAppx",
            "appxDependency": [
                "Microsoft.NET.Native.Framework.2.2_2.2.29512.0_x64__8wekyb3d8bbwe.appxbundle",
                "Microsoft.NET.Native.Runtime.2.2_2.2.28604.0_x64__8wekyb3d8bbwe.appxbundle",
                "Microsoft.UI.Xaml.2.1_2.11906.6001.0_x64__8wekyb3d8bbwe.appxbundle",
                "Microsoft.VCLibs.140.00_14.0.30704.0_x64__8wekyb3d8bbwe.appxbundle"
            ],
            "appxBundle": "Microsoft.BingNews_4.9.30001.0_neutral_~_8wekyb3d8bbwe.appxbundle",
            "appxLicense": "Microsoft.BingNews_8wekyb3d8bbwe_1f63b8c3-2d48-9497-0a0a-2cbd462ede76.xml"
        },
    ]

Example 2

download appx dependency zipped file, extract and install

"customSequence":  [
        {
            "type": "ModernApp",
            "name": "Install Microsoft News App",
            "workingDirectory": "NewsAppx",
            "sasToken": "sp=r&st=2022-09-03T19:23:53Z&se=2022-09-04T03:23:53Z&spr=https&sv=2021-06-08&sr=b&sig=2FoV6VhJ2lFMK8OOrhFvwpYYICEeHqNUq5UwOZmsjfA%3D",
            "appxDependency": [
                "Microsoft.BingNews.4.9.30001.0.zip"
            ],
            "appxBundle": "Microsoft.BingNews_4.9.30001.0_neutral_~_8wekyb3d8bbwe.appxbundle",
            "appxLicense": "Microsoft.BingNews_8wekyb3d8bbwe_1f63b8c3-2d48-9497-0a0a-2cbd462ede76.xml"
        },
    ]

Type: Command

Based on the idea of the Inline customization in AIB, but builds the inline commands automatically to include the ability to arguments and reboot

Supported parameters are:

  • Name - Name of the process
  • workingDirectory – Folder at which the zip files is extracted to. The root starts with c:\temp
  • command – The command to run; this will read the commands extension and determine the appropriate inline command (supported file extensions: .vbs, .ps1, .exe, .msi)
  • arguments – Optional, Provide the parameters need to run silently. The <destination> designated allows for additional path support

Example 1

run script. Assume its downloaded already

"customSequence":  [
        {
            "type": "Command",
            "name": "Install Apps",
            "workingDirectory": "Apps",
            "command": "Install.ps1",
            "restart": "false"
        }
    ]

Example 2

Run dism command and reboot

"customSequence":  [
        {
            "type": "Command",
            "name": "Cleanup image base",
            "command": "Dism.exe",
            "arguments": "/online /Cleanup-Image /StartComponentCleanup /ResetBase",
            "restart": "true"
        }
    ]

Type: Module

Uses the Inline customization in AIB, but specifically targets PowerShell modules.

Supported parameters are:

  • modules – Array, The list of modules to install
  • TrustedRepos - Optional, array, a list of repository to trust.
"customSequence":  [
        {
            "type": "Module",
            "modules": [
                "LGPO",
                "YetAnotherCMLogger",
                "MSFTLinkDownloader"
            ],
            "trustedRepos": [
                "PSgallery"
            ]
        },
    ]

Type: Archive

This process generates additional Inline customizations to auto download AzCopy and trigger AzCopy copy commands to support the optional SAS Token URI

Supported parameters are:

  • Name - Name of the process
  • workingDirectory – Folder at which the zip files is extracted to. The root starts with c:\temp
  • archiveFile – The single archive file to extract (supported extensions: .zip and .cab). This can be [ps1, exe or msi]
  • sasToken – Optional, Provide Sas token from blob container. Do not provide full URI, it is built from this
"customSequence":  [
        {
            "type": "Archive",
            "name": "Get Apps",
            "workingDirectory": "Apps",
            "archiveFile": "Apps.zip",
            "sasToken": "sp=r&st=2022-09-03T19:23:53Z&se=2022-09-04T03:23:53Z&spr=https&sv=2021-06-08&sr=b&sig=2FoV6VhJ2lFMK8OOrhFvwpYYICEeHqNUq5UwOZmsjfA%3D"
        }
    ]

Type: WindowsUpdate

Based on the idea of the WindowsUpdate command for the AIB customization, but with standard options. Filter capability not available; but may be coming soon

Supported parameters are:

  • restartTimeout - Optional, boolean, generates the WindowsRestart customization with 10 minute timeout
"customSequence":  [
        {
            "type": "WindowsUpdate",
            "restartTimeout": "10"
        }
    ]

Type: Restart

Based on the idea of the WindowsRestart for the AIB customization, but simpler. Not typically used since most other customsequence support restarts

Supported parameters are:

  • Name - Name of the process
"customSequence":  [
        {
            "type": "Restart",
            "Name": "One last reboot"
        }
    ]

References

DISCLAIMER

Even though I have tested this to the extend that I could, I want to ensure your aware of Microsoft’s position on developing custom scripts.

This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment. THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. We grant You a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute the object code form of the Sample Code, provided that You agree: (i) to not use Our name, logo, or trademarks to market Your software product in which the Sample Code is embedded; (ii) to include a valid copyright notice on Your software product in which the Sample Code is embedded; and (iii) to indemnify, hold harmless, and defend Us and Our suppliers from and against any claims or lawsuits, including attorneys’ fees, that arise or result from the use or distribution of the Sample Code.

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/en-us/legal/copyright.

About

A project for managing process for Azure Image Builder using PowerShell

License:MIT License


Languages

Language:PowerShell 100.0%