Windows PowerShell Filtering by data range - powershell

I have a powershell script to get deactivated accounts from our SSO app but would like to filter it down to only those that were deactivated more than 90 days ago.
I then have another script to take the results and deletes those users from the SSO app.
Can you tell me how to add a filter to the below script to exclude results were the StatusChanged date is greater than 90 days from current date.
$users = oktaListDeprovisionedUsers -oOrg PREV
$toexport = New-Object System.Collections.ArrayList
Foreach ($u in $users)
{
$line = #{
status = $u.status
employeeid = $u.profile.employeeNumber
firstName = $u.profile.firstName
lastName = $u.profile.lastName
email = $u.profile.email
department = $u.profile.department
supervisor = $u.profile.manager
created = $u.created
lastUpdated = $u.lastUpdated
login = $u.profile.login
title = $u.profile.title
GroupName = $u.profile.Group_Name
Organization = $u.profile.organization
Location = $u.profile.workday_location
User_type = $u.profile.userType
StatusChanged = $u.StatusChanged
}
$obj = New-Object psobject -Property $line
$_c = $toexport.Add($obj)
}
#Path for utility will have to be changed to a more generic location.
$toexport | Select-Object "login", "StatusChanged", "employeeid", "firstName","lastName", "email", "title","supervisor","department","Organization","Location", "GroupName" | >Export-Csv -Path "C:\OktaExport\user-list.csv" -NoTypeInformation

You can filter the $users object by a Where-Object
$users = $users | Where-Object{((Get-Date) - $_.StatusChanged).TotalDays -gt 90}
Add this to the 2nd line of your script.

Related

Add user to Meeting using Update-MgUserEvent

I'm trying to add a user to an existing meeting using "Update-MgUserEvent."
I can pull the existing event fine. However, I'm having trouble merging the existing attendees and the new attendee into something that the command will accept. Anytime I am close, it will add the new attendee and send cancellation requests to the existing attendees.
If anybody has any tips or any help at all, it would be GREATLY appreciated! Here is what I am working with so far. I'm trying to merge the "$New Attendees" and "$ExistingAttendees" data and send it back to the event as an update:
# New user to test.
$NewAttendees = #{
Attendees = #(
#{
EmailAddress = #{
Address = "bill.cosby#test.com"
Name = "Bill Cosby"
}
Type = "required"
}
)
}
# Get user start date.
$EmpStartDate = Read-Host -prompt "Enter employee start date (YYYY-MM-DD)"
# Get existing events.
Clear-Variable Existing*
$ExistingEvent = Get-MgUserEvent -UserId "michael.scott#test.com" -filter "Subject eq 'I.T. Orientation'" | Select-Object Id,Attendees -ExpandProperty start | Where-Object {$_.DateTime -like "*$EmpStartDate*"}
$ExistingAttendees = #{
Attendees = #(
#{
EmailAddress = #{
Address = $ExistingEvent.Attendees.EmailAddress | Select-Object -ExpandProperty Address
Name = $ExistingEvent.Attendees.EmailAddress.Name
}
Type = "required"
}
)
}
# Update the event.
If ($ExistingEvent) {
Update-MgUserEvent -UserId "michael.scott#test.com" -EventId $ExistingEvent.Id -Attendees ?????
}

How do I get unique email address and retain other fields

