From 4cc21a6edff4da2a683b3e1bab70130ce65d5fa5 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 17 Jun 2026 13:02:17 -0300 Subject: [PATCH 01/12] pipeline: extract download-assembly-signing-key template and wire signing through CI - Create reusable eng/pipelines/common/steps/download-assembly-signing-key.yml template with isTest parameter for driver vs test key download - Migrate all pack jobs to use the template (Abstractions, Azure, Logging, SqlClient, OneBranch) - Add explicit signingKeyPath parameter to ci-project-build-step (replaces implicit ##vso[task.setvariable] mechanism) - Thread isInternalBuild through stages to pack and test jobs - Add testSigningKeyPath to run-all-tests-step and ci-run-tests-job - Add isInternalBuild + signing support to test-abstractions-package-ci-job and test-azure-package-ci-job templates - Remove @TODO comments about signing gap in stage files --- .../ci/package/sqlclient-package.yml | 12 ++-- .../steps/download-assembly-signing-key.yml | 39 ++++++++++++ .../templates/jobs/ci-build-nugets-job.yml | 15 +++++ .../templates/jobs/ci-run-tests-job.yml | 20 ++++++ .../templates/stages/ci-run-tests-stage.yml | 7 +++ .../templates/steps/ci-project-build-step.yml | 9 +++ .../templates/steps/run-all-tests-step.yml | 48 ++++++++++++++ eng/pipelines/dotnet-sqlclient-ci-core.yml | 11 ++++ ...qlclient-ci-package-reference-pipeline.yml | 1 + ...qlclient-ci-project-reference-pipeline.yml | 1 + .../jobs/pack-abstractions-package-ci-job.yml | 63 +++++++++++-------- .../jobs/pack-azure-package-ci-job.yml | 63 +++++++++++-------- .../jobs/pack-logging-package-ci-job.yml | 24 ++++++- .../jobs/test-abstractions-package-ci-job.yml | 25 +++++++- .../jobs/test-azure-package-ci-job.yml | 25 +++++++- .../onebranch/steps/build-buildproj-step.yml | 10 +-- .../build-abstractions-package-ci-stage.yml | 9 +++ .../stages/build-azure-package-ci-stage.yml | 11 ++++ .../build-sqlclient-package-ci-stage.yml | 6 ++ 19 files changed, 331 insertions(+), 68 deletions(-) create mode 100644 eng/pipelines/common/steps/download-assembly-signing-key.yml diff --git a/eng/pipelines/ci/package/sqlclient-package.yml b/eng/pipelines/ci/package/sqlclient-package.yml index e194e2abef..72c65b364e 100644 --- a/eng/pipelines/ci/package/sqlclient-package.yml +++ b/eng/pipelines/ci/package/sqlclient-package.yml @@ -89,10 +89,10 @@ variables: value: ${{ eq(variables['System.TeamProject'], 'ADO.Net') }} # Signing key argument passed to build.proj. On internal builds this references the secure file - # downloaded by DownloadSecureFile@1; on public builds it expands to empty. + # downloaded by download-assembly-signing-key.yml; on public builds it expands to empty. - name: signingKeyArg ${{ if eq(variables.isInternalBuild, true) }}: - value: '-p:SigningKeyPath="$(keyFile.secureFilePath)"' + value: '-p:SigningKeyPath="$(driverKeyFile.secureFilePath)"' ${{ else }}: value: '' @@ -133,13 +133,9 @@ jobs: Write-Host 'Done.' displayName: Clean packages/ directory - # On internal builds, download the strong-name signing key. + # On internal builds, download the assembly signing key. - ${{ if eq(variables.isInternalBuild, true) }}: - - task: DownloadSecureFile@1 - displayName: Download Signing Key - inputs: - secureFile: netfxKeypair.snk - name: keyFile + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self # Run the Pack target via build.proj. - task: DotNetCoreCLI@2 diff --git a/eng/pipelines/common/steps/download-assembly-signing-key.yml b/eng/pipelines/common/steps/download-assembly-signing-key.yml new file mode 100644 index 0000000000..b7c415f74d --- /dev/null +++ b/eng/pipelines/common/steps/download-assembly-signing-key.yml @@ -0,0 +1,39 @@ +################################################################################ +# Licensed to the .NET Foundation under one or more agreements. The .NET +# Foundation licenses this file to you under the MIT license. See the LICENSE +# file in the project root for more information. +################################################################################ + +# Downloads a signing key from ADO secure files. +# +# When isTest is false, downloads the driver signing key and exports it as 'driverKeyFile'. When +# isTest is true, downloads the test signing key and exports it as 'testKeyFile'. +# +# Downstream steps reference the path via: +# +# $(driverKeyFile.secureFilePath) or +# $(testKeyFile.secureFilePath) + +parameters: + + # When false, download the driver signing key. + # When true, download the test signing key. + - name: isTest + type: boolean + default: false + +steps: + + - ${{ if eq(parameters.isTest, false) }}: + - task: DownloadSecureFile@1 + displayName: Download Driver Signing Key + inputs: + secureFile: netfxKeypair.snk + name: driverKeyFile + + - ${{ if eq(parameters.isTest, true) }}: + - task: DownloadSecureFile@1 + displayName: Download Test Signing Key + inputs: + secureFile: sqlclient-test-key.snk + name: testKeyFile diff --git a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml index aa6a1c50c5..130f314beb 100644 --- a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml @@ -87,6 +87,11 @@ parameters: type: string default: SqlServer.Artifacts + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: build_mds_akv_packages_job displayName: Build MDS & AKV Packages @@ -137,6 +142,10 @@ jobs: # Restore dotnet CLI tools (e.g. pwsh, apicompat) before building. - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self + # Download the assembly signing key for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # When we're performing a Debug build, we still want to try _compiling_ the # code in Release mode to ensure downstream pipelines don't encounter # compilation errors. We won't use the Release artifacts for anything else @@ -148,6 +157,8 @@ jobs: buildConfiguration: Release referenceType: Project build: all + ${{ if eq(parameters.isInternalBuild, true) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) - template: /eng/pipelines/common/templates/steps/ci-project-build-step.yml@self parameters: @@ -159,6 +170,8 @@ jobs: abstractionsPackageVersion: ${{parameters.abstractionsPackageVersion}} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + ${{ if eq(parameters.isInternalBuild, true) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) - task: DotNetCoreCLI@2 displayName: 'Create MDS NuGet Package' @@ -206,6 +219,8 @@ jobs: mdsPackageVersion: ${{ parameters.mdsPackageVersion }} akvPackageVersion: ${{ parameters.akvPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + ${{ if eq(parameters.isInternalBuild, true) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) - task: DotNetCoreCLI@2 displayName: 'Create AKV Provider NuGet Package' diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index 1b1ea7a2e7..df508c9522 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -160,6 +160,11 @@ parameters: - name: saPassword type: string + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: ${{ format('{0}', coalesce(parameters.jobDisplayName, parameters.image, 'unknown_image')) }} @@ -223,6 +228,13 @@ jobs: # Restore dotnet CLI tools (e.g. pwsh, apicompat) before building. - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self + # Download the assembly signing keys for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + - ${{ if ne(parameters.prebuildSteps, '') }}: - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration @@ -232,6 +244,8 @@ jobs: build: allNoDocs buildConfiguration: ${{ parameters.buildConfiguration }} referenceType: Project + ${{ if eq(parameters.isInternalBuild, true) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) - ${{ if ne(parameters.configProperties, '{}') }}: - template: /eng/pipelines/common/templates/steps/update-config-file-step.yml@self # update config.jsonc file @@ -378,6 +392,9 @@ jobs: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + ${{ if eq(parameters.isInternalBuild, true) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) + testSigningKeyPath: $(testKeyFile.secureFilePath) - ${{ if and(eq(parameters.enableX86Test, true), eq(parameters.operatingSystem, 'Windows')) }}: - template: /eng/pipelines/common/templates/steps/run-all-tests-step.yml@self @@ -394,6 +411,9 @@ jobs: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + ${{ if eq(parameters.isInternalBuild, true) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) + testSigningKeyPath: $(testKeyFile.secureFilePath) - template: /eng/pipelines/common/templates/steps/publish-test-results-step.yml@self parameters: diff --git a/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml b/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml index 86ddc0ca45..86c86f7aec 100644 --- a/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml +++ b/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml @@ -88,6 +88,11 @@ parameters: - name: testJobTimeout type: number + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - ${{ each config in parameters.testConfigurations }}: - ${{ each image in config.value.images }}: @@ -124,6 +129,7 @@ stages: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsArtifactsName: ${{ parameters.mdsArtifactsName }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} + isInternalBuild: ${{ parameters.isInternalBuild }} sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} prebuildSteps: ${{ parameters.prebuildSteps }} @@ -162,6 +168,7 @@ stages: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsArtifactsName: ${{ parameters.mdsArtifactsName }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} + isInternalBuild: ${{ parameters.isInternalBuild }} sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} prebuildSteps: ${{ parameters.prebuildSteps }} diff --git a/eng/pipelines/common/templates/steps/ci-project-build-step.yml b/eng/pipelines/common/templates/steps/ci-project-build-step.yml index e5fa6d4424..a4b980f46e 100644 --- a/eng/pipelines/common/templates/steps/ci-project-build-step.yml +++ b/eng/pipelines/common/templates/steps/ci-project-build-step.yml @@ -73,6 +73,13 @@ parameters: type: string default: $(sqlServerPackageVersion) + # Path to the assembly signing key file. When non-empty, passed as -p:SigningKeyPath="" to the + # build. The calling job is responsible for downloading the key (via + # download-assembly-signing-key.yml). + - name: signingKeyPath + type: string + default: '' + steps: # Build MDS - ${{ if or(eq(parameters.build, 'MDS'), eq(parameters.build, 'all'), eq(parameters.build, 'allNoDocs')) }}: @@ -91,6 +98,7 @@ steps: -p:PackageVersionLogging=${{ parameters.loggingPackageVersion }} -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" # Build AKV Provider - ${{ if or(eq(parameters.build, 'AkvProvider'), eq(parameters.build, 'all'), eq(parameters.build, 'allNoDocs')) }}: @@ -110,3 +118,4 @@ steps: -p:PackageVersionLogging=${{ parameters.loggingPackageVersion }} -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" diff --git a/eng/pipelines/common/templates/steps/run-all-tests-step.yml b/eng/pipelines/common/templates/steps/run-all-tests-step.yml index e41c7d22b2..02c22087b4 100644 --- a/eng/pipelines/common/templates/steps/run-all-tests-step.yml +++ b/eng/pipelines/common/templates/steps/run-all-tests-step.yml @@ -72,6 +72,18 @@ parameters: type: number default: 2 + # Path to the assembly signing key file. When non-empty, passed to build.proj so that the + # test-filter logic can include category=signed tests. + - name: signingKeyPath + type: string + default: '' + + # Path to the test assembly signing key file. When non-empty, passed to build.proj so that test + # assemblies are signed and can satisfy InternalsVisibleTo grants from signed source assemblies. + - name: testSigningKeyPath + type: string + default: '' + steps: - ${{ if parameters.debug }}: - powershell: 'dotnet sdk check' @@ -94,6 +106,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientUnit @@ -104,6 +118,8 @@ steps: -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:DotnetPath=${{ parameters.dotnetx86RootPath }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" - task: DotNetCoreCLI@2 displayName: 'Run Flaky Unit Tests ${{parameters.msbuildArchitecture }}' @@ -122,6 +138,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientUnit @@ -134,6 +152,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - task: DotNetCoreCLI@2 @@ -153,6 +173,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientFunctional @@ -165,6 +187,8 @@ steps: -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:DotnetPath=${{ parameters.dotnetx86RootPath }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" - task: DotNetCoreCLI@2 displayName: 'Run Flaky Functional Tests ${{parameters.msbuildArchitecture }}' @@ -185,6 +209,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientFunctional @@ -199,6 +225,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - task: DotNetCoreCLI@2 @@ -219,6 +247,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientManual @@ -232,6 +262,8 @@ steps: -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:DotnetPath=${{ parameters.dotnetx86RootPath }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" retryCountOnTaskFailure: ${{parameters.retryCountOnManualTests }} - task: DotNetCoreCLI@2 @@ -254,6 +286,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientManual @@ -269,6 +303,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - ${{ else }}: # Linux or macOS @@ -286,6 +322,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" - task: DotNetCoreCLI@2 displayName: 'Run Flaky Unit Tests' @@ -303,6 +341,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - task: DotNetCoreCLI@2 @@ -321,6 +361,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" - task: DotNetCoreCLI@2 displayName: 'Run Flaky Functional Tests' @@ -340,6 +382,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - task: DotNetCoreCLI@2 displayName: 'Run Manual Tests' @@ -358,6 +402,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" retryCountOnTaskFailure: ${{parameters.retryCountOnManualTests }} - task: DotNetCoreCLI@2 @@ -379,4 +425,6 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 9ee7c7132d..5fdc25ee0e 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -104,6 +104,12 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. Internal builds may perform additional or + # different steps, such as assembly signing. + - name: isInternalBuild + type: boolean + default: false + variables: - template: /eng/pipelines/libraries/ci-build-variables.yml@self @@ -150,6 +156,7 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} # Build the Abstractions package, and publish it to the pipeline artifacts # under the given artifact name. @@ -167,6 +174,7 @@ stages: loggingArtifactsName: $(loggingArtifactsName) loggingPackageVersion: $(loggingPackageVersion) referenceType: ${{ parameters.referenceType }} + isInternalBuild: ${{ parameters.isInternalBuild }} # When building Abstractions via packages, we must depend on the Logging # package. ${{ if eq(parameters.referenceType, 'Package') }}: @@ -188,6 +196,7 @@ stages: mdsPackageVersion: $(mdsPackageVersion) akvPackageVersion: $(akvPackageVersion) referenceType: ${{ parameters.referenceType }} + isInternalBuild: ${{ parameters.isInternalBuild }} sqlServerArtifactsName: $(sqlServerArtifactsName) sqlServerPackageVersion: $(sqlServerPackageVersion) SNIVersion: ${{ parameters.SNIVersion }} @@ -220,6 +229,7 @@ stages: - build_sqlserver_package_stage - build_sqlclient_package_stage dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} loggingArtifactsName: $(loggingArtifactsName) loggingPackageVersion: $(loggingPackageVersion) mdsArtifactsName: $(mdsArtifactsName) @@ -251,6 +261,7 @@ stages: loggingPackageVersion: $(loggingPackageVersion) mdsArtifactsName: $(mdsArtifactsName) mdsPackageVersion: $(mdsPackageVersion) + isInternalBuild: ${{ parameters.isInternalBuild }} sqlServerArtifactsName: $(sqlServerArtifactsName) sqlServerPackageVersion: $(sqlServerPackageVersion) testJobTimeout: ${{ parameters.testJobTimeout }} diff --git a/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml b/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml index 98cac1bcdd..c510dc2c6b 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml @@ -174,3 +174,4 @@ extends: testJobTimeout: ${{ parameters.testJobTimeout }} testSets: ${{ parameters.testSets }} useManagedSNI: ${{ parameters.useManagedSNI }} + isInternalBuild: ${{ eq(variables['System.TeamProject'], 'ADO.Net') }} diff --git a/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml b/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml index 7068c9693c..29f2660f0f 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml @@ -174,3 +174,4 @@ extends: testJobTimeout: ${{ parameters.testJobTimeout }} testSets: ${{ parameters.testSets }} useManagedSNI: ${{ parameters.useManagedSNI }} + isInternalBuild: ${{ eq(variables['System.TeamProject'], 'ADO.Net') }} diff --git a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml index d077aa2115..b75900f1bc 100644 --- a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml @@ -77,6 +77,11 @@ parameters: # Reference sibling packages as C# projects. - Project + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: pack_abstractions_package_job @@ -119,6 +124,26 @@ jobs: - name: Configuration value: '' + # Build properties passed to dotnet pack. Composed from a base set plus + # optional suffixes for Package-mode dependencies and assembly signing. + - name: baseBuildProperties + value: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }} + + - name: packageModeProperties + ${{ if eq(parameters.referenceType, 'Package') }}: + value: ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }} + ${{ else }}: + value: '' + + - name: signingProperties + ${{ if eq(parameters.isInternalBuild, true) }}: + value: SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ else }}: + value: '' + + - name: buildProperties + value: $(baseBuildProperties);$(packageModeProperties);$(signingProperties) + steps: # Emit environment variables if debug is enabled. @@ -140,32 +165,20 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. - # - # When referenceType is Package, we must pass ReferenceType and the - # dependency version so that Directory.Packages.props applies version - # ranges to sibling package dependencies. - - ${{ if eq(parameters.referenceType, 'Package') }}: - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }};ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }} - - - ${{ else }}: - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }} + - task: DotNetCoreCLI@2 + displayName: Create NuGet Package + inputs: + command: pack + packagesToPack: $(project) + configurationToPack: ${{ parameters.buildConfiguration }} + packDirectory: $(dotnetPackagesDir) + verbosityToPack: ${{ parameters.dotnetVerbosity }} + buildProperties: $(buildProperties) # Publish the NuGet packages as a named pipeline artifact. - task: PublishPipelineArtifact@1 diff --git a/eng/pipelines/jobs/pack-azure-package-ci-job.yml b/eng/pipelines/jobs/pack-azure-package-ci-job.yml index 12567fec14..81def77c44 100644 --- a/eng/pipelines/jobs/pack-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-azure-package-ci-job.yml @@ -89,6 +89,11 @@ parameters: # Reference sibling packages as C# projects. - Project + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: pack_azure_package_job @@ -131,6 +136,26 @@ jobs: - name: Configuration value: '' + # Build properties passed to dotnet pack. Composed from a base set plus + # optional suffixes for Package-mode dependencies and assembly signing. + - name: baseBuildProperties + value: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }} + + - name: packageModeProperties + ${{ if eq(parameters.referenceType, 'Package') }}: + value: ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }} + ${{ else }}: + value: '' + + - name: signingProperties + ${{ if eq(parameters.isInternalBuild, true) }}: + value: SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ else }}: + value: '' + + - name: buildProperties + value: $(baseBuildProperties);$(packageModeProperties);$(signingProperties) + steps: # Emit environment variables if debug is enabled. @@ -157,32 +182,20 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. - # - # When referenceType is Package, we must pass ReferenceType and the - # dependency versions so that Directory.Packages.props applies version - # ranges to sibling package dependencies. - - ${{ if eq(parameters.referenceType, 'Package') }}: - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }};ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }} - - - ${{ else }}: - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }} + - task: DotNetCoreCLI@2 + displayName: Create NuGet Package + inputs: + command: pack + packagesToPack: $(project) + configurationToPack: ${{ parameters.buildConfiguration }} + packDirectory: $(dotnetPackagesDir) + verbosityToPack: ${{ parameters.dotnetVerbosity }} + buildProperties: $(buildProperties) # Publish the NuGet packages as a named pipeline artifact. - task: PublishPipelineArtifact@1 diff --git a/eng/pipelines/jobs/pack-logging-package-ci-job.yml b/eng/pipelines/jobs/pack-logging-package-ci-job.yml index f2a42699e0..f42b18cebe 100644 --- a/eng/pipelines/jobs/pack-logging-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-logging-package-ci-job.yml @@ -53,6 +53,11 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: pack_logging_package_job @@ -86,6 +91,19 @@ jobs: - name: Configuration value: '' + # Build properties passed to dotnet pack. + - name: baseBuildProperties + value: LoggingPackageVersion=${{ parameters.loggingPackageVersion }};LoggingAssemblyFileVersion=${{ parameters.loggingAssemblyFileVersion }} + + - name: signingProperties + ${{ if eq(parameters.isInternalBuild, true) }}: + value: SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ else }}: + value: '' + + - name: buildProperties + value: $(baseBuildProperties);$(signingProperties) + steps: # Emit environment variables if debug is enabled. @@ -98,6 +116,10 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. - task: DotNetCoreCLI@2 displayName: Create NuGet Package @@ -107,7 +129,7 @@ jobs: configurationToPack: ${{ parameters.buildConfiguration }} packDirectory: $(dotnetPackagesDir) verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: LoggingPackageVersion=${{ parameters.loggingPackageVersion }};LoggingAssemblyFileVersion=${{ parameters.loggingAssemblyFileVersion }} + buildProperties: $(buildProperties) # Publish the NuGet packages as a named pipeline artifact. - task: PublishPipelineArtifact@1 diff --git a/eng/pipelines/jobs/test-abstractions-package-ci-job.yml b/eng/pipelines/jobs/test-abstractions-package-ci-job.yml index 83366b52a9..d4deed9f65 100644 --- a/eng/pipelines/jobs/test-abstractions-package-ci-job.yml +++ b/eng/pipelines/jobs/test-abstractions-package-ci-job.yml @@ -61,6 +61,12 @@ parameters: - name: poolName type: string + # True when building on the internal ADO.Net project. When set, assemblies + # are signed with the driver key and tests are signed with the test key. + - name: isInternalBuild + type: boolean + default: false + # The pool VM image to use. - name: vmImage type: string @@ -94,6 +100,16 @@ jobs: -p:Configuration=${{ parameters.buildConfiguration }} --verbosity ${{ parameters.dotnetVerbosity }} + # Signing arguments — only set for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - name: signingArguments + value: >- + -p:SigningKeyPath=$(driverKeyFile.secureFilePath) + -p:TestSigningKeyPath=$(testKeyFile.secureFilePath) + - ${{ else }}: + - name: signingArguments + value: '' + # Explicitly unset the $PLATFORM environment variable that is set by the # 'ADO Build properties' Library in the ADO SqlClientDrivers public project. # This is defined with a non-standard Platform of 'AnyCPU', and will fail @@ -121,6 +137,13 @@ jobs: - pwsh: 'Get-ChildItem Env: | Sort-Object Name' displayName: '[Debug] Print Environment Variables' + # Download the assembly signing keys for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + # Install the .NET SDK and Runtimes. - template: /eng/pipelines/common/steps/install-dotnet.yml@self parameters: @@ -136,7 +159,7 @@ jobs: inputs: command: build projects: $(project) - arguments: $(buildArguments) + arguments: $(buildArguments) $(signingArguments) # Run the tests for each .NET runtime. - ${{ each runtime in parameters.netRuntimes }}: diff --git a/eng/pipelines/jobs/test-azure-package-ci-job.yml b/eng/pipelines/jobs/test-azure-package-ci-job.yml index eb9e36152a..457a3765c4 100644 --- a/eng/pipelines/jobs/test-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/test-azure-package-ci-job.yml @@ -69,6 +69,12 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. When set, assemblies + # are signed with the driver key and tests are signed with the test key. + - name: isInternalBuild + type: boolean + default: false + # The suffix to append to the job name. - name: jobNameSuffix type: string @@ -179,6 +185,16 @@ jobs: -p:SqlClientPackageVersion=${{ parameters.mdsPackageVersion }} -p:SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} + # Signing arguments — only set for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - name: signingArguments + value: >- + -p:SigningKeyPath=$(driverKeyFile.secureFilePath) + -p:TestSigningKeyPath=$(testKeyFile.secureFilePath) + - ${{ else }}: + - name: signingArguments + value: '' + # Explicitly unset the $PLATFORM environment variable that is set by the # 'ADO Build properties' Library in the ADO SqlClientDrivers public # project. This is defined with a non-standard Platform of 'AnyCPU', and @@ -206,6 +222,13 @@ jobs: - pwsh: 'Get-ChildItem Env: | Sort-Object Name' displayName: '[Debug] Print Environment Variables' + # Download the assembly signing keys for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + # We have a few extra steps for Package reference builds. - ${{ if eq(parameters.referenceType, 'Package') }}: @@ -289,7 +312,7 @@ jobs: inputs: command: build projects: $(project) - arguments: $(buildArguments) + arguments: $(buildArguments) $(signingArguments) # List the DLLs in the output directory for debugging purposes. - ${{ if eq(parameters.debug, true) }}: diff --git a/eng/pipelines/onebranch/steps/build-buildproj-step.yml b/eng/pipelines/onebranch/steps/build-buildproj-step.yml index 2a5730c848..4b18be369b 100644 --- a/eng/pipelines/onebranch/steps/build-buildproj-step.yml +++ b/eng/pipelines/onebranch/steps/build-buildproj-step.yml @@ -44,12 +44,8 @@ parameters: type: string steps: - # Download the strong name signing key from secure file storage - - task: DownloadSecureFile@1 - displayName: 'Download Signing Key' - inputs: - secureFile: 'netfxKeypair.snk' - name: keyFile + # Download the assembly signing key from secure file storage. + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self - task: DotNetCoreCLI@2 displayName: 'build.proj - Build${{ parameters.packageShortName }}' @@ -61,7 +57,7 @@ steps: -p:Configuration=${{ parameters.buildConfiguration }} -p:ReferenceType=Package -p:SkipDependencyPack=true - -p:SigningKeyPath="$(keyFile.secureFilePath)" + -p:SigningKeyPath="$(driverKeyFile.secureFilePath)" -p:BuildNumber="$(Build.BuildNumber)" -p:PackageVersion${{ parameters.packageShortName }}="${{ parameters.packageVersion }}" ${{ parameters.dependencyArguments }} diff --git a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml index 8579b79caf..f251d7d9c6 100644 --- a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml +++ b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml @@ -91,6 +91,11 @@ parameters: # Reference sibling packages as C# projects. - Project + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - stage: build_abstractions_package_stage @@ -112,6 +117,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Linux dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: linux netFrameworkRuntimes: [] netRuntimes: [net8.0, net9.0, net10.0] @@ -127,6 +133,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Win dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: windows netFrameworkRuntimes: [net462] netRuntimes: [net8.0, net9.0, net10.0] @@ -142,6 +149,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: macOS dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: macos netFrameworkRuntimes: [] netRuntimes: [net8.0, net9.0, net10.0] @@ -168,3 +176,4 @@ stages: loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} referenceType: ${{ parameters.referenceType }} + isInternalBuild: ${{ parameters.isInternalBuild }} diff --git a/eng/pipelines/stages/build-azure-package-ci-stage.yml b/eng/pipelines/stages/build-azure-package-ci-stage.yml index b3cf9073d5..396314125c 100644 --- a/eng/pipelines/stages/build-azure-package-ci-stage.yml +++ b/eng/pipelines/stages/build-azure-package-ci-stage.yml @@ -152,6 +152,11 @@ parameters: # Reference sibling packages as C# projects. - Project + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - stage: build_azure_package_stage @@ -180,6 +185,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Linux dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: linux loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -202,6 +208,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Linux Integration dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: linux_integration loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -233,6 +240,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Win dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: windows loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -255,6 +263,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Win Integration dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: windows_integration loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -295,6 +304,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: macOS dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: macos loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -331,6 +341,7 @@ stages: - test_azure_package_job_windows_integration - test_azure_package_job_macos dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} referenceType: ${{ parameters.referenceType }} diff --git a/eng/pipelines/stages/build-sqlclient-package-ci-stage.yml b/eng/pipelines/stages/build-sqlclient-package-ci-stage.yml index 858f1c8500..aa62f2122e 100644 --- a/eng/pipelines/stages/build-sqlclient-package-ci-stage.yml +++ b/eng/pipelines/stages/build-sqlclient-package-ci-stage.yml @@ -85,6 +85,11 @@ parameters: type: string default: '' + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - stage: build_sqlclient_package_stage @@ -109,6 +114,7 @@ stages: akvPackageVersion: ${{ parameters.akvPackageVersion }} sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + isInternalBuild: ${{ parameters.isInternalBuild }} ${{ if ne(parameters.SNIVersion, '') }}: prebuildSteps: - template: /eng/pipelines/common/templates/steps/override-sni-version.yml@self From 37d6dfa30023cc2ef2e850fc21e8f47e0db7557c Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 17 Jun 2026 13:03:15 -0300 Subject: [PATCH 02/12] src: add conditional signed IVT and TestSigningKeyPath to extension projects - Add STRONG_NAME_SIGNING conditional compilation to SqlAuthenticationProvider.Internal.cs - Add dual IVT blocks to Abstractions, Logging, and Azure source projects: unsigned (SigningKeyPath='') and signed+Package mode (with test public key) - Add TestSigningKeyPath signing support to Abstractions.Test, Azure.Test, and Logging.Test csproj files - Add SigningKeyPath, TestSigningKeyPath, and ReferenceType arguments to TestAbstractions, TestLogging, and TestAzure targets in build.proj --- build.proj | 46 +++++++++++-- .../Abstractions/src/Abstractions.csproj | 17 +++++ .../src/SqlAuthenticationProvider.Internal.cs | 67 ++++++++++++++++--- .../test/Abstractions.Test.csproj | 7 ++ .../Azure/src/Azure.csproj | 12 ++++ .../Azure/test/Azure.Test.csproj | 7 ++ .../Logging/src/Logging.csproj | 12 ++++ 7 files changed, 151 insertions(+), 17 deletions(-) diff --git a/build.proj b/build.proj index 4ff29a08df..ac08aeaaee 100644 --- a/build.proj +++ b/build.proj @@ -394,7 +394,7 @@ environments. Please consider running project specific test targets or specific test sets within the project. --> - + @@ -887,10 +887,6 @@ - AbstractionsTests-$(OS) $(LogFilePrefix)-$(TestFramework) @@ -901,6 +897,12 @@ $(TestCodeCoverageArgument) $(TestFiltersArgument) $(TestFrameworkArgument) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + + $(ReferenceTypeArgument) + $(PackageVersionLoggingArgument) --results-directory "$(TestResultsFolderPath)" --logger:"trx;LogFilePrefix=$(LogFilePrefix)" @@ -999,8 +1001,8 @@ $(TestCodeCoverageArgument) $(TestFiltersArgument) $(TestFrameworkArgument) - --results-directory "$(TestResultsFolderPath)" - --logger:"trx;LogFilePrefix=$(LogFilePrefix)" + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) $(ReferenceTypeArgument) @@ -1008,6 +1010,8 @@ $(PackageVersionLoggingArgument) $(PackageVersionSqlClientArgument) $(PackageVersionSqlServerArgument) + --results-directory "$(TestResultsFolderPath)" + --logger:"trx;LogFilePrefix=$(LogFilePrefix)" $([System.Text.RegularExpressions.Regex]::Replace($(DotnetCommand), "\s+", " ")) @@ -1022,6 +1026,7 @@ $(RepoRoot)src/Microsoft.Data.SqlClient.Internal/Logging/src/ $(LoggingSrcRoot)Logging.csproj + $(RepoRoot)src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj $(RepoRoot)artifacts/Microsoft.Data.SqlClient.Internal.Logging/$(Configuration)/ @@ -1079,6 +1084,33 @@ SkipUnchangedFiles="true" /> + + + + LoggingTests-$(OS) + $(LogFilePrefix)-$(TestFramework) + + + "$(DotnetPath)dotnet" test "$(LoggingTestProjectPath)" + -p:Configuration=$(Configuration) + $(TestBlameArgument) + $(TestCodeCoverageArgument) + $(TestFiltersArgument) + $(TestFrameworkArgument) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + $(ReferenceTypeArgument) + --results-directory "$(TestResultsFolderPath)" + --logger:"trx;LogFilePrefix=$(LogFilePrefix)" + + + $([System.Text.RegularExpressions.Regex]::Replace($(DotnetCommand), "\s+", " ")) + + + + + + diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj index 0a9d29aa1e..0957180637 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj @@ -34,10 +34,22 @@ + + + + + + + $(RepoRoot)artifacts/ @@ -79,6 +91,11 @@ Condition="'$(ReferenceType)' == 'Package'" /> + + + + + diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs index e0adf34e49..da56722718 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs @@ -23,6 +23,14 @@ public abstract partial class SqlAuthenticationProvider /// private static class Internal { + /// + /// The expected public key token of the SqlClient assembly, used to avoid loading imposter + /// assemblies. This is the same token used by all assemblies in this repository when + /// strong-name signed. + /// + private static readonly byte[] _sqlClientPublicKeyToken = + [ 0x23, 0xec, 0x7f, 0xc2, 0xd6, 0xea, 0xa4, 0xa5 ]; + /// /// Our handle to the reflected GetProvider() method. /// @@ -40,30 +48,69 @@ static Internal() { const string assemblyName = "Microsoft.Data.SqlClient"; - // If the MDS package is present, load its + // If the SqlClient assembly is present, load its // SqlAuthenticationProviderManager class and get/set methods. try { - // Try to load the MDS assembly. + // Try to load the SqlClient assembly. + + #if STRONG_NAME_SIGNING + + // When strong-name signing is enabled, build a fully-qualified AssemblyName that + // includes the expected public key token. + Log($"Attempting to load SqlClient assembly={assemblyName} with " + + "expected public key token=" + + BitConverter.ToString(_sqlClientPublicKeyToken).Replace("-", "")); + + var qualifiedName = new AssemblyName(assemblyName); + qualifiedName.SetPublicKeyToken(_sqlClientPublicKeyToken); + + // The .NET Framework runtime enforces the token during binding, causing Load() to + // throw if it doesn't match. The .NET (Core) runtime ignores the token, so we + // verify it ourselves below. + var assembly = Assembly.Load(qualifiedName); + + // Defense-in-depth: verify the public key token after loading. This is necessary + // on .NET Core where the runtime does not enforce the token. It is harmless on .NET + // Framework. + if (assembly is not null) + { + byte[]? actualToken = assembly.GetName().GetPublicKeyToken(); + + if (actualToken is null || + !actualToken.AsSpan().SequenceEqual(_sqlClientPublicKeyToken)) + { + Log($"SqlClient assembly={assembly.GetName()} has an " + + "unexpected public key token; " + + "Get/SetProvider() will not function"); + return; + } + } + + #else + + // Strong-name signing is disabled, so we cannot verify the public key token. + Log($"Loading SqlClient assembly={assemblyName} without strong name " + + "verification; ensure this assembly is from a trusted source"); + var assembly = Assembly.Load(assemblyName); + #endif + if (assembly is null) { - Log($"MDS assembly={assemblyName} not found; " + + Log($"SqlClient assembly={assemblyName} not found; " + "Get/SetProvider() will not function"); return; } - // TODO(https://sqlclientdrivers.visualstudio.com/ADO.Net/_workitems/edit/39845): - // Verify the assembly is signed by us? - // Look for the manager class. const string className = "Microsoft.Data.SqlClient.SqlAuthenticationProviderManager"; var manager = assembly.GetType(className); if (manager is null) { - Log($"MDS auth manager manager class={className} not found; " + + Log($"SqlClient auth manager class={className} not found; " + "Get/SetProvider() will not function"); return; } @@ -75,7 +122,7 @@ static Internal() if (_getProvider is null) { - Log($"MDS GetProvider() method not found; " + + Log($"SqlClient GetProvider() method not found; " + "GetProvider() will not function"); } @@ -85,7 +132,7 @@ static Internal() if (_setProvider is null) { - Log($"MDS SetProvider() method not found; " + + Log($"SqlClient SetProvider() method not found; " + "SetProvider() will not function"); } } @@ -97,7 +144,7 @@ or BadImageFormatException or FileLoadException or FileNotFoundException) { - Log($"MDS assembly={assemblyName} not found or not usable; " + + Log($"SqlClient assembly={assemblyName} not found or not usable; " + $"Get/SetProvider() will not function: {ex} "); } // Any other exceptions are fatal. diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj index 427a7aaf9f..0fe52f0327 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj @@ -8,6 +8,13 @@ true + + + + true + $(TestSigningKeyPath) + + enable diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj index dddf5673f9..796fc2767a 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj @@ -34,10 +34,22 @@ + + + + + + + $(RepoRoot)artifacts/ diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj index 1c020c2ae4..f34f247ea1 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj @@ -8,6 +8,13 @@ true + + + + true + $(TestSigningKeyPath) + + net8.0;net9.0;net10.0 diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj index d1c3e0fc5c..71d267f211 100644 --- a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj @@ -36,10 +36,22 @@ + + + + + + + $(RepoRoot)artifacts/ From 28efdb5133c10dd46c96600ee569f426c8e3f90d Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 17 Jun 2026 13:03:36 -0300 Subject: [PATCH 03/12] test: add Logging.Test project and CI pipeline coverage - Create Logging.Test.csproj targeting net462/net8.0/net9.0/net10.0 - Add SqlClientEventSourceTest verifying the singleton instance - Create test-logging-package-ci-job.yml template with signing support - Add Linux/Windows/macOS test jobs to build-logging-package-ci-stage - Add project to solution file --- .../jobs/test-logging-package-ci-job.yml | 210 ++++++++++++++++++ .../stages/build-logging-package-ci-stage.yml | 59 ++++- .../Logging/test/Directory.Packages.props | 10 + .../Logging/test/Logging.Test.csproj | 51 +++++ .../Logging/test/SqlClientEventSourceTest.cs | 14 ++ src/Microsoft.Data.SqlClient.slnx | 1 + 6 files changed, 341 insertions(+), 4 deletions(-) create mode 100644 eng/pipelines/jobs/test-logging-package-ci-job.yml create mode 100644 src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props create mode 100644 src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj create mode 100644 src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs diff --git a/eng/pipelines/jobs/test-logging-package-ci-job.yml b/eng/pipelines/jobs/test-logging-package-ci-job.yml new file mode 100644 index 0000000000..3678b99edf --- /dev/null +++ b/eng/pipelines/jobs/test-logging-package-ci-job.yml @@ -0,0 +1,210 @@ +################################################################################ +# Licensed to the .NET Foundation under one or more agreements. The .NET +# Foundation licenses this file to you under the MIT license. See the LICENSE +# file in the project root for more information. +################################################################################ + +# This job builds the Logging package and runs its tests for a set of .NET +# runtimes. +# +# This template defines a job named +# 'test_logging_package_job_' that can be depended on by +# downstream jobs. + +parameters: + + # The type of build to test (Release or Debug) + - name: buildConfiguration + type: string + values: + - Release + - Debug + + # True to emit debug information and steps. + - name: debug + type: boolean + default: false + + # The prefix to prepend to the job's display name: + # + # [] Test Logging Package + # + - name: displayNamePrefix + type: string + + # The verbosity level for the dotnet CLI commands. + - name: dotnetVerbosity + type: string + default: normal + values: + - quiet + - minimal + - normal + - detailed + - diagnostic + + # True when building on the internal ADO.Net project. When set, assemblies + # are signed with the driver key and tests are signed with the test key. + - name: isInternalBuild + type: boolean + default: false + + # The suffix to append to the job name. + - name: jobNameSuffix + type: string + + # The list of .NET Framework runtimes to test against. + - name: netFrameworkRuntimes + type: object + default: [] + + # The list of .NET runtimes to test against. + - name: netRuntimes + type: object + default: [] + + # The name of the Azure Pipelines pool to use. + - name: poolName + type: string + + # The pool VM image to use. + - name: vmImage + type: string + +jobs: + + - job: test_logging_package_job_${{ parameters.jobNameSuffix }} + displayName: '[${{ parameters.displayNamePrefix }}] Test Logging Package' + pool: + name: ${{ parameters.poolName }} + + # Images provided by Azure Pipelines must be selected using 'vmImage'. + ${{ if eq(parameters.poolName, 'Azure Pipelines') }}: + vmImage: ${{ parameters.vmImage }} + # Images provided by 1ES must be selected using a demand. + ${{ else }}: + demands: + - imageOverride -equals ${{ parameters.vmImage }} + + variables: + + # The Logging test project file to use for all dotnet CLI commands. + # + # Building this project implicitly builds the Logging project. + - name: project + value: src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj + + # dotnet CLI arguments for build/test/pack commands + - name: buildArguments + value: >- + -p:Configuration=${{ parameters.buildConfiguration }} + --verbosity ${{ parameters.dotnetVerbosity }} + + # Signing arguments — only set for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - name: signingArguments + value: >- + -p:SigningKeyPath=$(driverKeyFile.secureFilePath) + -p:TestSigningKeyPath=$(testKeyFile.secureFilePath) + - ${{ else }}: + - name: signingArguments + value: '' + + # Explicitly unset the $PLATFORM environment variable that is set by the + # 'ADO Build properties' Library in the ADO SqlClientDrivers public project. + # This is defined with a non-standard Platform of 'AnyCPU', and will fail + # the builds if left defined. + # + # Note that Azure Pipelines will inject this variable as PLATFORM into the + # environment of all tasks in this job. + # + # See: + # https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch + # + - name: Platform + value: '' + + # Do the same for $CONFIGURATION since we explicitly set it using our + # 'buildConfiguration' parameter, and we don't want the environment to + # override us. + - name: Configuration + value: '' + + steps: + + # Emit environment variables if debug is enabled. + - ${{ if eq(parameters.debug, true) }}: + - pwsh: 'Get-ChildItem Env: | Sort-Object Name' + displayName: '[Debug] Print Environment Variables' + + # Download the assembly signing keys for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + + # Install the .NET SDK and Runtimes. + - template: /eng/pipelines/common/steps/install-dotnet.yml@self + parameters: + debug: ${{ parameters.debug }} + runtimes: [8.x, 9.x] + + # The Windows agent images include a suitable .NET Framework runtime, so + # we don't have to install one explicitly. + + # Build the project. + - task: DotNetCoreCLI@2 + displayName: Build Project + inputs: + command: build + projects: $(project) + arguments: $(buildArguments) $(signingArguments) + + # Run the tests for each .NET runtime. + - ${{ each runtime in parameters.netRuntimes }}: + - task: DotNetCoreCLI@2 + displayName: Test [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(buildArguments) + --no-build + -f ${{ runtime }} + --filter "category != failing & category != flaky & category != interactive" + + - task: DotNetCoreCLI@2 + displayName: Test Flaky [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(buildArguments) + --no-build + -f ${{ runtime }} + --filter "category = flaky" + + # Run the tests for each .NET Framework runtime. + - ${{ each runtime in parameters.netFrameworkRuntimes }}: + - task: DotNetCoreCLI@2 + displayName: Test [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(buildArguments) + --no-build + -f ${{ runtime }} + --filter "category != failing & category != flaky & category != interactive" + + - task: DotNetCoreCLI@2 + displayName: Test Flaky [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(buildArguments) + --no-build + -f ${{ runtime }} + --filter "category = flaky" diff --git a/eng/pipelines/stages/build-logging-package-ci-stage.yml b/eng/pipelines/stages/build-logging-package-ci-stage.yml index 6b5f22feeb..d25954d35e 100644 --- a/eng/pipelines/stages/build-logging-package-ci-stage.yml +++ b/eng/pipelines/stages/build-logging-package-ci-stage.yml @@ -67,6 +67,11 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - stage: build_logging_package_stage @@ -79,11 +84,56 @@ stages: jobs: + # ------------------------------------------------------------------------ + # Build and test on Linux. + + - template: /eng/pipelines/jobs/test-logging-package-ci-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + displayNamePrefix: Linux + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + jobNameSuffix: linux + netFrameworkRuntimes: [] + netRuntimes: [net8.0, net9.0, net10.0] + poolName: Azure Pipelines + vmImage: ubuntu-latest + + # ------------------------------------------------------------------------ + # Build and test on Windows. + + - template: /eng/pipelines/jobs/test-logging-package-ci-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + displayNamePrefix: Win + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + jobNameSuffix: windows + netFrameworkRuntimes: [net462] + netRuntimes: [net8.0, net9.0, net10.0] + poolName: Azure Pipelines + vmImage: windows-latest + + # ------------------------------------------------------------------------ + # Build and test on macOS. + + - template: /eng/pipelines/jobs/test-logging-package-ci-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + displayNamePrefix: macOS + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + jobNameSuffix: macos + netFrameworkRuntimes: [] + netRuntimes: [net8.0, net9.0, net10.0] + poolName: Azure Pipelines + vmImage: macos-latest + + # ------------------------------------------------------------------------ # Create and publish the NuGet package. - # Note: No test jobs because the Logging project does not have a test - # project yet. When a test project is added, test jobs should be added - # here (mirroring the Abstractions stage pattern) and the pack job should - # depend on them. - template: /eng/pipelines/jobs/pack-logging-package-ci-job.yml@self parameters: @@ -93,3 +143,4 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props new file mode 100644 index 0000000000..f3593ec1ba --- /dev/null +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props @@ -0,0 +1,10 @@ + + + + diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj new file mode 100644 index 0000000000..58f6feae31 --- /dev/null +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj @@ -0,0 +1,51 @@ + + + + Microsoft.Data.SqlClient.Internal.Logging.Test + net462;net8.0;net9.0;net10.0 + + false + true + + + + + + true + $(TestSigningKeyPath) + + + + + enable + enable + + + + + + + + + + + PreserveNewest + xunit.runner.json + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs b/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs new file mode 100644 index 0000000000..ea3e4fabed --- /dev/null +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Data.SqlClient.Internal.Logging.Test; + +public class SqlClientEventSourceTest +{ + [Fact] + public void SqlClientEventSource_Log_IsNotNull() + { + Assert.NotNull(SqlClientEventSource.Log); + } +} diff --git a/src/Microsoft.Data.SqlClient.slnx b/src/Microsoft.Data.SqlClient.slnx index a578a82db6..d6a615e39f 100644 --- a/src/Microsoft.Data.SqlClient.slnx +++ b/src/Microsoft.Data.SqlClient.slnx @@ -146,6 +146,7 @@ + From 788979795bbc14f78abee258c41a691edcefa048 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 17 Jun 2026 13:46:34 -0300 Subject: [PATCH 04/12] Renamed STRONG_NAME_SIGNING to ASSEMBLY_SIGNING, and all similar terminology. --- build.proj | 6 +++--- eng/pipelines/ci/package/sqlclient-package.yml | 2 +- .../onebranch/jobs/validate-signed-package-job.yml | 4 ++-- .../onebranch/steps/build-buildproj-step.yml | 2 +- src/Directory.Build.props | 6 +++--- ...nt.AlwaysEncrypted.AzureKeyVaultProvider.csproj | 2 +- .../Abstractions/src/Abstractions.csproj | 2 +- .../src/SqlAuthenticationProvider.Internal.cs | 14 +++++++------- .../Abstractions/test/Abstractions.Test.csproj | 2 +- .../Azure/src/Azure.csproj | 2 +- .../Azure/test/Azure.Test.csproj | 2 +- .../Logging/src/Logging.csproj | 2 +- .../Logging/test/Logging.Test.csproj | 2 +- .../notsupported/Microsoft.Data.SqlClient.csproj | 2 +- .../ref/Microsoft.Data.SqlClient.csproj | 2 +- .../src/Microsoft.Data.SqlClient.csproj | 2 +- .../SqlClient/SqlAuthenticationProviderManager.cs | 6 +++--- .../Microsoft.Data.SqlClient.TestCommon.csproj | 2 +- .../tests/FunctionalTests/SqlDataRecordTest.cs | 2 +- .../ManualTests/SQL/UdtTest/SqlServerTypesTest.cs | 8 ++++---- .../Microsoft.Data.SqlClient.UnitTests.csproj | 2 +- .../Microsoft.Data.SqlClient.TestUtilities.csproj | 2 +- .../Microsoft.SqlServer.Server.csproj | 2 +- 23 files changed, 39 insertions(+), 39 deletions(-) diff --git a/build.proj b/build.proj index ac08aeaaee..5bdfb44e2e 100644 --- a/build.proj +++ b/build.proj @@ -247,8 +247,8 @@ $(TestFilters)&category!=signed diff --git a/eng/pipelines/ci/package/sqlclient-package.yml b/eng/pipelines/ci/package/sqlclient-package.yml index 72c65b364e..244993c23d 100644 --- a/eng/pipelines/ci/package/sqlclient-package.yml +++ b/eng/pipelines/ci/package/sqlclient-package.yml @@ -11,7 +11,7 @@ # - On pushes to GitHub main and ADO internal/main (batched) # - Nightly at 00:00 UTC on both branches # -# On internal/main the strong-name signing key is downloaded and used to sign assemblies during the +# On internal/main the assembly signing key is downloaded and used to sign assemblies during the # build. # # GOTCHA: This pipeline definition is triggered by GitHub _and_ ADO CI. We distinguish the two via diff --git a/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml b/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml index afa5aa5918..03f511af9b 100644 --- a/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml +++ b/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml @@ -157,8 +157,8 @@ jobs: $nugetPackageInstallPath = "${{ variables.nugetPackageInstallPath }}" echo "nugetPackageInstallPath= $nugetPackageInstallPath" - # Verify strong name signing ##################################### - echo "> 1. Verifying strong name signing of DLLs ..." + # Verify assembly signing ##################################### + echo "> 1. Verifying assembly signing of DLLs ..." # @TODO: This path seems brittle to VS upgrades, can we make it more flexible? $snPath = "C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\NETFX 4.8.1 Tools\sn.exe" diff --git a/eng/pipelines/onebranch/steps/build-buildproj-step.yml b/eng/pipelines/onebranch/steps/build-buildproj-step.yml index 4b18be369b..dcb66f6f15 100644 --- a/eng/pipelines/onebranch/steps/build-buildproj-step.yml +++ b/eng/pipelines/onebranch/steps/build-buildproj-step.yml @@ -7,7 +7,7 @@ # This collection of steps to build a project via the build.proj. This will execute the "Build*" # target in build.proj, where * is the packageShortName provided in the parameters. # -# Note: This differs from the pr/ci build-buildproj-step.yml in that it always strong-name signs +# Note: This differs from the pr/ci build-buildproj-step.yml in that it always signs # the assemblies, it only builds in package reference mode, and as such allows for version # parameters to be provided. diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b3e0663fd3..7982e8f785 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -106,15 +106,15 @@ low - + - + true $(SigningKeyPath) - $(DefineConstants);STRONG_NAME_SIGNING + $(DefineConstants);ASSEMBLY_SIGNING diff --git a/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj b/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj index 203aabd1f5..9604565837 100644 --- a/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj +++ b/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj @@ -22,7 +22,7 @@ $(AkvProviderPackageVersion) - + diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj index 0957180637..9eac7f6ecf 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj @@ -32,7 +32,7 @@ $(AbstractionsPackageVersion) - + diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs index da56722718..7a801e607a 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs @@ -25,8 +25,8 @@ private static class Internal { /// /// The expected public key token of the SqlClient assembly, used to avoid loading imposter - /// assemblies. This is the same token used by all assemblies in this repository when - /// strong-name signed. + /// assemblies. This is the public key token of the assembly signing key used for all of + /// our driver assemblies. /// private static readonly byte[] _sqlClientPublicKeyToken = [ 0x23, 0xec, 0x7f, 0xc2, 0xd6, 0xea, 0xa4, 0xa5 ]; @@ -54,9 +54,9 @@ static Internal() { // Try to load the SqlClient assembly. - #if STRONG_NAME_SIGNING + #if ASSEMBLY_SIGNING - // When strong-name signing is enabled, build a fully-qualified AssemblyName that + // When assembly signing is enabled, build a fully-qualified AssemblyName that // includes the expected public key token. Log($"Attempting to load SqlClient assembly={assemblyName} with " + "expected public key token=" + @@ -89,9 +89,9 @@ static Internal() #else - // Strong-name signing is disabled, so we cannot verify the public key token. - Log($"Loading SqlClient assembly={assemblyName} without strong name " + - "verification; ensure this assembly is from a trusted source"); + // Assembly signing is disabled, so we cannot verify the public key token. + Log($"Loading SqlClient assembly={assemblyName} without assembly verification; " + + "ensure this assembly is from a trusted source"); var assembly = Assembly.Load(assemblyName); diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj index 0fe52f0327..24b8905322 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj @@ -8,7 +8,7 @@ true - + true diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj index 796fc2767a..02d3733ffb 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj @@ -32,7 +32,7 @@ $(AzurePackageVersion) - + diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj index f34f247ea1..818a223f21 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj @@ -8,7 +8,7 @@ true - + true diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj index 71d267f211..bc7502d517 100644 --- a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj @@ -34,7 +34,7 @@ $(LoggingPackageVersion) - + diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj index 58f6feae31..2993bcd22c 100644 --- a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj @@ -8,7 +8,7 @@ true - + true diff --git a/src/Microsoft.Data.SqlClient/notsupported/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/notsupported/Microsoft.Data.SqlClient.csproj index a9474613e6..d1c65d6add 100644 --- a/src/Microsoft.Data.SqlClient/notsupported/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/notsupported/Microsoft.Data.SqlClient.csproj @@ -83,7 +83,7 @@ $(SqlClientPackageVersion) - + diff --git a/src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csproj index 43aca3f1c1..7976d967fb 100644 --- a/src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csproj @@ -28,7 +28,7 @@ - + diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj index 06eaf9e914..71e9c80215 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj @@ -60,7 +60,7 @@ $(SqlClientPackageVersion) - + diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs index 653063b68e..a3851e096f 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs @@ -61,9 +61,9 @@ static SqlAuthenticationProviderManager() try { // Try to load our Azure extension. - #if STRONG_NAME_SIGNING + #if ASSEMBLY_SIGNING - // When strong-name signing is enabled, build a fully-qualified AssemblyName + // When assembly signing is enabled, build a fully-qualified AssemblyName // that includes the expected public key token. SqlClientEventSource.Log.TryTraceEvent( @@ -109,7 +109,7 @@ static SqlAuthenticationProviderManager() SqlClientEventSource.Log.TryTraceEvent( nameof(SqlAuthenticationProviderManager) + $": Attempting to load Azure extension assembly={azureAssemblyName} without " + - "strong name verification; ensure this assembly is from a trusted source"); + "assembly verification; ensure this assembly is from a trusted source"); var assembly = Assembly.Load(azureAssemblyName); diff --git a/src/Microsoft.Data.SqlClient/tests/Common/Microsoft.Data.SqlClient.TestCommon.csproj b/src/Microsoft.Data.SqlClient/tests/Common/Microsoft.Data.SqlClient.TestCommon.csproj index 67c5250748..aac951b190 100644 --- a/src/Microsoft.Data.SqlClient/tests/Common/Microsoft.Data.SqlClient.TestCommon.csproj +++ b/src/Microsoft.Data.SqlClient/tests/Common/Microsoft.Data.SqlClient.TestCommon.csproj @@ -14,7 +14,7 @@ false - + true diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs index b051f2cc26..6c31e23bd3 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs @@ -334,7 +334,7 @@ public void GetChar_ThrowsNotSupported() [Theory] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif [MemberData( nameof(GetUdtTypeTestData.Get), diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs index 712d1ec2c6..911f2fbc58 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs @@ -37,7 +37,7 @@ public static class SqlServerTypesTest // Synapse: Parse error at line: 1, column: 48: Incorrect syntax near 'hierarchyid'. [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif public static void GetSchemaTableTest() { @@ -66,7 +66,7 @@ public static void GetSchemaTableTest() // Synapse: Parse error at line: 1, column: 48: Incorrect syntax near 'hierarchyid'. [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif public static void GetValueTest() { @@ -227,7 +227,7 @@ void ActAndAssert(int index, string expectedHexString) // Synapse: Parse error at line: 1, column: 41: Incorrect syntax near 'hierarchyid'. [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif public static void TestUdtSchemaMetadata() { @@ -384,7 +384,7 @@ private static string GetUdtName(Type udtClrType) // Synapse: Parse error at line: 1, column: 8: Incorrect syntax near 'geometry'. [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif public static void TestSqlServerTypesInsertAndRead() { diff --git a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj index e09e49c967..cd95155822 100644 --- a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj @@ -36,7 +36,7 @@ - + true diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj index 05444fd022..3d4f6c41d7 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj @@ -3,7 +3,7 @@ netstandard2.0 - + true diff --git a/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj b/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj index a995fa13b9..6769c42328 100644 --- a/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj +++ b/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj @@ -16,7 +16,7 @@ $(SqlServerPackageVersion) - + From 659d1eca4976bc825d4d3d380d7356997864774f Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:01:25 -0300 Subject: [PATCH 05/12] fix: address PR #4369 review feedback - Logging.Test.csproj: make net462 TFM conditional on Windows (matches Azure.Test.csproj pattern) - Rename buildArguments variable to dotnetBuildOpts in all three test job pipelines to avoid implicit .NET CLI argument injection via BUILDARGUMENTS environment variable - Add SqlClientEventSource_Log_IsSingleton test asserting singleton identity --- .../jobs/test-abstractions-package-ci-job.yml | 12 ++++++------ eng/pipelines/jobs/test-azure-package-ci-job.yml | 12 ++++++------ eng/pipelines/jobs/test-logging-package-ci-job.yml | 12 ++++++------ .../Logging/test/Logging.Test.csproj | 8 +++++++- .../Logging/test/SqlClientEventSourceTest.cs | 6 ++++++ 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/eng/pipelines/jobs/test-abstractions-package-ci-job.yml b/eng/pipelines/jobs/test-abstractions-package-ci-job.yml index d4deed9f65..880ea1d7f4 100644 --- a/eng/pipelines/jobs/test-abstractions-package-ci-job.yml +++ b/eng/pipelines/jobs/test-abstractions-package-ci-job.yml @@ -95,7 +95,7 @@ jobs: value: src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj # dotnet CLI arguments for build/test/pack commands - - name: buildArguments + - name: dotnetBuildOpts value: >- -p:Configuration=${{ parameters.buildConfiguration }} --verbosity ${{ parameters.dotnetVerbosity }} @@ -159,7 +159,7 @@ jobs: inputs: command: build projects: $(project) - arguments: $(buildArguments) $(signingArguments) + arguments: $(dotnetBuildOpts) $(signingArguments) # Run the tests for each .NET runtime. - ${{ each runtime in parameters.netRuntimes }}: @@ -169,7 +169,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -180,7 +180,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" @@ -193,7 +193,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -204,7 +204,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" diff --git a/eng/pipelines/jobs/test-azure-package-ci-job.yml b/eng/pipelines/jobs/test-azure-package-ci-job.yml index 457a3765c4..f1983eab91 100644 --- a/eng/pipelines/jobs/test-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/test-azure-package-ci-job.yml @@ -175,7 +175,7 @@ jobs: value: src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj # dotnet CLI arguments for build/test/pack commands. - - name: buildArguments + - name: dotnetBuildOpts value: >- -p:Configuration=${{ parameters.buildConfiguration }} --verbosity ${{ parameters.dotnetVerbosity }} @@ -312,7 +312,7 @@ jobs: inputs: command: build projects: $(project) - arguments: $(buildArguments) $(signingArguments) + arguments: $(dotnetBuildOpts) $(signingArguments) # List the DLLs in the output directory for debugging purposes. - ${{ if eq(parameters.debug, true) }}: @@ -347,7 +347,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -365,7 +365,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" @@ -385,7 +385,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -403,7 +403,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" diff --git a/eng/pipelines/jobs/test-logging-package-ci-job.yml b/eng/pipelines/jobs/test-logging-package-ci-job.yml index 3678b99edf..6e035e33d6 100644 --- a/eng/pipelines/jobs/test-logging-package-ci-job.yml +++ b/eng/pipelines/jobs/test-logging-package-ci-job.yml @@ -95,7 +95,7 @@ jobs: value: src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj # dotnet CLI arguments for build/test/pack commands - - name: buildArguments + - name: dotnetBuildOpts value: >- -p:Configuration=${{ parameters.buildConfiguration }} --verbosity ${{ parameters.dotnetVerbosity }} @@ -159,7 +159,7 @@ jobs: inputs: command: build projects: $(project) - arguments: $(buildArguments) $(signingArguments) + arguments: $(dotnetBuildOpts) $(signingArguments) # Run the tests for each .NET runtime. - ${{ each runtime in parameters.netRuntimes }}: @@ -169,7 +169,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -180,7 +180,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" @@ -193,7 +193,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -204,7 +204,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj index 2993bcd22c..be3ca85785 100644 --- a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj @@ -2,7 +2,13 @@ Microsoft.Data.SqlClient.Internal.Logging.Test - net462;net8.0;net9.0;net10.0 + net8.0;net9.0;net10.0 + + + $(TargetFrameworks);net462 false true diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs b/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs index ea3e4fabed..d46896672f 100644 --- a/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs @@ -11,4 +11,10 @@ public void SqlClientEventSource_Log_IsNotNull() { Assert.NotNull(SqlClientEventSource.Log); } + + [Fact] + public void SqlClientEventSource_Log_IsSingleton() + { + Assert.Same(SqlClientEventSource.Log, SqlClientEventSource.Log); + } } From 60edf88bdb39cd0ead18d3e3205ece6c8f676b58 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:36:25 -0300 Subject: [PATCH 06/12] fix: use compile-time branches for pack buildProperties to avoid MSB1005 When optional variables (packageModeProperties, signingProperties) are empty, concatenating them with hardcoded semicolons produces trailing ';;' that MSBuild rejects with MSB1005. Replace runtime concatenation with compile-time ${{ if }} branches so only non-empty segments appear. --- .../jobs/pack-abstractions-package-ci-job.yml | 25 +++++++++---------- .../jobs/pack-azure-package-ci-job.yml | 25 +++++++++---------- .../jobs/pack-logging-package-ci-job.yml | 13 +++++----- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml index b75900f1bc..7f7506c431 100644 --- a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml @@ -129,20 +129,19 @@ jobs: - name: baseBuildProperties value: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }} - - name: packageModeProperties - ${{ if eq(parameters.referenceType, 'Package') }}: - value: ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }} - ${{ else }}: - value: '' - - - name: signingProperties - ${{ if eq(parameters.isInternalBuild, true) }}: - value: SigningKeyPath=$(driverKeyFile.secureFilePath) - ${{ else }}: - value: '' - + # NOTE: We use compile-time ${{ if }} branches rather than concatenating + # separate variables (e.g. "$(base);$(optional);$(signing)") because + # when the optional variables are empty the semicolons remain, producing + # a trailing ";;" that MSBuild rejects with MSB1005. - name: buildProperties - value: $(baseBuildProperties);$(packageModeProperties);$(signingProperties) + ${{ if and(eq(parameters.referenceType, 'Package'), eq(parameters.isInternalBuild, true)) }}: + value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ elseif eq(parameters.referenceType, 'Package') }}: + value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }} + ${{ elseif eq(parameters.isInternalBuild, true) }}: + value: $(baseBuildProperties);SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ else }}: + value: $(baseBuildProperties) steps: diff --git a/eng/pipelines/jobs/pack-azure-package-ci-job.yml b/eng/pipelines/jobs/pack-azure-package-ci-job.yml index 81def77c44..d26a0f4e33 100644 --- a/eng/pipelines/jobs/pack-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-azure-package-ci-job.yml @@ -141,20 +141,19 @@ jobs: - name: baseBuildProperties value: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }} - - name: packageModeProperties - ${{ if eq(parameters.referenceType, 'Package') }}: - value: ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }} - ${{ else }}: - value: '' - - - name: signingProperties - ${{ if eq(parameters.isInternalBuild, true) }}: - value: SigningKeyPath=$(driverKeyFile.secureFilePath) - ${{ else }}: - value: '' - + # NOTE: We use compile-time ${{ if }} branches rather than concatenating + # separate variables (e.g. "$(base);$(optional);$(signing)") because + # when the optional variables are empty the semicolons remain, producing + # a trailing ";;" that MSBuild rejects with MSB1005. - name: buildProperties - value: $(baseBuildProperties);$(packageModeProperties);$(signingProperties) + ${{ if and(eq(parameters.referenceType, 'Package'), eq(parameters.isInternalBuild, true)) }}: + value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ elseif eq(parameters.referenceType, 'Package') }}: + value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }} + ${{ elseif eq(parameters.isInternalBuild, true) }}: + value: $(baseBuildProperties);SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ else }}: + value: $(baseBuildProperties) steps: diff --git a/eng/pipelines/jobs/pack-logging-package-ci-job.yml b/eng/pipelines/jobs/pack-logging-package-ci-job.yml index f42b18cebe..3598ce009d 100644 --- a/eng/pipelines/jobs/pack-logging-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-logging-package-ci-job.yml @@ -95,14 +95,15 @@ jobs: - name: baseBuildProperties value: LoggingPackageVersion=${{ parameters.loggingPackageVersion }};LoggingAssemblyFileVersion=${{ parameters.loggingAssemblyFileVersion }} - - name: signingProperties + # NOTE: We use compile-time ${{ if }} branches rather than concatenating + # separate variables (e.g. "$(base);$(signing)") because when the + # optional variable is empty the semicolons remain, producing a trailing + # ";;" that MSBuild rejects with MSB1005. + - name: buildProperties ${{ if eq(parameters.isInternalBuild, true) }}: - value: SigningKeyPath=$(driverKeyFile.secureFilePath) + value: $(baseBuildProperties);SigningKeyPath=$(driverKeyFile.secureFilePath) ${{ else }}: - value: '' - - - name: buildProperties - value: $(baseBuildProperties);$(signingProperties) + value: $(baseBuildProperties) steps: From a49e8461b6358f9b0af2a9eda62bda12e966be95 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 18 Jun 2026 10:42:38 -0300 Subject: [PATCH 07/12] Pass SigningKeyPathArgument to test targets and normalize DotnetCommand sections Add to TestSqlClientFunctional, TestSqlClientManual, and TestSqlClientUnit targets so the driver is strong-name signed when rebuilt during dotnet test on net462. Normalize all 20 DotnetCommand blocks to follow the BuildSqlClientNotSupported pattern: blank line after command+project, consistent section headers (Build arguments, Versioning arguments, Test arguments, Reference Type Arguments, Pack arguments), and SigningKeyPathArgument in the Build section. --- build.proj | 107 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 23 deletions(-) diff --git a/build.proj b/build.proj index 5bdfb44e2e..91c8729f23 100644 --- a/build.proj +++ b/build.proj @@ -452,6 +452,8 @@ "$(DotnetPath)dotnet" build "$(SqlClientNotSupportedProjectPath)" + + -p:Configuration=$(Configuration) -p:GenApiPath="@(GenApiArtifactPath->'%(FullPath)')" $(SigningKeyPathArgument) @@ -483,6 +485,8 @@ "$(DotnetPath)dotnet" build $(SqlClientRefProjectPath) + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) @@ -491,7 +495,7 @@ $(BuildSuffixArgument) $(PackageVersionSqlClientArgument) - + $(ReferenceTypeArgument) $(PackageVersionAbstractionsArgument) $(PackageVersionSqlServerArgument) @@ -512,6 +516,8 @@ "$(DotnetPath)dotnet" build $(SqlClientProjectPath) + + -p:Configuration=$(Configuration) -p:TargetOs=Unix $(SigningKeyPathArgument) @@ -543,11 +549,13 @@ "$(DotnetPath)dotnet" build $(SqlClientProjectPath) + + -p:Configuration=$(Configuration) -p:TargetOs=Windows_NT $(SigningKeyPathArgument) - + $(BuildNumberArgument) $(BuildSuffixArgument) $(PackageVersionSqlClientArgument) @@ -586,6 +594,8 @@ "$(DotnetPath)dotnet" pack "$(SqlClientProjectPath)" + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -601,7 +611,7 @@ $(PackageVersionLoggingArgument) $(PackageVersionSqlServerArgument) - + -p:PackageOutputPath="$(SqlClientPackageArtifactRoot)" @@ -635,7 +645,12 @@ "$(DotnetPath)dotnet" test "$(SqlClientFunctionalTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) @@ -680,7 +695,12 @@ "$(DotnetPath)dotnet" test "$(SqlClientManualTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(ManualTestFiltersArgument) @@ -710,17 +730,24 @@ "$(DotnetPath)dotnet" test "$(SqlClientUnitTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) $(TestFrameworkArgument) + --results-directory "$(TestResultsFolderPath)" + --logger:"trx;LogFilePrefix=$(LogFilePrefix)" + + $(ReferenceTypeArgument) - $(TestSigningKeyPathArgument) $(PackageVersionSqlClientArgument) $(PackageVersionSqlServerArgument) - --results-directory "$(TestResultsFolderPath)" - --logger:"trx;LogFilePrefix=$(LogFilePrefix)" @@ -746,15 +773,17 @@ "$(DotnetPath)dotnet" build "$(AkvProviderProjectPath)" + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) - + $(BuildNumberArgument) $(BuildSuffixArgument) $(PackageVersionAkvProviderArgument) - + $(ReferenceTypeArgument) $(PackageVersionAbstractionsArgument) $(PackageVersionLoggingArgument) @@ -774,6 +803,8 @@ "$(DotnetPath)dotnet" pack "$(AkvProviderProjectPath)" + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -827,6 +858,8 @@ "$(DotnetPath)dotnet" build "$(AbstractionsProjectPath)" + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) @@ -852,6 +885,8 @@ "$(DotnetPath)dotnet" pack "$(AbstractionsProjectPath)" + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -892,19 +927,23 @@ "$(DotnetPath)dotnet" test "$(AbstractionsTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) $(TestFrameworkArgument) - $(SigningKeyPathArgument) - $(TestSigningKeyPathArgument) + --results-directory "$(TestResultsFolderPath)" + --logger:"trx;LogFilePrefix=$(LogFilePrefix)" - + $(ReferenceTypeArgument) $(PackageVersionLoggingArgument) - --results-directory "$(TestResultsFolderPath)" - --logger:"trx;LogFilePrefix=$(LogFilePrefix)" $([System.Text.RegularExpressions.Regex]::Replace($(DotnetCommand), "\s+", " ")) @@ -931,6 +970,8 @@ "$(DotnetPath)dotnet" build "$(AzureProjectPath)" + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) @@ -939,7 +980,7 @@ $(BuildSuffixArgument) $(PackageVersionAzureArgument) - + $(ReferenceTypeArgument) $(PackageVersionLoggingArgument) @@ -956,6 +997,8 @@ "$(DotnetPath)dotnet" pack "$(AzureProjectPath)" + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -996,22 +1039,26 @@ "$(DotnetPath)dotnet" test "$(AzureTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) $(TestFrameworkArgument) - $(SigningKeyPathArgument) - $(TestSigningKeyPathArgument) + --results-directory "$(TestResultsFolderPath)" + --logger:"trx;LogFilePrefix=$(LogFilePrefix)" - + $(ReferenceTypeArgument) $(PackageVersionAbstractionsArgument) $(PackageVersionLoggingArgument) $(PackageVersionSqlClientArgument) $(PackageVersionSqlServerArgument) - --results-directory "$(TestResultsFolderPath)" - --logger:"trx;LogFilePrefix=$(LogFilePrefix)" $([System.Text.RegularExpressions.Regex]::Replace($(DotnetCommand), "\s+", " ")) @@ -1035,6 +1082,8 @@ "$(DotnetPath)dotnet" build $(LoggingProjectPath) + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) @@ -1056,6 +1105,8 @@ "$(DotnetPath)dotnet" pack $(LoggingProjectPath) + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -1092,16 +1143,22 @@ "$(DotnetPath)dotnet" test "$(LoggingTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) $(TestFrameworkArgument) - $(SigningKeyPathArgument) - $(TestSigningKeyPathArgument) - $(ReferenceTypeArgument) --results-directory "$(TestResultsFolderPath)" --logger:"trx;LogFilePrefix=$(LogFilePrefix)" + + + $(ReferenceTypeArgument) $([System.Text.RegularExpressions.Regex]::Replace($(DotnetCommand), "\s+", " ")) @@ -1124,10 +1181,12 @@ "$(DotnetPath)dotnet" build $(SqlServerProjectPath) + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) - + $(BuildNumberArgument) $(BuildSuffixArgument) $(PackageVersionSqlServerArgument) @@ -1145,6 +1204,8 @@ "$(DotnetPath)dotnet" pack $(SqlServerProjectPath) + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) From 84d437a790732ae9f11c7234ec394d121bd4421e Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 18 Jun 2026 14:15:55 -0300 Subject: [PATCH 08/12] Disable signing for Project-mode pipeline; add signing to SqlServer.Server pack - ci-run-tests-job.yml: Remove signingKeyPath from Project-mode build step; gate test step signing keys on referenceType != Project - ci-build-nugets-job.yml: Remove signingKeyPath from hardcoded Project build; gate other build steps on referenceType != Project - pack-sqlserver-package-ci-job.yml: Add isInternalBuild parameter, download signing key, and pass SigningKeyPath via buildProperties for internal builds - build-sqlserver-package-ci-stage.yml: Accept and forward isInternalBuild - dotnet-sqlclient-ci-core.yml: Pass isInternalBuild to SqlServer stage Project mode now builds and tests unsigned, avoiding InternalsVisibleTo conflicts (CS0122). Package mode retains signing for strong-name compliance on net462. SqlServer.Server packages are now signed in internal builds, fixing FileLoadException in Package-mode net462 tests. --- .../templates/jobs/ci-build-nugets-job.yml | 6 ++---- .../templates/jobs/ci-run-tests-job.yml | 6 ++---- eng/pipelines/dotnet-sqlclient-ci-core.yml | 1 + .../jobs/pack-sqlserver-package-ci-job.yml | 19 ++++++++++++++++++- .../build-sqlserver-package-ci-stage.yml | 6 ++++++ 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml index 130f314beb..ec0f18a5ea 100644 --- a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml @@ -157,8 +157,6 @@ jobs: buildConfiguration: Release referenceType: Project build: all - ${{ if eq(parameters.isInternalBuild, true) }}: - signingKeyPath: $(driverKeyFile.secureFilePath) - template: /eng/pipelines/common/templates/steps/ci-project-build-step.yml@self parameters: @@ -170,7 +168,7 @@ jobs: abstractionsPackageVersion: ${{parameters.abstractionsPackageVersion}} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} - ${{ if eq(parameters.isInternalBuild, true) }}: + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: signingKeyPath: $(driverKeyFile.secureFilePath) - task: DotNetCoreCLI@2 @@ -219,7 +217,7 @@ jobs: mdsPackageVersion: ${{ parameters.mdsPackageVersion }} akvPackageVersion: ${{ parameters.akvPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} - ${{ if eq(parameters.isInternalBuild, true) }}: + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: signingKeyPath: $(driverKeyFile.secureFilePath) - task: DotNetCoreCLI@2 diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index df508c9522..705c5133ad 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -244,8 +244,6 @@ jobs: build: allNoDocs buildConfiguration: ${{ parameters.buildConfiguration }} referenceType: Project - ${{ if eq(parameters.isInternalBuild, true) }}: - signingKeyPath: $(driverKeyFile.secureFilePath) - ${{ if ne(parameters.configProperties, '{}') }}: - template: /eng/pipelines/common/templates/steps/update-config-file-step.yml@self # update config.jsonc file @@ -392,7 +390,7 @@ jobs: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} - ${{ if eq(parameters.isInternalBuild, true) }}: + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: signingKeyPath: $(driverKeyFile.secureFilePath) testSigningKeyPath: $(testKeyFile.secureFilePath) @@ -411,7 +409,7 @@ jobs: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} - ${{ if eq(parameters.isInternalBuild, true) }}: + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: signingKeyPath: $(driverKeyFile.secureFilePath) testSigningKeyPath: $(testKeyFile.secureFilePath) diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 5fdc25ee0e..500d2a76e9 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -144,6 +144,7 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} # Build the Logging package, and publish it to the pipeline artifacts # under the given artifact name. This runs in parallel with the Secrets diff --git a/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml b/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml index 6b19e8c154..a5b840cb79 100644 --- a/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml @@ -49,6 +49,11 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: pack_sqlserver_package_job @@ -82,6 +87,14 @@ jobs: - name: Configuration value: '' + # Build properties passed to dotnet pack. Composed from a base set plus + # optional signing key path for internal builds. + - name: buildProperties + ${{ if eq(parameters.isInternalBuild, true) }}: + value: SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }};SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ else }}: + value: SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} + steps: # Emit environment variables if debug is enabled. @@ -94,6 +107,10 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal builds. + - ${{ if eq(parameters.isInternalBuild, true) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. - task: DotNetCoreCLI@2 displayName: Create NuGet Package @@ -103,7 +120,7 @@ jobs: configurationToPack: ${{ parameters.buildConfiguration }} packDirectory: $(dotnetPackagesDir) verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} + buildProperties: $(buildProperties) - task: PublishPipelineArtifact@1 displayName: Publish Pipeline Artifact diff --git a/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml b/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml index 1711725373..bebff7c44b 100644 --- a/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml +++ b/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml @@ -63,6 +63,11 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - stage: build_sqlserver_package_stage @@ -81,3 +86,4 @@ stages: sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} From 44ae0f7b0b4221c60a90400e88603e7a88792b68 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 18 Jun 2026 22:02:53 -0300 Subject: [PATCH 09/12] Disable signing for leaf packages in Project-mode pipeline Gate assembly signing in Abstractions, Logging, and SqlServer.Server pack jobs on ne(referenceType, 'Project') so that Project-mode builds produce unsigned assemblies consistently across all packages. - pack-abstractions-package-ci-job.yml: remove Project+internal signing branch, gate key download on Package mode - pack-logging-package-ci-job.yml: add referenceType parameter, gate buildProperties and key download - pack-sqlserver-package-ci-job.yml: add referenceType parameter, gate buildProperties and key download - build-logging-package-ci-stage.yml: add referenceType parameter, forward to pack job - build-sqlserver-package-ci-stage.yml: add referenceType parameter, forward to pack job - dotnet-sqlclient-ci-core.yml: pass referenceType to Logging and SqlServer stage invocations --- eng/pipelines/dotnet-sqlclient-ci-core.yml | 2 ++ .../jobs/pack-abstractions-package-ci-job.yml | 6 ++---- .../jobs/pack-logging-package-ci-job.yml | 14 +++++++++++--- .../jobs/pack-sqlserver-package-ci-job.yml | 16 ++++++++++++---- .../stages/build-logging-package-ci-stage.yml | 9 +++++++++ .../stages/build-sqlserver-package-ci-stage.yml | 9 +++++++++ 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 500d2a76e9..2df5d62e1e 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -145,6 +145,7 @@ stages: debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} # Build the Logging package, and publish it to the pipeline artifacts # under the given artifact name. This runs in parallel with the Secrets @@ -158,6 +159,7 @@ stages: debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} # Build the Abstractions package, and publish it to the pipeline artifacts # under the given artifact name. diff --git a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml index 7f7506c431..37b16769b4 100644 --- a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml @@ -138,8 +138,6 @@ jobs: value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};SigningKeyPath=$(driverKeyFile.secureFilePath) ${{ elseif eq(parameters.referenceType, 'Package') }}: value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }} - ${{ elseif eq(parameters.isInternalBuild, true) }}: - value: $(baseBuildProperties);SigningKeyPath=$(driverKeyFile.secureFilePath) ${{ else }}: value: $(baseBuildProperties) @@ -164,8 +162,8 @@ jobs: parameters: debug: ${{ parameters.debug }} - # Download the assembly signing key for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self # Create the NuGet packages. diff --git a/eng/pipelines/jobs/pack-logging-package-ci-job.yml b/eng/pipelines/jobs/pack-logging-package-ci-job.yml index 3598ce009d..5248bf0853 100644 --- a/eng/pipelines/jobs/pack-logging-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-logging-package-ci-job.yml @@ -53,6 +53,14 @@ parameters: - detailed - diagnostic + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + # True when building on the internal ADO.Net project. - name: isInternalBuild type: boolean @@ -100,7 +108,7 @@ jobs: # optional variable is empty the semicolons remain, producing a trailing # ";;" that MSBuild rejects with MSB1005. - name: buildProperties - ${{ if eq(parameters.isInternalBuild, true) }}: + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: value: $(baseBuildProperties);SigningKeyPath=$(driverKeyFile.secureFilePath) ${{ else }}: value: $(baseBuildProperties) @@ -117,8 +125,8 @@ jobs: parameters: debug: ${{ parameters.debug }} - # Download the assembly signing key for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self # Create the NuGet packages. diff --git a/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml b/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml index a5b840cb79..8684d474ac 100644 --- a/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml @@ -49,6 +49,14 @@ parameters: - detailed - diagnostic + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + # True when building on the internal ADO.Net project. - name: isInternalBuild type: boolean @@ -88,9 +96,9 @@ jobs: value: '' # Build properties passed to dotnet pack. Composed from a base set plus - # optional signing key path for internal builds. + # optional signing key path for internal Package-mode builds. - name: buildProperties - ${{ if eq(parameters.isInternalBuild, true) }}: + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: value: SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }};SigningKeyPath=$(driverKeyFile.secureFilePath) ${{ else }}: value: SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} @@ -107,8 +115,8 @@ jobs: parameters: debug: ${{ parameters.debug }} - # Download the assembly signing key for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self # Create the NuGet packages. diff --git a/eng/pipelines/stages/build-logging-package-ci-stage.yml b/eng/pipelines/stages/build-logging-package-ci-stage.yml index d25954d35e..bfdbe84ff2 100644 --- a/eng/pipelines/stages/build-logging-package-ci-stage.yml +++ b/eng/pipelines/stages/build-logging-package-ci-stage.yml @@ -72,6 +72,14 @@ parameters: type: boolean default: false + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + stages: - stage: build_logging_package_stage @@ -144,3 +152,4 @@ stages: debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} diff --git a/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml b/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml index bebff7c44b..e08fbba531 100644 --- a/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml +++ b/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml @@ -68,6 +68,14 @@ parameters: type: boolean default: false + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + stages: - stage: build_sqlserver_package_stage @@ -87,3 +95,4 @@ stages: sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} From 8668069dee87543f5f9a08ef26955be3e3b88d61 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Fri, 19 Jun 2026 08:05:54 -0300 Subject: [PATCH 10/12] Disable signing for Azure Extensions pack job in Project mode Same fix as the other leaf packages: remove the Project+internal signing branch from buildProperties and gate the key download step on ne(referenceType, 'Project'). --- eng/pipelines/jobs/pack-azure-package-ci-job.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/eng/pipelines/jobs/pack-azure-package-ci-job.yml b/eng/pipelines/jobs/pack-azure-package-ci-job.yml index d26a0f4e33..e1ddd7da76 100644 --- a/eng/pipelines/jobs/pack-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-azure-package-ci-job.yml @@ -150,8 +150,6 @@ jobs: value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};SigningKeyPath=$(driverKeyFile.secureFilePath) ${{ elseif eq(parameters.referenceType, 'Package') }}: value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }} - ${{ elseif eq(parameters.isInternalBuild, true) }}: - value: $(baseBuildProperties);SigningKeyPath=$(driverKeyFile.secureFilePath) ${{ else }}: value: $(baseBuildProperties) @@ -181,8 +179,8 @@ jobs: parameters: debug: ${{ parameters.debug }} - # Download the assembly signing key for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self # Create the NuGet packages. From 5b5ff12169d98454a45c0be8bc2af6e26dff59cf Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Fri, 19 Jun 2026 08:13:42 -0300 Subject: [PATCH 11/12] Gate test job signing on referenceType for leaf packages Logging, Abstractions, and Azure test jobs were signing unconditionally when isInternalBuild=true, causing Project-mode tests to run signed. - test-logging-package-ci-job.yml: add referenceType param, gate signing - test-abstractions-package-ci-job.yml: add referenceType param, gate signing - test-azure-package-ci-job.yml: gate signing (already had referenceType) - build-logging-package-ci-stage.yml: pass referenceType to test jobs - build-abstractions-package-ci-stage.yml: pass referenceType to test jobs --- .../jobs/test-abstractions-package-ci-job.yml | 16 ++++++++++++---- eng/pipelines/jobs/test-azure-package-ci-job.yml | 8 ++++---- .../jobs/test-logging-package-ci-job.yml | 16 ++++++++++++---- .../build-abstractions-package-ci-stage.yml | 3 +++ .../stages/build-logging-package-ci-stage.yml | 3 +++ 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/eng/pipelines/jobs/test-abstractions-package-ci-job.yml b/eng/pipelines/jobs/test-abstractions-package-ci-job.yml index 880ea1d7f4..ceb176274a 100644 --- a/eng/pipelines/jobs/test-abstractions-package-ci-job.yml +++ b/eng/pipelines/jobs/test-abstractions-package-ci-job.yml @@ -67,6 +67,14 @@ parameters: type: boolean default: false + # The C# project reference type to use when building. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + # The pool VM image to use. - name: vmImage type: string @@ -100,8 +108,8 @@ jobs: -p:Configuration=${{ parameters.buildConfiguration }} --verbosity ${{ parameters.dotnetVerbosity }} - # Signing arguments — only set for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Signing arguments — only set for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - name: signingArguments value: >- -p:SigningKeyPath=$(driverKeyFile.secureFilePath) @@ -137,8 +145,8 @@ jobs: - pwsh: 'Get-ChildItem Env: | Sort-Object Name' displayName: '[Debug] Print Environment Variables' - # Download the assembly signing keys for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self parameters: diff --git a/eng/pipelines/jobs/test-azure-package-ci-job.yml b/eng/pipelines/jobs/test-azure-package-ci-job.yml index f1983eab91..3570d72114 100644 --- a/eng/pipelines/jobs/test-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/test-azure-package-ci-job.yml @@ -185,8 +185,8 @@ jobs: -p:SqlClientPackageVersion=${{ parameters.mdsPackageVersion }} -p:SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} - # Signing arguments — only set for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Signing arguments — only set for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - name: signingArguments value: >- -p:SigningKeyPath=$(driverKeyFile.secureFilePath) @@ -222,8 +222,8 @@ jobs: - pwsh: 'Get-ChildItem Env: | Sort-Object Name' displayName: '[Debug] Print Environment Variables' - # Download the assembly signing keys for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self parameters: diff --git a/eng/pipelines/jobs/test-logging-package-ci-job.yml b/eng/pipelines/jobs/test-logging-package-ci-job.yml index 6e035e33d6..fde3e44c7e 100644 --- a/eng/pipelines/jobs/test-logging-package-ci-job.yml +++ b/eng/pipelines/jobs/test-logging-package-ci-job.yml @@ -71,6 +71,14 @@ parameters: - name: vmImage type: string + # The C# project reference type to use when building. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + jobs: - job: test_logging_package_job_${{ parameters.jobNameSuffix }} @@ -100,8 +108,8 @@ jobs: -p:Configuration=${{ parameters.buildConfiguration }} --verbosity ${{ parameters.dotnetVerbosity }} - # Signing arguments — only set for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Signing arguments — only set for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - name: signingArguments value: >- -p:SigningKeyPath=$(driverKeyFile.secureFilePath) @@ -137,8 +145,8 @@ jobs: - pwsh: 'Get-ChildItem Env: | Sort-Object Name' displayName: '[Debug] Print Environment Variables' - # Download the assembly signing keys for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self parameters: diff --git a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml index f251d7d9c6..82a4efd6a4 100644 --- a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml +++ b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml @@ -122,6 +122,7 @@ stages: netFrameworkRuntimes: [] netRuntimes: [net8.0, net9.0, net10.0] poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} vmImage: ubuntu-latest # ------------------------------------------------------------------------ @@ -138,6 +139,7 @@ stages: netFrameworkRuntimes: [net462] netRuntimes: [net8.0, net9.0, net10.0] poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} vmImage: windows-latest # ------------------------------------------------------------------------ @@ -154,6 +156,7 @@ stages: netFrameworkRuntimes: [] netRuntimes: [net8.0, net9.0, net10.0] poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} vmImage: macos-latest # ------------------------------------------------------------------------ diff --git a/eng/pipelines/stages/build-logging-package-ci-stage.yml b/eng/pipelines/stages/build-logging-package-ci-stage.yml index bfdbe84ff2..4a0ee11a8f 100644 --- a/eng/pipelines/stages/build-logging-package-ci-stage.yml +++ b/eng/pipelines/stages/build-logging-package-ci-stage.yml @@ -106,6 +106,7 @@ stages: netFrameworkRuntimes: [] netRuntimes: [net8.0, net9.0, net10.0] poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} vmImage: ubuntu-latest # ------------------------------------------------------------------------ @@ -122,6 +123,7 @@ stages: netFrameworkRuntimes: [net462] netRuntimes: [net8.0, net9.0, net10.0] poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} vmImage: windows-latest # ------------------------------------------------------------------------ @@ -138,6 +140,7 @@ stages: netFrameworkRuntimes: [] netRuntimes: [net8.0, net9.0, net10.0] poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} vmImage: macos-latest # ------------------------------------------------------------------------ From 240ea7e573ecc8a16807ee66456bb38820794da8 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Fri, 19 Jun 2026 09:47:34 -0300 Subject: [PATCH 12/12] Address PR #4369 review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace static _sqlClientPublicKeyToken field with local variable inside #if ASSEMBLY_SIGNING block to eliminate CS0414 warning - Align Abstractions.Test.csproj TFM pattern with sibling test projects (conditional net462 on Windows only) - Standardize terminology: 'assembly verification' → 'strong-name identity verification', 'assembly signing' → 'strong-name signing' - Gate key download steps in ci-run-tests-job and ci-build-nugets-job on ne(referenceType, 'Project') to skip unnecessary downloads --- .../templates/jobs/ci-build-nugets-job.yml | 4 ++-- .../templates/jobs/ci-run-tests-job.yml | 4 ++-- .../jobs/validate-signed-package-job.yml | 4 ++-- .../src/SqlAuthenticationProvider.Internal.cs | 24 +++++++++---------- .../test/Abstractions.Test.csproj | 9 ++++++- .../SqlAuthenticationProviderManager.cs | 2 +- 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml index ec0f18a5ea..50d017f459 100644 --- a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml @@ -142,8 +142,8 @@ jobs: # Restore dotnet CLI tools (e.g. pwsh, apicompat) before building. - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self - # Download the assembly signing key for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self # When we're performing a Debug build, we still want to try _compiling_ the diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index 705c5133ad..1bbaef213a 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -228,8 +228,8 @@ jobs: # Restore dotnet CLI tools (e.g. pwsh, apicompat) before building. - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self - # Download the assembly signing keys for internal builds. - - ${{ if eq(parameters.isInternalBuild, true) }}: + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self parameters: diff --git a/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml b/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml index 03f511af9b..0769e2093c 100644 --- a/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml +++ b/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml @@ -157,8 +157,8 @@ jobs: $nugetPackageInstallPath = "${{ variables.nugetPackageInstallPath }}" echo "nugetPackageInstallPath= $nugetPackageInstallPath" - # Verify assembly signing ##################################### - echo "> 1. Verifying assembly signing of DLLs ..." + # Verify strong-name signing ################################### + echo "> 1. Verifying strong-name signing of DLLs ..." # @TODO: This path seems brittle to VS upgrades, can we make it more flexible? $snPath = "C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\NETFX 4.8.1 Tools\sn.exe" diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs index 7a801e607a..dd7cc33e6e 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs @@ -23,14 +23,6 @@ public abstract partial class SqlAuthenticationProvider /// private static class Internal { - /// - /// The expected public key token of the SqlClient assembly, used to avoid loading imposter - /// assemblies. This is the public key token of the assembly signing key used for all of - /// our driver assemblies. - /// - private static readonly byte[] _sqlClientPublicKeyToken = - [ 0x23, 0xec, 0x7f, 0xc2, 0xd6, 0xea, 0xa4, 0xa5 ]; - /// /// Our handle to the reflected GetProvider() method. /// @@ -56,14 +48,20 @@ static Internal() #if ASSEMBLY_SIGNING + // The expected public key token of the SqlClient assembly, used to avoid invoking + // APIs from imposter assemblies. This is the public key token of the assembly + // signing key used for all of our driver assemblies. + byte[] expectedPublicKeyToken = + [ 0x23, 0xec, 0x7f, 0xc2, 0xd6, 0xea, 0xa4, 0xa5 ]; + // When assembly signing is enabled, build a fully-qualified AssemblyName that // includes the expected public key token. Log($"Attempting to load SqlClient assembly={assemblyName} with " + "expected public key token=" + - BitConverter.ToString(_sqlClientPublicKeyToken).Replace("-", "")); + BitConverter.ToString(expectedPublicKeyToken).Replace("-", "")); var qualifiedName = new AssemblyName(assemblyName); - qualifiedName.SetPublicKeyToken(_sqlClientPublicKeyToken); + qualifiedName.SetPublicKeyToken(expectedPublicKeyToken); // The .NET Framework runtime enforces the token during binding, causing Load() to // throw if it doesn't match. The .NET (Core) runtime ignores the token, so we @@ -78,7 +76,7 @@ static Internal() byte[]? actualToken = assembly.GetName().GetPublicKeyToken(); if (actualToken is null || - !actualToken.AsSpan().SequenceEqual(_sqlClientPublicKeyToken)) + !actualToken.AsSpan().SequenceEqual(expectedPublicKeyToken)) { Log($"SqlClient assembly={assembly.GetName()} has an " + "unexpected public key token; " + @@ -90,8 +88,8 @@ static Internal() #else // Assembly signing is disabled, so we cannot verify the public key token. - Log($"Loading SqlClient assembly={assemblyName} without assembly verification; " + - "ensure this assembly is from a trusted source"); + Log($"Loading SqlClient assembly={assemblyName} without strong-name identity " + + "verification; ensure this assembly is from a trusted source"); var assembly = Assembly.Load(assemblyName); diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj index 24b8905322..7ab085560e 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj @@ -2,7 +2,14 @@ Microsoft.Data.SqlClient.Extensions.Abstractions.Test - net462;net8.0;net9.0;net10.0 + net8.0;net9.0;net10.0 + + + $(TargetFrameworks);net462 false true diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs index a3851e096f..e73a533245 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs @@ -109,7 +109,7 @@ static SqlAuthenticationProviderManager() SqlClientEventSource.Log.TryTraceEvent( nameof(SqlAuthenticationProviderManager) + $": Attempting to load Azure extension assembly={azureAssemblyName} without " + - "assembly verification; ensure this assembly is from a trusted source"); + "strong-name identity verification; ensure this assembly is from a trusted source"); var assembly = Assembly.Load(azureAssemblyName);