Skip to content

Commit

Permalink
DuckTyping Isession feature
Browse files Browse the repository at this point in the history
  • Loading branch information
anna-git committed Mar 4, 2025
1 parent 918aa1f commit c51a9e6
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,10 @@
</assembly>
<assembly fullname="Microsoft.AspNetCore.Http.Features">
<type fullname="Microsoft.AspNetCore.Http.Features.IFeatureCollection" />
<type fullname="Microsoft.AspNetCore.Http.Features.ISessionFeature" />
<type fullname="Microsoft.AspNetCore.Http.IHeaderDictionary" />
<type fullname="Microsoft.AspNetCore.Http.IQueryCollection" />
<type fullname="Microsoft.AspNetCore.Http.IRequestCookieCollection" />
<type fullname="Microsoft.AspNetCore.Http.IResponseCookies" />
<type fullname="Microsoft.AspNetCore.Http.ISession" />
</assembly>
<assembly fullname="Microsoft.AspNetCore.Identity" />
<assembly fullname="Microsoft.AspNetCore.Mvc.Abstractions">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
using Datadog.Trace.Util.Http;
using Datadog.Trace.Vendors.Serilog.Events;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Primitives;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
#if !NETFRAMEWORK
using System;
using System.Collections.Generic;
using System.Reflection;
using Datadog.Trace.AppSec.Waf;
using Datadog.Trace.DuckTyping;
using Datadog.Trace.Logging;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Routing;

Expand All @@ -20,6 +21,8 @@ internal static class SecurityCoordinatorHelpers
{
private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(SecurityCoordinatorHelpers));

internal static readonly Type? SessionFeature = Assembly.GetAssembly(typeof(IHeaderDictionary))?.GetType("Microsoft.AspNetCore.Http.Features.ISessionFeature", throwOnError: false);

internal static void CheckAndBlock(this Security security, HttpContext context, Span span)
{
if (security.AppsecEnabled)
Expand Down Expand Up @@ -82,9 +85,16 @@ internal static void CheckPathParamsAndSessionId(this Security security, HttpCon
var args = new Dictionary<string, object> { { AddressesConstants.RequestPathParams, pathParams } };
IResult? result;
// we need to check context.Features.Get<ISessionFeature> as accessing the Session item if session has not been configured for the application is throwing InvalidOperationException
if (context.Features.Get<ISessionFeature>() is { Session.IsAvailable: true } feature)
var sessionFeature = context.Features[SessionFeature];
Datadog.Trace.ClrProfiler.AutoInstrumentation.AspNetCore.UserEvents.ISessionFeature? sessionFeatureProxy = null;
if (sessionFeature is not null)
{
sessionFeatureProxy = sessionFeature.DuckCast<ClrProfiler.AutoInstrumentation.AspNetCore.UserEvents.ISessionFeature>();
}

if (sessionFeatureProxy?.Session?.IsAvailable == true)
{
result = securityCoordinator.RunWaf(args, sessionId: feature.Session.Id);
result = securityCoordinator.RunWaf(args, sessionId: sessionFeatureProxy.Session.Id);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Datadog.Trace.AppSec.Coordinator;
using Datadog.Trace.ClrProfiler.CallTarget;
using Datadog.Trace.Configuration;
using Datadog.Trace.DuckTyping;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;

Expand Down Expand Up @@ -90,8 +91,15 @@ internal static CallTargetState OnMethodBegin<TTarget>(TTarget instance, ref Cla
}
}

var sessionId = httpContext.Features.Get<ISessionFeature>()?.Session?.Id;
var result = secCoord.RunWafForUser(userSessionId: sessionId, userId: userId);
ISessionFeature? sessionFeatureProxy = null;
var sessionFeature = httpContext.Features[SecurityCoordinatorHelpers.SessionFeature];

if (sessionFeature is not null)
{
sessionFeatureProxy = sessionFeature.DuckCast<ISessionFeature>();
}

var result = secCoord.RunWafForUser(userSessionId: sessionFeatureProxy?.Session?.Id, userId: userId);
secCoord.BlockAndReport(result);

UserEventsCommon.RecordMetricsLoginSuccessIfNotFound(foundUserId, true);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// <copyright file="ISession.cs" company="Datadog">
// 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>

#if !NETFRAMEWORK
#nullable enable
using System.ComponentModel;

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

/// <summary>
/// Duck type of the SignInManager aspnet core type
/// </summary>
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public interface ISession
{
/// <summary>
/// Gets a value indicating whether the session is available
/// </summary>
bool IsAvailable { get; }

/// <summary>
/// Gets the session id
/// </summary>
string Id { get; }
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// <copyright file="ISessionFeature.cs" company="Datadog">
// 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>

#if !NETFRAMEWORK
#nullable enable
using System.ComponentModel;

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

/// <summary>
/// Duck type of the ISessionFeature aspnet core type in Microsoft.AspNetCore.Http.Features assembly
/// </summary>
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public interface ISessionFeature
{
/// <summary>
/// Gets the Session object, can be null
/// </summary>
public ISession Session { get; }
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.AspNetCore.Routing;
using System.Collections.Generic;
using System.Threading.Tasks;
using Datadog.Trace;

namespace weblog
{
[ApiController]
[Route("session")]
public class SessionController : Controller
{
[HttpGet("new")]
public IActionResult New()
{
return Content(HttpContext.Session.Id);
}

[HttpGet("user")]
public IActionResult User(string sdk_user)
{
if (sdk_user != null)
{
Samples.SampleHelpers.TrackUserLoginSuccessEvent(sdk_user, null);
}

return Content($"Hello, set the user to {sdk_user}");
}
}
}

0 comments on commit c51a9e6

Please sign in to comment.