$AllMeetUsers = $null
[array]$AllMeetUsers = gam report meet user all | ConvertFrom-Csv | Select-Object 'actor.email','id.time'
[array]$result = $AllMeetUsers | ForEach-Object {
$Email = $_.'actor.email'
If (-not([string]::IsNullOrWhiteSpace($Email))) {
$IDTime = $_.'id.time'
$FormatIDTime = Get-date($IDTime) -Format("MM-dd-yy")
[PSCustomObject]#{
Email = $Email
Time = $FormatIDTime
}
}
}
Makes an output table like the following
06-07-21 <Email>
09-29-21 <Email>
06-15-21 <Email>
07-12-21 <Email>
07-20-21 <Email>
07-14-21 <Email>
I would like to remove the full duplicate email address line.
but this line is not working
[array]$result = $result | Sort-Object -Property email | Select-Object time,email -Unique
and
[array]$result = $result | Sort-Object -Property email | Select-Object email -Unique
removes the time field while giving me unique email addresses.
How do I accomplish this?
Use a Dictionnary #{} instead of an array.
$results = #{}
if (-not $results.ContainsKey($Email)) {
$results.Add($Email, [PSCustomObject]#{
Email = $Email
Time = $FormatIDTime
})
}
$results.Values
#MathiasR.Jessen made a good point in the comments and I think my code probably needs a conceptual change. However with the answer I accepted from #Hazrelle above this is how the code came out.
$AllMeetUsers = $null
[array]$AllMeetUsers = gam report meet user all | ConvertFrom-Csv | Select-Object 'actor.email','id.time'
$results = #{}
$AllMeetUsers | ForEach-Object {
$Email = $_.'actor.email'
if (-not $results.ContainsKey($Email) -and -not([string]::IsNullOrWhiteSpace($Email))) {
$IDTime = $_.'id.time'
$FormatIDTime = Get-date($IDTime) -Format("MM-dd-yy")
$results.Add($Email, [PSCustomObject]#{
Email = $Email
Time = $FormatIDTime
})
}
}
$results.values
For more information.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_hash_tables?view=powershell-7.1

How to add a boolean flag to a variable based on a condition in powershell?

I have a PS script retrieving all the devices from AD with their OU information like below:
$UserList = Get-ADComputer -Filter * -Property * | Select-Object Name,DistinguishedName,LastLogonDate
$Results = foreach ($UL_Item in $UserList)
{
[array]$OuList = #($UL_Item.DistinguishedName.Split(',')).
Where({$_ -match 'OU='}).
ForEach({$_.Split('=')[-1]}).
Trim()
[PSCustomObject]#{
ComputerName = $UL_Item.Name
OU_1 = $OuList[0]
OU_2 = $OuList[1]
OU_3 = $OuList[2]
OU_4 = $OuList[3]
OU_5 = $OuList[4]
}
}
What I would like to do is to add a flag called IsServer to my variable: $Results and set it to True if any of the OU is equal to "Domain Servers", so I am looking for the correct syntax for something like:
...
OU_5 = $OuList[4]
IsServer = if ($OuList[0]="Domain Servers" OR
$OuList[1]="Domain Servers" OR
$OuList[2]="Domain Servers" OR
$OuList[3]="Domain Servers" OR
$OuList[4]="Domain Servers" OR ) then true else false end
What is the best way to manage this? Any help would be appreciated.
You can do:
IsServer = #{$true="true";$false="false"}[($OuList -contains "Domain Servers"]

My AD users are not updating using powershell and csv

I have read many articles and I've been able to come up with a code that works for what i want to do: I want to be able to update my AD USERS and if a the attribute is blank on my csv it should be removed on the users attribute
$Users = Import-CSV "C:\Users\tolulope\Desktop\Tolu AD\ADusers2.csv"
foreach($User in $Users )
{
Write-host "$user"
Get-ADUser -Filter "DisplayName -like '$user'"|Set-ADUser -Replace #{
givenName = "$User.givenName";
sn = "$User.sn";
c = "$User.c";
cn = "$User.cn";
company = "$User.company";
co = "$User.co";
countryCode = "$User.countryCode" ;
department = "$User.department";
displayName = "$User.displayName";
mobile = "$User.mobile";
name = "$User.name";
userPrincipalName = "$User.userPrincipalName"
telephoneNumber = "$User.telephoneNumber";
streetAddress = "$User.streetAddress";
st = "$User.st";
postalCode = "$User.postalCode";
physicalDeliveryOfficeName = "$User.physicalDeliveryOfficeName";
manager = "$User.manager";
employeeID = "$User.employeeID";
title = "$User.title";
l = "$User.l";
homePhone = "$User.homePhone";
mail = "$User.mail";
}
}
Read-Host -Prompt "Press Enter to exit"

