From 9ff235d25448ec5dbf20d989fb64a15627187509 Mon Sep 17 00:00:00 2001 From: Hector Hernandez <39923391+hectorhdzg@users.noreply.github.com> Date: Wed, 2 Jun 2021 15:17:43 -0700 Subject: [PATCH] 2.1.0 release (#766) --- Bootstrap/DiagnosticLogger.ts | 2 +- Library/AuthorizationHandler.ts | 34 --------- Library/Config.ts | 3 - Library/QuickPulseSender.ts | 21 +----- Library/QuickPulseStateManager.ts | 6 +- Library/Sender.ts | 26 +------ Library/TelemetryClient.ts | 16 +--- Tests/Library/AuthorizationHandler.tests.ts | 73 ------------------- Tests/Library/Client.tests.ts | 10 --- Tests/Library/Context.tests.ts | 2 +- Tests/Library/QuickPulseStateManager.tests.ts | 57 --------------- Tests/Library/Sender.tests.ts | 69 ------------------ applicationinsights.ts | 2 +- package.json | 2 +- 14 files changed, 9 insertions(+), 314 deletions(-) delete mode 100644 Library/AuthorizationHandler.ts delete mode 100644 Tests/Library/AuthorizationHandler.tests.ts diff --git a/Bootstrap/DiagnosticLogger.ts b/Bootstrap/DiagnosticLogger.ts index e8f313b3..feb8b866 100644 --- a/Bootstrap/DiagnosticLogger.ts +++ b/Bootstrap/DiagnosticLogger.ts @@ -20,7 +20,7 @@ export class DiagnosticLogger { siteName: process.env.WEBSITE_SITE_NAME, ikey: process.env.APPINSIGHTS_INSTRUMENTATIONKEY, extensionVersion: process.env.ApplicationInsightsAgent_EXTENSION_VERSION, - sdkVersion: "2.0.0", + sdkVersion: "2.1.0", subscriptionId: process.env.WEBSITE_OWNER_NAME ? process.env.WEBSITE_OWNER_NAME.split("+")[0] : null, } } diff --git a/Library/AuthorizationHandler.ts b/Library/AuthorizationHandler.ts deleted file mode 100644 index 96634218..00000000 --- a/Library/AuthorizationHandler.ts +++ /dev/null @@ -1,34 +0,0 @@ -import http = require("http"); -import https = require("https"); -import azureCore = require("@azure/core-http"); - -const applicationInsightsResource = "https://monitor.azure.com//.default"; - - -class AuthorizationHandler { - - private _azureTokenPolicy: azureCore.RequestPolicy; - - constructor(credential: azureCore.TokenCredential) { - let scopes: string[] = [applicationInsightsResource]; - let emptyPolicy: azureCore.RequestPolicy = { - sendRequest(httpRequest: azureCore.WebResourceLike): Promise { - return null; - } - }; - this._azureTokenPolicy = azureCore.bearerTokenAuthenticationPolicy(credential, scopes).create(emptyPolicy, new azureCore.RequestPolicyOptions()); - } - - /** - * Applies the Bearer token to the request through the Authorization header. - */ - public async addAuthorizationHeader(requestOptions: http.RequestOptions | https.RequestOptions): Promise { - let authHeaderName = azureCore.Constants.HeaderConstants.AUTHORIZATION; - let webResource = new azureCore.WebResource(); - await this._azureTokenPolicy.sendRequest(webResource); - requestOptions.headers[authHeaderName] = webResource.headers.get(authHeaderName); - } - -} - -export = AuthorizationHandler; diff --git a/Library/Config.ts b/Library/Config.ts index 54706427..405d4edc 100644 --- a/Library/Config.ts +++ b/Library/Config.ts @@ -58,9 +58,6 @@ class Config { /** Disable including legacy headers in outgoing requests, x-ms-request-id */ public ignoreLegacyHeaders?: boolean; - /** AAD TokenCredential to use to authenticate the app */ - public aadTokenCredential?: azureCore.TokenCredential; - private endpointBase: string = Constants.DEFAULT_BREEZE_ENDPOINT; private setCorrelationId: (v: string) => void; private _profileQueryEndpoint: string; diff --git a/Library/QuickPulseSender.ts b/Library/QuickPulseSender.ts index 1ba8b263..eea6e8c3 100644 --- a/Library/QuickPulseSender.ts +++ b/Library/QuickPulseSender.ts @@ -1,6 +1,5 @@ import https = require("https"); -import AuthorizationHandler = require("./AuthorizationHandler"); import Config = require("./Config"); import AutoCollectHttpDependencies = require("../AutoCollection/HttpDependencies"); import Logging = require("./Logging"); @@ -31,12 +30,10 @@ class QuickPulseSender { private _config: Config; private _consecutiveErrors: number; - private _getAuthorizationHandler: (config: Config) => AuthorizationHandler; - constructor(config: Config, getAuthorizationHandler?: (config: Config) => AuthorizationHandler) { + constructor(config: Config) { this._config = config; this._consecutiveErrors = 0; - this._getAuthorizationHandler = getAuthorizationHandler; } public ping(envelope: Contracts.EnvelopeQuickPulse, @@ -88,22 +85,6 @@ class QuickPulseSender { additionalHeaders.forEach(header => options.headers[header.name] = header.value); } - if (postOrPing === "post") { - let authHandler = this._getAuthorizationHandler ? this._getAuthorizationHandler(this._config) : null; - if (authHandler) { - try { - // Add bearer token - await authHandler.addAuthorizationHeader(options); - } - catch (authError) { - let notice = `Failed to get AAD bearer token for the Application. Error:`; - Logging.info(QuickPulseSender.TAG, notice, authError); - // Do not send request to Quickpulse if auth fails, data will be dropped - return; - } - } - } - // HTTPS only if (this._config.httpsAgent) { (options).agent = this._config.httpsAgent; diff --git a/Library/QuickPulseStateManager.ts b/Library/QuickPulseStateManager.ts index 390d4437..5a257ee2 100644 --- a/Library/QuickPulseStateManager.ts +++ b/Library/QuickPulseStateManager.ts @@ -1,4 +1,3 @@ -import AuthorizationHandler = require("./AuthorizationHandler"); import Logging = require("./Logging"); import Config = require("./Config"); import QuickPulseEnvelopeFactory = require("./QuickPulseEnvelopeFactory"); @@ -14,7 +13,6 @@ import * as Contracts from "../Declarations/Contracts"; class QuickPulseStateManager { public config: Config; public context: Context; - public authorizationHandler: AuthorizationHandler; private static MAX_POST_WAIT_TIME = 20000; private static MAX_PING_WAIT_TIME = 60000; @@ -34,10 +32,10 @@ class QuickPulseStateManager { private _redirectedHost: string = null; private _pollingIntervalHint: number = -1; - constructor(config: Config, context?: Context, getAuthorizationHandler?: (config: Config) => AuthorizationHandler) { + constructor(config: Config, context?: Context) { this.config = config; this.context = context || new Context(); - this._sender = new QuickPulseSender(this.config, getAuthorizationHandler); + this._sender = new QuickPulseSender(this.config); this._isEnabled = false; } diff --git a/Library/Sender.ts b/Library/Sender.ts index c6c07254..3b6e7715 100644 --- a/Library/Sender.ts +++ b/Library/Sender.ts @@ -5,7 +5,6 @@ import path = require("path"); import zlib = require("zlib"); import child_process = require("child_process"); -import AuthorizationHandler = require("./AuthorizationHandler"); import Logging = require("./Logging"); import Config = require("./Config") import Contracts = require("../Declarations/Contracts"); @@ -32,7 +31,6 @@ class Sender { private _config: Config; private _onSuccess: (response: string) => void; private _onError: (error: Error) => void; - private _getAuthorizationHandler: (config: Config) => AuthorizationHandler; private _enableDiskRetryMode: boolean; private _numConsecutiveFailures: number; private _numConsecutiveRedirects: number; @@ -43,7 +41,7 @@ class Sender { protected _resendInterval: number; protected _maxBytesOnDisk: number; - constructor(config: Config, getAuthorizationHandler?: (config: Config) => AuthorizationHandler, onSuccess?: (response: string) => void, onError?: (error: Error) => void) { + constructor(config: Config, onSuccess?: (response: string) => void, onError?: (error: Error) => void) { this._config = config; this._onSuccess = onSuccess; this._onError = onError; @@ -53,7 +51,6 @@ class Sender { this._numConsecutiveFailures = 0; this._numConsecutiveRedirects = 0; this._resendTimer = null; - this._getAuthorizationHandler = getAuthorizationHandler; this._fileCleanupTimer = null; // tmpdir is /tmp for *nix and USERDIR/AppData/Local/Temp for Windows this._tempDir = path.join(os.tmpdir(), Sender.TEMPDIR_PREFIX + this._config.instrumentationKey); @@ -121,26 +118,7 @@ class Sender { } }; - let authHandler = this._getAuthorizationHandler ? this._getAuthorizationHandler(this._config) : null; - if (authHandler) { - try { - // Add bearer token - await authHandler.addAuthorizationHeader(options); - } - catch (authError) { - let errorMsg = "Failed to get AAD bearer token for the Application. Error:" + authError.toString(); - // If AAD auth fails do not send to Breeze - if (typeof callback === "function") { - callback(errorMsg); - } - this._storeToDisk(envelopes); - Logging.warn(Sender.TAG, errorMsg); - return; - } - } - let batch: string = ""; - envelopes.forEach(envelope => { var payload: string = this._stringify(envelope); if (typeof payload !== "string") { @@ -283,8 +261,6 @@ class Sender { return ( statusCode === 206 || // Retriable statusCode === 308 || // Permanent Redirect - statusCode === 401 || // Unauthorized - statusCode === 403 || // Forbidden statusCode === 408 || // Timeout statusCode === 429 || // Throttle statusCode === 439 || // Quota diff --git a/Library/TelemetryClient.ts b/Library/TelemetryClient.ts index 6fbce4c4..26454561 100644 --- a/Library/TelemetryClient.ts +++ b/Library/TelemetryClient.ts @@ -3,7 +3,6 @@ import os = require("os"); import azureCore = require("@azure/core-http"); import Config = require("./Config"); -import AuthorizationHandler = require("./AuthorizationHandler"); import Context = require("./Context"); import Contracts = require("../Declarations/Contracts"); import Channel = require("./Channel"); @@ -30,8 +29,6 @@ class TelemetryClient { public commonProperties: { [key: string]: string; }; public channel: Channel; public quickPulseClient: QuickPulseStateManager; - public authorizationHandler: AuthorizationHandler; - /** * Constructs a new client of the client @@ -42,8 +39,7 @@ class TelemetryClient { this.config = config; this.context = new Context(); this.commonProperties = {}; - this.authorizationHandler = null; - var sender = new Sender(this.config, this.getAuthorizationHandler); + var sender = new Sender(this.config); this.channel = new Channel(() => config.disableAppInsights, () => config.maxBatchSize, () => config.maxBatchIntervalMs, sender); } @@ -178,16 +174,6 @@ class TelemetryClient { this._enableAzureProperties = value; } - /** - * Get Authorization handler - */ - public getAuthorizationHandler(config: Config): AuthorizationHandler { - if (config && config.aadTokenCredential) { - return this.authorizationHandler || new AuthorizationHandler(config.aadTokenCredential); - } - return null; - } - /** * Adds telemetry processor to the collection. Telemetry processors will be called one by one * before telemetry item is pushed for sending and in the order they were added. diff --git a/Tests/Library/AuthorizationHandler.tests.ts b/Tests/Library/AuthorizationHandler.tests.ts deleted file mode 100644 index 5fcd7234..00000000 --- a/Tests/Library/AuthorizationHandler.tests.ts +++ /dev/null @@ -1,73 +0,0 @@ -import assert = require("assert"); -import https = require("https"); -import sinon = require("sinon"); -import azureCore = require("@azure/core-http"); - -import AuthorizationHandler = require("../../Library/AuthorizationHandler"); -import Config = require("../../Library/Config"); -import Util = require("../../Library/Util"); - -class TestTokenCredential implements azureCore.TokenCredential { - private _expiresOn: Date; - private _numberOfRefreshs = 0; - - constructor(expiresOn?: Date) { - this._expiresOn = expiresOn || new Date(); - } - - async getToken(scopes: string | string[], options?: any): Promise { - this._numberOfRefreshs++; - return { - token: "testToken" + this._numberOfRefreshs, - expiresOnTimestamp: this._expiresOn - }; - } -} - -describe("Library/AuthorizationHandler", () => { - - var sandbox: sinon.SinonSandbox; - Util.tlsRestrictedAgent = new https.Agent(); - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe("#addAuthorizationHeader()", () => { - it("should add Authorization header to options", async () => { - var config = new Config(""); - config.aadTokenCredential = new TestTokenCredential(); - var handler = new AuthorizationHandler(config.aadTokenCredential); - var options = { - method: "POST", - headers: <{ [key: string]: string }>{ - "Content-Type": "application/x-json-stream" - } - }; - await handler.addAuthorizationHeader(options); - assert.equal(options.headers["authorization"], "Bearer testToken1"); - }); - - it("should refresh token if expired", async () => { - var config = new Config(""); - var tokenCredential = new TestTokenCredential(new Date(new Date().getMilliseconds() - 500)); - config.aadTokenCredential = tokenCredential; - var handler = new AuthorizationHandler(config.aadTokenCredential); - var options = { - method: "POST", - headers: <{ [key: string]: string }>{ - "Content-Type": "application/x-json-stream" - } - }; - await handler.addAuthorizationHeader(options); - assert.equal(options.headers["authorization"], "Bearer testToken1"); - await handler.addAuthorizationHeader(options); - assert.equal(tokenCredential["_numberOfRefreshs"], 2); - assert.equal(options.headers["authorization"], "Bearer testToken2"); - }); - }); -}); diff --git a/Tests/Library/Client.tests.ts b/Tests/Library/Client.tests.ts index bf73febc..c4f07d93 100644 --- a/Tests/Library/Client.tests.ts +++ b/Tests/Library/Client.tests.ts @@ -102,16 +102,6 @@ describe("Library/TelemetryClient", () => { var client = new Client("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); assert.ok(client.channel); }); - - it("should initialize authorization handler", () => { - var client = new Client("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;"); - client.config.aadTokenCredential = { - async getToken(scopes: string | string[], options?: any): Promise { - return { token: "testToken", }; - } - }; - assert.ok(client.getAuthorizationHandler(client.config)); - }); }); describe("#trackEvent()", () => { diff --git a/Tests/Library/Context.tests.ts b/Tests/Library/Context.tests.ts index f4b84f36..89efa513 100644 --- a/Tests/Library/Context.tests.ts +++ b/Tests/Library/Context.tests.ts @@ -55,7 +55,7 @@ describe("Library/Context", () => { it("should set internalSdkVersion to 'node:'", () => { var context = new Context(); // todo: make this less fragile (will need updating on each minor version change) - assert.equal(context.tags[context.keys.internalSdkVersion].substring(0, 9), "node:2.0."); + assert.equal(context.tags[context.keys.internalSdkVersion].substring(0, 9), "node:2.1."); }); it("should correctly set device context", () => { diff --git a/Tests/Library/QuickPulseStateManager.tests.ts b/Tests/Library/QuickPulseStateManager.tests.ts index 9fde0d88..4fa97fa1 100644 --- a/Tests/Library/QuickPulseStateManager.tests.ts +++ b/Tests/Library/QuickPulseStateManager.tests.ts @@ -1,11 +1,9 @@ import assert = require("assert"); import https = require("https"); import sinon = require("sinon"); -import azureCore = require("@azure/core-http"); import QuickPulseClient = require("../../Library/QuickPulseStateManager"); import Contracts = require("../../Declarations/Contracts"); -import AuthorizationHandler = require("../../Library/AuthorizationHandler"); import { IncomingMessage } from "http"; import Config = require("../../Library/Config"); import QuickPulseSender = require("../../Library/QuickPulseSender"); @@ -33,21 +31,6 @@ describe("Library/QuickPulseStateManager", () => { assert.ok(qps["_documents"].length === 0); assert.ok(qps["_collectors"].length === 0); }); - - it("should reuse authorization handler if provided", () => { - var config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;"); - var handler = new AuthorizationHandler({ - async getToken(scopes: string | string[], options?: any): Promise { - return { token: "testToken", }; - } - }); - var getAuthorizationHandler = () => { - return handler; - }; - qps = new QuickPulseClient(config, null, getAuthorizationHandler); - assert.equal(qps["_sender"]["_getAuthorizationHandler"](config), handler); - }); - }); describe("#enable", () => { @@ -269,44 +252,4 @@ describe("Library/QuickPulseStateManager", () => { assert.equal(qps['_pollingIntervalHint'], 5000); }); }); - - describe("#AuthorizationHandler ", () => { - var sandbox: sinon.SinonSandbox; - let envelope: Contracts.EnvelopeQuickPulse = { - Documents: null, - Instance: "", - RoleName: "", - InstrumentationKey: "", - InvariantVersion: 1, - MachineName: "", - Metrics: null, - StreamId: "", - Timestamp: "", - Version: "" - }; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it("should add token if handler present", () => { - var handler = new AuthorizationHandler({ - async getToken(scopes: string | string[], options?: any): Promise { - return { token: "testToken", }; - } - }); - var getAuthorizationHandler = () => { - return handler; - }; - var config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;"); - var addHeaderStub = sandbox.stub(handler, "addAuthorizationHeader"); - let sender = new QuickPulseSender(config, getAuthorizationHandler); - sender.post(envelope, "", () => { }); - assert.ok(addHeaderStub.calledOnce); - }); - }); }); diff --git a/Tests/Library/Sender.tests.ts b/Tests/Library/Sender.tests.ts index 21d203af..cf999602 100644 --- a/Tests/Library/Sender.tests.ts +++ b/Tests/Library/Sender.tests.ts @@ -8,7 +8,6 @@ import Sender = require("../../Library/Sender"); import Config = require("../../Library/Config"); import Constants = require("../../Declarations/Constants"); import Contracts = require("../../Declarations/Contracts"); -import AuthorizationHandler = require("../../Library/AuthorizationHandler"); import Util = require("../../Library/Util"); class SenderMock extends Sender { @@ -233,72 +232,4 @@ describe("Library/Sender", () => { }, 600); }); }); - - describe("#AuthorizationHandler ", () => { - before(() => { - nock("https://dc.services.visualstudio.com") - .post("/v2.1/track", (body: string) => { - return true; - }) - .reply(200, { - itemsAccepted: 1, - itemsReceived: 1, - errors: [] - }) - .persist(); - }); - - var sandbox: sinon.SinonSandbox; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - after(() => { - nock.cleanAll(); - }); - - it("should add token if handler present", () => { - var handler = new AuthorizationHandler({ - async getToken(scopes: string | string[], options?: any): Promise { - return { token: "testToken", }; - } - }); - var getAuthorizationHandler = () => { - return handler; - }; - var config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); - var addHeaderStub = sandbox.stub(handler, "addAuthorizationHeader"); - - var sender = new Sender(config, getAuthorizationHandler); - sender.send([testEnvelope]); - assert.ok(addHeaderStub.calledOnce); - }); - - it("should put telemetry to disk if auth fails", () => { - var handler = new AuthorizationHandler({ - async getToken(scopes: string | string[], options?: any): Promise { - return { token: "testToken", }; - } - }); - var getAuthorizationHandler = () => { - return handler; - }; - var config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;"); - var addHeaderStub = sandbox.stub(handler, "addAuthorizationHeader", () => { throw new Error(); }); - - var sender = new Sender(config, getAuthorizationHandler); - var storeToDiskStub = sandbox.stub(sender, "_storeToDisk"); - let envelope = new Contracts.Envelope(); - envelope.name = "TestEnvelope"; - sender.send([envelope]); - assert.ok(addHeaderStub.calledOnce); - assert.ok(storeToDiskStub.calledOnce); - assert.equal(storeToDiskStub.firstCall.args[0][0].name, "TestEnvelope"); - }); - }); }); diff --git a/applicationinsights.ts b/applicationinsights.ts index 5b555d92..c17358da 100644 --- a/applicationinsights.ts +++ b/applicationinsights.ts @@ -362,7 +362,7 @@ export class Configuration { if (!liveMetricsClient && enable) { // No qps client exists. Create one and prepare it to be enabled at .start() - liveMetricsClient = new QuickPulseClient(defaultClient.config, null, defaultClient.getAuthorizationHandler); + liveMetricsClient = new QuickPulseClient(defaultClient.config, null); _performanceLiveMetrics = new AutoCollectPerformance(liveMetricsClient as any, 1000, true); liveMetricsClient.addCollector(_performanceLiveMetrics); defaultClient.quickPulseClient = liveMetricsClient; // Need this so we can forward all manual tracks to live metrics via PerformanceMetricsTelemetryProcessor diff --git a/package.json b/package.json index b9f1b42f..af9dbefc 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "author": "Microsoft Application Insights Team", "license": "MIT", "bugs": "https://github.com/microsoft/ApplicationInsights-node.js/issues", - "version": "2.0.0", + "version": "2.1.0", "description": "Microsoft Application Insights module for Node.js", "repository": { "type": "git",