├── .gitignore
├── 0.2-Import-microsoft.graph.authentication.ps1
├── 1-Compare-ConditionalAccess-v1-and-Beta.ps1
├── 10-Daniel-DC-Conditional Access Policy Deployment Script copy.ps1
├── 11-Entra Group Cleanup Script copy 6.ps1
├── 12-Conditional Access Report-Only Analysis Script copy 3.ps1
├── 13-Copy-CAPs-For-BYOD-Pilot.ps1
├── 14-Exclude-Include-Admins-Roles-CAPs copy 2.ps1
├── 14-Exclude-Include-Admins-Roles-CAPs copy 3.ps1
├── 2-Exclude-EntraGroup-AllConditionalAccessPolicies copy 9.ps1
├── 2.1-Exclude-Intune-App-AllConditionalAccessPolicies copy 14.ps1
├── 3-Move-ConditionalAccessPoliciesJSONfiles.ps1
├── 4-Delete-allConditionalAccessPolicies-v4-CSV.ps1
├── 4.1-Delete-allConditionalAccessPolicies-v4-API copy 4.ps1
├── 5-recreateConditionalAccesspoliciesusingJSON-v7.ps1
├── 6-RemoveCAOrphanedGroup.ps1
├── 7-RemoveCAOrphanedUser copy 2.ps1
├── 8-RemoveCAOrphanedobjects-dynamic copy.ps1
├── 9-Conditional Access JSON Converter copy 4.ps1
├── Archive
├── 15-Exclude-Include-Gues-Roles-CAPs copy 10.ps1
└── 15-Exclude-Include-Gues-Roles-CAPs copy 8.ps1
├── CABaseline2025
├── AppConfigurationManagedApp
│ ├── ACP001 - iOSiPadOS - Outlook - Default Signature and External Mailtip.json
│ └── ACP002 - Android - Outlook - Default Signature and External Mailtip.json
├── AppProtection
│ ├── APP001 - Unmanaged - BYOD - iOSiPadOS - MAM - Require Min iOS version.json
│ ├── APP002 - Unmanaged - BYOD - Android - MAM - Require Min OS version.json
│ └── MAM for Edge.json
├── AssignmentFilters
│ ├── Filter001 - Exclude Library Computers from Filehold Install.json
│ ├── Filter002 - Unmanaged - BYOD - iOSiPad OS Devices.json
│ └── Filter003 - Unmanaged - BYOD - Android OS Devices.json
├── AuthenticationStrengths
│ ├── MS Auth app - WHFB - TAP.json
│ ├── Multifactor authentication.json
│ ├── Passwordless MFA.json
│ └── Phishing-resistant MFA.json
├── CompliancePolicies
│ └── Default compliance policy for Android.json
├── ConditionalAccess
│ ├── CAD001-O365 Grant macOS access for All users when Modern Auth Clients and Compliant-v1.1.json
│ ├── CAD002-O365 Grant Windows access for All users when Modern Auth Clients and Compliant-v1.1.json
│ ├── CAD003-O365 Grant iOS and Android access for All users when Modern Auth Clients and ApprovedApp or Compliant-v1.2.json
│ ├── CAD004-O365 Grant Require MFA for All users when Browser and Non-Compliant-v1.5.json
│ ├── CAD005-O365 Block access for unsupported device platforms for All users when Modern Auth Clients-v1.2.json
│ ├── CAD006-O365 Session block download on unmanaged device for All users when Browser and Modern App Clients and Non-Compliant-v1.5.json
│ ├── CAD007-O365 Session set Sign-in Frequency for Apps for All users when Modern Auth Clients and Non-Compliant-v1.2.json
│ ├── CAD008-All Session set Sign-in Frequency for All users when Browser and Non-Compliant-v1.1.json
│ ├── CAD009-All Session disable browser persistence for All users when Browser and Non-Compliant-v1.2.json
│ ├── CAD010-RJD Require MFA for device join or registration when Browser and Modern Auth Clients-v1.2.json
│ ├── CAD011-O365 Grant Linux access for All users when Modern Auth Clients and Compliant-v1.0.json
│ ├── CAD012-ALL Grant access for Admin users when Browser and Modern Auth Clients and Compliant- Remember to Exclude Trusted locationsv1.2.json
│ ├── CAD014-O365 Require App Protection Policy for Edge on Windows for All users when Browser and Non-Compliant-v1.0.json
│ ├── CAD015-All Grant access for All users when Browser and Modern Auth Clients and Compliant on Windows and macOS- v1.0 .json
│ ├── CAD016-EXO_SPO Require token protection when Modern Auth Clients on Windows - v1.1.json
│ ├── CAL002-RSI Require MFA registration from trusted locations only for All users when Browser and Modern Auth Clients-v1.5.json
│ ├── CAL004-All Block access for Admins from non-trusted locations when Browser and Modern Auth Clients-v1.1.json
│ ├── CAL011-Allow access from Trusted Countries Only v1.2.json
│ ├── CAP001-All Block Legacy Authentication for All users when OtherClients-v1.1.json
│ ├── CAP002-O365 Grant Exchange ActiveSync Clients for All users when Approved App-v1.0.json
│ ├── CAU001-All Grant Require MFA for guests when Browser and Modern Auth Clients-v1.0.json
│ ├── CAU002-All Grant Require MFA for All users when Browser and Modern Auth Clients-v1.2.json
│ ├── CAU003-Selected Block unapproved apps for guests when Browser and Modern Auth Clients-v1.0.json
│ ├── CAU005-Selected Session route through MDCA for All users when Browser on Compliant-v1.1.json
│ ├── CAU008-All Grant Require Phishing-resistant MFA for Admins when Browser and Modern Auth Clients-Test if WHFB work from BYOD-v1.4.json
│ ├── CAU009-Management BLOCK Admin Portals for All Users when Browser and Modern Auth Clients-v1.2.json
│ ├── CAU013-All Grant Require phishing resistant MFA for All users when Browser and Modern Auth Clients - Keep for Admins initially-v1.1.json
│ ├── GLOBAL - 1020 - BLOCK - Device Code Auth Flow.json
│ ├── GLOBAL - 1040 - BLOCK - Countries not Allowed - Remember to Update Countries.json
│ ├── GLOBAL - 1060 - BLOCK - Service Accounts (Trusted Locations Excluded) - Remember to add 1 service account per policy.json
│ ├── GLOBAL - 1080 - BLOCK - Guest Access to Sensitive Apps.json
│ ├── GLOBAL - 1085 - BLOCK - User Access to Sensitive Apps - v1.2.json
│ ├── GLOBAL - 1090 - BLOCK - High-Med-Risk Sign-Ins - Entra ID P2 - v1.3.json
│ ├── GLOBAL - 1100 - BLOCK - High-Med-Risk Users - Entra ID P2 - v1.3.json
│ ├── GLOBAL - 2010 - GRANT - Low-Risk Sign-ins - Entra ID P2 - v1.3.json
│ ├── GLOBAL - 2020 - GRANT - Low-Risk Users - Entra ID P2 - v1.3.json
│ ├── GLOBAL - 2040 - GRANT - Terms of Use (All users) - Remember to update TOU v1.2.json
│ ├── GLOBAL - 2050 - GRANT - MFA for All Users - need to exclude all Admins - v1.2.json
│ ├── GLOBAL - 2060 - GRANT - Mobile Apps and Desktop Clients - Only for fully Blocking BYOD.json
│ ├── GLOBAL - 2070 - GRANT - Mobile Device Access Requirements - v1.2.json
│ ├── GLOBAL - 3010 - SESSION - ADMINS - Persistence.json
│ ├── GLOBAL - 3020 - SESSION - BYOD Persistence.json
│ ├── GLOBAL - 3030 - SESSION - Register Security Info Requirements - v1.2.json
│ └── OVERRIDE - 0001 - GRANT - Example.json
├── Groups
│ ├── AAD_UA_CAD001_Exclude.json
│ ├── AAD_UA_CAD002_Exclude.json
│ ├── AAD_UA_CAD003_Exclude.json
│ ├── AAD_UA_CAD004_Exclude.json
│ ├── AAD_UA_CAD005_Exclude.json
│ ├── AAD_UA_CAD006_Exclude.json
│ ├── AAD_UA_CAD007_Exclude.json
│ ├── AAD_UA_CAD008_Exclude.json
│ ├── AAD_UA_CAD009_Exclude.json
│ ├── AAD_UA_CAD010_Exclude.json
│ ├── AAD_UA_CAD012_Exclude.json
│ ├── AAD_UA_CAD014_Exclude.json
│ ├── AAD_UA_CAD015_Exclude.json
│ ├── AAD_UA_CAD015_Include.json
│ ├── AAD_UA_CAD016_Exclude.json
│ ├── AAD_UA_CAD016_Include.json
│ ├── AAD_UA_CAL002_Exclude.json
│ ├── AAD_UA_CAL004_Exclude.json
│ ├── AAD_UA_CAP001_Exclude.json
│ ├── AAD_UA_CAP002_Exclude.json
│ ├── AAD_UA_CAU001_Exclude.json
│ ├── AAD_UA_CAU002_Exclude.json
│ ├── AAD_UA_CAU003_Exclude.json
│ ├── AAD_UA_CAU005_Exclude.json
│ ├── AAD_UA_CAU008_Exclude.json
│ ├── AAD_UA_CAU009_Exclude.json
│ ├── AAD_UA_CAU013_Include.json
│ ├── AAD_UA_ConAcc-Breakglass.json
│ ├── AAD_UA_Update-Ring-02.json
│ ├── Conditional Access Service Accounts.json
│ ├── Excluded from Country Block List.json
│ ├── Excluded from Device Code Auth Flow Block.json
│ └── Information Technology and Systems.json
├── MigrationTable.json
├── NamedLocations
│ ├── All Compliant Network locations.json
│ ├── Allowed Countries.json
│ ├── CCI - FortiGate VPN SSL.json
│ ├── CCI JumpBox.json
│ ├── Canada and USA.json
│ ├── Fake Restrictive Location.json
│ ├── HQ - Canada.json
│ ├── High-Risk Countries.json
│ └── Service Accounts Trusted IPs.json
└── TermsOfUse
│ ├── MSFT Terms of Use.json
│ ├── Terms of Use.json
│ ├── file-sample_150kB.pdf
│ └── termsofuse.pdf
├── Compliance
├── Archive
│ ├── Connect-MGGraphwithCert-Template-v1.1.ps1
│ ├── Find-MgGraphPermissions.ps1
│ ├── Get-ComplianceReportBasedonSignInLogs.ps1
│ ├── Get-LatestWinGetversion.Archive.ps1
│ ├── GraphCalls.ps1
│ ├── Invoke-MgGraphRequestwithAccessToken copy 2.ps1
│ ├── Invoke-MgGraphRequestwithAccessToken copy 3.ps1
│ ├── Invoke-MgGraphRequestwithAccessToken copy.ps1
│ ├── Invoke-MgGraphRequestwithAccessToken.ps1
│ ├── Logging.ps1
│ ├── Ondrej-Sebela-doitpshway copy 2.ps1
│ ├── Ondrej-Sebela-doitpshway copy.ps1
│ ├── Ondrej-Sebela-doitpshway.ps1
│ ├── get-allauditlogs copy 2.ps1
│ ├── get-allauditlogs copy 4.ps1
│ ├── get-allauditlogs copy 5-working-code-no-parallel.ps1
│ ├── get-allauditlogs copy 6-allmodulesinparallelblock.ps1
│ ├── get-allauditlogs copy 6-parallel.ps1
│ ├── get-allauditlogs copy 7-parallel-removed-boiler-plate.ps1
│ ├── get-allauditlogs copy.ps1
│ ├── get-allauditlogs.ps1
│ ├── helloworld.psm1
│ ├── test-LINQ-v2.ps1
│ ├── test-LINQ-v3.ps1
│ ├── test-LINQ.ps1
│ ├── test-Parallel-v2.ps1
│ ├── test-Parallel.ps1
│ └── tests
│ │ ├── Async.Logging.PSF.test.ps1
│ │ ├── GetLatestVersion.Choco.test.ps1
│ │ ├── GetLatestVersion.Winget.test.ps1
│ │ ├── validatesoftware.test copy.ps1
│ │ └── validatesoftware.test.ps1
├── Benchmarking
│ ├── 1-Get-Content and ConvertFrom-Json.ps1
│ ├── 2-System.IO.StreamReader and ConvertFrom-Json.ps1
│ ├── 3-System.Text.Json.JsonDocument.ps1
│ ├── 4-System.Text.Json.JsonDocument.ps1
│ ├── 5-compare-json-file-read.ps1
│ ├── Test-DataStructures.ps1
│ ├── test-newtonsoft-linq.ps1
│ └── test-vscode-debugging.ps1
├── CustomExports
│ ├── BYODCompliant.csv
│ ├── BYOD_AND_CORP_ER_Incompliant.csv
│ ├── CorporateCompliant.csv
│ ├── CorporateIncompliant.csv
│ ├── MasterReport.csv
│ ├── Report_Compliant.csv
│ ├── Report_Error.csv
│ ├── Report_External.csv
│ ├── Report_NonCompliant.csv
│ ├── Report_NonPremiumLicenses.csv
│ ├── Report_PIIRemoved.csv
│ ├── Report_PremiumLicenses.csv
│ ├── Report_Present.csv
│ └── StructuredReport.csv
├── Get-ComplianceReportBasedonSignInLogs-ALPHA-v1.ps1
├── Modules.json
├── Readme.md
├── combine-allmodules.ps1
├── config.json
└── modulesexclusion.json
├── ConditionalAccess
├── Archive
│ ├── Delete-allConditionalAccessPolicies-v2.ps1
│ ├── Delete-allConditionalAccessPolicies-v3.ps1
│ ├── Delete-allConditionalAccessPolicies.ps1
│ ├── Rename-ConditionalAccessPolicies-All-v2.ps1
│ ├── Rename-ConditionalAccessPolicies-All-v3.ps1
│ ├── Rename-ConditionalAccessPolicies-All-v4.ps1
│ ├── recreateConditionalAccesspoliciesusingJSON-v2.ps1
│ ├── recreateConditionalAccesspoliciesusingJSON-v3.ps1
│ ├── recreateConditionalAccesspoliciesusingJSON-v4.ps1
│ ├── recreateConditionalAccesspoliciesusingJSON-v5.ps1
│ ├── recreateConditionalAccesspoliciesusingJSON-v6.ps1
│ └── recreateConditionalAccesspoliciesusingJSON.ps1
├── Conditional Access Policy Name Generator copy.ps1
├── Conditional Access Policy Name Generator.ps1
├── Delete-allConditionalAccessPolicies-v4.ps1
├── Export-CAPolicy.ps1
├── Rename-ConditionalAccessPolicies-All.ps1
└── Rename-ConditionalAccessPolicies.ps1
├── Module
├── ConditionalAccess.psd1
├── ConditionalAccess.psm1
├── Example
│ └── 15-Exclude-Include-Gues-Roles-CAPs copy 9.ps1
├── Private
│ ├── Get-GuestUserTypes.ps1
│ └── Show-GuestOperationMenu.ps1
├── Public
│ ├── Export-GuestPolicyReport.ps1
│ ├── Get-ConditionalAccessPoliciesDetails.ps1
│ └── Update-ConditionalAccessPolicyGuestTypes.ps1
└── en-US
│ └── about_ConditionalAccess.help.txt
├── Modules.json
├── README.md
├── config.json
├── modulesexclusion.json
└── scopes.json
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | /Reports
3 |
--------------------------------------------------------------------------------
/0.2-Import-microsoft.graph.authentication.ps1:
--------------------------------------------------------------------------------
1 | # Define error handling preferences
2 | $ErrorActionPreference = 'Stop'
3 |
4 |
5 | function Write-ConditionalAccessLog {
6 | param(
7 | [Parameter(Mandatory)]
8 | [string]$Message,
9 |
10 | [ValidateSet('Info', 'Warning', 'Error')]
11 | [string]$Level = 'Info'
12 | )
13 |
14 | $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
15 | $logMessage = "[$timestamp] [$Level] $Message"
16 |
17 | switch ($Level) {
18 | 'Info' { Write-Host $logMessage -ForegroundColor Green }
19 | 'Warning' { Write-Host $logMessage -ForegroundColor Yellow }
20 | 'Error' { Write-Host $logMessage -ForegroundColor Red }
21 | }
22 | }
23 |
24 |
25 | function Test-AdminAndPSVersion {
26 | Write-ConditionalAccessLog "Checking PowerShell version and administrative privileges..."
27 |
28 | $currentPrincipal = [Security.Principal.WindowsPrincipal]::new(
29 | [Security.Principal.WindowsIdentity]::GetCurrent()
30 | )
31 |
32 | $isAdmin = $currentPrincipal.IsInRole(
33 | [Security.Principal.WindowsBuiltInRole]::Administrator
34 | )
35 | $isPS5 = $PSVersionTable.PSVersion.Major -eq 5
36 |
37 | Write-ConditionalAccessLog "Current PowerShell Version: $($PSVersionTable.PSVersion.ToString())"
38 | Write-ConditionalAccessLog "Running as Administrator: $isAdmin"
39 |
40 | if (-not $isPS5) {
41 | Write-ConditionalAccessLog "PowerShell 5 check failed. Current version: $($PSVersionTable.PSVersion.ToString())" -Level Error
42 | throw [System.InvalidOperationException]::new(
43 | "PowerShell 5 is required. Current version: $($PSVersionTable.PSVersion.ToString())"
44 | )
45 | }
46 |
47 | if (-not $isAdmin) {
48 | Write-ConditionalAccessLog "Administrator privileges check failed" -Level Error
49 | throw [System.UnauthorizedAccessException]::new(
50 | 'Administrator rights are required to run this script.'
51 | )
52 | }
53 |
54 | Write-ConditionalAccessLog "All prerequisite checks passed successfully"
55 | return $true
56 | }
57 |
58 | function Install-RequiredModule {
59 | param(
60 | [Parameter(Mandatory)]
61 | [string]$ModuleName
62 | )
63 |
64 | Write-ConditionalAccessLog "Checking module: $ModuleName"
65 | Test-AdminAndPSVersion | Out-Null
66 |
67 | if (Get-Module -ListAvailable -Name $ModuleName) {
68 | Write-ConditionalAccessLog "Module '$ModuleName' is already installed"
69 | $existingVersion = (Get-Module -ListAvailable -Name $ModuleName | Sort-Object Version -Descending | Select-Object -First 1).Version
70 | Write-ConditionalAccessLog "Current version: $existingVersion"
71 | }
72 | else {
73 | Write-ConditionalAccessLog "Module '$ModuleName' not found. Attempting installation..."
74 | $installParams = @{
75 | Name = $ModuleName
76 | Force = $true
77 | AllowClobber = $true
78 | Scope = 'AllUsers'
79 | ErrorAction = 'Stop'
80 | }
81 |
82 | try {
83 | Install-Module @installParams
84 | $installedVersion = (Get-Module -ListAvailable -Name $ModuleName | Sort-Object Version -Descending | Select-Object -First 1).Version
85 | Write-ConditionalAccessLog "Successfully installed '$ModuleName' version $installedVersion"
86 | }
87 | catch {
88 | Write-ConditionalAccessLog "Failed to install module '$ModuleName': $_" -Level Error
89 | throw [System.Management.Automation.ItemNotFoundException]::new(
90 | "Failed to install module '$ModuleName': $_"
91 | )
92 | }
93 | }
94 | }
95 |
96 | # Required modules
97 | $requiredModules = @(
98 | 'Microsoft.Graph.Users'
99 | 'Microsoft.Graph.Identity.DirectoryManagement'
100 | 'Microsoft.Graph.Authentication'
101 | 'ExchangeOnlineManagement'
102 | 'Microsoft.Graph.Beta.Identity.SignIns'
103 | 'Microsoft.Graph.Groups',
104 | 'Microsoft.Graph.Identity.SignIns',
105 | 'Microsoft.Graph.Beta.Identity.DirectoryManagement'
106 |
107 | )
108 |
109 | # Main execution block
110 | try {
111 | Write-ConditionalAccessLog "=== Starting Module Installation Process ==="
112 | Write-ConditionalAccessLog "Required modules: $($requiredModules -join ', ')"
113 |
114 | foreach ($module in $requiredModules) {
115 | Install-RequiredModule -ModuleName $module
116 | }
117 |
118 | Write-ConditionalAccessLog "Importing all required modules..."
119 | Import-Module -Name $requiredModules -ErrorAction Stop
120 | Write-ConditionalAccessLog "=== Module Installation Process Completed Successfully ==="
121 | }
122 | catch {
123 | Write-ConditionalAccessLog "=== Module Installation Process Failed ===" -Level Error
124 | throw "Module installation failed: $_"
125 | }
126 |
127 |
128 | function Import-RequiredModules {
129 | [CmdletBinding()]
130 | param()
131 |
132 | $logParams = @{
133 | Message = "Importing required Microsoft Graph modules"
134 | Level = "Info"
135 | }
136 | Write-ConditionalAccessLog @logParams
137 |
138 | try {
139 | # Remove existing modules first to avoid assembly conflicts
140 | $modulesToRemove = @(
141 | 'Microsoft.Graph.Users'
142 | 'Microsoft.Graph.Groups'
143 | 'Microsoft.Graph.Authentication'
144 | 'Microsoft.Graph.Beta.Identity.SignIns'
145 | )
146 |
147 | foreach ($module in $modulesToRemove) {
148 | if (Get-Module $module) {
149 | $removeParams = @{
150 | Name = $module
151 | Force = $true
152 | ErrorAction = "SilentlyContinue"
153 | }
154 | Remove-Module @removeParams
155 | }
156 | }
157 |
158 | # Import required modules
159 | $modulesToImport = @(
160 | 'Microsoft.Graph.Users'
161 | 'Microsoft.Graph.Identity.DirectoryManagement'
162 | 'Microsoft.Graph.Authentication'
163 | 'ExchangeOnlineManagement'
164 | 'Microsoft.Graph.Beta.Identity.SignIns'
165 | 'Microsoft.Graph.Groups',
166 | 'Microsoft.Graph.Identity.SignIns',
167 | 'Microsoft.Graph.Beta.Identity.DirectoryManagement'
168 | )
169 |
170 | foreach ($module in $modulesToImport) {
171 | $importParams = @{
172 | Name = $module
173 | Force = $true
174 | ErrorAction = "Stop"
175 | }
176 | Import-Module @importParams
177 |
178 | $logParams = @{
179 | Message = "Successfully imported module: $module"
180 | Level = "Info"
181 | }
182 | Write-ConditionalAccessLog @logParams
183 | }
184 |
185 | return $true
186 | }
187 | catch {
188 | $logParams = @{
189 | Message = "Failed to import required modules: $_"
190 | Level = "Error"
191 | }
192 | Write-ConditionalAccessLog @logParams
193 | throw
194 | }
195 | }
196 |
197 |
198 | Import-RequiredModules
199 |
200 |
201 |
202 |
203 | # Enhanced Connection Functions for Graph and Exchange Online
204 |
205 | function Connect-GraphWithScope {
206 | [CmdletBinding()]
207 | param()
208 |
209 | # Define the scopes in an array
210 | $requiredScopes = @(
211 | "RoleAssignmentSchedule.ReadWrite.Directory",
212 | "Domain.Read.All",
213 | "Domain.ReadWrite.All",
214 | "Directory.Read.All",
215 | "Policy.ReadWrite.ConditionalAccess",
216 | "DeviceManagementApps.ReadWrite.All",
217 | "DeviceManagementConfiguration.ReadWrite.All",
218 | "DeviceManagementManagedDevices.ReadWrite.All",
219 | "openid",
220 | "profile",
221 | "email",
222 | "offline_access",
223 | "Policy.ReadWrite.PermissionGrant",
224 | "RoleManagement.ReadWrite.Directory",
225 | "Policy.ReadWrite.DeviceConfiguration",
226 | "DeviceLocalCredential.Read.All",
227 | "DeviceManagementManagedDevices.PrivilegedOperations.All",
228 | "DeviceManagementServiceConfig.ReadWrite.All",
229 | "Policy.Read.All",
230 | "DeviceManagementRBAC.ReadWrite.All",
231 | "UserAuthenticationMethod.ReadWrite.All",
232 | "User.Read.All",
233 | "Group.ReadWrite.All",
234 | "Directory.ReadWrite.All",
235 | "User.ReadWrite.All",
236 | "Application.Read.All"
237 | )
238 |
239 | Write-ConditionalAccessLog "Checking Microsoft Graph connection..."
240 | $currentContext = Get-MgContext
241 |
242 | if ($null -eq $currentContext) {
243 | Write-ConditionalAccessLog "No existing Graph connection found. Connecting..." -Level Warning
244 | Connect-MgGraph -Scopes $requiredScopes
245 | $newContext = Get-MgContext
246 | Write-ConditionalAccessLog "Connected to Microsoft Graph as: $($newContext.Account)" -Level Info
247 | return
248 | }
249 |
250 | $missingScopes = $requiredScopes | Where-Object { $_ -notin $currentContext.Scopes }
251 |
252 | if ($missingScopes) {
253 | Write-ConditionalAccessLog "Missing required scopes: $($missingScopes -join ', ')" -Level Warning
254 | Write-ConditionalAccessLog "Reconnecting with all required scopes..." -Level Warning
255 | Disconnect-MgGraph
256 | Connect-MgGraph -Scopes $requiredScopes
257 | $newContext = Get-MgContext
258 | Write-ConditionalAccessLog "Reconnected to Microsoft Graph as: $($newContext.Account)" -Level Info
259 | }
260 | else {
261 | Write-ConditionalAccessLog "Already connected to Microsoft Graph with required scopes as: $($currentContext.Account)" -Level Info
262 | }
263 | }
264 |
265 | function Connect-RequiredServices {
266 | [CmdletBinding()]
267 | param()
268 |
269 | Write-ConditionalAccessLog "=== Starting Service Connections ===" -Level Info
270 |
271 | try {
272 | Connect-GraphWithScope
273 | Write-ConditionalAccessLog "=== All Service Connections Completed Successfully ===" -Level Info
274 | }
275 | catch {
276 | Write-ConditionalAccessLog "=== Service Connection Process Failed ===" -Level Error
277 | throw "Failed to connect to required services: $_"
278 | }
279 | }
280 |
281 |
282 |
283 | Connect-RequiredServices
--------------------------------------------------------------------------------
/1-Compare-ConditionalAccess-v1-and-Beta.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph
2 | Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess", "Group.ReadWrite.All", "Policy.Read.All"
3 |
4 | function Get-ConditionalAccessPoliciesViaMgGraph {
5 | param (
6 | [string]$GraphVersion
7 | )
8 |
9 | $uri = "https://graph.microsoft.com/$GraphVersion/identity/conditionalAccess/policies"
10 | $allPolicies = @()
11 |
12 | do {
13 | $response = Invoke-MgGraphRequest -Uri $uri -Method GET -Headers @{"Prefer"="odata.maxpagesize=999"}
14 | $policies = $response.Value
15 | $allPolicies += $policies
16 | $uri = if ($response.'@odata.nextLink') { $response.'@odata.nextLink' } else { $null }
17 | } while ($uri)
18 |
19 | return $allPolicies
20 | }
21 |
22 | # Fetch policies using Beta endpoint
23 | $betaPolicies = Get-ConditionalAccessPoliciesViaMgGraph -GraphVersion "beta"
24 |
25 | # Fetch policies using v1.0 endpoint
26 | $v1Policies = Get-ConditionalAccessPoliciesViaMgGraph -GraphVersion "v1.0"
27 |
28 | # Extract IDs into simple arrays
29 | $betaPolicyIds = $betaPolicies | ForEach-Object { $_.id }
30 | $v1PolicyIds = $v1Policies | ForEach-Object { $_.id }
31 |
32 | # Identify deprecated policies by comparing IDs
33 | $deprecatedPolicyIds = $betaPolicyIds | Where-Object { $_ -notin $v1PolicyIds }
34 |
35 |
36 | # Filter the full policy objects for deprecated policies
37 | $deprecatedPolicies = $betaPolicies | Where-Object { $deprecatedPolicyIds -contains $_.id }
38 |
39 |
40 | # Assuming $deprecatedPolicies contains hashtables with the desired keys
41 |
42 | # Prepare the data for CSV export and Out-GridView by accessing the hashtable properties directly
43 | $exportData = $deprecatedPolicies | ForEach-Object {
44 | [PSCustomObject]@{
45 | id = $_.id
46 | displayName = $_.displayName
47 | createdDateTime = $_.createdDateTime
48 | state = $_.state
49 | }
50 | }
51 |
52 |
53 | # New-Item -Path 'D:\Code\CB\Entra\ICTC\Graph\export\'
54 |
55 |
56 | # Export to CSV
57 | # mkdir C:\Code\CB\Entra\Ambico\Graph\export
58 |
59 | # Define the tenant name variable
60 | $TenantName = "MSFT"
61 |
62 | # Construct the directory path using the tenant name
63 | $DirectoryPath = Join-Path -Path "C:\Code\CB\Entra" -ChildPath "$TenantName\Graph\export"
64 |
65 | # Check if the directory exists, and create it if it does not
66 | if (-not (Test-Path -Path $DirectoryPath)) {
67 | New-Item -Path $DirectoryPath -ItemType Directory -Force
68 | Write-Host "Directory created: $DirectoryPath"
69 | } else {
70 | Write-Host "Directory already exists: $DirectoryPath"
71 | }
72 |
73 |
74 | $exportData | Export-Csv -Path "$DirectoryPath\DeprecatedPolicies.csv" -NoTypeInformation
75 |
76 | # Display in Out-GridView
77 | $exportData | Out-GridView -Title "Deprecated Policies"
78 |
79 | # Output policy details to console in a well-formatted table
80 | Write-Host "Deprecated Policies:"
81 | $exportData | Format-Table -AutoSize
--------------------------------------------------------------------------------
/10-Daniel-DC-Conditional Access Policy Deployment Script copy.ps1:
--------------------------------------------------------------------------------
1 | # Install required modules if not already installed
2 | function Install-RequiredModules {
3 | $modules = @(
4 | 'Microsoft.Graph.Authentication',
5 | 'Microsoft.Graph.Identity.SignIns',
6 | 'Microsoft.Graph.Groups',
7 | 'Microsoft.Graph.Users',
8 | 'Microsoft.Graph.Identity.Governance',
9 | 'Microsoft.Graph.Identity.DirectoryManagement',
10 | 'DCToolbox'
11 | )
12 |
13 | foreach ($module in $modules) {
14 | if (-not (Get-Module -ListAvailable -Name $module)) {
15 | Write-Host "Installing $module..." -ForegroundColor Yellow
16 | Install-Module -Name $module -Force -AllowClobber -Scope CurrentUser
17 | }
18 | }
19 | }
20 |
21 | function Initialize-CADeployment {
22 | # Show warning message
23 | Write-Host @"
24 | IMPORTANT SAFETY NOTICE
25 | ----------------------
26 | You are about to deploy Conditional Access policies. These policies can affect all users'
27 | ability to access your environment. Before proceeding, ensure you have:
28 |
29 | 1. Created a break glass account
30 | 2. Documented the break glass account credentials securely
31 | 3. Backed up any existing policies
32 | 4. Reviewed the policies that will be deployed
33 | 5. Have a plan to test each policy before enabling
34 |
35 | "@ -ForegroundColor Yellow
36 |
37 | $continue = Read-Host "Have you completed all the above steps? (yes/no)"
38 | if ($continue -ne "yes") {
39 | Write-Host "Deployment cancelled for safety. Please complete all preparatory steps first." -ForegroundColor Red
40 | return
41 | }
42 |
43 | # Install required modules
44 | Install-RequiredModules
45 |
46 | # Import required modules
47 | Import-Module Microsoft.Graph.Authentication
48 | Import-Module Microsoft.Graph.Identity.SignIns
49 | Import-Module Microsoft.Graph.Groups
50 | Import-Module Microsoft.Graph.Users
51 | Import-Module Microsoft.Graph.Identity.Governance
52 | Import-Module Microsoft.Graph.Identity.DirectoryManagement
53 | Import-Module DCToolbox
54 |
55 | # Connect to Microsoft Graph with required permissions
56 | $requiredScopes = @(
57 | 'Policy.ReadWrite.ConditionalAccess',
58 | 'Policy.Read.All',
59 | 'Directory.Read.All',
60 | 'Application.Read.All',
61 | 'Agreement.Read.All',
62 | 'GroupMember.Read.All',
63 | 'Agreement.ReadWrite.All'
64 | )
65 |
66 | Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Yellow
67 | Connect-DCMsGraphAsUser -Scopes $requiredScopes
68 |
69 | # Deploy baseline policies
70 | Write-Host "Starting Conditional Access baseline deployment..." -ForegroundColor Green
71 |
72 | # Force Report-Only mode for safety
73 | $deployParams = @{
74 | CreateDocumentation = $true
75 | SkipReportOnlyMode = $false # Always deploy in report-only mode first
76 | }
77 |
78 | try {
79 | # Create break glass account exclusion group if it doesn't exist
80 | Write-Host "Checking break glass account exclusion group..." -ForegroundColor Yellow
81 |
82 | # Deploy the baseline policies
83 | Deploy-DCConditionalAccessBaselinePoC @deployParams
84 |
85 | Write-Host "Deployment completed successfully!" -ForegroundColor Green
86 | Write-Host @"
87 |
88 | NEXT STEPS (DO NOT SKIP THESE):
89 | ------------------------------
90 | 1. Add your break glass accounts to the 'Excluded from Conditional Access' group
91 | 2. Review each policy in the Azure Portal (https://portal.azure.com/#blade/Microsoft_AAD_IAM/ConditionalAccessBlade/Policies)
92 | 3. Test each policy in Report-Only mode and review the Insights
93 | 4. Document any changes needed based on your testing
94 | 5. Create a pilot group for initial testing
95 | 6. Enable policies one at a time, starting with least impactful
96 | 7. Monitor sign-in logs for issues
97 |
98 | SAFE ENABLEMENT PROCESS:
99 | ----------------------
100 | 1. First, test with a pilot group:
101 | Set-DCConditionalAccessPoliciesPilotMode -PrefixFilter 'GLOBAL - ' -PilotGroupName 'Conditional Access Pilot' -EnablePilot
102 |
103 | 2. After successful pilot, enable individual policies:
104 | - Use Azure Portal to enable policies one at a time
105 | - Monitor between each enablement
106 | - Have your break glass account ready
107 |
108 | 3. DO NOT enable all policies at once using PowerShell commands
109 |
110 | Documentation has been generated - please review it thoroughly.
111 |
112 | "@ -ForegroundColor Yellow
113 | }
114 | catch {
115 | Write-Host "Error during deployment: $_" -ForegroundColor Red
116 | Write-Host "Please ensure you have Global Administrator or Security Administrator rights." -ForegroundColor Red
117 | }
118 | }
119 |
120 | # Execute the deployment
121 | Initialize-CADeployment
--------------------------------------------------------------------------------
/13-Copy-CAPs-For-BYOD-Pilot.ps1:
--------------------------------------------------------------------------------
1 | # Function definitions
2 | function Test-PolicyJson {
3 | [CmdletBinding()]
4 | param(
5 | [Parameter(Mandatory)]
6 | [string]$FilePath
7 | )
8 |
9 | try {
10 | $null = Get-Content $FilePath -Raw | ConvertFrom-Json
11 | return @{
12 | IsValid = $true
13 | Error = $null
14 | }
15 | }
16 | catch {
17 | return @{
18 | IsValid = $false
19 | Error = $_.Exception.Message
20 | }
21 | }
22 | }
23 |
24 | function Test-PolicyFiles {
25 | [CmdletBinding()]
26 | param (
27 | [Parameter(Mandatory)]
28 | [string]$SourcePath,
29 |
30 | [Parameter(Mandatory)]
31 | [string[]]$ExpectedPolicies
32 | )
33 |
34 | $results = [System.Collections.ArrayList]::new()
35 |
36 | foreach ($policy in $ExpectedPolicies) {
37 | $policyPath = Join-Path $SourcePath "$policy.json"
38 | $exists = Test-Path $policyPath
39 |
40 | $resultObject = [PSCustomObject]@{
41 | PolicyName = $policy
42 | Exists = $exists
43 | FullPath = $policyPath
44 | IsValidJson = $false
45 | JsonError = $null
46 | }
47 |
48 | if ($exists) {
49 | $jsonTest = Test-PolicyJson -FilePath $policyPath
50 | $resultObject.IsValidJson = $jsonTest.IsValid
51 | $resultObject.JsonError = $jsonTest.Error
52 | }
53 |
54 | $null = $results.Add($resultObject)
55 | }
56 |
57 | return $results
58 | }
59 |
60 | function Copy-PolicyFiles {
61 | [CmdletBinding()]
62 | param (
63 | [Parameter(Mandatory)]
64 | [string]$SourcePath,
65 |
66 | [Parameter(Mandatory)]
67 | [string]$DestinationPath,
68 |
69 | [Parameter(Mandatory)]
70 | [string[]]$Policies
71 | )
72 |
73 | $results = [System.Collections.ArrayList]::new()
74 |
75 | foreach ($policy in $Policies) {
76 | try {
77 | $sourceFile = Join-Path $SourcePath "$policy.json"
78 | Copy-Item -Path $sourceFile -Destination $DestinationPath -Force -ErrorAction Stop
79 |
80 | $resultObject = [PSCustomObject]@{
81 | PolicyName = $policy
82 | Status = 'Success'
83 | ErrorMessage = ''
84 | }
85 | }
86 | catch {
87 | $resultObject = [PSCustomObject]@{
88 | PolicyName = $policy
89 | Status = 'Failed'
90 | ErrorMessage = $_.Exception.Message
91 | }
92 | }
93 |
94 | $null = $results.Add($resultObject)
95 | }
96 |
97 | return $results
98 | }
99 |
100 | function Export-PolicyCopyReport {
101 | param(
102 | [Parameter(Mandatory)]
103 | $Results,
104 |
105 | [Parameter(Mandatory)]
106 | [string]$OutputDir,
107 |
108 | [Parameter()]
109 | [string]$ReportName = "PolicyCopy_Report"
110 | )
111 |
112 | $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
113 | $htmlPath = Join-Path $OutputDir "$($ReportName)_$timestamp.html"
114 | $csvPath = Join-Path $OutputDir "$($ReportName)_$timestamp.csv"
115 |
116 | # Export to CSV
117 | $Results | Export-Csv -Path $csvPath -NoTypeInformation
118 |
119 | $metadata = @{
120 | GeneratedBy = $env:USERNAME
121 | GeneratedOn = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
122 | TotalPolicies = $Results.Count
123 | SuccessCount = ($Results | Where-Object Status -eq "Success").Count
124 | FailureCount = ($Results | Where-Object Status -eq "Failed").Count
125 | }
126 |
127 | New-HTML -Title "Policy Copy Report" -FilePath $htmlPath -ShowHTML {
128 | New-HTMLSection -HeaderText "Copy Operation Summary" {
129 | New-HTMLPanel {
130 | New-HTMLText -Text @"
131 |
Report Details
132 |
133 | - Generated By: $($metadata.GeneratedBy)
134 | - Generated On: $($metadata.GeneratedOn)
135 | - Total Policies: $($metadata.TotalPolicies)
136 | - Successful Copies: $($metadata.SuccessCount)
137 | - Failed Copies: $($metadata.FailureCount)
138 |
139 | "@
140 | }
141 | }
142 |
143 | New-HTMLSection -HeaderText "Policy Copy Results" {
144 | New-HTMLTable -DataTable $Results -ScrollX -Buttons @('copyHtml5', 'excelHtml5', 'csvHtml5') -SearchBuilder {
145 | New-TableCondition -Name 'Status' -ComparisonType string -Operator eq -Value 'Failed' -BackgroundColor Salmon -Color Black
146 | New-TableCondition -Name 'Status' -ComparisonType string -Operator eq -Value 'Success' -BackgroundColor LightGreen -Color Black
147 | }
148 | }
149 | }
150 |
151 | Write-Host "`nReports generated:" -ForegroundColor Green
152 | Write-Host "CSV Report: $csvPath" -ForegroundColor Green
153 | Write-Host "HTML Report: $htmlPath" -ForegroundColor Green
154 |
155 | return @{
156 | CSVPath = $csvPath
157 | HTMLPath = $htmlPath
158 | }
159 | }
160 |
161 | function Copy-ConditionalAccessPolicies {
162 | [CmdletBinding()]
163 | param (
164 | [Parameter(Mandatory)]
165 | [string]$SourcePath,
166 |
167 | [Parameter(Mandatory)]
168 | [string]$BaseDestPath,
169 |
170 | [Parameter(Mandatory)]
171 | [string[]]$ExpectedPolicies
172 | )
173 |
174 | # Create timestamp for destination folder
175 | $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
176 | $destPath = Join-Path $BaseDestPath "BYOD-Pilot-CAPs-$timestamp"
177 |
178 | # Test policy files
179 | $fileCheck = Test-PolicyFiles -SourcePath $SourcePath -ExpectedPolicies $ExpectedPolicies
180 | $missingFiles = $fileCheck | Where-Object { -not $_.Exists }
181 | $invalidJsonFiles = $fileCheck | Where-Object { $_.Exists -and -not $_.IsValidJson }
182 |
183 | $hasErrors = $false
184 |
185 | if ($missingFiles) {
186 | Write-Error "Missing policy files:"
187 | $missingFiles | ForEach-Object {
188 | Write-Error "- $($_.PolicyName)"
189 | }
190 | $hasErrors = $true
191 | }
192 |
193 | if ($invalidJsonFiles) {
194 | Write-Error "Invalid JSON found in policy files:"
195 | $invalidJsonFiles | ForEach-Object {
196 | Write-Error "- $($_.PolicyName): $($_.JsonError)"
197 | }
198 | $hasErrors = $true
199 | }
200 |
201 | if ($hasErrors) {
202 | return
203 | }
204 |
205 | # Create destination directory
206 | try {
207 | $null = New-Item -ItemType Directory -Path $destPath -Force
208 | Write-Host "Created destination directory: $destPath" -ForegroundColor Green
209 | }
210 | catch {
211 | Write-Error "Failed to create destination directory: $_"
212 | return
213 | }
214 |
215 | # Copy files and generate report
216 | $copyResults = Copy-PolicyFiles -SourcePath $SourcePath -DestinationPath $destPath -Policies $ExpectedPolicies
217 | Export-PolicyCopyReport -Results $copyResults -OutputDir $destPath
218 |
219 | return $copyResults
220 | }
221 |
222 | # Define paths and policies
223 | $sourcePath = "C:\CaaC\SandBox\Dec182024-v5\DC_KVS_AO_Combined\MSFT\ConditionalAccess"
224 | $baseDestPath = "C:\CaaC\SandBox"
225 | $expectedPolicies = @(
226 | "CAD004-O365 Grant Require MFA for All users when Browser and Non-Compliant-v1.5",
227 | "CAD005-O365 Block access for unsupported device platforms for All users when Modern Auth Clients-v1.2",
228 | "CAD006-O365 Session block download on unmanaged device for All users when Browser and Modern App Clients and Non-Compliant-v1.5",
229 | "CAD007-O365 Session set Sign-in Frequency for Apps for All users when Modern Auth Clients and Non-Compliant-v1.2",
230 | "GLOBAL - 3020 - SESSION - BYOD Persistence",
231 | "CAD010-RJD Require MFA for device join or registration when Browser and Modern Auth Clients-v1.2",
232 | "CAL002-RSI Require MFA registration from trusted locations only for All users when Browser and Modern Auth Clients-v1.5",
233 | "CAP002-O365 Grant Exchange ActiveSync Clients for All users when Approved App-v1.0",
234 | "CAU009-Management BLOCK Admin Portals for All Users when Browser and Modern Auth Clients-v1.2",
235 | "GLOBAL - 1020 - BLOCK - Device Code Auth Flow",
236 | "GLOBAL - 1060 - BLOCK - Service Accounts (Trusted Locations Excluded) - Remember to add 1 service account per policy",
237 | "GLOBAL - 1080 - BLOCK - Guest Access to Sensitive Apps",
238 | "GLOBAL - 3030 - SESSION - Register Security Info Requirements - v1.2",
239 | "CAD001-O365 Grant macOS access for All users when Modern Auth Clients and Compliant-v1.1",
240 | "CAD002-O365 Grant Windows access for All users when Modern Auth Clients and Compliant-v1.1",
241 | "CAD003-O365 Grant iOS and Android access for All users when Modern Auth Clients and ApprovedApp or Compliant-v1.2",
242 | "CAD011-O365 Grant Linux access for All users when Modern Auth Clients and Compliant-v1.0",
243 | "GLOBAL - 2070 - GRANT - Mobile Device Access Requirements - v1.2",
244 | "CAD014-O365 Require App Protection Policy for Edge on Windows for All users when Browser and Non-Compliant-v1.0"
245 | )
246 |
247 | # Execute the copy operation
248 | Copy-ConditionalAccessPolicies -SourcePath $sourcePath -BaseDestPath $baseDestPath -ExpectedPolicies $expectedPolicies
249 |
--------------------------------------------------------------------------------
/14-Exclude-Include-Admins-Roles-CAPs copy 3.ps1:
--------------------------------------------------------------------------------
1 | Import-module 'C:\code\ConditionalAccessManagement\ConditionalAccessManagement.psm1'
2 |
3 | # Use functions
4 | # Update-ConditionalAccessPolicyGuestTypes
5 | Update-ConditionalAccessPolicyAdminRoles
--------------------------------------------------------------------------------
/2-Exclude-EntraGroup-AllConditionalAccessPolicies copy 9.ps1:
--------------------------------------------------------------------------------
1 |
2 |
3 | Start-Transcript -Path "C:\Code\CB\Entra\CNA\ConditionalAccess\Exclude_GroupFromAllCAPoliciesUsingBeta-v8.log"
4 | # Install the Microsoft Graph Beta module if not already installed
5 | # Install-Module Microsoft.Graph.Beta -Scope Allusers -AllowClobber -Force
6 | # Install-Module Microsoft.Graph.Groups -Scope Allusers -AllowClobber -Force
7 |
8 | # Import the Microsoft Graph Beta module
9 | # Import-Module Microsoft.Graph.Beta
10 |
11 |
12 | # Import-Module Microsoft.Graph.Identity.SignIns
13 |
14 | # Disconnect-MgGraph
15 | # Connect to Microsoft Graph
16 | Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess", "Group.ReadWrite.All", "Policy.Read.All", "Application.Read.All"
17 |
18 | # Disconnect-MgGraph
19 |
20 |
21 | # Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess", "Group.ReadWrite.All", "Policy.Read.All", "Application.Read.All"
22 | function New-ConditionalAccessGroup {
23 | param (
24 | [string]$GroupName
25 | )
26 |
27 | $groupParams = @{
28 | DisplayName = $GroupName
29 | MailEnabled = $false
30 | MailNickname = "NotSet"
31 | SecurityEnabled = $true
32 | }
33 | $group = New-MgGroup @groupParams
34 | # Write-Output "Group Created: $($group.DisplayName) with ID: $($group.Id)"
35 | return $group.Id
36 | }
37 |
38 |
39 | function Get-ConditionalAccessPoliciesViaMgGraph {
40 | $uri = "https://graph.microsoft.com/beta/identity/conditionalAccess/policies"
41 |
42 | # Initialize a list for better performance
43 | $allPolicies = [System.Collections.Generic.List[PSObject]]::new()
44 |
45 | do {
46 | # Fetch the policies via Graph API
47 | $response = Invoke-MgGraphRequest -Uri $uri -Method GET -Headers @{"Prefer" = "odata.maxpagesize=999" }
48 | $policies = $response.Value
49 |
50 | # Add the policies to the list
51 | $allPolicies.Add($policies)
52 |
53 | # Check for next link for pagination
54 | $uri = if ($response.'@odata.nextLink') { $response.'@odata.nextLink' } else { $null }
55 | } while ($uri)
56 |
57 | # Convert the list back to an array (optional)
58 | return $allPolicies.ToArray()
59 | }
60 |
61 |
62 | # function Exclude-GroupFromAllCAPoliciesUsingBeta {
63 | # param (
64 | # [string]$ExcludeGroupId # The ID of the group to be excluded
65 | # )
66 |
67 | # # Retrieve all Conditional Access Policies using the custom function
68 | # $allPolicies = Get-ConditionalAccessPoliciesViaMgGraph
69 |
70 | # foreach ($policy in $allPolicies) {
71 | # # Check if the group is already excluded
72 | # if ($policy.conditions.users.excludeGroups -contains $ExcludeGroupId) {
73 | # Write-Output "Group '$ExcludeGroupId' is already excluded in Policy: $($policy.displayName)"
74 | # continue
75 | # }
76 |
77 | # # Add the group to the excludeGroups array
78 | # $updatedExcludeGroups = $policy.conditions.users.excludeGroups + $ExcludeGroupId
79 |
80 | # # Prepare the conditions parameter
81 | # $conditions = @{
82 | # users = @{
83 | # excludeGroups = $updatedExcludeGroups
84 | # }
85 | # }
86 |
87 | # # Update the Conditional Access Policy using the Beta endpoint
88 | # try {
89 | # Update-MgBetaIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.id -Conditions $conditions
90 | # Write-Output "Updated Policy: $($policy.displayName) to exclude Group '$ExcludeGroupId'"
91 | # } catch {
92 | # Write-Error "Failed to update Policy: $($policy.displayName). Error: $_"
93 | # }
94 | # }
95 | # }
96 |
97 |
98 |
99 |
100 |
101 | function Exclude-GroupFromAllCAPoliciesUsingBeta {
102 | param (
103 | [Parameter(Mandatory = $true)]
104 | [string]$ExcludeGroupId # The ID of the group to be excluded
105 | )
106 |
107 | # Ensure a connection to Microsoft Graph
108 | # $graphScopes = "Policy.ReadWrite.ConditionalAccess"
109 | # Connect-MgGraph -Scopes $graphScopes
110 |
111 | # Retrieve all Conditional Access Policies using the custom function
112 | $allPolicies = Get-ConditionalAccessPoliciesViaMgGraph
113 |
114 | foreach ($policy in $allPolicies) {
115 | # Check if the group is already excluded
116 | if ($policy.conditions.users.excludeGroups -contains $ExcludeGroupId) {
117 | Write-Output "Group '$ExcludeGroupId' is already excluded in Policy: $($policy.displayName)"
118 | continue
119 | }
120 |
121 | # Add the group to the excludeGroups array
122 | $updatedExcludeGroups = $policy.conditions.users.excludeGroups + $ExcludeGroupId
123 |
124 | # Prepare the body parameter for Update-MgBetaIdentityConditionalAccessPolicy
125 | $bodyParams = @{
126 | Conditions = @{
127 | Users = @{
128 | ExcludeGroups = $updatedExcludeGroups
129 | }
130 | }
131 | }
132 |
133 | # Update the Conditional Access Policy using the Beta endpoint
134 | try {
135 | Update-MgBetaIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.id -BodyParameter $bodyParams
136 | Write-Output "Updated Policy: $($policy.displayName) to exclude Group '$ExcludeGroupId'"
137 | }
138 | catch {
139 | Write-Error "Failed to update Policy: $($policy.displayName). Error: $_"
140 | }
141 | }
142 |
143 | # Optionally, disconnect from Microsoft Graph after operations are complete
144 | # Disconnect-MgGraph
145 | }
146 |
147 |
148 |
149 |
150 |
151 | $groupId = $null
152 |
153 |
154 | $allconditionalaccesspoliciescount = (Get-ConditionalAccessPoliciesViaMgGraph).Count
155 | $allconditionalaccesspoliciescount
156 |
157 | # Uncomment the following lines to create a new group and add it to Conditional Access Policies
158 | # $groupId = New-ConditionalAccessGroup -GroupName "SG002 - Conditional Access - GLOBAL - DMZ - Exclusion Group"
159 |
160 |
161 | # $groupId = '4ecfb1e1-d76d-464a-866a-203bd77815c2' #CCI
162 | # $groupId = '2b56f107-e156-4ba6-ac5d-0db1e412a1d5' #Bellwoods
163 | # $groupId = '1e83e83f-6b88-4e6e-b979-37ad3c938d7e' #RAC
164 | # $groupId = 'b7f7e66a-a0f8-4113-ade7-987d8bae0cb6' #BCFHT
165 | # $groupId = '7b8fdb31-6ae0-460d-8c4c-afc671f52ecf' #Sandbox
166 | # $groupId = 'eccafc70-52d9-4935-b20b-543507559930' #ICTC
167 | # $groupId = 'f995c07d-5258-4478-ba41-503c9e8bde59' #Antea
168 | # $groupId = 'ef0f9b0f-52a0-4369-a955-aa5703aa8518' #CARMS
169 | # $groupId = '13f371ff-d912-4195-a238-750840cb47d5' #ARH
170 | # $groupId = "05fb21ca-b737-4e48-b557-e40d5feaaa58" #Ambico
171 | # $groupId = "d230864a-3736-4556-b978-fc1a99e624f5" #CNA
172 | # $groupId = "e7ff2f49-96f2-42fb-bcde-053dc9488e6a" #MSFT
173 | $groupId = "7c71e1c5-bd77-4684-9ea9-369baaecd536" #TGB
174 | # $groupId = '' #CPHA
175 |
176 | # Exclude-GroupFromAllCAPolicies -ExcludeGroupId $groupId
177 | Exclude-GroupFromAllCAPoliciesUsingBeta -ExcludeGroupId $groupId
178 |
179 | Stop-Transcript
--------------------------------------------------------------------------------
/3-Move-ConditionalAccessPoliciesJSONfiles.ps1:
--------------------------------------------------------------------------------
1 | # Define the path to the CSV file
2 | $csvPath = "D:\Code\CB\Entra\CCI\Graph\export\DeprecatedPolicies-v9-cci.csv"
3 |
4 | # Define the source and destination directories
5 | $sourceDir = "C:\code\caac\Feb192024\CCI\Canada Computing Inc\ConditionalAccess"
6 | $destinationDir = "C:\code\caac\Feb192024\CCI\Canada Computing Inc\ConditionalAccess-Recreated-Modern-Graph-API"
7 |
8 | # Import the CSV file
9 | $csvData = Import-Csv -Path $csvPath
10 |
11 | # Iterate over each row in the CSV
12 | foreach ($row in $csvData) {
13 | # Extract the display name
14 | $displayName = $row.'displayname'
15 |
16 | # Define the source file path based on the display name
17 | $sourceFile = Join-Path -Path $sourceDir -ChildPath "$displayName.json"
18 |
19 | # Define the destination file path
20 | $destinationFile = Join-Path -Path $destinationDir -ChildPath "$displayName.json"
21 |
22 | # Check if the source file exists
23 | if (Test-Path -Path $sourceFile) {
24 | # Move the JSON file from the source to the destination directory
25 | Move-Item -Path $sourceFile -Destination $destinationFile
26 | Write-Host "Moved: $sourceFile to $destinationFile"
27 | } else {
28 | Write-Host "File not found: $sourceFile"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/4-Delete-allConditionalAccessPolicies-v4-CSV.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with the necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.Read.All', 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Confirm before proceeding as this will delete Conditional Access policies specified in the CSV
5 | $confirmation = Read-Host "Are you sure you want to delete Conditional Access policies listed in the CSV? (yes/no)"
6 | if ($confirmation -ne 'yes') {
7 | Write-Output "Operation aborted by the user."
8 | Disconnect-MgGraph
9 | exit
10 | }
11 |
12 | # Import the CSV file containing the policy IDs
13 | # $csvPath = Read-Host "D:\Code\CB\Entra\CCI\Graph\export\DeprecatedPolicies-v6-sandbox.csv"
14 | $csvPath = "D:\Code\CB\Entra\Ladco\Graph\export\DeprecatedPolicies-v9-cci.csv"
15 | $policyIds = Import-Csv -Path $csvPath
16 |
17 | # Iterate through the CSV data and delete each policy by ID
18 | foreach ($policy in $policyIds) {
19 | $policyId = $policy.Id # Assuming the column name in the CSV is 'PolicyId'
20 | try {
21 | # Delete the Conditional Access policy by its ID
22 | Remove-MgBetaIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policyId
23 | Write-Output "Successfully requested deletion of Conditional Access policy with ID: $policyId"
24 | } catch {
25 | Write-Error "Failed to delete Conditional Access policy with ID: $policyId. Error: $_"
26 | }
27 | }
28 |
29 | # Disconnect from Microsoft Graph
30 | # Disconnect-MgGraph
31 |
--------------------------------------------------------------------------------
/4.1-Delete-allConditionalAccessPolicies-v4-API copy 4.ps1:
--------------------------------------------------------------------------------
1 | #Requires -Modules Microsoft.Graph.Identity.SignIns, PSWriteHTML, Microsoft.Graph.Identity.DirectoryManagement
2 |
3 | function Connect-GraphWithScope {
4 | [CmdletBinding()]
5 | param()
6 |
7 | $requiredScopes = @(
8 | "Policy.Read.All"
9 | "Policy.ReadWrite.ConditionalAccess"
10 | "Organization.Read.All"
11 | )
12 |
13 | $currentContext = Get-MgContext
14 |
15 | if ($null -eq $currentContext) {
16 | Write-Host "No existing Graph connection found. Connecting..." -ForegroundColor Yellow
17 | Connect-MgGraph -Scopes $requiredScopes
18 | return
19 | }
20 |
21 | $missingScopes = $requiredScopes | Where-Object { $_ -notin $currentContext.Scopes }
22 |
23 | if ($missingScopes) {
24 | Write-Host "Missing required scopes. Reconnecting with all required scopes..." -ForegroundColor Yellow
25 | Disconnect-MgGraph
26 | Connect-MgGraph -Scopes $requiredScopes
27 | }
28 | }
29 |
30 | function New-ExportPath {
31 | param (
32 | [string]$BasePath = "C:\Code\CB\Entra\Sandbox\Graph\export",
33 | [string]$FilePrefix = "ConditionalAccessPolicies"
34 | )
35 |
36 | $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
37 | $exportPaths = @{
38 | Directory = $BasePath
39 | Csv = Join-Path -Path $BasePath -ChildPath "$FilePrefix`_$timestamp.csv"
40 | Html = Join-Path -Path $BasePath -ChildPath "$FilePrefix`_$timestamp.html"
41 | }
42 |
43 | if (-not (Test-Path -Path $exportPaths.Directory)) {
44 | New-Item -Path $exportPaths.Directory -ItemType Directory -Force | Out-Null
45 | }
46 |
47 | return $exportPaths
48 | }
49 |
50 | function Export-PolicyData {
51 | param (
52 | [Parameter(Mandatory)]
53 | [object[]]$Policies,
54 | [Parameter(Mandatory)]
55 | [string]$CsvPath,
56 | [Parameter(Mandatory)]
57 | [string]$HtmlPath,
58 | [Parameter()]
59 | [hashtable]$Metadata
60 | )
61 |
62 | # Export to CSV
63 | $Policies | Export-Csv -Path $CsvPath -NoTypeInformation
64 |
65 | New-HTML -Title "Conditional Access Policies Report" -FilePath $HtmlPath -ShowHTML {
66 | New-HTMLSection -HeaderText "Deletion Summary" {
67 | New-HTMLPanel {
68 | New-HTMLText -Text @"
69 | Report Details
70 |
71 | - Generated By: $($env:USERNAME)
72 | - Generated On: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
73 | - Tenant Name: $($Metadata.TenantName)
74 | - Tenant ID: $($Metadata.TenantId)
75 | - Total Policies: $($Metadata.TotalPolicies)
76 | - Successful Deletions: $($Metadata.SuccessCount)
77 | - Failed Deletions: $($Metadata.FailureCount)
78 |
79 | "@
80 | }
81 | }
82 |
83 | New-HTMLSection -HeaderText "Policy Deletion Results" {
84 | New-HTMLTable -DataTable $Policies -ScrollX -Buttons @('copyHtml5', 'excelHtml5', 'csvHtml5') -SearchBuilder {
85 | New-TableCondition -Name 'Status' -ComparisonType string -Operator eq -Value 'Failed' -BackgroundColor Salmon -Color Black
86 | New-TableCondition -Name 'Status' -ComparisonType string -Operator eq -Value 'Success' -BackgroundColor LightGreen -Color Black
87 | New-TableCondition -Name 'DisplayName' -ComparisonType string -Operator contains -Value '' -BackgroundColor White -Color Black
88 | }
89 | }
90 | }
91 | }
92 |
93 | function Remove-ConditionalAccessPolicies {
94 | [CmdletBinding(SupportsShouldProcess)]
95 | param()
96 |
97 | try {
98 | # Ensure proper Graph connection
99 | Connect-GraphWithScope
100 |
101 | # Get current tenant details
102 | $tenantInfo = Get-MgOrganization
103 | $tenantName = $tenantInfo.DisplayName
104 | $tenantId = $tenantInfo.Id
105 |
106 | Write-Host "Connected to tenant: $tenantName (ID: $tenantId)" -ForegroundColor Yellow
107 |
108 | # Get export paths
109 | $exportPaths = New-ExportPath
110 |
111 | # Retrieve all Conditional Access policies
112 | $policies = Get-MgIdentityConditionalAccessPolicy
113 | $initialPolicyCount = $policies.Count
114 |
115 | if ($initialPolicyCount -eq 0) {
116 | Write-Warning "No Conditional Access policies found in the tenant."
117 | return
118 | }
119 |
120 | # Initialize results tracking
121 | $results = [System.Collections.ArrayList]::new()
122 |
123 | # Create initial backup with all policies
124 | $policies | ForEach-Object {
125 | $null = $results.Add([PSCustomObject]@{
126 | DisplayName = $_.DisplayName
127 | Id = $_.Id
128 | State = $_.State
129 | Status = "Pending"
130 | ErrorMessage = ""
131 | })
132 | }
133 |
134 | # Display summary
135 | Write-Host "`nSummary:" -ForegroundColor Cyan
136 | Write-Host "- Tenant: $tenantName" -ForegroundColor Cyan
137 | Write-Host "- Total policies to be deleted: $initialPolicyCount" -ForegroundColor Cyan
138 | Write-Host "- Backup will be saved to: $($exportPaths.Csv)" -ForegroundColor Cyan
139 | Write-Host "- HTML report: $($exportPaths.Html)" -ForegroundColor Cyan
140 |
141 | # Confirm deletion
142 | $confirmMessage = "Are you sure you want to delete all $initialPolicyCount Conditional Access policies from tenant '$tenantName'? (yes/no)"
143 | $confirmation = Read-Host -Prompt $confirmMessage
144 |
145 | if ($confirmation -ne 'yes') {
146 | Write-Warning "Operation aborted by user"
147 | return
148 | }
149 |
150 | # Delete policies and update results
151 | foreach ($policy in $policies) {
152 | if ($PSCmdlet.ShouldProcess($policy.DisplayName, "Delete Conditional Access Policy")) {
153 | try {
154 | Remove-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.Id
155 | $result = $results | Where-Object Id -eq $policy.Id
156 | $result.Status = "Success"
157 | Write-Host "Deleted policy: $($policy.DisplayName)" -ForegroundColor Green
158 | }
159 | catch {
160 | $result = $results | Where-Object Id -eq $policy.Id
161 | $result.Status = "Failed"
162 | $result.ErrorMessage = $_.Exception.Message
163 | Write-Error "Failed to delete policy '$($policy.DisplayName)': $_"
164 | }
165 | }
166 | }
167 |
168 | # Final verification
169 | Start-Sleep -Seconds 5 # Allow time for deletions to process
170 | $remainingPolicies = Get-MgIdentityConditionalAccessPolicy
171 |
172 | # Prepare metadata for report
173 | $metadata = @{
174 | TenantName = $tenantName
175 | TenantId = $tenantId
176 | TotalPolicies = $initialPolicyCount
177 | SuccessCount = ($results | Where-Object Status -eq "Success").Count
178 | FailureCount = ($results | Where-Object Status -eq "Failed").Count
179 | RemainingPolicies = $remainingPolicies.Count
180 | }
181 |
182 | # Generate reports
183 | Export-PolicyData -Policies $results -CsvPath $exportPaths.Csv -HtmlPath $exportPaths.Html -Metadata $metadata
184 |
185 | # Display final results
186 | Write-Host "`nOperation Complete:" -ForegroundColor Cyan
187 | Write-Host "- Successfully deleted: $($metadata.SuccessCount) policies" -ForegroundColor Green
188 | Write-Host "- Failed to delete: $($metadata.FailureCount) policies" -ForegroundColor $(if ($metadata.FailureCount -gt 0) { 'Red' } else { 'Green' })
189 | Write-Host "- Remaining policies: $($metadata.RemainingPolicies)" -ForegroundColor Cyan
190 | Write-Host "`nReports generated:" -ForegroundColor Green
191 | Write-Host "CSV Report: $($exportPaths.Csv)" -ForegroundColor Green
192 | Write-Host "HTML Report: $($exportPaths.Html)" -ForegroundColor Green
193 |
194 | if ($metadata.FailureCount -gt 0) {
195 | Write-Host "`nFailed Deletions:" -ForegroundColor Red
196 | $results | Where-Object Status -eq "Failed" | ForEach-Object {
197 | Write-Host "- $($_.DisplayName): $($_.ErrorMessage)" -ForegroundColor Red
198 | }
199 | }
200 | }
201 | catch {
202 | Write-Error "An error occurred: $_"
203 | }
204 | }
205 |
206 | # Run the cleanup
207 | Remove-ConditionalAccessPolicies
--------------------------------------------------------------------------------
/5-recreateConditionalAccesspoliciesusingJSON-v7.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Specify the directory containing the JSON files
5 | # $jsonDir = "C:\code\caac\Feb172024\CCI\Entra-Intune-v1\Canada Computing Inc\ConditionalAccess-Recreated-Modern-Graph-API"
6 | $jsonDir = "C:\code\caac\Feb192024\CCI\Canada Computing Inc\ConditionalAccess-Recreated-Modern-Graph-API"
7 |
8 | # Get all JSON files from the directory
9 | $jsonFiles = Get-ChildItem -Path $jsonDir -Filter "*.json"
10 |
11 | foreach ($jsonFile in $jsonFiles) {
12 | # Load the JSON content
13 | $jsonContent = Get-Content -Path $jsonFile.FullName -Raw | ConvertFrom-Json
14 |
15 | # Prepare the policy object for creation
16 | $policyParams = @{
17 | DisplayName = $jsonContent.displayName + " - Modern API"
18 | State = "disabled" # Ensure the policy is created in the "off" state
19 | Conditions = @{
20 | Users = @{
21 | IncludeUsers = @("All") # Specify user object IDs to include
22 | # ExcludeUsers = @("userObjectId3") # Specify user object IDs to exclude
23 | }
24 | Applications = @{
25 | # IncludeApplications = @("appId1", "appId2") # Specify application IDs to include
26 | IncludeApplications = @("All") # Specify application IDs to include
27 | }
28 | }
29 | GrantControls = @{
30 | BuiltInControls = @("mfa") # Require MFA
31 | Operator = "OR"
32 | }
33 | }
34 |
35 | # Convert policy object to JSON
36 | $policyJson = $policyParams | ConvertTo-Json -Depth 10
37 |
38 | try {
39 | # Attempt to create the Conditional Access policy
40 | $result = New-MgIdentityConditionalAccessPolicy -BodyParameter $policyJson
41 | Write-Host "Successfully created policy: $($result.DisplayName)"
42 | } catch {
43 | Write-Error "Failed to create policy from file $($jsonFile.Name): $_"
44 | }
45 | }
46 |
47 | # Disconnect from Microsoft Graph
48 | # Disconnect-MgGraph
49 |
--------------------------------------------------------------------------------
/6-RemoveCAOrphanedGroup.ps1:
--------------------------------------------------------------------------------
1 | $orphanedGroupId = '614050e3-2fa4-4ab3-ad4e-12ef93d805e3' # The ID of the deleted (orphan) group
2 |
3 |
4 | Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess", "Group.ReadWrite.All", "Policy.Read.All"
5 |
6 |
7 |
8 | function Get-ConditionalAccessPoliciesViaMgGraph {
9 | $uri = "https://graph.microsoft.com/beta/identity/conditionalAccess/policies"
10 | $allPolicies = @()
11 |
12 | do {
13 | $response = Invoke-MgGraphRequest -Uri $uri -Method GET -Headers @{"Prefer"="odata.maxpagesize=999"}
14 | $policies = $response.Value
15 | $allPolicies += $policies
16 |
17 | $uri = if ($response.'@odata.nextLink') { $response.'@odata.nextLink' } else { $null }
18 | } while ($uri)
19 |
20 | return $allPolicies
21 | }
22 |
23 | $allPolicies = Get-ConditionalAccessPoliciesViaMgGraph
24 |
25 | foreach ($policy in $allPolicies) {
26 | if ($policy.conditions.users.excludeGroups -contains $orphanedGroupId) {
27 | # Prepare to update the policy by removing the orphaned group ID
28 | $updatedExcludeGroups = $policy.conditions.users.excludeGroups | Where-Object { $_ -ne $orphanedGroupId }
29 |
30 | # Prepare the updated conditions without the orphaned group ID
31 | $conditions = @{
32 | users = @{
33 | excludeGroups = $updatedExcludeGroups
34 | }
35 | }
36 |
37 | # Update the policy
38 | try {
39 | Update-MgBetaIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.id -Conditions $conditions
40 | Write-Output "Removed orphaned group from Policy: $($policy.displayName)"
41 | } catch {
42 | Write-Error "Failed to remove orphaned group from Policy: $($policy.displayName). Error: $_"
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/7-RemoveCAOrphanedUser copy 2.ps1:
--------------------------------------------------------------------------------
1 | function Get-ConditionalAccessPoliciesViaMgGraph {
2 | $uri = "https://graph.microsoft.com/beta/identity/conditionalAccess/policies"
3 | $allPolicies = @()
4 |
5 | do {
6 | $response = Invoke-MgGraphRequest -Uri $uri -Method GET -Headers @{"Prefer" = "odata.maxpagesize=999" }
7 | $policies = $response.Value
8 | $allPolicies += $policies
9 |
10 | $uri = if ($response.'@odata.nextLink') { $response.'@odata.nextLink' } else { $null }
11 | } while ($uri)
12 |
13 | return $allPolicies
14 | }
15 |
16 |
17 |
18 | $allPolicies = Get-ConditionalAccessPoliciesViaMgGraph
19 |
20 |
21 | function Remove-OrphanedUserFromCAPolicy {
22 | param(
23 | [Parameter(Mandatory = $true)]
24 | [string]$orphanedUserId,
25 | [Parameter(Mandatory = $true)]
26 | [object]$policy
27 | )
28 |
29 | Process {
30 | Write-Verbose "Processing Policy: $($policy.displayName)"
31 |
32 | # Check if the orphaned user is in the excludeUsers list
33 | if ($policy.conditions.users.excludeUsers -contains $orphanedUserId) {
34 | Write-Verbose "Found orphaned user in Policy: $($policy.displayName)"
35 |
36 | # Remove the orphaned user ID from excludeUsers
37 | $updatedExcludeUsers = $policy.conditions.users.excludeUsers | Where-Object { $_ -ne $orphanedUserId }
38 |
39 | # Check if updatedExcludeUsers is empty to determine if we need to pass an empty array
40 | if (-not $updatedExcludeUsers) {
41 | $updatedExcludeUsers = @()
42 | }
43 |
44 | # Prepare the body parameter for Update-MgBetaIdentityConditionalAccessPolicy
45 | $bodyParams = @{
46 | Conditions = @{
47 | Users = @{
48 | ExcludeUsers = $updatedExcludeUsers
49 | }
50 | }
51 | }
52 |
53 | try {
54 | # Update the policy using Update-MgBetaIdentityConditionalAccessPolicy
55 | Update-MgBetaIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.id -BodyParameter $bodyParams
56 | Write-Output "Successfully updated Policy: $($policy.displayName)"
57 | }
58 | catch {
59 | Write-Error "Failed to update Policy: $($policy.displayName). Error: $($_.Exception.Message)"
60 | }
61 | }
62 | else {
63 | Write-Verbose "Orphaned user not found in Policy: $($policy.displayName)"
64 | }
65 | }
66 | }
67 |
68 |
69 | # Connect to Microsoft Graph
70 | $graphScopes = "Policy.ReadWrite.ConditionalAccess", "Group.ReadWrite.All", "Policy.Read.All"
71 | Connect-MgGraph -Scopes $graphScopes -ErrorAction Stop
72 | Write-Verbose "Connected to Microsoft Graph with necessary scopes."
73 |
74 | # Retrieve all Conditional Access Policies
75 | $allPolicies = Get-ConditionalAccessPoliciesViaMgGraph
76 | Write-Verbose "Retrieved all Conditional Access Policies."
77 |
78 |
79 | $orphanedUserId = $null
80 | $orphanedUserId = '6303c7ce-c078-47ce-a1f3-9750d8d3ff68' # Replace this with the actual orphaned user ID
81 |
82 | foreach ($policy in $allPolicies) {
83 | Remove-OrphanedUserFromCAPolicy -orphanedUserId $orphanedUserId -policy $policy -Verbose
84 | }
85 |
86 | # Optionally, disconnect from Microsoft Graph after operations are complete
87 | # Disconnect-MgGraph
88 | # Write-Verbose "Disconnected from Microsoft Graph."
89 |
--------------------------------------------------------------------------------
/8-RemoveCAOrphanedobjects-dynamic copy.ps1:
--------------------------------------------------------------------------------
1 | # Function to get all users and groups from Microsoft Graph
2 | function Get-AllUsersAndGroups {
3 | $allUsers = [System.Collections.Generic.List[PSCustomObject]]::new()
4 | $allGroups = [System.Collections.Generic.List[PSCustomObject]]::new()
5 |
6 | # Get all users
7 | $uriUsers = "https://graph.microsoft.com/v1.0/users"
8 | do {
9 | $responseUsers = Invoke-MgGraphRequest -Uri $uriUsers -Method GET -Headers @{"Prefer"="odata.maxpagesize=999"}
10 | $users = [System.Collections.Generic.List[PSCustomObject]]::new()
11 | $responseUsers.value | ForEach-Object { [void]$users.Add($_) }
12 | $allUsers.Add($users)
13 |
14 | $uriUsers = if ($responseUsers.'@odata.nextLink') { $responseUsers.'@odata.nextLink' } else { $null }
15 | } while ($uriUsers)
16 |
17 | # Get all groups
18 | $uriGroups = "https://graph.microsoft.com/v1.0/groups"
19 | do {
20 | $responseGroups = Invoke-MgGraphRequest -Uri $uriGroups -Method GET -Headers @{"Prefer"="odata.maxpagesize=999"}
21 | $groups = [System.Collections.Generic.List[PSCustomObject]]::new()
22 | $responseGroups.value | ForEach-Object { [void]$groups.Add($_) }
23 | $allGroups.Add($groups)
24 |
25 | $uriGroups = if ($responseGroups.'@odata.nextLink') { $responseGroups.'@odata.nextLink' } else { $null }
26 | } while ($uriGroups)
27 |
28 | return [PSCustomObject]@{ Users = $allUsers; Groups = $allGroups }
29 | }
30 |
31 | # Function to get all conditional access policies
32 | function Get-ConditionalAccessPoliciesViaMgGraph {
33 | $allPolicies = [System.Collections.Generic.List[PSCustomObject]]::new()
34 | $uri = "https://graph.microsoft.com/beta/identity/conditionalAccess/policies"
35 |
36 | do {
37 | $response = Invoke-MgGraphRequest -Uri $uri -Method GET -Headers @{"Prefer" = "odata.maxpagesize=999" }
38 | $policies = [System.Collections.Generic.List[PSCustomObject]]::new()
39 | $response.Value | ForEach-Object { [void]$policies.Add($_) }
40 | $allPolicies.Add($policies)
41 |
42 | $uri = if ($response.'@odata.nextLink') { $response.'@odata.nextLink' } else { $null }
43 | } while ($uri)
44 |
45 | return $allPolicies
46 | }
47 |
48 | # Function to remove orphaned users and groups from conditional access policies
49 | function Remove-OrphanedUsersAndGroups {
50 | param(
51 | [Parameter(Mandatory = $true)]
52 | [object]$allEntities,
53 | [Parameter(Mandatory = $true)]
54 | [object]$policy
55 | )
56 |
57 | Process {
58 | Write-Verbose "Processing Policy: $($policy.displayName)"
59 |
60 | $isUpdated = $false
61 |
62 | # Function to validate if a user or group ID is present in the respective entities list
63 | function Is-Orphaned {
64 | param (
65 | [string]$id,
66 | [System.Collections.Generic.List[PSCustomObject]]$entities
67 | )
68 | return (-not ($entities.id -contains $id)) -and ($id -ne "All")
69 | }
70 |
71 | # Remove orphaned users from includeUsers and excludeUsers
72 | if ($policy.conditions.users.includeUsers) {
73 | $orphanedIncludeUsers = $policy.conditions.users.includeUsers | Where-Object { Is-Orphaned -id $_ -entities $allEntities.Users }
74 | if ($orphanedIncludeUsers) {
75 | $updatedIncludeUsers = $policy.conditions.users.includeUsers | Where-Object { -not ($orphanedIncludeUsers -contains $_) }
76 | foreach ($userId in $orphanedIncludeUsers) {
77 | Write-Host "Orphaned user found in includeUsers in Policy: $($policy.displayName). User ID: $userId" -ForegroundColor Yellow
78 | }
79 | $policy.conditions.users.includeUsers = $updatedIncludeUsers
80 | $isUpdated = $true
81 | }
82 | }
83 |
84 | if ($policy.conditions.users.excludeUsers) {
85 | $orphanedExcludeUsers = $policy.conditions.users.excludeUsers | Where-Object { Is-Orphaned -id $_ -entities $allEntities.Users }
86 | if ($orphanedExcludeUsers) {
87 | $updatedExcludeUsers = $policy.conditions.users.excludeUsers | Where-Object { -not ($orphanedExcludeUsers -contains $_) }
88 | foreach ($userId in $orphanedExcludeUsers) {
89 | Write-Host "Orphaned user found in excludeUsers in Policy: $($policy.displayName). User ID: $userId" -ForegroundColor Yellow
90 | }
91 | $policy.conditions.users.excludeUsers = $updatedExcludeUsers
92 | $isUpdated = $true
93 | }
94 | }
95 |
96 | # Remove orphaned groups from includeGroups and excludeGroups
97 | if ($policy.conditions.users.includeGroups) {
98 | $orphanedIncludeGroups = $policy.conditions.users.includeGroups | Where-Object { Is-Orphaned -id $_ -entities $allEntities.Groups }
99 | if ($orphanedIncludeGroups) {
100 | $updatedIncludeGroups = $policy.conditions.users.includeGroups | Where-Object { -not ($orphanedIncludeGroups -contains $_) }
101 | foreach ($groupId in $orphanedIncludeGroups) {
102 | Write-Host "Orphaned group found in includeGroups in Policy: $($policy.displayName). Group ID: $groupId" -ForegroundColor Yellow
103 | }
104 | $policy.conditions.users.includeGroups = $updatedIncludeGroups
105 | $isUpdated = $true
106 | }
107 | }
108 |
109 | if ($policy.conditions.users.excludeGroups) {
110 | $orphanedExcludeGroups = $policy.conditions.users.excludeGroups | Where-Object { Is-Orphaned -id $_ -entities $allEntities.Groups }
111 | if ($orphanedExcludeGroups) {
112 | $updatedExcludeGroups = $policy.conditions.users.excludeGroups | Where-Object { -not ($orphanedExcludeGroups -contains $_) }
113 | foreach ($groupId in $orphanedExcludeGroups) {
114 | Write-Host "Orphaned group found in excludeGroups in Policy: $($policy.displayName). Group ID: $groupId" -ForegroundColor Yellow
115 | }
116 | $policy.conditions.users.excludeGroups = $updatedExcludeGroups
117 | $isUpdated = $true
118 | }
119 | }
120 |
121 | # Update the policy if there were changes
122 | if ($isUpdated) {
123 | try {
124 | Update-MgBetaIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.id -Conditions $policy.conditions
125 | Write-Host "Updated policy: $($policy.displayName)" -ForegroundColor Green
126 | } catch {
127 | Write-Error "Failed to update policy: $($policy.displayName). Error: $_"
128 | }
129 | } else {
130 | Write-Host "No orphaned users or groups found in Policy: $($policy.displayName)" -ForegroundColor Cyan
131 | }
132 | }
133 | }
134 |
135 | # Connect to Microsoft Graph
136 | $graphScopes = "Policy.ReadWrite.ConditionalAccess", "Group.ReadWrite.All", "Policy.Read.All"
137 | Connect-MgGraph -Scopes $graphScopes -ErrorAction Stop
138 | Write-Verbose "Connected to Microsoft Graph with necessary scopes."
139 |
140 | # Retrieve all users and groups
141 | $allEntities = Get-AllUsersAndGroups
142 | Write-Verbose "Retrieved all users and groups."
143 |
144 | # Retrieve all Conditional Access Policies
145 | $allPolicies = Get-ConditionalAccessPoliciesViaMgGraph
146 | Write-Verbose "Retrieved all Conditional Access Policies."
147 |
148 | foreach ($policy in $allPolicies) {
149 | Remove-OrphanedUsersAndGroups -allEntities $allEntities -policy $policy -Verbose
150 | }
--------------------------------------------------------------------------------
/9-Conditional Access JSON Converter copy 4.ps1:
--------------------------------------------------------------------------------
1 | #Requires -Modules PSWriteHTML
2 |
3 | function Convert-CADirectoryToSingleJson {
4 | [CmdletBinding()]
5 | param (
6 | [Parameter(Mandatory)]
7 | [string]$DirectoryPath,
8 |
9 | [Parameter()]
10 | [string]$OutputPath = "conversion_results.html"
11 | )
12 |
13 | if (-not (Test-Path -Path $DirectoryPath)) {
14 | Write-Error "Directory not found: $DirectoryPath"
15 | return
16 | }
17 |
18 | $allPolicies = [System.Collections.ArrayList]::new()
19 | $results = [System.Collections.ArrayList]::new()
20 |
21 | $getChildParams = @{
22 | Path = $DirectoryPath
23 | Filter = "*.json"
24 | }
25 | $jsonFiles = @(Get-ChildItem @getChildParams)
26 |
27 | foreach ($file in $jsonFiles) {
28 | try {
29 | $getContentParams = @{
30 | Path = $file.FullName
31 | Raw = $true
32 | }
33 | $policy = Get-Content @getContentParams | ConvertFrom-Json
34 | $null = $allPolicies.Add($policy)
35 |
36 | $successResult = [PSCustomObject]@{
37 | FileName = $file.Name
38 | Status = "Success"
39 | Error = ""
40 | PolicyName = $policy.displayName
41 | }
42 | $null = $results.Add($successResult)
43 | }
44 | catch {
45 | $failureResult = [PSCustomObject]@{
46 | FileName = $file.Name
47 | Status = "Failed"
48 | Error = $_.Exception.Message
49 | PolicyName = ""
50 | }
51 | $null = $results.Add($failureResult)
52 | }
53 | }
54 |
55 | $combinedJson = @{
56 | '@odata.context' = 'https://graph.microsoft.com/beta/$metadata#policies/conditionalAccessPolicies'
57 | 'value' = $allPolicies.ToArray()
58 | }
59 |
60 | $convertToJsonParams = @{
61 | Depth = 20
62 | }
63 | $combinedJson | ConvertTo-Json @convertToJsonParams | Set-Clipboard
64 |
65 | $successCount = ($results | Where-Object Status -eq "Success").Count
66 | $failureCount = ($results | Where-Object Status -eq "Failed").Count
67 |
68 | $metadata = @{
69 | GeneratedBy = $env:USERNAME
70 | GeneratedOn = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
71 | TotalPolicies = $results.Count
72 | SuccessCount = $successCount
73 | FailureCount = $failureCount
74 | }
75 |
76 | $htmlParams = @{
77 | Title = "Conditional Access Policy Conversion Report"
78 | FilePath = $OutputPath
79 | ShowHTML = $true
80 | }
81 |
82 | New-HTML @htmlParams {
83 | $sectionParams = @{
84 | HeaderText = "Conversion Summary"
85 | }
86 | New-HTMLSection @sectionParams {
87 | New-HTMLPanel {
88 | $textParams = @{
89 | Text = @"
90 | Report Details
91 |
92 | - Generated By: $($metadata.GeneratedBy)
93 | - Generated On: $($metadata.GeneratedOn)
94 | - Total Policies Processed: $($metadata.TotalPolicies)
95 | - Successful Conversions: $($metadata.SuccessCount)
96 | - Failed Conversions: $($metadata.FailureCount)
97 |
98 | "@
99 | }
100 | New-HTMLText @textParams
101 | }
102 | }
103 |
104 | $resultsSectionParams = @{
105 | HeaderText = "Policy Conversion Results"
106 | }
107 | New-HTMLSection @resultsSectionParams {
108 | $tableParams = @{
109 | DataTable = $results
110 | ScrollX = $true
111 | Buttons = @('copyHtml5', 'excelHtml5', 'csvHtml5')
112 | SearchBuilder = $true
113 | }
114 | New-HTMLTable @tableParams {
115 | $failedConditionParams = @{
116 | Name = 'Status'
117 | ComparisonType = 'string'
118 | Operator = 'eq'
119 | Value = 'Failed'
120 | BackgroundColor = 'Salmon'
121 | Color = 'Black'
122 | }
123 | New-TableCondition @failedConditionParams
124 |
125 | $successConditionParams = @{
126 | Name = 'Status'
127 | ComparisonType = 'string'
128 | Operator = 'eq'
129 | Value = 'Success'
130 | BackgroundColor = 'LightGreen'
131 | Color = 'Black'
132 | }
133 | New-TableCondition @successConditionParams
134 | }
135 | }
136 | }
137 |
138 | $summaryParams = @{
139 | Object = "`nConversion Summary:"
140 | ForegroundColor = "Cyan"
141 | }
142 | Write-Host @summaryParams
143 |
144 | Write-Host "----------------"
145 |
146 | $successParams = @{
147 | Object = "Successful conversions: $successCount"
148 | ForegroundColor = "Green"
149 | }
150 | Write-Host @successParams
151 |
152 | $failureColor = if ($failureCount -gt 0) { "Red" } else { "Green" }
153 | $failureParams = @{
154 | Object = "Failed conversions: $failureCount"
155 | ForegroundColor = $failureColor
156 | }
157 | Write-Host @failureParams
158 |
159 | $clipboardParams = @{
160 | Object = "`nCombined JSON has been copied to clipboard"
161 | ForegroundColor = "Green"
162 | }
163 | Write-Host @clipboardParams
164 |
165 | $reportParams = @{
166 | Object = "Report saved to: $OutputPath"
167 | ForegroundColor = "Green"
168 | }
169 | Write-Host @reportParams
170 | }
171 |
172 |
173 |
174 | # Example usage:
175 | # Convert-CADirectoryToSingleJson -DirectoryPath "C:\code\CA\KVS\cabaseline202409\ConditionalAccess"
176 | # Convert-CADirectoryToSingleJson -DirectoryPath "C:\CaaC\SandBox\Dec102024-v2\AO\ConditionalAccess"
177 | Convert-CADirectoryToSingleJson -DirectoryPath "C:\CaaC\SandBox\Dec162024-v3\DC_KVS_Combined\MSFT\ADMINS"
--------------------------------------------------------------------------------
/Archive/15-Exclude-Include-Gues-Roles-CAPs copy 10.ps1:
--------------------------------------------------------------------------------
1 | #Requires -Modules Microsoft.Graph.Identity.SignIns, PSWriteHTML
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | # Main execution
12 | Update-ConditionalAccessPolicyGuestTypes
--------------------------------------------------------------------------------
/CABaseline2025/AppConfigurationManagedApp/ACP001 - iOSiPadOS - Outlook - Default Signature and External Mailtip.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AppConfigurationManagedApp/ACP001 - iOSiPadOS - Outlook - Default Signature and External Mailtip.json
--------------------------------------------------------------------------------
/CABaseline2025/AppConfigurationManagedApp/ACP002 - Android - Outlook - Default Signature and External Mailtip.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AppConfigurationManagedApp/ACP002 - Android - Outlook - Default Signature and External Mailtip.json
--------------------------------------------------------------------------------
/CABaseline2025/AppProtection/APP001 - Unmanaged - BYOD - iOSiPadOS - MAM - Require Min iOS version.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AppProtection/APP001 - Unmanaged - BYOD - iOSiPadOS - MAM - Require Min iOS version.json
--------------------------------------------------------------------------------
/CABaseline2025/AppProtection/APP002 - Unmanaged - BYOD - Android - MAM - Require Min OS version.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AppProtection/APP002 - Unmanaged - BYOD - Android - MAM - Require Min OS version.json
--------------------------------------------------------------------------------
/CABaseline2025/AppProtection/MAM for Edge.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AppProtection/MAM for Edge.json
--------------------------------------------------------------------------------
/CABaseline2025/AssignmentFilters/Filter001 - Exclude Library Computers from Filehold Install.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AssignmentFilters/Filter001 - Exclude Library Computers from Filehold Install.json
--------------------------------------------------------------------------------
/CABaseline2025/AssignmentFilters/Filter002 - Unmanaged - BYOD - iOSiPad OS Devices.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AssignmentFilters/Filter002 - Unmanaged - BYOD - iOSiPad OS Devices.json
--------------------------------------------------------------------------------
/CABaseline2025/AssignmentFilters/Filter003 - Unmanaged - BYOD - Android OS Devices.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AssignmentFilters/Filter003 - Unmanaged - BYOD - Android OS Devices.json
--------------------------------------------------------------------------------
/CABaseline2025/AuthenticationStrengths/MS Auth app - WHFB - TAP.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AuthenticationStrengths/MS Auth app - WHFB - TAP.json
--------------------------------------------------------------------------------
/CABaseline2025/AuthenticationStrengths/Multifactor authentication.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AuthenticationStrengths/Multifactor authentication.json
--------------------------------------------------------------------------------
/CABaseline2025/AuthenticationStrengths/Passwordless MFA.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AuthenticationStrengths/Passwordless MFA.json
--------------------------------------------------------------------------------
/CABaseline2025/AuthenticationStrengths/Phishing-resistant MFA.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/AuthenticationStrengths/Phishing-resistant MFA.json
--------------------------------------------------------------------------------
/CABaseline2025/CompliancePolicies/Default compliance policy for Android.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/CompliancePolicies/Default compliance policy for Android.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD001-O365 Grant macOS access for All users when Modern Auth Clients and Compliant-v1.1.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD001-O365 Grant macOS access for All users when Modern Auth Clients and Compliant-v1.1.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD002-O365 Grant Windows access for All users when Modern Auth Clients and Compliant-v1.1.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD002-O365 Grant Windows access for All users when Modern Auth Clients and Compliant-v1.1.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD003-O365 Grant iOS and Android access for All users when Modern Auth Clients and ApprovedApp or Compliant-v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD003-O365 Grant iOS and Android access for All users when Modern Auth Clients and ApprovedApp or Compliant-v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD004-O365 Grant Require MFA for All users when Browser and Non-Compliant-v1.5.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD004-O365 Grant Require MFA for All users when Browser and Non-Compliant-v1.5.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD005-O365 Block access for unsupported device platforms for All users when Modern Auth Clients-v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD005-O365 Block access for unsupported device platforms for All users when Modern Auth Clients-v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD006-O365 Session block download on unmanaged device for All users when Browser and Modern App Clients and Non-Compliant-v1.5.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD006-O365 Session block download on unmanaged device for All users when Browser and Modern App Clients and Non-Compliant-v1.5.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD007-O365 Session set Sign-in Frequency for Apps for All users when Modern Auth Clients and Non-Compliant-v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD007-O365 Session set Sign-in Frequency for Apps for All users when Modern Auth Clients and Non-Compliant-v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD008-All Session set Sign-in Frequency for All users when Browser and Non-Compliant-v1.1.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD008-All Session set Sign-in Frequency for All users when Browser and Non-Compliant-v1.1.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD009-All Session disable browser persistence for All users when Browser and Non-Compliant-v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD009-All Session disable browser persistence for All users when Browser and Non-Compliant-v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD010-RJD Require MFA for device join or registration when Browser and Modern Auth Clients-v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD010-RJD Require MFA for device join or registration when Browser and Modern Auth Clients-v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD011-O365 Grant Linux access for All users when Modern Auth Clients and Compliant-v1.0.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD011-O365 Grant Linux access for All users when Modern Auth Clients and Compliant-v1.0.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD012-ALL Grant access for Admin users when Browser and Modern Auth Clients and Compliant- Remember to Exclude Trusted locationsv1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD012-ALL Grant access for Admin users when Browser and Modern Auth Clients and Compliant- Remember to Exclude Trusted locationsv1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD014-O365 Require App Protection Policy for Edge on Windows for All users when Browser and Non-Compliant-v1.0.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD014-O365 Require App Protection Policy for Edge on Windows for All users when Browser and Non-Compliant-v1.0.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD015-All Grant access for All users when Browser and Modern Auth Clients and Compliant on Windows and macOS- v1.0 .json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD015-All Grant access for All users when Browser and Modern Auth Clients and Compliant on Windows and macOS- v1.0 .json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAD016-EXO_SPO Require token protection when Modern Auth Clients on Windows - v1.1.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAD016-EXO_SPO Require token protection when Modern Auth Clients on Windows - v1.1.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAL002-RSI Require MFA registration from trusted locations only for All users when Browser and Modern Auth Clients-v1.5.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAL002-RSI Require MFA registration from trusted locations only for All users when Browser and Modern Auth Clients-v1.5.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAL004-All Block access for Admins from non-trusted locations when Browser and Modern Auth Clients-v1.1.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAL004-All Block access for Admins from non-trusted locations when Browser and Modern Auth Clients-v1.1.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAL011-Allow access from Trusted Countries Only v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAL011-Allow access from Trusted Countries Only v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAP001-All Block Legacy Authentication for All users when OtherClients-v1.1.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAP001-All Block Legacy Authentication for All users when OtherClients-v1.1.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAP002-O365 Grant Exchange ActiveSync Clients for All users when Approved App-v1.0.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAP002-O365 Grant Exchange ActiveSync Clients for All users when Approved App-v1.0.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAU001-All Grant Require MFA for guests when Browser and Modern Auth Clients-v1.0.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAU001-All Grant Require MFA for guests when Browser and Modern Auth Clients-v1.0.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAU002-All Grant Require MFA for All users when Browser and Modern Auth Clients-v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAU002-All Grant Require MFA for All users when Browser and Modern Auth Clients-v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAU003-Selected Block unapproved apps for guests when Browser and Modern Auth Clients-v1.0.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAU003-Selected Block unapproved apps for guests when Browser and Modern Auth Clients-v1.0.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAU005-Selected Session route through MDCA for All users when Browser on Compliant-v1.1.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAU005-Selected Session route through MDCA for All users when Browser on Compliant-v1.1.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAU008-All Grant Require Phishing-resistant MFA for Admins when Browser and Modern Auth Clients-Test if WHFB work from BYOD-v1.4.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAU008-All Grant Require Phishing-resistant MFA for Admins when Browser and Modern Auth Clients-Test if WHFB work from BYOD-v1.4.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAU009-Management BLOCK Admin Portals for All Users when Browser and Modern Auth Clients-v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAU009-Management BLOCK Admin Portals for All Users when Browser and Modern Auth Clients-v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/CAU013-All Grant Require phishing resistant MFA for All users when Browser and Modern Auth Clients - Keep for Admins initially-v1.1.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/CAU013-All Grant Require phishing resistant MFA for All users when Browser and Modern Auth Clients - Keep for Admins initially-v1.1.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 1020 - BLOCK - Device Code Auth Flow.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 1020 - BLOCK - Device Code Auth Flow.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 1040 - BLOCK - Countries not Allowed - Remember to Update Countries.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 1040 - BLOCK - Countries not Allowed - Remember to Update Countries.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 1060 - BLOCK - Service Accounts (Trusted Locations Excluded) - Remember to add 1 service account per policy.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 1060 - BLOCK - Service Accounts (Trusted Locations Excluded) - Remember to add 1 service account per policy.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 1080 - BLOCK - Guest Access to Sensitive Apps.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 1080 - BLOCK - Guest Access to Sensitive Apps.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 1085 - BLOCK - User Access to Sensitive Apps - v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 1085 - BLOCK - User Access to Sensitive Apps - v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 1090 - BLOCK - High-Med-Risk Sign-Ins - Entra ID P2 - v1.3.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 1090 - BLOCK - High-Med-Risk Sign-Ins - Entra ID P2 - v1.3.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 1100 - BLOCK - High-Med-Risk Users - Entra ID P2 - v1.3.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 1100 - BLOCK - High-Med-Risk Users - Entra ID P2 - v1.3.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 2010 - GRANT - Low-Risk Sign-ins - Entra ID P2 - v1.3.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 2010 - GRANT - Low-Risk Sign-ins - Entra ID P2 - v1.3.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 2020 - GRANT - Low-Risk Users - Entra ID P2 - v1.3.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 2020 - GRANT - Low-Risk Users - Entra ID P2 - v1.3.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 2040 - GRANT - Terms of Use (All users) - Remember to update TOU v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 2040 - GRANT - Terms of Use (All users) - Remember to update TOU v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 2050 - GRANT - MFA for All Users - need to exclude all Admins - v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 2050 - GRANT - MFA for All Users - need to exclude all Admins - v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 2060 - GRANT - Mobile Apps and Desktop Clients - Only for fully Blocking BYOD.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 2060 - GRANT - Mobile Apps and Desktop Clients - Only for fully Blocking BYOD.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 2070 - GRANT - Mobile Device Access Requirements - v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 2070 - GRANT - Mobile Device Access Requirements - v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 3010 - SESSION - ADMINS - Persistence.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 3010 - SESSION - ADMINS - Persistence.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 3020 - SESSION - BYOD Persistence.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 3020 - SESSION - BYOD Persistence.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/GLOBAL - 3030 - SESSION - Register Security Info Requirements - v1.2.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/GLOBAL - 3030 - SESSION - Register Security Info Requirements - v1.2.json
--------------------------------------------------------------------------------
/CABaseline2025/ConditionalAccess/OVERRIDE - 0001 - GRANT - Example.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/ConditionalAccess/OVERRIDE - 0001 - GRANT - Example.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD001_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD001_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD002_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD002_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD003_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD003_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD004_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD004_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD005_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD005_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD006_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD006_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD007_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD007_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD008_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD008_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD009_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD009_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD010_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD010_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD012_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD012_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD014_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD014_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD015_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD015_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD015_Include.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD015_Include.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD016_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD016_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAD016_Include.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAD016_Include.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAL002_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAL002_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAL004_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAL004_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAP001_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAP001_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAP002_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAP002_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAU001_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAU001_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAU002_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAU002_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAU003_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAU003_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAU005_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAU005_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAU008_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAU008_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAU009_Exclude.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAU009_Exclude.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_CAU013_Include.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_CAU013_Include.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_ConAcc-Breakglass.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_ConAcc-Breakglass.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/AAD_UA_Update-Ring-02.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/AAD_UA_Update-Ring-02.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/Conditional Access Service Accounts.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/Conditional Access Service Accounts.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/Excluded from Country Block List.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/Excluded from Country Block List.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/Excluded from Device Code Auth Flow Block.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/Excluded from Device Code Auth Flow Block.json
--------------------------------------------------------------------------------
/CABaseline2025/Groups/Information Technology and Systems.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/Groups/Information Technology and Systems.json
--------------------------------------------------------------------------------
/CABaseline2025/MigrationTable.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/MigrationTable.json
--------------------------------------------------------------------------------
/CABaseline2025/NamedLocations/All Compliant Network locations.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/NamedLocations/All Compliant Network locations.json
--------------------------------------------------------------------------------
/CABaseline2025/NamedLocations/Allowed Countries.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/NamedLocations/Allowed Countries.json
--------------------------------------------------------------------------------
/CABaseline2025/NamedLocations/CCI - FortiGate VPN SSL.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/NamedLocations/CCI - FortiGate VPN SSL.json
--------------------------------------------------------------------------------
/CABaseline2025/NamedLocations/CCI JumpBox.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/NamedLocations/CCI JumpBox.json
--------------------------------------------------------------------------------
/CABaseline2025/NamedLocations/Canada and USA.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/NamedLocations/Canada and USA.json
--------------------------------------------------------------------------------
/CABaseline2025/NamedLocations/Fake Restrictive Location.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/NamedLocations/Fake Restrictive Location.json
--------------------------------------------------------------------------------
/CABaseline2025/NamedLocations/HQ - Canada.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/NamedLocations/HQ - Canada.json
--------------------------------------------------------------------------------
/CABaseline2025/NamedLocations/High-Risk Countries.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/NamedLocations/High-Risk Countries.json
--------------------------------------------------------------------------------
/CABaseline2025/NamedLocations/Service Accounts Trusted IPs.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/NamedLocations/Service Accounts Trusted IPs.json
--------------------------------------------------------------------------------
/CABaseline2025/TermsOfUse/MSFT Terms of Use.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/TermsOfUse/MSFT Terms of Use.json
--------------------------------------------------------------------------------
/CABaseline2025/TermsOfUse/Terms of Use.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/TermsOfUse/Terms of Use.json
--------------------------------------------------------------------------------
/CABaseline2025/TermsOfUse/file-sample_150kB.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/CABaseline2025/TermsOfUse/file-sample_150kB.pdf
--------------------------------------------------------------------------------
/Compliance/Archive/Find-MgGraphPermissions.ps1:
--------------------------------------------------------------------------------
1 | Find-MgGraphPermission audit
--------------------------------------------------------------------------------
/Compliance/Archive/GraphCalls.ps1:
--------------------------------------------------------------------------------
1 | # relative v1.0 URI
2 | Invoke-MgGraphRequest -Uri "v1.0/auditLogs/directoryAudits?filter=activityDateTime ge $startDate" -OutputType PSObject
3 |
4 | # absolute beta URI, special (PATCH) request method
5 | Invoke-MgGraphRequest -Method PATCH -Uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies" -Body $body
6 |
7 | # relative URI with variable instead of ID
8 | Invoke-MgGraphRequest -Uri "v1.0/groups/$($group.Id)/settings" -Method POST -Body $json -ContentType "application/json"
9 |
10 | # URI defined via positional argument
11 | Invoke-MgGraphRequest -OutputType PSObject "https://graph.microsoft.com/v1.0/devices"
12 |
13 | # non resolvable URI
14 | Invoke-MgGraphRequest -OutputType PSObject -Uri $msGraphPermissionsRequestUri
15 |
16 | # official Mg command (read operation)
17 | Get-MgApplication -ApplicationId "123456"
18 |
19 | # official Mg command (write operation)
20 | Update-MgApplication
21 |
22 | # Invoke-MSGraphRequest
23 | Invoke-MSGraphRequest -Url 'https://graph.microsoft.com/beta/servicePrincipals?$select=id'
24 |
25 | # Invoke-WebRequest
26 | Invoke-WebRequest "https://graph.microsoft.com/v1.0/devices"
27 |
28 | # Invoke-RestMethod
29 | Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/devices" -header $header
30 |
31 | # using Invoke-RestMethod alias
32 | irm -Uri "https://graph.microsoft.com/v1.0/users" -header $header
33 |
34 | # dependant function that has its own Graph API calls
35 | Remove-O365OrphanedMailbox
--------------------------------------------------------------------------------
/Compliance/Archive/Invoke-MgGraphRequestwithAccessToken copy 2.ps1:
--------------------------------------------------------------------------------
1 | # Ensure you are authenticated
2 | Connect-MgGraph -Scopes "Directory.Read.All"
3 |
4 | # Fetch organization details using the Graph cmdlet
5 | $organization = Get-MgOrganization
6 |
7 | # Output the organization details
8 | $organization | Format-List
9 |
--------------------------------------------------------------------------------
/Compliance/Archive/Logging.ps1:
--------------------------------------------------------------------------------
1 | function Log-FunctionCall {
2 | param (
3 | [string]$Message,
4 | [string]$Level = 'INFO'
5 | )
6 |
7 | $callerFunction = (Get-PSCallStack)[1].Command
8 | $formattedMessage = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [$Level] [Function: $callerFunction] $Message"
9 | Write-Host $formattedMessage
10 | }
11 |
12 | function Test-Function {
13 | Log-FunctionCall -Message "This is a test message from the function."
14 | }
15 |
16 | Test-Function
17 |
18 |
19 |
20 |
21 | class Logger {
22 | [void] LogClassCall([string]$Message, [string]$Level = 'INFO') {
23 | $callerFunction = (Get-PSCallStack)[1].Command
24 | $callerClass = $this.GetType().Name
25 | $formattedMessage = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [$Level] [Class: $callerClass] [Function: $callerFunction] $Message"
26 | Write-Host $formattedMessage
27 | }
28 | }
29 |
30 | class TestClass {
31 | [Logger]$logger
32 |
33 | TestClass() {
34 | $this.logger = [Logger]::new()
35 | }
36 |
37 | [void] TestMethod() {
38 | $this.logger.LogClassCall("This is a test message from the class method.", "INFO")
39 | }
40 | }
41 |
42 | $testInstance = [TestClass]::new()
43 | $testInstance.TestMethod()
44 |
--------------------------------------------------------------------------------
/Compliance/Archive/Ondrej-Sebela-doitpshway copy 2.ps1:
--------------------------------------------------------------------------------
1 | #the following does not work keeps returning
2 |
3 |
4 | # WARNING: Command's Invoke-MgGraphRequest definition is missing. Skip getting its dependencies
5 | # WARNING: Command's Invoke-MgGraphRequest definition is missing. Skip getting its dependencies
6 | # WARNING: Command's Invoke-MgGraphRequest definition is missing. Skip getting its dependencies
7 | # WARNING: Command's Invoke-MgGraphRequest definition is missing. Skip getting its dependencies
8 | # WARNING: Command's Invoke-MgGraphRequest definition is missing. Skip getting its dependencies
9 | # WARNING: Command's Get-MgApplication definition is missing. Skip getting its dependencies
10 | # WARNING: Command's Update-MgApplication definition is missing. Skip getting its dependencies
11 | # WARNING: Unable to find command 'Invoke-MSGraphRequest' (source: ) details. Skip getting its dependencies
12 | # InvalidOperation: Cannot index into a null array.
13 | # InvalidOperation: Cannot index into a null array.
14 | # InvalidOperation: Cannot index into a null array.
15 | # WARNING: Unable to find command 'Remove-O365OrphanedMailbox' (source: ) details. Skip getting its dependencies
16 | # WARNING: 'Find-MgGraphCommand' was unable to find command ''?!
17 | # WARNING: Be noted that it is impossible to tell whether found permissions for some command are all required, or just some subset of them (for least-privileged access). Consult the Microsoft Graph Permissions Reference documentation to identify the least-privileged permission for your use case :(
18 |
19 | # # Ensure required modules are installed
20 | # Install-Module -Name MSGraphStuff -Scope Allusers -Force -AllowClobber
21 | # Install-Module -Name DependencySearch -Scope Allusers -Force -AllowClobber
22 | # Install-Module -Name Microsoft.Graph.Authentication -Scope Allusers -Force -AllowClobber
23 | # Install-Module -Name Microsoft.Graph.Reports -Scope Allusers -Force -AllowClobber
24 | # Install-Module -Name Microsoft.Graph.Users -Scope Allusers -Force -AllowClobber
25 |
26 | # Load the necessary modules
27 | Import-Module MSGraphStuff
28 | Import-Module DependencySearch
29 | Import-Module Microsoft.Graph.Authentication
30 | Import-Module Microsoft.Graph.Reports
31 | Import-Module Microsoft.Graph.Users
32 |
33 | # Example code that includes the URI we want to check using a recognized command
34 | # Example code that includes a recognized command
35 | # $codeToCheck = @"
36 | # Get-MgUser -UserId 'user@example.com'
37 | # "@
38 |
39 | # Write the example code to a temporary file
40 | # $tempScriptPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "tempGraphScript.ps1")
41 | # Set-Content -Path $tempScriptPath -Value $codeToCheck
42 |
43 | # Cache available modules to speed up repeated 'Get-CodeGraphPermissionRequirement' function invocations
44 | $availableModules = @(Get-Module -ListAvailable)
45 |
46 | # Get the required permissions for the example code
47 | # $permissions = Get-CodeGraphPermissionRequirement -scriptPath $tempScriptPath -goDeep -availableModules $availableModules -permType "application", "delegated"
48 | $permissions = Get-CodeGraphPermissionRequirement -scriptPath "C:\Code\CB\Entra\ICTC\Entra\Devices\Beta\GraphCalls.ps1" -goDeep -availableModules $availableModules -permType "application", "delegated"
49 |
50 | # Output the permissions
51 | $permissions | Out-GridView
52 |
53 | # Clean up the temporary file
54 | # Remove-Item -Path $tempScriptPath
--------------------------------------------------------------------------------
/Compliance/Archive/Ondrej-Sebela-doitpshway copy.ps1:
--------------------------------------------------------------------------------
1 | # # Ensure required modules are installed
2 | Install-Module -Name MSGraphStuff -Scope Allusers -Force -AllowClobber
3 | Install-Module -Name DependencySearch -Scope Allusers -Force -AllowClobber
4 | Install-Module -Name Microsoft.Graph.Authentication -Scope Allusers -Force -AllowClobber
5 |
6 | # Load the necessary modules
7 | Import-Module MSGraphStuff
8 | Import-Module DependencySearch
9 | Import-Module Microsoft.Graph.Authentication
10 |
11 | # Example code that includes the URI we want to check
12 | $codeToCheck = @"
13 | Invoke-MgGraphRequest -Uri 'https://graph.microsoft.com/v1.0/auditLogs/signIns' -Method Get
14 | "@
15 |
16 | # Write the example code to a temporary file
17 | $tempScriptPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "tempGraphScript.ps1")
18 | Set-Content -Path $tempScriptPath -Value $codeToCheck
19 |
20 | # Cache available modules to speed up repeated 'Get-CodeGraphPermissionRequirement' function invocations
21 | $availableModules = @(Get-Module -ListAvailable)
22 |
23 | # Get the required permissions for the example code
24 | $permissions = Get-CodeGraphPermissionRequirement -scriptPath $tempScriptPath -goDeep -availableModules $availableModules -permType "application", "delegated"
25 |
26 | # Output the permissions
27 | $permissions | Out-GridView
28 |
29 | # Clean up the temporary file
30 | Remove-Item -Path $tempScriptPath
31 |
--------------------------------------------------------------------------------
/Compliance/Archive/Ondrej-Sebela-doitpshway.ps1:
--------------------------------------------------------------------------------
1 | # Install MSGraphStuff module from the PowerShell Gallery
2 | Install-Module -Name MSGraphStuff -Scope AllUsers -Force -AllowClobber
3 |
4 | # Example code that includes the URI we want to check
5 | $codeToCheck = @"
6 | Invoke-RestMethod -Uri 'https://graph.microsoft.com/v1.0/auditLogs/signIns' -Method Get
7 | "@
8 |
9 | # Write the example code to a temporary file
10 | $tempScriptPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "tempGraphScript.ps1")
11 | Set-Content -Path $tempScriptPath -Value $codeToCheck
12 |
13 | # Load the MSGraphStuff module
14 | Import-Module MSGraphStuff
15 |
16 | # Get the required permissions for the example code
17 | $permissions = Get-CodeGraphPermissionRequirement -scriptPath $tempScriptPath -permType "application", "delegated"
18 |
19 | # Output the permissions
20 | $permissions | Out-GridView
21 |
22 | # Clean up the temporary file
23 | Remove-Item -Path $tempScriptPath
24 |
--------------------------------------------------------------------------------
/Compliance/Archive/helloworld.psm1:
--------------------------------------------------------------------------------
1 | function Get-Greeting {
2 | param (
3 | [string]$Name
4 | )
5 | return "Bonjour, $Name!"
6 | }
--------------------------------------------------------------------------------
/Compliance/Archive/test-LINQ-v2.ps1:
--------------------------------------------------------------------------------
1 | # Define the class
2 | class SignInLog {
3 | [string] $userDisplayName
4 | [string] $deviceId
5 | }
6 |
7 | # Path to the JSON file
8 | $JsonFilePath = "C:\log.json"
9 |
10 | # Initialize a list to store the filtered log objects
11 | $logList = [System.Collections.Generic.List[SignInLog]]::new()
12 |
13 | # Open the JSON file and create a JsonTextReader
14 | $reader = [System.IO.StreamReader]::new($JsonFilePath)
15 | $jsonReader = [Newtonsoft.Json.JsonTextReader]::new($reader)
16 |
17 | # Read and process the JSON file incrementally
18 | while ($jsonReader.Read()) {
19 | if ($jsonReader.TokenType -eq [Newtonsoft.Json.JsonToken]::StartObject) {
20 | $jObject = [Newtonsoft.Json.Linq.JObject]::Load($jsonReader)
21 | $userDisplayName = $jObject["userDisplayName"]
22 | $deviceId = $jObject["deviceDetail"]["deviceId"]
23 |
24 | if ($userDisplayName -ne "On-Premises Directory Synchronization Service Account") {
25 | $signInLog = [SignInLog]::new()
26 | $signInLog.userDisplayName = [string]$userDisplayName
27 | $signInLog.deviceId = [string]$deviceId
28 | $logList.Add($signInLog)
29 | }
30 | }
31 | }
32 |
33 | # # Output the filtered logs
34 | # $logList | ForEach-Object {
35 | # Write-Host "User: $($_.userDisplayName), Device ID: $($_.deviceId)"
36 | # }
37 |
--------------------------------------------------------------------------------
/Compliance/Archive/test-LINQ-v3.ps1:
--------------------------------------------------------------------------------
1 | # Define the class
2 | class SignInLog {
3 | [string] $userDisplayName
4 | [string] $deviceId
5 | }
6 |
7 | # Path to the JSON file
8 | $JsonFilePath = "C:\log.json"
9 |
10 | # Initialize a list to store the filtered log objects
11 | $logList = [System.Collections.Generic.List[SignInLog]]::new()
12 |
13 | # Open the JSON file and create a JsonDocument
14 | $fileStream = [System.IO.File]::OpenRead($JsonFilePath)
15 |
16 | try {
17 | # Read and process the JSON file incrementally
18 | $jsonDoc = [System.Text.Json.JsonDocument]::Parse($fileStream)
19 |
20 | foreach ($element in $jsonDoc.RootElement.EnumerateArray()) {
21 | $userDisplayName = $element.GetProperty("userDisplayName").GetString()
22 | $deviceId = $element.GetProperty("deviceDetail").GetProperty("deviceId").GetString()
23 |
24 | if ($userDisplayName -ne "On-Premises Directory Synchronization Service Account") {
25 | $signInLog = [SignInLog]::new()
26 | $signInLog.userDisplayName = $userDisplayName
27 | $signInLog.deviceId = $deviceId
28 | $logList.Add($signInLog)
29 | }
30 | }
31 |
32 | # Output the filtered logs
33 | # $logList | ForEach-Object {
34 | # Write-Host "User: $($_.userDisplayName), Device ID: $($_.deviceId)"
35 | # }
36 | }
37 | finally {
38 | # Clean up
39 | $fileStream.Dispose()
40 | }
41 |
--------------------------------------------------------------------------------
/Compliance/Archive/test-LINQ.ps1:
--------------------------------------------------------------------------------
1 | # Define the class
2 | class SignInLog {
3 | [string] $userDisplayName
4 | [string] $deviceId
5 | }
6 |
7 | # Path to the JSON file
8 | $JsonFilePath = "C:\log.json"
9 |
10 | # Load the JSON file
11 | $reader = [System.IO.StreamReader]::new($JsonFilePath)
12 | $jarray = [Newtonsoft.Json.Linq.JArray]::Load([NewtonSoft.Json.JsonTextReader]$reader)
13 |
14 | # Filter out specific users and create instances of SignInLog
15 | $filteredLogs = $jarray.SelectTokens('$..[?(@.userDisplayName != ''On-Premises Directory Synchronization Service Account'')]')
16 |
17 | # Initialize a list to store the filtered log objects
18 | $logList = [System.Collections.Generic.List[SignInLog]]::new()
19 |
20 | # Convert filtered JSON tokens to SignInLog objects
21 | foreach ($log in $filteredLogs) {
22 | $userDisplayName = [string]$log.userDisplayName
23 | $deviceId = [string]$log.deviceDetail.deviceId
24 | $signInLog = [SignInLog]::new()
25 | $signInLog.userDisplayName = $userDisplayName
26 | $signInLog.deviceId = $deviceId
27 | $logList.Add($signInLog)
28 | }
29 |
30 | # Output the filtered logs
31 | # $logList | ForEach-Object {
32 | # Write-Host "User: $($_.userDisplayName), Device ID: $($_.deviceId)"
33 | # }
34 |
--------------------------------------------------------------------------------
/Compliance/Archive/test-Parallel-v2.ps1:
--------------------------------------------------------------------------------
1 | # Example JSON data
2 | $Json = @(
3 | @{userDisplayName = 'User1'; userPrincipalName = 'user1@example.com'},
4 | @{userDisplayName = 'On-Premises Directory Synchronization Service Account'; userPrincipalName = 'sync@example.com'},
5 | @{userDisplayName = 'User2'; userPrincipalName = 'user2@example.com'}
6 | )
7 |
8 | # Convert the array to JSON and then back to an array of PSCustomObjects to simulate receiving JSON data
9 | $JsonData = $Json | ConvertTo-Json | ConvertFrom-Json
10 |
11 | # Process the JSON data in parallel
12 | $JsonData | ForEach-Object -Parallel {
13 | # Simulate some processing for each user
14 | $user = $_
15 | $result = [PSCustomObject]@{
16 | UserDisplayName = $user.userDisplayName
17 | UserPrincipalName = $user.userPrincipalName
18 | ProcessedTime = (Get-Date).ToString()
19 | }
20 | # Output the result
21 | $result
22 | } -ThrottleLimit 4
23 |
--------------------------------------------------------------------------------
/Compliance/Archive/test-Parallel.ps1:
--------------------------------------------------------------------------------
1 | # Define a function that uses ForEach-Object -Parallel
2 | function Demo-ParallelScriptRoot {
3 | param (
4 | [Parameter(Mandatory = $true)]
5 | [string]$ScriptRoot
6 | )
7 |
8 | # Example array to iterate over
9 | $array = 1..5
10 |
11 | # Use ForEach-Object -Parallel
12 | $array | ForEach-Object -Parallel {
13 | # Use $using: scope to pass $ScriptRoot
14 | $localScriptRoot = $using:ScriptRoot
15 | Write-Output "Script Root in parallel block: $localScriptRoot"
16 | } -ThrottleLimit 2
17 | }
18 |
19 | # Call the function
20 | Demo-ParallelScriptRoot -ScriptRoot $PSScriptRoot
21 |
--------------------------------------------------------------------------------
/Compliance/Archive/tests/Async.Logging.PSF.test.ps1:
--------------------------------------------------------------------------------
1 | # Enable asynchronous logging in PSFramework
2 | Set-PSFConfig -FullName PSFramework.Logging.FileSystem.Asynchronous -Value $true -PassThru | Register-PSFConfig
3 |
4 |
5 | # Example of logging a message
6 | Write-PSFMessage -Level 'Debug' -Message "This is a Debug message."
7 |
--------------------------------------------------------------------------------
/Compliance/Archive/tests/GetLatestVersion.Choco.test.ps1:
--------------------------------------------------------------------------------
1 | # $mode = $env:EnvironmentMode
2 |
3 | #region FIRING UP MODULE STARTER
4 | #################################################################################################
5 | # #
6 | # FIRING UP MODULE STARTER #
7 | # #
8 | #################################################################################################
9 |
10 |
11 | Invoke-Expression (Invoke-RestMethod "https://raw.githubusercontent.com/aollivierre/module-starter/main/Install-EnhancedModuleStarterAO.ps1")
12 |
13 | # Define a hashtable for splatting
14 | $moduleStarterParams = @{
15 | Mode = 'dev'
16 | SkipPSGalleryModules = $true
17 | SkipCheckandElevate = $true
18 | SkipPowerShell7Install = $true
19 | SkipEnhancedModules = $true
20 | SkipGitRepos = $true
21 | # ExecutionMode = 'Parallel'
22 | }
23 |
24 | # Call the function using the splat
25 | Invoke-ModuleStarter @moduleStarterParams
26 |
27 | #endregion FIRING UP MODULE STARTER
28 |
29 |
30 | # Example usage with pipeline support
31 | # 'GoogleChrome', 'MicrosoftEdge', 'Firefox' | Get-LatestChocoVersion
32 |
33 |
34 | # Example usage
35 | $apps = 'GoogleChrome', 'MicrosoftEdge', 'Firefox'
36 | $apps | Get-LatestChocoVersion
--------------------------------------------------------------------------------
/Compliance/Archive/tests/GetLatestVersion.Winget.test.ps1:
--------------------------------------------------------------------------------
1 | # $mode = $env:EnvironmentMode
2 |
3 | #region FIRING UP MODULE STARTER
4 | #################################################################################################
5 | # #
6 | # FIRING UP MODULE STARTER #
7 | # #
8 | #################################################################################################
9 |
10 |
11 | # Invoke-Expression (Invoke-RestMethod "https://raw.githubusercontent.com/aollivierre/module-starter/main/Install-EnhancedModuleStarterAO.ps1")
12 |
13 | # Define a hashtable for splatting
14 | # $moduleStarterParams = @{
15 | # Mode = 'dev'
16 | # SkipPSGalleryModules = $true
17 | # SkipCheckandElevate = $true
18 | # SkipPowerShell7Install = $true
19 | # SkipEnhancedModules = $true
20 | # SkipGitRepos = $true
21 | # # ExecutionMode = 'Parallel'
22 | # }
23 |
24 | # Call the function using the splat
25 | # Invoke-ModuleStarter @moduleStarterParams
26 |
27 | #endregion FIRING UP MODULE STARTER
28 |
29 |
30 |
31 | import-module 'C:\code\Modulesv2\EnhancedModuleStarterAO\EnhancedModuleStarterAO.psm1' -Force
32 |
33 |
34 | # $params = @{
35 | # id = "7zip.7zip"
36 | # # TargetVersion = "24.8.0.0"
37 | # AcceptNewerVersion = $true
38 | # }
39 |
40 | # $result = Get-LatestWinGetVersion @params
41 | # $result | Format-List
42 |
43 |
44 |
45 |
46 | $params = @{
47 | id = "Microsoft.PowerShell"
48 | AcceptNewerVersion = $true
49 | }
50 |
51 | $result = Get-LatestWinGetVersion @params
52 | $result | Format-List
53 |
54 |
55 |
56 | # # Example usage:
57 | # $params = @{
58 | # id = "7zip.7zip"
59 | # TargetVersion = ""
60 | # AcceptNewerVersion = $true
61 | # }
62 | # $latestVersion = Get-LatestWinGetVersion @params
63 | # if ($latestVersion) {
64 | # Write-Host "Latest version installed: $latestVersion"
65 | # } else {
66 | # Write-Host "Latest version is not installed or not found."
67 | # }
--------------------------------------------------------------------------------
/Compliance/Archive/tests/validatesoftware.test copy.ps1:
--------------------------------------------------------------------------------
1 | # $mode = $env:EnvironmentMode
2 |
3 | #region FIRING UP MODULE STARTER
4 | #################################################################################################
5 | # #
6 | # FIRING UP MODULE STARTER #
7 | # #
8 | #################################################################################################
9 |
10 |
11 | # Invoke-Expression (Invoke-RestMethod "https://raw.githubusercontent.com/aollivierre/module-starter/main/Install-EnhancedModuleStarterAO.ps1")
12 |
13 | # Define a hashtable for splatting
14 | # $moduleStarterParams = @{
15 | # Mode = 'dev'
16 | # SkipPSGalleryModules = $true
17 | # SkipCheckandElevate = $true
18 | # SkipPowerShell7Install = $true
19 | # SkipEnhancedModules = $true
20 | # SkipGitRepos = $true
21 | # ExecutionMode = 'Parallel'
22 | # }
23 |
24 | # Call the function using the splat
25 | # Invoke-ModuleStarter @moduleStarterParams
26 |
27 | # Define replacements in a hashtable
28 | # $replacements = @{
29 | # '\$Mode = "dev"' = '$Mode = "dev"'
30 | # '\$SkipPSGalleryModules = \$false' = '$SkipPSGalleryModules = $true'
31 | # '\$SkipCheckandElevate = \$false' = '$SkipCheckandElevate = $true'
32 | # '\$SkipAdminCheck = \$false' = '$SkipAdminCheck = $true'
33 | # '\$SkipPowerShell7Install = \$false' = '$SkipPowerShell7Install = $true'
34 | # '\$SkipModuleDownload = \$false' = '$SkipModuleDownload = $true'
35 | # '\$SkipGitrepos = \$false' = '$SkipGitrepos = $true'
36 | # }
37 |
38 | # # Apply the replacements
39 | # foreach ($pattern in $replacements.Keys) {
40 | # $scriptContent = $scriptContent -replace $pattern, $replacements[$pattern]
41 | # }
42 |
43 | # # Execute the script
44 | # Invoke-Expression $scriptContent
45 |
46 |
47 |
48 |
49 |
50 |
51 | # function Set-ScriptModeToDev {
52 | # # [CmdletBinding()]
53 | # # param (
54 | # # [Parameter(Mandatory = $true)]
55 | # # [string]$ScriptContent
56 | # # )
57 |
58 | # $scriptContent = Invoke-RestMethod "https://raw.githubusercontent.com/aollivierre/module-starter/main/Module-Starter.ps1"
59 |
60 | # # Ensure TLS 1.2 is used for all web requests
61 | # [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
62 |
63 | # # Define replacements in a hashtable
64 | # $replacements = @{
65 | # '\$Mode = "dev"' = '$Mode = "dev"'
66 | # '\$SkipPSGalleryModules = \$false' = '$SkipPSGalleryModules = $true'
67 | # '\$SkipCheckandElevate = \$false' = '$SkipCheckandElevate = $true'
68 | # '\$SkipAdminCheck = \$false' = '$SkipAdminCheck = $true'
69 | # '\$SkipPowerShell7Install = \$false' = '$SkipPowerShell7Install = $true'
70 | # '\$SkipModuleDownload = \$false' = '$SkipModuleDownload = $true'
71 | # '\$SkipGitrepos = \$false' = '$SkipGitrepos = $true'
72 | # }
73 |
74 | # # Apply the replacements
75 | # foreach ($pattern in $replacements.Keys) {
76 | # $ScriptContent = $ScriptContent -replace $pattern, $replacements[$pattern]
77 | # }
78 |
79 | # # Execute the script
80 | # Invoke-Expression $ScriptContent
81 | # }
82 |
83 | # Example usage:
84 | # Set-ScriptModeToDev
85 |
86 |
87 | import-module 'C:\code\Modulesv2\EnhancedModuleStarterAO\EnhancedModuleStarterAO.psm1' -Force
88 |
89 |
90 |
91 | #endregion FIRING UP MODULE STARTER
92 |
93 |
94 | # . "C:\code\IntuneDeviceMigration\DeviceMigration\PSAppDeployToolkit\Toolkit\AppDeployToolkit\AppDeployToolkitMain.ps1"
95 |
96 | # $validationParams = @{
97 | # SoftwareName = "Git"
98 | # MinVersion = [version]"2.46.0"
99 | # RegistryPath = "HKLM:\SOFTWARE\GitForWindows"
100 | # ExePath = "C:\Program Files\Git\bin\git.exe"
101 | # MaxRetries = 3 # Single retry after installation
102 | # DelayBetweenRetries = 5
103 | # }
104 |
105 | # Validate-SoftwareInstallation @validationParams
106 |
107 |
108 | # $params = @{
109 | # SoftwareName = '7-Zip'
110 | # MinVersion = [version] "19.0.0.0"
111 | # LatestVersion = [version] "22.1.0.0"
112 | # RegistryPath = 'HKLM:\SOFTWARE\7-Zip'
113 | # ExePath = 'C:\Program Files\7-Zip\7z.exe'
114 | # MaxRetries = 1
115 | # DelayBetweenRetries = 5
116 | # }
117 |
118 | # Validate-SoftwareInstallation @params
119 |
120 |
121 |
122 |
123 | function Check-7ZipInstallation {
124 | param (
125 | [string]$CustomRegistryPath = "HKLM:\SOFTWARE\7-Zip",
126 | [string]$LogFilePath = "C:\Logs\7ZipCheck.log"
127 | )
128 |
129 | Begin {
130 | # Initialize log file
131 | $logMessage = "Checking 7-Zip installation..." | Out-String
132 | Write-EnhancedLog -Message $logMessage -Level "INFO" -FilePath $LogFilePath
133 |
134 | # Define registry paths to check
135 | $registryPaths = @(
136 | "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
137 | "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
138 | $CustomRegistryPath
139 | )
140 |
141 | # Initialize result variable
142 | $sevenZipVersion = $null
143 | }
144 |
145 | Process {
146 | foreach ($registryPath in $registryPaths) {
147 | try {
148 | # Get all installed software in the current registry path
149 | $subkeys = Get-ChildItem -Path $registryPath -ErrorAction Stop
150 |
151 | foreach ($subkey in $subkeys) {
152 | # Check if 7-Zip is installed
153 | $displayName = (Get-ItemProperty -Path $subkey.PSPath -Name DisplayName -ErrorAction SilentlyContinue).DisplayName
154 | if ($displayName -like "*7-Zip*") {
155 | $sevenZipVersion = (Get-ItemProperty -Path $subkey.PSPath -Name DisplayVersion -ErrorAction SilentlyContinue).DisplayVersion
156 | Write-EnhancedLog -Message "7-Zip found in '$registryPath' with version $sevenZipVersion." -Level "INFO" -FilePath $LogFilePath
157 | break
158 | }
159 | }
160 |
161 | if ($sevenZipVersion) {
162 | break
163 | }
164 | } catch {
165 | Write-EnhancedLog -Message "Failed to access registry path: $registryPath. Error: $_" -Level "ERROR" -FilePath $LogFilePath
166 | }
167 | }
168 | }
169 |
170 | End {
171 | if ($sevenZipVersion) {
172 | Write-EnhancedLog -Message "7-Zip version $sevenZipVersion is installed." -Level "NOTICE" -FilePath $LogFilePath
173 | return $true
174 | } else {
175 | Write-EnhancedLog -Message "7-Zip is not installed." -Level "WARNING" -FilePath $LogFilePath
176 | return $false
177 | }
178 | }
179 | }
180 |
181 | # Example usage:
182 | $checkResult = Check-7ZipInstallation -CustomRegistryPath "HKLM:\SOFTWARE\7-Zip" -LogFilePath "C:\Logs\7ZipCheck.log"
183 |
184 | if ($checkResult -eq $false) {
185 | Write-Host "7-Zip is not installed on this machine." -ForegroundColor Red
186 | exit 1
187 | } else {
188 | Write-Host "7-Zip is installed." -ForegroundColor Green
189 | exit 0
190 | }
191 |
192 |
193 |
194 |
195 | # $params = @{
196 | # SoftwareName = 'notepad++'
197 | # MinVersion = [version] "19.0.0.0"
198 | # LatestVersion = [version] "22.1.0.0"
199 | # # RegistryPath = 'HKLM:\SOFTWARE\7-Zip'
200 | # # ExePath = 'C:\Program Files\7-Zip\7z.exe'
201 | # MaxRetries = 3
202 | # DelayBetweenRetries = 5
203 | # }
204 |
205 | # Validate-SoftwareInstallation @params
206 |
--------------------------------------------------------------------------------
/Compliance/Benchmarking/1-Get-Content and ConvertFrom-Json.ps1:
--------------------------------------------------------------------------------
1 | # Method 1: Using Get-Content and ConvertFrom-Json
2 | function Process-Json-GetContent {
3 | param (
4 | [string]$JsonFilePath
5 | )
6 |
7 | $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
8 |
9 | $jsonContent = Get-Content -Path $JsonFilePath -Raw
10 | $jsonData = $jsonContent | ConvertFrom-Json
11 |
12 | # Simulate processing
13 | $jsonData.Count
14 |
15 | $stopwatch.Stop()
16 | Write-Host "Method 1: Get-Content and ConvertFrom-Json took $($stopwatch.Elapsed.TotalMilliseconds) ms"
17 | }
18 |
19 | # Usage
20 | Process-Json-GetContent -JsonFilePath "C:\log.json"
--------------------------------------------------------------------------------
/Compliance/Benchmarking/2-System.IO.StreamReader and ConvertFrom-Json.ps1:
--------------------------------------------------------------------------------
1 | # Method 2: Using System.IO.StreamReader and ConvertFrom-Json
2 | function Process-Json-StreamReader {
3 | param (
4 | [string]$JsonFilePath
5 | )
6 |
7 | $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
8 |
9 | $streamReader = [System.IO.StreamReader]::new($JsonFilePath)
10 | $jsonContent = $streamReader.ReadToEnd()
11 | $streamReader.Close()
12 | $jsonData = $jsonContent | ConvertFrom-Json
13 |
14 | # Simulate processing
15 | $jsonData.Count
16 |
17 | $stopwatch.Stop()
18 | Write-Host "Method 2: StreamReader and ConvertFrom-Json took $($stopwatch.Elapsed.TotalMilliseconds) ms"
19 | }
20 |
21 | # Usage
22 | Process-Json-StreamReader -JsonFilePath "C:\log.json"
--------------------------------------------------------------------------------
/Compliance/Benchmarking/3-System.Text.Json.JsonDocument.ps1:
--------------------------------------------------------------------------------
1 | # Load System.Text.Json assembly
2 | Add-Type -AssemblyName System.Text.Json
3 |
4 | # Method 3: Using System.Text.Json.JsonDocument
5 | function Process-Json-JsonDocument {
6 | param (
7 | [string]$JsonFilePath
8 | )
9 |
10 | $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
11 |
12 | $fileStream = [System.IO.File]::OpenRead($JsonFilePath)
13 | $jsonDoc = [System.Text.Json.JsonDocument]::Parse($fileStream)
14 |
15 | # Simulate processing
16 | $elementCount = $jsonDoc.RootElement.GetArrayLength()
17 |
18 | $fileStream.Close()
19 |
20 | $stopwatch.Stop()
21 | Write-Host "Method 3: System.Text.Json.JsonDocument took $($stopwatch.Elapsed.TotalMilliseconds) ms"
22 | }
23 |
24 | # Usage
25 | Process-Json-JsonDocument -JsonFilePath "C:\log.json"
--------------------------------------------------------------------------------
/Compliance/Benchmarking/4-System.Text.Json.JsonDocument.ps1:
--------------------------------------------------------------------------------
1 | # Load System.Text.Json assembly
2 | Add-Type -AssemblyName System.Text.Json
3 |
4 | # Method 4: Using System.Text.Json.JsonDocument with an Efficient File Open
5 | function Process-Json-JsonDocument {
6 | param (
7 | [string]$JsonFilePath
8 | )
9 |
10 | $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
11 |
12 | # Open the file using FileStream with buffering and SequentialScan
13 | $fileStream = [System.IO.FileStream]::new($JsonFilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read, 4096, [System.IO.FileOptions]::SequentialScan)
14 | $jsonDoc = [System.Text.Json.JsonDocument]::Parse($fileStream)
15 |
16 | # Simulate processing
17 | $elementCount = $jsonDoc.RootElement.GetArrayLength()
18 |
19 | $fileStream.Close()
20 |
21 | $stopwatch.Stop()
22 | Write-Host "Method 4: System.Text.Json.JsonDocument with system.io.filestream took $($stopwatch.Elapsed.TotalMilliseconds) ms"
23 | }
24 |
25 | # Usage
26 | Process-Json-JsonDocument -JsonFilePath "C:\log.json"
--------------------------------------------------------------------------------
/Compliance/Benchmarking/5-compare-json-file-read.ps1:
--------------------------------------------------------------------------------
1 | # Load System.Text.Json assembly
2 | Add-Type -AssemblyName System.Text.Json
3 |
4 | # Method 3: Using System.Text.Json.JsonDocument
5 | function Process-Json-JsonDocument-Method3 {
6 | param (
7 | [string]$JsonFilePath
8 | )
9 |
10 | $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
11 |
12 | $fileStream = [System.IO.File]::OpenRead($JsonFilePath)
13 | $jsonDoc = [System.Text.Json.JsonDocument]::Parse($fileStream)
14 |
15 | # Simulate processing
16 | $elementCount = $jsonDoc.RootElement.GetArrayLength()
17 |
18 | $fileStream.Close()
19 |
20 | $stopwatch.Stop()
21 | return $stopwatch.Elapsed.TotalMilliseconds
22 | }
23 |
24 | # Method 4: Using System.Text.Json.JsonDocument with an Efficient File Open
25 | function Process-Json-JsonDocument-Method4 {
26 | param (
27 | [string]$JsonFilePath
28 | )
29 |
30 | $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
31 |
32 | # Open the file using FileStream with buffering and SequentialScan
33 | $fileStream = [System.IO.FileStream]::new($JsonFilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read, 4096, [System.IO.FileOptions]::SequentialScan)
34 | $jsonDoc = [System.Text.Json.JsonDocument]::Parse($fileStream)
35 |
36 | # Simulate processing
37 | $elementCount = $jsonDoc.RootElement.GetArrayLength()
38 |
39 | $fileStream.Close()
40 |
41 | $stopwatch.Stop()
42 | return $stopwatch.Elapsed.TotalMilliseconds
43 | }
44 |
45 | # Run each method 100 times and record the elapsed times
46 | $resultsMethod3 = @()
47 | $resultsMethod4 = @()
48 | $JsonFilePath = "C:\log.json"
49 |
50 | for ($i = 0; $i -lt 100; $i++) {
51 | $resultsMethod3 += Process-Json-JsonDocument-Method3 -JsonFilePath $JsonFilePath
52 | $resultsMethod4 += Process-Json-JsonDocument-Method4 -JsonFilePath $JsonFilePath
53 | }
54 |
55 | # Calculate average times
56 | $averageTimeMethod3 = ($resultsMethod3 | Measure-Object -Average).Average
57 | $averageTimeMethod4 = ($resultsMethod4 | Measure-Object -Average).Average
58 |
59 | # Display results
60 | Write-Host "Method 3: Average time using System.Text.Json.JsonDocument took $averageTimeMethod3 ms"
61 | Write-Host "Method 4: Average time using System.Text.Json.JsonDocument with FileStream took $averageTimeMethod4 ms"
62 |
63 |
64 |
65 |
66 |
67 |
68 | # $code = @"
69 | # using System;
70 | # using System.IO;
71 | # using System.Text.Json;
72 |
73 | # public class JsonProcessor
74 | # {
75 | # public static long ProcessJson(string jsonFilePath)
76 | # {
77 | # var stopwatch = System.Diagnostics.Stopwatch.StartNew();
78 |
79 | # using (FileStream fileStream = new FileStream(jsonFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan))
80 | # {
81 | # byte[] buffer = new byte[4096];
82 | # int bytesRead;
83 | # long elementCount = 0;
84 |
85 | # while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
86 | # {
87 | # var jsonReader = new Utf8JsonReader(buffer.AsSpan(0, bytesRead), isFinalBlock: bytesRead < buffer.Length, state: default);
88 |
89 | # while (jsonReader.Read())
90 | # {
91 | # if (jsonReader.TokenType == JsonTokenType.StartObject)
92 | # {
93 | # elementCount++;
94 | # }
95 | # }
96 | # }
97 |
98 | # stopwatch.Stop();
99 | # Console.WriteLine($"Utf8JsonReader took {stopwatch.Elapsed.TotalMilliseconds} ms, processed {elementCount} elements");
100 | # return stopwatch.ElapsedMilliseconds;
101 | # }
102 | # }
103 | # }
104 | # "@
105 |
106 |
107 |
108 |
109 | # # Compile the C# code
110 | # Add-Type -TypeDefinition $code -Language CSharp
111 |
112 | # # Define the PowerShell function to call the C# method
113 | # function Process-Json-Utf8JsonReader {
114 | # param (
115 | # [string]$JsonFilePath
116 | # )
117 |
118 | # return [JsonProcessor]::ProcessJson($JsonFilePath)
119 | # }
120 |
121 | # # Run the method 100 times and record the elapsed times
122 | # $resultsMethod5 = @()
123 | # $JsonFilePath = "C:\log.json"
124 |
125 | # for ($i = 0; $i -lt 100; $i++) {
126 | # $resultsMethod5 += Process-Json-Utf8JsonReader -JsonFilePath $JsonFilePath
127 | # }
128 |
129 | # # Calculate average time
130 | # $averageTimeMethod5 = ($resultsMethod5 | Measure-Object -Average).Average
131 |
132 | # # Display results
133 | # Write-Host "Method 5: Average time using System.Text.Json.Utf8JsonReader took $averageTimeMethod5 ms"
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/Compliance/Benchmarking/Test-DataStructures.ps1:
--------------------------------------------------------------------------------
1 | # Helper function to measure execution time
2 | function Measure-ExecutionTime {
3 | param (
4 | [scriptblock]$Code,
5 | [int]$Iterations = 100
6 | )
7 | $totalTime = [timespan]::Zero
8 | for ($i = 0; $i -lt $Iterations; $i++) {
9 | $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
10 | & $Code
11 | $stopwatch.Stop()
12 | $totalTime += $stopwatch.Elapsed
13 | }
14 | return $totalTime.TotalMilliseconds / $Iterations
15 | }
16 |
17 | # Helper function to parse JSON data
18 | function Parse-JsonData {
19 | param (
20 | [string]$JsonData
21 | )
22 | $jsonData = $JsonData.Trim()
23 | if ($jsonData.StartsWith('[') -and $jsonData.EndsWith(']')) {
24 | return $jsonData | ConvertFrom-Json
25 | }
26 | elseif ($jsonData.StartsWith('{') -and $jsonData.EndsWith('}')) {
27 | return , $jsonData | ConvertFrom-Json
28 | }
29 | else {
30 | Write-Warning "Invalid JSON data encountered: $jsonData"
31 | return $null
32 | }
33 | }
34 |
35 | # Method 1: Using Array
36 | function Process-SignInLogs-Array {
37 | param (
38 | [string]$JsonFilePath
39 | )
40 | $uniqueIds = @()
41 | $lines = Get-Content -Path $JsonFilePath -ReadCount 0
42 | foreach ($line in $lines) {
43 | $logs = Parse-JsonData -JsonData $line
44 | if ($logs) {
45 | foreach ($log in $logs) {
46 | $deviceId = $log.deviceDetail.deviceId
47 | if (-not $uniqueIds.Contains($deviceId)) {
48 | $uniqueIds += $deviceId
49 | }
50 | }
51 | }
52 | }
53 | }
54 |
55 | # Method 2: Using Hashtable
56 | function Process-SignInLogs-Hashtable {
57 | param (
58 | [string]$JsonFilePath
59 | )
60 | $uniqueIds = @{}
61 | $lines = Get-Content -Path $JsonFilePath -ReadCount 0
62 | foreach ($line in $lines) {
63 | $logs = Parse-JsonData -JsonData $line
64 | if ($logs) {
65 | foreach ($log in $logs) {
66 | $deviceId = $log.deviceDetail.deviceId
67 | if (-not $uniqueIds.ContainsKey($deviceId)) {
68 | $uniqueIds[$deviceId] = $true
69 | }
70 | }
71 | }
72 | }
73 | }
74 |
75 | # Method 3: Using HashSet
76 | function Process-SignInLogs-HashSet {
77 | param (
78 | [string]$JsonFilePath
79 | )
80 | $uniqueIds = [System.Collections.Generic.HashSet[string]]::new()
81 | $lines = Get-Content -Path $JsonFilePath -ReadCount 0
82 | foreach ($line in $lines) {
83 | $logs = Parse-JsonData -JsonData $line
84 | if ($logs) {
85 | foreach ($log in $logs) {
86 | $deviceId = $log.deviceDetail.deviceId
87 | $uniqueIds.Add($deviceId) | Out-Null
88 | }
89 | }
90 | }
91 | }
92 |
93 | # JSON file path
94 | $jsonFilePath = "C:\log.json"
95 |
96 | # Measure execution times
97 | $arrayTime = Measure-ExecutionTime -Code { Process-SignInLogs-Array -JsonFilePath $jsonFilePath }
98 | $hashtableTime = Measure-ExecutionTime -Code { Process-SignInLogs-Hashtable -JsonFilePath $jsonFilePath }
99 | $hashSetTime = Measure-ExecutionTime -Code { Process-SignInLogs-HashSet -JsonFilePath $jsonFilePath }
100 |
101 | # Output results
102 | Write-Host "Average execution time using Array: $arrayTime ms"
103 | Write-Host "Average execution time using Hashtable: $hashtableTime ms"
104 | Write-Host "Average execution time using HashSet: $hashSetTime ms"
--------------------------------------------------------------------------------
/Compliance/Benchmarking/test-vscode-debugging.ps1:
--------------------------------------------------------------------------------
1 | function Get-Greeting {
2 | param (
3 | [string]$Name
4 | )
5 | return "Hello, $Name!"
6 | }
7 |
8 | # Import the module
9 | Import-Module "$PSScriptRoot\helloworld.psm1" -Force
10 |
11 | # Test the function
12 | $greeting = Get-Greeting -Name "World"
13 | Write-Host $greeting
14 |
15 | $DBG
16 |
17 | # Breakpoint to inspect the variable
18 | $greeting
19 |
--------------------------------------------------------------------------------
/Compliance/CustomExports/BYODCompliant.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/Compliance/CustomExports/BYODCompliant.csv
--------------------------------------------------------------------------------
/Compliance/CustomExports/CorporateIncompliant.csv:
--------------------------------------------------------------------------------
1 | "DeviceName","UserName","DeviceEntraID","UserEntraID","DeviceOS","OSVersion","DeviceComplianceStatus","DeviceStateInIntune","TrustType","UserLicense","SignInStatus","City","State","CountryOrRegion"
2 | "ICTC-642","Sadik Idriss","2eb123e2-eed7-4b20-86f7-4f4ac8a88733","d3e336a8-fc7a-4188-92a1-7d0c3d906467","Windows10","10.0.19045.5011","Non-Compliant","Absent","Hybrid Azure AD joined","Microsoft 365 Business Premium","Success","Quebec City","Quebec","CA"
3 | "ICTC-622","Reem Fakhouri","61e9e207-6650-4fe3-acd6-91a30437f226","c7fb58ea-321b-4768-8cbf-50077d0179bc","Windows10","","Non-Compliant","Absent","Hybrid Azure AD joined","Microsoft 365 Business Premium","Success","Toronto","Ontario","CA"
4 | "ICTC-581","Mairead Matthews","c55915fc-6fba-422a-9328-394a0bc508ef","027b0c6d-7da4-4b25-8d86-08c338ade181","Windows10","10.0.19045.4170","Non-Compliant","Absent","Hybrid Azure AD joined","Microsoft 365 Business Premium","Success","Vancouver","British Columbia","CA"
5 | "ICTC-571","Dave Murray","c95b0eb5-87e4-49ec-a619-2b6e686e8c72","271e64f6-a1e3-4792-8e7e-3ddf6b97e3b1","Windows10","","Non-Compliant","Absent","Hybrid Azure AD joined","Microsoft 365 Business Premium","Success","Calgary","Alberta","CA"
6 | "ICTC-MGMT","Nijat Mammadov","0bb33864-ff6a-4fb7-8495-4d3d4b84a0ae","66fe21d7-0a19-4988-b5d2-4f6147ee29b2","Windows","10.0.17763.0","Non-Compliant","Absent","Hybrid Azure AD joined","Other","Success","Toronto","Ontario","CA"
7 |
--------------------------------------------------------------------------------
/Compliance/CustomExports/Report_Compliant.csv:
--------------------------------------------------------------------------------
1 | "ComplianceStatus","TrustType","DeviceOS","DeviceStateInIntune","Count"
2 | "Compliant","Azure AD joined","Windows","Present","6"
3 | "Compliant","Azure AD joined","Windows10","Present","14"
4 | "Compliant","Hybrid Azure AD joined","Windows","Present","15"
5 | "Compliant","Hybrid Azure AD joined","Windows10","Present","13"
6 |
--------------------------------------------------------------------------------
/Compliance/CustomExports/Report_Error.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aollivierre/ConditionalAccess/1b182d291022f8eb3d9d930f5d6fe8f2448280e5/Compliance/CustomExports/Report_Error.csv
--------------------------------------------------------------------------------
/Compliance/CustomExports/Report_External.csv:
--------------------------------------------------------------------------------
1 | "DeviceName","UserName","DeviceEntraID","UserEntraID","DeviceOS","OSVersion","DeviceComplianceStatus","DeviceStateInIntune","TrustType","UserLicense","SignInStatus","City","State","CountryOrRegion"
2 | "{PII Removed}","Siddiqui, Ayesha","N/A","21b90bc7-95c1-4988-8b84-c6833fc38699","Windows10","","Non-Compliant","External","Hybrid Azure AD joined","Other","Success","Toronto","Ontario","CA"
3 |
--------------------------------------------------------------------------------
/Compliance/CustomExports/Report_NonCompliant.csv:
--------------------------------------------------------------------------------
1 | "ComplianceStatus","TrustType","DeviceOS","DeviceStateInIntune","Count"
2 | "Non-Compliant","","","BYOD","2"
3 | "Non-Compliant","","Android","BYOD","4"
4 | "Non-Compliant","","Ios 16.7.10","BYOD","1"
5 | "Non-Compliant","","Ios 17.3","BYOD","1"
6 | "Non-Compliant","","Ios 17.3.0","BYOD","1"
7 | "Non-Compliant","","Ios 17.5.1","BYOD","1"
8 | "Non-Compliant","","Ios 17.6","BYOD","1"
9 | "Non-Compliant","","Ios 17.6.0","BYOD","1"
10 | "Non-Compliant","","Ios 17.6.1","BYOD","7"
11 | "Non-Compliant","","Ios 17.7","BYOD","2"
12 | "Non-Compliant","","Ios 17.7.0","BYOD","2"
13 | "Non-Compliant","","Ios 18.0","BYOD","3"
14 | "Non-Compliant","","Ios 18.0.0","BYOD","2"
15 | "Non-Compliant","","Ios 18.0.1","BYOD","1"
16 | "Non-Compliant","","MacOs","BYOD","7"
17 | "Non-Compliant","","Windows","BYOD","2"
18 | "Non-Compliant","","Windows10","BYOD","65"
19 | "Non-Compliant","Azure AD registered","Ios 17.6.1","Absent","1"
20 | "Non-Compliant","Azure AD registered","Windows10","Absent","25"
21 | "Non-Compliant","Hybrid Azure AD joined","Windows","Absent","1"
22 | "Non-Compliant","Hybrid Azure AD joined","Windows10","Absent","4"
23 |
--------------------------------------------------------------------------------
/Compliance/CustomExports/Report_NonPremiumLicenses.csv:
--------------------------------------------------------------------------------
1 | "DeviceName","UserName","DeviceEntraID","UserEntraID","DeviceOS","OSVersion","DeviceComplianceStatus","DeviceStateInIntune","TrustType","UserLicense","SignInStatus","City","State","CountryOrRegion"
2 | "BYOD","Terence Nascimento (Nova)","N/A","04213b98-7eba-41ab-96e7-0dde304504bb","Windows10","","Non-Compliant","BYOD","","Other","Success","Ottawa","Ontario","CA"
3 | "BYOD","Alexandra Cutean","N/A","0db0e3fe-7dc0-4439-b371-75844eb2966f","Windows10","","Non-Compliant","BYOD","","Other","Success","Squamish","British Columbia","CA"
4 | "{PII Removed}","Siddiqui, Ayesha","N/A","21b90bc7-95c1-4988-8b84-c6833fc38699","Windows10","","Non-Compliant","External","Hybrid Azure AD joined","Other","Success","Toronto","Ontario","CA"
5 | "BYOD","ICTC-CTIC Women in Tech","N/A","481e1fd1-86f2-4a49-9ea7-eacfbff71e7b","Windows10","","Non-Compliant","BYOD","","Other","Success","Ottawa","Ontario","CA"
6 | "BYOD","Terence Nascimento (Nova)","N/A","501e6933-d388-48c2-8ece-2fca572c9a19","Windows10","","Non-Compliant","BYOD","","Other","Success","Ottawa","Ontario","CA"
7 | "BYOD","Magi Reyes (NOVA)","N/A","65012f3d-59d2-4620-a7ea-c7f0c1b9c69c","Windows10","","Non-Compliant","BYOD","","Other","Success","Kitchener","Ontario","CA"
8 | "BYOD","Nijat Mammadov","N/A","66fe21d7-0a19-4988-b5d2-4f6147ee29b2","Windows10","","Non-Compliant","BYOD","","Other","Success","Stittsville","Ontario","CA"
9 | "BYOD","NovaAdmin-John Fawcett","N/A","677d34c0-14f0-4a26-9db6-f21bd7c048c0","Windows10","","Non-Compliant","BYOD","","Other","Success","Toronto","Ontario","CA"
10 | "BYOD","Jainish Acharya","N/A","7d5f579e-11a7-4dfa-8a15-13c585de86da","Windows10","","Non-Compliant","BYOD","","Other","Success","Nepean","Ontario","CA"
11 | "BYOD","No-Reply","N/A","8f29e97e-0f20-40f5-8a9b-24264301d99d","","","Non-Compliant","BYOD","","Other","Success","Barrie","Ontario","CA"
12 | "BYOD","Ann Stephen","N/A","a3925472-e922-4d7e-98f5-8d62bdc9e8c6","Windows10","","Non-Compliant","BYOD","","Other","Success","Ottawa","Ontario","CA"
13 | "BYOD","Abdullah Ollivierre (NOVA)","N/A","bde8ec78-f15e-449a-ae87-63d6f1b512bb","Windows","","Non-Compliant","BYOD","","Other","Success","Winnipeg","Manitoba","CA"
14 | "BYOD","Shakeel Ahmed","N/A","f1580fa8-2db6-41f0-b331-8501de1c3e08","Windows10","","Non-Compliant","BYOD","","Other","Success","Windsor","Ontario","CA"
15 | "BYOD","ICTC Finance","N/A","f7c280af-539b-4ca1-bcd7-8dce889ce935","","","Non-Compliant","BYOD","","Other","Success","Barrie","Ontario","CA"
16 | "BYOD","Abdulahad Shaikh (NOVA)","N/A","fcc23ae1-4167-4d1a-9794-8fb7e279b873","Windows10","","Non-Compliant","BYOD","","Other","Success","Toronto","Ontario","CA"
17 |
--------------------------------------------------------------------------------
/Compliance/CustomExports/Report_PIIRemoved.csv:
--------------------------------------------------------------------------------
1 | "DeviceName","UserName","DeviceEntraID","UserEntraID","DeviceOS","OSVersion","DeviceComplianceStatus","DeviceStateInIntune","TrustType","UserLicense","SignInStatus","City","State","CountryOrRegion"
2 | "{PII Removed}","Siddiqui, Ayesha","N/A","21b90bc7-95c1-4988-8b84-c6833fc38699","Windows10","","Non-Compliant","External","Hybrid Azure AD joined","Other","Success","Toronto","Ontario","CA"
3 |
--------------------------------------------------------------------------------
/Compliance/CustomExports/Report_Present.csv:
--------------------------------------------------------------------------------
1 | "ComplianceStatus","TrustType","DeviceOS","DeviceStateInIntune","Count"
2 | "Compliant","Azure AD joined","Windows","Present","6"
3 | "Compliant","Azure AD joined","Windows10","Present","14"
4 | "Compliant","Hybrid Azure AD joined","Windows","Present","15"
5 | "Compliant","Hybrid Azure AD joined","Windows10","Present","13"
6 |
--------------------------------------------------------------------------------
/Compliance/CustomExports/StructuredReport.csv:
--------------------------------------------------------------------------------
1 | "ComplianceStatus","TrustType","DeviceOS","DeviceStateInIntune","Count"
2 | "Compliant","Azure AD joined","Windows","Present","6"
3 | "Compliant","Azure AD joined","Windows10","Present","14"
4 | "Compliant","Hybrid Azure AD joined","Windows","Present","15"
5 | "Compliant","Hybrid Azure AD joined","Windows10","Present","13"
6 | "Non-Compliant","","","BYOD","2"
7 | "Non-Compliant","","Android","BYOD","4"
8 | "Non-Compliant","","Ios 16.7.10","BYOD","1"
9 | "Non-Compliant","","Ios 17.3","BYOD","1"
10 | "Non-Compliant","","Ios 17.3.0","BYOD","1"
11 | "Non-Compliant","","Ios 17.5.1","BYOD","1"
12 | "Non-Compliant","","Ios 17.6","BYOD","1"
13 | "Non-Compliant","","Ios 17.6.0","BYOD","1"
14 | "Non-Compliant","","Ios 17.6.1","BYOD","7"
15 | "Non-Compliant","","Ios 17.7","BYOD","2"
16 | "Non-Compliant","","Ios 17.7.0","BYOD","2"
17 | "Non-Compliant","","Ios 18.0","BYOD","3"
18 | "Non-Compliant","","Ios 18.0.0","BYOD","2"
19 | "Non-Compliant","","Ios 18.0.1","BYOD","1"
20 | "Non-Compliant","","MacOs","BYOD","7"
21 | "Non-Compliant","","Windows","BYOD","2"
22 | "Non-Compliant","","Windows10","BYOD","65"
23 | "Non-Compliant","Azure AD registered","Ios 17.6.1","Absent","1"
24 | "Non-Compliant","Azure AD registered","Windows10","Absent","25"
25 | "Non-Compliant","Hybrid Azure AD joined","Windows","Absent","1"
26 | "Non-Compliant","Hybrid Azure AD joined","Windows10","Absent","4"
27 |
--------------------------------------------------------------------------------
/Compliance/Modules.json:
--------------------------------------------------------------------------------
1 | {
2 | "requiredModules": [
3 | "Microsoft.Graph.Authentication",
4 | "Microsoft.Graph.Applications",
5 | "Microsoft.Graph.Identity.DirectoryManagement",
6 | "ImportExcel",
7 | "powershell-yaml" ,
8 | "PSWriteHTML",
9 | "MSAL.PS",
10 | "IntuneWin32App",
11 | "Microsoft.Graph.Groups",
12 | "SvRooij.ContentPrep.Cmdlet"
13 | ],
14 | "importedModules": [
15 | "Microsoft.Graph.Identity.DirectoryManagement",
16 | "Microsoft.Graph.Authentication",
17 | "Microsoft.Graph.Identity.DirectoryManagement",
18 | "Microsoft.Graph.Applications",
19 | "ImportExcel",
20 | "powershell-yaml" ,
21 | "PSWriteHTML",
22 | "MSAL.PS",
23 | "IntuneWin32App",
24 | "Microsoft.Graph.Groups",
25 | "SvRooij.ContentPrep.Cmdlet"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/Compliance/Readme.md:
--------------------------------------------------------------------------------
1 | Certainly! Here’s a documentation note for future reference, advising on how to maintain and customize the script, specifically focusing on the `Load-SignInLogs`, `Add-Result`, and `Process-DeviceItem` functions:
2 |
3 | ---
4 |
5 | ### **Script Maintenance and Customization Guide**
6 |
7 | #### **1. Customizing the `Load-SignInLogs` Function**
8 |
9 | The `Load-SignInLogs` function is responsible for loading and parsing sign-in logs from a JSON file. This function extracts specific properties from the JSON data and includes them in the `signInLog` object.
10 |
11 | - **When to Update:**
12 | - If you need to include additional properties from the JSON file (e.g., `location`, `clientAppUsed`), you should modify the `Load-SignInLogs` function to capture these properties.
13 | - If certain properties are no longer needed in the report, you can remove them from this function to simplify the `signInLog` object.
14 |
15 | - **How to Update:**
16 | - Locate the section where each property is extracted, for example:
17 | ```powershell
18 | $deviceDetail = [PSCustomObject]@{
19 | DeviceId = $element.GetProperty("deviceDetail").GetProperty("deviceId").GetString()
20 | DisplayName = $element.GetProperty("deviceDetail").GetProperty("displayName").GetString()
21 | OperatingSystem = $element.GetProperty("deviceDetail").GetProperty("operatingSystem").GetString()
22 | IsCompliant = $element.GetProperty("deviceDetail").GetProperty("isCompliant").GetBoolean()
23 | TrustType = $element.GetProperty("deviceDetail").GetProperty("trustType").GetString()
24 | }
25 | ```
26 | - Add or remove lines within these blocks to include or exclude properties.
27 |
28 | #### **2. Customizing the `Add-Result` Function**
29 |
30 | The `Add-Result` function constructs a result object that is eventually added to the processing context. This result object is what gets exported in the final report.
31 |
32 | - **When to Update:**
33 | - If you’ve updated the `Load-SignInLogs` function to include new properties, you’ll need to update `Add-Result` to reflect these changes.
34 | - Conversely, if you’ve removed properties from `Load-SignInLogs`, you should also remove the corresponding fields in `Add-Result` to avoid unnecessary data processing.
35 |
36 | - **How to Update:**
37 | - Update the `Add-Result` function by modifying the `[PSCustomObject]` construction block:
38 | ```powershell
39 | $result = [PSCustomObject]@{
40 | DeviceName = $deviceName
41 | UserName = $Item.UserDisplayName
42 | DeviceEntraID = $DeviceId
43 | UserEntraID = $Item.UserId
44 | DeviceOS = $Item.DeviceDetail.OperatingSystem
45 | OSVersion = $osVersion
46 | DeviceComplianceStatus = $complianceStatus
47 | DeviceStateInIntune = $DeviceState
48 | TrustType = $Item.DeviceDetail.TrustType
49 | UserLicense = $userLicense
50 | SignInStatus = $signInStatus # New property for Sign-In Status
51 | City = $Item.Location.City # New property for City
52 | State = $Item.Location.State # New property for State
53 | CountryOrRegion = $Item.Location.CountryOrRegion # New property for Country/Region
54 | }
55 | ```
56 | - Add new properties as needed, or remove those no longer required.
57 |
58 | #### **3. Customizing the `Process-DeviceItem` Function**
59 |
60 | The `Process-DeviceItem` function is where logic is applied to decide whether to process a sign-in log entry or skip it based on specific conditions, such as error codes or the presence of specific properties.
61 |
62 | - **When to Update:**
63 | - Update this function when you want to change the conditions under which a sign-in log is processed or skipped. For example, you might want to skip logs with specific error codes or filter logs based on device compliance status.
64 |
65 | - **How to Update:**
66 | - Locate the conditional logic where decisions are made, for example:
67 | ```powershell
68 | if ($Item.Status.ErrorCode -ne 0) {
69 | Write-EnhancedLog -Message "Sign-in attempt failed for user $($Item.UserDisplayName) with ErrorCode: $($Item.Status.ErrorCode) - $($Item.Status.FailureReason)" -Level "WARNING"
70 | return
71 | }
72 | ```
73 | - Adjust the conditions to reflect your new requirements.
74 | - Modify or add logging statements as necessary to capture the reasons for skipping or processing specific entries.
75 |
76 | #### **Final Note:**
77 | Whenever you update any of these functions, make sure to thoroughly test the script to ensure that the changes work as expected and that all necessary data is being captured or excluded based on the updates.
78 |
79 | ---
80 |
81 | This guide should help maintain the script and ensure that any future changes can be made systematically, without losing track of why those changes are being implemented.
--------------------------------------------------------------------------------
/Compliance/combine-allmodules.ps1:
--------------------------------------------------------------------------------
1 | # Define the root path
2 | $rootPath = 'C:\Code\Modules'
3 | $outputFile = Join-Path -Path $rootPath -ChildPath 'CombinedModules.ps1'
4 |
5 | # Initialize the output file
6 | New-Item -Path $outputFile -ItemType File -Force
7 |
8 | # Function to combine files from a directory and its subdirectories
9 | function Combine-AllPS1Files {
10 | param (
11 | [string]$directory
12 | )
13 | Get-ChildItem -Path $directory -Filter *.ps1 -Recurse | ForEach-Object {
14 | Get-Content -Path $_.FullName | Add-Content -Path $outputFile
15 | Add-Content -Path $outputFile -Value "`n" # Add a new line for separation
16 | }
17 | }
18 |
19 | # Combine all PS1 files in the root path and its subdirectories
20 | Combine-AllPS1Files -directory $rootPath
21 |
22 | Write-Host "All PS1 files have been combined into $outputFile"
23 |
--------------------------------------------------------------------------------
/Compliance/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "PackageName": "PR4B_GetSignInLogs",
3 | "PackageUniqueGUID": "7b34084e-b856-40f5-9a5b-32b3249fb777",
4 | "Version": 1,
5 | "PackageExecutionContext": "SYSTEM",
6 | "RepetitionInterval": "PT60M",
7 | "LoggingDeploymentName": "PR4B_GetSignInLogsCustomlog",
8 | "ScriptMode": "Remediation",
9 | "RunOnDemand": true
10 | }
--------------------------------------------------------------------------------
/Compliance/modulesexclusion.json:
--------------------------------------------------------------------------------
1 | [
2 |
3 | ]
4 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/Delete-allConditionalAccessPolicies-v2.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with the necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.Read.All', 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Confirm before proceeding as this will delete all Conditional Access policies
5 | $confirmation = Read-Host "Are you sure you want to delete ALL Conditional Access policies? (yes/no)"
6 | if ($confirmation -ne 'yes') {
7 | Write-Output "Operation aborted by the user."
8 | Disconnect-MgGraph
9 | exit
10 | }
11 |
12 | # Fetch all Conditional Access policies
13 | $policies = Get-MgIdentityConditionalAccessPolicy
14 |
15 | # Iterate and delete each policy
16 | foreach ($policy in $policies) {
17 | $policyId = $policy.Id
18 | $policyName = $policy.DisplayName
19 | try {
20 | # Assuming there's a cmdlet to remove policies by ID. If not, you may need to use Invoke-MgGraphRequest with the appropriate HTTP method and URI
21 | Remove-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policyId -Force
22 | Write-Output "Successfully deleted Conditional Access policy: $policyName ($policyId)"
23 | } catch {
24 | Write-Error "Failed to delete Conditional Access policy: $policyName ($policyId). Error: $_"
25 | }
26 | }
27 |
28 | # Disconnect from Microsoft Graph
29 | Disconnect-MgGraph
30 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/Delete-allConditionalAccessPolicies-v3.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with the necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.Read.All', 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Confirm before proceeding as this will delete all Conditional Access policies
5 | $confirmation = Read-Host "Are you sure you want to delete ALL Conditional Access policies? (yes/no)"
6 | if ($confirmation -ne 'yes') {
7 | Write-Output "Operation aborted by the user."
8 | Disconnect-MgGraph
9 | exit
10 | }
11 |
12 | # Fetch all Conditional Access policies
13 | $policies = Get-MgIdentityConditionalAccessPolicy
14 |
15 | # Iterate and attempt to delete each policy
16 | foreach ($policy in $policies) {
17 | $policyId = $policy.Id
18 | $policyName = $policy.DisplayName
19 | try {
20 | # Adjusted cmdlet call without the -Force parameter
21 | Remove-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policyId
22 | Write-Output "Successfully requested deletion of Conditional Access policy: $policyName ($policyId)"
23 | } catch {
24 | Write-Error "Failed to delete Conditional Access policy: $policyName ($policyId). Error: $_"
25 | }
26 | }
27 |
28 |
29 | # Disconnect from Microsoft Graph
30 | Disconnect-MgGraph
31 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/Delete-allConditionalAccessPolicies.ps1:
--------------------------------------------------------------------------------
1 | # Install the required modules if not already installed
2 | Install-Module Microsoft.Graph.Authentication -Scope allusers
3 | Install-Module Microsoft.Graph.Identity.SignIns -Scope AllUsers
4 |
5 | # Connect to Microsoft Graph
6 | Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"
7 |
8 | # Confirm before proceeding as this will delete all Conditional Access policies
9 | $confirmation = Read-Host "Are you sure you want to delete ALL Conditional Access policies? (yes/no)"
10 | if ($confirmation -ne 'yes') {
11 | Write-Output "Operation aborted by the user."
12 | exit
13 | }
14 |
15 | # Fetch all Conditional Access policies
16 | $policies = Get-MgConditionalAccessPolicy
17 |
18 | # Iterate and delete each policy
19 | foreach ($policy in $policies) {
20 | $policyId = $policy.Id
21 | $policyName = $policy.DisplayName
22 | try {
23 | Remove-MgConditionalAccessPolicy -ConditionalAccessPolicyId $policyId -Force
24 | Write-Output "Successfully deleted Conditional Access policy: $policyName ($policyId)"
25 | } catch {
26 | Write-Error "Failed to delete Conditional Access policy: $policyName ($policyId). Error: $_"
27 | }
28 | }
29 |
30 | # Disconnect from Microsoft Graph
31 | Disconnect-MgGraph
32 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/Rename-ConditionalAccessPolicies-All-v2.ps1:
--------------------------------------------------------------------------------
1 | # $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\ConditionalAccess\Main"
2 | $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\ConditionalAccess\PMM\GRANT"
3 | $jsonFiles = Get-ChildItem -Path $jsonFilesDirectory -Filter "*.json"
4 |
5 | foreach ($file in $jsonFiles) {
6 | if (Test-Path $file.FullName) {
7 | $jsonContent = Get-Content -Path $file.FullName | Out-String
8 | $jsonObject = $jsonContent | ConvertFrom-Json
9 |
10 | if ($null -ne $jsonObject.PSObject.Properties.Match('displayName')) {
11 | $fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)
12 | $jsonObject.displayName = $fileNameWithoutExtension
13 | $updatedJsonContent = $jsonObject | ConvertTo-Json -Depth 100
14 | $updatedJsonContent | Set-Content -Path $file.FullName
15 | } else {
16 | Write-Host "The file $($file.Name) does not contain a 'displayName' property."
17 | }
18 | } else {
19 | Write-Host "Unable to find or access the file: $($file.FullName)"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/Rename-ConditionalAccessPolicies-All-v3.ps1:
--------------------------------------------------------------------------------
1 | # $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\ConditionalAccess\Main"
2 | $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\ConditionalAccess\PMM\GRANT"
3 | $jsonFiles = Get-ChildItem -Path $jsonFilesDirectory -Filter "*.json"
4 |
5 | foreach ($file in $jsonFiles) {
6 | try {
7 | # Ensure the JSON content is read with the correct encoding, UTF8 is commonly used for JSON files
8 | $jsonContent = Get-Content -Path $file.FullName -Raw -Encoding UTF8
9 | $jsonObject = $jsonContent | ConvertFrom-Json
10 |
11 | $fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)
12 |
13 | # Update the displayName property
14 | $jsonObject.displayName = $fileNameWithoutExtension
15 |
16 | $updatedJsonContent = $jsonObject | ConvertTo-Json -Depth 100 -Compress
17 | $updatedJsonContent | Set-Content -Path $file.FullName -Force -Encoding UTF8
18 | } catch {
19 | Write-Host "An error occurred processing $($file.Name): $_"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/Rename-ConditionalAccessPolicies-All-v4.ps1:
--------------------------------------------------------------------------------
1 | # $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\ConditionalAccess\Main"
2 | $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\ConditionalAccess\PMM\GRANT"
3 | $jsonFiles = Get-ChildItem -Path $jsonFilesDirectory -Filter "*.json"
4 |
5 | foreach ($file in $jsonFiles) {
6 | try {
7 | # Read the file content as an array of lines and then join them into a single string
8 | $jsonContentLines = Get-Content -Path $file.FullName -Encoding UTF8
9 | $jsonContent = $jsonContentLines -join ""
10 | $jsonObject = $jsonContent | ConvertFrom-Json
11 |
12 | $fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)
13 |
14 | # Update the displayName property
15 | $jsonObject.displayName = $fileNameWithoutExtension
16 |
17 | $updatedJsonContent = $jsonObject | ConvertTo-Json -Depth 100 -Compress
18 | $updatedJsonContent | Set-Content -Path $file.FullName -Force -Encoding UTF8
19 | } catch {
20 | Write-Host "An error occurred processing $($file.Name): $_"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/recreateConditionalAccesspoliciesusingJSON-v2.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Specify the directory containing the JSON files
5 | $jsonDir = "C:\code\caac\Feb172024\CCI\Entra-Intune-v1\Canada Computing Inc\ConditionalAccess-Recreated-Modern-Graph-API"
6 |
7 | # Get all JSON files from the directory
8 | $jsonFiles = Get-ChildItem -Path $jsonDir -Filter "*.json"
9 |
10 | foreach ($jsonFile in $jsonFiles) {
11 | # Load the JSON content
12 | $jsonContent = Get-Content -Path $jsonFile.FullName -Raw | ConvertFrom-Json
13 |
14 | # Prepare the policy object for creation
15 | $policyParams = @{
16 | DisplayName = $jsonContent.displayName + " - Modern API"
17 | State = $jsonContent.state
18 | Conditions = $jsonContent.conditions
19 | GrantControls = $jsonContent.grantControls
20 | # Include other fields as needed, ensuring they match the expected schema
21 | }
22 |
23 | # Remove any null or deprecated properties to match the expected schema
24 | $policyParams.GetEnumerator() | ForEach-Object {
25 | if ($null -eq $policyParams[$_.Key]) {
26 | $policyParams.Remove($_.Key)
27 | }
28 | }
29 |
30 | # Convert the policy parameters to a JSON object
31 | $policyJson = $policyParams | ConvertTo-Json -Depth 10
32 |
33 | try {
34 | # Create the new Conditional Access policy
35 | $result = New-MgIdentityConditionalAccessPolicy -BodyParameter $policyJson
36 | Write-Host "Successfully created policy: $($result.DisplayName)"
37 | } catch {
38 | Write-Error "Failed to create policy from $($jsonFile.Name): $_"
39 | }
40 | }
41 |
42 | # Disconnect from Microsoft Graph
43 | # Disconnect-MgGraph
44 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/recreateConditionalAccesspoliciesusingJSON-v3.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Define a simple Conditional Access policy
5 | $policyDisplayName = "Sample Policy - Modern API"
6 | $policyState = "enabled"
7 |
8 | # Define conditions for the policy (adjust as needed)
9 | $conditions = @{
10 | Applications = @{
11 | IncludeApplications = "All"
12 | }
13 | Users = @{
14 | IncludeUsers = "All"
15 | }
16 | }
17 |
18 | # Define grant controls for the policy (adjust as needed)
19 | $grantControls = @{
20 | BuiltInControls = @("mfa")
21 | Operator = "OR"
22 | }
23 |
24 | # Create the policy
25 | try {
26 | $policyParams = @{
27 | DisplayName = $policyDisplayName
28 | State = $policyState
29 | Conditions = $conditions
30 | GrantControls = $grantControls
31 | }
32 |
33 | $policyJson = $policyParams | ConvertTo-Json -Depth 10
34 |
35 | # Create the Conditional Access policy
36 | $result = New-MgIdentityConditionalAccessPolicy -BodyParameter $policyJson
37 | Write-Host "Successfully created policy: $($result.DisplayName)"
38 | } catch {
39 | Write-Error "Failed to create policy: $_"
40 | }
41 |
42 | # Disconnect from Microsoft Graph
43 | # Disconnect-MgGraph
44 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/recreateConditionalAccesspoliciesusingJSON-v4.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Define a Conditional Access policy with required conditions
5 | $policyDisplayName = "Sample Policy - Modern API"
6 | $policyState = "enabled"
7 |
8 | # Define conditions for the policy, including 'users' and 'applications'
9 | $conditions = @{
10 | Applications = @{
11 | IncludeApplications = @("All") # Include all applications
12 | }
13 | Users = @{
14 | IncludeUsers = @("All") # Include all users
15 | }
16 | }
17 |
18 | # Define grant controls for the policy
19 | $grantControls = @{
20 | BuiltInControls = @("mfa") # Require MFA
21 | Operator = "OR"
22 | }
23 |
24 | # Construct the policy object
25 | $policyObject = @{
26 | DisplayName = $policyDisplayName
27 | State = $policyState
28 | Conditions = $conditions
29 | GrantControls = $grantControls
30 | }
31 |
32 | # Convert policy object to JSON
33 | $policyJson = $policyObject | ConvertTo-Json -Depth 10
34 |
35 | try {
36 | # Attempt to create the Conditional Access policy
37 | $result = New-MgIdentityConditionalAccessPolicy -BodyParameter $policyJson
38 | Write-Host "Successfully created policy: $($result.DisplayName)"
39 | } catch {
40 | Write-Error "Failed to create policy: $_"
41 | }
42 |
43 | # Disconnect from Microsoft Graph
44 | # Disconnect-MgGraph
45 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/recreateConditionalAccesspoliciesusingJSON-v5.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Define a Conditional Access policy with required conditions
5 | $policyDisplayName = "Sample Policy - Modern API - v2 - OFF"
6 | $policyState = "disabled" # Set policy to be off (disabled)
7 |
8 | # Define conditions for the policy, including 'users' and 'applications'
9 | $conditions = @{
10 | Applications = @{
11 | IncludeApplications = @("All") # Include all applications
12 | }
13 | Users = @{
14 | IncludeUsers = @("All") # Include all users
15 | }
16 | }
17 |
18 | # Define grant controls for the policy
19 | $grantControls = @{
20 | BuiltInControls = @("mfa") # Require MFA
21 | Operator = "OR"
22 | }
23 |
24 | # Construct the policy object
25 | $policyObject = @{
26 | DisplayName = $policyDisplayName
27 | State = $policyState
28 | Conditions = $conditions
29 | GrantControls = $grantControls
30 | }
31 |
32 | # Convert policy object to JSON
33 | $policyJson = $policyObject | ConvertTo-Json -Depth 10
34 |
35 | try {
36 | # Attempt to create the Conditional Access policy in the "off" state
37 | $result = New-MgIdentityConditionalAccessPolicy -BodyParameter $policyJson
38 | Write-Host "Successfully created policy in the 'off' state: $($result.DisplayName)"
39 | } catch {
40 | Write-Error "Failed to create policy: $_"
41 | }
42 |
43 | # Disconnect from Microsoft Graph
44 | Disconnect-MgGraph
45 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/recreateConditionalAccesspoliciesusingJSON-v6.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Specify the directory containing the JSON files
5 | $jsonDir = "C:\code\caac\Feb172024\CCI\Entra-Intune-v1\Canada Computing Inc\ConditionalAccess-Recreated-Modern-Graph-API"
6 |
7 | # Get all JSON files from the directory
8 | $jsonFiles = Get-ChildItem -Path $jsonDir -Filter "*.json"
9 |
10 | foreach ($jsonFile in $jsonFiles) {
11 | # Load the JSON content
12 | $jsonContent = Get-Content -Path $jsonFile.FullName -Raw | ConvertFrom-Json
13 |
14 | # Prepare the policy object for creation
15 | $policyParams = @{
16 | DisplayName = $jsonContent.displayName + " - Modern API"
17 | State = "disabled" # Ensure the policy is created in the "off" state
18 | # Define other necessary properties for the policy here
19 | # For example, Conditions and GrantControls as per your requirements
20 | # This example uses placeholder values
21 | Conditions = @{
22 | Applications = @{
23 | IncludeApplications = @("All")
24 | }
25 | Users = @{
26 | IncludeUsers = @("All")
27 | }
28 | }
29 | GrantControls = @{
30 | BuiltInControls = @("block")
31 | Operator = "OR"
32 | }
33 | }
34 |
35 | # Convert policy object to JSON
36 | $policyJson = $policyParams | ConvertTo-Json -Depth 10
37 |
38 | try {
39 | # Attempt to create the Conditional Access policy
40 | $result = New-MgIdentityConditionalAccessPolicy -BodyParameter $policyJson
41 | Write-Host "Successfully created policy: $($result.DisplayName)"
42 | } catch {
43 | Write-Error "Failed to create policy from file $($jsonFile.Name): $_"
44 | }
45 | }
46 |
47 | # Disconnect from Microsoft Graph
48 | # Disconnect-MgGraph
49 |
--------------------------------------------------------------------------------
/ConditionalAccess/Archive/recreateConditionalAccesspoliciesusingJSON.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Specify the directory containing the JSON files
5 | $jsonDir = "C:\code\caac\Feb172024\CCI\Entra-Intune-v1\Canada Computing Inc\ConditionalAccess-Recreated-Modern-Graph-API"
6 |
7 | # Get all JSON files from the directory
8 | $jsonFiles = Get-ChildItem -Path $jsonDir -Filter "*.json"
9 |
10 | foreach ($jsonFile in $jsonFiles) {
11 | # Load the JSON content
12 | $jsonContent = Get-Content -Path $jsonFile.FullName -Raw | ConvertFrom-Json
13 |
14 | # Construct a new policy object from the JSON content, ensuring to avoid deprecated attributes
15 | $newPolicy = @{
16 | DisplayName = $jsonContent.displayName + " - Modern API"
17 | State = $jsonContent.state
18 | Conditions = @{
19 | Applications = $jsonContent.conditions.applications
20 | Users = $jsonContent.conditions.users
21 | Platforms = $jsonContent.conditions.platforms
22 | Locations = $jsonContent.conditions.locations
23 | ClientAppTypes = $jsonContent.conditions.clientAppTypes
24 | }
25 | GrantControls = $jsonContent.grantControls
26 | SessionControls = $jsonContent.sessionControls
27 | }
28 |
29 | # Convert the new policy object to JSON
30 | $newPolicyJson = $newPolicy | ConvertTo-Json -Depth 10
31 |
32 | try {
33 | # Create the new Conditional Access policy using the Modern API
34 | $result = New-MgIdentityConditionalAccessPolicy -BodyParameter $newPolicyJson
35 | Write-Host "Successfully created policy: $($result.DisplayName)"
36 | } catch {
37 | Write-Error "Failed to create policy from $($jsonFile.Name): $_"
38 | }
39 | }
40 |
41 | # Disconnect from Microsoft Graph
42 | Disconnect-MgGraph
43 |
--------------------------------------------------------------------------------
/ConditionalAccess/Conditional Access Policy Name Generator.ps1:
--------------------------------------------------------------------------------
1 | # Functions for policy generation
2 | function New-CAPolicyName {
3 | param (
4 | [string]$CategoryCode,
5 | [string]$SequenceNumber,
6 | [string]$Scope,
7 | [string]$Action,
8 | [string]$Condition,
9 | [string]$Clients,
10 | [string]$Version
11 | )
12 |
13 | "CA$CategoryCode$SequenceNumber - $($Scope.ToUpper()) - $($Action.ToUpper()) - $Condition - when - $Clients - v$Version.json"
14 | }
15 |
16 | function Export-CAPolicy {
17 | param (
18 | [string]$OutputPath = ".\CAPolicies.csv"
19 | )
20 |
21 | $policies = @(
22 | # Identity & Authentication Policies
23 | @{
24 | CategoryCode = "CAP"
25 | SequenceNumber = "001"
26 | Scope = "GLOBAL"
27 | Action = "BLOCK"
28 | Condition = "LegacyAuth"
29 | Clients = "AllClients"
30 | Version = "1.0"
31 | }
32 | @{
33 | CategoryCode = "CAP"
34 | SequenceNumber = "002"
35 | Scope = "GLOBAL"
36 | Action = "BLOCK"
37 | Condition = "DeviceCodeAuth"
38 | Clients = "AllClients"
39 | Version = "1.0"
40 | }
41 | @{
42 | CategoryCode = "CAU"
43 | SequenceNumber = "001"
44 | Scope = "ADMINS"
45 | Action = "GRANT"
46 | Condition = "RequirePhishingResistantMFA"
47 | Clients = "BrowserModernAuthClients"
48 | Version = "1.0"
49 | }
50 | # Location-Based Access
51 | @{
52 | CategoryCode = "CAL"
53 | SequenceNumber = "001"
54 | Scope = "GLOBAL"
55 | Action = "BLOCK"
56 | Condition = "NonAllowedCountries"
57 | Clients = "AllClients"
58 | Version = "1.0"
59 | }
60 | # Device-Based Policies
61 | @{
62 | CategoryCode = "CAD"
63 | SequenceNumber = "001"
64 | Scope = "GLOBAL"
65 | Action = "BLOCK"
66 | Condition = "UnsupportedPlatforms"
67 | Clients = "AllClients"
68 | Version = "1.0"
69 | }
70 | # Risk-Based Policies
71 | @{
72 | CategoryCode = "CAU"
73 | SequenceNumber = "002"
74 | Scope = "ADMINS"
75 | Action = "BLOCK"
76 | Condition = "AnyRiskLevel"
77 | Clients = "AllClients"
78 | Version = "1.0"
79 | }
80 | # Guest-Specific Policies
81 | @{
82 | CategoryCode = "CAU"
83 | SequenceNumber = "003"
84 | Scope = "GUESTS"
85 | Action = "BLOCK"
86 | Condition = "SensitiveApps"
87 | Clients = "AllClients"
88 | Version = "1.0"
89 | }
90 | # Break-Glass Policies
91 | @{
92 | CategoryCode = "CAB"
93 | SequenceNumber = "001"
94 | Scope = "SELECTED"
95 | Action = "GRANT"
96 | Condition = "EmergencyAccess"
97 | Clients = "BrowserModernAuthClients"
98 | Version = "1.0"
99 | }
100 | )
101 |
102 | $output = foreach ($policy in $policies) {
103 | [PSCustomObject]@{
104 | PolicyName = New-CAPolicyName @policy
105 | CategoryCode = $policy.CategoryCode
106 | Scope = $policy.Scope
107 | Action = $policy.Action
108 | Condition = $policy.Condition
109 | Clients = $policy.Clients
110 | Version = $policy.Version
111 | }
112 | }
113 |
114 | # Export to CSV
115 | $output | Export-Csv -Path $OutputPath -NoTypeInformation
116 |
117 | # Generate HTML report
118 | $HTMLPath = $OutputPath.Replace('.csv', '.html')
119 |
120 | $metadata = @{
121 | GeneratedBy = $env:USERNAME
122 | GeneratedOn = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
123 | TotalPolicies = $output.Count
124 | Categories = ($output | Group-Object CategoryCode | ForEach-Object { "$($_.Name): $($_.Count)" }) -join ", "
125 | }
126 |
127 | New-HTML -Title "Conditional Access Policies" -FilePath $HTMLPath -ShowHTML {
128 | New-HTMLSection -HeaderText "Generation Summary" {
129 | New-HTMLPanel {
130 | New-HTMLText -Text @"
131 | Report Details
132 |
133 | - Generated By: $($metadata.GeneratedBy)
134 | - Generated On: $($metadata.GeneratedOn)
135 | - Total Policies: $($metadata.TotalPolicies)
136 | - Categories: $($metadata.Categories)
137 |
138 | "@
139 | }
140 | }
141 |
142 | New-HTMLSection -HeaderText "Conditional Access Policies" {
143 | New-HTMLTable -DataTable $output -ScrollX -Buttons @('copyHtml5', 'excelHtml5', 'csvHtml5') -SearchBuilder {
144 | New-TableCondition -Name 'Action' -ComparisonType string -Operator eq -Value 'BLOCK' -BackgroundColor Salmon -Color Black
145 | New-TableCondition -Name 'Action' -ComparisonType string -Operator eq -Value 'GRANT' -BackgroundColor LightGreen -Color Black
146 | New-TableCondition -Name 'Action' -ComparisonType string -Operator eq -Value 'SESSION' -BackgroundColor LightBlue -Color Black
147 | }
148 | }
149 | }
150 |
151 | # Display summary in console
152 | Write-Host "`nPolicy Summary:" -ForegroundColor Cyan
153 | $output | Group-Object CategoryCode | ForEach-Object {
154 | Write-Host "$($_.Name): $($_.Count) policies"
155 | }
156 |
157 | Write-Host "`nOutput files generated:" -ForegroundColor Green
158 | Write-Host "CSV: $OutputPath"
159 | Write-Host "HTML: $HTMLPath"
160 | }
161 |
162 | # Execute the function
163 | Export-CAPolicy
--------------------------------------------------------------------------------
/ConditionalAccess/Delete-allConditionalAccessPolicies-v4.ps1:
--------------------------------------------------------------------------------
1 | # Connect to Microsoft Graph with the necessary permissions
2 | Connect-MgGraph -Scopes 'Policy.Read.All', 'Policy.ReadWrite.ConditionalAccess'
3 |
4 | # Confirm before proceeding as this will delete all Conditional Access policies
5 | $confirmation = Read-Host "Are you sure you want to delete ALL Conditional Access policies? (yes/no)"
6 | if ($confirmation -ne 'yes') {
7 | Write-Output "Operation aborted by the user."
8 | Disconnect-MgGraph
9 | exit
10 | }
11 |
12 |
13 |
14 | function Get-ConditionalAccessPoliciesViaMgGraph {
15 | $uri = "https://graph.microsoft.com/beta/identity/conditionalAccess/policies"
16 | $allPolicies = @()
17 |
18 | do {
19 | $response = Invoke-MgGraphRequest -Uri $uri -Method GET -Headers @{"Prefer"="odata.maxpagesize=999"}
20 | $policies = $response.Value
21 | $allPolicies += $policies
22 |
23 | $uri = if ($response.'@odata.nextLink') { $response.'@odata.nextLink' } else { $null }
24 | } while ($uri)
25 |
26 | return $allPolicies
27 | }
28 |
29 |
30 | # $allPolicies = Get-ConditionalAccessPoliciesViaMgGraph
31 | $policies = Get-ConditionalAccessPoliciesViaMgGraph
32 |
33 | # Fetch all Conditional Access policies
34 | # $policies = Get-MgIdentityConditionalAccessPolicy
35 |
36 | # Iterate and attempt to delete each policy
37 | foreach ($policy in $policies) {
38 | $policyId = $policy.Id
39 | $policyName = $policy.DisplayName
40 | try {
41 | # Adjusted cmdlet call without the -Force parameter
42 | Remove-MgBetaIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policyId
43 | Write-Output "Successfully requested deletion of Conditional Access policy: $policyName ($policyId)"
44 | } catch {
45 | Write-Error "Failed to delete Conditional Access policy: $policyName ($policyId). Error: $_"
46 | }
47 | }
48 |
49 |
50 | # Disconnect from Microsoft Graph
51 | # Disconnect-MgGraph
52 |
--------------------------------------------------------------------------------
/ConditionalAccess/Rename-ConditionalAccessPolicies-All.ps1:
--------------------------------------------------------------------------------
1 | # Define the directory containing the JSON files
2 | # $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\ConditionalAccess\Main"
3 | # $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\ConditionalAccess\PMM\GRANT"
4 | # $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\SettingsCatalog"
5 | # $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\DeviceConfiguration"
6 | # $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\UpdatePolicies"
7 | # $jsonFilesDirectory = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\AdministrativeTemplates"
8 |
9 | # Get all JSON files in the directory
10 | $jsonFiles = Get-ChildItem -Path $jsonFilesDirectory -Filter "*.json"
11 |
12 | # Iterate over each JSON file
13 | foreach ($file in $jsonFiles) {
14 | # Read the content of the JSON file
15 | $jsonContent = Get-Content -Path $file.FullName | Out-String
16 |
17 | # Convert the JSON content to a PowerShell object
18 | $jsonObject = $jsonContent | ConvertFrom-Json
19 |
20 | # Extract the file name without the extension
21 | $fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)
22 |
23 | # Update the displayName property
24 | # $jsonObject.name = $fileNameWithoutExtension
25 | $jsonObject.displayName = $fileNameWithoutExtension
26 |
27 | # Convert the modified object back to JSON
28 | $updatedJsonContent = $jsonObject | ConvertTo-Json -Depth 100
29 |
30 | # Save the updated JSON back to the file, overwriting the original content
31 | $updatedJsonContent | Set-Content -Path $file.FullName
32 | }
--------------------------------------------------------------------------------
/ConditionalAccess/Rename-ConditionalAccessPolicies.ps1:
--------------------------------------------------------------------------------
1 | # Define the path to your JSON file
2 | $jsonFilePath = "C:\Code\CaaC\Nova\Feb022024\AOllivierre-Sandbox\Entra-Intune-v2\MSFT\ConditionalAccess\Main\zzz-CA004 - GRANT - ADMINS - MFA - Global Admins with default Auth Strengths.json"
3 |
4 | # Read the content of the JSON file
5 | $jsonContent = Get-Content -Path $jsonFilePath | Out-String
6 |
7 | # Convert the JSON content to a PowerShell object
8 | $jsonObject = $jsonContent | ConvertFrom-Json
9 |
10 | # Extract the file name without the extension
11 | $fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($jsonFilePath)
12 |
13 | # Update the displayName property
14 | $jsonObject.displayName = $fileNameWithoutExtension
15 |
16 | # Convert the modified object back to JSON
17 | $updatedJsonContent = $jsonObject | ConvertTo-Json -Depth 100
18 |
19 | # Save the updated JSON back to the file, overwriting the original content
20 | $updatedJsonContent | Set-Content -Path $jsonFilePath
21 |
--------------------------------------------------------------------------------
/Module/ConditionalAccess.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | ModuleVersion = '1.0.0'
3 | GUID = New-Guid
4 | Author = 'Your Name'
5 | CompanyName = 'Your Company'
6 | Copyright = '(c) 2025. All rights reserved.'
7 | Description = 'Module for managing Conditional Access Policies with focus on Guest Access'
8 | PowerShellVersion = '5.1'
9 | RequiredModules = @(
10 | 'Microsoft.Graph.Identity.SignIns',
11 | 'PSWriteHTML'
12 | )
13 | FunctionsToExport = @(
14 | 'Get-ConditionalAccessPoliciesDetails',
15 | 'Export-GuestPolicyReport',
16 | 'Update-ConditionalAccessPolicyGuestTypes'
17 | )
18 | PrivateData = @{
19 | PSData = @{
20 | Tags = @('ConditionalAccess', 'Azure', 'Security', 'Guest')
21 | ProjectUri = ''
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Module/ConditionalAccess.psm1:
--------------------------------------------------------------------------------
1 | # Import all public functions
2 | Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue |
3 | ForEach-Object { . $_.FullName }
4 |
5 | # Import all private functions
6 | Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue |
7 | ForEach-Object { . $_.FullName }
8 |
9 | # Export public functions
10 | Export-ModuleMember -Function (Get-ChildItem -Path $PSScriptRoot\Public\*.ps1).BaseName
11 |
--------------------------------------------------------------------------------
/Module/Example/15-Exclude-Include-Gues-Roles-CAPs copy 9.ps1:
--------------------------------------------------------------------------------
1 | Import-module 'C:\code\ConditionalAccess\Module\ConditionalAccess.psm1'
2 |
3 | Update-ConditionalAccessPolicyGuestTypes
--------------------------------------------------------------------------------
/Module/Private/Get-GuestUserTypes.ps1:
--------------------------------------------------------------------------------
1 | function Get-GuestUserTypes {
2 | [CmdletBinding()]
3 | param()
4 |
5 | @(
6 | [PSCustomObject]@{
7 | DisplayName = "Internal guest users"
8 | Id = "internalGuest"
9 | Description = "Guest users within your organization"
10 | Category = "Internal"
11 | },
12 | [PSCustomObject]@{
13 | DisplayName = "B2B collaboration guest users"
14 | Id = "b2bCollaborationGuest"
15 | Description = "Users invited to collaborate with your organization"
16 | Category = "B2B"
17 | },
18 | [PSCustomObject]@{
19 | DisplayName = "B2B collaboration member users"
20 | Id = "b2bCollaborationMember"
21 | Description = "Members from other organizations"
22 | Category = "B2B"
23 | },
24 | [PSCustomObject]@{
25 | DisplayName = "B2B direct connect users"
26 | Id = "b2bDirectConnectUser"
27 | Description = "Users connecting directly from partner organizations"
28 | Category = "B2B"
29 | },
30 | [PSCustomObject]@{
31 | DisplayName = "Other external users"
32 | Id = "otherExternalUser"
33 | Description = "All other types of external users"
34 | Category = "External"
35 | },
36 | [PSCustomObject]@{
37 | DisplayName = "Service provider users"
38 | Id = "serviceProvider"
39 | Description = "Users from service provider organizations"
40 | Category = "External"
41 | }
42 | ) | Sort-Object Category, DisplayName
43 | }
--------------------------------------------------------------------------------
/Module/Private/Show-GuestOperationMenu.ps1:
--------------------------------------------------------------------------------
1 | function Show-GuestOperationMenu {
2 | [CmdletBinding()]
3 | param()
4 |
5 | $menuText = @"
6 |
7 | ====== Conditional Access Policy Guest Operation ======
8 |
9 | Select an operation:
10 | [I] Include Selected Guest Types
11 | [E] Exclude Selected Guest Types
12 | [C] Cancel Operation
13 |
14 | Enter your choice [I/E/C]:
15 | "@
16 |
17 | do {
18 | $choice = Read-Host -Prompt $menuText
19 | switch ($choice.ToUpper()) {
20 | 'I' { return 'Include' }
21 | 'E' { return 'Exclude' }
22 | 'C' { return 'Cancel' }
23 | default {
24 | Write-Host "Invalid selection. Please try again." -ForegroundColor Yellow
25 | }
26 | }
27 | } while ($true)
28 | }
29 |
--------------------------------------------------------------------------------
/Module/Public/Export-GuestPolicyReport.ps1:
--------------------------------------------------------------------------------
1 | function Export-GuestPolicyReport {
2 | [CmdletBinding()]
3 | param(
4 | [Parameter(Mandatory)]
5 | [object[]]$Results,
6 |
7 | [Parameter(Mandatory)]
8 | [string]$OutputDir,
9 |
10 | [Parameter()]
11 | [string]$ReportName = "GuestPolicy_Update"
12 | )
13 |
14 | $reportParams = @{
15 | OutputDir = $OutputDir
16 | ReportName = $ReportName
17 | Results = $Results
18 | Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
19 | }
20 |
21 | $reportPaths = @{
22 | HTML = Join-Path $OutputDir "$($ReportName)_$($reportParams.Timestamp).html"
23 | CSV = Join-Path $OutputDir "$($ReportName)_$($reportParams.Timestamp).csv"
24 | }
25 |
26 | # Ensure output directory exists
27 | $null = New-Item -ItemType Directory -Force -Path $OutputDir
28 |
29 | # Export to CSV
30 | $Results | Export-Csv -Path $reportPaths.CSV -NoTypeInformation
31 |
32 | # Generate HTML report
33 | New-HTML -TitleText "Guest Policy Update Report" -FilePath $reportPaths.HTML -ShowHTML {
34 | New-HTMLSection -HeaderText "Policy Update Summary" {
35 | New-HTMLPanel {
36 | New-HTMLText -Text @"
37 | Update Details
38 |
39 | - Total Policies Updated: $($Results.Count)
40 | - Successful Updates: $($Results.Where{$_.Status -eq 'Success'}.Count)
41 | - Failed Updates: $($Results.Where{$_.Status -eq 'Failed'}.Count)
42 | - Operation Performed: $($Results[0].Operation)
43 | - Generated On: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
44 |
45 | "@
46 | }
47 | }
48 |
49 | New-HTMLSection -HeaderText "Updated Policies" {
50 | New-HTMLTable -DataTable $Results -ScrollX {
51 | New-TableCondition -Name 'Status' -ComparisonType string -Operator eq -Value 'Success' -BackgroundColor LightGreen -Color Black
52 | New-TableCondition -Name 'Status' -ComparisonType string -Operator eq -Value 'Failed' -BackgroundColor Salmon -Color Black
53 | } -Buttons @('copyHtml5', 'excelHtml5', 'csvHtml5', 'searchBuilder')
54 | }
55 | }
56 |
57 | Write-Host "`nReports generated:" -ForegroundColor Green
58 | Write-Host "CSV Report: $($reportPaths.CSV)" -ForegroundColor Green
59 | Write-Host "HTML Report: $($reportPaths.HTML)" -ForegroundColor Green
60 |
61 | return $reportPaths
62 | }
--------------------------------------------------------------------------------
/Module/Public/Get-ConditionalAccessPoliciesDetails.ps1:
--------------------------------------------------------------------------------
1 | function Get-ConditionalAccessPoliciesDetails {
2 | [CmdletBinding()]
3 | param(
4 | [Parameter()]
5 | [ValidateSet('All', 'Guest', 'AdminRoles')]
6 | [string]$PolicyType = 'All'
7 | )
8 |
9 | try {
10 | Write-Verbose "Retrieving policies from Microsoft Graph..."
11 | $policies = Get-MgIdentityConditionalAccessPolicy -All
12 |
13 | if (-not $policies) {
14 | Write-Warning "No policies retrieved from Microsoft Graph"
15 | return @()
16 | }
17 |
18 | Write-Verbose "Processing $($policies.Count) policies..."
19 | $formattedPolicies = @(foreach ($policy in $policies) {
20 | Write-Verbose "Processing policy: $($policy.DisplayName)"
21 |
22 | # Extract current version from display name
23 | $version = if ($policy.DisplayName -match '-v(\d+\.\d+)$') {
24 | [decimal]$matches[1]
25 | } else {
26 | 1.0
27 | }
28 |
29 | # Build the admin roles status
30 | $adminRolesStatus = [System.Collections.ArrayList]::new()
31 | if ($PolicyType -in @('All', 'AdminRoles')) {
32 | if ($policy.Conditions.Users.IncludeRoles.Count -gt 0) {
33 | $null = $adminRolesStatus.Add("Include: $($policy.Conditions.Users.IncludeRoles.Count) roles")
34 | }
35 |
36 | if ($policy.Conditions.Users.ExcludeRoles.Count -gt 0) {
37 | $null = $adminRolesStatus.Add("Exclude: $($policy.Conditions.Users.ExcludeRoles.Count) roles")
38 | }
39 | }
40 |
41 | # Build the guest status
42 | $guestStatus = [System.Collections.ArrayList]::new()
43 | if ($PolicyType -in @('All', 'Guest')) {
44 | if ($policy.Conditions.Users.IncludeGuestsOrExternalUsers) {
45 | $null = $guestStatus.Add("Include: Guest/External Users")
46 | }
47 |
48 | if ($policy.Conditions.Users.ExcludeGuestsOrExternalUsers) {
49 | $null = $guestStatus.Add("Exclude: Guest/External Users")
50 | }
51 | }
52 |
53 | # Format status strings
54 | $currentAdminRoles = if ($adminRolesStatus.Count -gt 0) {
55 | $adminRolesStatus -join ' | '
56 | } else {
57 | "No admin roles configured"
58 | }
59 |
60 | $currentGuestStatus = if ($guestStatus.Count -gt 0) {
61 | $guestStatus -join ' | '
62 | } else {
63 | "No guest configuration"
64 | }
65 |
66 | # Create output object based on PolicyType
67 | $outputObject = [ordered]@{
68 | DisplayName = $policy.DisplayName
69 | Id = $policy.Id
70 | State = $policy.State
71 | Version = $version
72 | }
73 |
74 | # Add type-specific properties based on PolicyType
75 | switch ($PolicyType) {
76 | 'All' {
77 | $outputObject['CurrentAdminRoles'] = $currentAdminRoles
78 | $outputObject['CurrentGuestStatus'] = $currentGuestStatus
79 | }
80 | 'Guest' {
81 | $outputObject['CurrentGuestStatus'] = $currentGuestStatus
82 | }
83 | 'AdminRoles' {
84 | $outputObject['CurrentAdminRoles'] = $currentAdminRoles
85 | }
86 | }
87 |
88 | [PSCustomObject]$outputObject
89 | })
90 |
91 | Write-Verbose "Returning $($formattedPolicies.Count) formatted policies"
92 | return $formattedPolicies
93 | }
94 | catch {
95 | Write-Error "Failed to retrieve or process Conditional Access Policies: $_"
96 | return @()
97 | }
98 | }
99 |
100 |
101 |
102 | # # Get all policy details
103 | # Get-ConditionalAccessPoliciesDetails -PolicyType All
104 |
105 | # # Get only guest-related details
106 | # Get-ConditionalAccessPoliciesDetails -PolicyType Guest
107 |
108 | # # Get only admin role details
109 | # Get-ConditionalAccessPoliciesDetails -PolicyType AdminRoles
110 |
111 | # # With verbose output
112 | # Get-ConditionalAccessPoliciesDetails -PolicyType All -Verbose
--------------------------------------------------------------------------------
/Module/Public/Update-ConditionalAccessPolicyGuestTypes.ps1:
--------------------------------------------------------------------------------
1 |
2 | function Update-ConditionalAccessPolicyGuestTypes {
3 | [CmdletBinding()]
4 | param(
5 | [Parameter()]
6 | [string]$OutputPath = ".\Reports"
7 | )
8 |
9 | try {
10 | # Show welcome message
11 | Write-Host "`nConditional Access Policy Guest Types Update Tool" -ForegroundColor Cyan
12 | Write-Host "=================================================" -ForegroundColor Cyan
13 |
14 | # Get operation type
15 | $operation = Show-GuestOperationMenu
16 | if ($operation -eq 'Cancel') {
17 | Write-Host "`nOperation cancelled by user." -ForegroundColor Yellow
18 | return
19 | }
20 |
21 | Write-Host "`nSelected Operation: $operation" -ForegroundColor Green
22 |
23 | # Get current policies
24 | Write-Host "`nRetrieving current policy information..." -ForegroundColor Cyan
25 | $policies = Get-ConditionalAccessPoliciesDetails
26 |
27 | if (-not $policies) {
28 | Write-Warning "No policies found to process."
29 | return
30 | }
31 |
32 | # Select policies to update
33 | Write-Host "`nSelect policies to update..." -ForegroundColor Cyan
34 | $selectedPolicies = $policies |
35 | Out-GridView -Title "Select Conditional Access Policies to Modify" -PassThru
36 |
37 | if (-not $selectedPolicies) {
38 | Write-Warning "No policies selected for processing."
39 | return
40 | }
41 |
42 | # Select guest types
43 | Write-Host "`nSelect guest types to $($operation.ToLower())..." -ForegroundColor Cyan
44 | $guestTypes = Get-GuestUserTypes
45 |
46 | $selectedGuestTypes = $guestTypes |
47 | Out-GridView -Title "Select Guest Types to $operation" -PassThru
48 |
49 | if (-not $selectedGuestTypes) {
50 | Write-Warning "No guest types selected. Operation cancelled."
51 | return
52 | }
53 |
54 | # Enhanced operation summary
55 | Write-Host "`nOperation Summary:" -ForegroundColor Cyan
56 | Write-Host "==================" -ForegroundColor Cyan
57 | Write-Host "Operation: $operation guest/external users" -ForegroundColor White
58 | Write-Host "`nSelected Policies:" -ForegroundColor White
59 | $selectedPolicies | ForEach-Object { Write-Host "- $($_.DisplayName)" -ForegroundColor Gray }
60 | Write-Host "`nSelected Guest Types:" -ForegroundColor White
61 | $selectedGuestTypes | ForEach-Object { Write-Host "- $($_.DisplayName)" -ForegroundColor Gray }
62 |
63 | $confirm = Read-Host "`nDo you want to proceed? [Y/N]"
64 | if ($confirm -notmatch '^[Yy]$') {
65 | Write-Host "`nOperation cancelled by user." -ForegroundColor Yellow
66 | return
67 | }
68 |
69 | $results = [System.Collections.ArrayList]::new()
70 |
71 | foreach ($policy in $selectedPolicies) {
72 | try {
73 | Write-Host "`nProcessing policy: $($policy.DisplayName)" -ForegroundColor Cyan
74 |
75 | # Create update body
76 | $bodyParams = @{
77 | conditions = @{
78 | users = @{
79 | "$($operation.ToLower())GuestsOrExternalUsers" = @{
80 | guestOrExternalUserTypes = $selectedGuestTypes.Id -join ','
81 | externalTenants = @{
82 | membershipKind = "all"
83 | }
84 | }
85 | }
86 | }
87 | }
88 |
89 | # Update policy
90 | $null = Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.Id -BodyParameter $bodyParams
91 |
92 | $null = $results.Add([PSCustomObject]@{
93 | PolicyName = $policy.DisplayName
94 | PolicyId = $policy.Id
95 | Operation = $operation
96 | GuestTypesUpdated = $selectedGuestTypes.DisplayName -join ', '
97 | Status = 'Success'
98 | ErrorMessage = ''
99 | })
100 |
101 | Write-Host "Successfully updated policy: $($policy.DisplayName)" -ForegroundColor Green
102 | }
103 | catch {
104 | $errorMessage = $_.Exception.Message
105 |
106 | $null = $results.Add([PSCustomObject]@{
107 | PolicyName = $policy.DisplayName
108 | PolicyId = $policy.Id
109 | Operation = $operation
110 | GuestTypesUpdated = ''
111 | Status = 'Failed'
112 | ErrorMessage = $errorMessage
113 | })
114 |
115 | Write-Warning "Failed to update policy $($policy.DisplayName): $errorMessage"
116 | }
117 | }
118 |
119 | if ($results.Count -gt 0) {
120 | Export-GuestPolicyReport -Results $results -OutputDir $OutputPath
121 | }
122 |
123 | return $results
124 | }
125 | catch {
126 | Write-Error "Operation failed: $_"
127 | }
128 | }
--------------------------------------------------------------------------------
/Module/en-US/about_ConditionalAccess.help.txt:
--------------------------------------------------------------------------------
1 | TOPIC
2 | about_ConditionalAccess
3 |
4 | SHORT DESCRIPTION
5 | A PowerShell module for managing Azure AD Conditional Access Policies with focus on Guest Access.
6 |
7 | LONG DESCRIPTION
8 | The ConditionalAccess module provides cmdlets for managing and updating Azure AD Conditional Access
9 | Policies, specifically focusing on guest access configurations. It allows you to:
10 |
11 | - Retrieve details about existing Conditional Access policies
12 | - Update guest access configurations (Include/Exclude)
13 | - Generate detailed reports of policy changes
14 | - Manage different guest user types
15 |
16 | COMMANDS
17 | Get-ConditionalAccessPoliciesDetails
18 | Retrieves and formats details about existing Conditional Access policies
19 |
20 | Export-GuestPolicyReport
21 | Generates HTML and CSV reports for policy updates
22 |
23 | Update-ConditionalAccessPolicyGuestTypes
24 | Updates guest configurations in Conditional Access policies
25 |
26 | EXAMPLES
27 | Get policy details:
28 | Get-ConditionalAccessPoliciesDetails
29 |
30 | Update guest configurations:
31 | Update-ConditionalAccessPolicyGuestTypes -OutputPath "C:\Reports"
32 |
33 | KEYWORDS
34 | - ConditionalAccess
35 | - Azure
36 | - Security
37 | - Guest Access
38 | - Policies
39 |
40 | SEE ALSO
41 | Online version: [Your documentation URL]
42 | Microsoft Graph documentation: https://docs.microsoft.com/graph/api/resources/conditionalaccesspolicy
43 |
--------------------------------------------------------------------------------
/Modules.json:
--------------------------------------------------------------------------------
1 | {
2 | "requiredModules": [
3 | "Microsoft.Graph.Authentication",
4 | "Microsoft.Graph.Applications",
5 | "Microsoft.Graph.Identity.DirectoryManagement",
6 | "Microsoft.Graph.Users",
7 | "Microsoft.Graph.Beta.Identity.SignIns"
8 | ],
9 | "importedModules": [
10 | "Microsoft.Graph.Identity.DirectoryManagement",
11 | "Microsoft.Graph.Authentication",
12 | "Microsoft.Graph.Identity.DirectoryManagement",
13 | "Microsoft.Graph.Applications",
14 | "Microsoft.Graph.Users",
15 | "Microsoft.Graph.Beta.Identity.SignIns"
16 | ]
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Modern Conditional Access Baseline 2025
2 |
3 | This repository contains a comprehensive set of Conditional Access (CA) policies and PowerShell management tools for Microsoft Entra ID (formerly Azure AD), designed to enhance your organization's security posture while maintaining usability.
4 |
5 | ## 🙏 Acknowledgments
6 |
7 | This project builds upon the excellent work of:
8 | - Kenneth van Surksum ([@kennethvs](https://github.com/kennethvs)) - Original CA baseline policies
9 | - Daniel Chronlund ([@DanielChronlund](https://github.com/DanielChronlund)) - DC Toolbox CA implementations
10 |
11 | ## 📋 Prerequisites
12 |
13 | Before implementing these baselines, ensure:
14 |
15 | 1. Security Defaults are disabled in your tenant
16 | 2. Legacy Per-User MFA is disabled for all users (except unlicensed accounts if necessary)
17 | 3. Required licenses are available for your users
18 | 4. Basic familiarity with Conditional Access concepts
19 |
20 | ## 🏗️ Implementation Components
21 |
22 | ### Required Infrastructure
23 | - 42 Entra ID Groups for inclusion/exclusion management
24 | - 44 Conditional Access policies
25 | - Supporting Intune MAM/APP policies
26 |
27 | ### Policy Modes
28 | - Most policies are deployed in "Report-only" mode for impact assessment
29 | - Compliance-check policies are set to "Off" mode initially to prevent unexpected authentication prompts
30 |
31 | ## 🛠️ Recommended Tools
32 |
33 | ### Policy Deployment
34 | - [Intune Management Tool](https://github.com/Micke-K/IntuneManagement) - For importing and managing policies
35 |
36 | ### Policy Visualization
37 | - [IdPowerToys](https://idpowertoys.merill.net/) - For visualizing and understanding policy interactions
38 |
39 | ## 📝 Best Practices
40 |
41 | 1. **Group-Based Assignment**
42 | - Always use groups for inclusions/exclusions instead of direct user assignments
43 | - Enables easier management and automated import via Intune Management Tool
44 |
45 | 2. **Staged Rollout**
46 | - Start with policies in report-only mode
47 | - Use provided PowerShell tools to analyze sign-in logs
48 | - Assess impact before enabling enforcement
49 |
50 | 3. **Policy Management**
51 | - Maintain documentation of policy exceptions
52 | - Regular review of policy effectiveness
53 | - Monitor for policy conflicts
54 |
55 | ## 🚀 Implementation Guide
56 |
57 | 1. Clone this repository
58 | 2. Create required Entra ID groups
59 | 3. Import baseline policies using Intune Management Tool
60 | 4. Review and customize policies for your environment
61 | 5. Use provided PowerShell tools to monitor impact
62 | 6. Gradually enable enforcement based on analysis
63 |
64 | ## 📊 Included Tools
65 |
66 | This repository includes PowerShell scripts for:
67 | - Managing user/group assignments
68 | - Analyzing sign-in logs for report-only policies
69 | - Impact assessment reporting
70 | - Policy compliance monitoring
71 |
72 | ## 🔜 Future Plans
73 |
74 | - Enhanced PowerShell tools for sign-in log analysis
75 | - Automated impact assessment reporting
76 | - Additional compliance templates
77 | - Integration with Microsoft Graph API
78 | - Additional baseline policies for specific scenarios
79 |
80 | ## 📚 Documentation
81 |
82 | Detailed documentation for each component is available in the respective folders:
83 | - `/policies` - Baseline CA policies
84 | - `/scripts` - PowerShell management tools
85 | - `/docs` - Implementation guides and best practices
86 |
87 | ## 🤝 Contributing
88 |
89 | Contributions are welcome! Please read our contributing guidelines before submitting pull requests.
90 |
91 | ## 📄 License
92 |
93 | This project is licensed under the MIT License - see the LICENSE file for details.
94 |
95 | ## 💬 Support
96 |
97 | For issues and feature requests, please use the GitHub issues section.
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "PackageName": "BuildEntraAppRegCertBasedwithGraph",
3 | "PackageUniqueGUID": "7b34084e-b856-40f5-9a5b-32b3249fb777",
4 | "Version": 1,
5 | "PackageExecutionContext": "SYSTEM",
6 | "RepetitionInterval": "PT60M",
7 | "LoggingDeploymentName": "BuildEntraAppRegCertBasedwithGraphCustomlog",
8 | "ScriptMode": "Remediation",
9 | "RunOnDemand": true
10 | }
--------------------------------------------------------------------------------
/modulesexclusion.json:
--------------------------------------------------------------------------------
1 | [
2 |
3 | ]
4 |
--------------------------------------------------------------------------------
/scopes.json:
--------------------------------------------------------------------------------
1 | {
2 | "Scopes": [
3 | "User.Read",
4 | "User.ReadWrite",
5 | "User.ReadBasic.All",
6 | "Mail.Read",
7 | "Mail.ReadWrite",
8 | "Mail.Send",
9 | "Calendars.Read",
10 | "Calendars.ReadWrite",
11 | "Contacts.Read",
12 | "Contacts.ReadWrite",
13 | "Files.Read",
14 | "Files.ReadWrite",
15 | "Sites.Read.All",
16 | "Sites.ReadWrite.All",
17 | "Group.Read.All",
18 | "Group.ReadWrite.All",
19 | "Directory.Read.All",
20 | "Directory.ReadWrite.All",
21 | "Application.Read.All",
22 | "Application.ReadWrite.All",
23 | "Device.Read",
24 | "DeviceManagementApps.Read.All",
25 | "DeviceManagementApps.ReadWrite.All",
26 | "DeviceManagementConfiguration.Read.All",
27 | "DeviceManagementConfiguration.ReadWrite.All",
28 | "Organization.Read.All",
29 | "Organization.ReadWrite.All",
30 | "Policy.Read.All",
31 | "Policy.ReadWrite.ConditionalAccess",
32 | "DeviceManagementApps.ReadWrite.All",
33 | "AppRoleAssignment.ReadWrite.All"
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------