Skip to content

Commit 624c702

Browse files
mariamgergesR9 FundamentalsIEvangelist
authored
Adding Redaction and Compliance docs (#45373)
* Docs update * Docs update * moving docs * moving docs * doc update * doc update * doc update * doc update based on suggestions * doc update * doc update * doc update * doc update * doc update * Improve formatting and add example class in compliance doc * Add missing section and code example in docs * doc update * doc fix * doc fix * doc fix * docs updates * docs updates --------- Co-authored-by: R9 Fundamentals <[email protected]> Co-authored-by: David Pine <[email protected]>
1 parent 851a2e0 commit 624c702

File tree

4 files changed

+342
-0
lines changed

4 files changed

+342
-0
lines changed

docs/core/extensions/compliance.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
title: Compliance libraries in .NET
3+
description: Learn how to use compliance libraries to implement compliance features in .NET applications.
4+
ms.date: 03/21/2025
5+
---
6+
7+
# Compliance libraries in .NET
8+
9+
.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. In this article, you get an overview on the data classification and redaction compliance libraries.
10+
11+
## Data classification in .NET
12+
13+
Data classification helps categorize data based on its sensitivity and protection level using the <xref:Microsoft.Extensions.Compliance.Classification.DataClassification> structure. This allows you to label sensitive information and enforce policies based on these labels. You can create custom classifications and attributes to tag your data appropriately.
14+
15+
For more information about .NET's data classification library, see [Data classification in .NET](data-classification.md).
16+
17+
## Data redaction in .NET
18+
19+
Data redaction helps protect sensitive information in logs, error messages, or other outputs to comply with privacy rules and protect sensitive data. The <xref:Microsoft.Extensions.Compliance.Redaction> library provides various redactors, such as the <xref:Microsoft.Extensions.Compliance.Redaction.ErasingRedactor> and <xref:Microsoft.Extensions.Compliance.Redaction.HmacRedactor>. You can configure these redactors and register them using the `AddRedaction` methods. Additionally, you can create custom redactors and redactor providers to suit your specific needs.
20+
21+
For more information about .NET's data redaction library, see [Data redaction in .NET](data-redaction.md).
+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
---
2+
title: Data classification in .NET
3+
description: Learn how to use .NET data classification libraries to categorize your application's data.
4+
ms.date: 03/21/2025
5+
---
6+
7+
# Data classification in .NET
8+
9+
Data classification helps you categorize (or classify) data based on its sensitivity and protection level. The <xref:Microsoft.Extensions.Compliance.Classification.DataClassification> structure lets you label sensitive information and enforce policies based on these labels.
10+
11+
- <xref:Microsoft.Extensions.Compliance.Classification.DataClassification.TaxonomyName?displayProperty=nameWithType>: Identifies the classification system.
12+
- <xref:Microsoft.Extensions.Compliance.Classification.DataClassification.Value?displayProperty=nameWithType>: Represents the specific label within the taxonomy.
13+
14+
In some situations, you might need to specify that data explicitly has no data classification, this is achieved with <xref:Microsoft.Extensions.Compliance.Classification.DataClassification.None?displayProperty=nameWithType>. Similarly, you might need to specify that data classification is unknown—use <xref:Microsoft.Extensions.Compliance.Classification.DataClassification.Unknown?displayProperty=nameWithType> in these cases.
15+
16+
## Install the package
17+
18+
To get started, install the [📦 Microsoft.Extensions.Compliance.Abstractions](https://www.nuget.org/packages/Microsoft.Extensions.Compliance.Abstractions) NuGet package:
19+
20+
### [.NET CLI](#tab/dotnet-cli)
21+
22+
```dotnetcli
23+
dotnet add package Microsoft.Extensions.Compliance.Abstractions
24+
```
25+
26+
### [PackageReference](#tab/package-reference)
27+
28+
```xml
29+
<ItemGroup>
30+
<PackageReference Include="Microsoft.Extensions.Compliance.Abstractions"
31+
Version="*" />
32+
</ItemGroup>
33+
```
34+
35+
---
36+
37+
## Create custom classifications
38+
39+
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. Consider the following example class:
40+
41+
```csharp
42+
using Microsoft.Extensions.Compliance.Classification;
43+
44+
internal static class MyTaxonomyClassifications
45+
{
46+
internal static string Name => "MyTaxonomy";
47+
48+
internal static DataClassification PrivateInformation => new(Name, nameof(PrivateInformation));
49+
internal static DataClassification CreditCardNumber => new(Name, nameof(CreditCardNumber));
50+
internal static DataClassification SocialSecurityNumber => new(Name, nameof(SocialSecurityNumber));
51+
52+
internal static DataClassificationSet PrivateAndSocialSet => new(PrivateInformation, SocialSecurityNumber);
53+
}
54+
```
55+
56+
If you want to share your custom classification taxonomy with other apps, this class and its members should be `public` instead of `internal`. For example, you can have a shared library containing custom classifications, that you can use in multiple applications.
57+
58+
<xref:Microsoft.Extensions.Compliance.Classification.DataClassificationSet> lets you compose multiple data classifications into a single set. This allows you classify your data with multiple data classifications. In addition, the .NET redaction APIs make use of a <xref:Microsoft.Extensions.Compliance.Classification.DataClassificationSet>.
59+
60+
## Create custom classification attributes
61+
62+
Create custom attributes based on your custom classifications. Use these attributes to tag your data with the right classification. Consider the following custom attribute class definition:
63+
64+
```csharp
65+
public sealed class PrivateInformationAttribute : DataClassificationAttribute
66+
{
67+
public PrivateInformationAttribute()
68+
: base(MyTaxonomyClassifications.PrivateInformation)
69+
{
70+
}
71+
}
72+
```
73+
74+
The preceding code declares a private information attribute, that's a subclass of the <xref:Microsoft.Extensions.Compliance.Classification.DataClassificationAttribute> type. It defines a parameterless constructor and pass the custom <xref:Microsoft.Extensions.Compliance.Classification.DataClassification> to its `base`.
75+
76+
## Bind data classification settings
77+
78+
To bind your data classification settings, use the .NET configuration system. For example, assuming you're using a JSON configuration provider, your _appsettings.json_ could be defined as follows:
79+
80+
```json
81+
{
82+
"Key": {
83+
"PhoneNumber": "MyTaxonomy:PrivateInformation",
84+
"ExampleDictionary": {
85+
"CreditCard": "MyTaxonomy:CreditCardNumber",
86+
"SSN": "MyTaxonomy:SocialSecurityNumber"
87+
}
88+
}
89+
}
90+
```
91+
92+
Now consider the following options pattern approach, that binds these configuration settings into the `TestOptions` object:
93+
94+
```csharp
95+
using Microsoft.Extensions.DependencyInjection;
96+
using Microsoft.Extensions.Compliance.Classification;
97+
using Microsoft.Extensions.Configuration;
98+
using Microsoft.Extensions.Options;
99+
100+
public class TestOptions
101+
{
102+
public DataClassification? PhoneNumber { get; set; }
103+
public IDictionary<string, DataClassification> ExampleDictionary { get; set; } = new Dictionary<string, DataClassification>();
104+
}
105+
106+
class Program
107+
{
108+
static void Main(string[] args)
109+
{
110+
// Build configuration from an external json file.
111+
IConfiguration configuration = new ConfigurationBuilder()
112+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
113+
.Build();
114+
115+
// Setup DI container and bind the configuration section "Key" to TestOptions.
116+
IServiceCollection services = new ServiceCollection();
117+
services.Configure<TestOptions>(configuration.GetSection("Key"));
118+
119+
// Build the service provider.
120+
IServiceProvider serviceProvider = services.BuildServiceProvider();
121+
122+
// Get the bound options.
123+
TestOptions options = serviceProvider.GetRequiredService<IOptions<TestOptions>>().Value;
124+
125+
// Simple output demonstrating binding results.
126+
Console.WriteLine("Configuration bound to TestOptions:");
127+
Console.WriteLine($"PhoneNumber: {options.PhoneNumber}");
128+
foreach (var item in options.ExampleDictionary)
129+
{
130+
Console.WriteLine($"{item.Key}: {item.Value}");
131+
}
132+
}
133+
}
134+
```
+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
---
2+
title: Data redaction in .NET
3+
description: Learn how to use .NET data redaction libraries to protect your application's sensitive data.
4+
ms.date: 03/21/2025
5+
---
6+
7+
# Data redaction in .NET
8+
9+
Redaction helps you sanitize or mask sensitive information 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 information, or other confidential data points.
10+
11+
## Install redaction package
12+
13+
To get started, install the [📦 Microsoft.Extensions.Compliance.Redaction](https://www.nuget.org/packages/Microsoft.Extensions.Compliance.Redaction) NuGet package:
14+
15+
### [.NET CLI](#tab/dotnet-cli)
16+
17+
```dotnetcli
18+
dotnet add package Microsoft.Extensions.Compliance.Redaction
19+
```
20+
21+
### [PackageReference](#tab/package-reference)
22+
23+
```xml
24+
<ItemGroup>
25+
<PackageReference Include="Microsoft.Extensions.Compliance.Redaction"
26+
Version="*" />
27+
</ItemGroup>
28+
```
29+
30+
---
31+
32+
## Available redactors
33+
34+
Redactors are responsible for the act of redacting sensitive data. They redact, replace, or mask sensitive information. Consider the following available redactors provided by the library:
35+
36+
- The <xref:Microsoft.Extensions.Compliance.Redaction.ErasingRedactor> replaces any input with an empty string.
37+
- The <xref:Microsoft.Extensions.Compliance.Redaction.HmacRedactor> uses `HMACSHA256` to encode data being redacted.
38+
39+
## Usage example
40+
41+
To use the built-in redactors, you have to register the required services. Register the services using one of the available `AddRedaction` methods as described in the following list:
42+
43+
- <xref:Microsoft.Extensions.DependencyInjection.RedactionServiceCollectionExtensions.AddRedaction(Microsoft.Extensions.DependencyInjection.IServiceCollection)>: Registers an implementation of <xref:Microsoft.Extensions.Compliance.Redaction.IRedactorProvider> in the <xref:Microsoft.Extensions.DependencyInjection.IServiceCollection>.
44+
- <xref:Microsoft.Extensions.DependencyInjection.RedactionServiceCollectionExtensions.AddRedaction(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{Microsoft.Extensions.Compliance.Redaction.IRedactionBuilder})>: Registers an implementation of <xref:Microsoft.Extensions.Compliance.Redaction.IRedactorProvider> in the <xref:Microsoft.Extensions.DependencyInjection.IServiceCollection> and configures available redactors with the given `configure` delegate.
45+
46+
### Configure a redactor
47+
48+
Fetch redactors at runtime using an <xref:Microsoft.Extensions.Compliance.Redaction.IRedactorProvider>. You can implement your own provider and register it inside the `AddRedaction` call, or use the default provider. Configure redactors using these <xref:Microsoft.Extensions.Compliance.Redaction.IRedactionBuilder> methods:
49+
50+
```csharp
51+
// This will use the default redactor, which is the ErasingRedactor
52+
var serviceCollection = new ServiceCollection();
53+
serviceCollection.AddRedaction();
54+
55+
// Using the default redactor provider:
56+
serviceCollection.AddRedaction(redactionBuilder =>
57+
{
58+
// Assign a redactor to use for a set of data classifications.
59+
redactionBuilder.SetRedactor<StarRedactor>(
60+
MyTaxonomyClassifications.Private,
61+
MyTaxonomyClassifications.Personal);
62+
// Assign a fallback redactor to use when processing classified data for which no specific redactor has been registered.
63+
// The `ErasingRedactor` is the default fallback redactor. If no redactor is configured for a data classification then the data will be erased.
64+
redactionBuilder.SetFallbackRedactor<MyFallbackRedactor>();
65+
});
66+
67+
// Using a custom redactor provider:
68+
builder.Services.AddSingleton<IRedactorProvider, StarRedactorProvider>();
69+
```
70+
71+
Given this data classification in your code:
72+
73+
```csharp
74+
public static class MyTaxonomyClassifications
75+
{
76+
public static string Name => "MyTaxonomy";
77+
78+
public static DataClassification Private => new(Name, nameof(Private));
79+
public static DataClassification Public => new(Name, nameof(Public));
80+
public static DataClassification Personal => new(Name, nameof(Personal));
81+
}
82+
```
83+
84+
### Configure the HMAC redactor
85+
86+
Configure the HMAC redactor using these <xref:Microsoft.Extensions.Compliance.Redaction.IRedactionBuilder> methods:
87+
88+
```csharp
89+
var serviceCollection = new ServiceCollection();
90+
serviceCollection.AddRedaction(builder =>
91+
{
92+
builder.SetHmacRedactor(
93+
options =>
94+
{
95+
options.KeyId = 1234567890;
96+
options.Key = Convert.ToBase64String("1234567890abcdefghijklmnopqrstuvwxyz");
97+
},
98+
99+
// Any data tagged with Personal or Private attributes will be redacted by the Hmac redactor.
100+
MyTaxonomyClassifications.Personal, MyTaxonomyClassifications.Private,
101+
102+
// "DataClassificationSet" lets you compose multiple data classifications:
103+
// For example, here the Hmac redactor will be used for data tagged
104+
// with BOTH Personal and Private (but not one without the other).
105+
new DataClassificationSet(MyTaxonomyClassifications.Personal,
106+
MyTaxonomyClassifications.Private));
107+
});
108+
```
109+
110+
Alternatively, configure it this way:
111+
112+
```csharp
113+
var serviceCollection = new ServiceCollection();
114+
serviceCollection.AddRedaction(builder =>
115+
{
116+
builder.SetHmacRedactor(
117+
Configuration.GetSection("HmacRedactorOptions"), MyTaxonomyClassifications.Personal);
118+
});
119+
```
120+
121+
Include this section in your JSON config file:
122+
123+
```json
124+
{
125+
"HmacRedactorOptions": {
126+
"KeyId": 1234567890,
127+
"Key": "1234567890abcdefghijklmnopqrstuvwxyz"
128+
}
129+
}
130+
```
131+
132+
- The <xref:Microsoft.Extensions.Compliance.Redaction.HmacRedactorOptions> requires its <xref:Microsoft.Extensions.Compliance.Redaction.HmacRedactorOptions.Key?displayProperty=nameWithType> and <xref:Microsoft.Extensions.Compliance.Redaction.HmacRedactorOptions.KeyId?displayProperty=nameWithType> properties to be set.
133+
- 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.
134+
- The `KeyId` is appended to each redacted value to identify the key used to hash the data.
135+
- Different key IDs mean the values are unrelated and can't be used for correlation.
136+
137+
> [!NOTE]
138+
> The <xref:Microsoft.Extensions.Compliance.Redaction.HmacRedactor> is still experimental, so the preceding methods will cause the `EXTEXP0002` warningm indicating it's not yet stable.
139+
> To use it, add `<NoWarn>$(NoWarn);EXTEXP0002</NoWarn>` to your project file or add `#pragma warning disable EXTEXP0002` around the calls to `SetHmacRedactor`.
140+
141+
### Configure a custom redactor
142+
143+
To create a custom redactor, define a subclass that inherits from <xref:Microsoft.Extensions.Compliance.Redaction.Redactor>:
144+
145+
```csharp
146+
public sealed class StarRedactor : Redactor
147+
148+
public class StarRedactor : Redactor
149+
{
150+
private const string Stars = "****";
151+
152+
public override int GetRedactedLength(ReadOnlySpan<char> input) => Stars.Length;
153+
154+
public override int Redact(ReadOnlySpan<char> source, Span<char> destination)
155+
{
156+
Stars.CopyTo(destination);
157+
158+
return Stars.Length;
159+
}
160+
}
161+
```
162+
163+
### Create a custom redactor provider
164+
165+
The <xref:Microsoft.Extensions.Compliance.Redaction.IRedactorProvider> interface provides instances of redactors based on data classification. To create a custom redactor provider, inherit from <xref:Microsoft.Extensions.Compliance.Redaction.IRedactorProvider> as shown in the following example:
166+
167+
```csharp
168+
using Microsoft.Extensions.Compliance.Classification;
169+
using Microsoft.Extensions.Compliance.Redaction;
170+
171+
public sealed class StarRedactorProvider : IRedactorProvider
172+
{
173+
private static readonly StarRedactor _starRedactor = new();
174+
175+
public static StarRedactorProvider Instance { get; } = new();
176+
177+
public Redactor GetRedactor(DataClassificationSet classifications) => _starRedactor;
178+
}
179+
```

docs/fundamentals/toc.yml

+8
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,14 @@ items:
673673
href: runtime-libraries/system-text-rune.md
674674
- name: StringBuilder class
675675
href: runtime-libraries/system-text-stringbuilder.md
676+
- name: Compliance
677+
items:
678+
- name: Overview
679+
href: ../core/extensions/compliance.md
680+
- name: Data classification
681+
href: ../core/extensions/data-classification.md
682+
- name: Data redaction
683+
href: ../core/extensions/data-redaction.md
676684
- name: Regular expressions
677685
items:
678686
- name: Overview

0 commit comments

Comments
 (0)