PowerShell - AD
9 TopicsQuery OU - Get Groups - Get Group Members - Export to CSV
The AI result did not work I am getting an error. The error is "Get-ADGroupMember: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input." Import-Module ActiveDirectory # Specify the OU where your groups are located $SearchBase = "CN=test,DC=test,DC=LOC" # Get all groups within the specified OU $Groups = Get-ADGroup -Filter * -Properties * -SearchBase $SearchBase # Initialize an empty array to store group members $GroupMembers = @() foreach ($Group in $Groups) { $Members = $Group | Get-ADGroupMember foreach ($Member in $Members) { $Info = New-Object psObject $Info | Add-Member -MemberType NoteProperty -Name "GroupName" -Value $Group.Name $Info | Add-Member -MemberType NoteProperty -Name "Description" -Value $Group.Description $Info | Add-Member -MemberType NoteProperty -Name "Member" -Value $Member.Name $GroupMembers += $Info } } # Export the results to a CSV file $GroupMembers | Sort-Object GroupName | Export-CSV C:\temp\group_members.csv -NoTypeInformationSolved317Views0likes5CommentsRun Get-Aduser from Get-Adgroupmember with users from sub-domains
Hello, I running is script that retrieves users from a group in ad.local The users within can be from ad.local and/or subdomain1.ad.local, subdomain2.ad.local etc When I run (from a computer that is part of subdomain1.ad.local) $userlist = get-adgroupmember -Identity $object_name -Server $object_ad -Credential $mycreds foreach ($user in$userlist){ $userad= Get-ADUser -Identity $($user.distinguishedName) } => I get Get-ADuser : A referral was returned from the server I tried this : Get-ADUser -Identity $($user.distinguishedName) -server "usersdomain" -Credential $mycreds It works. But get-adgroupmember only returns distinguishedName : CN=jdoe,OU=Users,DC=subdomain1,DC=ad,DC=local name : jdoe objectClass : user objectGUID : 2293fd35-9fa7-4acc-a22f-5799f6dd2369 SamAccountName : jdoe SID : S-1-5-21-1231254564-630871074-310601177-1324 Do you know how I can retrieve the users domain (ex : "subdomain1.ad.local" or "ad.local" etc) without having to manipulate distinguishedName ? Thank you for your help.2.1KViews0likes1CommentBlog post - Retrieve local group members of Windows Servers (Active Directory)
Wrote a blog post about how to get all local group members of Active Directory member servers, more information here https://powershellisfun.com/2022/10/21/retrieve-all-local-group-members-of-active-directory-member-servers/ The script: function Get-LocalGroupMembers { param ( [parameter(Mandatory = $true)][string]$Outfile, [parameter(Mandatory = $false)][string]$ComputerNameFilter, [parameter(Mandatory = $false)][string]$OUfilter ) #Check if both ComputerNameFilter and OUfilter where used if ($ComputerNameFilter -and $OUfilter) { Write-Warning ("Both COmputerNameFilter and OUfilter were used, these can't be combined. Exiting...") return } #Check file extension, if it's not .csv or .xlsx exit if (-not ($Outfile.EndsWith('.csv') -or $Outfile.EndsWith('.xlsx'))) { Write-Warning ("The specified {0} output file should use the .csv or .xlsx extension, exiting..." -f $Outfile) return } #Check is ActiveDirectory module is intalled if (-not (Get-Module -ListAvailable | Where-Object Name -Match ActiveDirectory)) { Write-Warning ("ActiveDirectory PowerShell Module was not found, please install before running script...") return } #Retrieve all enabled computer accounts of Domain Member servers which updated their computer account the last 30 days, skip Domain Controllers #Using $ComputerNameFilter if ($ComputerNameFilter) { $servers = Get-ADComputer -Filter { (OperatingSystem -like 'Windows Server*') -and (PrimaryGroupID -ne '516') -and (Enabled -eq $TRUE) } -Properties LastLogonDate ` | Where-Object Name -Match $ComputerNameFilter ` | Where-Object LastLogonDate -gt (Get-Date).AddDays(-31) ` | Sort-Object Name } #Using OUfilter if ($OUfilter) { $servers = Get-ADComputer -Filter { (OperatingSystem -like 'Windows Server*') -and (PrimaryGroupID -ne '516') -and (Enabled -eq $TRUE) } -Properties LastLogonDate ` | Where-Object DistinguishedName -Match $OUfilter ` | Where-Object LastLogonDate -gt (Get-Date).AddDays(-31) ` | Sort-Object Name } #Without a Name or OU filter if (-not $OUfilter -and -not $ComputerNameFilter) { $servers = Get-ADComputer -Filter { (OperatingSystem -like 'Windows Server*') -and (PrimaryGroupID -ne '516') -and (Enabled -eq $TRUE) } -Properties LastLogonDate -ErrorAction Stop ` | Where-Object LastLogonDate -gt (Get-Date).AddDays(-31) ` | Sort-Object Name } #Exit if no computer accounts were found if ($servers.count -eq 0) { Write-Warning ("No Computer Accounts were found, check access or filters. Exiting...") return } $total = foreach ($server in $servers) { #Retrieve all local groups on the server and their members try { $groupmembers = Get-CimInstance -ClassName Win32_GroupUser -ComputerName $server.name -ErrorAction Stop | Where-Object GroupComponent -Match $server.Name Write-Host ("`nRetrieving local groups and their members on server {0}" -f $server.name) -ForeGroundColor Green } catch { Write-Warning ("Could not connect to {0}, skipping..." -f $server.Name) Continue } #Loop through all groupmembers and add them to the $total variable foreach ($member in $groupmembers) { Write-Host ("[{0}] Adding {1} from domain or server {2} which is member of the local group '{3}'" -f $member.PSComputerName, $member.PartComponent.Name, $member.PartComponent.Domain, $member.GroupComponent.Name) -ForegroundColor Green [PSCustomObject]@{ Server = $member.PSComputerName Group = $member.GroupComponent.Name Domain = $member.PartComponent.Domain Member = $member.PartComponent.Name } } } #Output to report is resuls where found if ($total.count -gt 0) { #Export results to either CSV of XLSX, install ImportExcel module if needed if ($Outfile.EndsWith('.csv')) { try { New-Item -Path $Outfile -ItemType File -Force:$true -Confirm:$false -ErrorAction Stop | Out-Null $total | Sort-Object Server, Group, User | Export-Csv -Path $Outfile -Encoding UTF8 -Delimiter ';' -NoTypeInformation Write-Host ("`nExported results to {0}" -f $Outfile) -ForegroundColor Green } catch { Write-Warning ("`nCould not export results to {0}, check path and permissions" -f $Outfile) } } if ($Outfile.EndsWith('.xlsx')) { try { #Test path and remove empty file afterwards because xlsx is corrupted if not New-Item -Path $Outfile -ItemType File -Force:$true -Confirm:$false -ErrorAction Stop | Out-Null Remove-Item -Path $Outfile -Force:$true -Confirm:$false | Out-Null #Install ImportExcel module if needed if (-not (Get-Module -ListAvailable | Where-Object Name -Match ImportExcel)) { Write-Warning ("`nImportExcel PowerShell Module was not found, installing...") Install-Module ImportExcel -Scope CurrentUser -Force:$true Import-Module ImportExcel } $total | Sort-Object Server, Group, User | Export-Excel -AutoSize -BoldTopRow -FreezeTopRow -AutoFilter -Path $Outfile Write-Host ("`nExported results to {0}" -f $Outfile) -ForegroundColor Green } catch { Write-Warning ("`nCould not export results to {0}, check path and permissions" -f $Outfile) } } } else { Write-Warning ("Could not find any members, please check acces or filter...") } }1.4KViews0likes0CommentsBlogpost - Report on changed Active Directory groups using PowerShell
Wrote a blog post on how to monitor Active Directory admin groups and how to log/report changes on them. The script below monitors the groups you specify and emails them to an admin address if there are changes. (More details here https://powershellisfun.com/2022/07/13/report-on-changed-active-directory-groups-using-powershell/ ) #Set Logs folder $logs = 'c:\scripts\logs' #Create Logs folder it it doesn't exist if (-not (Test-Path -Path $logs -PathType Any)) { New-Item -Path $logs -ItemType Directory | Out-Null } #Start Transcript logging to $logs\run.log Start-Transcript -Path "$($logs)\run.log" -Append #Configure groups to monitor $admingroups = @( "Account Operators", "Administrators", "Backup Operators", "Domain Admins", "DNSAdmins", "Enterprise Admins", "Group Policy Creator Owners", "Schema Admins", "Server Operators" ) #rename previous currentmembers.csv to previousmembers.csv and rename the old #previousmembers.csv to one with a time-stamp for archiving if (Test-Path -Path "$($logs)\previousmembers.csv" -ErrorAction SilentlyContinue) { #Set date format variable $date = Get-Date -Format 'dd-MM-yyyy-HHMM' Write-Host ("- Renaming previousmembers.csv to {0}_previousmembers.csv" -f $date) -ForegroundColor Green Move-Item -Path "$($logs)\previousmembers.csv" -Destination "$($logs)\$($date)_previousmembers.csv" -Confirm:$false -Force:$true } if (Test-Path -Path "$($logs)\currentmembers.csv" -ErrorAction SilentlyContinue) { Write-Host ("- Renaming currentmembers.csv to previousmembers.csv") -ForegroundColor Green Move-Item -Path "$($logs)\currentmembers.csv" -Destination "$($logs)\previousmembers.csv" -Confirm:$false -Force:$true } #Retrieve all direct members of the admingroups, #store them in the members variable and output #them to currentmembers.csv $members = foreach ($admingroup in $admingroups) { Write-Host ("- Checking {0}" -f $admingroup) -ForegroundColor Green try { $admingroupmembers = Get-ADGroupMember -Identity $admingroup -Recursive -ErrorAction Stop | Sort-Object SamAccountName } catch { Write-Warning ("Members of {0} can't be retrieved, skipping..." -f $admingroup) $admingroupmembers = $null } if ($null -ne $admingroupmembers) { foreach ($admingroupmember in $admingroupmembers) { Write-Host (" - Adding {0} to list" -f $admingroupmember.SamAccountName) -ForegroundColor Green [PSCustomObject]@{ Group = $admingroup Member = $admingroupmember.SamAccountName } } } } #Save found members to currentmembers.csv and create previousmembers.csv if not present (First Run) Write-Host ("- Exporting results to currentmembers.csv") -ForegroundColor Green $members | export-csv -Path "$($logs)\currentmembers.csv" -NoTypeInformation -Encoding UTF8 -Delimiter ';' if (-not (Test-Path "$($logs)\previousmembers.csv")) { $members | export-csv -Path "$($logs)\previousmembers.csv" -NoTypeInformation -Encoding UTF8 -Delimiter ';' } #Compare currentmembers.csv to the #previousmembers.csv $CurrentMembers = Import-Csv -Path "$($logs)\currentmembers.csv" -Delimiter ';' $PreviousMembers = Import-Csv -Path "$($logs)\previousmembers.csv" -Delimiter ';' Write-Host ("- Comparing current members to the previous members") -ForegroundColor Green $compare = Compare-Object -ReferenceObject $PreviousMembers -DifferenceObject $CurrentMembers -Property Group, Member if ($null -ne $compare) { $differencetotal = foreach ($change in $compare) { if ($change.SideIndicator -match ">") { $action = 'Added' } if ($change.SideIndicator -match "<") { $action = 'Removed' } [PSCustomObject]@{ Date = $date Group = $change.Group Action = $action Member = $change.Member } } #Save output to file $differencetotal | Sort-Object group | Out-File "$($logs)\$($date)_changes.txt" #Send email with changes to admin email address Write-Host ("- Emailing detected changes") -ForegroundColor Green $body = Get-Content "$($logs)\$($date)_changes.txt" | Out-String $options = @{ Body = $body Erroraction = 'Stop' From = 'email address removed for privacy reasons' Priority = 'High' Subject = "Admin group change detected" SmtpServer = 'emailserver.domain.local' To = 'email address removed for privacy reasons' } try { Send-MailMessage @options } catch { Write-Warning ("- Error sending email, please check the email options") } } else { Write-Host ("No changes detected") -ForegroundColor Green } Stop-Transcript3.3KViews1like2CommentsBlogpost - Retrieving Security events from Active Directory
Wrote a blog post about getting Security events from your Domain Controller, the script is shown below: (More information here https://powershellisfun.com/2022/07/19/retrieve-security-events-from-active-directory-using-powershell/ ) function Get-SecurityEvents { param ( [Parameter(Mandatory = $true, HelpMessage = "Number of hours to search back", Position = 1)][string]$hours, [Parameter(Mandatory = $true, HelpMessage = "Folder for storing found events", Position = 2)][string]$outputfolder, [Parameter(Mandatory = $False, HelpMessage = "Enter email-address to send the logs to", Position = 3)][string]$to_emailaddress, [Parameter(Mandatory = $False, HelpMessage = "Enter the From Address", Position = 4)][string]$from_emailaddress, [Parameter(Mandatory = $False, HelpMessage = "Enter the SMTP server to use", Position = 5)][string]$smtpserver ) # Test admin privileges without using -Requires RunAsAdministrator, # which causes a nasty error message, if trying to load the function within a PS profile but without admin privileges if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")) { Write-Warning ("Function {0} needs admin privileges, aborting..." -f $MyInvocation.MyCommand) break } #Get Domain Controller with PDC FSMO Role to get events from try { $domaincontroller = (Get-ADDomain).PDCEmulator } catch { Write-Warning ("Unable to get Domain information, check ActiveDirectory module installation. Aborting...") } #Event id's from https://www.ultimatewindowssecurity.com/securitylog/book/page.aspx?spid=chapter8 $useraccountmanagementeventids = 4720, #A user account was created 4722, #A user account was enabled 4723, #An attempt was made to change an account's password 4724, #An attempt was made to reset an accounts password 4725, #A user account was disabled 4726, #A user account was deleted 4738, #A user account was changed 4740, #A user account was locked out 4767, #A user account was unlocked 4780, #The ACL was set on accounts which are members of administrators groups 4781, #The name of an account was changed 4794, #n attempt was made to set the Directory Services Restore Mode administrator password 5376, #Credential Manager credentials were backed up 5377 #redential Manager credentials were restored from a backup $computeraccountmanagementeventids = 4741, #A computer account was created 4742, #A computer account was changed 4743 #A computer account was deleted $securitygroupmanagementeventids = 4727, #A security-enabled global group was created 4728, #A member was added to a security-enabled global group 4729, #A member was removed from a security-enabled global group 4730, #A security-enabled global group was deleted 4731, #A security-enabled local group was created 4732, #A member was added to a security-enabled local group 4733, #A member was removed from a security-enabled local group 4734, #A security-enabled local group was deleted 4735, #A security-enabled local group was changed 4737, #A security-enabled global group was changed 4754, #A security-enabled universal group was created 4755, #A security-enabled universal group was changed 4756, #A member was added to a security-enabled universal group 4757, #A member was removed from a security-enabled universal group 4758, #A security-enabled universal group was deleted 4764 #A groups type was changed $distributiongroupmanagementeventids = 4744, #A security-disabled local group was created 4745, #A security-disabled local group was changed 4746, #A member was added to a security-disabled local group 4747, #A member was removed from a security-disabled local group 4748, #A security-disabled local group was deleted 4749, #A security-disabled global group was created 4750, #A security-disabled global group was changed 4751, #A member was added to a security-disabled global group 4752, #A member was removed from a security-disabled global group 4753, #A security-disabled global group was deleted 4759, #A security-disabled universal group was created 4760, #A security-disabled universal group was changed 4761, #A member was added to a security-disabled universal group 4762, #A member was removed from a security-disabled universal group 4763 #A security-disabled universal group was deleted $applicationgroupmanagementeventids = 4783, #A basic application group was created 4784, #A basic application group was changed 4785, #A member was added to a basic application group 4786, #A member was removed from a basic application group 4787, #A non-member was added to a basic application group 4788, #A non-member was removed from a basic application group 4789, #A basic application group was deleted 4790, #An LDAP query group was created 4791, #A basic application group was changed 4792 #An LDAP query group was deleted $otheraccountmanagementeventids = 4739, #Domain Policy was changed 4793 #The Password Policy Checking API was called #Set empty collection variable, date and eventids $collection = @() $date = (Get-Date).AddHours( - $($hours)) $filteruseraccountmanagement = @{ Logname = 'Security' ID = $useraccountmanagementeventids StartTime = $date EndTime = [datetime]::Now } $filtercomputeraccountmanagement = @{ Logname = 'Security' ID = $computeraccountmanagementeventids StartTime = $date EndTime = [datetime]::Now } $filtersecuritygroupmanagement = @{ Logname = 'Security' ID = $securitygroupmanagementeventids StartTime = $date EndTime = [datetime]::Now } $filterdistributiongroupmanagement = @{ Logname = 'Security' ID = $distributiongroupmanagementeventids StartTime = $date EndTime = [datetime]::Now } $filterapplicationgroupmanagement = @{ Logname = 'Security' ID = $applicationgroupmanagementeventids StartTime = $date EndTime = [datetime]::Now } $filterotheraccountmanagement = @{ Logname = 'Security' ID = $otheraccountmanagementeventids StartTime = $date EndTime = [datetime]::Now } #Retrieve events Write-Host ("Retrieving Security events from {0}..." -f $domaincontroller) -ForegroundColor Green foreach ($eventids in ` $filteruseraccountmanagement, ` $filtercomputeraccountmanagement, ` $filtersecuritygroupmanagement, ` $filterdistributiongroupmanagement, ` $filterapplicationgroupmanagement, ` $filterotheraccountmanagement ) { $events = Get-WinEvent -FilterHashtable $eventids -ComputerName $domaincontroller -ErrorAction SilentlyContinue foreach ($event in $events) { Write-Host ("- Found EventID {0} on {1} and adding to list..." -f $event.id, $event.TimeCreated) -ForegroundColor Green $eventfound = [PSCustomObject]@{ DomainController = $domaincontroller Timestamp = $event.TimeCreated LevelDisplayName = $event.LevelDisplayName EventId = $event.Id Message = $event.message -replace '\s+', " " } $collection += $eventfound } } if ($null -ne $collection) { $filenametimestamp = Get-Date -Format 'dd-MM-yyyy-HHmm' Write-Host ("- Saving the {0} events found to {1}..." -f $collection.count, "$($outputfolder)\events_$($filenametimestamp).csv") -ForegroundColor Green $collection | Sort-Object TimeStamp, DomainController, EventId | Export-Csv -Delimiter ';' -NoTypeInformation -Path "$($outputfolder)\events_$($filenametimestamp).csv" if ($to_emailaddress) { $emailoptions = @{ Attachments = "$($outputfolder)\events_$($filenametimestamp).csv" Body = "See Attached CSV file" ErrorAction = "Stop" From = $from_emailaddress Priority = "High" SmtpServer = $smtpserver Subject = "Security event found" To = $to_emailaddress } Write-Host ("- Emailing the {0} events found to {1}..." -f $collection.count, $to_emailaddress) -ForegroundColor Green try { Send-MailMessage @emailoptions } catch { Write-Warning ("Unable to email results, please check the email settings...") } } } }1.4KViews1like2CommentsPowershell Command for AD export
I have been searching for info, I am not even sure if what I am doing is feasible. All I want to do is export AD all computers. I have the command "Get-ADComputer -Filter "*" | Export-CSV -Path c:\Users\USERNAME\documents\Computers.csv" and this works fine, BUT... I want to be able to add a pull of serial numbers 1) either through the attribute editor in AD or 2) by using Get-WmiObject Win32_BIOS | Select SerialNumber and having it the serial number displayed in the .csv file. I have tried so many combinations of commands, but nothing works. I even tried to add in the "ForEach" option. I have used Get-WmiObject Win32_ComputerSystem | Select Manufacturer,Model to get get the info from my own computer, but if I am able to get it exported into the .csv as well - not required, but would be a bonus for my reports. If I can get a command that combines basic AD computer properties & at least serial number, I would greatly appreciate it. And if the command can also include what to add in the get the make/model of the computer, I would appreciate it more! Thank you for your time and assistance!5.3KViews0likes4CommentsUnable to upgrade to A7 and A8 using Azure PowerShell Cmdlet -
We are using this Cmdlet: https://docs.microsoft.com/en-us/powershell, to Upgrade the SKU to A7 and A8. We are able to scale to A7 from UI as shown below. On trying with PowerShell Cmdlet, we get the below error: Update-AzureRmPowerBIEmbeddedCapacity : Cannot validate argument on parameter 'Sku'. The argument "A7" does not belong to the set "A1,A2,A3,A4,A5,A6" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again. At line:70 char:121 + ... -Name $pbiEmbCap.Name -ResourceGroupName $resourceGroupName -Sku $sku + ~~~~ + CategoryInfo : InvalidData: (:) [Update-AzureRmPowerBIEmbeddedCapacity], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Azure.Commands.PowerBI.UpdateAzurePowerBIEmbeddedCapacity Is it possible to update the parameter set including A7 and A8, so that we can use the same Cmdlet to upgrade the SKU888Views0likes1CommentNeed to change bulk users Samaccountname to uppercase
Hello I am trying to get this script to update a list of samaccountname from lowercase to uppercase. We have an application that has issues with lowercase. I have tried the below and it is giving me a "You cannot call a method on a null-valued expression" error when running. I am not sure what I am doing wrong but any help will be greatly appreciated. Here is the script I am using now. $users = get-content '.\users.txt' foreach($user in $users){ set-aduser $user -SamAccountName $user.samaccountname.toupper() }Solved5.5KViews0likes4CommentsExport/Import Users/Groups from AD to Test AD
I'm trying to compile a script that will help in my project. Project scope: Mirror Prod to Dev AD. Export all users and security group membership (including nested groups) to a csv. Users live in Sub OU's and sub OU's of the previous OU so would need to capture all. My current script you have to manually change each OU when running and this is not doable long term. I need to incorporate the correct attributes needed to build a new AD account on import (FirstName, email address, UPN, etc.) After the export, I can massage the csv to use the new test domain information so the import process will work correctly. Import process should build new users, assign temp password and also overlook any users that are already built in the new test AD. I did get some users there and need the script to overlook ones that may already exists but still add them to the right group memberships. AD server is 2016Datacenter Any help is truly appreciated!3KViews0likes4Comments