# Cascades of Tucson — Enable Caregiver Password Rotation via FGPP # Run on: CS-SERVER as a domain admin # # Step 1: Creates a Fine-Grained Password Policy (PSO) with 30-day max age. # Step 2: Applies it to SG-Caregivers. # Step 3: Clears PasswordNeverExpires on all caregiver accounts so the FGPP takes effect. # # IMPORTANT: Run create-caregiver-accounts.ps1 first (accounts must exist before step 3). # # After this runs: # - Caregiver passwords expire after 30 days # - No warning prompt on Android/MSDM phones (that prompt is Windows-only) # - When a caregiver's sign-in fails, Howard resets via ADUC or GuruRMM # - The "Interactive logon: Prompt user to change password before expiration" GPO # setting (5 days) only affects Windows PC logons — not relevant for shared phones $PolicyName = "PSO-Caregivers-30day" $Group = "SG-Caregivers" # --- Step 1: Create FGPP --- if (Get-ADFineGrainedPasswordPolicy -Filter "Name -eq '$PolicyName'" -ErrorAction SilentlyContinue) { Write-Host "[SKIP] FGPP '$PolicyName' already exists" } else { New-ADFineGrainedPasswordPolicy ` -Name $PolicyName ` -Precedence 10 ` -MaxPasswordAge "30.00:00:00" ` -MinPasswordAge "1.00:00:00" ` -MinPasswordLength 8 ` -PasswordHistoryCount 5 ` -ComplexityEnabled $true ` -LockoutThreshold 5 ` -LockoutDuration "00:30:00" ` -LockoutObservationWindow "00:30:00" ` -ReversibleEncryptionEnabled $false Write-Host "[OK] FGPP '$PolicyName' created (30-day max age, precedence 10)" } # --- Step 2: Apply FGPP to SG-Caregivers --- $existing = Get-ADFineGrainedPasswordPolicySubject -Identity $PolicyName -ErrorAction SilentlyContinue | Where-Object { $_.Name -eq $Group } if ($existing) { Write-Host "[SKIP] FGPP already applied to $Group" } else { Add-ADFineGrainedPasswordPolicySubject -Identity $PolicyName -Subjects $Group Write-Host "[OK] FGPP applied to $Group" } # --- Step 3: Clear PasswordNeverExpires on all caregiver accounts --- Write-Host "" Write-Host "Clearing PasswordNeverExpires on members of $Group..." $cleared = 0 $failed = 0 Get-ADGroupMember -Identity $Group -Recursive | ForEach-Object { try { Set-ADUser $_.SamAccountName -PasswordNeverExpires $false Write-Host "[OK] $($_.SamAccountName)" $cleared++ } catch { Write-Host "[ERROR] $($_.SamAccountName) — $_" $failed++ } } Write-Host "" Write-Host "Done. PasswordNeverExpires cleared on $cleared accounts | $failed failed" Write-Host "FGPP '$PolicyName' is now active for $Group — passwords expire in 30 days." Write-Host "" Write-Host "Verify FGPP is applied correctly with:" Write-Host " Get-ADUserResultantPasswordPolicy -Identity "