From 70baafcfc20b101ff1406d8ce811e849f0f501c3 Mon Sep 17 00:00:00 2001
From: Gladwin Johnson <90415114+gladjohn@users.noreply.github.com>
Date: Wed, 29 Jul 2026 12:58:15 -0700
Subject: [PATCH 1/3] Add Linux Attested Managed Identity Flow documentation
Document the Linux Attested Managed Identity flow using KMPP and MSAL.
---
docs/msi_v2/linux-attested-story.md | 45 +++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 docs/msi_v2/linux-attested-story.md
diff --git a/docs/msi_v2/linux-attested-story.md b/docs/msi_v2/linux-attested-story.md
new file mode 100644
index 0000000000..20423badd1
--- /dev/null
+++ b/docs/msi_v2/linux-attested-story.md
@@ -0,0 +1,45 @@
+## Linux Attested Managed Identity Flow
+
+This flow extends MSI V2 on Linux by using KMPP to generate and retain a protected, non-exportable private key. MSAL attests that key, obtains a short-lived managed identity certificate through IMDS, and uses the certificate to acquire an mTLS-bound access token from regional ESTS.
+
+```mermaid
+sequenceDiagram
+ participant Workload as 1P Workload
+ participant MSAL
+ participant IMDS as IMDS / Managed Identity RP
+ participant KMPP as KMPP Client
+ participant TA as KMPP Trusted Application
+ participant MAA as Microsoft Azure Attestation
+ participant ESTS as Regional Entra STS
+ participant AKV as Azure Key Vault
+
+ Workload->>MSAL: Acquire token for AKV
+
+ MSAL->>IMDS: Probe MSI V2 support
+ IMDS-->>MSAL: issuecredential supported
+
+ MSAL->>IMDS: GET getPlatformMetadata
+ IMDS-->>MSAL: client_id, tenant_id, CUID, MAA endpoint
+
+ MSAL->>KMPP: Create or load protected binding key
+ KMPP->>TA: Generate protected key
+ TA-->>KMPP: Key reference and public key
+ KMPP-->>MSAL: Public key and protected-key handle
+
+ MSAL->>MAA: Request attestation token for protected key
+ MAA-->>MSAL: Attestation token
+
+ MSAL->>IMDS: POST issuecredential
protected-key handle and attestation token
+
+ Note over IMDS,KMPP: IMDS internally creates and signs the CSR
using the protected KMPP key
+
+ IMDS-->>MSAL: X.509 certificate
regional_token_url and expiry metadata
+
+ MSAL->>ESTS: Token request over mTLS
token_type=mtls_pop
+ ESTS-->>MSAL: Certificate-bound access token
+
+ MSAL-->>Workload: Access token and mTLS certificate
+
+ Workload->>AKV: Request secret over mTLS
+ AKV-->>Workload: Protected secret
+```
From afe69a36f940338d74a7f1d9ec5d29da6f1949b9 Mon Sep 17 00:00:00 2001
From: Gladwin Johnson <90415114+gladjohn@users.noreply.github.com>
Date: Sat, 15 Aug 2026 13:42:35 -0700
Subject: [PATCH 2/3] Clarify Linux KMPP managed identity design
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c958606f-3471-4310-8715-83d1081964f5
---
docs/msi_v2/linux-attested-story.md | 85 ++++++++++++++---------
docs/msi_v2/msi_with_credential_design.md | 72 +++++++++----------
2 files changed, 86 insertions(+), 71 deletions(-)
diff --git a/docs/msi_v2/linux-attested-story.md b/docs/msi_v2/linux-attested-story.md
index 20423badd1..c1aa3f9435 100644
--- a/docs/msi_v2/linux-attested-story.md
+++ b/docs/msi_v2/linux-attested-story.md
@@ -1,45 +1,68 @@
-## Linux Attested Managed Identity Flow
+## Linux KMPP Managed Identity Key Provider
-This flow extends MSI V2 on Linux by using KMPP to generate and retain a protected, non-exportable private key. MSAL attests that key, obtains a short-lived managed identity certificate through IMDS, and uses the certificate to acquire an mTLS-bound access token from regional ESTS.
+> [!IMPORTANT]
+> Linux support is currently a proof of concept. The implementation creates a
+> protected key and builds the certificate signing request (CSR). Linux key
+> attestation and the complete MSI V2 mTLS-PoP token acquisition flow remain
+> future work.
-```mermaid
-sequenceDiagram
- participant Workload as 1P Workload
- participant MSAL
- participant IMDS as IMDS / Managed Identity RP
- participant KMPP as KMPP Client
- participant TA as KMPP Trusted Application
- participant MAA as Microsoft Azure Attestation
- participant ESTS as Regional Entra STS
- participant AKV as Azure Key Vault
+### Overview
+
+The Linux Managed Identity key provider uses KMPP (KeyIso with OP-TEE and
+TrustZone) to create a non-exportable RSA-PSS key. MSAL accesses KMPP through
+`libkmpp.so`; private-key operations remain inside the trusted execution
+environment.
- Workload->>MSAL: Acquire token for AKV
+KMPP is the Linux key-provider technology. It should not be described as Linux
+Credential Guard or Linux KeyGuard.
- MSAL->>IMDS: Probe MSI V2 support
- IMDS-->>MSAL: issuecredential supported
+### Current proof-of-concept scope
- MSAL->>IMDS: GET getPlatformMetadata
- IMDS-->>MSAL: client_id, tenant_id, CUID, MAA endpoint
+The current implementation covers:
- MSAL->>KMPP: Create or load protected binding key
- KMPP->>TA: Generate protected key
- TA-->>KMPP: Key reference and public key
- KMPP-->>MSAL: Public key and protected-key handle
+- Native interoperability with `libkmpp.so`.
+- Creating and opening an enclave-backed KMPP key.
+- Reading the public key from the KMPP-generated self-signed certificate.
+- Performing RSA-PSS/SHA-256 signing inside the enclave.
+- Rejecting private-key export.
+- Building the MSI V2 CSR with the KMPP-backed key.
- MSAL->>MAA: Request attestation token for protected key
- MAA-->>MSAL: Attestation token
+The following work is not yet complete:
- MSAL->>IMDS: POST issuecredential
protected-key handle and attestation token
+- Attesting the KMPP key.
+- Sending the Linux attestation evidence to Microsoft Azure Attestation.
+- Completing the `/issuecredential` and regional ESTS token-acquisition flow.
+- Defining production fallback, recovery, and key-lifecycle behavior.
- Note over IMDS,KMPP: IMDS internally creates and signs the CSR
using the protected KMPP key
+### Key-provider architecture
- IMDS-->>MSAL: X.509 certificate
regional_token_url and expiry metadata
+```mermaid
+sequenceDiagram
+ participant MSAL
+ participant KMPP as libkmpp.so
+ participant TA as KMPP Trusted Application
- MSAL->>ESTS: Token request over mTLS
token_type=mtls_pop
- ESTS-->>MSAL: Certificate-bound access token
+ MSAL->>KMPP: Create or open key
+ KMPP->>TA: Generate non-exportable RSA-PSS key
+ TA-->>KMPP: Key identifier and self-signed certificate
+ KMPP-->>MSAL: Key handle and public certificate
- MSAL-->>Workload: Access token and mTLS certificate
+ MSAL->>KMPP: Sign CSR data
+ KMPP->>TA: RSA-PSS/SHA-256 sign
+ TA-->>KMPP: Signature
+ KMPP-->>MSAL: Signature
- Workload->>AKV: Request secret over mTLS
- AKV-->>Workload: Protected secret
+ MSAL->>MSAL: Build CSR using the public key and signature
```
+
+### Platform comparison
+
+| Platform | Key provider | Key properties | Status |
+|---|---|---|---|
+| Windows | KeyGuard KSP | Non-exportable, hardware-backed RSA key | Implemented |
+| Linux | KMPP/KeyIso through `libkmpp.so` | Non-exportable RSA-PSS key held in an OP-TEE/TrustZone enclave | POC: key creation and CSR generation only |
+
+The existence of the KMPP key provider does not indicate that Linux MSI V2
+mTLS-PoP is ready for production use. Linux support should be advertised only
+after attestation and the remaining token-acquisition stages are implemented
+and validated.
diff --git a/docs/msi_v2/msi_with_credential_design.md b/docs/msi_v2/msi_with_credential_design.md
index 148106dd2a..84a50021fe 100644
--- a/docs/msi_v2/msi_with_credential_design.md
+++ b/docs/msi_v2/msi_with_credential_design.md
@@ -10,7 +10,7 @@ The primary objective is to enable seamless token acquisition in MSI V2 for VM/V
- Define the **MSI V2 token acquisition process**.
- Describe how MSAL interacts with the `/issuecredential` and the ESTS regional token endpoint.
-- Ensure compatibility with **Windows and Linux** VMs and VMSS.
+- Support the Windows flow and define the planned Linux KMPP integration.
## Token Acquisition Process
@@ -51,18 +51,14 @@ sequenceDiagram
MSAL ->> IMDS: GET /metadata/identity/getPlatformMetadata
IMDS -->> MSAL: client_id, tenant_id, cuid, maa_endpoint
- alt Attestable CU
- MSAL ->> MAA: POST /attest/keyguard (attestation info)
- MAA -->> MSAL: attestation_token
- else Unattestable CU
- Note over MSAL: Skip attestation
- end
-
- MSAL ->> IMDS: POST /metadata/identity/issuecredential (CSR + attestation_token?)
+ MSAL ->> MAA: POST key attestation info
+ MAA -->> MSAL: attestation_token
+
+ MSAL ->> IMDS: POST /metadata/identity/issuecredential (CSR + attestation_token)
IMDS -->> MSAL: client_credential (x509), regional_token_url
MSAL ->> ESTS: POST /oauth2/v2.0/token (mTLS)
- ESTS -->> MSAL: access_token (bearer|mtls_pop **for attested CUs**, bearer **only** for unattested CUs)
+ ESTS -->> MSAL: access_token (mtls_pop)
MSAL -->> App : AuthenticationResult (access_token + mtls_certificate)
```
@@ -70,9 +66,11 @@ sequenceDiagram
- MSAL needs to create a CSR (Certificate Signing Request) with a sourced key.
- Azure RP will add a new `PlatformMetadata` endpoint which will provide the info needed to create the CSR.
-- MSAL will source a key from CredentialGuard (where available) or in-memory to form the CSR
-- For keys from CredentialGuard, MSAL will perform a key attestation with MAA (Microsoft Attestation Service) - POP only
-- MSAL will then send the CSR and the attestation token (where applicable) to the MIRP
+- On Windows, MSAL sources a non-exportable key from the KeyGuard KSP.
+- The planned Linux implementation sources a non-exportable RSA-PSS key from KMPP through `libkmpp.so`.
+- MSAL builds the CSR using the platform-backed key.
+- MSAL obtains key attestation evidence from MAA and sends the CSR and attestation token to the MIRP.
+- Linux KMPP key creation and CSR generation are currently a proof of concept; Linux attestation and the complete token flow are not yet implemented.
### Certificate Retrieval from `/issuecredential` Endpoint
@@ -86,7 +84,7 @@ sequenceDiagram
- The client (MSAL) presents the **certificate** to **ESTS** over **MTLS**.
- ESTS validates the certificate and issues an **access token**.
- The access token is then used to authenticate with Azure services.
-- The access token can be bearer / pop depending upon the key that was sourced.
+- ESTS issues an mTLS PoP access token bound to the certificate.
- MSAL will then return the access token and the certificate obtained from MIRP back to the caller.
- The caller will need to use the access token to call the target resource over mTLS using the cert.
@@ -151,11 +149,10 @@ Response supplies the UAID/client_id, tenant_id, CUID, and (for attestable VMs)
MSAL will load a pre-exisitng key, if none available MSAL will try creating one in KSP (Key Storage Provider)
-| OS | Key Store | Persistence |
-|------------------------|------------------|-------------------|
-| Windows (attested) | KeyGuard KSP | Durable |
-| Windows (unattested) | Software KSP | Durable |
-| Linux | In-memory → KMPP (future) | Process-lifetime |
+| OS | Key provider | Key properties | Status |
+|---|---|---|---|
+| Windows | KeyGuard KSP | Non-exportable, hardware-backed RSA key | Implemented |
+| Linux | KMPP/KeyIso through `libkmpp.so` | Non-exportable RSA-PSS key held in an OP-TEE/TrustZone enclave | POC: key creation and CSR generation only |
#### CSR requirements
@@ -163,9 +160,10 @@ MSAL will load a pre-exisitng key, if none available MSAL will try creating one
- **Attribute OID 1.2.840.113549.1.9.7:** `PrintableString = {CUID}`
- **Signed with:** new key `RSA 2048`
-#### (Optionally) Attest Key
+#### Attest Key
-If they Key is from KeyGuard, MSAL will then get an attestation token for this key.
+MSAL obtains an attestation token for the platform-backed key. Windows KeyGuard
+attestation is implemented. Linux KMPP attestation remains future work.
#### Request Certificate
@@ -175,7 +173,7 @@ Content-Type: application/json
{
"csr": "",
- "attestation_token": "" // Optional on unattested compute units
+ "attestation_token": ""
}
```
@@ -189,7 +187,7 @@ MSAL will then call ESTS-R to get an access token
grant_type=client_credentials
client_id=
scope=https://management.azure.com/.default
-token_type=mtls_pop // **Only valid for attested CUs**; omit (default bearer) for unattested
+token_type=mtls_pop
```
Response identical to AAD v2 but may include token_type":"mtls_pop".
@@ -211,7 +209,6 @@ Response identical to AAD v2 but may include token_type":"mtls_pop".
.PARAMETERS
-Scope Resource scope (default: ARM).
- -Unattested Skip attestation token; forces bearer token.
-Mock Use mocked responses (auto‑fallback if IMDS is not reachable).
.NOTES
@@ -220,7 +217,6 @@ Response identical to AAD v2 but may include token_type":"mtls_pop".
param(
[string]$Scope = "https://management.azure.com/.default",
- [switch]$Unattested,
[switch]$Mock
)
@@ -255,7 +251,7 @@ if ($Mock) {
client_id = [guid]::NewGuid().Guid
tenant_id = [guid]::NewGuid().Guid
CUID = [guid]::NewGuid().Guid
- attestation_endpoint = if ($Unattested) { $null } else { "https://mock.maa.contoso.com" }
+ attestation_endpoint = "https://mock.maa.contoso.com"
}
Info "Generated mock platform metadata."
}
@@ -299,15 +295,13 @@ Info "CSR ready (len=$($csrBytes.Length))"
# 4. Attestation token (mock or real)
# ------------------------------------------------------------
$attToken = $null
-if (-not $Unattested) {
- if ($Mock) {
- $attToken = "eyMock.Token"; Info "Mock attestation token generated."
- } elseif ($maaEp) {
- Info "Requesting attestation token from $maaEp …"
- $maaResp = Invoke-WebRequest -Uri "$maaEp/attest/keyguard?api-version=2023-04-01-preview" -Method POST -Body (@{ AttestationInfo = '' } | ConvertTo-Json -Compress) -ContentType 'application/json'
- Throw-IfError $maaResp 'attest/keyguard'
- $attToken = ($maaResp.Content | ConvertFrom-Json).token
- }
+if ($Mock) {
+ $attToken = "eyMock.Token"; Info "Mock attestation token generated."
+} elseif ($maaEp) {
+ Info "Requesting attestation token from $maaEp …"
+ $maaResp = Invoke-WebRequest -Uri "$maaEp/attest/keyguard?api-version=2023-04-01-preview" -Method POST -Body (@{ AttestationInfo = '' } | ConvertTo-Json -Compress) -ContentType 'application/json'
+ Throw-IfError $maaResp 'attest/keyguard'
+ $attToken = ($maaResp.Content | ConvertFrom-Json).token
}
# ------------------------------------------------------------
@@ -320,7 +314,7 @@ if ($Mock) {
} else {
$issueUri = "http://169.254.169.254/metadata/identity/issuecredential?api-version=2025-05-01&cid=$cuid&uaid=$clientId"
$issueHdr = @{ Metadata = 'true'; 'X-ms-Client-Request-id' = [guid]::NewGuid() }
- $bodyObj = @{ csr = $csrBase64 }; if ($attToken) { $bodyObj.attestation_token = $attToken }
+ $bodyObj = @{ csr = $csrBase64; attestation_token = $attToken }
$issueResp = Invoke-WebRequest -Uri $issueUri -Method POST -Headers $issueHdr -Body ($bodyObj | ConvertTo-Json -Compress) -ContentType 'application/json'
Throw-IfError $issueResp 'issuecredential'
$cred = $issueResp.Content | ConvertFrom-Json
@@ -343,15 +337,13 @@ if ($Mock) {
Info "Mock access token generated."
} else {
$regional = "$regionalTokenUrl/$tenantId/oauth2/v2.0/token"
- $bodyStr = "grant_type=client_credentials&scope=$([Uri]::EscapeDataString($Scope))&client_id=$clientId"
- if (-not $Unattested) { $bodyStr += "&token_type=mtls_pop" }
+ $bodyStr = "grant_type=client_credentials&scope=$([Uri]::EscapeDataString($Scope))&client_id=$clientId&token_type=mtls_pop"
$tokResp = Invoke-WebRequest -Uri $regional -Method POST -Body $bodyStr -Headers @{ 'Accept'='application/json'; 'Content-Type'='application/x-www-form-urlencoded' } -Certificate $miCert
Throw-IfError $tokResp 'token'
$tokenJson = $tokResp.Content | ConvertFrom-Json
}
-$kind = if ($Unattested) { 'Bearer' } else { 'mTLS-PoP' }
-Info "$kind token acquired – expires_in = $($tokenJson.expires_in)s"
+Info "mTLS-PoP token acquired – expires_in = $($tokenJson.expires_in)s"
```
## Summary of New APIs on Managed Identity Builder
From 28fb46e17fc6a384753358e2b3c2aadcf9fc1219 Mon Sep 17 00:00:00 2001
From: Gladwin Johnson <90415114+gladjohn@users.noreply.github.com>
Date: Sat, 15 Aug 2026 13:52:28 -0700
Subject: [PATCH 3/3] Address Linux design review feedback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c958606f-3471-4310-8715-83d1081964f5
---
docs/msi_v2/linux-attested-story.md | 44 ++++++++++++++++++++++-------
1 file changed, 34 insertions(+), 10 deletions(-)
diff --git a/docs/msi_v2/linux-attested-story.md b/docs/msi_v2/linux-attested-story.md
index c1aa3f9435..2343e01381 100644
--- a/docs/msi_v2/linux-attested-story.md
+++ b/docs/msi_v2/linux-attested-story.md
@@ -1,4 +1,19 @@
-## Linux KMPP Managed Identity Key Provider
+# Linux KMPP Managed Identity Key Provider
+
+## Audience and purpose
+
+This document is for MSAL maintainers and SDK engineers working on MSI V2
+Managed Identity support. It supplements the
+[MSI V2 `/issuecredential` design](msi_with_credential_design.md) by documenting
+the Linux-specific key-provider architecture.
+
+It answers the following questions:
+
+- What Linux functionality exists today?
+- How does Linux key handling differ from the Windows implementation?
+- Which security properties does KMPP provide?
+- What remains before Linux has an end-to-end MSI V2 mTLS-PoP flow?
+- Which behaviors must not yet be treated as production contracts?
> [!IMPORTANT]
> Linux support is currently a proof of concept. The implementation creates a
@@ -6,7 +21,7 @@
> attestation and the complete MSI V2 mTLS-PoP token acquisition flow remain
> future work.
-### Overview
+## Overview
The Linux Managed Identity key provider uses KMPP (KeyIso with OP-TEE and
TrustZone) to create a non-exportable RSA-PSS key. MSAL accesses KMPP through
@@ -16,7 +31,7 @@ environment.
KMPP is the Linux key-provider technology. It should not be described as Linux
Credential Guard or Linux KeyGuard.
-### Current proof-of-concept scope
+## Current proof-of-concept scope
The current implementation covers:
@@ -34,7 +49,7 @@ The following work is not yet complete:
- Completing the `/issuecredential` and regional ESTS token-acquisition flow.
- Defining production fallback, recovery, and key-lifecycle behavior.
-### Key-provider architecture
+## Key-provider architecture
```mermaid
sequenceDiagram
@@ -55,12 +70,21 @@ sequenceDiagram
MSAL->>MSAL: Build CSR using the public key and signature
```
-### Platform comparison
-
-| Platform | Key provider | Key properties | Status |
-|---|---|---|---|
-| Windows | KeyGuard KSP | Non-exportable, hardware-backed RSA key | Implemented |
-| Linux | KMPP/KeyIso through `libkmpp.so` | Non-exportable RSA-PSS key held in an OP-TEE/TrustZone enclave | POC: key creation and CSR generation only |
+## Windows and Linux comparison
+
+| Aspect | Windows | Linux |
+|---|---|---|
+| Key provider | KeyGuard KSP | KMPP/KeyIso through `libkmpp.so` |
+| Protection boundary | Credential Guard and the Windows key-storage provider | OP-TEE/TrustZone trusted execution environment |
+| Key properties | Non-exportable, hardware-backed RSA key | Non-exportable RSA-PSS key |
+| Native integration | Windows CNG/KSP APIs | P/Invoke into `libkmpp.so` |
+| Public-key source | Windows key provider | KMPP-generated self-signed certificate |
+| Private-key operations | Performed by the Windows key provider | Performed inside the KMPP trusted application |
+| CSR ownership | MSAL builds and signs the CSR using the protected key | MSAL builds and signs the CSR using the protected key |
+| Key attestation | Implemented through Microsoft Azure Attestation | Not yet implemented |
+| End-to-end token flow | Implemented | Not yet implemented |
+| E2E validation | Existing Windows flow | No Linux E2E flow yet |
+| Current status | Supported implementation | POC: key creation and CSR generation only |
The existence of the KMPP key provider does not indicate that Linux MSI V2
mTLS-PoP is ready for production use. Linux support should be advertised only