Tag Archives: AD

Find where a certificate is installed

Some organizations use wildcard certificates. The problem with these certificates is that they start to lead a life on it’s own. So when the time comes that such a certificate is about to expire one can wonder where is this certificate installed? Luckily we have Powershell to save us from having to open all certificate stores on all servers in the domain. At first I was  thinking maybe the easiest way could be to have a Powershell remoting session. But that would require all servers to have Powershell remoting enabled. Unfortunately not all servers have it enabled or have a reasonable Powershell version to start with. So just for documenting purpose I’ll write down the command to find a certificate.

A certificate has a thumbprint. This thumbprint is equal on all servers as it part of the certificate, much like the serial number.  So you can easily find the thumbprint where your looking for running the command on a server where the certificate is present.

Just copy the thumbprint and enter it into the command to find the certificate like the on below

Invoke-Command {gci cert:\Localmachine\My | ? {$_.Thumbprint -eq "FF9C130AE6C1D18FAC43AF0416E44B7011307545"}} -ComputerName #COMPUTERNAME#

Replace #COMPUTERNAME#  for the computername you would want to question. Now this is all good but like I mentioned before I would want to find certificate regardless of Operation system contstrains or whether Powershell Remoting is enabled or not. So this script would process that accordingly. Change the thumbprint to the thumbprint of your certificate. The script export all servers where the certificate with the given thumbprint is present. Please feel free to modify this to your needs.

Function Get-Cert( $computer=$env:computername ){
    #Sets ReadOnly flag upon external Certificate store.
	$ro=[System.Security.Cryptography.X509Certificates.OpenFlags]"ReadOnly"
	#Opens LocalMachine store. You could potentially enter a different Cert store. 
	$lm=[System.Security.Cryptography.X509Certificates.StoreLocation]"LocalMachine"
	#Opens personal certificate store from local machine. 
	$store=new-object System.Security.Cryptography.X509Certificates.X509Store("\\$computer\My",$lm)
	#Establish connection with remote PC
    $store.Open($ro)

	#Display certificates in console or variable
	$store.Certificates

}

#Opens list
$Thumbprint = "FF9C130AE6C1D18FAC43AF0416E44B7011307545" 
$List = @()

#Servers reset their machine password within a specific timeframe
$Servers = Get-ADComputer -Filter * -Properties OperatingSystem,PasswordLastSet | ?{$_.OperatingSystem -match "Server" -and $_.PasswordLastSet -gt (Get-Date).AddDays(-60)}

Foreach ($Server in $Servers)
	{
	$Server.DNSHostName 
	If ((Get-Cert $Server.DNSHostname | ? {$_.Thumbprint -eq $Thumbprint}).Count -ne 0)
		{
		$List += $Server.DNSHostName
		}
	}

$List | % {AC -Value $_ -Path ".\ComputersWithCertificate.txt"}

Correct data in mobile field in AD

A script changed the format of values in the Mobile field in AD. This however caused errors in the operation of soft tokens. I made an export of all mobile phone numbers and noticed that there were more errors. As so I’ve made a script that uses the substring method to correct the values. Please feel free to change it as desired.

$List2 = @()
$List = Get-ADUser -Filter * -Properties Mobile | ?{$_.Mobile -ne $Null}
Foreach ($Item in $List)
	{
	If ($Item.Mobile.Substring(0,2) -notmatch "06" -or $Item.Mobile.Length -ne "10")
		{
		$List2 += $Item
		}
	}

