Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
190 changes: 190 additions & 0 deletions docs/core/extensions/compliance.md
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
---

# Compliance

.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.

## 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.

- **Taxonomy Name:** Identifies the classification system.
- **Value:** Represents the specific label within the taxonomy.

### Install the package

From the command line:

```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;

public static class MyTaxonomyClassifications
{
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));
}
```

### Create custom attributes

Create custom attributes based on your custom classifications. Use these attributes to tag your data with the right classification.

Example:

```csharp
public sealed class PrivateInformationAttribute : DataClassificationAttribute
{
public PrivateInformationAttribute()
: base(MyTaxonomyClassifications.PrivateInformation)
{
}
}
```

### Bind data classification settings

Bind data classification settings from your configuration using the options pattern. In your `appsettings.json`, add:

```json
{
"Key": {
"PhoneNumber": "MyTaxonomy:PrivateInformation",
"ExampleDictionary": {
"CreditCard": "MyTaxonomy:CreditCardNumber",
"SSN": "MyTaxonomy:SocialSecurityNumber"
}
}
}
```

Example code:

```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.

### Install the package

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>
```

### Redactor

Create a redactor by inheriting from <xref:Microsoft.Extensions.Compliance.Redaction.Redactor>:

```csharp
using Microsoft.Extensions.Compliance.Redaction;

public class StarRedactor : Redactor
{
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;
}
}
```

### Redactor provider

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>:

```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)
135 changes: 135 additions & 0 deletions docs/core/extensions/data-redaction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
title: Data redaction
description: Learn how to use .NET data redaction libraries to protect your application's sensitive data.
ms.date: 03/17/2025
---

# Data redaction

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.

## Install the package

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>
```

## Redactors

Redactors handle the actual redaction of sensitive data. They replace or mask sensitive information.

- 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:

```csharp
public static IServiceCollection AddRedaction(this IServiceCollection services)
public static IServiceCollection AddRedaction(this IServiceCollection services, Action<IRedactionBuilder> configure)
```

### 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:

```csharp
// This will use the default redactor, which is the ErasingRedactor
builder.Services.AddRedaction();
// 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
{
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));
}
```

### Configure the HMAC redactor

Configure the HMAC redactor using these `IRedactionBuilder` methods:

```csharp
var serviceCollection = new ServiceCollection();
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.
- 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]
> The `HmacRedactor` is still experimental, so the above methods will show warning `EXTEXP0002` indicating it's not yet stable.
> To use it, add `<NoWarn>$(NoWarn);EXTEXP0002</NoWarn>` to your project file or add `#pragma warning disable EXTEXP0002` around the calls to `SetHmacRedactor`.
6 changes: 6 additions & 0 deletions docs/fundamentals/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,12 @@ items:
href: runtime-libraries/system-text-rune.md
- name: StringBuilder class
href: runtime-libraries/system-text-stringbuilder.md
- name: Compliance
items:
- name: Compliance
href: ../core/extensions/compliance.md
- name: Data Redaction
href: ../core/extensions/data-redaction.md
- name: Regular expressions
items:
- name: Overview
Expand Down
Loading