Jun 082016
 

If you’re using Azure as an Active Directory lab and need to make sure your NTP is set properly with an external source, this is a good set of commands to run on your VM’s. I know Azure’s own built-in NTP synchronization system via HyperV is probably bar-none, but I’m trying to experiment with NTP settings on my PDC emulator and it just gets in the way.

I found this extremely useful tidbit of information here: https://blogs.technet.microsoft.com/keithmayer/2012/10/10/deploying-windows-server-2012-essentials-rtm-now-available/

Of course I lay no claim to this knowledge, it was pre-existing. I just added the little strike through below. 🙂

NOTE: Replace TIME_SERVER_x with time servers of your choice, hopefully Stratum 1.

If you run these commands, you will partially disable HyperV time integration.
Partially Disable Hyper-V Host Time Synchronization.

reg add HKLM\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\VMICTimeProvider /v Enabled /t reg_dword /d 0

Configure Windows Server Essentials to synchronize time with an external authoritative time server.

w32tm /config /manualpeerlist:TIME_SERVER_1, TIME_SERVER_2 /syncfromflags:MANUAL

Restart the Windows Time Service and force a time synchronization to occur.

net stop w32time && net start w32time
w32tm /resync /force

 

 

 

Jun 032016
 

This little bit of code is a work in progress but it is functional. Run it against your windows certificate authorities (make sure wsman/winrm is enabled on them), and you will get a report of failed requests in the $failedrequests string before it cleans out all failed requests older than 7 days (the success of which is reported in $result string). Uses certutil.

This can go a long way in preventing a bloated cert db on your ca’s, but it’s always a good idea to track down the reason why you’re getting failed requests in the first place. Nefarious reasons? Misconfiguration?


$certservers = @('enter','ca servers','here')

$DateFrom = "$((get-date).AddDays(-7).Month)/$((get-date).AddDays(-7).Day)/$((get-date).AddDays(-7).Year)"

$Scriptblock = {
Param($Date)
certutil -deleterow $date Request
}

[system.string]$failedrequests = $null
[system.string]$result = $null

foreach ($server in $certservers) {

  $failedrequests = $failedrequests + "=== Failed Requests for $server :"
  $failedrequests = $failedrequests + $(invoke-command -ComputerName $server -ScriptBlock {certutil -view logfail} | out-string)
  $result = $result + "=== Clearing failed requests older than $datefrom on $server :"
  $result = $result + $(invoke-command -ComputerName $server -ScriptBlock $scriptblock -ArgumentList $datefrom | out-string)

}
 Posted by at 4:26 pm
Jun 022016
 

So I have not posted anything to my blog for quite some time. I’ve decided to fix that, and I’m also changing the focus of my blog slightly from a broad catch-all for my technology interests to a more focused blog on what I’m learning with PowerShell, operating systems, and hardware.

First up is a new script I created to generate a server uptime report. Is also uses Microsoft SCCM WMI classes to determine if a reboot is pending (useful if updates delivered via SCCM didn’t trigger a reboot).

I also decided that I didn’t want to maintain a list of servers to query, so I have my script querying Active Directory OUs to compile the server list.

There are some things that you need to set in order to get this operational. The first is the list of OUs you wish to search. The other is information for the email report. The email stuff can be skipped if you wish, but I’ve found it quite useful, as long as you have an open SMTP relay.

Some things I need to do:

  • Allow toggle of CCM query. Not everyone has SCCM running.
  • Add optional authentication to email for relays that are not unauthenticated.
  • Additional error handling.

So here you go, and as always, let me know if you see something I can improve upon. I am learning this stuff after all.

#requires -Version 2 -Modules ActiveDirectory

# Author: Robert Hollingshead 
# Version: 1 
# Version History: First version. 
# Purpose: Get a list of servers based on arbitrary OU's, and then check each server for uptime. 
# Also grab pending reboot flag from CCM. Send as a report to an email address. 
# To-Do List: Allow toggle of CCM reboot-pending. Add optional authentication to mail. Additional error handling.

# Uncomment this to disable progress bar.
# $ProgressPreference = 'SilentlyContinue'

# Enter OUs to search here. One per line, follow the format below, omit comma on last line.
# You definately want to edit this stuff.
$OUsToSearch = @(
  'OU=OU=Servers,DC=Contoso,DC=net', 
  'OU=Domain Controllers,DC=Contoso,DC=net'
)