PowerShell variable definition from a pscustomobject

i've got this piece of code from a script i found on the web (just showing the part that interests me)
ForEach ($Computer in $Computername) {
$adsi = [ADSI]"WinNT://$Computername"
$adsi.Children | where {$_.SchemaClassName -eq 'user'} | ForEach {
[pscustomobject]#{
UserName = $_.Name[0]
SID = ConvertTo-SID -BinarySID $_.ObjectSID[0]
PasswordAge = [math]::Round($_.PasswordAge[0]/86400)
LastLogin = If ($_.LastLogin[0] -is [datetime]){$_.LastLogin[0]}Else{'Never logged on'}
UserFlags = Convert-UserFlag -UserFlag $_.UserFlags[0]
MinPasswordLength = $_.MinPasswordLength[0]
MinPasswordAge = [math]::Round($_.MinPasswordAge[0]/86400)
MaxPasswordAge = [math]::Round($_.MaxPasswordAge[0]/86400)
BadPasswordAttempts = $_.BadPasswordAttempts[0]
MaxBadPasswords = $_.MaxBadPasswordsAllowed[0]
}
}
}
the code displays things on the console, but i would like to define/use these values as variables instead (as i want to use them in a hash table afterwards to send them in a http/POST request afterwards)
is there a way to get all these attributes as variables such as $LastLogin, $MinPasswordAge etc ?
as i don't want to display them, but send them in a POST like this :
$postParams = #{LastLogin=$LastLogin;MinPasswordAge=$MinPasswordAge}
Invoke-WebRequest -Uri http://example.com/foobar -Method POST -Body $postParams
to be honest i'm a complete newbie in PowerShell (i'm a Perl guru) and i don't know what pscustomobject does in there, i just want to define the variables in that loop, and use them at the end.
i've tried a couple of things with no success (can post them if required)
thanks !
Your own solution works, but only if you perform all processing inside the ForEach-Object script block (unless there's only ever 1 iteration, which doesn't appear to be the case here).
If you want to process the results later, you can simply collect them in an array by assigning the entire foreach loop to a variable (code shortened):
$allUsers = foreach ($Computer in $Computername) {
$adsi = [ADSI]"WinNT://$Computername"
$adsi.Children | where {$_.SchemaClassName -eq 'user'} | ForEach {
# Output a custom object for each user.
[pscustomobject]#{
ComputerName = $Computer # also record the computer name
UserName = $_.Name[0]
SID = ConvertTo-SID -BinarySID $_.ObjectSID[0]
# ...
}
}
}
You can then simply enumerate the collected [pscustomobject]s and access their properties rather than using variables:
foreach ($user in $allUsers) {
# Use the properties to define a hashtable for later use in a http/POST request.
$ht = #{
User = $user.UserName
# ...
}
}
nm,
i found the solution a minute ago.
just got rid of that pscustomobject hash completely, and assigning the variables directory
$adsi.Children | where {$_.SchemaClassName -eq 'user'} | ForEach {
$UserName = $_.Name[0]
$SID = ConvertTo-SID -BinarySID $_.ObjectSID[0]
$PasswordAge = [math]::Round($_.PasswordAge[0]/86400)
$LastLogin = If ($_.LastLogin[0] -is [datetime]){$_.LastLogin[0]}Else{'Never logged on'}
$UserFlags = Convert-UserFlag -UserFlag $_.UserFlags[0]
$MinPasswordLength = $_.MinPasswordLength[0]
$MinPasswordAge = [math]::Round($_.MinPasswordAge[0]/86400)
$MaxPasswordAge = [math]::Round($_.MaxPasswordAge[0]/86400)
$BadPasswordAttempts = $_.BadPasswordAttempts[0]
$MaxBadPasswords = $_.MaxBadPasswordsAllowed[0]
Write-Host $UserName
}
}