Foreach ($Item in $List2)
	{
	If ($Item.Mobile.Substring(0,3) -match "316"){Set-ADUser -Identity $Item.sAMAccountName -MobilePhone ($item.mobile.Substring(0,3).Replace("316","06") + $Item.Mobile.Substring(3))}
	If ($Item.Mobile.Substring(0,1) -match "6"){Set-ADUser -Identity $Item.sAMAccountName -MobilePhone ($item.mobile.Substring(0,1).Replace("6","06") + $Item.Mobile.Substring(1))}
	If ($Item.Mobile.Substring(0,4) -match "\+316"){Set-ADUser -Identity $Item.sAMAccountName -MobilePhone ($item.mobile.Substring(0,4).Replace('+316',"06") + $Item.Mobile.Substring(4))}
	If ($Item.Mobile.Substring(0,5) -match "00316"){Set-ADUser -Identity $Item.sAMAccountName -MobilePhone ($item.mobile.Substring(0,5).Replace("00316","06") + $Item.Mobile.Substring(5))}	
	If ($Item.Mobile.Substring(0,3) -match "013"){Set-ADUser -Identity $Item.sAMAccountName -MobilePhone $Null}	
	If ($Item.Mobile -match " "){Set-ADUser -Identity $Item.sAMAccountName -MobilePhone ($Item.Mobile.Replace(" ",""))}
	If ($Item.Mobile -match "-"){Set-ADUser -Identity $Item.sAMAccountName -MobilePhone ($Item.Mobile.Replace("-",""))}
	If ($Item.Mobile -match "Geen"){Set-ADUser -Identity $Item.sAMAccountName -MobilePhone $Null}
	}

Compare AD User Properties

An administrator had to resolve an issue with a user account that could not sync with Share file. He thought that he had tried everything and so wanted to compare an Active Directory user that he copied from the trouble account with the actual user. The copied user did not have any trouble. After comparing he found that the user was member of an Active Directory Protected Group (aka Admincount=1). I made a Powershell script for him so he could compare the two.

Write-Host "Dit script vergelijkt twee Active Directory Users met elkaar."
$Outputdir = ".\exports\"
$Continue = "Y"
While ($Continue -eq "Y"){

While ($User1 -eq $Null){
$User1Value = Read-Host "Geef eerste user op"
$User1 = Get-ADUser $User1Value -Properties *}

While ($User2 -eq $Null){
$User2Value = Read-Host "Geef tweede user op"
$User2 = Get-ADUser $User2Value -Properties *
}

	$Usercomparison = @()
	$Usercomparison2 = @()

	$User1.GetEnumerator() | % {
		If ($User2.($_.Key) -eq $_.Value.value)
		{
			$Comparison = 'Gelijk'
		}
		else
		{
			$Comparison = 'Verschilt'
		}

		$UserObject = New-Object PSObject -Property ([ordered]@{
			Property = $_.Key
			$User1Value = $_.Value
			$User2Value = $User2.($_.Key)
			Overeenkomst = $Comparison
		})
		$UserObject2 = New-Object PSObject -Property ([ordered]@{
			Property = $_.Key
			$User1Value = $_.Value.Value
			$User2Value = $User2.($_.Key)
			Overeenkomst = $Comparison
		})
		$UserComparison += $UserObject
		$UserComparison2 += $UserObject2
	}

$UserComparison


while ($Difference -notmatch "[y|n]"){$Difference = read-host "Wil je filteren op gegevens die verschillen?(Y/N)"}

If ($Difference -eq "Y"){$UserComparison | ? {$_.Overeenkomst -match "Verschilt"} | FT}

while ($Choice -notmatch "[y|n]"){$choice = read-host "Wil je een export maken van de ongefilterde gegevens? (Y/N)"}
If ($Choice -eq "Y"){
Write-Host "Er wordt een export gemaakt van de bovenstaande gegevens op de locatie:"
If ((Test-Path ("$OutputDir"+"UserComparison-"+"$User1Value"+"$User2Value"+".csv")) -eq $True){
$List = GCI "$OutputDir" | ? {$_.FullName -match ("UserComparison-"+"$User1Value"+"$User2Value")}
[int]$Count = $list.count
$Count++}
If ($Count -ne $null){[string]$Count = ("-"+"$Count")}
$UserComparison2 | Export-csv -Path ("$OutputDir"+"UserComparison-"+"$User1Value"+"$User2Value"+"$Count"+".csv") -NoTypeInformation -Delimiter ";"
$Item = GI ("$OutputDir"+"UserComparison-"+"$User1Value"+"$User2Value"+"$Count"+".csv")
$Item.FullName
}
Remove-Variable User1,User1value,User2,User2value,Choice,Continue,Difference
While ($Continue -notmatch "[y|n]"){$Continue = Read-Host "Wil je nog een vergelijking uitvoeren? (Y/N)"}
}

