From ebe74ee0b8c371e3fe66bff41c8d1128785a2a9f Mon Sep 17 00:00:00 2001 From: gargsaumya Date: Wed, 12 Aug 2026 11:21:32 +0530 Subject: [PATCH 1/3] FIX: Remove credential exposure from CI/CD pipelines Eliminate secret leakage via bash xtrace, process arguments, and world-readable files across ADO/OneBranch pipelines and the devcontainer: - Replace 'set -eux' with 'set -euo pipefail' in all secret-handling blocks and nested shells - Map secrets through step env: and reference shell vars instead of ADO \ macros - Use SQLCMDPASSWORD and stdin for sqlcmd; inherit Docker env vars by name (-e VAR) - Replace SQL Server installer /SAPWD= with an ACL-restricted /ConfigurationFile= deleted in finally - devcontainer: use --env-file (0600) for docker run and a user-only env file instead of world-readable /etc/environment --- .devcontainer/post-create.sh | 29 ++- .../stages/build-linux-single-stage.yml | 28 +-- .../stages/build-macos-single-stage.yml | 8 +- .../stages/build-windows-single-stage.yml | 2 +- OneBranchPipelines/stress-test-pipeline.yml | 36 ++-- eng/pipelines/pr-validation-pipeline.yml | 196 +++++++++++------- 6 files changed, 186 insertions(+), 113 deletions(-) diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 63062828b..2a565b821 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -51,9 +51,11 @@ fi # Generate random password for SQL Server echo "" echo "Generating SQL Server password..." +umask 077 SA_PASSWORD="$(openssl rand -base64 16 | tr -dc 'A-Za-z0-9' | head -c 16)Aa1!" -echo "$SA_PASSWORD" > /tmp/.sqlserver_sa_password -chmod 600 /tmp/.sqlserver_sa_password +SQL_ENV_FILE="$(mktemp)" +printf 'ACCEPT_EULA=Y\nMSSQL_SA_PASSWORD=%s\n' "$SA_PASSWORD" > "$SQL_ENV_FILE" +chmod 600 "$SQL_ENV_FILE" # Start SQL Server container (use Azure SQL Edge for ARM64 compatibility) # This is optional - if Docker-in-Docker fails, the devcontainer still works @@ -63,15 +65,16 @@ echo "Starting SQL Server container (optional)..." ARCH=$(uname -m) if [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then echo "Detected ARM64 - using Azure SQL Edge..." - docker run -e 'ACCEPT_EULA=Y' -e "MSSQL_SA_PASSWORD=$SA_PASSWORD" \ + docker run --env-file "$SQL_ENV_FILE" \ -p 1433:1433 --name sqlserver \ -d mcr.microsoft.com/azure-sql-edge:latest && SQL_STARTED=true || SQL_STARTED=false else echo "Detected x86_64 - using SQL Server 2025..." - docker run -e 'ACCEPT_EULA=Y' -e "MSSQL_SA_PASSWORD=$SA_PASSWORD" \ + docker run --env-file "$SQL_ENV_FILE" \ -p 1433:1433 --name sqlserver \ -d mcr.microsoft.com/mssql/server:2025-latest && SQL_STARTED=true || SQL_STARTED=false fi +rm -f "$SQL_ENV_FILE" if [ "$SQL_STARTED" = "true" ]; then echo "Waiting for SQL Server to start..." @@ -85,12 +88,18 @@ fi # Set DB_CONNECTION_STRING environment variable (persist across all terminals) DB_CONNECTION_STRING="Server=localhost,1433;Database=master;UID=sa;PWD=$SA_PASSWORD;TrustServerCertificate=Yes;Encrypt=Yes" -# Write to /etc/environment for system-wide persistence -echo "DB_CONNECTION_STRING=\"$DB_CONNECTION_STRING\"" | sudo tee -a /etc/environment > /dev/null - -# Also add to shell rc files for immediate availability in new terminals -echo "export DB_CONNECTION_STRING=\"$DB_CONNECTION_STRING\"" >> ~/.bashrc -echo "export DB_CONNECTION_STRING=\"$DB_CONNECTION_STRING\"" >> ~/.zshrc +# Keep the credential in a user-only file and source it from interactive shells. +MSSQL_ENV_FILE="$HOME/.mssql_python_env" +printf "export DB_CONNECTION_STRING='%s'\n" "$DB_CONNECTION_STRING" > "$MSSQL_ENV_FILE" +chmod 600 "$MSSQL_ENV_FILE" + +# Remove plaintext entries left by older versions of this script. +[ -f /etc/environment ] && sudo sed -i '/^DB_CONNECTION_STRING=/d' /etc/environment +[ -f ~/.bashrc ] && sed -i '/^export DB_CONNECTION_STRING=/d' ~/.bashrc +[ -f ~/.zshrc ] && sed -i '/^export DB_CONNECTION_STRING=/d' ~/.zshrc +rm -f /tmp/.sqlserver_sa_password +grep -qxF 'source ~/.mssql_python_env' ~/.bashrc 2>/dev/null || echo 'source ~/.mssql_python_env' >> ~/.bashrc +grep -qxF 'source ~/.mssql_python_env' ~/.zshrc 2>/dev/null || echo 'source ~/.mssql_python_env' >> ~/.zshrc # Export for current session export DB_CONNECTION_STRING diff --git a/OneBranchPipelines/stages/build-linux-single-stage.yml b/OneBranchPipelines/stages/build-linux-single-stage.yml index da258e0bf..7b5f634fb 100644 --- a/OneBranchPipelines/stages/build-linux-single-stage.yml +++ b/OneBranchPipelines/stages/build-linux-single-stage.yml @@ -136,7 +136,7 @@ stages: displayName: 'Start $(LINUX_TAG) $(ARCH) container' - script: | - set -euxo pipefail + set -euo pipefail export PATH=$PATH:`pwd`/docker CONTAINER="build-$(LINUX_TAG)-$(ARCH)" @@ -170,7 +170,7 @@ stages: # manager is flaky under emulation (the header gate below is the real check). if [[ "$(LINUX_TAG)" == "manylinux_2_28" ]]; then docker exec "$CONTAINER" bash -lc ' - set -uxo pipefail + set -uo pipefail if command -v dnf >/dev/null 2>&1; then dnf -y install gcc gcc-c++ make cmake unixODBC-devel krb5-libs keyutils-libs ccache curl || true elif command -v yum >/dev/null 2>&1; then @@ -181,7 +181,7 @@ stages: ' else docker exec "$CONTAINER" sh -lc ' - set -uxo pipefail + set -uo pipefail apk add --no-cache bash build-base cmake unixodbc-dev krb5-libs keyutils-libs ccache curl || true gcc --version || true cmake --version || true @@ -199,20 +199,20 @@ stages: # Start SQL Server container for pytest execution # Runs on host (not in build container) to be accessible from build container via network - script: | - set -euxo pipefail + set -euo pipefail echo "Starting SQL Server 2022 container for testing..." docker run -d --name sqlserver-$(LINUX_TAG)-$(ARCH) \ --platform linux/amd64 \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="$(DB_PASSWORD)" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ mcr.microsoft.com/mssql/server:2022-latest echo "Waiting for SQL Server to be ready..." for i in {1..30}; do - if docker exec sqlserver-$(LINUX_TAG)-$(ARCH) /opt/mssql-tools18/bin/sqlcmd \ - -S localhost -U SA -P "$(DB_PASSWORD)" -C -Q "SELECT 1" >/dev/null 2>&1; then + if docker exec -e SQLCMDPASSWORD sqlserver-$(LINUX_TAG)-$(ARCH) /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -C -Q "SELECT 1" >/dev/null 2>&1; then echo "✓ SQL Server is ready!" break fi @@ -226,6 +226,8 @@ stages: displayName: 'Start SQL Server container for testing' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) # ========================= # PHASE 2: EXTERNAL ODBC DRIVER PACKAGE @@ -256,7 +258,7 @@ stages: # Build wheels for all Python versions (3.10-3.14) and test each one - script: | - set -euxo pipefail + set -euo pipefail if [[ "$(LINUX_TAG)" == "manylinux_2_28" ]]; then SHELL_EXE=bash; else SHELL_EXE=sh; fi docker exec build-$(LINUX_TAG)-$(ARCH) $SHELL_EXE -lc 'mkdir -p /workspace/dist' @@ -269,8 +271,8 @@ stages: if [[ "$(LINUX_TAG)" == "manylinux_2_28" ]]; then # Manylinux (glibc-based) - use bash - docker exec -e PYBIN=$PYBIN -e SQL_IP=$(SQL_IP) -e DB_PASSWORD="$(DB_PASSWORD)" -e MANYLINUX_TAG="$(LINUX_TAG)" -e PIP_FIND_LINKS="/workspace/odbc_wheels" build-$(LINUX_TAG)-$(ARCH) bash -lc ' - set -euxo pipefail; + docker exec -e PYBIN=$PYBIN -e SQL_IP=$(SQL_IP) -e DB_PASSWORD -e MANYLINUX_TAG="$(LINUX_TAG)" -e PIP_FIND_LINKS="/workspace/odbc_wheels" build-$(LINUX_TAG)-$(ARCH) bash -lc ' + set -euo pipefail; # Step 1: Setup Python environment PY=/opt/python/${PYBIN}-${PYBIN}/bin/python; @@ -337,8 +339,8 @@ stages: ' else # Musllinux (musl libc-based) - use sh - docker exec -e PYBIN=$PYBIN -e SQL_IP=$(SQL_IP) -e DB_PASSWORD="$(DB_PASSWORD)" -e MANYLINUX_TAG="$(LINUX_TAG)" -e PIP_FIND_LINKS="/workspace/odbc_wheels" build-$(LINUX_TAG)-$(ARCH) sh -lc ' - set -euxo pipefail; + docker exec -e PYBIN=$PYBIN -e SQL_IP=$(SQL_IP) -e DB_PASSWORD -e MANYLINUX_TAG="$(LINUX_TAG)" -e PIP_FIND_LINKS="/workspace/odbc_wheels" build-$(LINUX_TAG)-$(ARCH) sh -lc ' + set -euo pipefail; # Step 1: Setup Python environment PY=/opt/python/${PYBIN}-${PYBIN}/bin/python; @@ -418,7 +420,7 @@ stages: # Copy built artifacts from container to host for publishing - script: | - set -euxo pipefail + set -euo pipefail # Copy all wheels (5 Python versions) to output directory echo "Copying wheels to host..." diff --git a/OneBranchPipelines/stages/build-macos-single-stage.yml b/OneBranchPipelines/stages/build-macos-single-stage.yml index 20962ce66..ef69b61b8 100644 --- a/OneBranchPipelines/stages/build-macos-single-stage.yml +++ b/OneBranchPipelines/stages/build-macos-single-stage.yml @@ -165,20 +165,22 @@ stages: docker pull mcr.microsoft.com/mssql/server:2022-latest docker run --name sqlserver \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="${DB_PASSWORD}" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 -d \ mcr.microsoft.com/mssql/server:2022-latest # Wait for SQL Server to accept connections (up to 60 seconds) # sqlcmd -C flag = trust server certificate (for TLS connection) for i in {1..30}; do - docker exec sqlserver /opt/mssql-tools18/bin/sqlcmd \ - -S localhost -U SA -P "$DB_PASSWORD" -C -Q "SELECT 1" && break + docker exec -e SQLCMDPASSWORD sqlserver /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -C -Q "SELECT 1" && break sleep 2 done displayName: 'Start SQL Server (Docker)' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) # ========================= # MSSQL_PY_CORE INSTALLATION diff --git a/OneBranchPipelines/stages/build-windows-single-stage.yml b/OneBranchPipelines/stages/build-windows-single-stage.yml index db1c4b1eb..8b0ba7c36 100644 --- a/OneBranchPipelines/stages/build-windows-single-stage.yml +++ b/OneBranchPipelines/stages/build-windows-single-stage.yml @@ -169,7 +169,7 @@ stages: - powershell: | sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "CREATE DATABASE TestDB" - sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "CREATE LOGIN testuser WITH PASSWORD = '$(DB_PASSWORD)'" + "CREATE LOGIN testuser WITH PASSWORD = '$env:DB_PASSWORD'" | sqlcmd -S "(localdb)\MSSQLLocalDB" sqlcmd -S "(localdb)\MSSQLLocalDB" -d TestDB -Q "CREATE USER testuser FOR LOGIN testuser" sqlcmd -S "(localdb)\MSSQLLocalDB" -d TestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser" displayName: 'Setup database and user' diff --git a/OneBranchPipelines/stress-test-pipeline.yml b/OneBranchPipelines/stress-test-pipeline.yml index bf0000849..d0f753f87 100644 --- a/OneBranchPipelines/stress-test-pipeline.yml +++ b/OneBranchPipelines/stress-test-pipeline.yml @@ -103,7 +103,7 @@ jobs: - powershell: | Write-Host "Creating database and user for stress tests..." sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "CREATE DATABASE StressTestDB" - sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "CREATE LOGIN testuser WITH PASSWORD = '$env:DB_PASSWORD'" + "CREATE LOGIN testuser WITH PASSWORD = '$env:DB_PASSWORD'" | sqlcmd -S "(localdb)\MSSQLLocalDB" sqlcmd -S "(localdb)\MSSQLLocalDB" -d StressTestDB -Q "CREATE USER testuser FOR LOGIN testuser" sqlcmd -S "(localdb)\MSSQLLocalDB" -d StressTestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser" Write-Host "Database setup completed" @@ -113,7 +113,7 @@ jobs: # Run multi-threaded stress tests in an isolated subprocess. - powershell: | - $env:DB_CONNECTION_STRING = 'Server=(localdb)\MSSQLLocalDB;Database=StressTestDB;Uid=testuser;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes' + $env:DB_CONNECTION_STRING = "Server=(localdb)\MSSQLLocalDB;Database=StressTestDB;Uid=testuser;Pwd=$env:DB_PASSWORD;TrustServerCertificate=yes" Write-Host "Starting stress tests..." $xmlFile = "stress-test-results.xml" @@ -154,17 +154,21 @@ jobs: Write-Host "Test failures detected or XML not found" exit 1 displayName: 'Run Multi-Threaded Stress Tests' + env: + DB_PASSWORD: $(DB_PASSWORD) continueOnError: true # Run original stress tests - powershell: | - $env:DB_CONNECTION_STRING = 'Server=(localdb)\MSSQLLocalDB;Database=StressTestDB;Uid=testuser;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes' + $env:DB_CONNECTION_STRING = "Server=(localdb)\MSSQLLocalDB;Database=StressTestDB;Uid=testuser;Pwd=$env:DB_PASSWORD;TrustServerCertificate=yes" python -m pytest tests/test_011_singlethreaded_stress.py -v -m "stress" --junitxml=perf-stress-test-results.xml --timeout=1800 --capture=tee-sys $exitCode = $LASTEXITCODE Write-Host "Pytest exit code: $exitCode" exit $exitCode displayName: 'Run Single-Threaded Stress Tests' + env: + DB_PASSWORD: $(DB_PASSWORD) continueOnError: true # Publish test results @@ -257,20 +261,20 @@ jobs: # Start SQL Server container for stress tests - script: | - set -euxo pipefail + set -euo pipefail echo "Starting SQL Server 2022 container for stress tests..." docker run -d --name sqlserver-stress \ --platform linux/amd64 \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="$(DB_PASSWORD)" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ mcr.microsoft.com/mssql/server:2022-latest echo "Waiting for SQL Server to be ready..." for i in {1..30}; do - if docker exec sqlserver-stress /opt/mssql-tools18/bin/sqlcmd \ - -S localhost -U SA -P "$(DB_PASSWORD)" -C -Q "SELECT 1" >/dev/null 2>&1; then + if docker exec -e SQLCMDPASSWORD sqlserver-stress /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -C -Q "SELECT 1" >/dev/null 2>&1; then echo "SQL Server is ready!" break fi @@ -279,19 +283,21 @@ jobs: done echo "Creating database and user for stress tests..." - docker exec sqlserver-stress /opt/mssql-tools18/bin/sqlcmd \ - -S localhost -U SA -P "$(DB_PASSWORD)" -C -Q "CREATE DATABASE StressTestDB" - docker exec sqlserver-stress /opt/mssql-tools18/bin/sqlcmd \ - -S localhost -U SA -P "$(DB_PASSWORD)" -C -Q "CREATE LOGIN testuser WITH PASSWORD = '$(DB_PASSWORD)'" - docker exec sqlserver-stress /opt/mssql-tools18/bin/sqlcmd \ - -S localhost -U SA -P "$(DB_PASSWORD)" -C -d StressTestDB -Q "CREATE USER testuser FOR LOGIN testuser" - docker exec sqlserver-stress /opt/mssql-tools18/bin/sqlcmd \ - -S localhost -U SA -P "$(DB_PASSWORD)" -C -d StressTestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser" + docker exec -e SQLCMDPASSWORD sqlserver-stress /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -C -Q "CREATE DATABASE StressTestDB" + printf "CREATE LOGIN testuser WITH PASSWORD = '%s'\n" "$DB_PASSWORD" | \ + docker exec -i -e SQLCMDPASSWORD sqlserver-stress /opt/mssql-tools18/bin/sqlcmd -S localhost -U SA -C + docker exec -e SQLCMDPASSWORD sqlserver-stress /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -C -d StressTestDB -Q "CREATE USER testuser FOR LOGIN testuser" + docker exec -e SQLCMDPASSWORD sqlserver-stress /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -C -d StressTestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser" echo "Database setup completed" displayName: 'Start SQL Server container and setup database' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) # Run multi-threaded stress tests in an isolated subprocess. - script: | diff --git a/eng/pipelines/pr-validation-pipeline.yml b/eng/pipelines/pr-validation-pipeline.yml index f0323fb0b..9902b964e 100644 --- a/eng/pipelines/pr-validation-pipeline.yml +++ b/eng/pipelines/pr-validation-pipeline.yml @@ -85,7 +85,7 @@ jobs: # Create database and user for LocalDB - powershell: | sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "CREATE DATABASE TestDB" - sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "CREATE LOGIN testuser WITH PASSWORD = '$(DB_PASSWORD)'" + "CREATE LOGIN testuser WITH PASSWORD = '$env:DB_PASSWORD'" | sqlcmd -S "(localdb)\MSSQLLocalDB" sqlcmd -S "(localdb)\MSSQLLocalDB" -d TestDB -Q "CREATE USER testuser FOR LOGIN testuser" sqlcmd -S "(localdb)\MSSQLLocalDB" -d TestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser" displayName: 'Setup database and user for LocalDB' @@ -112,7 +112,27 @@ jobs: Start-Process -FilePath $setupFile.FullName -ArgumentList "/x:$env:TEMP\SQLSetup","/u" -Wait Write-Host "Running SQL Server setup..." - Start-Process -FilePath "$env:TEMP\SQLSetup\setup.exe" -ArgumentList "/Q","/ACTION=Install","/FEATURES=SQLEngine","/INSTANCENAME=MSSQLSERVER","/SQLSVCACCOUNT=`"NT AUTHORITY\SYSTEM`"","/SQLSYSADMINACCOUNTS=`"BUILTIN\Administrators`"","/TCPENABLED=1","/SECURITYMODE=SQL","/SAPWD=$(DB_PASSWORD)","/IACCEPTSQLSERVERLICENSETERMS" -Wait + $configPath = Join-Path $env:TEMP "sql2022-setup.ini" + @" +[OPTIONS] +QUIET="True" +ACTION="Install" +FEATURES=SQLEngine +INSTANCENAME=MSSQLSERVER +SQLSVCACCOUNT="NT AUTHORITY\SYSTEM" +SQLSYSADMINACCOUNTS="BUILTIN\Administrators" +TCPENABLED="1" +SECURITYMODE="SQL" +SAPWD="$env:DB_PASSWORD" +IACCEPTSQLSERVERLICENSETERMS="True" +"@ | Set-Content -Path $configPath -Encoding ASCII + $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name + icacls $configPath /inheritance:r /grant:r "${identity}:(R)" "SYSTEM:(R)" | Out-Null + try { + Start-Process -FilePath "$env:TEMP\SQLSetup\setup.exe" -ArgumentList "/ConfigurationFile=$configPath" -Wait + } finally { + Remove-Item $configPath -Force -ErrorAction SilentlyContinue + } } else { Write-Error "Failed to download SQL Server setup file" exit 1 @@ -126,6 +146,7 @@ jobs: # Create database for SQL Server 2022 - powershell: | + $env:SQLCMDPASSWORD = $env:DB_PASSWORD # Wait for SQL Server to start $maxAttempts = 30 $attempt = 0 @@ -134,7 +155,7 @@ jobs: Write-Host "Waiting for SQL Server 2022 to start..." while (-not $connected -and $attempt -lt $maxAttempts) { try { - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -Q "SELECT 1" -C + sqlcmd -S "localhost" -U "sa" -Q "SELECT 1" -C $connected = $true Write-Host "SQL Server is ready!" } catch { @@ -150,10 +171,10 @@ jobs: } # Create database and user - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -Q "CREATE DATABASE TestDB" -C - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -Q "CREATE LOGIN testuser WITH PASSWORD = '$(DB_PASSWORD)'" -C - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -d TestDB -Q "CREATE USER testuser FOR LOGIN testuser" -C - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -d TestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser" -C + sqlcmd -S "localhost" -U "sa" -Q "CREATE DATABASE TestDB" -C + "CREATE LOGIN testuser WITH PASSWORD = '$env:DB_PASSWORD'" | sqlcmd -S "localhost" -U "sa" -C + sqlcmd -S "localhost" -U "sa" -d TestDB -Q "CREATE USER testuser FOR LOGIN testuser" -C + sqlcmd -S "localhost" -U "sa" -d TestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser" -C displayName: 'Setup database and user for SQL Server 2022' condition: eq(variables['sqlVersion'], 'SQL2022') env: @@ -178,7 +199,27 @@ jobs: Start-Process -FilePath $setupFile.FullName -ArgumentList "/x:$env:TEMP\SQL2025Setup","/u" -Wait Write-Host "Running SQL Server setup..." - Start-Process -FilePath "$env:TEMP\SQL2025Setup\setup.exe" -ArgumentList "/Q","/ACTION=Install","/FEATURES=SQLEngine","/INSTANCENAME=MSSQLSERVER","/SQLSVCACCOUNT=`"NT AUTHORITY\SYSTEM`"","/SQLSYSADMINACCOUNTS=`"BUILTIN\Administrators`"","/TCPENABLED=1","/SECURITYMODE=SQL","/SAPWD=$(DB_PASSWORD)","/IACCEPTSQLSERVERLICENSETERMS" -Wait + $configPath = Join-Path $env:TEMP "sql2025-setup.ini" + @" +[OPTIONS] +QUIET="True" +ACTION="Install" +FEATURES=SQLEngine +INSTANCENAME=MSSQLSERVER +SQLSVCACCOUNT="NT AUTHORITY\SYSTEM" +SQLSYSADMINACCOUNTS="BUILTIN\Administrators" +TCPENABLED="1" +SECURITYMODE="SQL" +SAPWD="$env:DB_PASSWORD" +IACCEPTSQLSERVERLICENSETERMS="True" +"@ | Set-Content -Path $configPath -Encoding ASCII + $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name + icacls $configPath /inheritance:r /grant:r "${identity}:(R)" "SYSTEM:(R)" | Out-Null + try { + Start-Process -FilePath "$env:TEMP\SQL2025Setup\setup.exe" -ArgumentList "/ConfigurationFile=$configPath" -Wait + } finally { + Remove-Item $configPath -Force -ErrorAction SilentlyContinue + } } else { Write-Error "Failed to download SQL Server setup file" exit 1 @@ -192,6 +233,7 @@ jobs: # Create database for SQL Server 2025 - powershell: | + $env:SQLCMDPASSWORD = $env:DB_PASSWORD # Wait for SQL Server to start $maxAttempts = 30 $attempt = 0 @@ -200,7 +242,7 @@ jobs: Write-Host "Waiting for SQL Server 2025 to start..." while (-not $connected -and $attempt -lt $maxAttempts) { try { - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -Q "SELECT 1" -C + sqlcmd -S "localhost" -U "sa" -Q "SELECT 1" -C $connected = $true Write-Host "SQL Server is ready!" } catch { @@ -216,10 +258,10 @@ jobs: } # Create database and user - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -Q "CREATE DATABASE TestDB" -C - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -Q "CREATE LOGIN testuser WITH PASSWORD = '$(DB_PASSWORD)'" -C - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -d TestDB -Q "CREATE USER testuser FOR LOGIN testuser" -C - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -d TestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser" -C + sqlcmd -S "localhost" -U "sa" -Q "CREATE DATABASE TestDB" -C + "CREATE LOGIN testuser WITH PASSWORD = '$env:DB_PASSWORD'" | sqlcmd -S "localhost" -U "sa" -C + sqlcmd -S "localhost" -U "sa" -d TestDB -Q "CREATE USER testuser FOR LOGIN testuser" -C + sqlcmd -S "localhost" -U "sa" -d TestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser" -C displayName: 'Setup database and user for SQL Server 2025' condition: eq(variables['sqlVersion'], 'SQL2025') env: @@ -260,14 +302,15 @@ jobs: # Download and restore AdventureWorks2022 database for benchmarking - powershell: | + $env:SQLCMDPASSWORD = $env:DB_PASSWORD Write-Host "Downloading AdventureWorks2022.bak..." $ProgressPreference = 'SilentlyContinue' Invoke-WebRequest -Uri "https://github.com/Microsoft/sql-server-samples/releases/download/adventureworks/AdventureWorks2022.bak" -OutFile "$env:TEMP\AdventureWorks2022.bak" Write-Host "Restoring AdventureWorks2022 database..." # Get the default data and log paths - $dataPath = sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -Q "SET NOCOUNT ON; SELECT SERVERPROPERTY('InstanceDefaultDataPath') AS DataPath" -h -1 -C | Out-String - $logPath = sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -Q "SET NOCOUNT ON; SELECT SERVERPROPERTY('InstanceDefaultLogPath') AS LogPath" -h -1 -C | Out-String + $dataPath = sqlcmd -S "localhost" -U "sa" -Q "SET NOCOUNT ON; SELECT SERVERPROPERTY('InstanceDefaultDataPath') AS DataPath" -h -1 -C | Out-String + $logPath = sqlcmd -S "localhost" -U "sa" -Q "SET NOCOUNT ON; SELECT SERVERPROPERTY('InstanceDefaultLogPath') AS LogPath" -h -1 -C | Out-String $dataPath = $dataPath.Trim() $logPath = $logPath.Trim() @@ -276,7 +319,7 @@ jobs: Write-Host "Log path: $logPath" # Restore the database - sqlcmd -S "localhost" -U "sa" -P "$(DB_PASSWORD)" -C -Q @" + sqlcmd -S "localhost" -U "sa" -C -Q @" RESTORE DATABASE AdventureWorks2022 FROM DISK = '$env:TEMP\AdventureWorks2022.bak' WITH @@ -511,23 +554,24 @@ jobs: docker run \ --name sqlserver \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="${DB_PASSWORD}" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ -d $(sqlServerImage) # Starting SQL Server container… for i in {1..30}; do - docker exec sqlserver \ + docker exec -e SQLCMDPASSWORD sqlserver \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$DB_PASSWORD" \ -C -Q "SELECT 1" && break sleep 2 done displayName: 'Pull & start SQL Server (Docker)' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) - script: | python -m pip install --upgrade pip @@ -597,8 +641,8 @@ jobs: docker cp /tmp/AdventureWorks2022.bak sqlserver:/tmp/AdventureWorks2022.bak echo "Restoring AdventureWorks2022 database..." - docker exec sqlserver /opt/mssql-tools18/bin/sqlcmd \ - -S localhost -U SA -P "$DB_PASSWORD" -C \ + docker exec -e SQLCMDPASSWORD sqlserver /opt/mssql-tools18/bin/sqlcmd \ + -S localhost -U SA -C \ -Q "RESTORE DATABASE AdventureWorks2022 FROM DISK = '/tmp/AdventureWorks2022.bak' WITH MOVE 'AdventureWorks2022' TO '/var/opt/mssql/data/AdventureWorks2022.mdf', MOVE 'AdventureWorks2022_log' TO '/var/opt/mssql/data/AdventureWorks2022_log.ldf', REPLACE" if [ $? -eq 0 ]; then @@ -614,6 +658,7 @@ jobs: continueOnError: true env: DB_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) # Download macOS baseline from latest main run (for PR comparison) - task: DownloadPipelineArtifact@2 @@ -716,18 +761,17 @@ jobs: # Start SQL Server container docker run -d --name sqlserver-$(distroName) \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="$(DB_PASSWORD)" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ $(sqlServerImage) # Wait for SQL Server to be ready echo "Waiting for SQL Server to start..." for i in {1..60}; do - if docker exec sqlserver-$(distroName) \ + if docker exec -e SQLCMDPASSWORD sqlserver-$(distroName) \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "SELECT 1" >/dev/null 2>&1; then echo "SQL Server is ready!" break @@ -737,16 +781,17 @@ jobs: done # Create test database - docker exec sqlserver-$(distroName) \ + docker exec -e SQLCMDPASSWORD sqlserver-$(distroName) \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "CREATE DATABASE TestDB" displayName: 'Start SQL Server container for $(distroName)' condition: eq(variables['useAzureSQL'], 'false') env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) - script: | # Install dependencies in the container @@ -860,7 +905,7 @@ jobs: echo "Testing against Azure SQL Database" docker exec \ - -e DB_CONNECTION_STRING="$(AZURE_CONNECTION_STRING)" \ + -e DB_CONNECTION_STRING \ test-container-$(distroName) bash -c " source /opt/venv/bin/activate echo 'Build successful, running tests now on $(distroName) with Azure SQL' @@ -871,10 +916,11 @@ jobs: # Local SQL Server testing SQLSERVER_IP=$(docker inspect sqlserver-$(distroName) --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') echo "SQL Server IP: $SQLSERVER_IP" + export DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$DB_PASSWORD;TrustServerCertificate=yes" docker exec \ - -e DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes" \ - -e DB_PASSWORD="$(DB_PASSWORD)" \ + -e DB_CONNECTION_STRING \ + -e DB_PASSWORD \ test-container-$(distroName) bash -c " source /opt/venv/bin/activate echo 'Build successful, running tests now on $(distroName)' @@ -886,6 +932,7 @@ jobs: condition: or(eq(variables['useAzureSQL'], 'false'), and(eq(variables['useAzureSQL'], 'true'), ne(variables['AZURE_CONNECTION_STRING'], ''))) env: DB_PASSWORD: $(DB_PASSWORD) + DB_CONNECTION_STRING: $(AZURE_CONNECTION_STRING) - script: | # Download and restore AdventureWorks2022 database for benchmarking on Ubuntu only @@ -897,10 +944,9 @@ jobs: docker cp /tmp/AdventureWorks2022.bak sqlserver-$(distroName):/tmp/AdventureWorks2022.bak echo "Restoring AdventureWorks2022 database..." - docker exec sqlserver-$(distroName) /opt/mssql-tools18/bin/sqlcmd \ + docker exec -e SQLCMDPASSWORD sqlserver-$(distroName) /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C \ -Q "RESTORE DATABASE AdventureWorks2022 FROM DISK = '/tmp/AdventureWorks2022.bak' WITH MOVE 'AdventureWorks2022' TO '/var/opt/mssql/data/AdventureWorks2022.mdf', MOVE 'AdventureWorks2022_log' TO '/var/opt/mssql/data/AdventureWorks2022_log.ldf', REPLACE" @@ -919,15 +965,17 @@ jobs: continueOnError: true env: DB_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) - script: | # Run performance benchmarks on Ubuntu with SQL Server 2022 only if [ "$(distroName)" = "Ubuntu" ] && [ "$(useAzureSQL)" = "false" ]; then SQLSERVER_IP=$(docker inspect sqlserver-$(distroName) --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') echo "Running performance benchmarks on Ubuntu with SQL Server IP: $SQLSERVER_IP" + export DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=AdventureWorks2022;Uid=SA;Pwd=$DB_PASSWORD;TrustServerCertificate=yes" docker exec \ - -e DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=AdventureWorks2022;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes" \ + -e DB_CONNECTION_STRING \ test-container-$(distroName) bash -c " source /opt/venv/bin/activate @@ -1041,18 +1089,17 @@ jobs: docker run -d --name sqlserver-$(distroName)-$(archName) \ --platform linux/amd64 \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="$(DB_PASSWORD)" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ mcr.microsoft.com/mssql/server:2022-latest # Wait for SQL Server to be ready echo "Waiting for SQL Server to start..." for i in {1..60}; do - if docker exec sqlserver-$(distroName)-$(archName) \ + if docker exec -e SQLCMDPASSWORD sqlserver-$(distroName)-$(archName) \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "SELECT 1" >/dev/null 2>&1; then echo "SQL Server is ready!" break @@ -1062,15 +1109,16 @@ jobs: done # Create test database - docker exec sqlserver-$(distroName)-$(archName) \ + docker exec -e SQLCMDPASSWORD sqlserver-$(distroName)-$(archName) \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "CREATE DATABASE TestDB" displayName: 'Start SQL Server container for $(distroName) ARM64' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) - script: | # Install dependencies in the ARM64 container @@ -1207,10 +1255,11 @@ jobs: # Get SQL Server container IP SQLSERVER_IP=$(docker inspect sqlserver-$(distroName)-$(archName) --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') echo "SQL Server IP: $SQLSERVER_IP" + export DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$DB_PASSWORD;TrustServerCertificate=yes" docker exec \ - -e DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes" \ - -e DB_PASSWORD="$(DB_PASSWORD)" \ + -e DB_CONNECTION_STRING \ + -e DB_PASSWORD \ test-container-$(distroName)-$(archName) bash -c " source /opt/venv/bin/activate echo 'Build successful, running tests now on $(distroName) ARM64' @@ -1265,18 +1314,17 @@ jobs: # Start SQL Server container docker run -d --name sqlserver-rhel9 \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="$(DB_PASSWORD)" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ mcr.microsoft.com/mssql/server:2022-latest # Wait for SQL Server to be ready echo "Waiting for SQL Server to start..." for i in {1..60}; do - if docker exec sqlserver-rhel9 \ + if docker exec -e SQLCMDPASSWORD sqlserver-rhel9 \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "SELECT 1" >/dev/null 2>&1; then echo "SQL Server is ready!" break @@ -1286,15 +1334,16 @@ jobs: done # Create test database - docker exec sqlserver-rhel9 \ + docker exec -e SQLCMDPASSWORD sqlserver-rhel9 \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "CREATE DATABASE TestDB" displayName: 'Start SQL Server container for RHEL 9' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) - script: | # Install dependencies in the RHEL 9 container @@ -1426,10 +1475,11 @@ jobs: # Get SQL Server container IP SQLSERVER_IP=$(docker inspect sqlserver-rhel9 --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') echo "SQL Server IP: $SQLSERVER_IP" + export DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$DB_PASSWORD;TrustServerCertificate=yes" docker exec \ - -e DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes" \ - -e DB_PASSWORD="$(DB_PASSWORD)" \ + -e DB_CONNECTION_STRING \ + -e DB_PASSWORD \ test-container-rhel9 bash -c " source myvenv/bin/activate echo 'Build successful, running tests now on RHEL 9' @@ -1492,18 +1542,17 @@ jobs: docker run -d --name sqlserver-rhel9-arm64 \ --platform linux/amd64 \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="$(DB_PASSWORD)" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ mcr.microsoft.com/mssql/server:2022-latest # Wait for SQL Server to be ready echo "Waiting for SQL Server to start..." for i in {1..60}; do - if docker exec sqlserver-rhel9-arm64 \ + if docker exec -e SQLCMDPASSWORD sqlserver-rhel9-arm64 \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "SELECT 1" >/dev/null 2>&1; then echo "SQL Server is ready!" break @@ -1513,15 +1562,16 @@ jobs: done # Create test database - docker exec sqlserver-rhel9-arm64 \ + docker exec -e SQLCMDPASSWORD sqlserver-rhel9-arm64 \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "CREATE DATABASE TestDB" displayName: 'Start SQL Server container for RHEL 9 ARM64' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) - script: | # Install dependencies in the RHEL 9 ARM64 container @@ -1657,10 +1707,11 @@ jobs: # Get SQL Server container IP SQLSERVER_IP=$(docker inspect sqlserver-rhel9-arm64 --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') echo "SQL Server IP: $SQLSERVER_IP" + export DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$DB_PASSWORD;TrustServerCertificate=yes" docker exec \ - -e DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes" \ - -e DB_PASSWORD="$(DB_PASSWORD)" \ + -e DB_CONNECTION_STRING \ + -e DB_PASSWORD \ test-container-rhel9-arm64 bash -c " source myvenv/bin/activate echo 'Build successful, running tests now on RHEL 9 ARM64' @@ -1723,18 +1774,17 @@ jobs: docker run -d --name sqlserver-alpine \ --platform linux/amd64 \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="$(DB_PASSWORD)" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ mcr.microsoft.com/mssql/server:2022-latest # Wait for SQL Server to be ready echo "Waiting for SQL Server to start..." for i in {1..60}; do - if docker exec sqlserver-alpine \ + if docker exec -e SQLCMDPASSWORD sqlserver-alpine \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "SELECT 1" >/dev/null 2>&1; then echo "SQL Server is ready!" break @@ -1744,15 +1794,16 @@ jobs: done # Create test database - docker exec sqlserver-alpine \ + docker exec -e SQLCMDPASSWORD sqlserver-alpine \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "CREATE DATABASE TestDB" displayName: 'Start SQL Server container for Alpine x86_64' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) - script: | # Install dependencies in the Alpine x86_64 container @@ -1897,10 +1948,11 @@ jobs: # Get SQL Server container IP SQLSERVER_IP=$(docker inspect sqlserver-alpine --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') echo "SQL Server IP: $SQLSERVER_IP" + export DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$DB_PASSWORD;TrustServerCertificate=yes" docker exec \ - -e DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes" \ - -e DB_PASSWORD="$(DB_PASSWORD)" \ + -e DB_CONNECTION_STRING \ + -e DB_PASSWORD \ test-container-alpine bash -c " echo 'Build successful, running tests now on Alpine x86_64' echo 'Architecture:' \$(uname -m) @@ -1979,18 +2031,17 @@ jobs: docker run -d --name sqlserver-alpine-arm64 \ --platform linux/amd64 \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="$(DB_PASSWORD)" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ mcr.microsoft.com/mssql/server:2022-latest # Wait for SQL Server to be ready echo "Waiting for SQL Server to start..." for i in {1..60}; do - if docker exec sqlserver-alpine-arm64 \ + if docker exec -e SQLCMDPASSWORD sqlserver-alpine-arm64 \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "SELECT 1" >/dev/null 2>&1; then echo "SQL Server is ready!" break @@ -2000,15 +2051,16 @@ jobs: done # Create test database - docker exec sqlserver-alpine-arm64 \ + docker exec -e SQLCMDPASSWORD sqlserver-alpine-arm64 \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "CREATE DATABASE TestDB" displayName: 'Start SQL Server container for Alpine ARM64' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) - script: | # Install dependencies in the Alpine ARM64 container @@ -2154,10 +2206,11 @@ jobs: # Get SQL Server container IP SQLSERVER_IP=$(docker inspect sqlserver-alpine-arm64 --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}') echo "SQL Server IP: $SQLSERVER_IP" + export DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$DB_PASSWORD;TrustServerCertificate=yes" docker exec \ - -e DB_CONNECTION_STRING="Server=$SQLSERVER_IP;Database=TestDB;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes" \ - -e DB_PASSWORD="$(DB_PASSWORD)" \ + -e DB_CONNECTION_STRING \ + -e DB_PASSWORD \ test-container-alpine-arm64 bash -c " echo 'Build successful, running tests now on Alpine ARM64' echo 'Architecture:' \$(uname -m) @@ -2403,7 +2456,7 @@ jobs: # # - script: | # docker exec \ -# -e DB_CONNECTION_STRING="$(AZURE_CONNECTION_STRING)" \ +# -e DB_CONNECTION_STRING \ # test-container-ubuntu-azuresql bash -c " # source /opt/venv/bin/activate # echo 'Running tests on Ubuntu against Azure SQL Database' @@ -2449,23 +2502,24 @@ jobs: docker run \ --name sqlserver \ -e ACCEPT_EULA=Y \ - -e MSSQL_SA_PASSWORD="$(DB_PASSWORD)" \ + -e MSSQL_SA_PASSWORD \ -p 1433:1433 \ -d mcr.microsoft.com/mssql/server:2022-latest # Wait until SQL Server is ready for i in {1..30}; do - docker exec sqlserver \ + docker exec -e SQLCMDPASSWORD sqlserver \ /opt/mssql-tools18/bin/sqlcmd \ -S localhost \ -U SA \ - -P "$(DB_PASSWORD)" \ -C -Q "SELECT 1" && break sleep 2 done displayName: 'Start SQL Server container' env: DB_PASSWORD: $(DB_PASSWORD) + MSSQL_SA_PASSWORD: $(DB_PASSWORD) + SQLCMDPASSWORD: $(DB_PASSWORD) - script: | # Install Python dependencies From f90d11d77b074e26dbb5e30202b2e74c0d3a8d21 Mon Sep 17 00:00:00 2001 From: gargsaumya Date: Thu, 13 Aug 2026 12:04:31 +0530 Subject: [PATCH 2/3] FIX: Scope umask to secret-file writes in devcontainer post-create Avoid mutating the global umask; create per-file with owner-only perms via a scoped subshell and pre-write chmod. --- .devcontainer/post-create.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 2a565b821..e32748373 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -51,11 +51,11 @@ fi # Generate random password for SQL Server echo "" echo "Generating SQL Server password..." -umask 077 SA_PASSWORD="$(openssl rand -base64 16 | tr -dc 'A-Za-z0-9' | head -c 16)Aa1!" +# mktemp creates 0600; chmod before writing keeps it owner-only without touching the global umask. SQL_ENV_FILE="$(mktemp)" -printf 'ACCEPT_EULA=Y\nMSSQL_SA_PASSWORD=%s\n' "$SA_PASSWORD" > "$SQL_ENV_FILE" chmod 600 "$SQL_ENV_FILE" +printf 'ACCEPT_EULA=Y\nMSSQL_SA_PASSWORD=%s\n' "$SA_PASSWORD" > "$SQL_ENV_FILE" # Start SQL Server container (use Azure SQL Edge for ARM64 compatibility) # This is optional - if Docker-in-Docker fails, the devcontainer still works @@ -90,7 +90,8 @@ DB_CONNECTION_STRING="Server=localhost,1433;Database=master;UID=sa;PWD=$SA_PASSW # Keep the credential in a user-only file and source it from interactive shells. MSSQL_ENV_FILE="$HOME/.mssql_python_env" -printf "export DB_CONNECTION_STRING='%s'\n" "$DB_CONNECTION_STRING" > "$MSSQL_ENV_FILE" +# Scope umask to this write only so the file is owner-only from creation; global umask stays untouched. +( umask 077; printf "export DB_CONNECTION_STRING='%s'\n" "$DB_CONNECTION_STRING" > "$MSSQL_ENV_FILE" ) chmod 600 "$MSSQL_ENV_FILE" # Remove plaintext entries left by older versions of this script. From 86a4eac31f1c751bc10106117bf61169be95e11a Mon Sep 17 00:00:00 2001 From: gargsaumya Date: Thu, 13 Aug 2026 13:11:53 +0530 Subject: [PATCH 3/3] FIX: Repair YAML block scalar broken by SQL setup config here-string The PowerShell here-string content sat at column 0, which dedented out of the YAML '|' block and made the ADO parser reject the pipeline. Replace it with an indented PowerShell array written via Set-Content, keeping clean INI output. --- eng/pipelines/pr-validation-pipeline.yml | 54 ++++++++++++------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/eng/pipelines/pr-validation-pipeline.yml b/eng/pipelines/pr-validation-pipeline.yml index 9902b964e..4d6029aa0 100644 --- a/eng/pipelines/pr-validation-pipeline.yml +++ b/eng/pipelines/pr-validation-pipeline.yml @@ -113,19 +113,20 @@ jobs: Write-Host "Running SQL Server setup..." $configPath = Join-Path $env:TEMP "sql2022-setup.ini" - @" -[OPTIONS] -QUIET="True" -ACTION="Install" -FEATURES=SQLEngine -INSTANCENAME=MSSQLSERVER -SQLSVCACCOUNT="NT AUTHORITY\SYSTEM" -SQLSYSADMINACCOUNTS="BUILTIN\Administrators" -TCPENABLED="1" -SECURITYMODE="SQL" -SAPWD="$env:DB_PASSWORD" -IACCEPTSQLSERVERLICENSETERMS="True" -"@ | Set-Content -Path $configPath -Encoding ASCII + $configLines = @( + '[OPTIONS]' + 'QUIET="True"' + 'ACTION="Install"' + 'FEATURES=SQLEngine' + 'INSTANCENAME=MSSQLSERVER' + 'SQLSVCACCOUNT="NT AUTHORITY\SYSTEM"' + 'SQLSYSADMINACCOUNTS="BUILTIN\Administrators"' + 'TCPENABLED="1"' + 'SECURITYMODE="SQL"' + "SAPWD=`"$env:DB_PASSWORD`"" + 'IACCEPTSQLSERVERLICENSETERMS="True"' + ) + Set-Content -Path $configPath -Value $configLines -Encoding ASCII $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name icacls $configPath /inheritance:r /grant:r "${identity}:(R)" "SYSTEM:(R)" | Out-Null try { @@ -200,19 +201,20 @@ IACCEPTSQLSERVERLICENSETERMS="True" Write-Host "Running SQL Server setup..." $configPath = Join-Path $env:TEMP "sql2025-setup.ini" - @" -[OPTIONS] -QUIET="True" -ACTION="Install" -FEATURES=SQLEngine -INSTANCENAME=MSSQLSERVER -SQLSVCACCOUNT="NT AUTHORITY\SYSTEM" -SQLSYSADMINACCOUNTS="BUILTIN\Administrators" -TCPENABLED="1" -SECURITYMODE="SQL" -SAPWD="$env:DB_PASSWORD" -IACCEPTSQLSERVERLICENSETERMS="True" -"@ | Set-Content -Path $configPath -Encoding ASCII + $configLines = @( + '[OPTIONS]' + 'QUIET="True"' + 'ACTION="Install"' + 'FEATURES=SQLEngine' + 'INSTANCENAME=MSSQLSERVER' + 'SQLSVCACCOUNT="NT AUTHORITY\SYSTEM"' + 'SQLSYSADMINACCOUNTS="BUILTIN\Administrators"' + 'TCPENABLED="1"' + 'SECURITYMODE="SQL"' + "SAPWD=`"$env:DB_PASSWORD`"" + 'IACCEPTSQLSERVERLICENSETERMS="True"' + ) + Set-Content -Path $configPath -Value $configLines -Encoding ASCII $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name icacls $configPath /inheritance:r /grant:r "${identity}:(R)" "SYSTEM:(R)" | Out-Null try {