Skip to content

Commit

Permalink
Secure logging
Browse files Browse the repository at this point in the history
  • Loading branch information
dluc committed Aug 14, 2024
1 parent 56a6a35 commit f52a958
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 45 deletions.
33 changes: 19 additions & 14 deletions dotnet/WorkbenchConnector/AgentBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public virtual async Task<IAgentConfig> UpdateAgentConfigAsync(
IAgentConfig? config,
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Updating agent '{0}' config", this.Id);
this.Log.LogDebug("Updating agent '{0}' config", this.Id.HtmlEncode());

this.RawConfig ??= this.GetDefaultConfig();
config ??= this.GetDefaultConfig();
Expand Down Expand Up @@ -143,7 +143,8 @@ public virtual async Task CreateConversationAsync(
string conversationId,
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Creating conversation '{0}' on agent '{1}'", conversationId, this.Id);
this.Log.LogDebug("Creating conversation '{0}' on agent '{1}'",
conversationId.HtmlEncode(), this.Id.HtmlEncode());

Conversation conversation = await this.Storage.GetConversationAsync(conversationId, this.Id, cancellationToken).ConfigureAwait(false)
?? new Conversation(conversationId, this.Id);
Expand All @@ -164,7 +165,8 @@ public virtual Task DeleteConversationAsync(
string conversationId,
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Deleting conversation '{0}' on agent '{1}'", conversationId, this.Id);
this.Log.LogDebug("Deleting conversation '{0}' on agent '{1}'",
conversationId.HtmlEncode(), this.Id.HtmlEncode());
return this.Storage.DeleteConversationAsync(conversationId, this.Id, cancellationToken);
}

Expand All @@ -178,7 +180,8 @@ public virtual async Task<bool> ConversationExistsAsync(
string conversationId,
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Checking if conversation '{0}' on agent '{1}' exists", conversationId, this.Id);
this.Log.LogDebug("Checking if conversation '{0}' on agent '{1}' exists",
conversationId.HtmlEncode(), this.Id.HtmlEncode());
var conversation = await this.Storage.GetConversationAsync(conversationId, this.Id, cancellationToken).ConfigureAwait(false);
return conversation != null;
}
Expand All @@ -194,7 +197,8 @@ public virtual async Task AddParticipantAsync(
Participant participant,
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Adding participant to conversation '{0}' on agent '{1}'", conversationId, this.Id);
this.Log.LogDebug("Adding participant to conversation '{0}' on agent '{1}'",
conversationId.HtmlEncode(), this.Id.HtmlEncode());

Conversation conversation = await this.Storage.GetConversationAsync(conversationId, this.Id, cancellationToken).ConfigureAwait(false)
?? new Conversation(conversationId, this.Id);
Expand All @@ -214,7 +218,8 @@ public virtual async Task RemoveParticipantAsync(
Participant participantUpdatedEvent,
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Removing participant from conversation '{0}' on agent '{1}'", conversationId, this.Id);
this.Log.LogDebug("Removing participant from conversation '{0}' on agent '{1}'",
conversationId.HtmlEncode(), this.Id.HtmlEncode());

Conversation? conversation = await this.Storage.GetConversationAsync(conversationId, this.Id, cancellationToken).ConfigureAwait(false);
if (conversation == null) { return; }
Expand All @@ -235,7 +240,7 @@ public virtual Task ReceiveMessageAsync(
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Received {0} chat message in conversation '{1}' with agent '{2}' from '{3}' '{4}'",
message.ContentType, conversationId, this.Id, message.Sender.Role, message.Sender.Id);
message.ContentType.HtmlEncode(), conversationId.HtmlEncode(), this.Id.HtmlEncode(), message.Sender.Role.HtmlEncode(), message.Sender.Id.HtmlEncode());

// Update the chat history to include the message received
return this.AddMessageToHistoryAsync(conversationId, message, cancellationToken);
Expand All @@ -255,7 +260,7 @@ public virtual Task ReceiveNoticeAsync(
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Received {0} notice in conversation '{1}' with agent '{2}' from '{3}' '{4}': {5}",
message.ContentType, conversationId, this.Id, message.Sender.Role, message.Sender.Id, message.Content);
message.ContentType.HtmlEncode(), conversationId.HtmlEncode(), this.Id.HtmlEncode(), message.Sender.Role.HtmlEncode(), message.Sender.Id.HtmlEncode(), message.Content.HtmlEncode());

return Task.CompletedTask;
}
Expand All @@ -273,7 +278,7 @@ public virtual Task ReceiveNoteAsync(
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Received {0} note in conversation '{1}' with agent '{2}' from '{3}' '{4}': {5}",
message.ContentType, conversationId, this.Id, message.Sender.Role, message.Sender.Id, message.Content);
message.ContentType.HtmlEncode(), conversationId.HtmlEncode(), this.Id.HtmlEncode(), message.Sender.Role.HtmlEncode(), message.Sender.Id.HtmlEncode(), message.Content.HtmlEncode());

