Wednesday, November 22, 2023

Script to scan IPs and return SSL certificate information

I've compiled this script from various sources and tweaked it to the current state. It has been helpful in scanning a list of IP addresses on a port you specify (443, 8443, etc.) and returning the information in a CSV file. This has been quite useful when a certificate management solution is not in place.

This script goes through the IPs pretty quickly and I scanned a list of 35k IP addresses in 6 hours.

 function testport{
  Param($IP,$port,$timeout)
  $requestCallback = $state = $null
  $client = New-Object System.Net.Sockets.TcpClient
  $beginConnect = $client.BeginConnect($IP,$port,$requestCallback,$state)
  Start-Sleep -milli $timeOut
  if ($client.Connected) { $open = $true } else { $open = $false }
  $client.Close()
  [pscustomobject]@{IP=$IP;port=$port;open=$open}
}
$Port=443
$Timeout=300
Import-csv C:\temp\ips.txt|foreach-object{
write-host $_.IP
$IP = $_.IP
$test=testport -IP $IP -port $Port -timeout $Timeout
If($test.open -eq "True"){
[Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
$url = "https://" + $IP
$req = [Net.HttpWebRequest]::Create($url)
$req.Timeout=2000
$req.GetResponse() | Out-Null
$output = [PSCustomObject]@{
   IPAddress = $IP
   'StartDate' = $req.ServicePoint.Certificate.GetEffectiveDateString()
   'EndDate' = $req.ServicePoint.Certificate.GetExpirationDateString()
   'Subject' = $req.ServicePoint.Certificate.subject
}
#write-host $output
$output|export-csv C:\temp\certresults.csv -notypeinformation -append
$output=$null
}
$output=$null
}

Friday, July 9, 2021

Script to Stop and Disable Printer Spooler Service on Servers Not Sharing a Printer

 <#
PowerShell Script to find servers in domain that are not sharing a printer, and disable the printer spooler service on them.

Wes Brown - 7/9/2021
#>

#get servers from domain and filter out some by name

get-adcomputer -filter {name -notlike "*print*" -AND operatingsystem -like "*Server*"} -Properties operatingsystem|ForEach-Object{
$srvr = $_.dnshostname

#test connection to each server to see if it is responding
$rtn = Test-Connection -cn $_.dnshostname -count 1 -BufferSize 16 -Quiet

#log servers that are not responding
IF($rtn -match "False"){
$srvr|out-file C:\temp\spoolernoconnection.csv -Append -ErrorAction SilentlyContinue
}

ELSEIF ($rtn -match "True"){

#Check servers that respond for shared printer
$prntsrvr=Get-CimInstance -ClassName CIM_printer -ComputerName $srvr -erroraction silentlycontinue|?{$_.sharename -ne $null}

#Check servers that respond for spooler service, to include status
$prntservice=get-service -computername $srvr -name "spooler" -erroraction silentlycontinue

#If server doesn't have any shared printers, and the printer spooler is running, then stop and disable the spooler service

    IF($prntsrvr -eq $null -and $prntservice.status -eq "Running"){
        Get-Service -ComputerName $srvr -name "spooler" |stop-service -PassThru -Verbose|Set-Service -StartupType disabled -Verbose
$disabledlog = $srvr
$disabledlog|out-file C:\temp\spoolerdisable.csv -Append -ErrorAction SilentlyContinue
$prntsrvr=$null
$prntservice=$null

#Check spooler service after stop and disable command
$status = Get-Service -ComputerName $srvr -name "spooler" -erroraction SilentlyContinue|select status
$spoolerstatus = "$($srvr) , $($status)"

#Write spooler status to log file
$spoolerstatus | out-file C:\temp\spoolerstatus.csv -Append -ErrorAction SilentlyContinue
}

ELSE{
$faillog = "$($srvr) , $($prntsrvr.pscomputername) , $($prntsrvr.sharename)"
$faillog|Out-File C:\temp\spoolernoaction.csv -Append -ErrorAction SilentlyContinue
$status = Get-Service -ComputerName $srvr -name "spooler" -erroraction SilentlyContinue|select status
$spoolerstatus = "$($srvr) , $($status)"

#If a server has a shared printer, if the spooler service is disabled, log spooler status
$spoolerstatus | out-file C:\temp\spoolerstatus.csv -Append -ErrorAction SilentlyContinue
}}}


Tuesday, April 28, 2020

Email users of password expiration

I've run into many situations where we've needed to email end users of their pending password expiration. Sometimes it's remote users who don't see the password change alerts, sometimes it's just a way to show that the end user was notified their password was expiring. Here's the script I've cobbled together from various sources. It emails their password once it's 7 days out. I usually schedule the script to run daily at noon.

 # Please Configure the following variables....
$smtpServer="smtp.domain.com"
$expireindays = 7
$from = "noreply@domain.com"
$logging = "Enabled" # Set to Disabled to Disable Logging
$logFile = "c:\logs\pwdemaillog.csv" # ie. c:\logs\pwdemaillog.csv
#$testing = "Enabled" # Set to Disabled to Email Users
$testRecipient = "adminuser@domain.com"
$date = Get-Date -format ddMMyyyy
#
###################################################################################################################
# Check Logging Settings
if (($logging) -eq "Enabled")
{
    # Test Log File Path
    $logfilePath = (Test-Path $logFile)
    if (($logFilePath) -ne "True")
    {
        # Create CSV File and Headers
        New-Item $logfile -ItemType File
        Add-Content $logfile "Date,Name,EmailAddress,DaystoExpire,ExpiresOn"
    }
} # End Logging Check
# Get Users From AD who are Enabled, Passwords Expire and are Not Currently Expired
Import-Module ActiveDirectory
$users = get-aduser -filter * -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |where {$_.Enabled -eq "True"} | where { $_.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false }
$DefaultmaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge
# Process Each User for Password Expiry
foreach ($user in $users)
{
    $Name = $user.Name
    $emailaddress = $user.emailaddress
    $passwordSetDate = $user.PasswordLastSet
    $PasswordPol = (Get-AduserResultantPasswordPolicy $user)
    # Check for Fine Grained Password
    if (($PasswordPol) -ne $null)
    {
        $maxPasswordAge = ($PasswordPol).MaxPasswordAge
    }
    else
    {
        # No FGP set to Domain Default
        $maxPasswordAge = $DefaultmaxPasswordAge
    }

    $expireson = $passwordsetdate + $maxPasswordAge
    $today = (get-date)
    $daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days
     
    # Set Greeting based on Number of Days to Expiry.
    # Check Number of Days to Expiry
    $messageDays = $daystoexpire
    if (($messageDays) -ge "1")
    {
        $messageDays = "in " + "$daystoexpire" + " days."
    }
    else
    {
        $messageDays = "today."
    }
    # Email Subject Set Here
    $subject="This is a friendly reminder that your network password will expire $messageDays"

    # Email Body Set Here, Note You can use HTML, including Images.
    $body ="
    Dear $name,
    <p> Your Password will expire $messageDays<br>
    To change your password, press CTRL+ALT+DEL and select change password.<br>
    <p>Thank you, <br>
    <p>Company IT Team <br>
    <p>it@domain.com<br>
    </P>"
 
    # If Testing Is Enabled - Email Administrator
    if (($testing) -eq "Enabled")
    {
        $emailaddress = $testRecipient
    } # End Testing
    # If a user has no email address listed
    if (($emailaddress) -eq $null)
    {
        $emailaddress = $testRecipient 
    }# End No Valid Email
    # Send Email Message
    if (($daystoexpire -ge "0") -and ($daystoexpire -lt $expireindays))
    {
         # If Logging is Enabled Log Details
        if (($logging) -eq "Enabled")
        {
            Add-Content $logfile "$date,$Name,$emailaddress,$daystoExpire,$expireson"
        }
        # Send Email Message
        Send-Mailmessage -smtpServer $smtpServer -from $from -to $emailaddress -bcc "adminuser@domain.com" -subject $subject -body $body -bodyasHTML -priority High
    } # End Send Message
 
} # End User Processing
# End

Thursday, April 4, 2019

Revoke expired certificates from VMware vCSA with Embedded PSC

I was receiving errors indicating I had expired certificates in my vCenter, even though I had used the certificate manager to go through a complete refresh of the certificates. All the VMware KB articles that pointed me to the vecs-cli were fruitless. The certificate would say it successfully deleted, but it wouldn't actually delete. The following are steps I followed with support to get the certificates removed. (Note...this is not an officially supported method of removal by VMware...so continue at your own risk and create a snapshot of the vCSA before you proceed).

The process is to export the certs to crt files in the /tmp directory. Next run a script that scans all crt files for expired certificates, and then revokes all certificates that are expired.

  1. Create gencerts.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import re
import os
import subprocess

class SearchFunctions( object ):
    def __init__( self, rawdatas ):
        block_expr = re.findall(b"^-+BEGIN CERTIFICATE-+.*?-+END CERTIFICATE-+\s",rawdatas,re.DOTALL|re.MULTILINE)
        self.GetData = block_expr ###### get results
        print("-- Done with data parse.")
######  Main function
class dataParse( object ):
    def __init__( self, rawdatas ):
        count = 1

        print("\n-- Running data parse...")
        sa = SearchFunctions(rawdatas)

        print("-- Begin writing certs to files...")
        for i in sa.GetData:
            i = i.decode("utf-8")
            file_name = 'cert%s.crt' % count
            with open(file_name, 'w') as f:
                print("- Writing cert to %s" % file_name)
                f.write(i)
                count = count+1

def main():
    usage="use it right"
    print("-- Enumerating certs.  Counting...")
    p = subprocess.check_output(["/usr/lib/vmware-vmca/bin/certool","--enumcert","--filter=all"])
    dataParse(p)
if __name__ == "__main__":

    main()

  1. Run ./gencerts.py
  1. Create Find-expired.sh
#!/bin/bash
CERTFILE=$1

if openssl x509 -checkend 86400 -in $CERTFILE 2> /dev/null | grep -q "Certificate will not expire"
then
        echo "$CERTFILE is still valid.  Skipping..."
elif openssl x509 -checkend 86400 -in $CERTFILE 2> /dev/null | grep -q "Certificate will expire"
then
    echo -e "\nCertificate is expired!  Adding $CERTFILE to expiredcerts.txt...\n"
    echo "$CERTFILE" >> expiredcerts.txt
else
    echo -e "\nthere was a problem checking the cert.  ignoring $CERTFILE.\n"
fi

  1. Run "for i in $(ls cert*.crt); do ./find-expired.sh $i ; done"
  1. Run "for i in $(cat expiredcerts.txt); do /usr/lib/vmware-vmca/bin/certool --revokecert --cert /tmp/$i ;done"
  2. Validate the certificates are all revoked, then delete the snapshot you created.

Thursday, September 20, 2018

PowerShell script to reset service account password and restart services on multiple servers.

Need: You need to reset the password for a service account on one or more services on multiple servers at the same time, and restart the impacted services.

Prerequisite: Create a txt file with all the servers that are using a specific service account for one or more services.  Create a column header of "servers" and just paste all the servers names below.You can compile this file from my earlier blogpost here.

Script:

$newpass = "ReallyLongPasswordYouWouldHateTyping"
Import-csv C:\data\computers.txt|foreach-object {
$server = $_.servers
$services = get-wmiobject win32_service -ComputerName $server |?{$_.Startname -like "*svcaccountname*"}
foreach($service in $services)
{$service.change($null,$null,$null,$null,$null,$null,$null,$newpass)
get-service $service.name -ComputerName $server|stop-service
start-sleep -s 30
get-service $service.name -ComputerName $server|start-service
}}

Tuesday, August 7, 2018

PowerShell script to find all services using domain credentials

Whether it's changing a service account password, or looking for admins running service accounts under their own credentials, this script will come in handy. If you put a list of computer names or IP addresses in a servers.txt file, you can grab all services that have an account configured with your domain name or upn.

Import-csv C:\temp\servers.txt|foreach-object{
get-wmiobject win32_service -ComputerName $_.Server |?{$_.Startname -like "*Domain*" -or $_.Startname -like "*UPNSuffix*"}|select PSComputerName,Name,Started,State,StartName,Description|export-csv C:\temp\services.csv -append -notypeinformation
}
Results:

Thursday, May 3, 2018

User Home Drive Report


I was tasked with creating a report on our user home drives of information on every file, such as name, size, modified date, file extension, etc. They also wanted to include information on the user, including things like their name, location, department, and title. Since the home drives are created with the username, it made it pretty easy.

Get-ChildItem "\\fileserver\users$" |Where-Object {$_.psiscontainer -eq $true}|Select-Object -First 10|ForEach-Object{
 Get-ChildItem $_.FullName -Recurse -ErrorAction SilentlyContinue|Where-Object {$_.psiscontainer -eq $false}|Foreach-Object{
  $EID = $_.FullName
  $EID = $EID.Trim("\\\\fileserver\\users$\\")
  $EID = $EID.Substring(0,6)
  $User = (get-aduser $EID -Properties GivenName,Surname,Title,StreetAddress,Department,HomeDirectory)
  $UName = $User.GivenName + " " + $User.Surname
  $Server=$_.FullName.Trim("\\\\")
  $Server=$Server.Split('\\')[0]
 
$props = @{
    EmployeeID = $EID
    UserName = $UName
    UserTitle = $User.Title
    UserLocation = ($User.StreetAddress|Select-Object -First 1)
    UserDepartment = $User.Department
    UserHomeDirectory = $User.HomeDirectory
    File = $_.FullName
    FileServer = $Server
    Extension = $_.Extension
    CreationTime = $_.CreationTime
    LastWriteTime = $_.LastWriteTime
    Name = $_.Name
    SizeInKB = [math]::Round($_.Length/1024,2)
}
  $Export = new-object psobject -Property $props 
  $Export|export-csv -append C:\temp\First10.csv -NoTypeInformation
  $User = $null
}
}

Notes: This was made with the assumption that the employeeID is a fixed length of 6 characters, so you may need to adjust for your environment. Also, if you have a large number of users or files, you will need to break the data into more manageable sizes. I did this using the Select-Object command.