-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathGet-EntraInactiveSignInUser.ps1
More file actions
111 lines (98 loc) · 5.54 KB
/
Copy pathGet-EntraInactiveSignInUser.ps1
File metadata and controls
111 lines (98 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# ------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
# ------------------------------------------------------------------------------
function Get-EntraInactiveSignInUser {
[CmdletBinding()]
[OutputType([string])]
param (
# User Last Sign In Activity is before Days ago
[Parameter(ValueFromPipeline = $true, Position = 1)]
[Alias("BeforeDaysAgo")]
[ValidateRange(0, [int]::MaxValue)]
[int] $LastSignInBeforeDaysAgo = 30,
# Return results for All, Member, or Guest userTypes
[ValidateSet("All", "Member", "Guest")]
[string]
$UserType = "All"
)
begin {
# Ensure connection to Microsoft Entra
if (-not (Get-EntraContext)) {
$errorMessage = "Not connected to Microsoft Graph. Use 'Connect-Entra -Scopes AuditLog.Read.All, User.Read.All' to authenticate."
Write-Error -Message $errorMessage -ErrorAction Stop
return
}
}
process {
$customHeaders = New-EntraCustomHeaders -Command $MyInvocation.MyCommand
$queryDate = (Get-Date).AddDays(-$LastSignInBeforeDaysAgo).ToString("yyyy-MM-ddTHH:mm:ssZ")
$inactiveFilter = "(signInActivity/lastSignInDateTime le $queryDate)"
$uri = "/v1.0/users?`$filter=$inactiveFilter&`$select=signInActivity,UserPrincipalName,Id,DisplayName,mail,userType,createdDateTime,accountEnabled"
Write-Debug ("Retrieving Users with Filter {0}" -f $inactiveFilter)
$queryUsers = (Invoke-GraphRequest -Method GET -Uri $uri -Headers $customHeaders).value
switch ($UserType) {
"Member" { $users = $queryUsers | Where-Object { $_.userType -eq 'Member' } }
"Guest" { $users = $queryUsers | Where-Object { $_.userType -eq 'Guest' } }
"All" { $users = $queryUsers }
}
$users.Count | Write-Debug
foreach ($userObject in $users) {
# Some objects only have the id and signInActivity properties,
# so we need to check for the existence of UserPrincipalName and ignore them in the response
# {
# "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(id,signInActivity)/$entity",
# "id": "740d59d4-057f-4a6d-838b-a30bf3e31ec4",
# "signInActivity": {
# "lastSignInDateTime": "2024-08-22T04:13:19Z",
# "lastSignInRequestId": "bcbac647-1e81-45cb-9e45-c670173e1700",
# "lastNonInteractiveSignInDateTime": null,
# "lastNonInteractiveSignInRequestId": null,
# "lastSuccessfulSignInDateTime": "2024-08-22T04:13:19Z",
# "lastSuccessfulSignInRequestId": "bcbac647-1e81-45cb-9e45-c670173e1700"
# }
# }
# If you run GET https://graph.microsoft.com/v1.0/users/740d59d4-057f-4a6d-838b-a30bf3e31ec4
# you will get ResourceNotFound error.
# If you run GET https://graph.microsoft.com/v1.0/users/740d59d4-057f-4a6d-838b-a30bf3e31ec4?$select=id,signInActivity
# you will get the response above.
if (-not($userObject.ContainsKey("UserPrincipalName"))) {
continue
}
$checkedUser = [ordered] @{
UserID = $userObject.Id
DisplayName = $userObject.DisplayName
UserPrincipalName = $userObject.UserPrincipalName
Mail = $userObject.Mail
UserType = $userObject.UserType
AccountEnabled = $userObject.AccountEnabled
}
If ($null -eq $userObject.signInActivity.LastSignInDateTime) {
$checkedUser["LastSignInDateTime"] = "Unknown"
$checkedUser["LastSigninDaysAgo"] = "Unknown"
$checkedUser["lastNonInteractiveSignInDateTime"] = "Unknown"
}
else {
$checkedUser["LastSignInDateTime"] = $userObject.signInActivity.LastSignInDateTime
$checkedUser["LastSigninDaysAgo"] = (New-TimeSpan -Start $checkedUser.LastSignInDateTime -End (Get-Date)).Days
$checkedUser["lastSignInRequestId"] = $userObject.signInActivity.lastSignInRequestId
If ($null -eq $userObject.signInActivity.lastNonInteractiveSignInDateTime) {
$checkedUser["lastNonInteractiveSignInDateTime"] = "Unknown"
$checkedUser["LastNonInteractiveSigninDaysAgo"] = "Unknown"
} else {
$checkedUser["lastNonInteractiveSignInDateTime"] = $userObject.signInActivity.lastNonInteractiveSignInDateTime
$checkedUser["LastNonInteractiveSigninDaysAgo"] = (New-TimeSpan -Start $checkedUser.lastNonInteractiveSignInDateTime -End (Get-Date)).Days
$checkedUser["lastNonInteractiveSignInRequestId"] = $userObject.signInActivity.lastNonInteractiveSignInRequestId
}
}
If ($null -eq $userObject.CreatedDateTime) {
$checkedUser["CreatedDateTime"] = "Unknown"
$checkedUser["CreatedDaysAgo"] = "Unknown"
}
else {
$checkedUser["CreatedDateTime"] = $userObject.CreatedDateTime
$checkedUser["CreatedDaysAgo"] = (New-TimeSpan -Start $userObject.CreatedDateTime -End (Get-Date)).Days
}
Write-Output ([PSCustomObject]$checkedUser)
}
}
}