| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- "use strict";
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // Licensed under the MIT License. See License.txt in the project root for license information.
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- const ms_rest_js_1 = require("@azure/ms-rest-js");
- const login_1 = require("../login");
- /**
- * Describes the credentials by retrieving token via Azure CLI.
- */
- class AzureCliCredentials {
- constructor(subscriptionInfo, tokenInfo,
- // tslint:disable-next-line: no-inferrable-types
- resource = "https://management.azure.com") {
- /**
- * Azure resource endpoints.
- * - Defaults to Azure Resource Manager from environment: AzureCloud. "https://management.azure.com"
- * - For Azure KeyVault: "https://vault.azure.net"
- * - For Azure Batch: "https://batch.core.windows.net"
- * - For Azure Active Directory Graph: "https://graph.windows.net"
- *
- * To get the resource for other clouds:
- * - `az cloud list`
- */
- // tslint:disable-next-line: no-inferrable-types
- this.resource = "https://management.azure.com";
- /**
- * The number of seconds within which it is good to renew the token.
- * A constant set to 270 seconds (4.5 minutes).
- */
- this._tokenRenewalMarginInSeconds = 270;
- this.subscriptionInfo = subscriptionInfo;
- this.tokenInfo = tokenInfo;
- this.resource = resource;
- }
- /**
- * Tries to get the new token from Azure CLI, if the token has expired or the subscription has
- * changed else uses the cached accessToken.
- * @return The tokenResponse (tokenType and accessToken are the two important properties).
- */
- getToken() {
- return __awaiter(this, void 0, void 0, function* () {
- if (this._hasTokenExpired() || this._hasSubscriptionChanged() || this._hasResourceChanged()) {
- try {
- // refresh the access token
- this.tokenInfo = yield AzureCliCredentials.getAccessToken({
- subscriptionIdOrName: this.subscriptionInfo.id,
- resource: this.resource
- });
- }
- catch (err) {
- throw new Error(`An error occurred while refreshing the new access ` +
- `token:${err.stderr ? err.stderr : err.message}`);
- }
- }
- const result = {
- accessToken: this.tokenInfo.accessToken,
- tokenType: this.tokenInfo.tokenType,
- expiresOn: this.tokenInfo.expiresOn,
- tenantId: this.tokenInfo.tenant
- };
- return result;
- });
- }
- /**
- * Signs a request with the Authentication header.
- * @param The request to be signed.
- */
- signRequest(webResource) {
- return __awaiter(this, void 0, void 0, function* () {
- const tokenResponse = yield this.getToken();
- webResource.headers.set(ms_rest_js_1.Constants.HeaderConstants.AUTHORIZATION, `${tokenResponse.tokenType} ${tokenResponse.accessToken}`);
- return Promise.resolve(webResource);
- });
- }
- _hasTokenExpired() {
- let result = true;
- const now = Math.floor(Date.now() / 1000);
- if (this.tokenInfo.expiresOn &&
- this.tokenInfo.expiresOn instanceof Date &&
- Math.floor(this.tokenInfo.expiresOn.getTime() / 1000) - now > this._tokenRenewalMarginInSeconds) {
- result = false;
- }
- return result;
- }
- _hasSubscriptionChanged() {
- return this.subscriptionInfo.id !== this.tokenInfo.subscription;
- }
- _parseToken() {
- try {
- const base64Url = this.tokenInfo.accessToken.split(".")[1];
- const base64 = decodeURIComponent(Buffer.from(base64Url, "base64").toString("binary").split("").map((c) => {
- return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
- }).join(""));
- return JSON.parse(base64);
- }
- catch (err) {
- const msg = `An error occurred while parsing the access token: ${err.stack}`;
- throw new Error(msg);
- }
- }
- _isAzureResourceManagerEndpoint(newResource, currentResource) {
- if (newResource.endsWith("/"))
- newResource = newResource.slice(0, -1);
- if (currentResource.endsWith("/"))
- currentResource = currentResource.slice(0, -1);
- return (newResource === "https://management.core.windows.net" &&
- currentResource === "https://management.azure.com") ||
- (newResource === "https://management.azure.com" &&
- currentResource === "https://management.core.windows.net");
- }
- _hasResourceChanged() {
- const parsedToken = this._parseToken();
- // normalize the resource string, since it is possible to
- // provide a resource without a trailing slash
- const currentResource = parsedToken.aud && parsedToken.aud.endsWith("/")
- ? parsedToken.aud.slice(0, -1)
- : parsedToken.aud;
- const newResource = this.resource.endsWith("/")
- ? this.resource.slice(0, -1)
- : this.resource;
- const result = this._isAzureResourceManagerEndpoint(newResource, currentResource)
- ? false
- : currentResource !== newResource;
- return result;
- }
- /**
- * Gets the access token for the default or specified subscription.
- * @param options Optional parameters that can be provided to get the access token.
- */
- static getAccessToken(options = {}) {
- return __awaiter(this, void 0, void 0, function* () {
- try {
- let cmd = "account get-access-token";
- if (options.subscriptionIdOrName) {
- cmd += ` -s "${options.subscriptionIdOrName}"`;
- }
- if (options.resource) {
- cmd += ` --resource ${options.resource}`;
- }
- const result = yield login_1.execAz(cmd);
- result.expiresOn = new Date(result.expiresOn);
- return result;
- }
- catch (err) {
- const message = `An error occurred while getting credentials from ` +
- `Azure CLI: ${err.stack}`;
- throw new Error(message);
- }
- });
- }
- /**
- * Gets the subscription from Azure CLI.
- * @param subscriptionIdOrName - The name or id of the subscription for which the information is
- * required.
- */
- static getSubscription(subscriptionIdOrName) {
- return __awaiter(this, void 0, void 0, function* () {
- if (subscriptionIdOrName && (typeof subscriptionIdOrName !== "string" || !subscriptionIdOrName.length)) {
- throw new Error("'subscriptionIdOrName' must be a non-empty string.");
- }
- try {
- let cmd = "account show";
- if (subscriptionIdOrName) {
- cmd += ` -s "${subscriptionIdOrName}"`;
- }
- const result = yield login_1.execAz(cmd);
- return result;
- }
- catch (err) {
- const message = `An error occurred while getting information about the current subscription from ` +
- `Azure CLI: ${err.stack}`;
- throw new Error(message);
- }
- });
- }
- /**
- * Sets the specified subscription as the default subscription for Azure CLI.
- * @param subscriptionIdOrName The name or id of the subsciption that needs to be set as the
- * default subscription.
- */
- static setDefaultSubscription(subscriptionIdOrName) {
- return __awaiter(this, void 0, void 0, function* () {
- try {
- yield login_1.execAz(`account set -s ${subscriptionIdOrName}`);
- }
- catch (err) {
- const message = `An error occurred while setting the current subscription from ` +
- `Azure CLI: ${err.stack}`;
- throw new Error(message);
- }
- });
- }
- /**
- * Returns a list of all the subscriptions from Azure CLI.
- * @param options Optional parameters that can be provided while listing all the subcriptions.
- */
- static listAllSubscriptions(options = {}) {
- return __awaiter(this, void 0, void 0, function* () {
- let subscriptionList = [];
- try {
- let cmd = "account list";
- if (options.all) {
- cmd += " --all";
- }
- if (options.refresh) {
- cmd += "--refresh";
- }
- subscriptionList = yield login_1.execAz(cmd);
- if (subscriptionList && subscriptionList.length) {
- for (const sub of subscriptionList) {
- if (sub.cloudName) {
- sub.environmentName = sub.cloudName;
- delete sub.cloudName;
- }
- }
- }
- return subscriptionList;
- }
- catch (err) {
- const message = `An error occurred while getting a list of all the subscription from ` +
- `Azure CLI: ${err.stack}`;
- throw new Error(message);
- }
- });
- }
- /**
- * Provides credentials that can be used by the JS SDK to interact with Azure via azure cli.
- * **Pre-requisite**
- * - **install azure-cli** . For more information see
- * {@link https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest Install Azure CLI}
- * - **login via `az login`**
- * @param options - Optional parameters that can be provided while creating AzureCliCredentials.
- */
- static create(options = {}) {
- return __awaiter(this, void 0, void 0, function* () {
- const [subscriptinInfo, accessToken] = yield Promise.all([
- AzureCliCredentials.getSubscription(options.subscriptionIdOrName),
- AzureCliCredentials.getAccessToken(options)
- ]);
- return new AzureCliCredentials(subscriptinInfo, accessToken, options.resource);
- });
- }
- }
- exports.AzureCliCredentials = AzureCliCredentials;
- //# sourceMappingURL=azureCliCredentials.js.map
|