Powershell - Get-AzureADAuditSignInLogs multiple filters - azure

I'm trying to Get last signin date for Global Admins
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Global Administrator'}
$admins = #(Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | select DisplayName, UserPrincipalName)
Foreach ($admin in $admins){
$upn = $admin.UserPrincipalName
$signons = Get-AzureADAuditSignInLogs -Filter "UserPrincipalName eq '$upn' " -Top 1 | select UserDisplayName, #{Name = 'LastSignIn'; Expression = {$_.CreatedDateTime}}
}
And above code works as expected for users who have entry in AuditSignInLogs, but i want to return users who never logged in too, so modified above filter
(all users in for loop)
$signons = Get-AzureADAuditSignInLogs -Filter "UserPrincipalName eq '$upn' or CreatedDateTime eq '$null'" -Top 1 | select UserDisplayName, #{Name = 'LastSignIn'; Expression = {$_.CreatedDateTime}}
But getting error "Message: Invalid filter clause"
also tried or CreatedDateTime eq '' but same error

Please check below powershell commands.
I have initially checked the same for users .
Then checked the same for admin role i.e;admins and could get the lastlogon for all the admins including who has no recored yet in signins.
$AllSiginLogs = Get-AzureADAuditSignInLogs -All $true
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Global Administrator'}
$admins = #(Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | select DisplayName, UserPrincipalName)
$results = #()
Foreach ($admin in $admins){
$LoginRecord = $AllSiginLogs | Where-Object{ $_.UserId -eq $admin.ObjectId } | Sort-Object CreatedDateTime -Descending
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord[0].CreatedDateTime
}else{
$lastLogin = 'no login record'
}
$item = #{
userUPN=$admin.UserPrincipalName
userDisplayName = $admin.DisplayName
lastLogin = $lastLogin
accountEnabled = $admin.AccountEnabled
}
$results += New-Object PSObject -Property $item
Write-Output $results
}
#$results | export-csv -Path d:\result.csv -NoTypeInformation
Result:
Reference:
userlastlogon-export

thanks #kavyasaraboju-MT
Your hint helped me a lot, based on it, i modified my code which gets what i want
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Global Administrator'}
$admins = #(Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | select DisplayName, UserPrincipalName)
$results = #()
Foreach ($admin in $admins){
$upn = $admin.UserPrincipalName
$LoginRecord = Get-AzureADAuditSignInLogs -Filter "UserPrincipalName eq '$upn'" -Top 1
Start-Sleep -Seconds 2
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord.CreatedDateTime
}
else{
$lastLogin = 'no login record'
}
$item = #{
userUPN=$admin.UserPrincipalName
userDisplayName = $admin.DisplayName
lastLogin = $lastLogin
}
$results += New-Object PSObject -Property $item
}
$results | export-csv -Path c:\result.csv -NoTypeInformation -Encoding UTF8

Related

Get-MsolServicePrincipalCredential with the right propertys

With the code below I can get a list of client secrets listed, but trying to use propertys as in the example here as you could do for example if you want to list certificates on your server won't work. I tried to google on but can't find any examples.
With -property no matter which one you pick in this example the return would be nothing.
Connect-MsolService
$applist = Get-MsolServicePrincipal -all | Where-Object -FilterScript { ($_.DisplayName -notlike "*Microsoft*") -and ($_.DisplayName -notlike "autohost*") -and ($_.ServicePrincipalNames -notlike "*localhost*") }
foreach ($appentry in $applist) {
$principalId = $appentry.AppPrincipalId
$principalName = $appentry.DisplayName
Get-MsolServicePrincipalCredential -AppPrincipalId $principalId -ReturnKeyValues $false | ? { $_.Type -eq "Password" } | Select-Object -Property DisplayName
If we skip the property, it would look like:
Type :
Password Value :
KeyId : 642ee910-9b17-4d17-93d4-0192f3c1f855
StartDate : 2018-05-25 08:22:37
EndDate : 2019-05-25 08:22:37
Usage : Verify
I want in the same list format just with more propertys so I can recyle another script to upload the data to a sharepoint list.
I solved it this way:
$clientsecrets = #()
$applist = Get-MsolServicePrincipal -all | Where-Object -FilterScript { ($_.DisplayName -like "*SI*") -or ($_.DisplayName -like "*FD*") -or ($_.DisplayName -like "*AP*") -and ($_.DisplayName -notlike "*Microsoft*") -and ($_.DisplayName -notlike "autohost*") -and ($_.ServicePrincipalNames -notlike "*localhost*") }
foreach ($appentry in $applist) {
$principalId = $appentry.AppPrincipalId
$principalName = $appentry.DisplayName
$clientsecret = Get-MsolServicePrincipalCredential -AppPrincipalId $principalId -ReturnKeyValues $false | ? { $_.Type -eq "Password" } | % { $principalName, $principalId;, ($enddate = $_.EndDate.ToString()) } | select {$principalName}, {$principalId}, {$enddate}
$clientsecret | Add-Member -MemberType NoteProperty -Name 'principalId' -Value $principalId
$clientsecret | Add-Member -MemberType NoteProperty -Name 'principalName' -Value $principalName
$clientsecrets+=$clientsecret
}
Using an array and using add-member did put it in a format where I could use and read and add it to the sharepoint list.

UserLastLogon -Export

Hi I'm trying to export a list of AD users based on "Last Logon"
I've scripted using base powershell however I'd be interested if anyone can find a solution using "AzureAD to Powershell" commands.
I've gotten as far as getting the list however I cannot export it to any file type because of how it generates through the loop.
End result I'm looking for is to be able to organize the data to see which users have been inactive?
Import-Module ActiveDirectory
function Get-ADUserLastLogon([string]$userName) {
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$time = 0
foreach($dc in $dcs) {
$hostname = $dc.HostName
$user = Get-ADUser $userName | Get-ADObject -Properties lastLogon
if($user.LastLogon -gt $time) {
$time = $user.LastLogon
}
}
$dt = [DateTime]::FromFileTime($time)
Write-Host $username "last logged on at:" $dt
}
$unames = Get-ADUser -Filter 'ObjectClass -eq "User"' | Select -Expand SamAccountName
foreach ($uname in $unames) { Get-ADUserLastLogon($uname); }
In Azure AD, we can get all user Sign-ins records on Azure Portal or using Azure AD PowerShell.
If you are looking for a way by PowerShell to export Azure AD users last login list with user account status (enabled or not), just try the code below:
Connect-AzureAD
$AllUsers = Get-AzureADUser -All $true
$AllSiginLogs = Get-AzureADAuditSignInLogs -All $true
$results = #()
foreach($user in $AllUsers){
$LoginRecord = $AllSiginLogs | Where-Object{ $_.UserId -eq $user.ObjectId } | Sort-Object CreatedDateTime -Descending
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord[0].CreatedDateTime
}else{
$lastLogin = 'no login record'
}
$item = #{
userUPN=$user.UserPrincipalName
userDisplayName = $user.DisplayName
lastLogin = $lastLogin
accountEnabled = $user.AccountEnabled
}
$results += New-Object PSObject -Property $item
}
$results | export-csv -Path d:\result.csv -NoTypeInformation
export to .csv file Result:
There is one thing that you should know, for different Azure AD service tier, the time that Azure AD keep these data is different, details see here.

Export all Azure AD Groups and their owner to a csv file

