Skip to content

Commit 46d7096

Browse files
committed
Added: enumeration of the effective Entra ID tenant license
Change module import to be independent from the current directory.
1 parent 8a4be12 commit 46d7096

File tree

3 files changed

+113
-29
lines changed

3 files changed

+113
-29
lines changed

modules/export_Summary.psm1

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ return @"
9494
$headerHTML = [pscustomobject]@{
9595
"Tenant Name" = $($GlobalAuditSummary.Tenant.Name)
9696
"Tenant ID" = $($GlobalAuditSummary.Tenant.ID)
97+
"Tenant License" = $($GlobalAuditSummary.TenantLicense.Name)
9798
"Subscriptions" = $SubscriptionCount
9899
"Start Time" = $($GlobalAuditSummary.Time.Start)
99100
"End Time" = $($GlobalAuditSummary.Time.End)
@@ -704,14 +705,15 @@ $CustomCss = @"
704705

705706
$OutputCLI = @"
706707
Execution Information:
707-
- Tenant Name: $($GlobalAuditSummary.Tenant.Name)
708-
- Tenant ID: $($GlobalAuditSummary.Tenant.ID)
709-
- Subscriptions: $SubscriptionCount
710-
- Start: $($GlobalAuditSummary.Time.Start)
711-
- End: $($GlobalAuditSummary.Time.End)
712-
- EntraFalcon: $($GlobalAuditSummary.EntraFalcon.Version)
713-
- PowerShell: V$($PSVersionTable.PSVersion.ToString())
714-
- UserAgent: $($GlobalAuditSummary.UserAgent.Name)
708+
- Tenant Name: $($GlobalAuditSummary.Tenant.Name)
709+
- Tenant ID: $($GlobalAuditSummary.Tenant.ID)
710+
- Tenant License: $($GlobalAuditSummary.TenantLicense.Name)
711+
- Subscriptions: $SubscriptionCount
712+
- Start: $($GlobalAuditSummary.Time.Start)
713+
- End: $($GlobalAuditSummary.Time.End)
714+
- EntraFalcon: $($GlobalAuditSummary.EntraFalcon.Version)
715+
- PowerShell: V$($PSVersionTable.PSVersion.ToString())
716+
- UserAgent: $($GlobalAuditSummary.UserAgent.Name)
715717
716718
Enhanced Checks:
717719
- Enumerate Azure IAM: $GLOBALAzurePsChecks

modules/shared_Functions.psm1

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#>
55

66
############################## Static variables ########################
7-
import-module ./modules/EntraTokenAid.psm1 -force
87

98
$global:GLOBALMainTableDetailsHEAD = @'
109
<div id="mainTableContainer">
@@ -3772,8 +3771,9 @@ function start-InitTasks {
37723771

37733772
$Global:GlobalAuditSummary = @{
37743773
Time = @{ Start = Get-Date -Format "yyyyMMdd HH:mm"; End = ""}
3775-
Tenant = @{ Name = "" ; Id = "" }
3774+
Tenant = @{ Name = ""; Id = "" }
37763775
EntraFalcon = @{ Version = "$EntraFalconVersion"; Source = "https://github.com/CompassSecurity/EntraFalcon" }
3776+
TenantLicense = @{ Name = ""; Level = 0}
37773777
Subscriptions = @{ Count = 0 }
37783778
UserAgent = @{ Name = $UserAgent}
37793779
Users = @{ Count = 0; Guests = 0; Inactive = 0; Enabled=0; OnPrem=0; MfaCapable=0; SignInActivity = @{ '0-1 month' = 0; '1-2 months' = 0; '2-3 months' = 0; '4-5 months' = 0; '5-6 months' = 0; '6+ months' = 0; 'Never' = 0 }}
@@ -3790,6 +3790,81 @@ function start-InitTasks {
37903790
}
37913791
}
37923792

3793+
3794+
#Function to get the applied Entra teant license
3795+
function Get-EffectiveEntraLicense {
3796+
[CmdletBinding()]
3797+
3798+
$planPriority = @(
3799+
@{ Plan = 'AAD_PREMIUM_P2'; Name = 'Microsoft Entra ID P2'; Int = 4 }
3800+
@{ Plan = 'AAD_PREMIUM'; Name = 'Microsoft Entra ID P1'; Int = 3 }
3801+
@{ Plan = 'AAD_BASIC'; Name = 'Microsoft Entra ID Basic'; Int = 2 }
3802+
@{ Plan = 'AAD_FREE'; Name = 'Microsoft Entra ID Free'; Int = 1 }
3803+
)
3804+
3805+
$QueryParameters = @{
3806+
'$select' = "capabilityStatus,servicePlans"
3807+
}
3808+
try {
3809+
$response = Send-GraphRequest -AccessToken $GLOBALMsGraphAccessToken.access_token -Method GET -Uri '/subscribedSkus' -QueryParameters $QueryParameters -BetaAPI -UserAgent $($GlobalAuditSummary.UserAgent.Name) -ErrorAction Stop
3810+
} catch {
3811+
Write-Log -Level Debug -Message "Can't get Entra Tenant license. Request to /subscribedSkus failed"
3812+
return [pscustomobject]@{
3813+
EntraIDLicencesString = 'Unknown'
3814+
EntraIDLicencesInt = 0
3815+
}
3816+
}
3817+
$skus =
3818+
if ($null -eq $response) { @() }
3819+
elseif ($response -is [System.Collections.IEnumerable] -and -not ($response -is [string])) { @($response) }
3820+
elseif ($response.PSObject.Properties.Name -contains 'value') { @($response.value) }
3821+
else { @($response) }
3822+
3823+
# Entra Free does not have any SKUs
3824+
if ($skus.Count -eq 0) {
3825+
return [pscustomobject]@{
3826+
EntraIDLicencesString = 'Microsoft Entra ID Free'
3827+
EntraIDLicencesInt = 1
3828+
}
3829+
}
3830+
3831+
$observedPlans = New-Object System.Collections.Generic.HashSet[string]
3832+
3833+
foreach ($sku in $skus) {
3834+
if ($null -eq $sku) { continue }
3835+
3836+
$capabilityStatus = $sku.capabilityStatus
3837+
if ($capabilityStatus -ne 'Enabled' -and $capabilityStatus -ne 'Warning') { continue }
3838+
3839+
foreach ($plan in @($sku.servicePlans)) {
3840+
if ($null -eq $plan) { continue }
3841+
3842+
if ($plan.provisioningStatus -ne 'Success') { continue }
3843+
3844+
$servicePlanName = [string]$plan.servicePlanName
3845+
[void]$observedPlans.Add($servicePlanName)
3846+
}
3847+
}
3848+
3849+
foreach ($item in $planPriority) {
3850+
if ($observedPlans.Contains($item.Plan)) {
3851+
Write-Log -Level Verbose -Message "Entra Tenant license: $($item.Name)"
3852+
return [pscustomobject]@{
3853+
EntraIDLicencesString = $item.Name
3854+
EntraIDLicencesInt = $item.Int
3855+
}
3856+
}
3857+
}
3858+
3859+
Write-Log -Level Verbose -Message "Entra Tenant license: Unknown"
3860+
return [pscustomobject]@{
3861+
EntraIDLicencesString = 'Unknown'
3862+
EntraIDLicencesInt = 0
3863+
}
3864+
}
3865+
3866+
3867+
37933868
# Function to help built the TXT report (avoiding using slow stuff like format-table)
37943869
function Format-ReportSection {
37953870
param (
@@ -4328,4 +4403,4 @@ function Show-EntraFalconBanner {
43284403
Write-Host ""
43294404
}
43304405

4331-
Export-ModuleMember -Function Show-EntraFalconBanner,AuthenticationMSGraph,Get-Devices,Get-UsersBasic,start-CleanUp,Format-ReportSection,Get-OrgInfo,Get-LogLevel, Write-Log,Invoke-MsGraphRefreshPIM,Write-LogVerbose,Invoke-AzureRoleProcessing,Get-RegisterAuthMethodsUsers,Invoke-EntraRoleProcessing,Get-EntraPIMRoleAssignments,AuthCheckMSGraph,RefreshAuthenticationMsGraph,Get-PimforGroupsAssignments,Invoke-CheckTokenExpiration,Invoke-MsGraphAuthPIM,EnsureAuthMsGraph,Get-AzureRoleDetails,Get-AdministrativeUnitsWithMembers,Get-ConditionalAccessPolicies,Get-EntraRoleAssignments,Get-APIPermissionCategory,Get-ObjectInfo,EnsureAuthAzurePsNative,checkSubscriptionNative,Get-AllAzureIAMAssignmentsNative,Get-PIMForGroupsAssignmentsDetails,Show-EnumerationSummary,start-InitTasks
4406+
Export-ModuleMember -Function Show-EntraFalconBanner,AuthenticationMSGraph,Get-EffectiveEntraLicense,Get-Devices,Get-UsersBasic,start-CleanUp,Format-ReportSection,Get-OrgInfo,Get-LogLevel, Write-Log,Invoke-MsGraphRefreshPIM,Write-LogVerbose,Invoke-AzureRoleProcessing,Get-RegisterAuthMethodsUsers,Invoke-EntraRoleProcessing,Get-EntraPIMRoleAssignments,AuthCheckMSGraph,RefreshAuthenticationMsGraph,Get-PimforGroupsAssignments,Invoke-CheckTokenExpiration,Invoke-MsGraphAuthPIM,EnsureAuthMsGraph,Get-AzureRoleDetails,Get-AdministrativeUnitsWithMembers,Get-ConditionalAccessPolicies,Get-EntraRoleAssignments,Get-APIPermissionCategory,Get-ObjectInfo,EnsureAuthAzurePsNative,checkSubscriptionNative,Get-AllAzureIAMAssignmentsNative,Get-PIMForGroupsAssignmentsDetails,Show-EnumerationSummary,start-InitTasks

run_EntraFalcon.ps1

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@
5959
Controls runtime status output.
6060
- `Off` (default): No additional status output
6161
- `Verbose`: High-level status messages
62-
- `Debug`: Includes Verbose plus additional details usful for debugging
62+
- `Debug`: Includes Verbose plus additional details useful for debugging
6363
- `Trace`: Includes Debug plus very detailed output (may be noisy)
6464
6565
.PARAMETER QAMode
66-
Dumps the AllGroups and AllUsers objects as JSON for QA tests.
66+
Dumps the AllGroups and AllUsers objects as JSON for internal QA tests.
6767
6868
.NOTES
6969
Author: Christian Feuchter, Compass Security Switzerland AG, https://www.compass-security.com/
@@ -129,14 +129,30 @@ if ($BroCi -and $AuthMethod -eq "DeviceCode") {
129129
}
130130

131131
#Constants
132-
$EntraFalconVersion = "V20260112"
132+
$EntraFalconVersion = "V20260115"
133+
134+
# Import shared functions
135+
$ScriptRoot = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $MyInvocation.MyCommand.Path }
136+
Import-Module (Join-Path $ScriptRoot 'modules\EntraTokenAid.psm1') -Force
137+
Import-Module (Join-Path $ScriptRoot 'modules\shared_Functions.psm1') -Force
138+
Import-Module (Join-Path $ScriptRoot 'modules\check_Groups.psm1') -Force
139+
Import-Module (Join-Path $ScriptRoot 'modules\check_EnterpriseApps.psm1') -Force
140+
Import-Module (Join-Path $ScriptRoot 'modules\check_AppRegistrations.psm1') -Force
141+
Import-Module (Join-Path $ScriptRoot 'modules\check_Users.psm1') -Force
142+
Import-Module (Join-Path $ScriptRoot 'modules\check_ManagedIdentities.psm1') -Force
143+
Import-Module (Join-Path $ScriptRoot 'modules\check_Roles.psm1') -Force
144+
Import-Module (Join-Path $ScriptRoot 'modules\check_CAPs.psm1') -Force
145+
Import-Module (Join-Path $ScriptRoot 'modules\Send-GraphBatchRequest.psm1') -Force
146+
Import-Module (Join-Path $ScriptRoot 'modules\Send-GraphRequest.psm1') -Force
147+
Import-Module (Join-Path $ScriptRoot 'modules\export_Summary.psm1') -Force
148+
Import-Module (Join-Path $ScriptRoot 'modules\check_PIM.psm1') -Force
133149

134150

135151
#Splat AuthMethods
136152
$Global:GLOBALAuthMethods = @{
137153
AuthMethod = $AuthMethod
138-
Verbose = $VerbosePreference
139154
}
155+
140156
if ($BroCi) { $GLOBALAuthMethods.BroCi = $true }
141157
if (-not [string]::IsNullOrWhiteSpace($BroCiToken)) {
142158

@@ -179,20 +195,6 @@ if ($QAMode) {
179195
$optionalParamsUserandGroup['QAMode'] = $QAMode
180196
}
181197

182-
# Import shared functions
183-
import-module ./modules/shared_Functions.psm1 -force
184-
import-module ./modules/check_Groups.psm1 -force
185-
import-module ./modules/check_EnterpriseApps.psm1 -force
186-
import-module ./modules/check_AppRegistrations.psm1 -force
187-
import-module ./modules/check_Users.psm1 -force
188-
import-module ./modules/check_ManagedIdentities.psm1 -force
189-
import-module ./modules/check_Roles.psm1 -force
190-
import-module ./modules/check_CAPs.psm1 -force
191-
import-module ./modules/Send-GraphBatchRequest.psm1 -force
192-
import-module ./modules/Send-GraphRequest.psm1 -force
193-
import-module ./modules/export_Summary.psm1 -force
194-
import-module ./modules/check_PIM.psm1 -force
195-
196198
#Define summary array and show banner
197199
Start-InitTasks -EntraFalconVersion $EntraFalconVersion -UserAgent $UserAgent
198200
Show-EntraFalconBanner -EntraFalconVersion $EntraFalconVersion
@@ -205,6 +207,7 @@ if (-Not(EnsureAuthMsGraph)) {
205207
Return
206208
}
207209

210+
208211
if (-not($SkipPimForGroups)) {
209212
write-host ""
210213
write-host "********************************** PIM for Groups: Pre-Collection Phase **********************************"
@@ -222,6 +225,10 @@ $StartTimestamp = Get-Date -Format "yyyyMMdd_HHmm"
222225
$GlobalAuditSummary.Tenant.Name = $CurrentTenant.DisplayName
223226
$GlobalAuditSummary.Tenant.Id = $CurrentTenant.Id
224227

228+
$licenseResult = Get-EffectiveEntraLicense
229+
$GlobalAuditSummary.TenantLicense.Name = $licenseResult.EntraIDLicencesString
230+
$GlobalAuditSummary.TenantLicense.Level = $licenseResult.EntraIDLicencesInt
231+
225232
#Define output folder if not defined
226233
if ($null -eq $OutputFolder -or "" -eq $OutputFolder) {
227234
$OutputFolder = "Results_$($CurrentTenant.DisplayName)_$($StartTimestamp)"

0 commit comments

Comments
 (0)