Skip to content

Backport #543: use SQL per-service SID for folder ACLs (vm_mssql_win)#550

Merged
doherty100 merged 1 commit into
vnextfrom
backport-543-per-service-sid
Jul 7, 2026
Merged

Backport #543: use SQL per-service SID for folder ACLs (vm_mssql_win)#550
doherty100 merged 1 commit into
vnextfrom
backport-543-per-service-sid

Conversation

@doherty100

Copy link
Copy Markdown
Contributor

Closes #549

Summary

Backports theme A of PR #543 into the production modules/vm-mssql-win scripts. Grant-SqlFullControl in Set-MssqlConfiguration.ps1 previously queried the MSSQLSERVER service's logon account (Get-CimInstance … StartName) and granted that account FullControl on the freshly created SQL data ($sqlPath) and errorlog ($sqlErrorlogPath) directories.

This change grants FullControl to the Database Engine per-service SID NT SERVICE\MSSQLSERVER instead. The per-service SID:

  • is present in the service process token regardless of the configured logon account,
  • survives service-account changes, and
  • matches the permissions the SQL Server installer applies to its data directories.

The grant remains non-destructive (SetAccessRule, inheritance preserved), on directories that are freshly created immediately before the call → low risk.

Out of scope (from PR #543)

Theme Verdict Why
B — inheritance disable + clean-slate ACEs Deferred Targets live data/errorlog dirs; needs a deploy + Invoke-UnitTests.ps1 -Module vm_mssql_win -Integration cycle first.
C — C:\Scripts lockdown N/A CustomScriptExtension delivery; no user-writable C:\Scripts.
D — encoding/em-dash fix N/A Module scripts already ASCII-clean.
E — README N/A README documents task identity, not the folder-ACL service account.

Validation

  • PSScriptAnalyzer (CI settings, -Severity Error,Warning): no issues.
  • Non-ASCII scan of edited file: clean.

Reference

Grant-SqlFullControl queried the MSSQLSERVER service's logon account
(Get-CimInstance ... StartName) and granted that account FullControl on the
freshly created SQL data and errorlog directories. Backport the ACL-identity
hardening from PR #543: grant FullControl to the Database Engine per-service
SID 'NT SERVICE\MSSQLSERVER' instead.

The per-service SID is present in the service process token regardless of the
configured logon account, survives service-account changes, and matches the
permissions the SQL Server installer applies to its data directories. The grant
remains non-destructive (SetAccessRule, inheritance preserved), so this is a
low-risk change on the already freshly-created target directories.

Only theme A from PR #543 is backported. Themes B (inheritance disable +
clean-slate ACEs on data/errorlog dirs), C (C:\Scripts lockdown), D (encoding),
and E (README) are out of scope: B needs deploy+integration testing before
adoption, C has no analog (CustomScriptExtension delivery, no user-writable
C:\Scripts), D is N/A (module scripts already ASCII-clean), and E is unneeded
(README does not document the folder-ACL service account).

Closes #549

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@doherty100 doherty100 merged commit 871b0b9 into vnext Jul 7, 2026
15 checks passed
@doherty100 doherty100 deleted the backport-543-per-service-sid branch July 7, 2026 21:20
@doherty100

Copy link
Copy Markdown
Contributor Author

✅ Deploy + integration test validation — PASS

Applied vnext (which contains this merged change) to a live sandbox and ran the full vm_mssql_win unit + integration suite. The patched Grant-SqlFullControl (per-service SID NT SERVICE\MSSQLSERVER) executed as part of the configure_sql_server CustomScriptExtension without error.

terraform apply

Apply complete! Resources: 26 added, 3 changed, 3 destroyed.configure_sql_server extension completed in 5m55s (this is the step that runs Set-MssqlConfiguration.ps1Grant-SqlFullControl on the freshly-created M:\MSSQL\DATA and L:\MSSQL\LOG directories).

Tests: Invoke-UnitTests.ps1 -Module vm_mssql_win -Integration

UNIT TEST RESULTS SUMMARY
  [PASS] vm-mssql-win: Passed=25 Failed=0
  [PASS] integration: SQL: jumpwin1 -> mssqlwin1: Passed=1 Failed=0
Overall: Passed=26 Failed=0 Total=26
RESULT: PASS

Relevant checks directly exercising the ACL'd SQL data/log directories (all PASS):

  • SQL Connectivity: Connected to instance mssqlwin1
  • SQL Config: system db data files on M: / log files on L:
  • SQL Smoke Test: created unittestdb — data on M:, log on L:
  • SQL Service: MSSQLSERVER + SQLSERVERAGENT running
  • Integration: jumpwin1 → mssqlwin1 SQL auth as MYSANDBOX\bootstrapadmin (sysadmin)

The SQL Server engine (running under its per-service SID identity) successfully created and wrote database files in the directories granted FullControl by the refactored function, confirming the per-service SID grant is functionally correct.

Environment

  • Branch/base: vnext @ 871b0b9 (this PR's squash-merge commit)
  • Enabled modules: vnet_shared, vnet_app, vm_mssql_win
  • All VMs (adds1, jumpwin1, mssqlwin1) confirmed running before tests (DC up).

doherty100 added a commit that referenced this pull request Jul 7, 2026
* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#541)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#540)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#539)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#538)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#537)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#536)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#534)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#533)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#532)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#531)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#530)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#529)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): update hashicorp/azurerm requirement from ~> 4.79.0 to ~> 4.80.0 (#528)

Updates the requirements on [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) to permit the latest version.

Updates `hashicorp/azurerm` to 4.80.0
- [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases)
- [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md)
- [Commits](hashicorp/terraform-provider-azurerm@v4.79.0...v4.80.0)

---
updated-dependencies:
- dependency-name: hashicorp/azurerm
  dependency-version: 4.80.0
  dependency-type: direct:production
  dependency-group: terraform-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Retire ai-foundry module and remove from dependabot (#542)

* Retire ai-foundry module and remove from dependabot

Move extras/modules/ai-foundry to extras/modules/retired/ai-foundry,
remove its dependabot terraform entry, and update the commented-out
module source path in main.tf.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Exclude retired boneyard from lychee and fix ai-foundry link

Add exclude_path = ["retired"] to lychee.toml so retired modules are
skipped by the link checker, and update the ai-foundry link in
extras/README.md to its new retired location.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* security: harden ACLs - per-service SID, disable inheritance, lock down C:\Scripts (#543)

Co-authored-by: David Pless <dplessMSFT@users.noreply.github.com>
Co-authored-by: Roger Doherty (MSFT) <rdoherty@microsoft.com>

* Fix #544: run vm_mssql_win boot tasks as SYSTEM (#547)

The AtStartup scheduled task 'Set-MssqlStartupConfiguration' (rebuilds the
ephemeral temp-disk stripe, recreates tempdb folders, fixes the pagefile and
starts SQL Server after a stop/deallocate) was registered to run as the domain
admin with a stored password. On the post-deallocate boot this failed to launch
(TaskScheduler Event 104, ERROR_LOGON_FAILURE 0x8007052E): an AtStartup batch
logon with a stored domain password races the domain controller secure channel
at boot and is blocked by Credential Guard (default-on in Windows Server 2025).
The task never ran, so T: was never rebuilt and SQL Server stayed stopped.

Changes (vm-mssql-win only):
- Set-MssqlConfiguration.ps1: register 'Set-MssqlStartupConfiguration' with a
  'NT AUTHORITY\SYSTEM' principal (no stored password, no DC dependency,
  Credential-Guard-immune). The task does only local work, so it needs no domain
  admin / SQL sysadmin identity.
- Set-MssqlStartupConfiguration.ps1: update header to document it runs as SYSTEM
  and why.
- Invoke-MssqlConfiguration.ps1: harden the one-time 'Set-MssqlConfiguration-Reboot'
  task (Restart-Computer only) to SYSTEM; document that 'Set-MssqlConfiguration'
  intentionally stays domain admin (on-demand, trusted-auth SQL sysadmin work,
  not boot-triggered).
- Test-VmMssqlWin.ps1: harden Startup Check 1 to also assert LastRunTime is after
  the last OS boot, catching the false PASS where a boot task fails to launch and
  leaves a stale success result.
- README.md: reflect that the startup/reboot tasks run as SYSTEM while first-boot
  config is unchanged (still domain admin).

End state preserved: domain-joined VM with SQL Server administered by the domain
admin (SQL sysadmin). Swept all provisioning automation in compute.tf
(join_domain, run commands, CustomScriptExtension, ama) and confirmed no other
stored-domain-credential-at-boot pattern exists.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Backport #543: use SQL per-service SID for folder ACLs (vm_mssql_win) (#550)

Grant-SqlFullControl queried the MSSQLSERVER service's logon account
(Get-CimInstance ... StartName) and granted that account FullControl on the
freshly created SQL data and errorlog directories. Backport the ACL-identity
hardening from PR #543: grant FullControl to the Database Engine per-service
SID 'NT SERVICE\MSSQLSERVER' instead.

The per-service SID is present in the service process token regardless of the
configured logon account, survives service-account changes, and matches the
permissions the SQL Server installer applies to its data directories. The grant
remains non-destructive (SetAccessRule, inheritance preserved), so this is a
low-risk change on the already freshly-created target directories.

Only theme A from PR #543 is backported. Themes B (inheritance disable +
clean-slate ACEs on data/errorlog dirs), C (C:\Scripts lockdown), D (encoding),
and E (README) are out of scope: B needs deploy+integration testing before
adoption, C has no analog (CustomScriptExtension delivery, no user-writable
C:\Scripts), D is N/A (module scripts already ASCII-clean), and E is unneeded
(README does not document the folder-ACL service account).

Closes #549

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: David Pless <69168864+dplessMSFT@users.noreply.github.com>
Co-authored-by: David Pless <dplessMSFT@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant