Add logon script to set computer ManagedBy attribute
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
#Requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sets the Active Directory computer object's "Managed By" attribute to the currently logged-in user.
|
||||
|
||||
.DESCRIPTION
|
||||
Designed to run as a GPO User Logon Script. On each login, it resolves the current
|
||||
user and computer in AD, then stamps the user's Distinguished Name into the computer
|
||||
object's "managedBy" attribute.
|
||||
|
||||
PREREQUISITES:
|
||||
- The RSAT ActiveDirectory PowerShell module must be installed on client machines,
|
||||
OR the script can fall back to ADSI/DirectorySearcher (no module needed).
|
||||
- AD permissions must be delegated so that Authenticated Users (or Domain Users)
|
||||
can WRITE the "managedBy" attribute on Computer objects in the relevant OU(s).
|
||||
See README.md for delegation instructions.
|
||||
|
||||
.NOTES
|
||||
Deploy via: GPO > User Configuration > Policies > Windows Settings > Scripts > Logon
|
||||
Filename: Set-ComputerManagedBy.ps1
|
||||
#>
|
||||
|
||||
# ── Configuration ────────────────────────────────────────────────────────────
|
||||
$LogFile = "$env:TEMP\Set-ComputerManagedBy.log"
|
||||
$MaxLogSizeKB = 256
|
||||
|
||||
# ── Logging helper ───────────────────────────────────────────────────────────
|
||||
function Write-Log {
|
||||
param([string]$Message, [string]$Level = "INFO")
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$entry = "[$timestamp] [$Level] $Message"
|
||||
# Rotate log if oversized
|
||||
if ((Test-Path $LogFile) -and ((Get-Item $LogFile).Length / 1KB -gt $MaxLogSizeKB)) {
|
||||
Remove-Item $LogFile -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
Add-Content -Path $LogFile -Value $entry -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
# ── Gather environment ──────────────────────────────────────────────────────
|
||||
$currentUser = $env:USERNAME
|
||||
$computerName = $env:COMPUTERNAME
|
||||
$userDomain = $env:USERDOMAIN
|
||||
|
||||
Write-Log "Script started. User=$userDomain\$currentUser, Computer=$computerName"
|
||||
|
||||
# ── Skip if local/non-domain login ──────────────────────────────────────────
|
||||
if ($userDomain -eq $computerName) {
|
||||
Write-Log "Local login detected (domain = computername). Skipping." "WARN"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# ── Try AD module first, fall back to ADSI ──────────────────────────────────
|
||||
$useADModule = $false
|
||||
try {
|
||||
Import-Module ActiveDirectory -ErrorAction Stop
|
||||
$useADModule = $true
|
||||
Write-Log "Using ActiveDirectory PowerShell module."
|
||||
} catch {
|
||||
Write-Log "AD module not available. Falling back to ADSI/DirectorySearcher." "WARN"
|
||||
}
|
||||
|
||||
try {
|
||||
if ($useADModule) {
|
||||
# ── AD Module path ──────────────────────────────────────────────────
|
||||
$userObj = Get-ADUser -Identity $currentUser -ErrorAction Stop
|
||||
$computerObj = Get-ADComputer -Identity $computerName -ErrorAction Stop
|
||||
|
||||
$currentManagedBy = (Get-ADComputer -Identity $computerName -Properties managedBy).managedBy
|
||||
|
||||
if ($currentManagedBy -eq $userObj.DistinguishedName) {
|
||||
Write-Log "ManagedBy already set to $currentUser. No change needed."
|
||||
exit 0
|
||||
}
|
||||
|
||||
Set-ADComputer -Identity $computerName -ManagedBy $userObj.DistinguishedName -ErrorAction Stop
|
||||
Write-Log "SUCCESS: Set ManagedBy on '$computerName' to '$($userObj.DistinguishedName)'"
|
||||
|
||||
} else {
|
||||
# ── ADSI fallback (no module required) ──────────────────────────────
|
||||
$rootDSE = [ADSI]"LDAP://RootDSE"
|
||||
$domainDN = $rootDSE.defaultNamingContext
|
||||
|
||||
$searcher = New-Object DirectoryServices.DirectorySearcher
|
||||
$searcher.SearchRoot = [ADSI]"LDAP://$domainDN"
|
||||
|
||||
# Find the user DN
|
||||
$searcher.Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=$currentUser))"
|
||||
$searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null
|
||||
$userResult = $searcher.FindOne()
|
||||
|
||||
if (-not $userResult) {
|
||||
Write-Log "Could not find user '$currentUser' in AD." "ERROR"
|
||||
exit 1
|
||||
}
|
||||
$userDN = $userResult.Properties["distinguishedname"][0]
|
||||
|
||||
# Find the computer DN
|
||||
$searcher.Filter = "(&(objectCategory=computer)(sAMAccountName=$computerName$))"
|
||||
$searcher.PropertiesToLoad.Clear()
|
||||
$searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null
|
||||
$searcher.PropertiesToLoad.Add("managedBy") | Out-Null
|
||||
$computerResult = $searcher.FindOne()
|
||||
|
||||
if (-not $computerResult) {
|
||||
Write-Log "Could not find computer '$computerName' in AD." "ERROR"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$computerDN = $computerResult.Properties["distinguishedname"][0]
|
||||
|
||||
# Check current value
|
||||
$currentManagedBy = $null
|
||||
if ($computerResult.Properties["managedby"].Count -gt 0) {
|
||||
$currentManagedBy = $computerResult.Properties["managedby"][0]
|
||||
}
|
||||
|
||||
if ($currentManagedBy -eq $userDN) {
|
||||
Write-Log "ManagedBy already set to $currentUser. No change needed."
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Set the attribute via ADSI
|
||||
$computerEntry = [ADSI]"LDAP://$computerDN"
|
||||
$computerEntry.Put("managedBy", $userDN)
|
||||
$computerEntry.SetInfo()
|
||||
|
||||
Write-Log "SUCCESS: Set ManagedBy on '$computerName' to '$userDN'"
|
||||
}
|
||||
} catch {
|
||||
Write-Log "FAILED to set ManagedBy: $($_.Exception.Message)" "ERROR"
|
||||
exit 1
|
||||
}
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user