Skip to content

Password decryption commands - Document the remote DAC prerequisite - #10551

Draft
andreasjordan wants to merge 2 commits into
developmentfrom
document-dac-prerequisite
Draft

Password decryption commands - Document the remote DAC prerequisite#10551
andreasjordan wants to merge 2 commits into
developmentfrom
document-dac-prerequisite

Conversation

@andreasjordan

Copy link
Copy Markdown
Collaborator

Draft, to show what the documentation-only option from #10549 actually looks like. The design question on that issue is still open — this PR deliberately does not answer it.

Problem

Up to dbatools 2.7, Get-DecryptedObject opened the DAC itself, from inside the PowerShell remoting session on the SQL Server host (ADMIN:127.0.0.1\<instance>). That is a local DAC: it needs neither remote admin connections nor a reachable DAC port.

PR #10174 removed that path so that a single DAC can be opened early and shared across every command that needs one — SQL Server allows only one DAC per instance, and the per-command open/close pattern was the root of #10040, #9921 and #10475.

The refactor was intended. The side effect was not documented: the requirement changed from "PowerShell remoting to the host" to "PowerShell remoting plus a remote DAC". Reporters hit this as a silent failure, most recently in #10549.

What changed

Help only — no behaviour change, no code touched.

Added to the .DESCRIPTION of the five commands that decrypt passwords directly (Export-DbaLinkedServer, Export-DbaCredential, Copy-DbaLinkedServer, Copy-DbaCredential, Copy-DbaDbMail) a short block naming both connections:

  • the DAC, opened from the machine running the command, hence a remote DAC — so the instance needs remote admin connections enabled and its DAC port reachable (TCP 1434 for a default instance, the dynamic port published by SQL Server Browser for a named one)
  • PowerShell remoting to the Windows host, to read the service master key from the registry

The three orchestrators (Export-DbaInstance, Start-DbaMigration, Sync-DbaAvailabilityGroup) get a shorter version that also states they open one shared DAC and hand it down, and points at the underlying commands. Sync-DbaAvailabilityGroup already explained the shared DAC; only the network prerequisite was missing.

Every -ExcludePassword parameter now says it is also the way out when the DAC or remoting is unavailable, since the command then needs neither.

Get-DecryptedObject records why it no longer opens a DAC itself, so the next person to read it does not have to reconstruct the history from git.

Two statements that are no longer true are corrected:

  • Copy-DbaCredential listed DAC access enabled for local (default) under Requires: — the opposite of what it needs now
  • Export-DbaLinkedServer said it "accesses the local registry"; the registry read happens on the SQL Server host, not locally

What deliberately did not change

No code. Whether Get-DecryptedObject should regain a local-DAC-over-remoting path is the question put to contributors on #10549. Reintroducing a second DAC path costs reliability in an area that took several releases to stabilise, so it should be a decision, not a side effect of this PR.

Invoke-DbaDbDecryptObject also opens a DAC but is untouched — it needs one for the encrypted object definitions themselves and has no remoting leg to route through, so the requirement there is inherent rather than a consequence of the refactor.

Testing

  • All 9 changed files parse
  • Get-Help renders the new text on all 8 commands
  • Unit tests for the 9 affected test files pass, no failures and no warnings

Reported and diagnosed by @edbmfo in #10549, whose analysis of the 127.0.0.1 change and its removal was correct in every detail.

Up to dbatools 2.7, Get-DecryptedObject opened a local DAC itself from
inside the PowerShell remoting session on the SQL Server host, so no
remote DAC was needed. PR #10174 removed that path so a single DAC can
be opened early and shared, because SQL Server allows only one DAC per
instance. That refactor was deliberate, but it changed the network
requirement from "PowerShell remoting only" to "PowerShell remoting plus
a reachable remote DAC", and nothing in the help said so.

Documents the current state in the eight affected commands and in
Get-DecryptedObject: what the two connections are, that the DAC is
opened from the client and therefore needs remote admin connections
enabled and a reachable DAC port, and that -ExcludePassword avoids both.

