-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Adding Redaction and Compliance docs #45373
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
Merged
Merged
Changes from 8 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
d611f18
Docs update
bbe5e51
Docs update
abe8124
moving docs
3631f65
Merge branch 'main' into mariamaziz/redaction-compliance-docs
3163a2c
moving docs
9c87e95
doc update
be2c705
doc update
846d356
doc update
20fc2c4
doc update based on suggestions
583126a
doc update
7a5f41d
doc update
cb41035
doc update
5927395
doc update
75dc76e
doc update
40843ae
Improve formatting and add example class in compliance doc
IEvangelist c814ecb
Add missing section and code example in docs
IEvangelist 4b1b5a8
doc update
e826c20
doc fix
051cbb2
doc fix
92431b8
doc fix
54655a4
docs updates
e077d25
docs updates
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,190 @@ | ||
| --- | ||
| title: Compliance | ||
| description: Learn how to use compliance libraries to implement compliance features in .NET applications. | ||
| ms.date: 03/18/2025 | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| --- | ||
|
|
||
| # Compliance | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| .NET provides libraries that offer foundational components and abstractions for implementing compliance features, such as data classification and redaction, in .NET applications. These abstractions help developers create and manage data in a standardized way. | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ## Data classification | ||
|
|
||
| Data classification helps you categorize data based on its sensitivity and protection level. The `DataClassification` structure lets you label sensitive info and enforce policies based on these labels. | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| - **Taxonomy Name:** Identifies the classification system. | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - **Value:** Represents the specific label within the taxonomy. | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
mariamgerges marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ### Install the package | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| From the command line: | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```console | ||
| dotnet add package Microsoft.Extensions.Compliance.Classification | ||
| ``` | ||
|
|
||
| Or directly in the C# project file: | ||
|
|
||
| ```xml | ||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.Extensions.Compliance.Classification" Version="[CURRENTVERSION]" /> | ||
| </ItemGroup> | ||
| ``` | ||
|
|
||
| ### Create custom classifications | ||
|
|
||
| Define custom classifications by creating static members for different types of sensitive data. This gives you a consistent way to label and handle data across your app. | ||
|
|
||
| Example: | ||
|
|
||
| ```csharp | ||
| using Microsoft.Extensions.Compliance.Classification; | ||
IEvangelist marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| public static class MyTaxonomyClassifications | ||
IEvangelist marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| public static string Name => "MyTaxonomy"; | ||
|
|
||
| public static DataClassification PrivateInformation => new DataClassification(Name, nameof(PrivateInformation)); | ||
| public static DataClassification CreditCardNumber => new DataClassification(Name, nameof(CreditCardNumber)); | ||
| public static DataClassification SocialSecurityNumber => new DataClassification(Name, nameof(SocialSecurityNumber)); | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| ``` | ||
|
|
||
| ### Create custom attributes | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Create custom attributes based on your custom classifications. Use these attributes to tag your data with the right classification. | ||
|
|
||
| Example: | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```csharp | ||
| public sealed class PrivateInformationAttribute : DataClassificationAttribute | ||
| { | ||
| public PrivateInformationAttribute() | ||
| : base(MyTaxonomyClassifications.PrivateInformation) | ||
| { | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ### Bind data classification settings | ||
|
|
||
| Bind data classification settings from your configuration using the options pattern. In your `appsettings.json`, add: | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```json | ||
| { | ||
| "Key": { | ||
| "PhoneNumber": "MyTaxonomy:PrivateInformation", | ||
| "ExampleDictionary": { | ||
| "CreditCard": "MyTaxonomy:CreditCardNumber", | ||
| "SSN": "MyTaxonomy:SocialSecurityNumber" | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Example code: | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```csharp | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Compliance.Classification; | ||
| using Microsoft.Extensions.Configuration; | ||
| using Microsoft.Extensions.Options; | ||
|
|
||
| public class TestOptions | ||
| { | ||
| public DataClassification? PhoneNumber { get; set; } | ||
| public IDictionary<string, DataClassification> ExampleDictionary { get; set; } = new Dictionary<string, DataClassification>(); | ||
| } | ||
|
|
||
| class Program | ||
| { | ||
| static void Main(string[] args) | ||
| { | ||
| // Build configuration from an external json file. | ||
| IConfiguration configuration = new ConfigurationBuilder() | ||
| .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | ||
| .Build(); | ||
|
|
||
| // Setup DI container and bind the configuration section "Key" to TestOptions. | ||
| IServiceCollection services = new ServiceCollection(); | ||
| services.Configure<TestOptions>(configuration.GetSection("Key")); | ||
|
|
||
| // Build the service provider. | ||
| IServiceProvider serviceProvider = services.BuildServiceProvider(); | ||
|
|
||
| // Get the bound options. | ||
| TestOptions options = serviceProvider.GetRequiredService<IOptions<TestOptions>>().Value; | ||
|
|
||
| // Simple output demonstrating binding results. | ||
| Console.WriteLine("Configuration bound to TestOptions:"); | ||
| Console.WriteLine($"PhoneNumber: {options.PhoneNumber}"); | ||
| foreach (var item in options.ExampleDictionary) | ||
| { | ||
| Console.WriteLine($"{item.Key}: {item.Value}"); | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Redaction | ||
|
|
||
| Redactors replace or mask sensitive data. They help you protect sensitive info in logs, error messages, or other outputs. | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Install the package | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| From the command line: | ||
|
|
||
| ```console | ||
| dotnet add package Microsoft.Extensions.Compliance.Redaction | ||
| ``` | ||
|
|
||
| Or directly in the C# project file: | ||
|
|
||
| ```xml | ||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.Extensions.Compliance.Redaction" Version="[CURRENTVERSION]"/> | ||
| </ItemGroup> | ||
| ``` | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Redactor | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Create a redactor by inheriting from <xref:Microsoft.Extensions.Compliance.Redaction.Redactor>: | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```csharp | ||
| using Microsoft.Extensions.Compliance.Redaction; | ||
|
|
||
| public class StarRedactor : Redactor | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| private const string Stars = "****"; | ||
|
|
||
| public override int GetRedactedLength(ReadOnlySpan<char> input) => Stars.Length; | ||
|
|
||
| public override int Redact(ReadOnlySpan<char> source, Span<char> destination) | ||
| { | ||
| Stars.CopyTo(destination); | ||
| return Stars.Length; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ### Redactor provider | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| The <xref:Microsoft.Extensions.Compliance.Redaction.IRedactorProvider> interface provides instances of redactors based on data classification. | ||
|
|
||
| Create a redactor provider by inheriting from <xref:Microsoft.Extensions.Compliance.Redaction.IRedactorProvider>: | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```csharp | ||
| using Microsoft.Extensions.Compliance.Classification; | ||
| using Microsoft.Extensions.Compliance.Redaction; | ||
|
|
||
| public sealed class StarRedactorProvider : IRedactorProvider | ||
| { | ||
| private static readonly StarRedactor _starRedactor = new(); | ||
|
|
||
| public static StarRedactorProvider Instance { get; } = new(); | ||
|
|
||
| public Redactor GetRedactor(DataClassificationSet classifications) => _starRedactor; | ||
| } | ||
| ``` | ||
|
|
||
| For more information about .NET's data redaction library, check [.NET Data Redaction](data-redaction.md) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| --- | ||
| title: Data redaction | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| description: Learn how to use .NET data redaction libraries to protect your application's sensitive data. | ||
| ms.date: 03/17/2025 | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| --- | ||
|
|
||
| # Data redaction | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Redaction helps you sanitize or mask sensitive info in logs, error messages, or other outputs. This keeps you compliant with privacy rules and protects sensitive data. It's useful in apps that handle personal data, financial info, or other confidential info. | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ## Install the package | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
mariamgerges marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| From the command line: | ||
|
|
||
| ```console | ||
| dotnet add package Microsoft.Extensions.Compliance.Redaction | ||
| ``` | ||
|
|
||
| Or directly in the C# project file: | ||
|
|
||
| ```xml | ||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.Extensions.Compliance.Redaction" Version="[CURRENTVERSION]" /> | ||
| </ItemGroup> | ||
| ``` | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ## Redactors | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Redactors handle the actual redaction of sensitive data. They replace or mask sensitive information. | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| - The <xref:Microsoft.Extensions.Compliance.Redaction.ErasingRedactor> replaces any input with an empty string. | ||
| - The <xref:Microsoft.Extensions.Compliance.Redaction.HmacRedactor> uses `HMACSHA256` to encode data being redacted. | ||
|
|
||
| ## Usage example | ||
|
|
||
| ### Register the services | ||
|
|
||
| Register the services using one of the `AddRedaction` methods: | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```csharp | ||
| public static IServiceCollection AddRedaction(this IServiceCollection services) | ||
| public static IServiceCollection AddRedaction(this IServiceCollection services, Action<IRedactionBuilder> configure) | ||
| ``` | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Configure a redactor | ||
|
|
||
| Fetch redactors at runtime using an `IRedactorProvider`. You can implement your own provider and register it inside the `AddRedaction` call, or use the default provider. Configure redactors using these `IRedactionBuilder` methods: | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```csharp | ||
| // This will use the default redactor, which is the ErasingRedactor | ||
| builder.Services.AddRedaction(); | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // Using the default redactor provider: | ||
| builder.Services.AddRedaction(redactionBuilder => | ||
| { | ||
| // Assign a redactor to use for a set of data classifications. | ||
| redactionBuilder.SetRedactor<MyRedactor>(MyTaxonomy.Private, MyTaxonomy.Personal); | ||
| // Assign a fallback redactor to use when processing classified data for which no specific redactor has been registered. | ||
| // The `ErasingRedactor` is the default fallback redactor. If no redactor is configured for a data classification then the data will be erased. | ||
| redactionBuilder.SetFallbackRedactor<MyFallbackRedactor>(); | ||
| }); | ||
|
|
||
| // Using a custom redactor provider: | ||
| builder.Services.AddSingleton<IRedactorProvider, MyRedactorProvider>(); | ||
| ``` | ||
|
|
||
| Given this data classification in your code: | ||
|
|
||
| ```csharp | ||
| using Microsoft.Extensions.Compliance.Classification; | ||
|
|
||
| public static class MyTaxonomy | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| public static string Name => "MyTaxonomy"; | ||
|
|
||
| public static DataClassification Private => new DataClassification(Name, nameof(Private)); | ||
| public static DataClassification Public => new DataClassification(Name, nameof(Public)); | ||
| public static DataClassification Personal => new DataClassification(Name, nameof(Personal)); | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| ``` | ||
|
|
||
| ### Configure the HMAC redactor | ||
|
|
||
| Configure the HMAC redactor using these `IRedactionBuilder` methods: | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```csharp | ||
| var serviceCollection = new ServiceCollection(); | ||
IEvangelist marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| serviceCollection.AddRedaction(builder => | ||
| { | ||
| builder.SetHmacRedactor( | ||
| options => | ||
| { | ||
| options.KeyId = 1234567890; | ||
| options.Key = Convert.ToBase64String("1234567890abcdefghijklmnopqrstuvwxyz"); | ||
| }, | ||
|
|
||
| // Any data tagged with Personal or Private attributes will be redacted by the Hmac redactor. | ||
| MyTaxonomy.Personal, MyTaxonomy.Private, | ||
|
|
||
| // "DataClassificationSet" lets you compose multiple data classifications: | ||
| // For example, here the Hmac redactor will be used for data tagged | ||
| // with BOTH Personal and Private (but not one without the other). | ||
| new DataClassificationSet(MyTaxonomy.Personal, MyTaxonomy.Private)); | ||
| }); | ||
| ``` | ||
|
|
||
| Alternatively, configure it this way: | ||
|
|
||
| ```csharp | ||
| var serviceCollection = new ServiceCollection(); | ||
| serviceCollection.AddRedaction(builder => | ||
| { | ||
| builder.SetHmacRedactor( | ||
| Configuration.GetSection("HmacRedactorOptions"), MyTaxonomy.Personal); | ||
| }); | ||
| ``` | ||
|
|
||
| Include this section in your JSON config file: | ||
|
|
||
| ```json | ||
| { | ||
| "HmacRedactorOptions": { | ||
| "KeyId": 1234567890, | ||
| "Key": "1234567890abcdefghijklmnopqrstuvwxyz" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| - The `HmacRedactorOptions` requires its `KeyId` and `Key` properties to be set. | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - The `Key` should be in base 64 format and at least 44 characters long. Use a distinct key for each major deployment of a service. Keep the key material secret and rotate it regularly. | ||
| - The `KeyId` is appended to each redacted value to identify the key used to hash the data. | ||
| - Different key IDs mean the values are unrelated and can't be used for correlation. | ||
|
|
||
| > [!Note] | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| > The `HmacRedactor` is still experimental, so the above methods will show warning `EXTEXP0002` indicating it's not yet stable. | ||
mariamgerges marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| > To use it, add `<NoWarn>$(NoWarn);EXTEXP0002</NoWarn>` to your project file or add `#pragma warning disable EXTEXP0002` around the calls to `SetHmacRedactor`. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.