# Enter your mail information here. 
$MailSender = '{sender email address here}'
$MailRecipients = '{recipient list here}'
$MailSubject = "Server UpTime Report for $(Get-Date -Format d)"
$MailBody = $MailSubject + ' is attached'
$MailServer = '{smtp server here}'

# Change nothing below this line. 
# ===============================

# Grab the class so that we can use convert to date fu nction. 
$WMI = [wmiclass]'\\.\root\cimv2:win32_operatingsystem'

# Set up some arrays. 
[system.array]$UpTimeReport = $null
[system.array]$Servers = $null

# Query Active Directory
ForEach ($OU in $OUsToSearch) 
{ 
  $OUResult = $null
  Try 
  { 
    $OUResult = Get-ADComputer -SearchBase $OU -Filter * -ErrorAction Stop
    $Servers = $Servers + $OUResult
  }
  catch 
  {
    Write-Warning -Message "Failed to get servers in $OU"
  }
}

# Set up for progress bar.
[long]$totalitems = $Servers.count
[long]$progress = 1
[long]$percentage = 0

# Query each server for uptime. 
foreach ($Server in $Servers) 
{
  # Calculate percent complete and write-progress (if enabled)
  $percentage = ($progress * 100) / $totalitems
  Write-Progress -Activity 'Querying servers.' -PercentComplete $percentage `
  -Status "$percentage% complete..." -CurrentOperation "Checking $($Server.name)."

  # Attempt to get last bootup time and local date/time, then calculate. If fails, handle error. 
  try 
  { 
    $Stopwatch = Measure-Command -Expression {
      $OSProps = Get-WmiObject -ComputerName $Server.name -Class win32_operatingsystem -Property LocalDateTime, LastBootupTime
      $UpTime = $WMI.ConvertToDateTime($OSProps.LocalDateTime) - $WMI.ConvertToDateTime($OSProps.LastBootUpTime)
      $LastBootTime = $WMI.ConvertToDateTime($OSProps.LastBootUpTime)

      # Use CCM to determine if a reboot is pending.
      $CCMWmi = [wmiclass]"\\$($Server.name)\ROOT\ccm\ClientSDK:CCM_ClientUtilities"
      $Reboot = ($CCMWmi.DetermineIfRebootPending()).RebootPending
    }
    $ServerUptime = "$($UpTime.days)+$($UpTime.Hours):$($UpTime.Minutes):$($UpTime.Seconds).$($UpTime.Milliseconds)"
    $TimeToRetrieve = "$($Stopwatch.Minutes):$($Stopwatch.Seconds).$($Stopwatch.Milliseconds)"
  }
  catch 
  {
    $ServerUptime = 'Not Available'
    $LastBootTime = 'Not Available'
    $TimeToRetrieve = 'Failed To Retrieve'
    $Reboot = $false
  }

  # Create object to be added to report. 
  $CurrentServer = New-Object -TypeName PSObject
  $CurrentServer | Add-Member -MemberType NoteProperty -Name 'ServerName' -Value $($Server.name) 
  $CurrentServer | Add-Member -MemberType NoteProperty -Name 'UpTime' -Value $($ServerUptime)
  $CurrentServer | Add-Member -MemberType NoteProperty -Name 'LastBootTime' -Value $($LastBootTime)
  $CurrentServer | Add-Member -MemberType NoteProperty -Name 'TimeToRetrieve' -Value $($TimeToRetrieve)
  $CurrentServer | Add-Member -MemberType NoteProperty -Name 'TimeRetrieveFinished' -Value $(Get-Date -Format T)
  $CurrentServer | Add-Member -MemberType NoteProperty -Name 'RebootPending' -Value $($Reboot)
  
  # Add to report object.
  $UpTimeReport = $UpTimeReport + $CurrentServer
  
  # Increment progress counter for progress bar. 
  $progress++
}

$ReportPath = $env:Temp + '\ServerUpTime.csv'
$UpTimeReport | Export-Csv $ReportPath
Send-MailMessage -From $MailSender -To $MailRecipients -Subject $MailSubject -Body $MailBody -Attachments $ReportPath -SmtpServer $MailServer