From 1151f55d5356be66526cbe8be9f302879b9a91fe Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 17 Aug 2022 09:20:15 +0530 Subject: [PATCH] Client Telemetry : Refactors code to compute hash of VM ID and Process Name information (#3376) * hashed vmid and processname * appended hashedvmid * dummycommit * use string format * renamed util class name * fix refrence Co-authored-by: Sourabh Jain --- .../src/Telemetry/ClientTelemetry.cs | 3 +- .../src/Telemetry/ClientTelemetryOptions.cs | 1 + .../src/Telemetry/Compute.cs | 3 +- .../src/Telemetry/VmMetadataApiHandler.cs | 34 ++++------------- .../src/Util/HashingExtension.cs | 38 +++++++++++++++++++ .../ClientTelemetryTests.cs | 7 ++-- .../VmMetadataApiHandlerTest.cs | 9 +++-- 7 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Util/HashingExtension.cs diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs index 43f8cb841a..e2d8ac0b93 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs @@ -19,6 +19,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry using Microsoft.Azure.Documents.Collections; using Microsoft.Azure.Documents.Rntbd; using Newtonsoft.Json; + using Util; /// /// This class collects and send all the telemetry information. @@ -99,7 +100,7 @@ private ClientTelemetry( this.clientTelemetryInfo = new ClientTelemetryProperties( clientId: clientId, - processId: System.Diagnostics.Process.GetCurrentProcess().ProcessName, + processId: HashingExtension.ComputeHash(System.Diagnostics.Process.GetCurrentProcess().ProcessName), userAgent: userAgent, connectionMode: connectionMode, preferredRegions: preferredRegions, diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs index e8dc0cbc13..cb090a0c0c 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Documents; using Newtonsoft.Json; + using Util; internal static class ClientTelemetryOptions { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Compute.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Compute.cs index 03d2cdb40f..b09af55cce 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Compute.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System; using Newtonsoft.Json; + using Util; [Serializable] internal sealed class Compute @@ -24,7 +25,7 @@ public Compute( this.AzEnvironment = azEnvironment; this.OSType = oSType; this.VMSize = vMSize; - this.VMId = "vmId:" + vMId; + this.VMId = $"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash(vMId)}"; } [JsonProperty(PropertyName = "location")] diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs b/Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs index 9dbebeb1e6..e8c4a802ef 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs @@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Documents; using Newtonsoft.Json.Linq; + using Util; /// /// Task to collect virtual machine metadata information. using instance metedata service API. @@ -20,7 +21,12 @@ namespace Microsoft.Azure.Cosmos.Telemetry /// internal static class VmMetadataApiHandler { + internal const string HashedMachineNamePrefix = "hashedMachineName:"; + internal const string HashedVmIdPrefix = "hashedVmId:"; + internal const string UuidPrefix = "uuid:"; + internal static readonly Uri vmMetadataEndpointUrl = new ("http://169.254.169.254/metadata/instance?api-version=2020-06-01"); + private static readonly string nonAzureCloud = "NonAzureVM"; private static readonly object lockObject = new object(); @@ -139,42 +145,18 @@ internal static string GetCloudInformation() return VmMetadataApiHandler.azMetadata?.Compute?.AzEnvironment ?? VmMetadataApiHandler.nonAzureCloud; } - /// - /// Hash a passed Value - /// - /// - /// hashed Value - internal static string ComputeHash(string rawData) - { - if (string.IsNullOrEmpty(rawData)) - { - throw new ArgumentNullException(nameof(rawData)); - } - - // Create a SHA256 - using (SHA256 sha256Hash = SHA256.Create()) - { - // ComputeHash - returns byte array - byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData)); - Array.Resize(ref bytes, 16); - - // Convert byte array to a string - return new Guid(bytes).ToString(); - } - } - private static readonly Lazy uniqueId = new Lazy(() => { try { - return "hashedMachineName:" + VmMetadataApiHandler.ComputeHash(Environment.MachineName); + return $"{VmMetadataApiHandler.HashedMachineNamePrefix}{HashingExtension.ComputeHash(Environment.MachineName)}"; } catch (Exception ex) { DefaultTrace.TraceWarning("Error while generating hashed machine name " + ex.Message); } - return "uuid:" + Guid.NewGuid().ToString(); + return $"{VmMetadataApiHandler.UuidPrefix}{Guid.NewGuid()}"; }); } diff --git a/Microsoft.Azure.Cosmos/src/Util/HashingExtension.cs b/Microsoft.Azure.Cosmos/src/Util/HashingExtension.cs new file mode 100644 index 0000000000..cd3f190b15 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Util/HashingExtension.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Util +{ + using System; + using System.Collections.Generic; + using System.Security.Cryptography; + using System.Text; + + internal class HashingExtension + { + /// + /// Hash a passed Value + /// + /// + /// hashed Value + internal static string ComputeHash(string rawData) + { + if (string.IsNullOrEmpty(rawData)) + { + throw new ArgumentNullException(nameof(rawData)); + } + + // Create a SHA256 + using (SHA256 sha256Hash = SHA256.Create()) + { + // ComputeHash - returns byte array + byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData)); + Array.Resize(ref bytes, 16); + + // Convert byte array to a string + return new Guid(bytes).ToString(); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs index 06d9e80b86..8ce2aa9327 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs @@ -23,6 +23,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Documents.Rntbd; using System.Globalization; using System.Linq; + using Cosmos.Util; [TestClass] public class ClientTelemetryTests : BaseCosmosClientHelper @@ -935,6 +936,7 @@ private static void AssertAccountLevelInformation( Assert.IsNull(telemetryInfo.AcceleratedNetworking); Assert.IsNotNull(telemetryInfo.ClientId); Assert.IsNotNull(telemetryInfo.ProcessId); + Assert.AreEqual(HashingExtension.ComputeHash(System.Diagnostics.Process.GetCurrentProcess().ProcessName), telemetryInfo.ProcessId); Assert.IsNotNull(telemetryInfo.UserAgent); Assert.IsNotNull(telemetryInfo.ConnectionMode); @@ -948,15 +950,14 @@ private static void AssertAccountLevelInformation( { if (isAzureInstance.Value) { - Assert.AreEqual("vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", machineId.First(), $"Generated Machine id is : {machineId.First()}"); + Assert.AreEqual($"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash("d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd")}", machineId.First(), $"Generated Machine id is : {machineId.First()}"); } else { - Assert.AreNotEqual("vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", machineId.First(), $"Generated Machine id is : {machineId.First()}"); + Assert.AreNotEqual($"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash("d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd")}", machineId.First(), $"Generated Machine id is : {machineId.First()}"); Assert.AreEqual(1, machineId.Count, $"Multiple Machine Id has been generated i.e {JsonConvert.SerializeObject(machineId)}"); } } - } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/VmMetadataApiHandlerTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/VmMetadataApiHandlerTest.cs index ea600dda3c..ed25aa72eb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/VmMetadataApiHandlerTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/VmMetadataApiHandlerTest.cs @@ -18,6 +18,7 @@ namespace Microsoft.Azure.Cosmos using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Newtonsoft.Json; + using Util; [TestClass] public class VmMetadataApiHandlerTest @@ -56,7 +57,7 @@ static Task sendFunc(HttpRequestMessage request, Cancellati VmMetadataApiHandler.TryInitialize(cosmoshttpClient); await Task.Delay(2000); - Assert.AreEqual("vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", VmMetadataApiHandler.GetMachineId()); + Assert.AreEqual($"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash("d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd")}", VmMetadataApiHandler.GetMachineId()); Assert.AreEqual(VmMetadataApiHandler.GetMachineRegion(), "eastus"); } @@ -88,7 +89,7 @@ static Task sendFunc(HttpRequestMessage request, Cancellati [TestMethod] public async Task GetHashedMachineNameAsMachineIdTest() { - string expectedMachineId = "hashedMachineName:" + VmMetadataApiHandler.ComputeHash(Environment.MachineName); + string expectedMachineId = VmMetadataApiHandler.HashedMachineNamePrefix + HashingExtension.ComputeHash(Environment.MachineName); static Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) { throw new Exception("error while making API call"); }; @@ -105,7 +106,7 @@ public async Task GetHashedMachineNameAsMachineIdTest() [TestMethod] public void ComputeHashTest() { - string hashedValue = VmMetadataApiHandler.ComputeHash("abc"); + string hashedValue = HashingExtension.ComputeHash("abc"); Assert.AreEqual("bf1678ba-018f-eacf-4141-40de5dae2223", hashedValue); } @@ -128,7 +129,7 @@ public async Task ParseAzureVMMetadataTest() Assert.AreEqual("AzurePublicCloud", metadata.Compute.AzEnvironment); Assert.AreEqual("Linux", metadata.Compute.OSType); Assert.AreEqual("Standard_D2s_v3", metadata.Compute.VMSize); - Assert.AreEqual("vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", metadata.Compute.VMId); + Assert.AreEqual($"{VmMetadataApiHandler.HashedVmIdPrefix}{HashingExtension.ComputeHash("d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd")}", metadata.Compute.VMId); } [TestMethod]