From 124a010fdbfa71f75b0177c49d388a0c283531c6 Mon Sep 17 00:00:00 2001 From: Jeremy Meng Date: Tue, 6 Aug 2024 16:38:38 -0700 Subject: [PATCH] [rush-azure-storage-build-cache-plugin] Add support for auth via AzurePipelinesCredential - bump dependency `@azure/identity` version to `~4.4.1` - add a login flow of `'AzurePipeline'` --- ...-pipeline-credential_2024-08-07-00-13.json | 10 +++++++ .../config/subspaces/default/pnpm-lock.yaml | 14 +++++----- .../config/subspaces/default/repo-state.json | 2 +- .../package.json | 2 +- .../src/AzureAuthenticationBase.ts | 26 ++++++++++++++++++- 5 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 common/changes/@microsoft/rush/azure-pipeline-credential_2024-08-07-00-13.json diff --git a/common/changes/@microsoft/rush/azure-pipeline-credential_2024-08-07-00-13.json b/common/changes/@microsoft/rush/azure-pipeline-credential_2024-08-07-00-13.json new file mode 100644 index 00000000000..ff150722cb1 --- /dev/null +++ b/common/changes/@microsoft/rush/azure-pipeline-credential_2024-08-07-00-13.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/rush", + "comment": "Add AzurePipelinesCredential support to rush azure storage build cache", + "type": "none" + } + ], + "packageName": "@microsoft/rush" +} \ No newline at end of file diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index a58e39fe4b6..b3c751a5387 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -3946,8 +3946,8 @@ importers: ../../../rush-plugins/rush-azure-storage-build-cache-plugin: dependencies: '@azure/identity': - specifier: ~4.2.1 - version: 4.2.1 + specifier: ~4.4.1 + version: 4.4.1 '@azure/storage-blob': specifier: ~12.17.0 version: 12.17.0 @@ -5120,8 +5120,8 @@ packages: tslib: 2.6.2 dev: false - /@azure/core-client@1.9.0: - resolution: {integrity: sha512-x50SSD7bbG5wen3tMDI2oWVSAjt1K1xw6JZSnc6239RmBwqLJF9dPsKsh9w0Rzh5+mGpsu9FDu3DlsT0lo1+Uw==} + /@azure/core-client@1.9.2: + resolution: {integrity: sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==} engines: {node: '>=18.0.0'} dependencies: '@azure/abort-controller': 2.1.0 @@ -5213,13 +5213,13 @@ packages: tslib: 2.6.2 dev: false - /@azure/identity@4.2.1: - resolution: {integrity: sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q==} + /@azure/identity@4.4.1: + resolution: {integrity: sha512-DwnG4cKFEM7S3T+9u05NstXU/HN0dk45kPOinUyNKsn5VWwpXd9sbPKEg6kgJzGbm1lMuhx9o31PVbCtM5sfBA==} engines: {node: '>=18.0.0'} dependencies: '@azure/abort-controller': 1.1.0 '@azure/core-auth': 1.7.0 - '@azure/core-client': 1.9.0 + '@azure/core-client': 1.9.2 '@azure/core-rest-pipeline': 1.15.0 '@azure/core-tracing': 1.1.0 '@azure/core-util': 1.8.0 diff --git a/common/config/subspaces/default/repo-state.json b/common/config/subspaces/default/repo-state.json index 470d4a9a7e4..4c44f4b15f4 100644 --- a/common/config/subspaces/default/repo-state.json +++ b/common/config/subspaces/default/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "b57605a120edc7c8740eb54e092f24d026f7819f", + "pnpmShrinkwrapHash": "37b11d6b25526493014e83332b2e15fe9d177f24", "preferredVersionsHash": "ce857ea0536b894ec8f346aaea08cfd85a5af648" } diff --git a/rush-plugins/rush-azure-storage-build-cache-plugin/package.json b/rush-plugins/rush-azure-storage-build-cache-plugin/package.json index 33778d715d9..2ba5d0b8597 100644 --- a/rush-plugins/rush-azure-storage-build-cache-plugin/package.json +++ b/rush-plugins/rush-azure-storage-build-cache-plugin/package.json @@ -18,7 +18,7 @@ "_phase:test": "heft run --only test -- --clean" }, "dependencies": { - "@azure/identity": "~4.2.1", + "@azure/identity": "~4.4.1", "@azure/storage-blob": "~12.17.0", "@rushstack/node-core-library": "workspace:*", "@rushstack/rush-sdk": "workspace:*", diff --git a/rush-plugins/rush-azure-storage-build-cache-plugin/src/AzureAuthenticationBase.ts b/rush-plugins/rush-azure-storage-build-cache-plugin/src/AzureAuthenticationBase.ts index aa3eb2c254b..b8164659d1a 100644 --- a/rush-plugins/rush-azure-storage-build-cache-plugin/src/AzureAuthenticationBase.ts +++ b/rush-plugins/rush-azure-storage-build-cache-plugin/src/AzureAuthenticationBase.ts @@ -2,6 +2,7 @@ // See LICENSE in the project root for license information. import { + AzurePipelinesCredential, DeviceCodeCredential, type DeviceCodeInfo, AzureAuthorityHosts, @@ -80,7 +81,7 @@ export type AzureEnvironmentName = keyof typeof AzureAuthorityHosts; /** * @public */ -export type LoginFlowType = 'DeviceCode' | 'InteractiveBrowser' | 'AdoCodespacesAuth'; +export type LoginFlowType = 'DeviceCode' | 'InteractiveBrowser' | 'AdoCodespacesAuth' | 'AzurePipelines'; /** * @public @@ -150,6 +151,7 @@ export abstract class AzureAuthenticationBase { this._credentialUpdateCommandForLogging = options.credentialUpdateCommandForLogging; this._loginFlow = options.loginFlow || 'DeviceCode'; this._failoverOrder = options.loginFlowFailover || { + AzurePipelines: 'AdoCodespacesAuth', AdoCodespacesAuth: 'InteractiveBrowser', InteractiveBrowser: 'DeviceCode', DeviceCode: undefined @@ -300,6 +302,28 @@ export abstract class AzureAuthenticationBase { tokenCredential = new AdoCodespacesAuthCredential(); break; } + case 'AzurePipelines': { + const systemAccessToken = process.env.SYSTEM_ACCESSTOKEN; + // If we have a system access token, we are in Azure Pipelines + if (systemAccessToken) { + const serviceConnectionID = process.env.AZURESUBSCRIPTION_SERVICE_CONNECTION_ID; + const clientID = process.env.AZURESUBSCRIPTION_CLIENT_ID; + const tenantID = process.env.AZURESUBSCRIPTION_TENANT_ID; + if (serviceConnectionID && clientID && tenantID) { + tokenCredential = new AzurePipelinesCredential( + tenantID, + clientID, + serviceConnectionID, + systemAccessToken + ); + } else { + throw new Error( + `Running in Azure Pipelines environment. Missing environment variables: serviceConnectionID: ${serviceConnectionID}, tenantID: ${tenantID}, clientID: ${clientID}` + ); + } + } + throw new Error(`SYSTEM_ACCESSTOKEN is not set while attempting '${loginFlow}' login flow`); + } case 'InteractiveBrowser': { tokenCredential = new InteractiveBrowserCredential(interactiveCredentialOptions); break;