Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ dotnet_diagnostic.SA1600.severity = none
dotnet_diagnostic.SA1602.severity = none

# Verify
[*.{received,verified}.{txt}]
[*.{received,verified}.{html}]
charset = utf-8-bom
end_of_line = lf
indent_size = unset
Expand Down
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*.verified.txt text eol=lf working-tree-encoding=UTF-8
*.verified.html text eol=lf working-tree-encoding=UTF-8
*.verified.xml text eol=lf working-tree-encoding=UTF-8
*.verified.json text eol=lf working-tree-encoding=UTF-8
*.verified.bin binary
5 changes: 3 additions & 2 deletions .github/workflows/github-actions-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
type: string
description: The version of the application
required: true
default: 1.0.0
default: 1.1.0
VersionSuffix:
type: string
description: The version suffix of the application (for example rc.1)
Expand Down Expand Up @@ -42,6 +42,7 @@ jobs:
tag_name: v${{ github.event.inputs.VersionPrefix }}${{ github.event.inputs.VersionSuffix && format('-{0}', github.event.inputs.VersionSuffix) || '' }}
files: ./PosInformatique.Azure.Identity.AppRegistrationSecretWatcher.Functions.net9.0.zip
overwrite_files: true
draft: ${{ !github.event.inputs.VersionSuffix }}
draft: ${{ github.event.inputs.VersionSuffix == '' }}
prerelease: ${{ github.event.inputs.VersionSuffix != '' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
21 changes: 12 additions & 9 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<!-- Versions of the packages -->
<PosInformationFoundationsVersion>1.0.0</PosInformationFoundationsVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Azure.Identity" Version="1.17.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="FluentAssertions" Version="7.2.0" />
<PackageVersion Include="Microsoft.ApplicationInsights.WorkerService" Version="2.23.0" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker" Version="2.2.0" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.0.0" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker" Version="2.51.0" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.50.0" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.1.0" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.1" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.6" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.10" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.7" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.11" />
<PackageVersion Include="Microsoft.Graph" Version="5.96.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="PosInformatique.Foundations.EmailAddresses" Version="1.0.0-alpha.6" />
<PackageVersion Include="PosInformatique.Moq.Analyzers" Version="2.0.1-rc.2" />
<PackageVersion Include="Scriban" Version="6.5.0" />
<PackageVersion Include="PosInformatique.Foundations.EmailAddresses" Version="$(PosInformationFoundationsVersion)" />
<PackageVersion Include="PosInformatique.Foundations.Emailing.Graph" Version="$(PosInformationFoundationsVersion)" />
<PackageVersion Include="PosInformatique.Foundations.Emailing.Templates.Razor" Version="$(PosInformationFoundationsVersion)" />
<PackageVersion Include="PosInformatique.Moq.Analyzers" Version="2.0.1" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="10.15.0.120848" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<PackageVersion Include="Verify.XunitV3" Version="31.5.1" />
<PackageVersion Include="Verify.XunitV3" Version="31.7.1" />
<PackageVersion Include="xunit.v3" Version="3.2.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
</ItemGroup>
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ executable with the monitoring logic already packaged.
## Features
- Monitor secrets across one or multiple Entra ID tenants (Entra ID, Azure B2C, Entra External ID,...).
- Send a consolidated report at a customizable interval (cron-based).
- Quick summary with the number of secrets valid, expired and expiring soon.
- Customizable threshold of expiration date for the secrets.
- Date/Time formatting customizable to avoid issued between US / European expiration date formats.
- Simple deployment to Azure Functions (pre-packaged, no build/CD required).
- Runs on Azure Functions Consumption plan (**NO COST!!!**).

![Report example](./docs/ReportExample.png)

## How it works
- Enumerates App Registrations and checks client secrets and certificates nearing expiration.
- Sends a summary report by email using Microsoft Graph.
Expand Down Expand Up @@ -46,6 +51,8 @@ To send the e-mail using Graph API:
Client ID of the App Registration used to query secrets across tenants. If omitted, the Function managed identity is used (single-tenant only).
- `APP_SECRET_WATCHER_CLIENT_SECRET`:
Client secret of the App Registration. Not required if using managed identity or certificate auth.
- `APP_SECRET_WATCHER_CULTURE`:
Culture name used to format the dates and times for the reports. (`en-US` will be used if not specified).
- `APP_SECRET_WATCHER_EXPIRATION_THRESHOLD`:
Time span threshold to raise warnings before secret expiration. Example: `30.00:00:00` for 30 days.
- `APP_SECRET_WATCHER_FREQUENCY`:
Expand Down
Loading