-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathDetect-Remediate-LockToUser.ps1
More file actions
618 lines (546 loc) · 28.3 KB
/
Detect-Remediate-LockToUser.ps1
File metadata and controls
618 lines (546 loc) · 28.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
<#
.SYNOPSIS
Restricts local logon rights (SeInteractiveLogonRight) to only authorized accounts on the device.
Ensures that only the device owner, local administrators, and necessary service accounts can log on locally.
Designed for Microsoft Intune deployment as a detection and remediation script.
.DESCRIPTION
This script enforces device security by restricting the "Allow log on locally" security policy
(SeInteractiveLogonRight) to a controlled list of authorized accounts. This prevents unauthorized
users from logging on to devices that don't belong to them.
The script locks down the device by allowing ONLY the following accounts to log on locally:
- Built-in Administrators group (S-1-5-32-544)
- The currently logged-on user (device owner)
- A trusted administrative group (configurable)
- WSI service account (if enabled)
- MEM service accounts for device management (if enabled)
Any other accounts are explicitly denied local logon rights, ensuring devices remain locked
to their assigned users.
Version 3.0 adds comprehensive account validation and dynamic MEM service account support.
The script operates in two phases:
DETECTION PHASE:
1. Identifies currently logged-on users
2. Verifies all required accounts have SeInteractiveLogonRight permission
3. Reports compliance status for each account
4. Exits with code 1 if any required account is missing (triggers remediation in Intune)
REMEDIATION PHASE (if enabled):
1. Rebuilds the SeInteractiveLogonRight policy with ONLY authorized accounts
2. Removes any unauthorized accounts that may have been added
3. Validates configuration before applying
4. Uses retry logic for reliability
5. Exits with code 0 on success
.PARAMETER runDetection
Whether to run the detection phase. Cannot be set to false as detection is required.
Default: $true
.PARAMETER runRemediation
Whether to run the remediation phase if issues are detected.
Default: $false
.PARAMETER trustedGroup
The trusted group to include in the security policy.
IMPORTANT: This should be changed to match your organization's trusted admin group.
Default: "DOMAIN\Trusted Group"
.PARAMETER includeWSIAccount
Whether to include the WSI account in the security policy.
The account will be added using its SID for better compatibility.
Default: $true
.PARAMETER wsiAccountName
The name of the WSI account to include in the security policy.
Default: "wsiaccount"
.PARAMETER includeMEMAccount
Whether to include MEM service accounts based on logged-on users.
The account will be dynamically constructed as MEM\KM_<USERNAME>_$
IMPORTANT: The NetBIOS domain portion (MEM\KM_) must be manually changed in the script
if your organization uses a different naming convention for MEM service accounts.
Default: $true
.EXAMPLE
.\Detect-Remediate-LockToUser.ps1
Runs detection only with default settings (remediation disabled by default).
.EXAMPLE
.\Detect-Remediate-LockToUser.ps1 -runRemediation $true
Runs both detection and remediation with default settings.
.EXAMPLE
.\Detect-Remediate-LockToUser.ps1 -Verbose
Runs with verbose output for troubleshooting.
.EXAMPLE
.\Detect-Remediate-LockToUser.ps1 -includeMEMAccount $false -runRemediation $true
Runs detection and remediation but excludes MEM service accounts.
.NOTES
Filename: Detect-Remediate-LockToUser.ps1
Version: 3.0
Author: Martin Bengtsson
Blog: www.imab.dk
Twitter: @mwbengtsson
Version History:
3.0 - Added comprehensive detection for all required accounts (not just users)
- Added dynamic MEM service account support (MEM\KM_<USERNAME>_$)
- Detection now validates: logged-on users, trusted group, WSI account, and MEM accounts
- All missing accounts are flagged during detection phase
- Remediation adds all required accounts in a single operation
- Enhanced parameter documentation
- Added new parameter: includeMEMAccount
- Fixed comparison logic to handle both SID format and account name format
- NOTE: MEM account NetBIOS domain (MEM\KM_) must be manually configured in script
2.0 - Enhanced error handling for secedit operations
- Added retry logic for failed secedit operations
- Improved WSI account handling using SID format
- Added configuration validation before applying changes
- Better error diagnostics with specific guidance for common issues
- Robust temporary file management
1.1 - Previous version
Requirements:
- Administrative privileges
- Windows with secedit.exe available
.LINK
https://www.imab.dk/configure-allow-logon-locally-automatically-using-powershell-and-microsoft-intune/
#>
[CmdletBinding()]
param (
[parameter(Mandatory=$false, HelpMessage="Whether to run the detection phase. Cannot be disabled.")]
[ValidateNotNullOrEmpty()]
[bool]$runDetection = $true,
[parameter(Mandatory=$false, HelpMessage="Whether to run the remediation phase if issues are detected.")]
[ValidateNotNullOrEmpty()]
[bool]$runRemediation = $false,
[parameter(Mandatory=$false, HelpMessage="The trusted group to include in the security policy. Change to match your organization.")]
[ValidateNotNullOrEmpty()]
[string]$trustedGroup = "DOMAIN\Trusted Group", # CUSTOMIZE: Change to your organization's trusted admin group
[parameter(Mandatory=$false, HelpMessage="Whether to include the WSI account in the security policy.")]
[bool]$includeWSIAccount = $true,
[parameter(Mandatory=$false, HelpMessage="The name of the WSI account to include in the security policy.")]
[ValidateNotNullOrEmpty()]
[string]$wsiAccountName = "wsiaccount",
[parameter(Mandatory=$false, HelpMessage="Whether to include the MEM service account based on logged-on user.")]
[bool]$includeMEMAccount = $true
)
begin {
function Test-UserLoggedOn() {
Write-Verbose "Checking if any users are currently logged on..."
try {
$explorerProcesses = Get-Process -Name explorer -ErrorAction SilentlyContinue
if ($explorerProcesses) {
Write-Verbose "Found $($explorerProcesses.Count) explorer process(es) - users are logged on"
return $true
} else {
Write-Verbose "No explorer processes found - no users logged on"
return $false
}
}
catch {
Write-Error "Failed to check for logged on users: $_"
return $false
}
}
function Get-LoggedOnUsers() {
Write-Verbose "Retrieving currently logged on users..."
try {
$loggedOnUser = (Get-Process -Name explorer -IncludeUserName | Select-Object UserName -Unique).UserName
if (-NOT[string]::IsNullOrEmpty($loggedOnUser)) {
Write-Verbose "Found logged on user(s): $($loggedOnUser -join ', ')"
Write-Output $loggedOnUser
}
else {
Write-Verbose "No logged on users found"
$null = $loggedOnUser
}
}
catch {
Write-Error "Failed to retrieve the username of the logged on user: $_"
throw
}
}
function Get-AccountSID() {
param (
[string]$commonName
)
Write-Verbose "Getting SID for account: $commonName"
try {
$account = New-Object System.Security.Principal.NTAccount($commonName)
$accountSID = $account.Translate([System.Security.Principal.SecurityIdentifier])
if (-NOT[string]::IsNullOrEmpty($accountSID)) {
Write-Verbose "SID for $commonName is: $accountSID"
Write-Output $accountSID
}
else {
$null = $accountSID
}
}
catch {
Write-Error "Failed to retrieve the SID of the user: $_"
throw
}
}
function Test-SeInteractiveLogonRightConfig() {
param (
[string]$configLine
)
Write-Verbose "Validating SeInteractiveLogonRight configuration: $configLine"
if ([string]::IsNullOrEmpty($configLine)) {
Write-Error "Configuration line is empty"
return $false
}
if (-not $configLine.StartsWith("SeInteractiveLogonRight = ")) {
Write-Error "Configuration line does not start with 'SeInteractiveLogonRight = '"
return $false
}
# Extract the accounts part
$accountsPart = $configLine.Substring("SeInteractiveLogonRight = ".Length)
if ([string]::IsNullOrEmpty($accountsPart)) {
Write-Error "No accounts specified in configuration"
return $false
}
# Split and validate each account
$accounts = $accountsPart -split ","
foreach ($account in $accounts) {
$trimmedAccount = $account.Trim()
if ([string]::IsNullOrEmpty($trimmedAccount)) {
Write-Error "Empty account found in configuration"
return $false
}
# Check if it's a SID (starts with *S-) or account name
if ($trimmedAccount.StartsWith("*S-")) {
# Validate SID format (basic check)
if ($trimmedAccount -notmatch "^\*S-\d+-\d+(-\d+)*$") {
Write-Error "Invalid SID format: $trimmedAccount"
return $false
}
} elseif (-not $trimmedAccount.Contains("\")) {
# Account names should contain domain\username format for most cases
Write-Warning "Account '$trimmedAccount' may not be in proper domain\username format"
}
}
Write-Verbose "Configuration validation passed"
return $true
}
function Get-SeInterActiveLogonRightConfig() {
try {
Write-Verbose "Exporting security configuration to temporary file..."
$exportResult = secedit.exe /export /cfg $global:tmpFile 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Error "secedit.exe export failed with exit code: $LASTEXITCODE. Output: $exportResult"
throw "Failed to export security configuration"
}
if (-not (Test-Path $global:tmpFile)) {
Write-Error "Temporary file was not created: $global:tmpFile"
throw "Security configuration export did not create expected file"
}
$fileContent = Get-Content $global:tmpFile -ErrorAction Stop
if (-not $fileContent) {
Write-Error "Temporary file is empty or unreadable: $global:tmpFile"
throw "Security configuration file is empty"
}
$currentConfig = $fileContent | Where-Object { $_ -like "SeInterActiveLogonRight*" }
if (-NOT[string]::IsNullOrEmpty($currentConfig)) {
Write-Verbose "Current SeInteractiveLogonRight configuration: $currentConfig"
Write-Output $currentConfig
}
else {
Write-Warning "SeInteractiveLogonRight not found in security configuration"
$null = $currentConfig
}
}
catch {
Write-Error "Failed to retrieve the current configuration of SeInteractiveLogonRight: $_"
throw
}
}
function Set-SeInterActiveLogonRightConfig() {
param (
[string]$currentConfig,
[string]$newConfig
)
Write-Verbose "Applying new SeInteractiveLogonRight configuration..."
try {
# Validate inputs
if ([string]::IsNullOrEmpty($currentConfig)) {
throw "Current configuration is empty or null"
}
if ([string]::IsNullOrEmpty($newConfig)) {
throw "New configuration is empty or null"
}
# Validate temporary file exists and is readable
if (-not (Test-Path $global:tmpFile)) {
throw "Temporary file does not exist: $global:tmpFile"
}
# Validate the new configuration before applying
if (-not (Test-SeInteractiveLogonRightConfig -configLine $newConfig)) {
throw "New configuration failed validation: $newConfig"
}
# Update the configuration file
Write-Verbose "Updating configuration file with new policy..."
$content = Get-Content $global:tmpFile -ErrorAction Stop
$updatedContent = $content -replace [regex]::Escape($currentConfig), $newConfig
$updatedContent | Set-Content $global:tmpFile -ErrorAction Stop
# Verify the replacement was successful
$verifyContent = Get-Content $global:tmpFile -ErrorAction Stop
if ($verifyContent -notcontains $newConfig) {
throw "Failed to update configuration file - new configuration not found"
}
Write-Verbose "New configuration written to file: $newConfig"
# Apply the configuration with retry logic
$maxRetries = 3
$retryCount = 0
$success = $false
while ($retryCount -lt $maxRetries -and -not $success) {
$retryCount++
Write-Verbose "Applying security configuration (attempt $retryCount of $maxRetries)..."
# Create a new database file for each attempt to avoid corruption
$dbFile = "$env:windir\Temp\secedit_$retryCount.sdb"
try {
$configureResult = secedit.exe /configure /db $dbFile /cfg $global:tmpFile /areas USER_RIGHTS /quiet 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Verbose "Security policy updated successfully on attempt $retryCount"
$global:remediationSuccess += $true
$success = $true
} else {
$errorMessage = "secedit.exe configure failed with exit code: $LASTEXITCODE"
if ($configureResult) {
$errorMessage += ". Output: $configureResult"
}
# Provide specific guidance for common exit codes
switch ($LASTEXITCODE) {
1 { $errorMessage += ". This usually indicates a syntax error in the configuration file or invalid account names." }
2 { $errorMessage += ". This usually indicates the specified file could not be found." }
3 { $errorMessage += ". This usually indicates insufficient privileges to modify security policy." }
default { $errorMessage += ". Unknown error code." }
}
if ($retryCount -eq $maxRetries) {
throw $errorMessage
} else {
Write-Warning "$errorMessage Retrying in 2 seconds..."
Start-Sleep -Seconds 2
}
}
} finally {
# Clean up database file
if (Test-Path $dbFile) {
Remove-Item -Path $dbFile -Force -ErrorAction SilentlyContinue
}
}
}
if (-not $success) {
throw "Failed to apply security configuration after $maxRetries attempts"
}
}
catch {
Write-Error "Failed to set the new configuration of SeInteractiveLogonRight: $_"
throw
}
finally {
# Ensure cleanup happens even if there's an error
if (Test-Path $global:tmpFile) {
Remove-Item -Path $global:tmpFile -Force -ErrorAction SilentlyContinue
Write-Verbose "Temporary file cleaned up: $global:tmpFile"
}
}
}
if ($runDetection -eq $false) {
Write-Error "runDetection cannot be set to false. As a minimum runDetection must be set to true."
exit 1
}
# Early check to ensure users are logged on before proceeding
if (-not (Test-UserLoggedOn)) {
Write-Output "[INFO] No users are currently logged on to the computer. Script will exit without making changes."
exit 0
}
}
process {
$global:tmpFile = "$env:windir\Temp\secedit.tmp"
$global:needsRemediation = @()
$global:remediationSuccess = @()
$loggedonUserSID = @()
$loggedOnUsers = Get-LoggedOnUsers
# Get trusted group SID
# IMPORTANT CONFIGURATION NOTE:
# The trusted group is organization-specific and should be changed to match your environment.
# Examples for other organizations:
# - "DOMAIN\IT Administrators"
# - "CORP\Desktop Admins"
# - "AD\Workstation Admins"
# Change the default value in the parameter section above to customize.
$trustedGroupSID = $null
try {
$trustedGroupSID = Get-AccountSID -commonName $trustedGroup
Write-Verbose "Trusted group SID: $trustedGroupSID"
} catch {
Write-Warning "Failed to get SID for trusted group '$trustedGroup': $_."
Write-Warning "Trusted group will be skipped. Please verify the group name is correct."
$trustedGroupSID = $null
}
# Get WSI account SID if enabled
$wsiAccountSID = $null
if ($includeWSIAccount) {
$computerName = $env:COMPUTERNAME
$wsiAccountFullName = "$computerName\$wsiAccountName"
Write-Verbose "Attempting to get SID for WSI account: $wsiAccountFullName"
try {
$wsiAccountSID = Get-AccountSID -commonName $wsiAccountFullName
Write-Verbose "WSI account SID: $wsiAccountSID"
} catch {
Write-Warning "Failed to get SID for WSI account '$wsiAccountFullName': $_. WSI account will be skipped."
$wsiAccountSID = $null
}
}
# Get MEM service account SIDs if enabled (one per logged-on user)
# IMPORTANT CONFIGURATION NOTE:
# The MEM service account naming convention is organization-specific.
# This script is configured for: MEM\KM_<USERNAME>_$
# Where:
# - MEM = NetBIOS domain name for MEM service accounts
# - KM_ = Prefix for the organization
# - <USERNAME> = The logged-on user's username in UPPERCASE
# - _$ = Suffix with dollar sign (common for service accounts)
#
# TO CUSTOMIZE: Change the line below to match your organization's naming convention:
# $memAccountFullName = "MEM\KM_$($username)_`$"
# Example for different organizations:
# $memAccountFullName = "DOMAIN\SVC_$($username)"
# $memAccountFullName = "AD\$($username)_SERVICE`$"
$memAccountSIDs = @()
if ($includeMEMAccount -and -NOT[string]::IsNullOrEmpty($loggedOnUsers)) {
foreach ($loggedOnUser in $loggedOnUsers) {
# Extract username from domain\username format
if ($loggedOnUser -match '\\(.+)$') {
$username = $matches[1].ToUpper()
# CUSTOMIZE THIS LINE for your organization's MEM account naming convention
$memAccountFullName = "MEM\KM_$($username)_`$"
Write-Verbose "Attempting to get SID for MEM service account: $memAccountFullName"
try {
$memAccountSID = Get-AccountSID -commonName $memAccountFullName
$memAccountSIDs += $memAccountSID
Write-Verbose "MEM service account SID: $memAccountSID"
} catch {
Write-Warning "Failed to get SID for MEM account '$memAccountFullName': $_. MEM account will be skipped for user $loggedOnUser."
}
}
}
}
if (-NOT[string]::IsNullOrEmpty($loggedOnUsers)) {
if ($runDetection -eq $true) {
$currentConfig = Get-SeInterActiveLogonRightConfig
$trimCurrentConfig = $currentConfig -split "," | ForEach-Object { ($_ -replace "SeInteractiveLogonRight = ", "").Trim() }
Write-Verbose "Raw current configuration: $currentConfig"
Write-Verbose "Current configured SIDs (count: $($trimCurrentConfig.Count)): $($trimCurrentConfig -join ' | ')"
Write-Verbose "Each configured SID:"
foreach ($sid in $trimCurrentConfig) {
Write-Verbose " - '$sid' (Length: $($sid.Length))"
}
foreach ($loggedOnUser in $loggedOnUsers) {
$loggedonUserSID += Get-AccountSID -commonName $loggedOnUser
}
# Check logged-on users
foreach ($userSID in $loggedonUserSID) {
$sidWithPrefix = "*$($userSID)"
Write-Verbose "Checking if '$sidWithPrefix' is in configuration"
if ($trimCurrentConfig -notcontains $sidWithPrefix) {
Write-Output "[WARNING] the user's SID: $userSID is NOT added to the security policy: SeInteractiveLogonRight"
$global:needsRemediation += $true
}
elseif ($trimCurrentConfig -contains $sidWithPrefix) {
Write-Output "[OK] the user's SID: $userSID is already added to the security policy: SeInteractiveLogonRight"
$global:needsRemediation += $false
}
}
# Check trusted group
if ($trustedGroupSID) {
$sidWithPrefix = "*$($trustedGroupSID.Value)"
Write-Verbose "Checking if trusted group '$sidWithPrefix' is in configuration"
if ($trimCurrentConfig -notcontains $sidWithPrefix) {
Write-Output "[WARNING] Trusted group SID: $($trustedGroupSID.Value) ($trustedGroup) is NOT added to the security policy: SeInteractiveLogonRight"
$global:needsRemediation += $true
}
else {
Write-Output "[OK] Trusted group SID: $($trustedGroupSID.Value) ($trustedGroup) is already added to the security policy: SeInteractiveLogonRight"
$global:needsRemediation += $false
}
}
# Check WSI account
if ($includeWSIAccount -and $wsiAccountSID) {
$sidWithPrefix = "*$($wsiAccountSID.Value)"
$accountNameAlternative = $wsiAccountName
Write-Verbose "Checking if WSI account '$sidWithPrefix' or account name '$accountNameAlternative' is in configuration"
# Check if either the SID format or the account name is present
if (($trimCurrentConfig -notcontains $sidWithPrefix) -and ($trimCurrentConfig -notcontains $accountNameAlternative)) {
Write-Output "[WARNING] WSI account SID: $($wsiAccountSID.Value) is NOT added to the security policy: SeInteractiveLogonRight"
$global:needsRemediation += $true
}
else {
if ($trimCurrentConfig -contains $sidWithPrefix) {
Write-Output "[OK] WSI account SID: $($wsiAccountSID.Value) is already added to the security policy: SeInteractiveLogonRight (as SID)"
} else {
Write-Output "[OK] WSI account is already added to the security policy: SeInteractiveLogonRight (as account name: $accountNameAlternative)"
}
$global:needsRemediation += $false
}
}
# Check MEM service accounts
if ($includeMEMAccount -and $memAccountSIDs.Count -gt 0) {
foreach ($memSID in $memAccountSIDs) {
$sidWithPrefix = "*$($memSID.Value)"
Write-Verbose "Checking if MEM account '$sidWithPrefix' is in configuration"
if ($trimCurrentConfig -notcontains $sidWithPrefix) {
Write-Output "[WARNING] MEM service account SID: $($memSID.Value) is NOT added to the security policy: SeInteractiveLogonRight"
$global:needsRemediation += $true
}
else {
Write-Output "[OK] MEM service account SID: $($memSID.Value) is already added to the security policy: SeInteractiveLogonRight"
$global:needsRemediation += $false
}
}
}
}
if ($runRemediation -eq $true) {
if ($global:needsRemediation -contains $true) {
# Build new configuration starting with built-in Administrators
$newConfig = "SeInteractiveLogonRight = *S-1-5-32-544"
# Add trusted group if available
if ($trustedGroupSID) {
$newConfig += ",*$($trustedGroupSID.Value)"
}
# Add WSI account if enabled and SID was retrieved successfully
if ($includeWSIAccount -and $wsiAccountSID) {
$newConfig += ",*$($wsiAccountSID.Value)"
Write-Verbose "Added WSI account to security policy with SID: $($wsiAccountSID.Value)"
}
# Add MEM service accounts if enabled and SIDs were retrieved successfully
if ($includeMEMAccount -and $memAccountSIDs.Count -gt 0) {
foreach ($memSID in $memAccountSIDs) {
$newConfig += ",*$($memSID.Value)"
Write-Verbose "Added MEM service account to security policy with SID: $($memSID.Value)"
}
}
# Add all logged on user SIDs
foreach ($sid in $loggedonUserSID) {
$newConfig += ",*$($sid.Value)"
}
Write-Verbose "New security policy configuration: $newConfig"
# Validate the new configuration before applying
if (-not (Test-SeInteractiveLogonRightConfig -configLine $newConfig)) {
Write-Error "Generated configuration failed validation. Configuration: $newConfig"
$global:needsRemediation += $false
} else {
Set-SeInterActiveLogonRightConfig -currentConfig $currentConfig -newConfig $newConfig
}
}
}
}
}
end {
# Ensure cleanup of temporary files
if (Test-Path $global:tmpFile) {
Remove-Item -Path $global:tmpFile -Force -ErrorAction SilentlyContinue
Write-Verbose "Final cleanup of temporary file: $global:tmpFile"
}
if ($runDetection -eq $true) {
if ($global:needsRemediation -contains $true -AND $global:remediationSuccess -notcontains $true) {
Write-Output "[WARNING] Config of the security policy: SeInteractiveLogonRight is not as expected. Remediation is needed."
exit 1
}
elseif ($global:remediationSuccess -contains $true -AND $global:remediationSuccess -notcontains $false) {
Write-Output "[OK] Remediation was run successfully. Config of the security policy: SeInteractiveLogonRight is now as expected"
exit 0
}
else {
Write-Output "[OK] Config of the security policy: SeInteractiveLogonRight is as expected. Doing nothing."
exit 0
}
}
}