Active Directory

Script to count computers in AD which have changed computer password within a certain period

This script will count the number of Windows computers (excluding servers) in Active Directory under the specified path which have changed computer password within the last 90 days.

When the script completes it will write the computer Count to the prompt and it will send an email with a csv file attached to the specified recipients.

Modify the following variables:

  • Smtpserver – Name of the smtpserver / relay
  • From – Mail address which should appear as sender (Could be the name of the server from which the mail is sent)
  • Recipient – Mail address of the recipient(s).
  • ComputerpasswordAgeDays – Number of days since the password was last changed.
  • ADSearchBase – OU to search for computers. DistinguishedName attribute from AD.
$m = Get-Module -List ActiveDirectory
if(!$m) {
    Write-Host "AD Powershell Module is not installed. Install it and run the script again."
    Exit
}

else{
    Import-Module ActiveDirectory
}


#Mail
$smtpServer = "ex01.domain.com"
$from = "MAN01@domain.com"
$recipient = "user@domain.com"

#Variables
[string]$SavePath = "$PSScriptRoot\reports"
[int]$ComputerPasswordAgeDays = 90
[string]$ADSearchBase = "DC=domain,DC=com"


#--------------------------------------
#Name: sendMail 
#Arguments: 2 Arguments:
#           1. Computer Count
#           2. File to be attached
#Return: -
#Description: Sends an E-mail to recipient defined in $recipient containing the csv file and computer count.
#--------------------------------------

function sendMail{

     $mailinfo_computer_count = $args[0]
     $file = $args[1]
  

    $body = "Computers which have changed computer password within the last $ComputerPasswordAgeDays days.</br></br>"
    $body += $mailinfo_computer_count

    $subject = "Antal computere: " + $mailinfo_computer_count
    
                 
     #Sending email 
     Send-MailMessage -SmtpServer $smtpServer -From $from -To $recipient -Subject $subject -Body $body -BodyAsHtml -Attachments $file
  
}


$Date = (Get-Date -format "MM-dd-yyyy")
IF ((test-path $SavePath) -eq $False) { md $SavePath }
$ExportFile = "$SavePath\Workstations-$Date.csv"
$ComputerStaleDate = (Get-Date).AddDays(-$ComputerPasswordAgeDays)
$Computers = Get-ADComputer -SearchBase $ADSearchBase -filter { (passwordLastSet -ge $ComputerStaleDate) -and (OperatingSystem -notlike "*Server*") -and (OperatingSystem -like "*Windows*") } -properties Name, DistinguishedName, OperatingSystem,OperatingSystemServicePack, passwordLastSet,LastLogonDate,Description
$ComputerTrimmed = $Computers.Count
write-output "Number of computers: " ($ComputerTrimmed) 

$Computers | export-csv $ExportFile -NoTypeInformation
sendMail $ComputerTrimmed $ExportFile

Script to extract all GPOs that a specific User, Group or Computer either have or doesnt have rights to

If you ever need to provide information about which GPO’s a specific User, Group or Computer have or doesnt have access to you can use this script.

The script will run through all GPO’s in the domain and check if a given User, Group or Computer either have or havent been delegated permissons. The script will produce a text file listing all GPO’s including detailed information about linkpaths, WMI Filters, Modify Dates, if its link or not and much more.

All you have to do is supply 3 parameters

  • TargetName – Name of the target (ie. Authenticated Users)
  • TargetType – Type of the target (Group, User or Computer)
  • hasPermissions – Boolean to specify if you want to find all the GPO’s that the target has permissions to (True) or does not have permissons to (False)

Example:

This will list all the GPO’s which the Group “Authenticated Users” doesnt have access to.

Get-GPOPermissionReport -TargetName “Authenticated Users” -TargetType Group -hasPermission -$False

<#
 
.SYNOPSIS
    Runs through all GPOs and checks if a given target has permissions and adds result to a text file. 
 
.DESCRIPTION
    This script will produce a text file containing all GPO details of the GPOs where the target either have or doesnt have permissions to. 
 
.PARAMETER TargetName
    Name of the target 
 
.PARAMETER TargetType
    Type of target (Group, User or Computer)

.PARAMETER hasPermissions
    Boolean to specify if we want to find all the GPO's that the target has permission to (True) or does not have permission to (False)
   
.EXAMPLE
    Get-GPOPermissionReport -TargetName "Authenticated Users" -TargetType Group -hasPermission $False
    Lists all the GPO's where Authenticated Users doesnt have access