Also corrects two statements that no longer hold:
- Copy-DbaCredential claimed "DAC access enabled for local (default)"
- Export-DbaLinkedServer said it "accesses the local registry"

No behaviour change - help only. Whether the code should also regain a
local-DAC path is the open question on the issue, deliberately not
answered here.

Refs #10549

(do Copy-DbaCredential, Copy-DbaDbMail, Copy-DbaLinkedServer, Export-DbaCredential, Export-DbaInstance, Export-DbaLinkedServer, Start-DbaMigration, Sync-DbaAvailabilityGroup)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@potatoqualitee

Copy link
Copy Markdown
Member

Verdict

Request changes. The documentation-only approach is reasonable, and the underlying DAC-sharing logic is sound, but the current wording contains three factual problems. I would not merge it as written.

Findings

1. Blocking: remote DAC and PowerShell remoting are not always required

Every new description effectively says:

The command opens the DAC from the machine running it, therefore it is a remote DAC, and PowerShell remoting is also required.

That is only true when the command runs on a different computer from the SQL Server host.

Connect-DbaInstance -DedicatedAdminConnection explicitly uses ADMIN:localhost when the target is local. Invoke-Command2 also creates a PowerShell remoting session only when the target is non-local; otherwise it executes the script block locally.

Consequently, when these commands run directly on the SQL Server host:

  • remote admin connections does not have to be enabled.
  • The DAC TCP port does not have to be exposed remotely.
  • WinRM/PowerShell remoting is not required.
  • The user still needs sufficient local Windows rights to read and unprotect the key.

This affects the wording added to all eight public commands and the internal Get-DecryptedObject documentation.

This is worth blocking because the current text could cause administrators to enable remote DAC unnecessarily, even though Microsoft recommends leaving remote administration connections disabled unless they are specifically required. ([Microsoft Learn]1)

2. Blocking: the DAC port is not determined by default versus named instance

The repeated wording says:

TCP port 1434 for a default instance, or the dynamically assigned port published by SQL Server Browser for a named instance.

That split is inaccurate. SQL Server listens for the DAC on TCP 1434 when that port is available. Otherwise, it assigns a TCP port during startup. This can happen to a default instance too, and the SQL Server error log is the authoritative source for the active DAC port. ([Microsoft Learn]2)

SQL Server Browser is a separate discovery mechanism using UDP 1434. The actual DAC endpoint remains a TCP port. The current wording risks sending an administrator to the wrong port or causing confusion between TCP 1434 and UDP 1434. ([Microsoft Learn]3)

3. Medium: the Set-DbaSpConfigure command shown is incomplete

The repeated example is:

Set-DbaSpConfigure -Name RemoteDacConnectionsEnabled -Value 1

It does not specify -SqlInstance or receive an input object. Set-DbaSpConfigure only retrieves the configuration object when -SqlInstance is bound, then iterates its input collection. In ordinary copied usage, the command above changes nothing.

It should be something like:

Set-DbaSpConfigure -SqlInstance <source-instance> `
    -Name RemoteDacConnectionsEnabled `
    -Value 1

4. Non-blocking: existing prerequisite text now contradicts the new text

Two stale areas should be reconciled while this PR is already correcting prerequisites:

  • Copy-DbaCredential still lists “Administrator access on Windows” unconditionally, then immediately says Windows administrator access is only required unless -ExcludePassword is used. The code skips the DAC and Get-DecryptedObject when passwords are excluded.
  • Copy-DbaLinkedServer still says both the source and destination require Windows administrator access. The new description correctly identifies Windows access to the source host for decryption; no destination-host remoting occurs.

Suggested shared wording

This could replace the repeated prerequisite paragraph:

Decrypting stored passwords requires DAC access to the SQL Server instance and Windows administrator access to the source host.

