UNPKG

@rushstack/rush-azure-storage-build-cache-plugin

Version:

Rush plugin for Azure storage cloud build cache

173 lines 8 kB
"use strict"; // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. Object.defineProperty(exports, "__esModule", { value: true }); exports.AzureAuthenticationBase = void 0; const identity_1 = require("@azure/identity"); const AdoCodespacesAuthCredential_1 = require("./AdoCodespacesAuthCredential"); const rush_sdk_1 = require("@rushstack/rush-sdk"); const terminal_1 = require("@rushstack/terminal"); /** * @public */ class AzureAuthenticationBase { get _credentialCacheId() { if (!this.__credentialCacheId) { const cacheIdParts = [ this._credentialNameForCache, this._azureEnvironment, ...this._getCacheIdParts() ]; this.__credentialCacheId = cacheIdParts.join('|'); } return this.__credentialCacheId; } constructor(options) { const { azureEnvironment = 'AzurePublicCloud', loginFlow = process.env.CODESPACES === 'true' ? 'AdoCodespacesAuth' : 'VisualStudioCode' } = options; this._azureEnvironment = azureEnvironment; this._credentialUpdateCommandForLogging = options.credentialUpdateCommandForLogging; this._loginFlow = loginFlow; this._failoverOrder = options.loginFlowFailover || { AdoCodespacesAuth: 'VisualStudioCode', VisualStudioCode: 'AzureCli', AzureCli: 'AzureDeveloperCli', AzureDeveloperCli: 'AzurePowerShell', AzurePowerShell: 'InteractiveBrowser', InteractiveBrowser: 'DeviceCode', DeviceCode: undefined }; } async updateCachedCredentialAsync(terminal, credential) { await rush_sdk_1.CredentialCache.usingAsync({ supportEditing: true }, async (credentialsCache) => { credentialsCache.setCacheEntry(this._credentialCacheId, { credential }); await credentialsCache.saveIfModifiedAsync(); }); } /** * Launches an interactive flow to renew a cached credential. * * @param terminal - The terminal to log output to * @param onlyIfExistingCredentialExpiresBefore - If specified, and a cached credential exists, action will only * be taken if the cached credential expires before the specified date. */ async updateCachedCredentialInteractiveAsync(terminal, onlyIfExistingCredentialExpiresBefore) { await rush_sdk_1.CredentialCache.usingAsync({ supportEditing: true }, async (credentialsCache) => { var _a; if (onlyIfExistingCredentialExpiresBefore) { const existingCredentialExpiration = (_a = credentialsCache.tryGetCacheEntry(this._credentialCacheId)) === null || _a === void 0 ? void 0 : _a.expires; if (existingCredentialExpiration && existingCredentialExpiration > onlyIfExistingCredentialExpiresBefore) { return; } } const credential = await this._getCredentialAsync(terminal, this._loginFlow, credentialsCache); credentialsCache.setCacheEntry(this._credentialCacheId, { credential: credential.credentialString, expires: credential.expiresOn, credentialMetadata: credential.credentialMetadata }); await credentialsCache.saveIfModifiedAsync(); }); } async deleteCachedCredentialsAsync(terminal) { await rush_sdk_1.CredentialCache.usingAsync({ supportEditing: true }, async (credentialsCache) => { credentialsCache.deleteCacheEntry(this._credentialCacheId); await credentialsCache.saveIfModifiedAsync(); }); } async tryGetCachedCredentialAsync({ expiredCredentialBehavior, terminal } = { expiredCredentialBehavior: 'throwError' }) { var _a; let cacheEntry; await rush_sdk_1.CredentialCache.usingAsync({ supportEditing: false }, (credentialsCache) => { cacheEntry = credentialsCache.tryGetCacheEntry(this._credentialCacheId); }); const expirationTime = (_a = cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.expires) === null || _a === void 0 ? void 0 : _a.getTime(); if (expirationTime && expirationTime < Date.now()) { if (expiredCredentialBehavior === 'logWarning' || expiredCredentialBehavior === 'throwError') { let errorMessage = `Cached Azure ${this._credentialKindForLogging} credentials have expired.`; if (this._credentialUpdateCommandForLogging) { errorMessage += ` Update the credentials by running "${this._credentialUpdateCommandForLogging}".`; } if (expiredCredentialBehavior === 'logWarning') { terminal.writeWarningLine(errorMessage); } else if (expiredCredentialBehavior === 'throwError') { throw new Error(errorMessage); } } return undefined; } else { return cacheEntry; } } async _getCredentialAsync(terminal, loginFlow, credentialsCache) { var _a; const authorityHost = identity_1.AzureAuthorityHosts[this._azureEnvironment]; if (!authorityHost) { throw new Error(`Unexpected Azure environment: ${this._azureEnvironment}`); } const interactiveCredentialOptions = { ...this._additionalInteractiveCredentialOptions, authorityHost }; const deviceCodeCredentialOptions = { ...this._additionalDeviceCodeCredentialOptions, ...interactiveCredentialOptions, userPromptCallback: (deviceCodeInfo) => { terminal_1.PrintUtilities.printMessageInBox(deviceCodeInfo.message, terminal); } }; const options = { authorityHost }; const priority = new Set([loginFlow]); for (const credType of priority) { const next = (_a = this._failoverOrder) === null || _a === void 0 ? void 0 : _a[credType]; if (next) { priority.add(next); } } const knownCredentialTypes = { DeviceCode: class extends identity_1.DeviceCodeCredential { new(credentialOptions) { return new identity_1.DeviceCodeCredential({ ...deviceCodeCredentialOptions, ...credentialOptions }); } }, InteractiveBrowser: class extends identity_1.InteractiveBrowserCredential { new(credentialOptions) { return new identity_1.InteractiveBrowserCredential({ ...interactiveCredentialOptions, ...credentialOptions }); } }, AdoCodespacesAuth: AdoCodespacesAuthCredential_1.AdoCodespacesAuthCredential, VisualStudioCode: identity_1.VisualStudioCodeCredential, AzureCli: identity_1.AzureCliCredential, AzureDeveloperCli: identity_1.AzureDeveloperCliCredential, AzurePowerShell: identity_1.AzurePowerShellCredential }; const credentials = Array.from(priority, (credType) => new knownCredentialTypes[credType](options)); const tokenCredential = new identity_1.ChainedTokenCredential(...credentials); try { return await this._getCredentialFromTokenAsync(terminal, tokenCredential, credentialsCache); } catch (error) { terminal.writeVerbose(`Failed to get credentials with ${loginFlow}: ${error}`); throw error; } } } exports.AzureAuthenticationBase = AzureAuthenticationBase; //# sourceMappingURL=AzureAuthenticationBase.js.map