It's been a little while since I last posted here. I've been having a very busy and productive time at work. Let's jump in to some of the stuff I've learned over the past couple of weeks. Come on! It'll be fun!
Or not. Who knows? More importantly, who cares what you think? It's my blog and I WILL cry when I want to.
It's All About the Cloud
As we all know, Cloud services are the way absolutely everything on God's green bloody earth are going these days. Microsoft device management is no different. So, of course, with our upcoming move to Windows 10 we need to devise a way to get all of our mobile devices managed by InTune rather than SCCM and Azure Active Directory rather than on-prem AD just so we can ship them out into the big wide world and still keep them managed. This sounds like it should be easy, but when you're working at the scale my job is working at the prospect of joining devices in bulk to Azure cloud services is daunting. Microsoft's official recommendation seems to be going to each device in turn and joining them to AAD/InTune using the built-in wizard, but of course we don't have the time or staff to do that. Let's script it out instead!
OSD Teething Issues
So you've built your Windows 10 image and got everything set up just how you like it. You insert it into your task sequence, and start applying all your drivers and software. Unfortunately, you're trying to use Office 365 Pro Plus with shared user activation and have packaged it as an application as per Microsoft's instructions. Well, let me tell you now sonny Jim, that ain't gonna work. While the deployment of this application will actually be successful, you are going to see your builds failing with error code 16389 A LOT when trying to run this in the OSD. What is error code 16389? Fuck knows. A lot of Googling brought up nothing useful.
Now you're running around like a headless chicken changing every single deployment rule you can think of. When you try installing on a live system, it returns code 0 so clearly it's working. Try it again in the OSD, 16389. Utter madness. I spent a good day and a half trying to work out what the hell could be wrong. The detection method was right, the application worked, the content was accessible and upon completing the build the software was present, but the error code caused the sequence to complete with some problems
So how do we get around this? We've used the wizard and packaged everything up nice exactly how M$ recommends but it's still not working. Well then. Clearly, Microsoft doesn't know what they're talking about. Let's instead build the O365 PP installer as a traditional package with a script installer. Does it work now? You're goddamn right it does. No more software failures!
So one thing you're going to come across that can stump you a little is setting up InTune as the authority for software management on your mobile device. See, when you build a machine using SCCM you load a config manager client on to the machine which deals with setting up software and managing communication to the CCM server. However, the presence of this client will cause InTune to reject the machine as it doesn't have the proper authority. Since we're not going down the path of co-management (InTune only for mobile devices), we need to get that off of there.
Now, the trick with this is remembering that getting rid of the CCM client will ALWAYS cause a task sequence failure. If you insert a script as the last step with the command C:\Windows\ccmsetup\ccmsetup.exe /uninstall you're going to get a whole load of error messages in your trace log and ultimately the build will fail. This is going to cause oddities. We need a smarter way around this. One way would be to set up a Powershell script in the build which sets a scheduled task to run the command after the machine's first boot, but surprisingly there's a more elegant way to do it.
If you add a Task Sequence variable during the OS setup with the variable SMSTSPostAction and write the above script in as a command, the machine will store this command to run it upon successful completion of the task sequence. After a bit of testing and tweaking, I started to get successful builds with no CCM client on them at all. All the benefits of the OSD with none of the residuals! Hoorah!
Azure AD is a Bastard
Okay, so we know that these machines need to join Azure AD and not on-prem AD. This seems like it should be easy enough, but unfortunately Microsoft are not keen on bulk joining devices like this. Eventually, it looks like they caved under the pressure from (justifiably) annoyed enterprise customers and created a WICD tool to enable bulk enrollment using a ppkg.
We used a ppkg to set some of our customization in the build, so we were fairly confident this would work perfectly. Using DISM, we applied both to the image and watched eagerly for our asset to appear in AAD.
It never did.
We saw a device joining, for sure, but it wasn't anything we recognised. "DESKTOP-£&$*£&*" something or other. Not anything like our standard naming convention. But it was being joined by the bulk join account. Hmm.
So I did a bit of digging around in the registry and found the issue. The machine's ORIGINAL name is DESKTOP-whatever. This value gets changed in the TS but only once you boot in to the live image. Of course, using DISM we're working with an offline image, so it's joining the machine using this old name and then going online. Well that's not good enough. We need to find a way to apply the package using an online image. To cut a long story short, here's how I did it.
First, we add a step in the TS to map a network drive. We point this to the UNC of the folder on our config manager server where the PPKG is stored and we use a login with the relevant permissions to access it so we can be sure it's picking it up. Then, we write the Powershell script to actually install the ppkg:
Install-ProvisioningPackage -Path "YourPackage.ppkg" -ForceInstall -QuietInstall
Now just package up that script, add a step to run it after mapping the drive. Badda-bing, badda-boom, the machine now joins AAD with the name you assigned in the TS. Hooray!
The next step is to ensure that your machine Bitlockers properly and passes the key back to AAD so that your organisation can recover it if necessary. This is easy enough when you have a device like a Surface which supports InstantGo, but I'm not lucky enough to just be working with these high-end devices. Some of our devices are kind of shit, yo. So we need a universal solution. Powershell to the rescue once more.
The trick here is the order in which you do things. This Bitlocker step should obviously be placed after the Azure AD Join step we made earlier. The machine will then need to provision a key, back up the key to Azure AD and then encrypt the drive with that key. The script looks like this:
#Provision the key first and force it to encrypt the drive with the provisioned key Add-BitLockerKeyProtector -MountPoint "C:" -RecoveryPasswordProtector #Create the variable $BLV with the value of the bitlocker'd C:\ drive $BLV = Get-BitLockerVolume -MountPoint "C:" #Back the key up to Azure for the drive that needs to be encrypted, assigning the drive's ID BackupToAAD-BitLockerKeyProtector -MountPoint "C:" -KeyProtectorId $BLV.KeyProtector.KeyProtectorId #Enable Bitlocker on the system drive (without a login pin) Enable-BitLocker -MountPoint "C:" -EncryptionMethod XtsAes256 -UsedSpaceOnly -TpmProtector
Package it, add the step, and move on with your life. The machine will now Bitlocker the used space and back the key up to the item in Azure AD.
This last bit is the bit I still haven't got working. As I mentioned before, we're trying to give InTune full authority over the devices rather than SCCM, so what we've looked at doing is setting up a group within AAD which have device adding rights. As of yet, the devices are not pulling through to InTune despite being owned by the users in that group. From what I can see, we may not be able to get it working that way. However, my suspicion is that if we use CCM's co-management setup during the build but then remove the CCM client as per the steps above, it will enroll the device and remove CCM's authority. More testing is required, but hopefully we'll have got it working next week.
Phew! It's been a bit of a slog, but a very productive one. Hope someone finds this somewhat useful.