Last active
December 18, 2024 12:45
-
-
Save Geofferey/98dd0664e7c9df3f7fd7b76d11bfd145 to your computer and use it in GitHub Desktop.
A Script for logging into Tailscale via preauth key stored in Active Direcotry
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ## I am a custom Script for logging TailScale in on boot using tsPreAuthKey attribute stored in AD Schema | |
| # This requires permanent modification to the schema for storing the PreAuthKey: | |
| # https://www.rebeladmin.com/step-step-guide-create-custom-active-directory-attributes/ | |
| # https://legacy.support.exclaimer.com/hc/en-gb/articles/360028648572-How-to-create-new-custom-AD-attributes-for-use-in-a-signature-template | |
| # Do NOT issue re-useable PreAuthTokens and store in AD, that would be foolish, storing them period might be ;)) | |
| # Execute me as a Computer policy based powershell startup script | |
| # Schduled task is also an option, may not work on first run | |
| # | |
| $env:Path = 'C:\Program Files\Tailscale;' + $env:Path | |
| $logF = "C:\ProgramData\Tailscale\tailscale-login.log" | |
| $serviceTimeout = 60 | |
| $jobTimeout = 60 | |
| $startTime = Get-Date | |
| $serviceName = 'tailscale' | |
| $tailscaleExe = "C:\Program Files\Tailscale\tailscale.exe" | |
| $tailscaleipnExe = "C:\Program Files\Tailscale\tailscale-ipn.exe" | |
| $preAuthTestF = "C:\ProgramData\TailScale\preauth" | |
| ##HINT: If a TS_LOGINURL specified in .msi/.mst/registry this cannot be changed, likely for security reasons | |
| $loginServer = "https://controlplane.tailscale.com" | |
| ## Function for getting AD computer attributes since RSAT is not available on every computer, duh | |
| function Get-Attributes ($arg1) { | |
| $searcher = New-Object system.directoryservices.directorysearcher | |
| $searcher.PropertiesToLoad.AddRange(@($arg1)) | |
| $null = $searcher.Filter = "(name=$env:ComputerName)" | |
| $result = $searcher.FindOne() | |
| $attribute = $result.properties.$arg1 | |
| echo $attribute | |
| } | |
| if (Test-Path -Path $preAuthTestF) { | |
| Move-Item $logF $logF'.old' | |
| } | |
| Start-Transcript -path $logF | |
| Write-Host $(Date) | |
| $domainName = (Get-CimInstance -ClassName Win32_ComputerSystem).Domain | |
| $compatMod = "\\$DomainName\SYSVOL\$domainName\Installers\tailscale.sdb" | |
| Write-Host "Grabbing the current machine's PreAuthKey from $domainName Active Directory..." | |
| $tspreauthkey = (Get-Attributes tspreauthkey) | |
| $tsloginurl = (Get-Attributes tsloginurl) | |
| ## This method left for historical purposes | |
| #$tsloginurl = (Get-ADComputer -identity $Env:ComputerName -properties tsloginurl).tsloginurl | |
| #$tspreauthkey = (Get-ADComputer -identity $Env:ComputerName -properties tspreauthkey).tspreauthkey | |
| Write-Host "Current PreAuthKey: $tspreauthkey" | |
| ## A script block for Job-Start because the variables will not be evaluated otherwise | |
| # https://stackoverflow.com/questions/19834643/powershell-how-to-pre-evaluate-variables-in-a-scriptblock-for-start-job | |
| $tsLogin = [scriptblock]::Create("tailscale up --reset --force-reauth --login-server=$loginServer --shields-up --authkey=$tspreauthkey --accept-dns --accept-routes --unattended") | |
| if ($tsloginurl -ne $null) { | |
| $loginServer = $tsloginurl | |
| } | |
| ## Log off if no key defined and no error when pulling key | |
| if ($tspreauthkey -eq $null -and (Get-Attributes tspreauthkey)) { | |
| Write-Host "No key defined in AD, logging out..." | |
| tailscale logout | |
| exit 0 | |
| } | |
| Write-Host "Current LoginURL: $loginServer" | |
| if (-Not (Test-Path -Path $tailscaleExe)) { | |
| Write-Host "tailscale.exe not found, quitting.." | |
| exit 1 | |
| } | |
| ## Install custom application compatibility db mod to force GUI app to run-as admin when executed | |
| Write-Host "Installing compatibility admin database run-as admin" | |
| sdbinst.exe -p -q $compatMod | |
| ## Wait for the tailscaled service to start | |
| do { | |
| $serviceStatus = (Get-Service -Name $serviceName).Status | |
| if ($serviceStatus -eq "Running") { | |
| Write-Host "The '$serviceName' service started successfully." | |
| break | |
| } | |
| Start-Sleep -Seconds 1 | |
| } while ((New-TimeSpan -Start $startTime).TotalSeconds -lt $serviceTimeout) | |
| if ($serviceStatus -ne "Running") { | |
| Write-Host "Timeout waiting for the '$serviceName' service to start." | |
| } | |
| ## Execute a first time login proceedure and store the used preauth key to detect future changes | |
| if (-Not (Test-Path -Path $preAuthTestF)) { | |
| Write-Host "Executing the tailscale login proceedure for the first time..." | |
| $job = Start-Job $tsLogin | |
| if ($job -ne "error") { | |
| Wait-Job $job -timeout $jobTimeout | |
| Write-Host | |
| if ($job.State -eq 'Completed' -and -not $job.Error) { | |
| Write-Host "Saving the used key to file for later comparison..." | |
| echo $tspreauthkey > $preAuthTestF | |
| } else { | |
| Write-Host "Could not complete the login operation in a timely manner..." | |
| } | |
| } | |
| } | |
| $oldtspreauthkey = Get-Content -Path $preAuthTestF | |
| echo $oldtspreauthkey | |
| if ($tspreauthkey -ne $oldtspreauthkey) { | |
| Write-Host "PreAuthKey change detected in Active Directory, re-running login proceedure..." | |
| $job = Start-Job $tsLogin | |
| if ($job -ne "error") { | |
| Wait-Job $job -timeout $jobTimeout | |
| Write-Host | |
| if ($job.State -eq 'Completed' -and -not $job.Error) { | |
| Write-Host "Saving the used key to file for later comparison..." | |
| echo $tspreauthkey > $preAuthTestF | |
| } else { | |
| Write-Host "Could not complete the login operation in a timely manner..." | |
| } | |
| } | |
| } | |
| Stop-Transcript | |
| exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment