Skip to content

Commit

Permalink
Adding fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
anna-git committed Nov 19, 2024
1 parent 6cd49e6 commit 655c1a5
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>
#nullable enable

#if !NETFRAMEWORK
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Security.Claims;
using Datadog.Trace.AppSec;
using Datadog.Trace.AppSec.Coordinator;
using Datadog.Trace.ClrProfiler.CallTarget;
using Datadog.Trace.Configuration;
using Datadog.Trace.Telemetry;
using Datadog.Trace.Telemetry.Metrics;

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AspNetCore.UserEvents
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,35 @@
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using Datadog.Trace.Logging;
using Datadog.Trace.Telemetry;
using Datadog.Trace.Telemetry.Metrics;

namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AspNetCore.UserEvents;

internal static class UserEventsCommon
{
private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(UserEventsCommon));

internal static string? GetId(IIdentityUser? user) => user?.Id?.ToString();

internal static string? GetLogin(IIdentityUser? user) => user?.UserName ?? user?.Email;

internal static unsafe string? Anonymize(string id)
internal static unsafe string Anonymize(string id)
{
using var hash = SHA256.Create();
var byteArray = hash.ComputeHash(Encoding.UTF8.GetBytes(id));

// spec says take first half of the hash
const int bytesToUse = 16;

if (byteArray.Length >= bytesToUse)
var encodedBytes = Encoding.UTF8.GetBytes(id);
#if NET6_0_OR_GREATER
var destination = new Span<byte>(new byte[32]);
var successfullyHashed = SHA256.TryHashData(new ReadOnlySpan<byte>(encodedBytes), destination, out var bytesWritten);
#else
using var hash = SHA256.Create();
var destination = hash.ComputeHash(encodedBytes);
var bytesWritten = destination.Length;
var successfullyHashed = bytesWritten > bytesToUse;
#endif
if (successfullyHashed)
{
// we want to end up with a string of the form anon_0c76692372ebf01a7da6e9570fb7d0a1
// 37 is 5 prefix character plus 32 hexadecimal digits (presenting 16 bytes)
Expand All @@ -41,7 +50,7 @@ internal static class UserEventsCommon
stringChars[4] = '_';
for (var iBytes = 0; iBytes < bytesToUse; iBytes++)
{
var b = byteArray[iBytes];
var b = destination[iBytes];
var iChars = iBytes * 2;
stringChars[iChars + 5] = ByteDigitToChar(b >> 4);
stringChars[iChars + 6] = ByteDigitToChar(b & 0x0F);
Expand All @@ -50,7 +59,8 @@ internal static class UserEventsCommon
return new string(stringChars, 0, 37);
}

return null;
Log.Warning<int>("Couldn't anonymize user information (login or id), byteArray length was {BytesWritten}", bytesWritten);
return string.Empty;
}

internal static void RecordMetricsIfNotFound(bool foundUserId, bool foundLogin)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,40 +70,45 @@ internal static TReturn OnAsyncMethodEnd<TTarget, TReturn>(TTarget instance, TRe
{
var userId = UserEventsCommon.GetId(user);
var userLogin = UserEventsCommon.GetLogin(user);
if (userId is null)
{
TelemetryFactory.Metrics.RecordCountMissingUserId(MetricTags.AuthenticationFramework.AspNetCoreIdentity);
return returnValue;
}

var setTag = TaggingUtils.GetSpanSetter(span, out _);
var tryAddTag = TaggingUtils.GetSpanSetter(span, out _, replaceIfExists: false);

var foundUserId = !string.IsNullOrEmpty(userId);
var foundLogin = !string.IsNullOrEmpty(userLogin);
UserEventsCommon.RecordMetricsIfNotFound(foundUserId, foundLogin);
if (returnValue.Succeeded)
{
setTag(Tags.AppSec.EventsUsers.SignUpEvent.Track, "true");
Func<string, string> processPii;
string successAutoMode;
if (security.IsAnonUserTrackingMode)
{
userId = UserEventsCommon.Anonymize(userId);
if (!string.IsNullOrEmpty(userLogin))
{
userLogin = UserEventsCommon.Anonymize(userLogin!);
tryAddTag(Tags.AppSec.EventsUsers.SignUpEvent.Login, userLogin!);
tryAddTag(Tags.AppSec.EventsUsers.InternalLogin, userLogin!);
}

setTag(Tags.AppSec.EventsUsers.SignUpEvent.AutoMode, SecuritySettings.UserTrackingAnonMode);
processPii = UserEventsCommon.Anonymize;
successAutoMode = SecuritySettings.UserTrackingAnonMode;
}
else
{
tryAddTag(Tags.AppSec.EventsUsers.SignUpEvent.Login, userLogin!);
tryAddTag(Tags.AppSec.EventsUsers.InternalLogin, userLogin!);

setTag(Tags.AppSec.EventsUsers.SignUpEvent.AutoMode, SecuritySettings.UserTrackingIdentMode);
processPii = val => val;
successAutoMode = SecuritySettings.UserTrackingIdentMode;
}

var setTag = TaggingUtils.GetSpanSetter(span, out _);
var tryAddTag = TaggingUtils.GetSpanSetter(span, out _, replaceIfExists: false);

setTag(Tags.AppSec.EventsUsers.SignUpEvent.Track, "true");
setTag(Tags.AppSec.EventsUsers.SignUpEvent.AutoMode, successAutoMode);
tryAddTag(Tags.AppSec.EventsUsers.SignUpEvent.UserId, userId!);
tryAddTag(Tags.AppSec.EventsUsers.InternalUserId, userId!);

if (foundUserId)
{
var processedUserId = processPii(userId!);
tryAddTag(Tags.AppSec.EventsUsers.SignUpEvent.UserId, processedUserId);
tryAddTag(Tags.AppSec.EventsUsers.InternalUserId, processedUserId);
}

if (foundLogin)
{
var processedUserLogin = processPii(userLogin!);
tryAddTag(Tags.AppSec.EventsUsers.SignUpEvent.Login, processedUserLogin);
tryAddTag(Tags.AppSec.EventsUsers.InternalLogin, processedUserLogin);
}
}

security.SetTraceSamplingPriority(span);
Expand Down

0 comments on commit 655c1a5

Please sign in to comment.