Skip to content

Commit 961c9ee

Browse files
msi with slc prototype using a demo app (#5369)
* slc * props * version --------- Co-authored-by: Gladwin Johnson <gljohns@microsoft.com>
1 parent 2a23172 commit 961c9ee

File tree

5 files changed

+177
-2
lines changed

5 files changed

+177
-2
lines changed

Directory.Packages.props

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@
8080
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
8181
<PackageVersion Include="System.Windows.Forms" Version="4.0.0" />
8282
<PackageVersion Include="CommandLineParser" Version="2.8.0" />
83-
<PackageVersion Include="System.Formats.Asn1" Version="9.0.0"/>
84-
83+
<PackageVersion Include="System.Formats.Asn1" Version="9.0.0" />
8584
</ItemGroup>
8685
</Project>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.14.36221.1 d17.14
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MsiSlcPublicApis", "MsiSlcPublicApis\MsiSlcPublicApis.csproj", "{8EF999FD-BFAA-4FA7-BDD7-2720712A6917}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{8EF999FD-BFAA-4FA7-BDD7-2720712A6917}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{8EF999FD-BFAA-4FA7-BDD7-2720712A6917}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{8EF999FD-BFAA-4FA7-BDD7-2720712A6917}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{8EF999FD-BFAA-4FA7-BDD7-2720712A6917}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {07C66F36-6EFF-4CF0-8479-92C14D60BEC9}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Microsoft.Identity.Client" />
12+
<PackageReference Include="Microsoft.IdentityModel.Abstractions" />
13+
</ItemGroup>
14+
15+
</Project>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.Identity.Client;
5+
using Microsoft.Identity.Client.AppConfig;
6+
using Microsoft.IdentityModel.Abstractions;
7+
using System;
8+
using System.Security.Cryptography.X509Certificates;
9+
using System.Runtime.InteropServices;
10+
using System.Threading.Tasks;
11+
12+
internal class Program
13+
{
14+
private static async Task Main()
15+
{
16+
// ─── 0. Environment banner ────────────────────────────────────────────────
17+
Console.WriteLine(new string('═', 70));
18+
19+
// ─── 1. Certificate events ────────────────────────────────────────────────
20+
ManagedIdentityApplication.BindingCertificateUpdated += c =>
21+
{
22+
Console.WriteLine($"\n[{Now()}] Event Fired - BindingCertificateUpdated:");
23+
PrintCertificate(c);
24+
};
25+
26+
// ─── 2. Managed-identity source & certs ───────────────────────────────────
27+
var source = await ManagedIdentityApplication.GetManagedIdentitySourceAsync()
28+
.ConfigureAwait(false);
29+
Console.WriteLine($"\n[{Now()}] Managed Identity Source: {source}");
30+
31+
var cert = ManagedIdentityApplication.GetManagedIdentityBindingCertificate();
32+
PrintCertificate(cert, "Initial Managed-Identity Binding Certificate");
33+
34+
//sleep for 5 second so we can see different timestamps
35+
Thread.Sleep(5000);
36+
37+
cert = ManagedIdentityApplication.ForceUpdateInMemoryCertificate();
38+
PrintCertificate(cert, "Forced NEW Managed-Identity Binding Certificate");
39+
40+
// ─── 3. Build MI app ──────────────────────────────────────────────────────
41+
IIdentityLogger logger = new IdentityLogger();
42+
IManagedIdentityApplication mi = ManagedIdentityApplicationBuilder
43+
.Create(ManagedIdentityId.SystemAssigned)
44+
.WithExperimentalFeatures()
45+
.WithLogging(logger, true)
46+
.Build();
47+
48+
// ─── 4. Token-acquisition loop ───────────────────────────────────────────
49+
string scope = "https://vault.azure.net/";
50+
while (true)
51+
{
52+
Console.WriteLine($"\n[{Now()}] Acquiring token for scope → {scope}");
53+
try
54+
{
55+
var result = await mi.AcquireTokenForManagedIdentity(scope)
56+
//.WithProofOfPossession()
57+
.ExecuteAsync()
58+
.ConfigureAwait(false);
59+
60+
Console.WriteLine($"[{Now()}] ✅ Success (expires {result.ExpiresOn:HH:mm:ss})");
61+
Console.WriteLine($"Access-Token (first 100 chars): {result.AccessToken[..100]}…");
62+
}
63+
catch (MsalServiceException ex)
64+
{
65+
Console.ForegroundColor = ConsoleColor.Red;
66+
Console.WriteLine($"[{Now()}] ❌ {ex.ErrorCode}: {ex.Message}");
67+
Console.ResetColor();
68+
}
69+
70+
Console.Write("\nEnter new scope or 'q' to quit: ");
71+
var input = Console.ReadLine();
72+
if (string.Equals(input, "q", StringComparison.OrdinalIgnoreCase))
73+
break;
74+
if (!string.IsNullOrWhiteSpace(input))
75+
scope = input.Trim();
76+
}
77+
}
78+
79+
// ─── Helpers ────────────────────────────────────────────────────────────────
80+
81+
private static string Now() => DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss");
82+
83+
private static void PrintCertificate(X509Certificate2 cert, string? title = null)
84+
{
85+
Console.WriteLine("\n" + (title ?? "Certificate details") + "\n" + new string('-', 60));
86+
Console.WriteLine($"Subject : {cert.Subject}");
87+
Console.WriteLine($"Issuer : {cert.Issuer}");
88+
Console.WriteLine($"Serial # : {cert.SerialNumber}");
89+
Console.WriteLine($"Not Before : {cert.NotBefore:yyyy-MM-dd HH:mm:ss}");
90+
Console.WriteLine($"Not After : {cert.NotAfter:yyyy-MM-dd HH:mm:ss}");
91+
Console.WriteLine($"Thumbprint : {cert.Thumbprint}");
92+
Console.WriteLine(new string('-', 60));
93+
}
94+
}
95+
96+
/// <summary>Minimal ILogger that pipes everything to Console.</summary>
97+
class IdentityLogger : IIdentityLogger
98+
{
99+
public EventLogLevel MinLogLevel => EventLogLevel.Verbose;
100+
public bool IsEnabled(EventLogLevel level) => level <= MinLogLevel;
101+
102+
public void Log(LogEntry entry) => Console.WriteLine($"[{DateTimeOffset.Now:HH:mm:ss}] {entry.Message}");
103+
}

prototype/MsiWithSlc/readme.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Managed Identity – SLC Prototype Demo
2+
3+
This sample showcases **certificate rotation** and **token acquisition** against the **prototype SLC endpoint** using MSAL’s *experimental* Managed-Identity flow.
4+
5+
---
6+
7+
## ✨ What the demo does
8+
9+
1. **Detects the Managed-Identity source** (should be `Credential` when the SLC endpoint is live).
10+
2. **Creates an in-memory binding certificate (`CN=devicecert.mtlsauth.local`).
11+
3. **Raises `BindingCertificateUpdated`** whenever MSAL generates a fresh cert (7-day lifetime in this prototype).
12+
4. **Calls the SLC `/credential` endpoint** over mTLS and exchanges the credential for an **AAD access token** (default scope `https://vault.azure.net/`).
13+
14+
---
15+
16+
## 🛠️ Prerequisites
17+
18+
| Requirement | Version / Notes |
19+
|--------------------|--------------------------------------------|
20+
| .NET SDK | **8.0.100** or later |
21+
| MSAL .NET | **4.72.3 preview** (included via [`Microsoft.Identity.Client`](https://www.nuget.org/packages/Microsoft.Identity.Client/4.72.3-slc-preview)) |
22+
| Access to SLC host | VM/VMSS image with the prototype **SLC agent** enabled |
23+
| Managed Identity | System-assigned (or override in code) |
24+
25+
> **Local run tip**: launch from an Azure VM/VMSS that already has the SLC agent bits; the demo will fail on a dev box without the endpoint.
26+
27+
---
28+
29+
## 🚀 Running the sample
30+
31+
```bash
32+
dotnet restore
33+
dotnet run --configuration Release

0 commit comments

Comments
 (0)