diff --git a/.azure-pipelines/1ES.Build.yml b/.azure-pipelines/1ES.Build.yml index 3aa2e3fc7..660e9bb88 100644 --- a/.azure-pipelines/1ES.Build.yml +++ b/.azure-pipelines/1ES.Build.yml @@ -87,10 +87,12 @@ extends: ESRPInfo: ${{ parameters.ESRPInfo }} # macOS uses a separate template because it runs on a different - # pool (Microsoft-hosted) and skips ESRP signing / cross-compile - # plumbing. The produced artifact name follows the same scheme - # (mxc-binaries-) so Package_MXC_NPM_SDK can consume it. + # pool (Microsoft-hosted). The produced artifact name follows the same + # scheme (mxc-binaries-) so Package_MXC_NPM_SDK can consume it. - template: .azure-pipelines/templates/Mac.Build.Job.yml@self + parameters: + isOfficialBuild: ${{ eq(parameters.officialBuild, 'Official') }} + ESRPInfo: ${{ parameters.ESRPInfo }} - stage: Package_MXC displayName: 'Package MXC' diff --git a/.azure-pipelines/templates/Mac.Build.Job.yml b/.azure-pipelines/templates/Mac.Build.Job.yml index fbb61ca11..ddbd53bd7 100644 --- a/.azure-pipelines/templates/Mac.Build.Job.yml +++ b/.azure-pipelines/templates/Mac.Build.Job.yml @@ -15,6 +15,12 @@ parameters: - name: triplet type: string default: aarch64-apple-darwin +- name: isOfficialBuild + type: boolean + default: false +- name: ESRPInfo + type: object + default: {} jobs: - job: 'build_arm64_MAC' @@ -82,6 +88,83 @@ jobs: displayName: Run tests workingDirectory: $(workingDirectory) + # --- macOS Code Signing + Notarization (official builds only) --- + # ESRP handles the full signing flow using Microsoft's Developer ID + # certificate (CP-401337-Apple). No local cert or codesign needed. + # + # ESRP's Mac signing requires a .zip (or .dmg) input — raw Mach-O + # binaries are rejected. We zip before signing and unzip afterward. + # + # Flow: (1) zip → (2) ESRP sign (hardened runtime) → (3) ESRP notarize → (4) unzip + # Stapling is impossible for standalone Mach-O binaries (Apple limitation); + # Gatekeeper checks the notarization ticket online instead. + - script: | + cd "$(targetTripleDir)" + zip mxc-exec-mac.zip mxc-exec-mac + displayName: 'Zip binary for ESRP signing' + condition: and(succeeded(), eq(${{ parameters.isOfficialBuild }}, true)) + + - task: EsrpCodeSigning@5 + displayName: 'Sign macOS binary (ESRP)' + condition: and(succeeded(), eq(${{ parameters.isOfficialBuild }}, true)) + inputs: + ConnectedServiceName: ${{ parameters.ESRPInfo.serviceName }} + AppRegistrationClientId: ${{ parameters.ESRPInfo.clientId }} + AppRegistrationTenantId: ${{ parameters.ESRPInfo.tenantId }} + AuthAKVName: ${{ parameters.ESRPInfo.azureKeyVaultName }} + AuthCertName: ${{ parameters.ESRPInfo.authCertName }} + AuthSignCertName: ${{ parameters.ESRPInfo.signCertName }} + FolderPath: $(targetTripleDir) + Pattern: mxc-exec-mac.zip + UseMinimatch: true + signConfigType: 'inlineSignParams' + inlineOperation: >- + [ + { + "KeyCode": "CP-401337-Apple", + "OperationCode": "MacAppDeveloperSign", + "Parameters": { + "Hardening": "--options=runtime" + }, + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + + - task: EsrpCodeSigning@5 + displayName: 'Notarize macOS binary (ESRP)' + condition: and(succeeded(), eq(${{ parameters.isOfficialBuild }}, true)) + inputs: + ConnectedServiceName: ${{ parameters.ESRPInfo.serviceName }} + AppRegistrationClientId: ${{ parameters.ESRPInfo.clientId }} + AppRegistrationTenantId: ${{ parameters.ESRPInfo.tenantId }} + AuthAKVName: ${{ parameters.ESRPInfo.azureKeyVaultName }} + AuthCertName: ${{ parameters.ESRPInfo.authCertName }} + AuthSignCertName: ${{ parameters.ESRPInfo.signCertName }} + FolderPath: $(targetTripleDir) + Pattern: mxc-exec-mac.zip + UseMinimatch: true + signConfigType: 'inlineSignParams' + inlineOperation: >- + [ + { + "KeyCode": "CP-401337-Apple", + "OperationCode": "MacAppNotarize", + "Parameters": { + "BundleId": "com.microsoft.mxc" + }, + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + + - script: | + cd "$(targetTripleDir)" + unzip -o mxc-exec-mac.zip + rm mxc-exec-mac.zip + displayName: 'Unzip signed binary' + condition: and(succeeded(), eq(${{ parameters.isOfficialBuild }}, true)) + - task: CopyFiles@2 displayName: Copy binary inputs: