\ ps script - /g/pasta 2.4
From me, 2 Weeks ago, written in PowerShell.
Embed
  1. #mini log function to keep track of what happened.
  2. function write-log {
  3.     param($logval)
  4.  
  5.     if([bool](test-path "d:\shares\d\tombstone-script.log")){
  6.         "$((Get-Date -Format yyyyMMddmmss).tostring()) - $logval - $env:username" >> "d:\shares\d\tombstone-script.log"
  7.     }else{
  8.         Write-Verbose "NO LOG FOUND " + "$((Get-Date -Format yyyyMMddmmss).tostring()) - $logval - $env:username"
  9.     }
  10. }
  11.  
  12. #drop file if we dont want to run the script any more because of errors that arent easy to fix
  13. function dontrunagain {
  14.     out-file "d:\shares\d\dontrunagain.txt"
  15. }
  16.  
  17. if([bool](Test-Path "d:\shares\d\dontrunagain.txt")){
  18.     write-log -logval "Hit Dont Run Again Condition"
  19.     break
  20. }
  21.  
  22. if(![bool](test-path "d:\shares\d\tombstone-script.log")){
  23.     try{
  24.         out-file "d:\shares\d\tombstone-script.log"
  25.         write-log -logval "Started UN-Tombstone Script"
  26.     }catch{
  27.         throw "Error Creating The Log File, Create It By Hand At 'd:\shares\d\tombstone-script.log' And Rerun The Script/Scheduled Task"
  28.     }
  29. }
  30.  
  31. #create a credential object so we can promote/demote and join member servers back
  32. $svcusr  = "dc_local\user"
  33. $enc = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" #encoded password
  34.  
  35. try{
  36.     $bytes = [convert]::FromBase64String($enc)
  37.     $decstr = [System.Text.Encoding]::Unicode.GetString($bytes)
  38.     $pass = $decstr | ConvertTo-SecureString -AsPlainText -Force
  39. }catch{
  40.     write-log -logval "Couldnt Decrypt The Password File, Powershell Error: $($error[0])"
  41.     throw "Couldnt Decrypt The Password File"
  42. }
  43.  
  44. try{
  45.     $cred = new-object -typename System.Management.Automation.PSCredential($svcusr, $pass) -ErrorAction Stop
  46.     write-log -logval "Created Credentials for $svcusr"
  47. }catch{
  48.     write-log -logval "Couldnt Make A Credential Object, Powershell Error: $($error[0])"
  49.     throw "Couldnt Make A Credential Object"
  50. }
  51.  
  52. #check if we dropped a check file on the drive so we can switch on it.
  53. $postrebootcheck  = [bool](Test-Path "d:\shares\d\promo_check.txt")
  54. $postrebootcheck2 = [bool](Test-Path "d:\shares\d\promo_check2.txt")
  55.  
  56. #switch on the check file, either we ran last time and its there, meaning we tombstoned and demoted or we didnt tombstone and we are just going to check if we did.
  57. switch($postrebootcheck){
  58.    
  59.     $false {
  60.         #get the tombstone lifetime
  61.         try{
  62.             $adroot   = (Get-ADRootDSE -ErrorAction Stop).configurationNamingContext
  63.             $tombdays = (Get-ADObject -Identity “CN=Directory Service,CN=Windows NT,CN=Services,$adroot-Partition $adroot -Properties tombstoneLifetime -ErrorAction Stop).tombstoneLifetime
  64.         }catch{
  65.             write-log -logval "Couldnt Find Tombstone Days, Assuming 180 Instead"
  66.             $tombdays = 180
  67.         }
  68.  
  69.         try{
  70.             try{
  71.                 #try dcdiag first as its most likley going to work without having access to ad
  72.                 $dates  = dcdiag /test:replications
  73.  
  74.                 $found = for($i = 0; $i -lt $dates.count - 1; $i++){
  75.                     #if we find our tag line, minus one its index to get its date then regex out the date, \S+ is not spaces.
  76.                     if($dates[$i] -like "*WARNING:*"){
  77.                         ([regex]::Match($dates[$i - 1],'\S+ \S+')).value
  78.                     }
  79.                 }
  80.                
  81.                 $lastsync = $(foreach($f in $found){
  82.                     if($f -ne $null){
  83.                         [datetime]$f
  84.                     }
  85.                 }) | sort -Descending | select -first 1
  86.  
  87.                 if(!$lastsync){
  88.                     Write-log "DCDiag Failed"
  89.                     Write-Error "DCDiag Failed" -ErrorAction Stop
  90.                 }
  91.  
  92.                 write-log -logval "Found Last Sync Time"
  93.             }catch{
  94.                 write-log -logval "DCdiag Failed To Find Last Sync Time"
  95.  
  96.                 try{
  97.                     #Try with repadmin
  98.                     $rep      = (repadmin /showrepl /csv | convertfrom-csv)."last success time"
  99.                     $lastsync = $(foreach($r in $rep){
  100.                         [datetime]::ParseExact($r, "yyyy-MM-dd hh:mm:ss", $null)
  101.                     }) | sort -Descending | select -First 1
  102.  
  103.                     if(!$lastsync){
  104.                         write-log -logval "Repadmin Failed"
  105.                         write-error "Failed To Get Replication Date" -ErrorAction Stop
  106.                     }
  107.            
  108.                     write-log -logval "Found Last Sync Time"
  109.                 }catch{
  110.                     write-log -logval "Repadmin Failed, Cant Figure Out if Im Tombstoned, Not Running Again"
  111.                     dontrunagain
  112.                     Throw "Repadmin Failed, Cant Figure Out if Im Tombstoned, Not Running Again"
  113.                 }
  114.             }
  115.         }catch{
  116.             write-log -logval "Getting Our Last Synced Day Or Getting The Tomb Days Failed, Check Network Conectivity And Ability To Conect To AD. Powershell Error: $($error[0])"
  117.             dontrunagain
  118.             throw "Getting Our Last Synced Day Or Getting The Tomb Days Failed, Check Network Conectivity And Ability To Conect To AD"
  119.         }
  120.  
  121.         $today = Get-Date
  122.  
  123.         #subtract the days since sync
  124.         if($lastsync -eq $null -or $lastsync -eq $null){
  125.             write-log -logval "Last Sync Or Tombstone Days Returned As Null, Powershell Error: $($error[0])"
  126.             break
  127.         }else{
  128.             $dayslastsync = ($today - $lastsync).Days
  129.             #greater than the life time?
  130.             $tombstone = [bool]($dayslastsync -gt $tombdays)
  131.             if($tombstone){
  132.                 write-log "$env:computername is TombStoned"
  133.             }else{
  134.                 write-log -logval "$env:computername Is Not TombStoned"
  135.             }
  136.         }
  137.  
  138.         #if greater than 30, force a replication
  139.         if($dayslastsync -gt 30 -and $dayslastsync -lt $tombdays){
  140.             & 'C:\Windows\System32\repadmin.exe' /syncall
  141.             write-host "30 Days More Out Of Sync, Force Replicating Now"
  142.             write-log -logval "30 Days More Out Of Sync, Force Replicating Now"
  143.             start-sleep 30
  144.             break
  145.         }
  146.  
  147.         #regex our OU, DN minus CN
  148.         try{
  149.             $OU = ((get-adcomputer $env:computername -Properties distinguishedname -ErrorAction Stop).distinguishedname -replace '^.+?(?<!\\),','').split(",")
  150.         }catch{
  151.             try{
  152.                 write-log -logval "Couldnt Get The OU From AD, Trying GPresult Instead."
  153.                 $ou = (gpresult /r /scope:computer | %{if($_ -like "*CN=*"){$_ -replace '^.+?(?<!\\),',''}}).trim(' ')
  154.             }catch{
  155.                 write-log -logval "Couldnt Get $env:computername Distinguished Name, Powershell Error: $($error[0])"
  156.             }
  157.         }
  158.  
  159.         #run if we are tombstoned
  160.         if($tombstone -eq $true){
  161.             try{
  162.                 import-module addsdeployment -ErrorAction Stop -WarningAction SilentlyContinue | out-null
  163.                 write-log -logval "Imported DC Module"
  164.             }catch{
  165.                 throw "Couldnt Import The ADDSDeployment Module"
  166.                 write-log -logval "Couldnt Import The ADDSDeployment Module, Powershell Error: $($error[0])"
  167.                 break
  168.             }
  169.  
  170.             #demote
  171.             try{
  172.                 uninstall-addsdomaincontroller `
  173.                     -credential $cred `
  174.                     -demoteoperationmasterrole:$true `
  175.                     -forceremoval:$true `
  176.                     -force:$true `
  177.                     -localadministratorpassword $pass `
  178.                     -confirm:$false `
  179.                     -norebootoncompletion `
  180.                     -erroraction stop
  181.  
  182.                 write-log -logval "Demotion Successful"
  183.             }catch{
  184.                 write-log -logval "Couldnt Demote $env:computername, Powershell Error: $($error[0])"
  185.                 dontrunagain
  186.                 Throw "Couldnt Demote $env:computername"
  187.             }
  188.  
  189.             #drop the check file
  190.             try{
  191.                 $ou >> 'd:\shares\d\promo_check.txt'
  192.             }catch{
  193.                 write-log -logval "Couldnt Drop 'd:\shares\d\promo_check.txt'"
  194.                 throw "Couldnt Drop 'd:\shares\d\promo_check.txt'"
  195.             }
  196.         }
  197.         Restart-Computer -Force -Confirm:$false
  198.     }
  199.    
  200.     $true {
  201.         if(!$postrebootcheck2){
  202.             try{
  203.                 import-module addsdeployment -ErrorAction Stop -WarningAction SilentlyContinue | out-null
  204.                 write-log -logval "Imported DC Module"
  205.             }catch{
  206.                 throw "Couldnt Import The ADDSDeployment Module"
  207.                 write-log -logval "Couldnt Import The ADDSDeployment Module, Powershell Error: $($error[0])"
  208.                 break
  209.             }
  210.  
  211.             #get our check file
  212.             try{
  213.                 $ou = get-content 'd:\shares\d\promo_check.txt' -ErrorAction Stop
  214.                 write-log -logval "Promo Check Passed Going to Promote to DC"
  215.             }catch{
  216.                 write-log -logval "Couldnt Get The Check File, Trying To Use The Well Known OU Instead."
  217.             }
  218.  
  219.             #promote
  220.             try{
  221.                 install-addsdomaincontroller `
  222.                     -allowdomaincontrollerreinstall:$true `
  223.                     -noglobalcatalog:$false `
  224.                     -creatednsdelegation:$false `
  225.                     -credential $cred `
  226.                     -safemodeadministratorpassword $pass `
  227.                     -criticalreplicationonly:$false `
  228.                     -databasepath "c:\windows\ntds" `
  229.                     -domainname "mydomain" `
  230.                     -installdns:$true `
  231.                     -logpath "d:\AD_Logs" `
  232.                     -norebootoncompletion `
  233.                     -replicationsourcedc "test-dc.domain" `
  234.                     -sitename $(if($ou){$($ou[0..($ou.count -1)]  -join ",")}else{
  235.                         (get-adobject -filter 'ObjectClass -eq "domain"' -Properties wellKnownObjects).wellKnownObjects |
  236.                         %{$_ -match '^B:32:AA312825768811D1ADED00C04FD8D5CD:(.*)$' |
  237.                         out-null};$matches[0].replace("B:32:AA312825768811D1ADED00C04FD8D5CD:","")
  238.                     }) `
  239.                     -sysvolpath "c:\windows\sysvol" `
  240.                     -force:$true `
  241.                     -confirm:$false `
  242.                     -erroraction stop `
  243.                     -warningaction silentlycontinue
  244.  
  245.                 write-log -logval "Promoted $env:computername To DC"
  246.                 out-file "d:\shares\d\promo_check2.txt"
  247.             }catch{
  248.                 write-log -logval "Couldnt Promote $env:computername Powershell Error: $($error[0])"
  249.                 dontrunagain
  250.                 throw "Couldnt Promote $env:computername"
  251.             }
  252.             Restart-Computer -Force -Confirm:$false
  253.         }
  254.  
  255.         #list the member servers
  256.         $serverlist = "asd","sdf","dfg"
  257.  
  258.         $computers = foreach($s in $serverlist){
  259.             #concatenate my name trimed with the MS to make the fullname
  260.             ($env:computername).trim("qwe") + $s
  261.         }
  262.  
  263.         foreach($c in $computers){
  264.             #set credentials for the local admin using the server name
  265.             $localuser2 = "$c\localadmin"
  266.             $cred2     = $null
  267.             if($pass){
  268.                 $cred2 = new-object -typename System.Management.Automation.PSCredential($localuser2, $pass)
  269.                 write-log "Local Admin Credentials Made For $c"
  270.             }else{
  271.                 write-log -logval  "Couldnt Generate Local Admin Credentials For $c, Powershell Error: $($error[0])"
  272.                 contniue
  273.             }
  274.  
  275.             $localuser3 = "$c\administrator"
  276.             $cred3     = $null
  277.             if($pass){
  278.                 $cred3 = new-object -typename System.Management.Automation.PSCredential($localuser3, $pass)
  279.                 write-log "Local Admin Credentials Made For $c"
  280.             }else{
  281.                 write-log -logval  "Couldnt Generate Local Admin Credentials For $c, Powershell Error: $($error[0])"
  282.                 contniue
  283.             }
  284.              
  285.             $myou = $null
  286.             try{
  287.                 #should i do this before i demote myself? probably.
  288.                 $myou = ((get-adcomputer $c -Server $env:computername -Properties distinguishedname -ErrorAction stop).distinguishedname -replace '^.+?(?<!\\),','').split(",")
  289.             }catch{
  290.                 write-log "Couldnt Get The OU For $c, Powershell Error: $($error[0])"
  291.             }
  292.  
  293.             #remove MS from AD
  294.             try{
  295.                 remove-computer -ComputerName $c -LocalCredential $cred2 -UnjoinDomainCredential $cred -WorkgroupName "WorkGroup" -Restart:$false -Confirm:$false -force -ErrorAction Stop
  296.                 write-log -logval "Removed $c From AD"
  297.             }catch{
  298.                 write-log -logval "Error Removing $c From The Domain, Powershell Error: $($error[0])"
  299.             }
  300.  
  301.             #restart MS and wait for winrm to come back up
  302.             try{
  303.                 Restart-Computer -ComputerName $c -Credential $cred -Force -Wait -For WinRM -Timeout 300 -ErrorAction Stop
  304.                 write-log -logval "Restarting $c"
  305.             }catch{
  306.                 write-log -logval "Member Server $c Failed To Reboot, Powershell Error: $($error[0])"
  307.             }
  308.  
  309.             #add MS to AD
  310.             try{
  311.                 add-Computer -ComputerName $c -LocalCredential $cred2 -DomainName "mydomain" -Credential $cred -OUPath $myou -Restart:$false -confirm:$false -Force -ErrorAction Stop
  312.                 write-log -logval "Added $c To The Domain"
  313.             }catch{
  314.                 write-log -logval "Error Adding $c To The Domain, Powershell Error: $($error[0])"
  315.             }
  316.  
  317.             #restart MS and wait for winrm to come back up
  318.             try{
  319.                 Restart-Computer -ComputerName $c -Credential $cred -Force -Wait -For WinRM -Timeout 300 -ErrorAction Stop
  320.                 write-log -logval "Restarting $c"
  321.             }catch{
  322.                 write-log -logval "Member Server $c Failed To Reboot, Powershell Error: $($error[0])"
  323.             }
  324.         }
  325.  
  326.         #cleanup
  327.         if([bool](Test-Path "c:\dontrunagain.txt")){
  328.             rm "d:\shares\d\dontrunagain.txt" -force | out-null
  329.         }
  330.         if([bool](Test-Path "c:\promo_check.txt")){
  331.             rm "d:\shares\d\promo_check.txt" -force | out-null
  332.         }
  333.         if([bool](Test-Path "c:\promo_check2.txt")){
  334.             rm "d:\shares\d\promo_check2.txt" -Force | out-null
  335.         }
  336.     }
  337.  
  338.     default {exit}
  339.     $null   {exit}
  340. }