Skip to content

Commit f5d188f

Browse files
authored
Merge pull request #754 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents bca8803 + df83265 commit f5d188f

File tree

3 files changed

+257
-0
lines changed

3 files changed

+257
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
function Get-CIPPAlertInactiveGuestUsers {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
#>
6+
[CmdletBinding()]
7+
param (
8+
[Parameter(Mandatory = $false)]
9+
[Alias('input')]
10+
$InputValue,
11+
[Parameter(Mandatory = $false)]
12+
[switch]$IncludeNeverSignedIn, # Include users who have never signed in (default is to skip them), future use would allow this to be set in an alert configuration
13+
$TenantFilter
14+
)
15+
16+
try {
17+
try {
18+
$inactiveDays = 90
19+
$excludeDisabled = $false
20+
21+
$excludeDisabled = [bool]$InputValue.ExcludeDisabled
22+
if ($null -ne $InputValue.DaysSinceLastLogin -and $InputValue.DaysSinceLastLogin -ne '') {
23+
$parsedDays = 0
24+
if ([int]::TryParse($InputValue.DaysSinceLastLogin.ToString(), [ref]$parsedDays) -and $parsedDays -gt 0) {
25+
$inactiveDays = $parsedDays
26+
}
27+
}
28+
29+
30+
31+
$Lookup = (Get-Date).AddDays(-$inactiveDays).ToUniversalTime()
32+
Write-Host "Checking for guest users inactive since $Lookup (excluding disabled: $excludeDisabled)"
33+
# Build base filter - cannot filter assignedLicenses server-side
34+
$BaseFilter = if ($excludeDisabled) { 'accountEnabled eq true' } else { '' }
35+
36+
$Uri = if ($BaseFilter) {
37+
"https://graph.microsoft.com/beta/users?`$filter=$BaseFilter&`$select=id,UserPrincipalName,signInActivity,mail,userType,accountEnabled,assignedLicenses"
38+
} else {
39+
"https://graph.microsoft.com/beta/users?`$select=id,UserPrincipalName,signInActivity,mail,userType,accountEnabled,assignedLicenses"
40+
}
41+
42+
$GraphRequest = New-GraphGetRequest -uri $Uri-tenantid $TenantFilter | Where-Object { $_.userType -eq 'Guest' }
43+
44+
$AlertData = foreach ($user in $GraphRequest) {
45+
$lastInteractive = $user.signInActivity.lastSignInDateTime
46+
$lastNonInteractive = $user.signInActivity.lastNonInteractiveSignInDateTime
47+
48+
# Find most recent sign-in
49+
$lastSignIn = $null
50+
if ($lastInteractive -and $lastNonInteractive) {
51+
$lastSignIn = if ([DateTime]$lastInteractive -gt [DateTime]$lastNonInteractive) { $lastInteractive } else { $lastNonInteractive }
52+
} elseif ($lastInteractive) {
53+
$lastSignIn = $lastInteractive
54+
} elseif ($lastNonInteractive) {
55+
$lastSignIn = $lastNonInteractive
56+
}
57+
58+
# Check if inactive
59+
$isInactive = (-not $lastSignIn) -or ([DateTime]$lastSignIn -le $Lookup)
60+
# Skip users who have never signed in by default (unless IncludeNeverSignedIn is specified)
61+
if (-not $IncludeNeverSignedIn -and -not $lastSignIn) { continue }
62+
# Only process inactive users
63+
if ($isInactive) {
64+
65+
if (-not $lastSignIn) {
66+
$Message = 'Guest user {0} has never signed in.' -f $user.UserPrincipalName
67+
} else {
68+
$daysSinceSignIn = [Math]::Round(((Get-Date) - [DateTime]$lastSignIn).TotalDays)
69+
$Message = 'Guest user {0} has been inactive for {1} days. Last sign-in: {2}' -f $user.UserPrincipalName, $daysSinceSignIn, $lastSignIn
70+
}
71+
72+
73+
[PSCustomObject]@{
74+
UserPrincipalName = $user.UserPrincipalName
75+
Id = $user.id
76+
lastSignIn = $lastSignIn
77+
DaysSinceLastSignIn = if ($daysSinceSignIn) { $daysSinceSignIn } else { 'N/A' }
78+
Message = $Message
79+
Tenant = $TenantFilter
80+
}
81+
}
82+
}
83+
84+
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
85+
} catch {}
86+
} catch {
87+
Write-AlertMessage -tenant $($TenantFilter) -message "Failed to check inactive guest users for $($TenantFilter): $(Get-NormalizedError -message $_.Exception.message)"
88+
}
89+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
function Get-CIPPAlertInactiveUsers {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
#>
6+
[CmdletBinding()]
7+
param (
8+
[Parameter(Mandatory = $false)]
9+
[Alias('input')]
10+
$InputValue,
11+
[Parameter(Mandatory = $false)]
12+
[switch]$IncludeNeverSignedIn, # Include users who have never signed in (default is to skip them), future use would allow this to be set in an alert configuration
13+
$TenantFilter
14+
)
15+
16+
try {
17+
try {
18+
$inactiveDays = 90
19+
$excludeDisabled = $false
20+
21+
$excludeDisabled = [bool]$InputValue.ExcludeDisabled
22+
if ($null -ne $InputValue.DaysSinceLastLogin -and $InputValue.DaysSinceLastLogin -ne '') {
23+
$parsedDays = 0
24+
if ([int]::TryParse($InputValue.DaysSinceLastLogin.ToString(), [ref]$parsedDays) -and $parsedDays -gt 0) {
25+
$inactiveDays = $parsedDays
26+
}
27+
}
28+
29+
$Lookup = (Get-Date).AddDays(-$inactiveDays).ToUniversalTime()
30+
Write-Host "Checking for users inactive since $Lookup (excluding disabled: $excludeDisabled)"
31+
# Build base filter - cannot filter accountEnabled server-side
32+
$BaseFilter = if ($excludeDisabled) { 'accountEnabled eq true' } else { '' }
33+
34+
$Uri = if ($BaseFilter) {
35+
"https://graph.microsoft.com/beta/users?`$filter=$BaseFilter&`$select=id,UserPrincipalName,signInActivity,mail,userType,accountEnabled,assignedLicenses"
36+
} else {
37+
"https://graph.microsoft.com/beta/users?`$select=id,UserPrincipalName,signInActivity,mail,userType,accountEnabled,assignedLicenses"
38+
}
39+
40+
$GraphRequest = New-GraphGetRequest -uri $Uri -tenantid $TenantFilter | Where-Object { $_.userType -eq 'Member' }
41+
42+
$AlertData = foreach ($user in $GraphRequest) {
43+
$lastInteractive = $user.signInActivity.lastSignInDateTime
44+
$lastNonInteractive = $user.signInActivity.lastNonInteractiveSignInDateTime
45+
46+
# Find most recent sign-in
47+
$lastSignIn = $null
48+
if ($lastInteractive -and $lastNonInteractive) {
49+
$lastSignIn = if ([DateTime]$lastInteractive -gt [DateTime]$lastNonInteractive) { $lastInteractive } else { $lastNonInteractive }
50+
} elseif ($lastInteractive) {
51+
$lastSignIn = $lastInteractive
52+
} elseif ($lastNonInteractive) {
53+
$lastSignIn = $lastNonInteractive
54+
}
55+
56+
# Check if inactive
57+
$isInactive = (-not $lastSignIn) -or ([DateTime]$lastSignIn -le $Lookup)
58+
# Skip users who have never signed in by default (unless IncludeNeverSignedIn is specified)
59+
if (-not $IncludeNeverSignedIn -and -not $lastSignIn) { continue }
60+
# Only process inactive users
61+
if ($isInactive) {
62+
if (-not $lastSignIn) {
63+
$Message = 'User {0} has never signed in.' -f $user.UserPrincipalName
64+
} else {
65+
$daysSinceSignIn = [Math]::Round(((Get-Date) - [DateTime]$lastSignIn).TotalDays)
66+
$Message = 'User {0} has been inactive for {1} days. Last sign-in: {2}' -f $user.UserPrincipalName, $daysSinceSignIn, $lastSignIn
67+
}
68+
69+
[PSCustomObject]@{
70+
UserPrincipalName = $user.UserPrincipalName
71+
Id = $user.id
72+
lastSignIn = $lastSignIn
73+
DaysSinceLastSignIn = if ($daysSinceSignIn) { $daysSinceSignIn } else { 'N/A' }
74+
Message = $Message
75+
Tenant = $TenantFilter
76+
}
77+
}
78+
}
79+
80+
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
81+
} catch {}
82+
} catch {
83+
Write-AlertMessage -tenant $($TenantFilter) -message "Failed to check inactive users with licenses for $($TenantFilter): $(Get-NormalizedError -message $_.Exception.message)"
84+
}
85+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
function Get-CIPPAlertStaleEntraDevices {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
#>
6+
[CmdletBinding()]
7+
param (
8+
[Parameter(Mandatory = $false)]
9+
[Alias('input')]
10+
$InputValue,
11+
$TenantFilter
12+
)
13+
14+
try {
15+
try {
16+
$inactiveDays = 90
17+
18+
$excludeDisabled = [bool]$InputValue.ExcludeDisabled
19+
if ($null -ne $InputValue.DaysSinceLastActivity -and $InputValue.DaysSinceLastActivity -ne '') {
20+
$parsedDays = 0
21+
if ([int]::TryParse($InputValue.DaysSinceLastActivity.ToString(), [ref]$parsedDays) -and $parsedDays -gt 0) {
22+
$inactiveDays = $parsedDays
23+
}
24+
}
25+
26+
$Lookup = (Get-Date).AddDays(-$inactiveDays).ToUniversalTime()
27+
Write-Host "Checking for inactive Entra devices since $Lookup (excluding disabled: $excludeDisabled)"
28+
# Build base filter - cannot filter accountEnabled server-side
29+
$BaseFilter = if ($excludeDisabled) { 'accountEnabled eq true' } else { '' }
30+
31+
$Uri = if ($BaseFilter) {
32+
"https://graph.microsoft.com/beta/devices?`$filter=$BaseFilter"
33+
} else {
34+
'https://graph.microsoft.com/beta/devices'
35+
}
36+
37+
$GraphRequest = New-GraphGetRequest -uri $Uri -tenantid $TenantFilter
38+
39+
$AlertData = foreach ($device in $GraphRequest) {
40+
41+
$lastActivity = $device.approximateLastSignInDateTime
42+
43+
$isInactive = (-not $lastActivity) -or ([DateTime]$lastActivity -le $Lookup)
44+
# Only process stale Entra devices
45+
if ($isInactive) {
46+
47+
if (-not $lastActivity) {
48+
49+
$Message = 'Device {0} has never been active' -f $device.displayName
50+
} else {
51+
$daysSinceLastActivity = [Math]::Round(((Get-Date) - [DateTime]$lastActivity).TotalDays)
52+
$Message = 'Device {0} has been inactive for {1} days. Last activity: {2}' -f $device.displayName, $daysSinceLastActivity, $lastActivity
53+
}
54+
55+
if ($device.TrustType -eq 'Workplace') { $TrustType = 'Entra registered' }
56+
elseif ($device.TrustType -eq 'AzureAd') { $TrustType = 'Entra joined' }
57+
elseif ($device.TrustType -eq 'ServerAd') { $TrustType = 'Entra hybrid joined' }
58+
59+
[PSCustomObject]@{
60+
DeviceName = if ($device.displayName) { $device.displayName } else { 'N/A' }
61+
Id = if ($device.id) { $device.id } else { 'N/A' }
62+
deviceOwnership = if ($device.deviceOwnership) { $device.deviceOwnership } else { 'N/A' }
63+
operatingSystem = if ($device.operatingSystem) { $device.operatingSystem } else { 'N/A' }
64+
enrollmentType = if ($device.enrollmentType) { $device.enrollmentType } else { 'N/A' }
65+
Enabled = if ($device.accountEnabled) { $device.accountEnabled } else { 'N/A' }
66+
Managed = if ($device.isManaged) { $device.isManaged } else { 'N/A' }
67+
Complaint = if ($device.isCompliant) { $device.isCompliant } else { 'N/A' }
68+
JoinType = $TrustType
69+
lastActivity = if ($lastActivity) { $lastActivity } else { 'N/A' }
70+
DaysSinceLastActivity = if ($daysSinceLastActivity) { $daysSinceLastActivity } else { 'N/A' }
71+
RegisteredDateTime = if ($device.createdDateTime) { $device.createdDateTime } else { 'N/A' }
72+
Message = $Message
73+
Tenant = $TenantFilter
74+
}
75+
}
76+
}
77+
78+
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
79+
} catch {}
80+
} catch {
81+
Write-AlertMessage -tenant $($TenantFilter) -message "Failed to check inactive guest users for $($TenantFilter): $(Get-NormalizedError -message $_.Exception.message)"
82+
}
83+
}

0 commit comments

Comments
 (0)