Azure Automation Week: Advanced Offline Domain Join With Azure Automation!
Azure automation week continues! Today we are going to look at joining computers to a domain through Azure Automation. I always liked the idea of offline domain join, but never really used it since I don’t prestage computers. I then got the idea, what if I could join a computer to the domain from offsite without having to prestage it first?
To do this, we will need to set some things up! First off, if you want the domain joined computer to get group policies right away, you’ll need direct access. If you are on a lab, go ahead and set it up with these instructions. Don’t worry if you don’t have direct access. You can still do this demo, it just won’t be as cool.
Second, I’ll be using the PowerShell ISE to work on the Azure Automation scripts. You will need the Azure Automation PowerShell ISE add-on to follow along. This really is a must have add-on if you want to develop in Azure Automation!
Third, I need the Active Directory cmdlets installed on my hybrid worker computer. My offline domain join script will use those cmdlets to create the computer account, so they are needed on the server the script runs on.
Once you have the add-on installed, open your ISE. You should see it on the right side when you open the console:
Be sure to sign into your account, then make sure the right subscription and automation account are selected.
To create a computer account, I’m going to need the credentials of a user that has those permissions. In Azure Automation, we can store credential objects in the cloud, and access them through the Azure cmdlets in our scripts. We can use a credential asset for this. Go to the Assets tab, then select new:
Choose the asset type and give it a name:
Once you click Ok, it will ask for the username and password. You must specify the username in Domain\UserName format:
Click Ok, then you have your new credential object! Right now, it is only local. You must hit “Upload” on the bottom to send it to the cloud. Once you do, the status will change to “In Sync”
Follow this procedure to create another Asset of type Variable for the Direct Access server name, if you have one:
Make sure you upload this to the cloud!
Now, you need to create a PowerShell runbook. Go to the Runbooks tab, and select Create New at the bottom. Enter a name for it (Mine is OfflineDomainJoin) and make sure it is a Script type. After it’s created, the script should be open in the window. First off, we need to know some parameters. To make this easier, we will only ask for ComputerName and Path. This way we can create a computer in the right location:
param ( $ComputerName, $Path = 'CN=Computers,DC=Home,DC=Lab' )
I’ll also need to import the active directory module, so be sure to say Import-Module ActiveDirectory
In the ISE, we are now going to access the DirectAccessServer variable. Type in $DAServer = then, hit insert on the right side:
You’ll want to do the same for your AD credential object.
The rest of the script is pretty straight forward. You’re going to create the AD computer, put it in the right OU, then add it to the Direct Access AD group (assuming you have DA):
$dName = "CN=$($Computername),$($Path)" $DirectAccessADGroup = 'Direct Access Clients' $null = New-ADComputer -Name $ComputerName -SAMAccountName $ComputerName -Path $Path -Enabled $true -Credential $ADCreds -PassThru $null = Add-ADGroupMember $DirectAccessADGroup -Members $dName -Credential $ADCreds
Now, for the domain join piece. I could not for the life of me get this to work on the same server as the hybrid runbook worker. The hybrid runbook worker will run your scripts as the system context, so you have to run it as a domain user to run djoin. The only thing I could get working was starting a PowerShell process on a remote machine to do the djoin step. Because of this, make sure DirectAccessServer is a remote computer!
The djoin step involves running a scriptblock on a remote machine. This scriptblock does the djoin step and then copies the file from the DiretAccessServer to the hybrid runbook worker:
$Session = New-PSSession -ComputerName $DAServer -Credential $ADCreds $djoinScriptBlock = { $ComputerName = $args[0] $HybridWorkerServer = $args[1] djoin.exe /provision /machine "$ComputerName" /domain "Home.Lab" /policynames "DirectAccess Client Settings" /savefile "c:\$ComputerName.txt" /reuse Copy-Item "c:\$ComputerName.txt" "\\$HybridWorkerServer\c$\" -Force Remove-Item "c:\$ComputerName.txt" -Force } $djoinResults = Invoke-Command -Session $Session -ScriptBlock $djoinScriptBlock -ArgumentList $ComputerName,$env:COMPUTERNAME
Lastly, I need to get the contents of the file, then remove the file, then return the file contents:
if (Test-Path "C:\$ComputerName.txt") { $FileContent = Get-Content "C:\$ComputerName.txt" Remove-Item "C:\$ComputerName.txt" -Force $count=100 } return $FileContent
Now, hit the “Upload Draft” button, then “Publish Draft” and now we are ready to test it out!
I’ll use my function from yesterday to invoke the runbook through PowerShell:
After a minute, I should get results:
I can now output $Results to a file and do an offline domain join with it! If that computer also has your direct access certificate, you will have direct access and start receiving group policies on the computer!
That’s it for today! Join me tomorrow when I build off the information we learned today to pull data from SCSM into Azure Automation. Then on Friday I’ll shove all of this into a SCCM task sequence!
Full script here:
param ( $ComputerName, $Path = 'CN=Computers,DC=Home,DC=Lab' ) Import-Module ActiveDirectory $DAServer = Get-AutomationVariable -Name "DirectAccessServer" $ADCreds = Get-AutomationPSCredential -Name "ADCredentials" $dName = "CN=$($Computername),$($Path)" $DirectAccessADGroup = 'Direct Access Clients' $null = New-ADComputer -Name $ComputerName -SAMAccountName $ComputerName -Path $Path -Enabled $true -Credential $ADCreds -PassThru $null = Add-ADGroupMember $DirectAccessADGroup -Members $dName -Credential $ADCreds $Session = New-PSSession -ComputerName $DAServer -Credential $ADCreds $djoinScriptBlock = { $ComputerName = $args[0] $HybridWorkerServer = $args[1] djoin.exe /provision /machine "$ComputerName" /domain "Home.Lab" /policynames "DirectAccess Client Settings" /savefile "c:\$ComputerName.txt" /reuse Copy-Item "c:\$ComputerName.txt" "\\$HybridWorkerServer\c$\" -Force Remove-Item "c:\$ComputerName.txt" -Force } $djoinResults = Invoke-Command -Session $Session -ScriptBlock $djoinScriptBlock -ArgumentList $ComputerName,$env:COMPUTERNAME if (Test-Path "C:\$ComputerName.txt") { $FileContent = Get-Content "C:\$ComputerName.txt" Remove-Item "C:\$ComputerName.txt" -Force $count=100 } return $FileContent
Leave a Comment