return Task.CompletedTask;
}
Expand All @@ -290,7 +295,7 @@ public virtual Task ReceiveCommandAsync(
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Received '{0}' command in conversation '{1}' with agent '{2}' from '{3}' '{4}': {5}",
command.CommandName, conversationId, this.Id, command.Sender.Role, command.Sender.Id, command.Content);
command.CommandName.HtmlEncode(), conversationId.HtmlEncode(), this.Id.HtmlEncode(), command.Sender.Role.HtmlEncode(), command.Sender.Id.HtmlEncode(), command.Content.HtmlEncode());

return Task.CompletedTask;
}
Expand All @@ -307,7 +312,7 @@ public virtual Task ReceiveCommandResponseAsync(
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Received {0} command response in conversation '{1}' with agent '{2}' from '{3}' '{4}': {5}",
message.ContentType, conversationId, this.Id, message.Sender.Role, message.Sender.Id, message.Content);
message.ContentType.HtmlEncode(), conversationId.HtmlEncode(), this.Id.HtmlEncode(), message.Sender.Role.HtmlEncode(), message.Sender.Id.HtmlEncode(), message.Content.HtmlEncode());

return Task.CompletedTask;
}
Expand All @@ -324,7 +329,7 @@ public virtual async Task DeleteMessageAsync(
CancellationToken cancellationToken = default)
{
this.Log.LogDebug("Deleting message in conversation '{0}' with agent '{1}', message from '{2}' '{3}'",
conversationId, this.Id, message.Sender.Role, message.Sender.Id);
conversationId.HtmlEncode(), this.Id.HtmlEncode(), message.Sender.Role.HtmlEncode(), message.Sender.Id.HtmlEncode());

// return this.DeleteMessageFromHistoryAsync(conversationId, message, cancellationToken);
Conversation? conversation = await this.Storage.GetConversationAsync(conversationId, this.Id, cancellationToken).ConfigureAwait(false);
Expand Down Expand Up @@ -379,7 +384,7 @@ protected virtual Task SetAgentStatusAsync(
string content,
CancellationToken cancellationToken = default)
{
this.Log.LogWarning("Change agent '{0}' status in conversation '{1}'", this.Id, conversationId);
this.Log.LogWarning("Change agent '{0}' status in conversation '{1}'", this.Id.HtmlEncode(), conversationId.HtmlEncode());
return this.WorkbenchConnector.SetAgentStatusAsync(this.Id, conversationId, content, cancellationToken);
}