.EXAMPLE
    Get-GPOPermissionReport -TargetName "Authenticated Users" -TargetType Group -hasPermission $True
    Lists all the GPO's where Authenticated Users have access
  
.NOTES
    Cmdlet name:      Get-GPOPermissionReport
    Author:           Mikael Blomqvist
    DateCreated:      2017-07-06
 
#>


[CmdletBinding(DefaultParameterSetName="String")] 
Param(
 [Parameter(Mandatory=$True, Position=0, HelpMessage="TargetName")] 
            [string]$TargetName,
 [Parameter(Mandatory=$True, Position=1, HelpMessage="TargetType(User/Computer/Group)")] 
            [string]$TargetType,
 [Parameter(Mandatory=$True, Position=2, HelpMessage="Find all GPO's where target has permission(True/False)")] 
            [boolean]$hasPermission
)


#Load GPO module
 Import-Module GroupPolicy
 
 $date = Get-Date -Format yyyyMMddhhmmss

 $file = "$PSScriptRoot\GPOPermissions_$date.csv"

 #Prepare the text file with the correct headings
 Add-Content $file "Name,LinksPath,WMI Filter,CreatedTime,ModifiedTime,CompVerDir,CompVerSys,UserVerDir,UserVerSys,CompEnabled,UserEnabled,SecurityFilter,GPO Enabled,Enforced"

#Get all GPOs in current domain
 $GPOs = Get-GPO -All

#Check we have GPOs
 if ($GPOs) 
 {
    foreach ($GPO in $GPOs) 
    {
        $GPOName = $GPO.DisplayName
        $GPOGuid = $GPO.id
        
        #Retrieve the permission for the specified target
        $GPPermissions = Get-GPPermissions -Guid $GPOGuid -TargetName $TargetName -TargetType $TargetType -ErrorAction SilentlyContinue

        #Check if target have permissions or not and set permission to either True(has permission) or False(no permission)
        If($GPPermissions -eq $null)
        { 
            $permission = $False
        }
        Else
        {
            $permission = $True
        }

        # if permissions matches what we look for either true or false
        if ($permission -eq $hasPermission) 
        { 
            [xml]$gpocontent =  Get-GPOReport -Guid $GPOGuid -ReportType xml
            $LinksPaths = $gpocontent.GPO.LinksTo
            $Wmi = Get-GPO -Guid $GPOGuid | Select-Object WmiFilter
 
            $CreatedTime = $gpocontent.GPO.CreatedTime
            $ModifiedTime = $gpocontent.GPO.ModifiedTime
            $CompVerDir = $gpocontent.GPO.Computer.VersionDirectory
            $CompVerSys = $gpocontent.GPO.Computer.VersionSysvol
            $CompEnabled = $gpocontent.GPO.Computer.Enabled
            $UserVerDir = $gpocontent.GPO.User.VersionDirectory
            $UserVerSys = $gpocontent.GPO.User.VersionSysvol
            $UserEnabled = $gpocontent.GPO.User.Enabled
            $SecurityFilter = ((Get-GPPermissions -Guid $GPOGuid -All | ?{$_.Permission -eq "GpoApply"}).Trustee | ?{$_.SidType -ne "Unknown"}).name -Join ','
        
            if($LinksPaths -ne $null)
            {
                foreach ($LinksPath in $LinksPaths)
                {
                    Add-Content $file "$GPOName,$($LinksPath.SOMPath),$(($wmi.WmiFilter).Name),$CreatedTime,$ModifiedTime,$CompVerDir,$CompVerSys,$UserVerDir,$UserVerSys,$CompEnabled,$UserEnabled,""$($SecurityFilter)"",$($LinksPath.Enabled),$($LinksPath.NoOverride)"
                }   
            }
            else
            {
                Add-Content $file "$GPOName,$($LinksPath.SOMPath),$(($wmi.WmiFilter).Name),$CreatedTime,$ModifiedTime,$CompVerDir,$CompVerSys,$UserVerDir,$UserVerSys,$CompEnabled,$UserEnabled,""$($SecurityFilter)"",$($LinksPath.Enabled),$($LinksPath.NoOverride)"
            } 
        }
    }
}

When was the Last Password Change

 

It can be handy to be able to look up when a User / System Account last changed password – this can be done using DSQuery

dsquery * “CN=<User name>,OU=<name of OU>,DC=<domain>,DC=<com> -Attr PwdLastSet

this will generate a long number which with the help of w32tm.exe can be converted to a date:

w32tm.exe /ntte <number generated above>

2015-06-11_09-41-51