Export PasswordNeverExpires for all accounts in the domain

A simple script to export all accounts in the domain that have the PasswordNeverExpires property set on True

ipmo ActiveDirectory 
$list = Get-ADUser -Filter 'PasswordNeverExpires -eq $True' -Properties PasswordNeverExpires | Select Name,SamAccountName,PasswordNeverExpires
$List | Export-CSV ".\PasswordNeverExpires.csv" -Delimiter ";" -Append -NoTypeInformation

You can make it more complex by adding filters based on the OU.If Users that you want to monitor are in the OU’s Accounts,Employees and Admins you can enter the code below. Adjust it to your needs.

ipmo ActiveDirectory 
$list = Get-ADUser -Filter 'PasswordNeverExpires -eq $True' -Properties PasswordNeverExpires | ? {$_.DistinguishedName -match ",OU=Accounts|,OU=Employees|,OU=Admins" | Select Name,SamAccountName,PasswordNeverExpires
$List | Export-CSV ".\PasswordNeverExpires.csv" -Delimiter ";" -Append -NoTypeInformation

Find members of a local group

We needed a list of all local admins in the domain. I found some code somewhere and adjusted it to my personal needs.

Import-Module ActiveDirectory

$date = (get-date).AddDays(-35)
$list = (Get-ADComputer -Filter {(OperatingSystem -like "*Server*") -and (PasswordLastSet -ge $Date)} ).Name

$Result = @()

foreach($server in $list){

$computer = [ADSI](”WinNT://” + $server + “,computer”)
$Group = $computer.psbase.children.find(”Administrators”)

function getAdmins

{$members = $Group.psbase.invoke(”Members”) | %{$_.GetType().InvokeMember(”Adspath”, ‘GetProperty’, $null, $_, $null)}
$members}

$Result += $server
$Result += ( getAdmins )
$Result += " "
}
$Result | ac c:\LocalAdmins.csv

Export all TNSNames files from all servers in the domain.

A colleague asked me if it was possible to export all servers that have an Oracle directory. I made a script that collects all server from Active Directory. Next I test if the C:\Oracle Directory Exists. That is arrayed. Next I search the directories of tnsnames. Excluding the .sample files of course.

Import-Module ActiveDirectory
$ADComputers = Get-ADComputer -Filter * -Properties * | Where {$_.OperatingSystem -match "Server"}
$Computers =@()
ForEach ($ADComputer in $ADComputers){$ADComputer = $ADComputer.DNSHostName
If((Test-Path "\\$ADComputer\C$\Oracle") -eq $True){$Computers += $ADComputer}}

ForEach ($Computer in $Computers){$Folders =@( gci "\\$Computer\c$\Oracle\" -recurse)
ForEach ($Item in $Folders){if ($item -match "TNSNames.ora" -and $item.fullname -notmatch "sample"){Add-content -Value $item.fullname -Path ".\Export.csv"}}}

Users being disconnected randomly

Some users reported that their sessions where being disconnected. The warning that was stated was that the peer disconnected. On the The XenApp servers reported error 4105. The Terminal Server License server was member of the group Terminal Server License Server. There’s a KB article for this problem.

If you want to export the users that could expierence this problem you can run the script below. In order to export the right group you need to have the default SID for this built in group. This SID is: “S-1-5-32-561″. The right value that the user must have is:”5805bc62-bdc9-4428-a5e2-856a0f4c185e”.

 

Import-module ActiveDirectory
$List2 =@()
$File = ".\Export.csv"
$Header = "DN;ActiveDirectoryRights;InheritanceType;ObjectType;InheritedObjectType;ObjectFlags;AccessControlType;IdentityReference;IsInherited;InheritanceFlags;PropagationFlags"
Add-Content -Value $Header -path $file
$list = get-aduser -Filter * | select DistinguishedName
foreach ($item in $list){$list2 +=$item.DistinguishedName}
foreach ($item in $list2){
$ACLs =@((get-Acl "AD:\$item")| ForEach-Object {$_.Access} | Where {$_.Identityreference -eq "S-1-5-32-561"})
IF ($ACLs.count -gt "0"){
[int]$Count = 0
Foreach ($ACL in $ACLS){IF ($ACL.Objecttype -match "5805bc62-bdc9-4428-a5e2-856a0f4c185e"){$count++}}
IF ($Count -eq "0"){
Foreach ($ACL in $ACLs){
$OutInfo = $item  + ";" + $ACL.ActiveDirectoryRights  + ";" + $ACL.InheritanceType + ";" + $ACL.ObjectType + ";" + $ACL.InheritedObjectType + ";" + $ACL.ObjectFlags + ";" + $ACL.AccessControlType  + ";" + $ACL.IdentityReference   + ";" + $ACL.IsInherited   + ";" + $ACL.InheritanceFlags   + ";" + $ACL.PropagationFlags
Add-content -Value $outinfo -path $File}}}}

Setting User logon hours

To set the user logon hours to 24×7 run the following script:

PS1:

Import-Module ActiveDirectory
$gebruikerslijst = Get-aduser -Filter * -Properties DistinguishedName

Foreach ($gebruiker in $gebruikerslijst){
$user = [ADSI]"LDAP://$gebruiker"
[byte[]]$hours = @(255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255)
$user.logonhours.value = $hours
$user.setinfo() 
}

Each byte represents 8 hours. The first byte start at 1 am at sunday untill 9 am at sunday. This next is byte is from 9 am untill 17 pm at sunday and so forth. Each byte represents of course 8 bit. Each bit is an hour. So to deny access on the first hour one should use 254.

ZIP:

Logonhours

Volgnummer bijhouden in een CSV file

Import-module 'ActiveDirectory'
 $getadusers = @()
 $filter = @()
 $samaccountnamelijst = @()
 $Header = 'Samaccountname'
 $CSV = '.\Gemeentenet.csv'
 $Extension = $null
 $import = @()
 Add-Content -Value $Header -Path $CSV
 $getadusers = Get-aduser -filter *
 foreach ($entry in $getadusers){if ($entry -ne $null){$samaccountnamelijst += $entry.samaccountname}}
 foreach ($sam in $samaccountnamelijst){Add-Content -Value $sam -Path $CSV}
 $Deelnemerlijst = @()
 $allusers = import-csv $csv
 foreach ($Deelnemeruser in $allusers){if ($Deelnemeruser -match $deelnemer){$Deelnemerlijst += $Deelnemeruser}}
 $Deelnemerlijst | export-csv .\$Deelnemer.csv

$entry = $null
$username = 'othext'
 $CSV = '.\Gemeentenet.csv'
 $import = @()
 $filter = @()
 $import = import-csv $csv
 foreach ($entry in $import){if ($entry -match $username){$filter += $entry.samaccountname}}
 $filter = $filter -split "@{samaccountname=" |sort
 $filter = $filter -split "$username" | sort
 $filter = $filter -split "}" | Sort -Descending
 $nummer = [int]$filter[0]
 $nummer++

Add-content -Value $volledigesamaccountname -path $csv

Query Inheritance op User Object in AD

De Get-ADuser heeft niet de mogelijkheid om op inheritance een query te doen. Laat staan het vinkje Include inheritable permissions from this object’s parent in het security tabblad.

Quest heeft CMDlet’s gemaakt die gratis zijn en die hier prima gebruikt kunnen worden. Het commando dat uitgevoerd moet worden is het volgende:

 
Get-QADUser -SizeLimit 0 | Where-Object {$_.DirectoryEntry.psbase.ObjectSecurity.AreAccessRulesProtected }

 

Om eventueel naar een ander domein te verbinden kan het volgende commando gebruikt worden:

Connect-QADService -service ''

Om de gevonden accounts ook daadwerkelijk aan te passen kan bovenstaande code ook uitgebreid worden:

Get-QADUser -SizeLimit 0 | Where-Object {$_.DirectoryEntry.psbase.ObjectSecurity.AreAccessRulesProtected } | Set-QADObjectSecurity -UnlockInheritance