Expand All @@ -392,7 +397,7 @@ protected virtual Task ResetAgentStatusAsync(
string conversationId,
CancellationToken cancellationToken = default)
{
this.Log.LogWarning("Reset agent '{0}' status in conversation '{1}'", this.Id, conversationId);
this.Log.LogWarning("Reset agent '{0}' status in conversation '{1}'", this.Id.HtmlEncode(), conversationId.HtmlEncode());
return this.WorkbenchConnector.ResetAgentStatusAsync(this.Id, conversationId, cancellationToken);
}
}
4 changes: 3 additions & 1 deletion dotnet/WorkbenchConnector/Storage/AgentServiceStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ public Task DeleteInsightAsync(string agentId, string conversationId, string ins

private async Task<List<T>> GetAllAsync<T>(string prefix, string suffix, CancellationToken cancellationToken = default)
{
this._log.LogTrace("Searching all files with prefix '{0}' and suffix '{1}'", prefix, suffix);
this._log.LogTrace("Searching all files with prefix '{0}' and suffix '{1}'",
prefix.HtmlEncode(), suffix.HtmlEncode());

var result = new List<T>();
string[] fileEntries = Directory.GetFiles(this._path);
foreach (string filePath in fileEntries)
Expand Down
39 changes: 39 additions & 0 deletions dotnet/WorkbenchConnector/StringLoggingExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Text;
using System.Web;
using Microsoft.AspNetCore.Http;

namespace Microsoft.SemanticWorkbench.Connector;

public static class StringLoggingExtensions
{
public static string HtmlEncode(this string? value)
{
return string.IsNullOrWhiteSpace(value)
? $"{value}"
: HttpUtility.HtmlEncode(value);
}

public static string HtmlEncode(this PathString value)
{
return string.IsNullOrWhiteSpace(value)
? $"{value}"
: HttpUtility.HtmlEncode(value);
}

public static string HtmlEncode(this StringBuilder value)
{
var s = value.ToString();
return string.IsNullOrWhiteSpace(value.ToString())
? $"{s}"
: HttpUtility.HtmlEncode(s);
}

public static string HtmlEncode(this object? value)
{
return value == null
? string.Empty
: HttpUtility.HtmlEncode(value.ToString() ?? string.Empty);
}
}
50 changes: 31 additions & 19 deletions dotnet/WorkbenchConnector/Webservice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ public static IEndpointRouteBuilder UseCreateAgentEndpoint(
string? name = agentId;
Dictionary<string, string>? settings = JsonSerializer.Deserialize<Dictionary<string, string>>(data);
settings?.TryGetValue("assistant_name", out name);
log.LogDebug("Received request to create/update agent instance '{0}', name '{1}'", agentId, name);

log.LogDebug("Received request to create/update agent instance '{0}', name '{1}'",
agentId.HtmlEncode(), name.HtmlEncode());

var agent = workbenchConnector.GetAgent(agentId);
if (agent == null)
Expand All @@ -91,7 +93,7 @@ public static IEndpointRouteBuilder UseDeleteAgentEndpoint(
[FromServices] ILogger<SemanticWorkbenchWebservice> log,
CancellationToken cancellationToken) =>
{
log.LogDebug("Received request to deleting agent instance '{0}'", agentId);
log.LogDebug("Received request to deleting agent instance '{0}'", agentId.HtmlEncode());
await workbenchConnector.DeleteAgentAsync(agentId, cancellationToken).ConfigureAwait(false);
return Results.Ok();
});
Expand All @@ -109,7 +111,7 @@ public static IEndpointRouteBuilder UseFetchAgentConfigEndpoint(
[FromServices] WorkbenchConnector workbenchConnector,
[FromServices] ILogger<SemanticWorkbenchWebservice> log) =>
{
log.LogDebug("Received request to fetch agent '{0}' configuration", agentId);
log.LogDebug("Received request to fetch agent '{0}' configuration", agentId.HtmlEncode());

var agent = workbenchConnector.GetAgent(agentId);
if (agent == null)
Expand All @@ -135,13 +137,14 @@ public static IEndpointRouteBuilder UseSaveAgentConfigEndpoint(
[FromServices] ILogger<SemanticWorkbenchWebservice> log,
CancellationToken cancellationToken) =>
{
log.LogDebug("Received request to update agent '{0}' configuration", agentId);
log.LogDebug("Received request to update agent '{0}' configuration", agentId.HtmlEncode());

var agent = workbenchConnector.GetAgent(agentId);
if (agent == null) { return Results.NotFound("Agent Not Found"); }

var config = agent.ParseConfig(data["config"]);
IAgentConfig newConfig = await agent.UpdateAgentConfigAsync(config, cancellationToken).ConfigureAwait(false);
IAgentConfig newConfig =
await agent.UpdateAgentConfigAsync(config, cancellationToken).ConfigureAwait(false);

var tmp = workbenchConnector.GetAgent(agentId);

Expand All @@ -165,7 +168,8 @@ private static IEndpointRouteBuilder UseCreateConversationEndpoint(
[FromServices] ILogger<SemanticWorkbenchWebservice> log,
CancellationToken cancellationToken) =>
{
log.LogDebug("Received request to create conversation '{0}' on agent '{1}'", conversationId, agentId);
log.LogDebug("Received request to create conversation '{0}' on agent '{1}'",
conversationId.HtmlEncode(), agentId.HtmlEncode());

var agent = workbenchConnector.GetAgent(agentId);
if (agent == null) { return Results.NotFound("Agent Not Found"); }
Expand All @@ -190,7 +194,8 @@ public static IEndpointRouteBuilder UseFetchConversationStatesEndpoint(
[FromServices] ILogger<SemanticWorkbenchWebservice> log,
CancellationToken cancellationToken) =>
{
log.LogDebug("Received request to fetch agent '{0}' conversation '{1}' states", agentId, conversationId);
log.LogDebug("Received request to fetch agent '{0}' conversation '{1}' states",
agentId.HtmlEncode(), conversationId.HtmlEncode());

var agent = workbenchConnector.GetAgent(agentId);
if (agent == null) { return Results.NotFound("Conversation Not Found"); }
Expand Down Expand Up @@ -260,7 +265,8 @@ public static IEndpointRouteBuilder UseFetchConversationInsightEndpoint(
[FromServices] ILogger<SemanticWorkbenchWebservice> log,
CancellationToken cancellationToken) =>
{
log.LogDebug("Received request to fetch agent '{0}' conversation '{1}' insight '{2}'", agentId, conversationId, insightId);
log.LogDebug("Received request to fetch agent '{0}' conversation '{1}' insight '{2}'",
agentId.HtmlEncode(), conversationId.HtmlEncode(), insightId.HtmlEncode());

var agent = workbenchConnector.GetAgent(agentId);
if (agent == null) { return Results.NotFound("Agent Not Found"); }
Expand Down Expand Up @@ -323,7 +329,8 @@ private static IEndpointRouteBuilder UseCreateConversationEventEndpoint(
[FromServices] ILogger<SemanticWorkbenchWebservice> log,
CancellationToken cancellationToken) =>
{
log.LogDebug("Received request to process new event for agent '{0}' on conversation '{1}'", agentId, conversationId);
log.LogDebug("Received request to process new event for agent '{0}' on conversation '{1}'",
agentId.HtmlEncode(), conversationId.HtmlEncode());

if (data == null || !data.TryGetValue("event", out object? eventType))
{
Expand All @@ -340,7 +347,8 @@ private static IEndpointRouteBuilder UseCreateConversationEventEndpoint(
}

var json = JsonSerializer.Serialize(data);
log.LogDebug("Agent '{0}', conversation '{1}', Event '{2}'", agentId, conversationId, eventType);
log.LogDebug("Agent '{0}', conversation '{1}', Event '{2}'",
agentId.HtmlEncode(), conversationId.HtmlEncode(), eventType.HtmlEncode());
switch (eventType.ToString())
{
case "participant.created":
Expand Down Expand Up @@ -401,8 +409,11 @@ private static IEndpointRouteBuilder UseCreateConversationEventEndpoint(
break;

default:
log.LogInformation($"{message.MessageType}: {message.Content}");
log.LogWarning("Agent '{0}', conversation '{1}', Message type '{2}' ignored", agentId, conversationId, message.MessageType);
log.LogInformation("{0}: {1}", message.MessageType.HtmlEncode(),
message.Content.HtmlEncode());
log.LogWarning("Agent '{0}', conversation '{1}', Message type '{2}' ignored",
agentId.HtmlEncode(), conversationId.HtmlEncode(),
message.MessageType.HtmlEncode());
break;
}

Expand Down Expand Up @@ -483,8 +494,8 @@ private static IEndpointRouteBuilder UseCreateConversationEventEndpoint(
}
}
*/
log.LogWarning("Event type '{0}' not supported", eventType);
log.LogTrace(json);
log.LogWarning("Event type '{0}' not supported", eventType.HtmlEncode());
log.LogTrace(json.HtmlEncode());
break;
}

Expand All @@ -507,7 +518,8 @@ public static IEndpointRouteBuilder UseDeleteConversationEndpoint(
[FromServices] ILogger<SemanticWorkbenchWebservice> log,
CancellationToken cancellationToken) =>
{
log.LogDebug("Received request to delete conversation '{0}' on agent instance '{1}'", conversationId, agentId);
log.LogDebug("Received request to delete conversation '{0}' on agent instance '{1}'",
conversationId.HtmlEncode(), agentId.HtmlEncode());

var agent = workbenchConnector.GetAgent(agentId);
if (agent == null) { return Results.Ok(); }
Expand Down Expand Up @@ -542,13 +554,13 @@ private static IEndpointRouteBuilder UseCatchAllEndpoint(
string requestBody = await reader.ReadToEndAsync().ConfigureAwait(false);
context.Request.Body.Position = 0;

log.LogWarning("Unknown request: {0} Path: {1}", context.Request.Method, context.Request.Path);
log.LogWarning("Unknown request: {0} Path: {1}", context.Request.Method, context.Request.Path.HtmlEncode());

string? query = context.Request.QueryString.Value;
if (!string.IsNullOrEmpty(query)) { log.LogDebug("Query: {0}", context.Request.QueryString.Value); }
if (!string.IsNullOrEmpty(query)) { log.LogDebug("Query: {0}", context.Request.QueryString.Value.HtmlEncode()); }

log.LogDebug("Headers: {0}", headersStringBuilder.ToString());
log.LogDebug("Body: {0}", requestBody);
log.LogDebug("Headers: {0}", headersStringBuilder.HtmlEncode());
log.LogDebug("Body: {0}", requestBody.HtmlEncode());

return Results.NotFound("Request not supported");
});
Expand Down
Loading

0 comments on commit f52a958

Please sign in to comment.