Sign CI Package pipeline assemblies and tests; verify SqlClient in Abstractions - #4382
Sign CI Package pipeline assemblies and tests; verify SqlClient in Abstractions#4382paulmedynski wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Enables internal Package CI builds to strong-name sign driver assemblies and run tests against the signed outputs, and adds Abstractions-side verification that the loaded Microsoft.Data.SqlClient assembly matches the expected public key token when signing is enabled.
Changes:
- Adds a reusable pipeline step to download signing keys from secure files and threads
isInternalBuild,SigningKeyPath, andTestSigningKeyPaththrough build/test templates. - Updates
build.projand CI templates so signed vs. unsigned test filtering and test-assembly signing can be exercised in CI. - Adds Abstractions runtime protection (
#if STRONG_NAME_SIGNING) to avoid invoking reflection-based APIs from imposterMicrosoft.Data.SqlClientassemblies, and updates Abstractions test/IVT behavior for signed Package-mode runs.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj | Makes net462 testing Windows-only and signs the test assembly when TestSigningKeyPath is provided. |
| src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs | Verifies SqlClient public key token under STRONG_NAME_SIGNING before using reflection-based APIs. |
| src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj | Adds signed IVT for Package-mode tests and includes System.Memory dependency. |
| eng/pipelines/stages/build-sqlclient-package-ci-stage.yml | Threads isInternalBuild into SqlClient package CI stage. |
| eng/pipelines/stages/build-abstractions-package-ci-stage.yml | Threads isInternalBuild/referenceType through Abstractions build/test/pack stage. |
| eng/pipelines/onebranch/steps/build-buildproj-step.yml | Replaces inline secure-file download with shared signing-key download step. |
| eng/pipelines/onebranch/jobs/validate-signed-package-job.yml | Minor wording update to “strong-name signing”. |
| eng/pipelines/jobs/test-abstractions-package-ci-job.yml | Adds internal-build signing key download + signing args; renames CLI opts variable to avoid env var injection pitfalls. |
| eng/pipelines/jobs/pack-abstractions-package-ci-job.yml | Adds internal-build signing key handling and consolidates pack buildProperties composition. |
| eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml | Computes/passes isInternalBuild to core template. |
| eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml | Computes/passes isInternalBuild to core template. |
| eng/pipelines/dotnet-sqlclient-ci-core.yml | Adds isInternalBuild parameter and threads it into dependent stages/jobs. |
| eng/pipelines/common/templates/steps/run-all-tests-step.yml | Adds signingKeyPath/testSigningKeyPath plumbing into build.proj test invocations. |
| eng/pipelines/common/templates/steps/ci-project-build-step.yml | Adds SigningKeyPath plumbing into build.proj build invocations. |
| eng/pipelines/common/templates/stages/ci-run-tests-stage.yml | Threads isInternalBuild into test job template. |
| eng/pipelines/common/templates/jobs/ci-run-tests-job.yml | Downloads signing keys for internal Package-mode runs and passes key paths into test steps. |
| eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml | Downloads signing key for internal Package-mode builds and passes it into build steps. |
| eng/pipelines/common/steps/download-assembly-signing-key.yml | New shared secure-file download step for driver/test signing keys. |
| eng/pipelines/ci/package/sqlclient-package.yml | Uses the shared signing-key download step and updated output variable name. |
| build.proj | Threads signing/test-signing properties through relevant build/test commands; improves command sectioning comments. |
|
|
||
| <!-- Polyfills ======================================================= --> | ||
| <ItemGroup> | ||
| <PackageReference Include="System.Memory" /> |
There was a problem hiding this comment.
For Span.SequenceEqual() in Internal.cs
| default: SqlServer.Artifacts | ||
|
|
||
| # True when building on the internal ADO.Net project. | ||
| - name: isInternalBuild |
There was a problem hiding this comment.
There is a bunch of template plumbing to get isInternalBuild down to the steps that need to decide whether or not to sign assemblies.
| // Try to load the MDS assembly. | ||
| // Try to load the SqlClient assembly. | ||
|
|
||
| #if STRONG_NAME_SIGNING |
There was a problem hiding this comment.
The impetus for this work - to validate the SqlClient assembly the same way we're validating the Azure assembly.
| <DotnetCommand> | ||
| "$(DotnetPath)dotnet" build "$(SqlClientNotSupportedProjectPath)" | ||
|
|
||
| <!-- Build arguments --> |
There was a problem hiding this comment.
Some minor unrelated cleanup for consistent sections and ordering in these repeated blocks.
|
|
||
| <!-- Build arguments --> | ||
| -p:Configuration=$(Configuration) | ||
| $(SigningKeyPathArgument) |
There was a problem hiding this comment.
We're adding the signing key build properties in a few new places now.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4382 +/- ##
==========================================
- Coverage 65.45% 63.46% -1.99%
==========================================
Files 285 280 -5
Lines 43373 66257 +22884
==========================================
+ Hits 28388 42050 +13662
- Misses 14985 24207 +9222
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
7bcc862 to
7ab93d0
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj:12
- The comment explaining why net462 is conditional is misleading: the Abstractions library targets netstandard2.0, so it can be referenced by a net462 test project. The real constraint is that targeting/building/running net462 is Windows-only. Reword this comment to avoid implying Abstractions itself is missing a net462 build.
The Abstractions project is not built for net462 unless it is built for Windows. Thus, we
will not be able to fulfill the Abstractions for net462 reference unless we are building on
Windows.
-->
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj:97
- The System.Memory package is only needed for the STRONG_NAME_SIGNING code path (the only place Abstractions uses AsSpan/Span APIs). Consider conditioning this PackageReference on SigningKeyPath (or another MSBuild property that matches STRONG_NAME_SIGNING) so unsigned/local builds don’t take an unnecessary transitive dependency.
<!-- Polyfills ======================================================= -->
<ItemGroup>
<PackageReference Include="System.Memory" />
</ItemGroup>
…stractions Bare-minimum changes to produce and test signed assemblies in the CI Package pipeline, plus the Abstractions strong-name verification of the SqlClient assembly. - Add the download-assembly-signing-key pipeline step and thread SigningKeyPath / TestSigningKeyPath through the CI Package build, pack, and test jobs so the SqlClient package and its tests are produced and run signed. - Thread isInternalBuild through the SqlClient and Abstractions package stages. - In SqlAuthenticationProvider (Abstractions), verify the loaded Microsoft.Data.SqlClient assembly's public key token when STRONG_NAME_SIGNING is defined, with defense-in-depth post-load verification on .NET Core. - Add conditional signed InternalsVisibleTo and test-assembly signing for the Abstractions project and its tests.
7ab93d0 to
b30d7ec
Compare
| # 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 }} | ||
|
|
||
| # 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 | ||
| ${{ 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 }} | ||
| ${{ else }}: | ||
| value: $(baseBuildProperties) | ||
|
|
| mdsArtifactsName: ${{ parameters.mdsArtifactsName }} | ||
| mdsPackageVersion: ${{ parameters.mdsPackageVersion }} | ||
| isInternalBuild: ${{ parameters.isInternalBuild }} |
| abstractionsArtifactsName: $(abstractionsArtifactsName) | ||
| loggingArtifactsName: $(loggingArtifactsName) | ||
| mdsArtifactsName: $(mdsArtifactsName) | ||
| mdsPackageVersion: $(mdsPackageVersion) | ||
| isInternalBuild: ${{ parameters.isInternalBuild }} |
Summary
Core of the assembly-signing work. Enables the CI Package pipeline to sign the driver assemblies and run tests against the signed assemblies, and adds the Abstractions-side verification of the
Microsoft.Data.SqlClientassembly's public key token.This reuses the existing
STRONG_NAME_SIGNINGconstant already defined onmain(no rename here — that is done in the follow-up PR).What's included
eng/pipelines/common/steps/download-assembly-signing-key.ymlstep.build.proj+ CI pipeline wiring to threadsigningKeyPath/testSigningKeyPath,isInternalBuild, andreferenceTypethrough the SqlClient and Abstractions package build/test stages.#if STRONG_NAME_SIGNING) of the SqlClient public key token inSqlAuthenticationProvider.Internal.cs, plus signedInternalsVisibleTofor the Abstractions test assembly in Package mode.🔗 PR Stack
Part of a 6-PR stack — current PR marked 👉. Indentation shows the branch base.
mainSTRONG_NAME_SIGNING→ASSEMBLY_SIGNINGMicrosoft.SqlServer.Serverassembly & CIflowchart TD main([main]) PR1["🏗️ #4382<br/>signing-core"] AOT["✂️ #4348<br/>aot"] PR2["🏷️ #4383<br/>rename"] PR3["🪵 #4384<br/>logging-tests"] PR4["☁️ #4385<br/>azure-signing"] PR5["🧩 #4386<br/>sqlserver.server"] main --> PR1 PR1 --> AOT PR1 --> PR2 PR2 --> PR3 PR2 --> PR4 PR2 --> PR5 click PR1 "https://github.com/dotnet/SqlClient/pull/4382" _blank click AOT "https://github.com/dotnet/SqlClient/pull/4348" _blank click PR2 "https://github.com/dotnet/SqlClient/pull/4383" _blank click PR3 "https://github.com/dotnet/SqlClient/pull/4384" _blank click PR4 "https://github.com/dotnet/SqlClient/pull/4385" _blank click PR5 "https://github.com/dotnet/SqlClient/pull/4386" _blank classDef current fill:#1f6feb,stroke:#1f6feb,color:#fff; class PR1 current;Checklist