Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions src/Npgsql/NpgsqlDataSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,8 @@ private protected readonly Dictionary<Transaction, List<NpgsqlConnector>> _pendi
readonly INpgsqlNameTranslator _defaultNameTranslator;
readonly IDisposable? _eventSourceEvents;

internal NpgsqlDataSource(
NpgsqlConnectionStringBuilder settings,
NpgsqlDataSourceConfiguration dataSourceConfig, bool reportMetrics)
internal NpgsqlDataSource(NpgsqlConnectionStringBuilder settings, NpgsqlDataSourceConfiguration dataSourceConfig, bool reportMetrics)
{
Settings = settings;
ConnectionString = settings.PersistSecurityInfo
? settings.ToString()
: settings.ToStringWithoutPassword();

Configuration = dataSourceConfig;

(var name,
Expand All @@ -128,6 +121,21 @@ internal NpgsqlDataSource(

Debug.Assert(_passwordProvider is null || _passwordProviderAsync is not null);

Settings = settings;

if (settings.PersistSecurityInfo)
{
ConnectionString = settings.ToString();

// The data source name is reported in tracing/metrics, so avoid leaking the password through there.
Name = name ?? settings.ToStringWithoutPassword();
}
else
{
ConnectionString = settings.ToStringWithoutPassword();
Name = name ?? ConnectionString;
}

_password = settings.Password;

if (_periodicPasswordSuccessRefreshInterval != default)
Expand All @@ -144,8 +152,6 @@ internal NpgsqlDataSource(
_passwordRefreshTask = Task.Run(RefreshPassword);
}

Name = name ?? ConnectionString;

// TODO this needs a rework, but for now we just avoid tracking multi-host data sources directly.
if (reportMetrics)
{
Expand Down
25 changes: 25 additions & 0 deletions test/Npgsql.Tests/MetricTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,31 @@ public async Task ConnectionMax()
Assert.That(tags["db.client.connection.pool.name"], Is.EqualTo(dataSource.Name));
}

[Test]
public async Task Password_does_not_leak_via_datasource_name([Values] bool persistSecurityInfo)
{
var exportedItems = new List<Metric>();
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("Npgsql")
.AddInMemoryExporter(exportedItems)
.Build();

var dataSourceBuilder = base.CreateDataSourceBuilder();
dataSourceBuilder.ConnectionStringBuilder.ApplicationName = "MetricsDataSource" + Interlocked.Increment(ref _dataSourceCounter);
dataSourceBuilder.ConnectionStringBuilder.PersistSecurityInfo = persistSecurityInfo;
// Do not set the data source name - this makes it default to the connection string, but without
// the password (even when Persist Security Info is true)
await using var dataSource = dataSourceBuilder.Build();

meterProvider.ForceFlush();

var metric = exportedItems.Single(m => m.Name == "db.client.connection.max");
var point = GetFilteredPoints(metric.GetMetricPoints(), dataSource.Name).First();
var tags = ToDictionary(point.Tags);
var connectionString = new NpgsqlConnectionStringBuilder((string)tags["db.client.connection.pool.name"]!);
Assert.That(connectionString.Password, Is.Null);
}

static Dictionary<string, object?> ToDictionary(ReadOnlyTagCollection tags)
{
var dict = new Dictionary<string, object?>();
Expand Down
21 changes: 21 additions & 0 deletions test/Npgsql.Tests/TracingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,27 @@ public async Task Copy_ConfigureTracing()
Assert.That(tags["custom_tag"], Is.EqualTo("custom_value"));
}

[Test]
public async Task Password_does_not_leak_via_datasource_name([Values] bool persistSecurityInfo)
{
var dataSourceBuilder = CreateDataSourceBuilder();
dataSourceBuilder.ConnectionStringBuilder.PersistSecurityInfo = persistSecurityInfo;
// Do not set the data source name - this makes it default to the connection string, but without
// the password (even when Persist Security Info is true)
await using var dataSource = dataSourceBuilder.Build();
await using var connection = await dataSource.OpenConnectionAsync();

using var activityListener = StartListener(out var activities);

await ExecuteScalar(connection, async, isBatch: false, query: "SELECT 42");

var activity = GetSingleActivity(activities, "postgresql", "postgresql");

var tags = activity.TagObjects.ToDictionary(t => t.Key, t => t.Value);
var connectionString = new NpgsqlConnectionStringBuilder((string)tags["db.npgsql.data_source"]!);
Assert.That(connectionString.Password, Is.Null);
}

static ActivityListener StartListener(out List<Activity> activities)
{
var a = new List<Activity>();
Expand Down
Loading