Skip to content

Support for use of "trustservercertificate" option in AzD 2022 scripts if they use Invoke-Sqlcmd#99

Draft
norschel wants to merge 16 commits intomicrosoft:masterfrom
norschel:topics/trustservercertificate
Draft

Support for use of "trustservercertificate" option in AzD 2022 scripts if they use Invoke-Sqlcmd#99
norschel wants to merge 16 commits intomicrosoft:masterfrom
norschel:topics/trustservercertificate

Conversation

@norschel
Copy link

Starting with SQL Server 2022 (and enforced in newer versions of the SqlServer PowerShell module), Invoke-Sqlcmd requires an explicit opt-in to trust self-signed or non-CA-issued TLS certificates on the SQL Server connection. Without it, connections to SQL Server instances using such certificates fail with a certificate validation error. The -TrustServerCertificate switch suppresses that validation — but it must only be passed when the administrator explicitly requests it, because silently trusting any certificate would bypass a security control. PowerShell conditional splatting (@trustCertParam) ensures the flag is appended to Invoke-Sqlcmd only when the operator passes -TrustServerCertificate at the script level, leaving the default behaviour (certificate verification) unchanged for all other users.

Changes Made
Added [switch]$TrustServerCertificate to root Common.psm1 (ValidateCollectionName, IsExtensionInstalled)
Added [switch]$TrustServerCertificate to SearchDiagonistics/Common.psm1
Added [switch]$TrustServerCertificate to all 19 root .ps1 scripts
Added [switch]$TrustServerCertificate to SearchDiagonistics scripts
Added [switch]$TrustServerCertificate to 16 functions in Troubleshooting/Utils/Common.psm1
Added [switch]$TrustServerCertificate to all Troubleshooting Analyzer modules (6 files)
Added [switch]$TrustServerCertificate to Troubleshooting Action modules that use SQL (4 files)
Added [switch]$TrustServerCertificate to Troubleshooting/Repair-Search.ps1 with inline help documentation
All 105 Invoke-Sqlcmd calls use conditional splatting — -TrustServerCertificate is only passed when the user explicitly enables the switch (never passed as $false)
All internal function call chains propagate $TrustServerCertificate

Copilot AI and others added 5 commits March 11, 2026 11:00
…lls in Azure_DevOps_Server_2022

Co-authored-by: norschel <12895005+norschel@users.noreply.github.com>
…function chain

Co-authored-by: norschel <12895005+norschel@users.noreply.github.com>
…qlcmd calls

Co-authored-by: norschel <12895005+norschel@users.noreply.github.com>
…e-support

Add -TrustServerCertificate switch to Azure DevOps Server 2022 PS1 scripts
Copilot AI review requested due to automatic review settings March 11, 2026 12:36
@norschel
Copy link
Author

@microsoft-github-policy-service agree

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an explicit, opt-in -TrustServerCertificate switch across Azure DevOps Server 2022 PowerShell scripts/modules so SQL connections made via Invoke-Sqlcmd can succeed when TLS certificates are self-signed/non-CA-issued, without weakening defaults for everyone else.

Changes:

  • Adds [switch]$TrustServerCertificate parameters and propagates them through script/function call chains.
  • Uses conditional splatting (@trustCertParam) so Invoke-Sqlcmd -TrustServerCertificate is only supplied when explicitly requested.
  • Updates Troubleshooting analyzers/actions and SearchDiagnostics scripts to pass the new switch consistently.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Azure_DevOps_Server_2022/ViewDelete-IncompatibleIndices.ps1 Adds -TrustServerCertificate and conditional splatting to its SQL call.
Azure_DevOps_Server_2022/Troubleshooting/Utils/Common.psm1 Propagates -TrustServerCertificate through helper functions and SQL calls.
Azure_DevOps_Server_2022/Troubleshooting/Repair-Search.ps1 Documents and forwards -TrustServerCertificate into troubleshooting flows.
Azure_DevOps_Server_2022/Troubleshooting/Analyzers/Test-SqlHealth.psm1 Adds switch and conditional splatting for analyzer SQL queries.
Azure_DevOps_Server_2022/Troubleshooting/Analyzers/Test-IndicesHaveUnsupportedMappings.psm1 Propagates switch into helper calls that query SQL.
Azure_DevOps_Server_2022/Troubleshooting/Analyzers/Test-IndexingUnitPointsToDeletedIndex.psm1 Adds switch and conditional splatting for SQL script execution.
Azure_DevOps_Server_2022/Troubleshooting/Analyzers/Test-GeneralTfvcIssues.psm1 Adds switch and conditional splatting for SQL query.
Azure_DevOps_Server_2022/Troubleshooting/Analyzers/Test-FaultInJobInInfiniteRetries.psm1 Adds switch and conditional splatting; propagates into registry lookup helpers.
Azure_DevOps_Server_2022/Troubleshooting/Analyzers/Test-ElasticsearchHealth.psm1 Propagates switch into SQL-reliant helper calls.
Azure_DevOps_Server_2022/Troubleshooting/Actions/Restart-Indexing.psm1 Adds switch, propagates it, and conditionally splats for SQL operations.
Azure_DevOps_Server_2022/Troubleshooting/Actions/Reset-ExtensionInstallationRegKeys.psm1 Propagates switch into registry-writing helper.
Azure_DevOps_Server_2022/Troubleshooting/Actions/Remove-OrphanIndexedDocuments.psm1 Adds switch and conditional splatting for SQL script execution.
Azure_DevOps_Server_2022/Troubleshooting/Actions/Enable-IndexingFeatureFlags.psm1 Propagates switch into Set-FeatureFlag calls.
Azure_DevOps_Server_2022/TriggerCollectionIndexing.ps1 Adds switch, propagates it to helpers, and splats it into SQL calls.
Azure_DevOps_Server_2022/SetIndexingStateRepository.ps1 Adds switch, propagates it to helpers, and splats it into SQL calls.
Azure_DevOps_Server_2022/SearchDiagonistics/ConfigurationDBSearchDiagnostics.ps1 Adds switch and conditional splatting for diagnostics SQL scripts.
Azure_DevOps_Server_2022/SearchDiagonistics/Common.psm1 Adds switch and conditional splatting to shared diagnostics helpers.
Azure_DevOps_Server_2022/SearchDiagonistics/CollectionDBSearchDiagnostics.ps1 Adds switch and conditional splatting for diagnostics SQL scripts.
Azure_DevOps_Server_2022/ResumeIndexing.ps1 Adds switch and conditional splatting for SQL scripts that resume indexing.
Azure_DevOps_Server_2022/RecentIndexingActivity.ps1 Adds switch, propagates it to helpers, and splats it into SQL calls.
Azure_DevOps_Server_2022/ReIndexFiles.ps1 Adds switch, propagates it, and splats it into SQL calls.
Azure_DevOps_Server_2022/Re-IndexingCodeRepository.ps1 Adds switch, propagates it, and splats it into SQL calls.
Azure_DevOps_Server_2022/PauseIndexing.ps1 Adds switch and conditional splatting for SQL scripts that pause indexing.
Azure_DevOps_Server_2022/OptimizeElasticIndex.ps1 Adds switch parameter (currently introduces a Param-block syntax issue).
Azure_DevOps_Server_2022/MissingIndexFolderTriggerCollectionIndexing.ps1 Adds switch, propagates it to helpers, and splats it into SQL calls.
Azure_DevOps_Server_2022/GetRepositoryReIndexingActivityStatus.ps1 Adds switch parameter (currently introduces a Param-block syntax issue).
Azure_DevOps_Server_2022/GetReIndexingStatusOfFiles.ps1 Adds switch, propagates it, and splats it into SQL calls.
Azure_DevOps_Server_2022/GetElasticsearchDocCountPerRepository.ps1 Adds switch parameter (currently introduces a Param-block syntax issue).
Azure_DevOps_Server_2022/GetCollectionReIndexingActivityStatus.ps1 Adds switch and splats it into SQL calls; propagates to child script invocation.
Azure_DevOps_Server_2022/FixIndexingIndexName.ps1 Adds switch, propagates it, and splats it into SQL calls.
Azure_DevOps_Server_2022/ExtensionInstallIndexingStatus.ps1 Adds switch, propagates it to helpers, and splats it into SQL calls.
Azure_DevOps_Server_2022/ExcludedTfvcFoldersForIndexing.ps1 Adds switch and conditional splatting for SQL scripts managing TFVC exclusions.
Azure_DevOps_Server_2022/Common.psm1 Adds switch and conditional splatting in shared root helper module.
Azure_DevOps_Server_2022/CleanUpShardDetails.ps1 Adds switch and conditional splatting for cleanup SQL script.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

norschel and others added 2 commits March 11, 2026 14:57
….ps1

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 34 changed files in this pull request and generated 29 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 34 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

Azure_DevOps_Server_2022/OptimizeElasticIndex.ps1:16

  • The script adds a TrustServerCertificate parameter but never uses it (there are no SQL connections in this script, and it isn’t applied to the REST call). This increases surface area/confusion for callers and may trigger unused-parameter linting. Either remove the parameter from this script or wire it into the actual connection behavior it’s meant to control.
[CmdletBinding()]
Param(
    [Parameter(Mandatory=$True, HelpMessage="Enter the Elasticsearch server Url. eg: http://localhost:9200/")]
    [string]$ElasticServerUrl,

    [Parameter(Mandatory=$True, HelpMessage="Enter index name. Eg: code* for all code indices or a specific index name")]
    [string]$IndexName,

    [Parameter(Mandatory=$False)]
    [switch]$TrustServerCertificate
)

function OptimizeIndex
{
    $optimizeCommand = $ElasticServerUrl +"/" + $IndexName + "/_forcemerge?only_expunge_deletes=true"
    $response = Invoke-RestMethod $optimizeCommand -Method Post -ContentType "application/json" -Credential (Get-Credential)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

$trustCertParam = if ($TrustServerCertificate) { @{TrustServerCertificate = $true} } else { @{} }

$queryResults = Invoke-Sqlcmd -Query "Select HostID from [dbo].[tbl_ServiceHost] where Name = '$CollectionName'" -serverInstance $SQLServerInstance -database $ConfigurationDatabaseName -Verbose
$queryResults = Invoke-Sqlcmd -Query "Select HostID from [dbo].[tbl_ServiceHost] where Name = '$CollectionName'" -serverInstance $SQLServerInstance -database $ConfigurationDatabaseName -Verbose @trustCertParam
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ValidateCollectionName here queries tbl_ServiceHost by Name only; in Azure_DevOps_Server_2022/Common.psm1 the same helper also filters HostType = 4 to ensure the HostId is for a collection. Without that filter, this can return a non-collection HostId and cause downstream scripts to target the wrong host. Consider adding and HostType = 4 (or otherwise matching the root helper’s criteria).

Suggested change
$queryResults = Invoke-Sqlcmd -Query "Select HostID from [dbo].[tbl_ServiceHost] where Name = '$CollectionName'" -serverInstance $SQLServerInstance -database $ConfigurationDatabaseName -Verbose @trustCertParam
$queryResults = Invoke-Sqlcmd -Query "Select HostID from [dbo].[tbl_ServiceHost] where Name = '$CollectionName' and HostType = 4" -serverInstance $SQLServerInstance -database $ConfigurationDatabaseName -Verbose @trustCertParam

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 33 out of 33 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

Azure_DevOps_Server_2022/SearchDiagonistics/Common.psm1:79

  • IsExtensionInstalled previously short-circuited with an unconditional return $true (as shown by the removed lines in this PR) and now performs a real SQL check. This is a significant functional change beyond adding -TrustServerCertificate; please confirm it’s intended and document it in the PR description (or move it to a separate change) because it can change script behavior for environments where the registry key isn’t present.
function IsExtensionInstalled
{
    [CmdletBinding()]
    [OutputType([boolean])]
    Param
    (
        [string] $SQLServerInstance,
        [string] $CollectionDatabaseName,
        [string] $RegValue,
        [Parameter(Mandatory=$False)]
        [switch] $TrustServerCertificate
    )
    $trustCertParam = if ($TrustServerCertificate) { @{TrustServerCertificate = $true} } else { @{} }

    $isCollectionIndexed = Invoke-Sqlcmd -Query "Select RegValue from tbl_RegistryItems where ChildItem like '%$RegValue%' and PartitionId > 0" -ServerInstance $SQLServerInstance -Database $CollectionDatabaseName @trustCertParam
    
    if($isCollectionIndexed.RegValue -eq "True")
    {
        return $true
    }
    else
    {
        return $false
    }
}

Azure_DevOps_Server_2022/Common.psm1:74

  • IsExtensionInstalled no longer returns $true unconditionally; it now queries tbl_RegistryItems and can return $false. This is a behavior change beyond the PR’s stated goal (TLS trust flag propagation) and could alter how multiple scripts behave. Please confirm this change is intentional and update the PR description/release notes accordingly (or split this behavior fix into a separate PR).
function IsExtensionInstalled
{
    [CmdletBinding()]
    [OutputType([boolean])]
    Param
    (
        [string] $SQLServerInstance,
        [string] $CollectionDatabaseName,
        [string] $RegValue,
        [Parameter(Mandatory=$False)]
        [switch] $TrustServerCertificate
    )
    $trustCertParam = if ($TrustServerCertificate) { @{TrustServerCertificate = $true} } else { @{} }

    $isCollectionIndexed = Invoke-Sqlcmd -Query "Select RegValue from tbl_RegistryItems where ChildItem like '%$RegValue%' and PartitionId > 0" -ServerInstance $SQLServerInstance -Database $CollectionDatabaseName @trustCertParam

    if($isCollectionIndexed.RegValue -eq "True")
    {
        return $true
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

norschel and others added 3 commits March 12, 2026 10:18
…lth.psm1

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI and others added 2 commits March 12, 2026 13:21
Co-authored-by: norschel <12895005+norschel@users.noreply.github.com>
…ficate

Pass -TrustServerCertificate only when explicitly provided by caller
@norschel norschel marked this pull request as draft March 12, 2026 15:21
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.

3 participants