Skip to content

Commit 5151272

Browse files
committed
Add build and publish workflows for ControlR.Libraries.DataRedaction NuGet package
1 parent 42f7e13 commit 5151272

File tree

6 files changed

+251
-37
lines changed

6 files changed

+251
-37
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Build and Upload NuGet Package
2+
description: Builds a NuGet package and uploads it as an artifact
3+
4+
inputs:
5+
project-path:
6+
description: 'Path to the project file'
7+
required: true
8+
version:
9+
description: 'Version number for the package'
10+
required: true
11+
artifact-name:
12+
description: 'Name for the uploaded artifact'
13+
required: true
14+
retention-days:
15+
description: 'Number of days to retain the artifact'
16+
required: false
17+
default: '1'
18+
19+
runs:
20+
using: composite
21+
steps:
22+
- name: Build NuGet Package
23+
shell: pwsh
24+
run: |
25+
Write-Host "Building ${{ inputs.project-path }} with version ${{ inputs.version }}"
26+
dotnet build ${{ inputs.project-path }} -c Release -p:Version=${{ inputs.version }}
27+
28+
- name: Find NuGet Package
29+
id: find-nupkg
30+
shell: pwsh
31+
run: |
32+
$projectDir = Split-Path -Parent "${{ inputs.project-path }}"
33+
$searchDir = Join-Path $projectDir "bin\Release"
34+
Write-Host "Searching for nupkg in $searchDir"
35+
36+
if (!(Test-Path $searchDir)) {
37+
Write-Error "Directory $searchDir not found"
38+
exit 1
39+
}
40+
41+
$pkg = Get-ChildItem -Path $searchDir -Filter '*.nupkg' -File | Sort-Object LastWriteTime -Descending | Select-Object -First 1
42+
43+
if (-not $pkg) {
44+
Write-Error "NuGet package not found in $searchDir"
45+
exit 1
46+
}
47+
48+
Write-Host "Found package: $($pkg.FullName)"
49+
echo "NUPKG_PATH=$($pkg.FullName)" >> $env:GITHUB_OUTPUT
50+
51+
- name: Upload NuGet Package
52+
uses: actions/upload-artifact@v6
53+
with:
54+
name: ${{ inputs.artifact-name }}
55+
path: ${{ steps.find-nupkg.outputs.NUPKG_PATH }}
56+
retention-days: ${{ inputs.retention-days }}

.github/workflows/build.yml

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,37 @@ jobs:
9191
run: |
9292
dotnet test -c Release
9393
94+
build-nuget-packages:
95+
name: Build NuGet Packages
96+
runs-on: ${{ fromJson(inputs.use_self_hosted_runners) && fromJson('["self-hosted","Unix"]') || fromJson('["ubuntu-latest"]') }}
97+
needs: set-version
98+
99+
steps:
100+
- name: Checkout
101+
uses: actions/checkout@v6
102+
with:
103+
clean: true
104+
fetch-depth: 0
105+
106+
- name: Setup .NET
107+
uses: ./.github/actions/setup-dotnet
108+
109+
- name: Build and Upload ControlR.ApiClient
110+
uses: ./.github/actions/build-upload-nuget
111+
with:
112+
project-path: ControlR.ApiClient/ControlR.ApiClient.csproj
113+
version: ${{ needs.set-version.outputs.version }}
114+
artifact-name: ApiClientNuGet
115+
retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }}
116+
117+
- name: Build and Upload ControlR.Libraries.DataRedaction
118+
uses: ./.github/actions/build-upload-nuget
119+
with:
120+
project-path: Libraries/ControlR.Libraries.DataRedaction/ControlR.Libraries.DataRedaction.csproj
121+
version: ${{ needs.set-version.outputs.version }}
122+
artifact-name: DataRedactionNuGet
123+
retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }}
124+
94125
build-mac-binaries:
95126
name: Apple Build
96127
runs-on: ${{ fromJson(inputs.use_self_hosted_runners) && fromJson('["self-hosted","macOS"]') || fromJson('["macos-latest"]') }}
@@ -182,35 +213,6 @@ jobs:
182213
- name: Setup .NET
183214
uses: ./.github/actions/setup-dotnet
184215

185-
- name: Pack ControlR.ApiClient (Release)
186-
run: dotnet build ControlR.ApiClient/ControlR.ApiClient.csproj -c Release -p:Version=${{ env.VERSION }}
187-
188-
- name: Find ApiClient nupkg
189-
id: find-nupkg
190-
shell: pwsh
191-
run: |
192-
$searchDir = 'ControlR.ApiClient\bin\Release'
193-
Write-Host "Searching for nupkg in $searchDir"
194-
if (!(Test-Path $searchDir)) {
195-
Write-Error "Directory $searchDir not found"
196-
exit 1
197-
}
198-
$pkg = Get-ChildItem -Path $searchDir -Filter 'ControlR.ApiClient*.nupkg' -File | Sort-Object LastWriteTime -Descending | Select-Object -First 1
199-
if (-not $pkg) {
200-
Write-Error 'ApiClient nupkg not found in Release folder.'
201-
exit 1
202-
}
203-
Write-Host "Found package: $($pkg.FullName)"
204-
echo "APICLIENT_NUPKG=$($pkg.FullName)" >> $env:GITHUB_OUTPUT
205-
206-
- name: Upload ApiClient NuGet
207-
if: matrix.arch == 'win-x64'
208-
uses: actions/upload-artifact@v6
209-
with:
210-
name: ApiClientNuGet
211-
path: ${{ steps.find-nupkg.outputs.APICLIENT_NUPKG }}
212-
retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }}
213-
214216
# ===== Azure Login with OIDC =====
215217
- name: Azure Login
216218
uses: azure/login@v2

.github/workflows/publish-nugets.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ jobs:
3737
github-token: ${{ github.token }}
3838
run-id: ${{ steps.get-run-id.outputs.run_id }}
3939

40+
- name: Download DataRedaction NuGet Package
41+
uses: actions/download-artifact@v7
42+
with:
43+
name: DataRedactionNuGet
44+
path: ./nuget-packages
45+
github-token: ${{ github.token }}
46+
run-id: ${{ steps.get-run-id.outputs.run_id }}
47+
4048
- name: Setup .NET
4149
uses: actions/setup-dotnet@v5
4250
with:
@@ -69,5 +77,6 @@ jobs:
6977
echo "**Version:** ${{ steps.get-version.outputs.VERSION }}" >> $GITHUB_STEP_SUMMARY
7078
echo "**Packages Published:**" >> $GITHUB_STEP_SUMMARY
7179
echo "- ControlR.ApiClient" >> $GITHUB_STEP_SUMMARY
80+
echo "- ControlR.Libraries.DataRedaction" >> $GITHUB_STEP_SUMMARY
7281
echo "" >> $GITHUB_STEP_SUMMARY
7382
echo "✅ Successfully published to NuGet.org" >> $GITHUB_STEP_SUMMARY
Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
<Project Sdk="Microsoft.NET.Sdk">
2-
32
<PropertyGroup>
4-
<TargetFramework>net10.0</TargetFramework>
5-
<ImplicitUsings>enable</ImplicitUsings>
6-
<Nullable>enable</Nullable>
3+
<IsPackable>true</IsPackable>
4+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
5+
<Title>ControlR Data Redaction</Title>
6+
<Description>
7+
A library for data redaction in ControlR, providing tools to redact sensitive information from logs and outputs.
8+
</Description>
9+
<PackageIcon>appicon.png</PackageIcon>
10+
<PackageReadmeFile>README.md</PackageReadmeFile>
11+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
712
</PropertyGroup>
8-
13+
<ItemGroup>
14+
<None Include="..\..\.assets\appicon.png">
15+
<Pack>True</Pack>
16+
<PackagePath>\</PackagePath>
17+
</None>
18+
<None Update="README.md">
19+
<Pack>True</Pack>
20+
<PackagePath>\</PackagePath>
21+
</None>
22+
</ItemGroup>
923
<ItemGroup>
1024
<PackageReference Include="Microsoft.Extensions.Compliance.Redaction" />
1125
<PackageReference Include="Microsoft.Extensions.Logging" />
1226
<PackageReference Include="Microsoft.Extensions.Telemetry" />
1327
</ItemGroup>
14-
15-
</Project>
28+
</Project>

Libraries/ControlR.Libraries.DataRedaction/DefaultDataClassifications.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace ControlR.Libraries.DataRedaction;
44

55
public static class DefaultDataClassifications
66
{
7-
public static string Name => "DefaultDataClassifications";
7+
public const string Name = "DefaultDataClassifications";
88
public static DataClassification Protected => new(Name, nameof(Protected));
99
public static DataClassification Public => new(Name, nameof(Public));
1010
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# ControlR Data Redaction Library
2+
3+
A lightweight library for redacting sensitive data in logs and outputs using Microsoft's data compliance framework.
4+
5+
## Overview
6+
7+
This library provides tools to automatically redact sensitive information during logging operations, helping you maintain security and comply with data protection regulations. It uses Microsoft's `Microsoft.Extensions.Compliance.Redaction` package to seamlessly integrate with standard .NET logging infrastructure.
8+
9+
## Installation
10+
11+
```bash
12+
dotnet add package ControlR.Libraries.DataRedaction
13+
```
14+
15+
## Quick Start
16+
17+
### 1. Register the Redactor
18+
19+
Add the redactor to your service collection:
20+
21+
```csharp
22+
using ControlR.Libraries.DataRedaction;
23+
24+
var builder = WebApplication.CreateBuilder(args);
25+
26+
// Add redaction services
27+
builder.Services.AddStarRedactor();
28+
29+
var app = builder.Build();
30+
```
31+
32+
### 2. Mark Sensitive Properties
33+
34+
Use the `ProtectedDataClassification` attribute to mark properties that should be redacted:
35+
36+
```csharp
37+
public class User
38+
{
39+
public string Name { get; set; }
40+
41+
[ProtectedDataClassification]
42+
public string Password { get; set; }
43+
44+
[ProtectedDataClassification]
45+
public string ApiKey { get; set; }
46+
}
47+
```
48+
49+
### 3. Log Structured Data
50+
51+
When you log objects with protected properties, they'll automatically be redacted:
52+
53+
```csharp
54+
var user = new User
55+
{
56+
Name = "John Doe",
57+
Password = "secret123",
58+
ApiKey = "sk_live_abc123"
59+
};
60+
61+
logger.LogInformation("User details: {@User}", user);
62+
// Output: User details: { Name: "John Doe", Password: "****", ApiKey: "****" }
63+
```
64+
65+
## Features
66+
67+
- **Automatic Redaction**: Sensitive data is redacted automatically during logging
68+
- **Attribute-Based**: Simple `[ProtectedDataClassification]` attribute to mark sensitive properties
69+
- **Star Redactor**: Replaces sensitive values with `****`
70+
- **Standard Integration**: Works with Microsoft's logging and compliance infrastructure
71+
- **Zero Configuration**: Works out of the box with sensible defaults
72+
73+
## API Reference
74+
75+
### `AddStarRedactor()`
76+
77+
Registers the `StarRedactor` and enables redaction in the logging pipeline.
78+
79+
```csharp
80+
services.AddStarRedactor();
81+
```
82+
83+
### `ProtectedDataClassificationAttribute`
84+
85+
Marks a property as containing protected data that should be redacted.
86+
87+
```csharp
88+
[ProtectedDataClassification]
89+
public string SensitiveData { get; set; }
90+
```
91+
92+
### `StarRedactor`
93+
94+
The default redactor that replaces sensitive values with `****`.
95+
96+
### `DefaultDataClassifications`
97+
98+
Provides standard data classification types:
99+
- `Protected`: Data that should be redacted
100+
- `Public`: Data that can be logged without redaction
101+
102+
## Advanced Usage
103+
104+
### Custom Data Classifications
105+
106+
You can use the built-in classifications for more granular control:
107+
108+
```csharp
109+
using Microsoft.Extensions.Compliance.Classification;
110+
111+
public class CustomModel
112+
{
113+
[DataClassification(DefaultDataClassifications.Public)]
114+
public string PublicInfo { get; set; }
115+
116+
[DataClassification(DefaultDataClassifications.Protected)]
117+
public string PrivateInfo { get; set; }
118+
}
119+
```
120+
121+
## Requirements
122+
123+
- .NET 10.0 or later
124+
- Microsoft.Extensions.Compliance.Redaction
125+
- Microsoft.Extensions.Logging
126+
127+
## Learn More
128+
129+
For more information about data redaction in .NET, see the official documentation:
130+
- [Data Redaction in .NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/data-redaction)
131+
132+
## License
133+
134+
MIT

0 commit comments

Comments
 (0)