Browse Source

Enhance Security: Redact Sensitive Configuration Values in Logs (#1212)

* Add sensitive data redaction in log configuration

- Implemented regex patterns to identify sensitive keys and values.
- Redacted sensitive information in logs to enhance security.
- Added methods to check for sensitive keys and values based on defined patterns.

* Refactor sensitive data patterns in log configuration to resolve build warning errors

- Changed the declaration of sensitive patterns from array to array initializer for improved readability.
- Removed unnecessary whitespace for cleaner code formatting.
pull/1214/head
Sina Darbouy 1 year ago
committed by GitHub
parent
commit
a6ad0c2317
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 53
      backend/src/Squidex/Config/Startup/LogConfigurationHost.cs

53
backend/src/Squidex/Config/Startup/LogConfigurationHost.cs

@ -5,12 +5,36 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Text.RegularExpressions;
using Squidex.Log;
namespace Squidex.Config.Startup;
public sealed class LogConfigurationHost(IConfiguration configuration, ISemanticLog log) : IHostedService
{
private static readonly Regex[] SensitivePatterns =
[
// Authentication and API keys
new Regex(@"(?i)(secret|token|key|password|credential|auth|api[_-]?key)$"),
new Regex(@"(?i)^(aws|azure|google|microsoft|github)[_-]"),
new Regex(@"(?i)(jwt|bearer|oauth|saml)"),
new Regex(@"(?i)(client|secret|password)$"),
// Connection strings and credentials
new Regex(@"(?i)(connectionstring|connection)$"),
new Regex(@"(?i)(username|password|credential)$"),
// Cloud provider specific
new Regex(@"(?i)(accesskey|secretkey|privatekey|publickey)$"),
new Regex(@"(?i)(projectid|tenantid)$"),
// Database specific
new Regex(@"(?i)(mongodb|sqlserver|postgres|mysql)://.*"),
new Regex(@"(?i)(database|db|server|host|port|user|pass)="),
];
private static readonly string RedactedValue = "*****";
public Task StartAsync(
CancellationToken cancellationToken)
{
@ -20,13 +44,18 @@ public sealed class LogConfigurationHost(IConfiguration configuration, ISemantic
{
var logged = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var orderedConfigs = configuration.AsEnumerable().Where(kvp => kvp.Value != null).OrderBy(x => x.Key, StringComparer.OrdinalIgnoreCase);
var orderedConfigs = configuration.AsEnumerable()
.Where(kvp => kvp.Value != null)
.OrderBy(x => x.Key, StringComparer.OrdinalIgnoreCase);
foreach (var (key, val) in orderedConfigs)
{
if (logged.Add(key))
{
c.WriteProperty(key.ToLowerInvariant(), val);
var keyLower = key.ToLowerInvariant();
var value = IsSensitiveKey(keyLower) || IsSensitiveValue(val) ? RedactedValue : val;
c.WriteProperty(keyLower, value);
}
}
}));
@ -34,6 +63,26 @@ public sealed class LogConfigurationHost(IConfiguration configuration, ISemantic
return Task.CompletedTask;
}
private static bool IsSensitiveKey(string key)
{
return SensitivePatterns.Any(pattern => pattern.IsMatch(key));
}
private static bool IsSensitiveValue(string? value)
{
if (string.IsNullOrEmpty(value))
{
return false;
}
// Check for connection strings and URLs with credentials
return value.Contains("://") && (
value.Contains("@") || // Contains username/password in URL
value.Contains(";") || // Contains connection string parameters
value.Contains("=") // Contains key-value pairs
);
}
public Task StopAsync(
CancellationToken cancellationToken)
{

Loading…
Cancel
Save