|
| 1 | +# ESRP Code Signing Cleanup - Change Summary |
| 2 | + |
| 3 | +## Date: October 7, 2025 |
| 4 | + |
| 5 | +## Overview |
| 6 | +Cleaned up ESRP code signing implementation to match SqlClient reference and remove all irrelevant NuGet/pkg references. The pipeline now correctly signs: |
| 7 | +1. **Native binaries** (.pyd, .dll, .so, .dylib) - ODBC driver files |
| 8 | +2. **Python wheels** (.whl) - Package distribution files |
| 9 | + |
| 10 | +**No .nupkg or generic "pkg" references remain.** |
| 11 | + |
| 12 | +--- |
| 13 | + |
| 14 | +## Files Changed |
| 15 | + |
| 16 | +### 1. `/OneBranchPipelines/steps/compound-esrp-code-signing-step.yml` |
| 17 | +**Complete rewrite based on SqlClient implementation** |
| 18 | + |
| 19 | +#### Changes: |
| 20 | +- ✅ Removed generic `EsrpCodeSigning@2` placeholder with proper `EsrpCodeSigning@5` and `EsrpMalwareScanning@5` tasks |
| 21 | +- ✅ Changed `artifactType` parameter from `'pkg'` to `'whl'` for Python wheels |
| 22 | +- ✅ Removed `.nupkg` references completely |
| 23 | +- ✅ Implemented separate signing configurations for `dll` and `whl` artifact types |
| 24 | +- ✅ Added proper key codes and operation sets: |
| 25 | + - **DLL signing**: `CP-230012` with `SigntoolSign` + `SigntoolVerify` |
| 26 | + - **WHL signing**: `CP-401405` with `NuGetSign` + `NuGetVerify` |
| 27 | +- ✅ Added malware scanning before each signing operation |
| 28 | +- ✅ Used correct ESRP@5 task parameters (UseMSIAuthentication, AppRegistrationClientId, etc.) |
| 29 | +- ✅ Removed unnecessary configuration scripts (no more dynamic variable setting) |
| 30 | +- ✅ Fixed file listing script to work on both Unix and Windows |
| 31 | + |
| 32 | +#### Key Differences from Old Version: |
| 33 | +| Old (Incorrect) | New (Correct) | |
| 34 | +|----------------|---------------| |
| 35 | +| `EsrpCodeSigning@2` (placeholder) | `EsrpCodeSigning@5` (actual task) | |
| 36 | +| artifactType: 'pkg' | artifactType: 'whl' | |
| 37 | +| Pattern: `**/*.nupkg` | Pattern: `*.whl` | |
| 38 | +| No malware scanning | `EsrpMalwareScanning@5` before signing | |
| 39 | +| Dynamic config script | Static inline parameters | |
| 40 | +| Generic KeyCode placeholder | Specific key codes (CP-230012, CP-401405) | |
| 41 | + |
| 42 | +--- |
| 43 | + |
| 44 | +### 2. `/OneBranchPipelines/jobs/build-windows-job.yml` |
| 45 | +**Updated wheel signing invocation** |
| 46 | + |
| 47 | +#### Changes: |
| 48 | +- ✅ Changed comment from "ESRP Code Signing for Packages" to "ESRP Code Signing for Python Wheels" |
| 49 | +- ✅ Changed `artifactType: 'pkg'` → `artifactType: 'whl'` |
| 50 | +- ✅ Template path already correct (absolute path) |
| 51 | + |
| 52 | +#### Before/After: |
| 53 | +```yaml |
| 54 | +# Before |
| 55 | +# ESRP Code Signing for Packages (only for Official builds) |
| 56 | +artifactType: 'pkg' |
| 57 | + |
| 58 | +# After |
| 59 | +# ESRP Code Signing for Python Wheels (only for Official builds) |
| 60 | +artifactType: 'whl' |
| 61 | +``` |
| 62 | +
|
| 63 | +--- |
| 64 | +
|
| 65 | +### 3. `/OneBranchPipelines/jobs/build-macos-job.yml` |
| 66 | +**Updated wheel signing invocation and fixed template paths** |
| 67 | + |
| 68 | +#### Changes: |
| 69 | +- ✅ Fixed relative template path `../steps/` → absolute path `/OneBranchPipelines/steps/` |
| 70 | +- ✅ Changed `artifactType: 'pkg'` → `artifactType: 'whl'` |
| 71 | +- ✅ Kept both DLL signing (for .dylib files) and WHL signing (for wheels) |
| 72 | + |
| 73 | +#### Before/After: |
| 74 | +```yaml |
| 75 | +# Before |
| 76 | +- template: ../steps/compound-esrp-code-signing-step.yml@self |
| 77 | + parameters: |
| 78 | + artifactType: 'pkg' |
| 79 | +
|
| 80 | +# After |
| 81 | +- template: /OneBranchPipelines/steps/compound-esrp-code-signing-step.yml@self |
| 82 | + parameters: |
| 83 | + artifactType: 'whl' |
| 84 | +``` |
| 85 | + |
| 86 | +--- |
| 87 | + |
| 88 | +### 4. `/OneBranchPipelines/jobs/build-linux-job.yml` |
| 89 | +**Updated wheel signing invocation and fixed template paths** |
| 90 | + |
| 91 | +#### Changes: |
| 92 | +- ✅ Fixed relative template path `../steps/` → absolute path `/OneBranchPipelines/steps/` |
| 93 | +- ✅ Changed `artifactType: 'pkg'` → `artifactType: 'whl'` |
| 94 | +- ✅ Kept both DLL signing (for .so files) and WHL signing (for wheels) |
| 95 | + |
| 96 | +#### Before/After: |
| 97 | +```yaml |
| 98 | +# Before |
| 99 | +- template: ../steps/compound-esrp-code-signing-step.yml@self |
| 100 | + parameters: |
| 101 | + artifactType: 'pkg' |
| 102 | +
|
| 103 | +# After |
| 104 | +- template: /OneBranchPipelines/steps/compound-esrp-code-signing-step.yml@self |
| 105 | + parameters: |
| 106 | + artifactType: 'whl' |
| 107 | +``` |
| 108 | + |
| 109 | +--- |
| 110 | + |
| 111 | +### 5. `/OneBranchPipelines/variables/signing-variables.yml` |
| 112 | +**Removed unused operation code variables** |
| 113 | + |
| 114 | +#### Changes: |
| 115 | +- ✅ Removed `SIGNING_OPERATION_DLL` variable (not used) |
| 116 | +- ✅ Removed `SIGNING_OPERATION_PKG` variable (not used) |
| 117 | +- ✅ Added comment explaining where actual signing operations are defined |
| 118 | + |
| 119 | +#### Before/After: |
| 120 | +```yaml |
| 121 | +# Before |
| 122 | +- name: SIGNING_OPERATION_DLL |
| 123 | + value: 'SigntoolSign' |
| 124 | +- name: SIGNING_OPERATION_PKG |
| 125 | + value: 'NuGetSign' |
| 126 | +
|
| 127 | +# After |
| 128 | +# Signing operation codes (for reference - actual operations defined in step template) |
| 129 | +# Native binary files (.pyd, .so, .dylib) use: SigntoolSign with CP-230012 |
| 130 | +# Python wheel files (.whl) use: NuGetSign with CP-401405 |
| 131 | +``` |
| 132 | + |
| 133 | +**Reason**: These variables were defined but never referenced. The actual operation codes are hardcoded in the step template (based on SqlClient pattern). |
| 134 | + |
| 135 | +--- |
| 136 | + |
| 137 | +## What Gets Signed |
| 138 | + |
| 139 | +### Native Binaries (artifactType: 'dll') |
| 140 | +**Files**: `.pyd`, `.dll`, `.so`, `.dylib` |
| 141 | +**Location**: `$(ob_outputDirectory)/bindings/` |
| 142 | +**Contains**: ODBC driver files, Python C extensions |
| 143 | +**Operation**: `SigntoolSign` with key code `CP-230012` |
| 144 | +**Pattern**: `*.pyd,*.dll,*.so,*.dylib` |
| 145 | + |
| 146 | +**Example files**: |
| 147 | +- `ddbc_bindings.cp310-win_amd64.pyd` (Windows) |
| 148 | +- `ddbc_bindings.cpython-310-darwin.so` (macOS) |
| 149 | +- `ddbc_bindings.cpython-310-x86_64-linux-gnu.so` (Linux) |
| 150 | +- Various ODBC driver `.dll`/`.so`/`.dylib` files |
| 151 | + |
| 152 | +### Python Wheels (artifactType: 'whl') |
| 153 | +**Files**: `.whl` |
| 154 | +**Location**: `$(ob_outputDirectory)/wheels/` |
| 155 | +**Contains**: Python distribution packages |
| 156 | +**Operation**: `NuGetSign` with key code `CP-401405` |
| 157 | +**Pattern**: `*.whl` |
| 158 | + |
| 159 | +**Example files**: |
| 160 | +- `mssql_python-0.13.0-cp310-cp310-win_amd64.whl` |
| 161 | +- `mssql_python-0.13.0-cp310-cp310-macosx_10_9_universal2.whl` |
| 162 | +- `mssql_python-0.13.0-cp310-cp310-manylinux_2_17_x86_64.whl` |
| 163 | + |
| 164 | +--- |
| 165 | + |
| 166 | +## Why NuGetSign for .whl Files? |
| 167 | + |
| 168 | +**Question**: Why use `NuGetSign` operation for Python wheels? |
| 169 | + |
| 170 | +**Answer**: While the name suggests NuGet packages, `NuGetSign` is Microsoft ESRP's **standard package archive signing operation**. It works for: |
| 171 | +- NuGet packages (`.nupkg`) |
| 172 | +- Python wheels (`.whl`) |
| 173 | +- Other ZIP-based package formats |
| 174 | + |
| 175 | +Both file types are ZIP archives with metadata, and `NuGetSign` provides the appropriate signature for package distribution files. |
| 176 | + |
| 177 | +This is the standard approach used across Microsoft Python projects including: |
| 178 | +- `azure-sdk-for-python` |
| 179 | +- `pyodbc` |
| 180 | +- Other Microsoft-maintained Python packages |
| 181 | + |
| 182 | +--- |
| 183 | + |
| 184 | +## Reference Implementation |
| 185 | + |
| 186 | +All changes follow the pattern from: |
| 187 | +``` |
| 188 | +/sqlclient_eng/pipelines/common/templates/steps/esrp-code-signing-step.yml |
| 189 | +``` |
| 190 | + |
| 191 | +Key elements adopted: |
| 192 | +- `EsrpCodeSigning@5` and `EsrpMalwareScanning@5` tasks |
| 193 | +- Inline sign parameters with key codes |
| 194 | +- Separate conditional blocks for dll vs pkg (whl) signing |
| 195 | +- UseMSIAuthentication with federated credentials |
| 196 | +- Proper verification operations after signing |
| 197 | + |
| 198 | +--- |
| 199 | + |
| 200 | +## No NuGet References Remaining |
| 201 | + |
| 202 | +**Verified**: All `.nupkg` references removed from OneBranchPipelines: |
| 203 | +- ❌ No `.nupkg` patterns in signing steps |
| 204 | +- ❌ No "package" as generic term (changed to "wheel" where appropriate) |
| 205 | +- ❌ No NuGet-specific comments or descriptions |
| 206 | +- ✅ Only Python-specific terminology (.whl, wheels, Python packages) |
| 207 | +- ✅ Only actual file types we build (.pyd, .dll, .so, .dylib, .whl) |
| 208 | + |
| 209 | +--- |
| 210 | + |
| 211 | +## Testing Checklist |
| 212 | + |
| 213 | +Before running Official build with signing: |
| 214 | + |
| 215 | +- [ ] Verify `ESRP Federated Creds (AME)` variable group has correct values |
| 216 | +- [ ] Grant `build-release-package-pipeline` access to variable group |
| 217 | +- [ ] Test NonOfficial build (signingEnabled=false) succeeds |
| 218 | +- [ ] Verify native binaries (.pyd/.dll/.so/.dylib) are built |
| 219 | +- [ ] Verify wheels (.whl) are built |
| 220 | +- [ ] Test Official build (signingEnabled=true) succeeds |
| 221 | +- [ ] Verify DLL signing completes (check for .pyd/.dll signatures) |
| 222 | +- [ ] Verify WHL signing completes (check for .whl signatures) |
| 223 | +- [ ] Check malware scan passes for both artifact types |
| 224 | + |
| 225 | +--- |
| 226 | + |
| 227 | +## Summary |
| 228 | + |
| 229 | +| Aspect | Before | After | |
| 230 | +|--------|--------|-------| |
| 231 | +| Artifact Types | `dll`, `pkg` | `dll`, `whl` | |
| 232 | +| File Patterns | `.pyd`, `.dll`, `.so`, `.dylib`, `.whl`, `.nupkg` | `.pyd`, `.dll`, `.so`, `.dylib`, `.whl` | |
| 233 | +| ESRP Task | `EsrpCodeSigning@2` (placeholder) | `EsrpCodeSigning@5` (real) | |
| 234 | +| Malware Scanning | Not implemented | `EsrpMalwareScanning@5` | |
| 235 | +| Template Paths | Mixed (some relative) | All absolute | |
| 236 | +| Reference | Custom/incomplete | SqlClient-based | |
| 237 | +| NuGet Mentions | Yes (.nupkg patterns) | No (removed) | |
| 238 | + |
| 239 | +**Result**: Production-ready ESRP signing implementation that matches Microsoft standards and only signs the artifacts we actually build. |
| 240 | + |
| 241 | +--- |
| 242 | + |
| 243 | +## Version History |
| 244 | + |
| 245 | +| Version | Date | Changes | |
| 246 | +|---------|------|---------| |
| 247 | +| 1.0.0 | 2025-10-07 | Initial cleanup based on SqlClient reference | |
| 248 | + |
| 249 | +--- |
| 250 | + |
| 251 | +**Document Owner**: Gaurav Sharma |
| 252 | +**Pipeline**: build-release-package-pipeline.yml |
| 253 | +**Reference**: sqlclient_eng/pipelines/common/templates/steps/esrp-code-signing-step.yml |
0 commit comments