Powershell script to audit new AD accounts & groups - powershell

I am trying to create a powershell to audit new created accounts & groups and who created them. The objects are created by account operators, but they are not domain admins.
I think something like this:
$Last = (Get-Date).AddDays(-1);
Get-Acl | Get-ADUser -Filter {WhenCreated -ge $Last} | FL DistinguishedName, Path,owner
But this doesn't work yet.

This one liner will let you know about the changes after a certain date. There is a whenchanged property with which you can filter down the objects.
Get-ADObject -Filter 'whenchanged -gt $dte' | Group-Object objectclass
then you can use :
get-adgroup -filter * | sort name | select Name
Get-adgroupmember "Name"
or
Get-ADGroup -filter "GroupCategory -eq 'Security'" –properties Member |
Select Name,#{Name="Members";
Expression={($_.member | Measure-Object).count}},
GroupCategory,GroupScope,Distinguishedname |
Out-GridView -Title "Select one or more groups to export" -OutputMode Multiple |
foreach {
Write-Host "Exporting $($_.name)" -ForegroundColor cyan
#replace spaces in name with a dash
$name = $_.name -replace " ","-"
$file = Join-Path -path "C:\work" -ChildPath "$name.csv"
Get-ADGroupMember -identity $_.distinguishedname -Recursive |
Get-ADUser -Properties Title,Department |
Select Name,Title,Department,SamAccountName,DistinguishedName |
Export-CSV -Path $file -NoTypeInformation
Get-Item -Path $file
}

Related

Powershell Script to get details of user along with group they are member of

I'm trying to export AD user list along with the group they are member of, exported csv format should be like
Group A User1_name
Group A User2_name
Group B User3_name
Group C User4_name
Group C User5_name
I have tried
$ErrorActionPreference = "SilentlyContinue"
Get-Content R:\PHRBI-R\ADGroup_list.csv | Where{$_ -ne $null -and $_.trim() -ne ""} |
foreach{
$Group = $_
Write-Host "$Group"
Get-ADGroup -Identity $Group -Properties members |
Select-Object -ExpandProperty members |
Get-ADUser -Properties samaccountname, enabled |
Select samaccountname, name, Enabled
}
But it doesn't gave the template I'm looking for and also new group keep adding so can't list groups manually in any file and export the required details.
The below should get you going, I tried to make it logical to follow. This can, of course, be cleaned up and optimized.
# Create csv
New-Item "Some\Path\To\CSV" -ItemType File -force
# Add header row
Add-Content -Path "Some\Path\To\CSV" -Value 'Group Name, NUID, Name, Enabled'
# Loop through each AD group
Get-ADGroup -Filter {Name -like 'ABC*'} | Foreach-Object {
# Keep the group object so we can use it later
$Group = $_
# loop through each group member
$Group.members | Foreach-Object {
$User = Get-ADUser -identity $_ -Properties samaccountname, name, enabled
Add-Content -Path "Some\Path\To\CSV" -Value "$($Group.Name),$($User.samaccountname),$($User.name),$($User.Enabled)"
}
}
Note that If there are nested groups (i.e. groups within groups) then the Get-AdUser cmdlet will error.
Import-Module ActiveDirectory
New-Item R:\PHRBI-R\Nishant\AD_List\user_list.csv -ItemType File -force
Add-Content -Path R:\PHRBI-R\Nishant\AD_List\user_list.csv -Value 'Group Name, NUID, Name,Enabled'
$Groups=Get-ADGroup -Filter {Name -like 'ABC*'}
foreach($Group in $Groups)
{
$Details=Get-ADGroup -Identity $Group.Name -Properties members |
Select-Object -ExpandProperty members |
Get-ADUser -Properties samaccountname, enabled, name | Select samaccountname, name, Enabled
foreach($Detail in $Details)
{
Add-Content -Path R:\PHRBI-R\Nishant\AD_List\user_list.csv -Value "$($Group.Name),$($Detail.samaccountname),$($Detail.name),$($Detail.Enabled)"
}}

Powershell: List with ADusers - need groups the users are memberof

