EntraTripwire.psm1
|
#Requires -Version 7.2 <# EntraTripwire -- deception-based intrusion detection for Microsoft Entra ID. Loader. Files are dot-sourced private-first, then the public surface. Only the functions in Public/ are exported; everything else stays internal so the module's contract is the documented command set rather than whatever happens to be defined. #> # Version 1.0 on purpose, not Latest. Microsoft Graph omits optional properties instead # of returning null -- signInActivity on an unlicensed tenant, location on a sign-in from # a private range, @odata.nextLink on a final page. StrictMode 2.0+ turns "Graph did not # return this field" into a terminating error, which is exactly the wrong failure for a # detector: it converts missing evidence into a crash instead of a withheld signal. Set-StrictMode -Version 1.0 foreach ($folder in @('Private', 'Public')) { $path = Join-Path -Path $PSScriptRoot -ChildPath $folder if (-not (Test-Path -LiteralPath $path)) { continue } foreach ($file in (Get-ChildItem -Path $path -Filter '*.ps1' -File | Sort-Object Name)) { try { . $file.FullName } catch { throw "Failed to load '$($file.FullName)': $($_.Exception.Message)" } } } # Declared before anything can read it. StrictMode turns a read of an unset variable into # a terminating error, so a module-scope variable that is only ever assigned by # Connect-EntraTripwire would make every command that consults the session crash in a # session that has not connected -- which is exactly the DEMO-mode path this module # promises works with no tenant. $script:TripwireSession = $null # Remembers which policy object has already passed Assert-TripwirePolicy, so scoring a # large batch validates once rather than once per touch. Declared here for the same # StrictMode reason as the session above. $script:TripwireValidatedPolicy = $null # The paid module's state, resolved once per session by Get-TripwireProvider. Declared # here for the same StrictMode reason as the two above: Test-TripwireProFeature reads it # before anything has had a chance to assign it. $script:TripwireProvider = $null # Set by Connect-EntraTripwire when a named tenant profile is in use, so each tenant's # decoy inventory and baseline stay apart. Null means the shared root, which is where a # single-tenant installation keeps its files and where they stay. $script:TripwireStateRootOverride = $null $publicPath = Join-Path -Path $PSScriptRoot -ChildPath 'Public' $publicFunctions = @( Get-ChildItem -Path $publicPath -Filter '*.ps1' -File -ErrorAction SilentlyContinue | ForEach-Object { $_.BaseName } ) Export-ModuleMember -Function $publicFunctions |