Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve sensitive data detection when logging records #4658

Merged
merged 8 commits into from
Nov 4, 2023

Conversation

xakep139
Copy link
Contributor

@xakep139 xakep139 commented Nov 2, 2023

This PR fixes an issue when our [LoggerMessage] source-gen was allowing this syntax without any warnings or errors:

record MyType
{
    [PrivateData]
    public required string Password { get; init; }
}

[LoggerMessage(LogLevel.Debug, "Command is {command}")]
static void LogCommand(ILogger logger, MyType command);

Now we'll emit an error if this happens.
Additionally, this PR fixes usages of [LogProperties] when it's applied on an argument of record type that has implicitly declared property via primary constructor and this property is annotated with a data classification attribute, e.g.:

record RecordWithSensitiveMembers(
    [PrivateData] string ArgFromPrimaryCtor); // <=== we need to redact the corresponding property

[LoggerMessage(LogLevel.Information)]
static partial void LogRecordMethod(
    ILogger logger,
    IRedactorProvider redactorProvider,
    [LogProperties] RecordWithSensitiveMembers data);

Ideally, this should be annotated as [property: PrivateData] string ArgFromPrimaryCtor, but usually folks don't do that (and some might not even know about that syntax).
Now we'll cover such cases and redact RecordWithSensitiveMembers.ArgFromPrimaryCtor in generated code.

Microsoft Reviewers: Open in CodeFlow

@xakep139 xakep139 marked this pull request as ready for review November 3, 2023 14:47
{
if (i.Name == ResourceUtilizationInstruments.CpuUtilization
|| i.Name == ResourceUtilizationInstruments.MemoryUtilization)
if (!ReferenceEquals(instrument.Meter.Scope, meterScope))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -40,7 +40,10 @@ public void WindowsCounters_Registers_Instruments()
{
InstrumentPublished = (instrument, listener) =>
{
listener.EnableMeasurementEvents(instrument);
if (ReferenceEquals(meter, instrument.Meter))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -231,4 +231,10 @@ internal sealed class DiagDescriptors : DiagDescriptorsBase
title: Resources.InvalidAttributeUsageTitle,
messageFormat: Resources.InvalidAttributeUsageMessage,
category: Category);

public static DiagnosticDescriptor RecordTypeSensitiveArgumentIsInTemplate { get; } = Make(
Copy link
Contributor Author

@xakep139 xakep139 Nov 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@geeknoid @davidfowl should this be an error or rather warning?

@dotnet-comment-bot
Copy link
Collaborator

🎉 Good job! The coverage increased 🎉
Update MinCodeCoverage in the project files.

Project Expected Actual
Microsoft.AspNetCore.Diagnostics.Middleware 99 100
Microsoft.Extensions.Telemetry 92 93

Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=459450&view=codecoverage-tab


public record class BaseRecord
{
[PrivateData] public const string ConstFieldBase = Sensitive;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it mean to apply this attribute to a const? Seems like we might need an analyzer to flag this as not desirable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it doesn't make sense, but I wanted to list all possible combinations (even if they don't make sense) to ensure that record's default ToString() implementation doesn't emit these values. I will file an issue for the analyzer shortly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created #4669

@@ -20,12 +20,13 @@ internal partial class Parser
{
private static readonly HashSet<TypeKind> _allowedTypeKinds = [TypeKind.Class, TypeKind.Struct, TypeKind.Interface];

private bool ProcessLogPropertiesForParameter(
internal bool ProcessLogPropertiesForParameter(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this internal for testing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct


namespace Microsoft.Gen.Logging.Parsing
{
internal partial class Parser
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this internal for testing? Otherwise it can be private.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parser class was internal even before my changes

xakep139 and others added 2 commits November 4, 2023 16:30
@geeknoid geeknoid merged commit f8ddd93 into release/8.0 Nov 4, 2023
6 checks passed
@geeknoid geeknoid deleted the xakep139/sensitive-record-logging-detection branch November 4, 2023 17:52
@github-actions github-actions bot locked and limited conversation to collaborators Dec 11, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants