Skip to content

Commit 7d80f16

Browse files
authored
use oidc (microsoft#233289)
* use oidc (microsoft#233126) * use oidc * undo dep bump * use ClientAssertionCredential * temporarily disable mangle * adopt oidc * move to new service connection, remove deprecated storage account upload (microsoft#233191) * use longer lived access tokens for cosmosdb auth (microsoft#233255)
1 parent 5d458f8 commit 7d80f16

28 files changed

+120
-86
lines changed

build/azure-pipelines/alpine/product-build-alpine.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ steps:
1010
- task: AzureKeyVault@2
1111
displayName: "Azure Key Vault: Get Secrets"
1212
inputs:
13-
azureSubscription: "vscode-builds-subscription"
13+
azureSubscription: vscode
1414
KeyVaultName: vscode-build-secrets
1515
SecretsFilter: "github-distro-mixin-password"
1616

@@ -59,7 +59,7 @@ steps:
5959

6060
- task: Docker@1
6161
inputs:
62-
azureSubscriptionEndpoint: "vscode-builds-subscription"
62+
azureSubscriptionEndpoint: vscode
6363
azureContainerRegistry: vscodehub.azurecr.io
6464
command: "Run an image"
6565
imageName: "vscode-linux-build-agent:alpine-$(VSCODE_ARCH)"

build/azure-pipelines/cli/cli-darwin-sign.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ steps:
77
- task: AzureKeyVault@2
88
displayName: "Azure Key Vault: Get Secrets"
99
inputs:
10-
azureSubscription: "vscode-builds-subscription"
10+
azureSubscription: vscode
1111
KeyVaultName: vscode-build-secrets
1212
SecretsFilter: "ESRP-PKI,esrp-aad-username,esrp-aad-password"
1313

build/azure-pipelines/cli/cli-win32-sign.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ steps:
77
- task: AzureKeyVault@2
88
displayName: "Azure Key Vault: Get Secrets"
99
inputs:
10-
azureSubscription: "vscode-builds-subscription"
10+
azureSubscription: vscode
1111
KeyVaultName: vscode-build-secrets
1212
SecretsFilter: "ESRP-PKI,esrp-aad-username,esrp-aad-password"
1313

build/azure-pipelines/common/createBuild.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/azure-pipelines/common/createBuild.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { ClientSecretCredential } from '@azure/identity';
6+
import { ClientAssertionCredential } from '@azure/identity';
77
import { CosmosClient } from '@azure/cosmos';
88
import { retry } from './retry';
99

@@ -47,7 +47,7 @@ async function main(): Promise<void> {
4747
updates: {}
4848
};
4949

50-
const aadCredentials = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
50+
const aadCredentials = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!));
5151
const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
5252
const scripts = client.database('builds').container(quality).scripts;
5353
await retry(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]));

build/azure-pipelines/common/publish.js

Lines changed: 33 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/azure-pipelines/common/publish.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,36 @@ class Temp {
4747
}
4848
}
4949

50+
/**
51+
* Gets an access token converted from a WIF/OIDC id token.
52+
* 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.
53+
* Source: https://goodworkaround.com/2021/12/21/another-deep-dive-into-azure-ad-workload-identity-federation-using-github-actions/
54+
*/
55+
export async function getAccessToken(endpoint: string, tenantId: string, clientId: string, idToken: string): Promise<string> {
56+
const body = new URLSearchParams({
57+
scope: `${endpoint}.default`,
58+
client_id: clientId,
59+
grant_type: 'client_credentials',
60+
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
61+
client_assertion: encodeURIComponent(idToken)
62+
});
63+
64+
const response = await fetch(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, {
65+
method: 'POST',
66+
headers: {
67+
'Content-Type': 'application/x-www-form-urlencoded'
68+
},
69+
body: body.toString()
70+
});
71+
72+
if (!response.ok) {
73+
throw new Error(`HTTP error! status: ${response.status}`);
74+
}
75+
76+
const aadToken = await response.json();
77+
return aadToken.access_token;
78+
}
79+
5080
interface RequestOptions {
5181
readonly body?: string;
5282
}
@@ -636,7 +666,7 @@ function getRealType(type: string) {
636666
}
637667
}
638668

639-
async function processArtifact(artifact: Artifact, artifactFilePath: string): Promise<void> {
669+
async function processArtifact(artifact: Artifact, artifactFilePath: string, cosmosDBAccessToken: string): Promise<void> {
640670
const log = (...args: any[]) => console.log(`[${artifact.name}]`, ...args);
641671
const match = /^vscode_(?<product>[^_]+)_(?<os>[^_]+)(?:_legacy)?_(?<arch>[^_]+)_(?<unprocessedType>[^_]+)$/.exec(artifact.name);
642672

@@ -674,8 +704,7 @@ async function processArtifact(artifact: Artifact, artifactFilePath: string): Pr
674704

675705
await retry(async (attempt) => {
676706
log(`Creating asset in Cosmos DB (attempt ${attempt})...`);
677-
const aadCredentials = new ClientSecretCredential(e('AZURE_TENANT_ID'), e('AZURE_CLIENT_ID'), e('AZURE_CLIENT_SECRET'));
678-
const client = new CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT'), aadCredentials });
707+
const client = new CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT')!, tokenProvider: () => Promise.resolve(`type=aad&ver=1.0&sig=${cosmosDBAccessToken}`) });
679708
const scripts = client.database('builds').container(quality).scripts;
680709
await scripts.storedProcedure('createAsset').execute('', [commit, asset, true]);
681710
});
@@ -691,8 +720,8 @@ async function processArtifact(artifact: Artifact, artifactFilePath: string): Pr
691720
// the CDN and finally update the build in Cosmos DB.
692721
async function main() {
693722
if (!isMainThread) {
694-
const { artifact, artifactFilePath } = workerData;
695-
await processArtifact(artifact, artifactFilePath);
723+
const { artifact, artifactFilePath, cosmosDBAccessToken } = workerData;
724+
await processArtifact(artifact, artifactFilePath, cosmosDBAccessToken);
696725
return;
697726
}
698727

@@ -713,6 +742,7 @@ async function main() {
713742

714743
let resultPromise = Promise.resolve<PromiseSettledResult<void>[]>([]);
715744
const operations: { name: string; operation: Promise<void> }[] = [];
745+
const cosmosDBAccessToken = await getAccessToken(e('AZURE_DOCUMENTDB_ENDPOINT')!, e('AZURE_TENANT_ID')!, e('AZURE_CLIENT_ID')!, e('AZURE_ID_TOKEN')!);
716746

717747
while (true) {
718748
const [timeline, artifacts] = await Promise.all([retry(() => getPipelineTimeline()), retry(() => getPipelineArtifacts())]);
@@ -754,7 +784,7 @@ async function main() {
754784

755785
processing.add(artifact.name);
756786
const promise = new Promise<void>((resolve, reject) => {
757-
const worker = new Worker(__filename, { workerData: { artifact, artifactFilePath } });
787+
const worker = new Worker(__filename, { workerData: { artifact, artifactFilePath, cosmosDBAccessToken } });
758788
worker.on('error', reject);
759789
worker.on('exit', code => {
760790
if (code === 0) {

build/azure-pipelines/common/releaseBuild.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/azure-pipelines/common/releaseBuild.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { ClientSecretCredential } from '@azure/identity';
6+
import { ClientAssertionCredential } from '@azure/identity';
77
import { CosmosClient } from '@azure/cosmos';
88
import { retry } from './retry';
99

@@ -45,7 +45,7 @@ async function main(force: boolean): Promise<void> {
4545
const commit = getEnv('BUILD_SOURCEVERSION');
4646
const quality = getEnv('VSCODE_QUALITY');
4747

48-
const aadCredentials = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
48+
const aadCredentials = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!));
4949
const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
5050

5151
if (!force) {

build/azure-pipelines/darwin/product-build-darwin-sign.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ steps:
1616
- task: AzureKeyVault@2
1717
displayName: "Azure Key Vault: Get Secrets"
1818
inputs:
19-
azureSubscription: "vscode-builds-subscription"
19+
azureSubscription: vscode
2020
KeyVaultName: vscode-build-secrets
2121
SecretsFilter: "ESRP-PKI,esrp-aad-username,esrp-aad-password"
2222

0 commit comments

Comments
 (0)