The command opens or reuses the DAC from the machine running the command. When that machine is different from the SQL Server host, enable remote DAC access on the source instance and make the actual DAC TCP listener reachable. SQL Server uses TCP port 1434 when available; otherwise it assigns a port during startup. Check the SQL Server error log for the active DAC port.

The service master key is read and unprotected on the source Windows host. When the source is remote, this uses PowerShell remoting. When the command runs on the source host, the operation runs locally, so remote DAC access and PowerShell remoting are not required.

Use -ExcludePassword to skip password decryption; no DAC or Windows-host access is then used for password retrieval.

For the commands that enable the setting, add the complete invocation:

Set-DbaSpConfigure -SqlInstance <source-instance> `
    -Name RemoteDacConnectionsEnabled `
    -Value 1

What checks out

The functional statements about -ExcludePassword are correct. The five leaf commands avoid Get-DecryptedObject and use a normal SQL connection when passwords are excluded.

The three orchestration commands also correctly calculate whether a DAC is needed and share one connection among the password-copying operations.

One low-priority edge case remains: SQL Server Express does not listen for DAC connections unless trace flag 7806 is enabled. Since some affected commands claim SQL Server 2005+ support without an edition exclusion, that caveat would improve completeness. ([Microsoft Learn]4)

Recommendation: request changes for findings 1 through 3. After those and the prerequisite cleanup, I would approve. The unresolved architectural discussion in issue #10549 does not need to block accurate documentation of the current implementation.

…nal on running remotely

Reworks the help added in this PR along the lines of the review:

- Remote admin connections, a reachable DAC port and PowerShell remoting
  are only needed when the command runs on a different machine than the
  SQL Server host. Connect-DbaInstance uses ADMIN:localhost and
  Invoke-Command2 runs locally when the target is local, so running on
  the host itself needs neither. The help now says so instead of
  presenting the remote path as unconditional.
- The DAC port split "TCP 1434 for default, Browser-published for named"
  was wrong. SQL Server listens on TCP 1434 when that port is available
  and otherwise assigns a port at startup; the error log names the
  active port. The help now states that and drops the Browser claim.
- The Set-DbaSpConfigure example now includes -SqlInstance, without
  which it changes nothing.
- Stale prerequisites reconciled: Copy-DbaCredential no longer lists
  Windows administrator access unconditionally, and Copy-DbaLinkedServer
  no longer claims the destination needs Windows access.
- Added the SQL Server Express caveat: no DAC without trace flag 7806.

The three orchestrators keep a short version and point at the leaf
commands for the full prerequisites, so the corrected details live in
one place per command family. Still help only - no behaviour change.

Refs #10549

(do Copy-DbaCredential, Copy-DbaDbMail, Copy-DbaLinkedServer, Export-DbaCredential, Export-DbaInstance, Export-DbaLinkedServer, Start-DbaMigration, Sync-DbaAvailabilityGroup)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@andreasjordan

Copy link
Copy Markdown
Collaborator Author

Thanks for the thorough review — all four findings were correct, and all are addressed in the latest commit.

  1. The help now follows your suggested structure: the remote prerequisites (remote admin connections, reachable DAC port, PowerShell remoting) are stated as applying only when the command runs on a different machine than the SQL Server host, with an explicit note that running on the host itself needs neither.
  2. The port wording now matches the documented behavior: TCP 1434 when available, otherwise a port assigned at startup, with the error log as the authoritative source. The Browser claim is gone.
  3. The Set-DbaSpConfigure example now includes -SqlInstance (kept on one line per repo style).
  4. Both stale prerequisite areas are reconciled: Copy-DbaCredential no longer requires Windows administrator access unconditionally, and Copy-DbaLinkedServer no longer claims the destination host needs Windows access.

The Express trace flag 7806 caveat is also added to the five leaf commands. The orchestrators keep a short version and defer the full prerequisites to the leaf commands, so the details live in one place per family.

This response was created by Claude and reviewed by Andreas Jordan.

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.

2 participants