CI runners - Set an account lockout threshold at bootstrap so a SQL login can be locked out - #10718
Conversation
…ogin can be locked out The base image sets no Windows account lockout threshold, so LOGINPROPERTY(login, 'IsLocked') stays 0 on a runner no matter how many logons fail, and the Set-DbaLogin unlock test cannot pass on CI (#10529). bootstrap-runner.ps1 now runs net accounts with a threshold of five, a duration and an observation window of ten minutes, next to the other local policy knob it already sets. SQL Server reads the local policy of the machine running the instance and the runners are not domain joined, so the local value is the one that counts. The bootstrap script is fetched from the default branch for every fresh VM, so this takes effect on merge without an image rebuild. A contract test pins the threshold at five or lower and its place before the runner takes its job. (do Set-DbaLogin) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
potatoqualitee
left a comment
There was a problem hiding this comment.
Reviewed the complete bootstrap/test change, runner workflows, linked issues, ordering, policy semantics, and exact-head CI. The lockout values are coherent and applied before runner registration in the privileged bootstrap context; I found no concrete material defect. The added test is a source-contract check rather than live policy proof, which the PR description already discloses.
|
thank you 🙏🏼 |
|
One more step is needed before this takes effect on the runners: the fleet controller bundles its own copy of created by Claude and reviewed by Andreas Jordan |
Fixes #10529, which blocks the
unlocks a login that was locked outtest in #10537.What is missing
The self-hosted runner image sets no Windows account lockout threshold. Without one,
LOGINPROPERTY(login, 'IsLocked')stays0on a runner no matter how many logons fail, so no test can cover unlocking a login, and theSet-DbaLoginunlock test in #10537 is knowingly red on CI.The change
bootstrap-runner.ps1runsnext to the
LocalAccountTokenFilterPolicyknob it already sets, with a warning line in the run-command output ifnet accountsfails. The threshold is five because the test fails exactly five logons; duration and window only decide when Windows would release the lock by itself, the test unlocks explicitly.Why the bootstrap and not the image
The issue proposed the image build. The bootstrap is the better place:
runner-scale-up.ymlandrunner-reconcile.ymlfetchbootstrap-runner.ps1fromraw.githubusercontent.comat the default branch for every fresh VM. An image change waits for the nextbuild-modern-image.ps1run and a VMSS repoint.sysprep /generalize. At boot time there is nothing to survive.Scope
The setting applies to the local account database of the runner VM only. The runners are not domain joined, so no domain policy overwrites it later. The practical effect on tests is that a SQL login with
CHECK_POLICY = ONlocks after five bad passwords, which is what the unlock test needs; the VM is single-use and deleted after its job.Tests
.github/runners/tests/bootstrap-runner.Tests.ps1gains a contract test that the script sets a lockout threshold of five or lower beforeconfig.cmdregisters the runner. Against development's script it fails on the first assertion, the missingnet accountsline. Both editions pass the file 11/11 with the change.Verification
What I could and could not verify:
CHECK_POLICYlogin locks after five bad logons,Set-DbaLogin.Tests.ps1passes 45/45). The lab hosts get the value through Group Policy, so that proves SQL Server follows the local value, not thenet accountsline itself.SINGLElane of the firstdevelopmentpush after the merge, or a rerun of Set-DbaLogin - Return the login as it is after unlocking it with a new password #10537's CI once the reconcile has cycled the fleet.created by Claude and reviewed by Andreas Jordan
🤖 Generated with Claude Code