I have a list of users (their CN), and I want a list of the groups they are member of.
I already have a code which almost does the trick, but it shows as follows:
User1 - group1;group2
User2 - group1;group2;group3 etc...
Also, groups are shown as distinguished name (with container etc), so very long. I only want the name.
I want to show it as follows:
User1 - group1
User1 - group2
User2 - group1, etc
The code that shows the groups the users are member of, but not in the visual way i like is below:
Import-Csv -Path .\Input_CN.csv |
ForEach-Object {
$User = Get-ADUser -filter "CN -eq '$($_.CN)'" -properties memberof
[PSCustomObject]#{
SourceCN = $_.CN
MemberOf = $User.MemberOf -join ";"
}
} | Export-Csv -Path .\Output.csv -Delimiter ";" -NoTypeInformation
.\Output.csv
I have some other code that list the groups how I want, but I am unable to list it per user. And unable to combine it with the above code.
get-aduser -filter {cn -eq "Testuser"} -properties memberof |
Select -ExpandProperty memberof |
ForEach-Object{Get-ADGroup $_} |
Select -ExpandProperty Name
Thanks in advance :)
You could combine both code pieces like this:
Import-Csv -Path .\Input_CN.csv |
ForEach-Object {
$user = Get-ADUser -Filter "CN -eq '$($_.CN)'" -Properties MemberOf, CN -ErrorAction SilentlyContinue
foreach($group in $user.MemberOf) {
[PSCustomObject]#{
SourceCN = $user.CN
MemberOf = (Get-ADGroup -Identity $group).Name
}
}
} | Export-Csv -Path .\Output.csv -Delimiter ";" -NoTypeInformation
Edit
Although I have never seen an AD user to have no group membership at all (should have at least the default Domain Users in the MemberOf property), You commented that you would like to have a test for that aswell.
Import-Csv -Path .\Input_CN.csv |
ForEach-Object {
$user = Get-ADUser -Filter "CN -eq '$($_.CN)'" -Properties MemberOf, CN -ErrorAction SilentlyContinue
if (!$user) {
Write-Warning "No user found with CN '$($_.CN)'"
# skip this one and resume with the next CN in the list
continue
}
$groups = $user.MemberOf
if (!$groups -or $groups.Count -eq 0) {
[PSCustomObject]#{
SourceCN = $user.CN
MemberOf = 'No Groups'
}
}
else {
foreach($group in $groups) {
[PSCustomObject]#{
SourceCN = $user.CN
MemberOf = (Get-ADGroup -Identity $group).Name
}
}
}
} | Export-Csv -Path .\Output.csv -Delimiter ";" -NoTypeInformation
This is a bit clunky, but you can use nested loops:
Import-Csv -Path .\Input_CN.csv | ForEach-Object {
$user = Get-ADUser -filter "CN -eq '$($_.CN)'" -properties cn, memberof
$user | ForEach-Object {
$_.MemberOf |
ForEach-Object {
[PSCustomObject]#{
SourceCN = $user.CN
MemberOf = $_.split('[=,]')[1]
}
}
}
} | Where-Object {$null -ne $_.MemberOf} |
Export-Csv -Path .\Output.csv -Delimiter ";" -NoTypeInformation
UPDATE: Updated to show only the 'CN' part of the group name and to filter any users who are not a member of any group.
All in one line could be
Get-ADUser -filter {Enabled -eq $True} -Properties Name, Created | Select-Object Name, Created, #{Name="Groups";Expression={Get-ADPrincipalGroupMembership -Identity $_.SamAccountName | Where-Object {$_.GroupCategory -Eq 'Security'} | Join-String -Property Name -Separator ", "}}

Export-Csv doesn't show AD group name while exporting its members

