From 7d80f16b5cdc2d70d505cbc146dccf33fa3937ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 7 Nov 2024 10:07:51 +0100 Subject: [PATCH] use oidc (#233289) * use oidc (#233126) * use oidc * undo dep bump * use ClientAssertionCredential * temporarily disable mangle * adopt oidc * move to new service connection, remove deprecated storage account upload (#233191) * use longer lived access tokens for cosmosdb auth (#233255) --- .../alpine/product-build-alpine.yml | 4 +- build/azure-pipelines/cli/cli-darwin-sign.yml | 2 +- build/azure-pipelines/cli/cli-win32-sign.yml | 2 +- build/azure-pipelines/common/createBuild.js | 2 +- build/azure-pipelines/common/createBuild.ts | 4 +- build/azure-pipelines/common/publish.js | 39 ++++++++++++++--- build/azure-pipelines/common/publish.ts | 42 ++++++++++++++++--- build/azure-pipelines/common/releaseBuild.js | 2 +- build/azure-pipelines/common/releaseBuild.ts | 4 +- .../darwin/product-build-darwin-sign.yml | 2 +- .../darwin/product-build-darwin-universal.yml | 2 +- .../darwin/product-build-darwin.yml | 2 +- .../distro/download-distro.yml | 2 +- .../product-build-linux-legacy-server.yml | 4 +- .../linux/product-build-linux.yml | 2 +- build/azure-pipelines/product-build.yml | 2 +- build/azure-pipelines/product-compile.yml | 17 ++------ build/azure-pipelines/product-publish.yml | 12 +++--- build/azure-pipelines/product-release.yml | 12 +++--- build/azure-pipelines/upload-cdn.js | 2 +- build/azure-pipelines/upload-cdn.ts | 4 +- build/azure-pipelines/upload-nlsmetadata.js | 2 +- build/azure-pipelines/upload-nlsmetadata.ts | 4 +- build/azure-pipelines/upload-sourcemaps.js | 2 +- build/azure-pipelines/upload-sourcemaps.ts | 4 +- .../azure-pipelines/web/product-build-web.yml | 26 ++++-------- .../win32/product-build-win32.yml | 2 +- .../azure-pipelines/win32/sdl-scan-win32.yml | 2 +- 28 files changed, 120 insertions(+), 86 deletions(-) diff --git a/build/azure-pipelines/alpine/product-build-alpine.yml b/build/azure-pipelines/alpine/product-build-alpine.yml index 890bc68c7380d..d6fe74a9d610b 100644 --- a/build/azure-pipelines/alpine/product-build-alpine.yml +++ b/build/azure-pipelines/alpine/product-build-alpine.yml @@ -10,7 +10,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password" @@ -59,7 +59,7 @@ steps: - task: Docker@1 inputs: - azureSubscriptionEndpoint: "vscode-builds-subscription" + azureSubscriptionEndpoint: vscode azureContainerRegistry: vscodehub.azurecr.io command: "Run an image" imageName: "vscode-linux-build-agent:alpine-$(VSCODE_ARCH)" diff --git a/build/azure-pipelines/cli/cli-darwin-sign.yml b/build/azure-pipelines/cli/cli-darwin-sign.yml index b6dc424d690b2..c79e4747522ba 100644 --- a/build/azure-pipelines/cli/cli-darwin-sign.yml +++ b/build/azure-pipelines/cli/cli-darwin-sign.yml @@ -7,7 +7,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "ESRP-PKI,esrp-aad-username,esrp-aad-password" diff --git a/build/azure-pipelines/cli/cli-win32-sign.yml b/build/azure-pipelines/cli/cli-win32-sign.yml index e39df13c998ea..b5af28fd080e3 100644 --- a/build/azure-pipelines/cli/cli-win32-sign.yml +++ b/build/azure-pipelines/cli/cli-win32-sign.yml @@ -7,7 +7,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "ESRP-PKI,esrp-aad-username,esrp-aad-password" diff --git a/build/azure-pipelines/common/createBuild.js b/build/azure-pipelines/common/createBuild.js index 29c3448edc193..c605ed6218efb 100644 --- a/build/azure-pipelines/common/createBuild.js +++ b/build/azure-pipelines/common/createBuild.js @@ -40,7 +40,7 @@ async function main() { assets: [], updates: {} }; - const aadCredentials = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']); + const aadCredentials = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN'])); const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials }); const scripts = client.database('builds').container(quality).scripts; await (0, retry_1.retry)(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }])); diff --git a/build/azure-pipelines/common/createBuild.ts b/build/azure-pipelines/common/createBuild.ts index afc5f59003a26..6afeb01e6cc78 100644 --- a/build/azure-pipelines/common/createBuild.ts +++ b/build/azure-pipelines/common/createBuild.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ClientSecretCredential } from '@azure/identity'; +import { ClientAssertionCredential } from '@azure/identity'; import { CosmosClient } from '@azure/cosmos'; import { retry } from './retry'; @@ -47,7 +47,7 @@ async function main(): Promise { updates: {} }; - const aadCredentials = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!); + const aadCredentials = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!)); const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials }); const scripts = client.database('builds').container(quality).scripts; await retry(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }])); diff --git a/build/azure-pipelines/common/publish.js b/build/azure-pipelines/common/publish.js index aa185ed836998..5b7acc2000158 100644 --- a/build/azure-pipelines/common/publish.js +++ b/build/azure-pipelines/common/publish.js @@ -4,6 +4,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); +exports.getAccessToken = getAccessToken; const fs = require("fs"); const path = require("path"); const stream_1 = require("stream"); @@ -41,6 +42,32 @@ class Temp { } } } +/** + * Gets an access token converted from a WIF/OIDC id token. + * We need this since this build job takes a while to run and while id tokens live for 10 minutes only, access tokens live for 24 hours. + * Source: https://goodworkaround.com/2021/12/21/another-deep-dive-into-azure-ad-workload-identity-federation-using-github-actions/ + */ +async function getAccessToken(endpoint, tenantId, clientId, idToken) { + const body = new URLSearchParams({ + scope: `${endpoint}.default`, + client_id: clientId, + grant_type: 'client_credentials', + client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer', + client_assertion: encodeURIComponent(idToken) + }); + const response = await fetch(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: body.toString() + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const aadToken = await response.json(); + return aadToken.access_token; +} function isCreateProvisionedFilesErrorResponse(response) { return response?.ErrorDetails?.Code !== undefined; } @@ -473,7 +500,7 @@ function getRealType(type) { return type; } } -async function processArtifact(artifact, artifactFilePath) { +async function processArtifact(artifact, artifactFilePath, cosmosDBAccessToken) { const log = (...args) => console.log(`[${artifact.name}]`, ...args); const match = /^vscode_(?[^_]+)_(?[^_]+)(?:_legacy)?_(?[^_]+)_(?[^_]+)$/.exec(artifact.name); if (!match) { @@ -494,8 +521,7 @@ async function processArtifact(artifact, artifactFilePath) { log('Creating asset...', JSON.stringify(asset, undefined, 2)); await (0, retry_1.retry)(async (attempt) => { log(`Creating asset in Cosmos DB (attempt ${attempt})...`); - const aadCredentials = new identity_1.ClientSecretCredential(e('AZURE_TENANT_ID'), e('AZURE_CLIENT_ID'), e('AZURE_CLIENT_SECRET')); - const client = new cosmos_1.CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT'), aadCredentials }); + const client = new cosmos_1.CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT'), tokenProvider: () => Promise.resolve(`type=aad&ver=1.0&sig=${cosmosDBAccessToken}`) }); const scripts = client.database('builds').container(quality).scripts; await scripts.storedProcedure('createAsset').execute('', [commit, asset, true]); }); @@ -509,8 +535,8 @@ async function processArtifact(artifact, artifactFilePath) { // the CDN and finally update the build in Cosmos DB. async function main() { if (!node_worker_threads_1.isMainThread) { - const { artifact, artifactFilePath } = node_worker_threads_1.workerData; - await processArtifact(artifact, artifactFilePath); + const { artifact, artifactFilePath, cosmosDBAccessToken } = node_worker_threads_1.workerData; + await processArtifact(artifact, artifactFilePath, cosmosDBAccessToken); return; } const done = new State(); @@ -539,6 +565,7 @@ async function main() { } let resultPromise = Promise.resolve([]); const operations = []; + const cosmosDBAccessToken = await getAccessToken(e('AZURE_DOCUMENTDB_ENDPOINT'), e('AZURE_TENANT_ID'), e('AZURE_CLIENT_ID'), e('AZURE_ID_TOKEN')); while (true) { const [timeline, artifacts] = await Promise.all([(0, retry_1.retry)(() => getPipelineTimeline()), (0, retry_1.retry)(() => getPipelineArtifacts())]); const stagesCompleted = new Set(timeline.records.filter(r => r.type === 'Stage' && r.state === 'completed' && stages.has(r.name)).map(r => r.name)); @@ -575,7 +602,7 @@ async function main() { const artifactFilePath = artifactFilePaths.filter(p => !/_manifest/.test(p))[0]; processing.add(artifact.name); const promise = new Promise((resolve, reject) => { - const worker = new node_worker_threads_1.Worker(__filename, { workerData: { artifact, artifactFilePath } }); + const worker = new node_worker_threads_1.Worker(__filename, { workerData: { artifact, artifactFilePath, cosmosDBAccessToken } }); worker.on('error', reject); worker.on('exit', code => { if (code === 0) { diff --git a/build/azure-pipelines/common/publish.ts b/build/azure-pipelines/common/publish.ts index 652cd1683351f..37ed4232f38e5 100644 --- a/build/azure-pipelines/common/publish.ts +++ b/build/azure-pipelines/common/publish.ts @@ -47,6 +47,36 @@ class Temp { } } +/** + * Gets an access token converted from a WIF/OIDC id token. + * We need this since this build job takes a while to run and while id tokens live for 10 minutes only, access tokens live for 24 hours. + * Source: https://goodworkaround.com/2021/12/21/another-deep-dive-into-azure-ad-workload-identity-federation-using-github-actions/ + */ +export async function getAccessToken(endpoint: string, tenantId: string, clientId: string, idToken: string): Promise { + const body = new URLSearchParams({ + scope: `${endpoint}.default`, + client_id: clientId, + grant_type: 'client_credentials', + client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer', + client_assertion: encodeURIComponent(idToken) + }); + + const response = await fetch(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: body.toString() + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const aadToken = await response.json(); + return aadToken.access_token; +} + interface RequestOptions { readonly body?: string; } @@ -636,7 +666,7 @@ function getRealType(type: string) { } } -async function processArtifact(artifact: Artifact, artifactFilePath: string): Promise { +async function processArtifact(artifact: Artifact, artifactFilePath: string, cosmosDBAccessToken: string): Promise { const log = (...args: any[]) => console.log(`[${artifact.name}]`, ...args); const match = /^vscode_(?[^_]+)_(?[^_]+)(?:_legacy)?_(?[^_]+)_(?[^_]+)$/.exec(artifact.name); @@ -674,8 +704,7 @@ async function processArtifact(artifact: Artifact, artifactFilePath: string): Pr await retry(async (attempt) => { log(`Creating asset in Cosmos DB (attempt ${attempt})...`); - const aadCredentials = new ClientSecretCredential(e('AZURE_TENANT_ID'), e('AZURE_CLIENT_ID'), e('AZURE_CLIENT_SECRET')); - const client = new CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT'), aadCredentials }); + const client = new CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT')!, tokenProvider: () => Promise.resolve(`type=aad&ver=1.0&sig=${cosmosDBAccessToken}`) }); const scripts = client.database('builds').container(quality).scripts; await scripts.storedProcedure('createAsset').execute('', [commit, asset, true]); }); @@ -691,8 +720,8 @@ async function processArtifact(artifact: Artifact, artifactFilePath: string): Pr // the CDN and finally update the build in Cosmos DB. async function main() { if (!isMainThread) { - const { artifact, artifactFilePath } = workerData; - await processArtifact(artifact, artifactFilePath); + const { artifact, artifactFilePath, cosmosDBAccessToken } = workerData; + await processArtifact(artifact, artifactFilePath, cosmosDBAccessToken); return; } @@ -713,6 +742,7 @@ async function main() { let resultPromise = Promise.resolve[]>([]); const operations: { name: string; operation: Promise }[] = []; + const cosmosDBAccessToken = await getAccessToken(e('AZURE_DOCUMENTDB_ENDPOINT')!, e('AZURE_TENANT_ID')!, e('AZURE_CLIENT_ID')!, e('AZURE_ID_TOKEN')!); while (true) { const [timeline, artifacts] = await Promise.all([retry(() => getPipelineTimeline()), retry(() => getPipelineArtifacts())]); @@ -754,7 +784,7 @@ async function main() { processing.add(artifact.name); const promise = new Promise((resolve, reject) => { - const worker = new Worker(__filename, { workerData: { artifact, artifactFilePath } }); + const worker = new Worker(__filename, { workerData: { artifact, artifactFilePath, cosmosDBAccessToken } }); worker.on('error', reject); worker.on('exit', code => { if (code === 0) { diff --git a/build/azure-pipelines/common/releaseBuild.js b/build/azure-pipelines/common/releaseBuild.js index c2aab2075d0ec..fa69cb4e258a5 100644 --- a/build/azure-pipelines/common/releaseBuild.js +++ b/build/azure-pipelines/common/releaseBuild.js @@ -31,7 +31,7 @@ async function getConfig(client, quality) { async function main(force) { const commit = getEnv('BUILD_SOURCEVERSION'); const quality = getEnv('VSCODE_QUALITY'); - const aadCredentials = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']); + const aadCredentials = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN'])); const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials }); if (!force) { const config = await getConfig(client, quality); diff --git a/build/azure-pipelines/common/releaseBuild.ts b/build/azure-pipelines/common/releaseBuild.ts index 2e8fff04fb409..b7762de7df608 100644 --- a/build/azure-pipelines/common/releaseBuild.ts +++ b/build/azure-pipelines/common/releaseBuild.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ClientSecretCredential } from '@azure/identity'; +import { ClientAssertionCredential } from '@azure/identity'; import { CosmosClient } from '@azure/cosmos'; import { retry } from './retry'; @@ -45,7 +45,7 @@ async function main(force: boolean): Promise { const commit = getEnv('BUILD_SOURCEVERSION'); const quality = getEnv('VSCODE_QUALITY'); - const aadCredentials = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!); + const aadCredentials = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!)); const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials }); if (!force) { diff --git a/build/azure-pipelines/darwin/product-build-darwin-sign.yml b/build/azure-pipelines/darwin/product-build-darwin-sign.yml index 82a1e89f2ab1f..cc0cc06d74001 100644 --- a/build/azure-pipelines/darwin/product-build-darwin-sign.yml +++ b/build/azure-pipelines/darwin/product-build-darwin-sign.yml @@ -16,7 +16,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "ESRP-PKI,esrp-aad-username,esrp-aad-password" diff --git a/build/azure-pipelines/darwin/product-build-darwin-universal.yml b/build/azure-pipelines/darwin/product-build-darwin-universal.yml index e9c532857955e..27408f71432e2 100644 --- a/build/azure-pipelines/darwin/product-build-darwin-universal.yml +++ b/build/azure-pipelines/darwin/product-build-darwin-universal.yml @@ -10,7 +10,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key" diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 6709b9149c3f0..e77000d431b6d 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -28,7 +28,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key" diff --git a/build/azure-pipelines/distro/download-distro.yml b/build/azure-pipelines/distro/download-distro.yml index 92325762a60c3..5c9ed0e56cd3f 100644 --- a/build/azure-pipelines/distro/download-distro.yml +++ b/build/azure-pipelines/distro/download-distro.yml @@ -2,7 +2,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password" diff --git a/build/azure-pipelines/linux/product-build-linux-legacy-server.yml b/build/azure-pipelines/linux/product-build-linux-legacy-server.yml index 63f71890f1994..fcbdb3254f081 100644 --- a/build/azure-pipelines/linux/product-build-linux-legacy-server.yml +++ b/build/azure-pipelines/linux/product-build-linux-legacy-server.yml @@ -18,7 +18,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password" @@ -77,7 +77,7 @@ steps: - task: Docker@1 displayName: "Pull Docker image" inputs: - azureSubscriptionEndpoint: "vscode-builds-subscription" + azureSubscriptionEndpoint: vscode azureContainerRegistry: vscodehub.azurecr.io command: "Run an image" imageName: vscode-linux-build-agent:centos7-devtoolset8-$(VSCODE_ARCH) diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index fe3951c9e5fca..1ff4f300597e1 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -30,7 +30,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password,ESRP-PKI,esrp-aad-username,esrp-aad-password" diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index a196a1117f83b..a053d96033c23 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -143,7 +143,7 @@ variables: - name: PRSS_PROVISION_TENANT_ID value: 72f988bf-86f1-41af-91ab-2d7cd011db47 - name: AZURE_DOCUMENTDB_ENDPOINT - value: https://vscode.documents.azure.com:443/ + value: https://vscode.documents.azure.com/ - name: VSCODE_MIXIN_REPO value: microsoft/vscode-distro - name: skipComponentGovernanceDetection diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index facc7af4bc282..ea71c18ff7d91 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -15,7 +15,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password" @@ -131,33 +131,24 @@ steps: - task: AzureCLI@2 displayName: Fetch secrets inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode scriptType: pscore scriptLocation: inlineScript addSpnToEnvironment: true inlineScript: | Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId" Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId" - Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey" + Write-Host "##vso[task.setvariable variable=AZURE_ID_TOKEN;issecret=true]$env:idToken" - script: | set -e AZURE_STORAGE_ACCOUNT="vscodeweb" \ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \ - AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \ + AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \ node build/azure-pipelines/upload-sourcemaps displayName: Upload sourcemaps to Azure - - script: | - set -e - AZURE_STORAGE_ACCOUNT="ticino" \ - AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \ - AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \ - AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \ - node build/azure-pipelines/upload-sourcemaps - displayName: Upload sourcemaps to Azure (Deprecated) - - script: ./build/azure-pipelines/common/extract-telemetry.sh displayName: Generate lists of telemetry events diff --git a/build/azure-pipelines/product-publish.yml b/build/azure-pipelines/product-publish.yml index 59012a938acca..d33d3d04cf802 100644 --- a/build/azure-pipelines/product-publish.yml +++ b/build/azure-pipelines/product-publish.yml @@ -11,14 +11,14 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password,esrp-aad-username,esrp-aad-password" - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-packages SecretsFilter: "vscode-esrp,c24324f7-e65f-4c45-8702-ed2d4c35df99" @@ -38,14 +38,14 @@ steps: - task: AzureCLI@2 displayName: Fetch secrets inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode scriptType: pscore scriptLocation: inlineScript addSpnToEnvironment: true inlineScript: | Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId" Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId" - Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey" + Write-Host "##vso[task.setvariable variable=AZURE_ID_TOKEN;issecret=true]$env:idToken" - pwsh: | . build/azure-pipelines/win32/exec.ps1 @@ -61,7 +61,7 @@ steps: env: AZURE_TENANT_ID: "$(AZURE_TENANT_ID)" AZURE_CLIENT_ID: "$(AZURE_CLIENT_ID)" - AZURE_CLIENT_SECRET: "$(AZURE_CLIENT_SECRET)" + AZURE_ID_TOKEN: "$(AZURE_ID_TOKEN)" displayName: Create build if it hasn't been created before - pwsh: | @@ -87,7 +87,7 @@ steps: GITHUB_TOKEN: "$(github-distro-mixin-password)" AZURE_TENANT_ID: "$(AZURE_TENANT_ID)" AZURE_CLIENT_ID: "$(AZURE_CLIENT_ID)" - AZURE_CLIENT_SECRET: "$(AZURE_CLIENT_SECRET)" + AZURE_ID_TOKEN: "$(AZURE_ID_TOKEN)" SYSTEM_ACCESSTOKEN: $(System.AccessToken) RELEASE_TENANT_ID: "$(PRSS_RELEASE_TENANT_ID)" RELEASE_CLIENT_ID: "$(PRSS_RELEASE_CLIENT_ID)" diff --git a/build/azure-pipelines/product-release.yml b/build/azure-pipelines/product-release.yml index 8afdcf10053e6..87896f9340b82 100644 --- a/build/azure-pipelines/product-release.yml +++ b/build/azure-pipelines/product-release.yml @@ -12,18 +12,16 @@ steps: - task: AzureCLI@2 displayName: Fetch secrets inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode scriptType: pscore scriptLocation: inlineScript addSpnToEnvironment: true inlineScript: | Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId" Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId" - Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey" + Write-Host "##vso[task.setvariable variable=AZURE_ID_TOKEN;issecret=true]$env:idToken" - - script: | - set -e - npm ci + - script: npm ci workingDirectory: build displayName: Install /build dependencies @@ -31,6 +29,6 @@ steps: set -e AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \ - AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \ - node build/azure-pipelines/common/releaseBuild.js ${{ parameters.VSCODE_RELEASE }} + AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \ + node build/azure-pipelines/common/releaseBuild.js ${{ parameters.VSCODE_RELEASE }} displayName: Release build diff --git a/build/azure-pipelines/upload-cdn.js b/build/azure-pipelines/upload-cdn.js index 62247de06bfd1..8ec40a0108e1b 100644 --- a/build/azure-pipelines/upload-cdn.js +++ b/build/azure-pipelines/upload-cdn.js @@ -13,7 +13,7 @@ const mime = require("mime"); const identity_1 = require("@azure/identity"); const azure = require('gulp-azure-storage'); const commit = process.env['BUILD_SOURCEVERSION']; -const credential = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']); +const credential = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN'])); mime.define({ 'application/typescript': ['ts'], 'application/json': ['code-snippets'], diff --git a/build/azure-pipelines/upload-cdn.ts b/build/azure-pipelines/upload-cdn.ts index 81a4ac14eabb6..a4a5857afe5ca 100644 --- a/build/azure-pipelines/upload-cdn.ts +++ b/build/azure-pipelines/upload-cdn.ts @@ -9,11 +9,11 @@ import * as vfs from 'vinyl-fs'; import * as filter from 'gulp-filter'; import * as gzip from 'gulp-gzip'; import * as mime from 'mime'; -import { ClientSecretCredential } from '@azure/identity'; +import { ClientAssertionCredential } from '@azure/identity'; const azure = require('gulp-azure-storage'); const commit = process.env['BUILD_SOURCEVERSION']; -const credential = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!); +const credential = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!)); mime.define({ 'application/typescript': ['ts'], diff --git a/build/azure-pipelines/upload-nlsmetadata.js b/build/azure-pipelines/upload-nlsmetadata.js index 5b6cd3ed1fd55..de75dcb8b3ab0 100644 --- a/build/azure-pipelines/upload-nlsmetadata.js +++ b/build/azure-pipelines/upload-nlsmetadata.js @@ -13,7 +13,7 @@ const path = require("path"); const fs_1 = require("fs"); const azure = require('gulp-azure-storage'); const commit = process.env['BUILD_SOURCEVERSION']; -const credential = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']); +const credential = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN'])); function main() { return new Promise((c, e) => { const combinedMetadataJson = es.merge( diff --git a/build/azure-pipelines/upload-nlsmetadata.ts b/build/azure-pipelines/upload-nlsmetadata.ts index 030cc8f0e5a6c..89a9eb6c536d9 100644 --- a/build/azure-pipelines/upload-nlsmetadata.ts +++ b/build/azure-pipelines/upload-nlsmetadata.ts @@ -8,13 +8,13 @@ import * as Vinyl from 'vinyl'; import * as vfs from 'vinyl-fs'; import * as merge from 'gulp-merge-json'; import * as gzip from 'gulp-gzip'; -import { ClientSecretCredential } from '@azure/identity'; +import { ClientAssertionCredential } from '@azure/identity'; import path = require('path'); import { readFileSync } from 'fs'; const azure = require('gulp-azure-storage'); const commit = process.env['BUILD_SOURCEVERSION']; -const credential = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!); +const credential = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!)); interface NlsMetadata { keys: { [module: string]: string }; diff --git a/build/azure-pipelines/upload-sourcemaps.js b/build/azure-pipelines/upload-sourcemaps.js index 83c1cae596d51..6f5f73fb8b0e2 100644 --- a/build/azure-pipelines/upload-sourcemaps.js +++ b/build/azure-pipelines/upload-sourcemaps.js @@ -14,7 +14,7 @@ const identity_1 = require("@azure/identity"); const azure = require('gulp-azure-storage'); const root = path.dirname(path.dirname(__dirname)); const commit = process.env['BUILD_SOURCEVERSION']; -const credential = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']); +const credential = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN'])); // optionally allow to pass in explicit base/maps to upload const [, , base, maps] = process.argv; function src(base, maps = `${base}/**/*.map`) { diff --git a/build/azure-pipelines/upload-sourcemaps.ts b/build/azure-pipelines/upload-sourcemaps.ts index 8e148c6095f2c..2eb5e69698305 100644 --- a/build/azure-pipelines/upload-sourcemaps.ts +++ b/build/azure-pipelines/upload-sourcemaps.ts @@ -10,12 +10,12 @@ import * as vfs from 'vinyl-fs'; import * as util from '../lib/util'; // @ts-ignore import * as deps from '../lib/dependencies'; -import { ClientSecretCredential } from '@azure/identity'; +import { ClientAssertionCredential } from '@azure/identity'; const azure = require('gulp-azure-storage'); const root = path.dirname(path.dirname(__dirname)); const commit = process.env['BUILD_SOURCEVERSION']; -const credential = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!); +const credential = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!)); // optionally allow to pass in explicit base/maps to upload const [, , base, maps] = process.argv; diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index 3866dc5cf8124..e0e91c1c58985 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -10,7 +10,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password" @@ -113,21 +113,21 @@ steps: - task: AzureCLI@2 displayName: Fetch secrets from Azure inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode scriptType: pscore scriptLocation: inlineScript addSpnToEnvironment: true inlineScript: | Write-Host "##vso[task.setvariable variable=AZURE_TENANT_ID]$env:tenantId" Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_ID]$env:servicePrincipalId" - Write-Host "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]$env:servicePrincipalKey" + Write-Host "##vso[task.setvariable variable=AZURE_ID_TOKEN;issecret=true]$env:idToken" - script: | set -e AZURE_STORAGE_ACCOUNT="vscodeweb" \ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \ - AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \ + AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \ node build/azure-pipelines/upload-cdn displayName: Upload to CDN @@ -136,7 +136,7 @@ steps: AZURE_STORAGE_ACCOUNT="vscodeweb" \ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \ - AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \ + AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \ node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.main.js.map displayName: Upload sourcemaps (Web Main) @@ -145,28 +145,16 @@ steps: AZURE_STORAGE_ACCOUNT="vscodeweb" \ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \ - AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \ + AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \ node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.main.internal.js.map displayName: Upload sourcemaps (Web Internal) - # upload only the workbench.web.main.js source maps because - # we just compiled these bits in the previous step and the - # general task to upload source maps has already been run - - script: | - set -e - AZURE_STORAGE_ACCOUNT="ticino" \ - AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \ - AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \ - AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \ - node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.main.js.map - displayName: Upload sourcemaps (Deprecated) - - script: | set -e AZURE_STORAGE_ACCOUNT="vscodeweb" \ AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \ AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \ - AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \ + AZURE_ID_TOKEN="$(AZURE_ID_TOKEN)" \ node build/azure-pipelines/upload-nlsmetadata displayName: Upload NLS Metadata diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index f52bf07de0847..a7d64ede336f4 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -35,7 +35,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password,ESRP-PKI,esrp-aad-username,esrp-aad-password" diff --git a/build/azure-pipelines/win32/sdl-scan-win32.yml b/build/azure-pipelines/win32/sdl-scan-win32.yml index ddec05386201b..33bfaf10289a3 100644 --- a/build/azure-pipelines/win32/sdl-scan-win32.yml +++ b/build/azure-pipelines/win32/sdl-scan-win32.yml @@ -21,7 +21,7 @@ steps: - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: - azureSubscription: "vscode-builds-subscription" + azureSubscription: vscode KeyVaultName: vscode-build-secrets SecretsFilter: "github-distro-mixin-password"