I need a way to export all Azure Ad groups with their corresponding owner to a csv file. The below code works, but the formatting of the csv file is horrendous. Everything is in one column and hard to read. How would I get all groups in one Column and the corresponding owner in a separate column in the corresponding row. Any help would be appreciated
$groups=Get-AzureADGroup -All $true
ForEach ($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
ForEach ($Owner in $Owners){
Write-output $group.DisplayName "," $Owner.ObjectId "," $Owner.ObjectType $Owner.UserType "," $Owner.UserPrincipalName >> C:\scripts\Owner.csv
}
}
Updated Script
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$groups = Get-AzureADGroup -All $true
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $id -All $true
$Properties.GroupDisplayName=$group.DisplayName
if($Owners -ne $null){
# group has owner
Foreach($Owner in $Owners){
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
else{
#group has no owner
$Properties.OwnerObjectId=$null
$Properties.OwnerObjectType=$null
$Properties.OwnerUserType=$null
$Properties.OwnerUserPrincipalName=$null
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path C:\test1234.csv -NoTypeInformation -Encoding UTF8
According to your need, you can refer to the following script:
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$groups = Get-AzureADGroup -All $true
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
ForEach ($Owner in $Owners){
$Properties.GroupDisplayName=$group.DisplayName
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path E:\test123.csv -NoTypeInformation -Encoding UTF8
Update
According to your need, I update my PowerShell script
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$groups = Get-AzureADGroup -All $true
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
$Properties.GroupDisplayName=$group.DisplayName
if($Owners -ne $null){
# group has owner
Foreach($Owner in $Owners){
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
else{
#group has no owner
$Properties.OwnerObjectId=$null
$Properties.OwnerObjectType=$null
$Properties.OwnerUserType=$null
$Properties.OwnerUserPrincipalName=$null
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path E:\test123.csv -NoTypeInformation -Encoding UTF8
In order to create a proper CSV file with headers and rows of data, you need to collect an array of Objects and send that to the Export-Csv cmdlet.
$groups = Get-AzureADGroup -All $true
$result = foreach ($group in $groups) {
Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true | ForEach-Object {
# output an object with the properties and headernames you need
# the $_ automatic variable contains 1 owner object in each iteration
[PsCustomObject]#{
'Group' = $group.DisplayName
'OwnerId' = $_.ObjectId
'OwnerType' = $_.ObjectType
'OwnerUPN' = $_.UserPrincipalName
}
}
}
# output on screen
$result | Format-Table -AutoSize
# output to CSV
$result | Export-Csv -Path 'C:\scripts\AZGroupOwners.csv' -NoTypeInformation
Hope that helps

Exporting Group Types from Azure AD Powershell

I am trying to export all Azure AD groups, their owners, description, email and its group type. Such as Office 365, Security or Distrubution. I have managed to export everything correctly into a .csv except the group type. Get-AzureADGroup will return only "Group" and I can't get any results from get-msolgroup -grouptype.
Script I have been using:
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$Properties.add("GroupDescription","6")
$Properties.add("Email","7")
$Properties.add("GroupTypes","8")
$groups = Get-AzureADGroup -All $true
$GroupType = Get-MsolGroup -Grouptype
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
$Properties.GroupDisplayName=$group.DisplayName
$Properties.GroupDescription=$group.description
$Properties.Email=$group.mail
$Properties.GroupTypes=$group.GroupType
if($Owners -ne $null){
# group has owner
Foreach($Owner in $Owners){
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
else{
#group has no owner
$Properties.OwnerObjectId=$null
$Properties.OwnerObjectType=$null
$Properties.OwnerUserType=$null
$Properties.OwnerUserPrincipalName=$null
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path C:\scripts\Owners13.csv -NoTypeInformation -Encoding UTF8
According to my research, the command Get-MsolGroup is a command of Azure AD V1 module : MSOnline. But the other commands you use are the command of Azure AD V2 module: AzureAD. They are in different modules. So if you want to use the command Get-MsolGroup, you need to run the command Connect-MsolService at frist.
For example:
Connect-MsolService
Get-MsolGroup -all | Select-Object DisplayName, GroupType
Besides, if you just want to use AzureAD module to get group type, we can use the command Get-AzureADMSGroup to get it. But if we use the command, we need to make some judgments by the response's properties. For more details, please refer to the document
For example
Connect-AzureAD
Get-AzureADMSGroup -All $true | Select-Object DisplayName, GroupTypes,MailEnabled, SecurityEnabled
Update
You can use the following script to implement your need.
connect-AzureAD
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$Properties.add("GroupDescription","6")
$Properties.add("Email","7")
$Properties.add("GroupTypes","8")
$groups = Get-AzureADGroup -All $true
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
$Properties.GroupDisplayName=$group.DisplayName
$Properties.GroupDescription=$group.description
$Properties.Email=$group.mail
$result=Get-AzureADMSGroup -Id $group.ObjectId | Select-Object GroupTypes,MailEnabled, SecurityEnabled, DisplayName
If($result.GroupTypes -contains "Unified"){
$Properties.GroupTypes="O365"
}
elseif($result.SecurityEnabled ){
$Properties.GroupTypes="Security"
}
else{
$Properties.GroupTypes="Distrubution"
}
if($Owners -ne $null){
# group has owner
Foreach($Owner in $Owners){
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
else{
#group has no owner
$Properties.OwnerObjectId=$null
$Properties.OwnerObjectType=$null
$Properties.OwnerUserType=$null
$Properties.OwnerUserPrincipalName=$null
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path E:\test.csv -Encoding UTF8 -NoTypeInformation

Switching Lastname, Firstname in Powershell AD script

I try to export AD groups and users from a OU by Firstname, Lastname but I only get it to work with Lastname, Firstname.
Everything else I try gives me an empty string for members.I tried changing the line under Select-Object to:
#{Name='Member';Expression={$_.FirstName = GetFirstName $_.Name $_.LastName = GetLastName $_.Name}},
$firt = $_.firstname
$last = $_.lastname
#{Name='Member';Expression={$_.name = "$first,$last"}},
This is the working code, but the names should be switched around.
$OU = 'OU=Groups,OU=City,OU=Continent,DC=DomainControler, DC=Domain, DC=net' #Change this to get different groups
$DateTime = Get-Date -f "dd-MM-yyyy"
$MyFileName = "CompanyName-Groups_"+$DateTime+".csv"
$Path = Join-Path $PSScriptRoot $MyFileName
$Groups = get-adobject -Filter 'ObjectClass -eq "group"' -SearchBase $OU
$i=0
$tot = $Groups.count
$Data = foreach ($Group in $Groups) {
$i++
$status = "{0:N0}" -f ($i / $tot * 100)
Write-Progress -Activity "Exporting AD Groups" -status "Processing Group $i of $tot : $status% Completed" -PercentComplete ($i / $tot * 100)
Get-ADGroupMember -Identity $Group |
Select-Object #{Name='Group';Expression={$Group.Name}},
#{Name='Member';Expression={$_.Name}},
#{Name='Enabled';Expression={if ($_.ObjectClass -eq 'user') {Get-ADUser $_ | Select-Object -Expand Enabled} else {'NA/Group'}}}
}
$Data | Export-Csv -Path $Path -NoTypeInformation
This is an example output:
Group, "member", enabled
Admin, "Mario, Speedwagon", True
Admin, "Petey, Cruiser", True
Admin, "Anna, Sthesia", False
HR, "Paul, Molive", True
HR, "Phaedra, Lugt", True
IT, "Paul, Molive", False
IT, "Cliff, Hanger", True
This is what it should become:
Group, "member", enabled
Admin, "Speedwagon, Mario", True
Admin, "Cruiser, Petey", True
Admin, "Sthesia, Anna", False
HR, "Molive, Paul", True
HR, "Lugt, Phaedra", True
IT, "Molive, Paul", False
IT, "Hanger, Cliff", True
I think this might clear things up for you:
$OU = 'OU=Groups,OU=City,OU=Continent,DC=DomainControler, DC=Domain, DC=net'
$PathParams = #{
Path = $PSScriptRoot
ChildPath = "PA-AD-Groups_{0}.csv" -f (Get-Date -f "dd-MM-yyyy")
}
$FilePath = Join-Path #PathParams
$Groups = Get-ADObject -Filter 'ObjectClass -eq "group"' -SearchBase $OU
$i = 0
$tot = $Groups.count
$Data = foreach ($Group in $Groups) {
$i++
$ProgressParams = #{
Activity = 'Exporting AD Groups'
PercentComplete = ($i / $tot * 100)
status = "Processing Group $i of $tot : {0:N0} Completed" -f
($i / $tot * 100)
}
Write-Progress #ProgressParams
Get-ADGroupMember -Identity $Group |
Select-Object #{Name = 'Group'; Expression = {$Group.Name}},
#{Name = 'Member'; Expression = {$_.Name}},
#{Name = 'Enabled'; Expression = {
$Script:User = $false
if ($_.ObjectClass -eq 'user') {
$Script:User = Get-ADUser $_
if ($User.Enabled) {$true} else {$false}
}
else {
'NA/Group'
}
}
},
#{Name = 'FirstName'; Expression = {
if ($User) {
$User.GivenName
}
}
},
#{Name = 'LastName'; Expression = {
if ($User) {
$User.Surname
}
}
},
#{Name = 'CombinedName'; Expression = {
if ($User) {
"{0}, {1}" -f $User.GivenName, $User.Surname
}
}
}
}
$Data | Export-Csv -Path $FilePath -NoTypeInformation
The issue you have is that you can't use the properties from $User outside of the Expression within the Select-Object. This is simply fixed by creating a variable that is available throughout the script and as such is called Script scope, used as $Script:User.
More info can be found in Get-Help about_Scopes or here.
On a side note I would advice you to use proper indentation, it makes things more readable. The splatted parameter hashtable helps in this regard too. As a last tip: don't create a variable if you only use it once. Otherwise it just confuses you later on.

Resources