I have a list with AD groups in a CSV file: Input_ADGroup.csv
Column A looks like this:
CN
ADgroup1
ADgroup2
I already have some code which list all the users of the groups in the output.csv file, however I am missing the ADgroup name. So it is unclear which users are member of which group.
$Manager = #{Name = "Manager"; Expression = {%{(Get-ADUser $_.Manager -Properties DisplayName).DisplayName}}}
$Manager_Location = #{Name = "Manager_Location"; Expression = {%{(Get-ADUser $_.Manager -Properties Office).Office}}}
$Fields = #(
'SamAccountName'
'CN'
'DisplayName'
'Office'
'mail'
'Department'
$Manager
$Manager_Location
)
Import-Csv -Path H:\Test\Input_ADGroup.csv |
ForEach-Object {
Get-ADGroup -Filter "CN -eq '$($_.CN)'" -Properties * -ErrorAction SilentlyContinue |
Get-ADGroupMember | Get-ADUser -properties * | Select $Fields
} | Export-Csv -Path H:\Test\Output_ADGroup.csv -NoTypeInformation
H:\Test\Output_ADGroup.csv
So is it possible to get a column which shows the "source-ADgroup"... or another format which breaks the list with the ADGroup name or something?
IMO my other suggested solution is more efficient applyig the same CN from the input:
$Data = ForEach($CN in (Import-Csv -Path H:\Test\Input_ADGroup.csv).CN) {
Get-ADGroup -Filter "CN -eq '$CN'" -Properties CN -ErrorAction SilentlyContinue |
Get-ADGroupMember | Get-ADUser -Properties * | Select-Object ($Fields+#{n="Group";e={$CN}})
}
$Data
$Data | Export-Csv -Path H:\Test\Output_ADGroup.csv -NoTypeInformation
As you already have AD group name in $_, you can add one more calculated property to your Select-Object by changing this:
Get-ADGroup -Filter "CN -eq '$($_.CN)'" -Properties * -ErrorAction SilentlyContinue |
Get-ADGroupMember | Get-ADUser -properties * | Select $Fields
to this (saving first group name to variable to not mix up with $_ used later in pipeline):
$GroupName = $_.CN
Get-ADGroup -Filter "CN -eq '$($_.CN)'" -Properties * -ErrorAction SilentlyContinue |
Get-ADGroupMember | Get-ADUser -properties * | Select ($Fields+#{n="Group";e={$GroupName}})
Credits to #LotPings and #Maikel for pointing out the issue with incorrect $_ usage in comments
NOTE: remember about brackets, otherwise you'd receive an error like:
Select-Object : A positional parameter cannot be found that accepts argument n="Group";e={$GroupName}
#Lotpings #robdy - Thanks for your input, I got it working so many thanks. See code below
Import-Csv -Path H:\Test\Input_ADGroup.csv |
ForEach-Object {
Get-ADGroup -Filter "CN -eq '$($_.CN)'" -Properties CN -PipelineVariable name -ErrorAction SilentlyContinue |
Get-ADGroupMember | Get-ADUser -properties * | Select ($Fields+#{n="Group";e={$name}})
} | Export-Csv -Path H:\Test\Output_ADGroup.csv -NoTypeInformation
H:\Test\Output_ADGroup.csv
One last note: The AD group gets displayed as CN=Groupname,OU=...OU=… etc
I couldn't get it to show just "Groupname" but this really is not an issue.

Powershell - query all users who only belong to domain users

I would like an active directory query to list all users who only belong to "Domain Users" and no other groups.
I already tried the following query, but it showed all users with all groups they belong to:
Import-Module Activedirectory
Get-ADUser -Filter * -Properties DisplayName,memberof | % {
New-Object PSObject -Property #{
UserName = $_.DisplayName
Groups = ($_.memberof | Get-ADGroup | Select -ExpandProperty Name) -join ","
}
} | Select UserName,Groups | Export-Csv C:\temp\report.csv -NTI
Search for an empty memberof-property while PrimaryGroup is "Domain Users". No need to list the groups if you expect nothing.
Get-ADUser -Filter "samaccountname -eq 'froflatest-sshf'" -Properties Memberof, PrimaryGroup, DisplayName, Description |
Where-Object { -not ($_.memberof) -and $_.PrimaryGroup -match 'Domain Users' } |
Select-Object SamAccountName, DisplayName, Description |
Export-CSV -Path "c:\report.csv" -NoTypeInformation
Import-Module Activedirectory
Get-ADUser -Filter "*" -Properties sAMAccountName,Description, Memberof, PrimaryGroup |
Where-Object { -not ($_.memberof) -and $_.PrimaryGroup -match 'Domain Users' } | Select sAMAccountName,Description | Export-Csv C:\temp\report.csv -NTI

Get recursive group membership of all AD users using Powershell

I'm trying to make a PS script which would list all Active Directory user group membership (recursive).
I already have working script:
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$groups = Get-ADPrincipalGroupMembership $user
foreach ($group in $groups)
{
$username = $user.samaccountname
$groupname = $group.name
$line = "$username;$groupname"
Add-Content $targetFile $line
}
}
But script doesn't list groups recursively, i.e., if group listed in the output file is part of another group.
Example:
Group1: User
Group2: Group3: User
Script shows only Group1 and 3 but not 2.
What should I add to the first script that it writes group membership recursively?
Sorry I am publishing an answer for a question from 3 years ago but if someone will see it, it can help.
Credit to:
How to get ALL AD user groups (recursively) with Powershell or other tools?
You can use the LDAP_MATCHING_RULE_IN_CHAIN:
Get-ADGroup -LDAPFilter "(member:1.2.840.113556.1.4.1941:=CN=User,CN=USers,DC=x)"
You can use it anywahere that you can use an LDAP filter.
Example:
$username = 'myUsername'
$dn = (Get-ADUser $username).DistinguishedName
Get-ADGroup -LDAPFilter ("(member:1.2.840.113556.1.4.1941:={0})" -f $dn) | select -expand Name | sort Name
Fix in your script:
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$dn = $user.DistinguishedName
$groups = Get-ADGroup -LDAPFilter ("(member:1.2.840.113556.1.4.1941:={0})" -f $dn) | select -expand Name | sort Name
foreach ($group in $groups)
{
$username = $user.samaccountname
$groupname = $group.name
$line = "$username;$groupname"
Add-Content $targetFile $line
}
}
If you make it a function you can call it recursively. Check this out, I think you'll be pleased with the results:
Function Get-ADGroupsRecursive{
Param([String[]]$Groups)
Begin{
$Results = #()
}
Process{
ForEach($Group in $Groups){
$Results+=$Group
ForEach($Object in (Get-ADGroupMember $Group|?{$_.objectClass -eq "Group"})){
$Results += Get-ADGroupsRecursive $Object
}
}
}
End{
$Results | Select -Unique
}
}
Toss that at the top of your script, and then call it for each user. Something like:
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" -Properties MemberOf | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$Groups = $User.MemberOf
$Groups += $Groups | %{Get-ADGroupsRecursive $_}
$Groups | %{New-Object PSObject -Property #{User=$User;Group=$_}}|Export-CSV $targetfile -notype -append
}
Now, depending on the size of your AD structure that may take quite a while, but it will get you what you were looking for.
It is very easy. Just use ActiveRoles Management Shell for Active Directory. Cmdlet Get-QADMemberOf with parameter Indirect is the one you are looking for. Example:
Get-QADMemberOf john.smith -Indirect
The Quest object returned already include All Recursive groupes (and first level users) in properties $_.AllMembers
Add-PSSnapin Quest.ActiveRoles.ADManagement
$UsersFirstLevel = ($Members | Get-QADObject -Type Group -DontUseDefaultIncludedProperties | Get-QADGroupMember -DontUseDefaultIncludedProperties | ?{$_.type -eq 'user'})
$UsersSubGroup = ($Members | Get-QADObject -Type Group -DontUseDefaultIncludedProperties | Get-QADGroupMember -DontUseDefaultIncludedProperties | ?{$_.type -eq 'group'}).Allmembers | Get-QADObject -DontUseDefaultIncludedProperties | ?{$_.type -eq 'user'}
$RecursiveUsers = $UsersFirstLevel
$RecursiveUsers += $UsersSubGroup
$RecursiveUsers = $RecursiveUsers | Sort-Object -Unique
Newer versions of PowerShell (AD Module) do have -Recursive switch. So you can easily use Get-ADGroupMember.
Example: Get-ADGroupMember -Identity My_Group -Recursive