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