Skip to content

Add Linux Attested Managed Identity Flow documentation - #6149

Merged
Gladwin Johnson VR (gladjohn) merged 5 commits into
mainfrom
gladjohn-patch-24
Aug 26, 2026
Merged

Gladwin Johnson VR (gladjohn) merged 5 commits into
mainfrom
gladjohn-patch-24

Conversation

@gladjohn

Copy link
Copy Markdown
Contributor

Document the Linux Attested Managed Identity flow using KMPP and MSAL.

Document the Linux Attested Managed Identity flow using KMPP and MSAL.
Copilot AI lite review requested due to automatic review settings July 29, 2026 19:58
@gladjohn
Gladwin Johnson VR (gladjohn) requested a review from a team as a code owner July 29, 2026 19:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new documentation page describing the Linux Attested Managed Identity (MSI v2) flow leveraging KMPP-based protected keys, MAA attestation, IMDS /issuecredential certificate issuance, and mTLS PoP token acquisition from the regional STS.

Changes:

  • Introduces a new doc page for the Linux attested MSI v2 story.
  • Adds a Mermaid sequence diagram capturing the end-to-end interactions (workload → MSAL → IMDS/KMPP/MAA → STS → AKV).
Comments suppressed due to low confidence (1)

docs/msi_v2/linux-attested-story.md:32

  • For consistency with the other MSI v2 docs (which use the full IMDSv2 path), this should be POST /metadata/identity/issuecredential rather than POST issuecredential.
    MSAL->>IMDS: POST issuecredential<br/>protected-key handle and attestation token

Comment thread docs/msi_v2/linux-attested-story.md Outdated
Comment thread docs/msi_v2/linux-attested-story.md Outdated
Comment thread docs/msi_v2/linux-attested-story.md Outdated
Comment thread docs/msi_v2/linux-attested-story.md Outdated
Comment thread docs/msi_v2/linux-attested-story.md Outdated
Comment thread docs/msi_v2/linux-attested-story.md Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c958606f-3471-4310-8715-83d1081964f5
Copilot AI review requested due to automatic review settings August 15, 2026 20:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (4)

docs/msi_v2/msi_with_credential_design.md:177

  • The /issuecredential request example makes attestation_token look mandatory, but the platform metadata section indicates the attestation endpoint may only be present for attestable VMs. Document this field as optional (or explicitly state the flow requires an attestable VM).
{
  "csr": "<Base64 CSR>",
  "attestation_token": "<jwt>"
}

docs/msi_v2/msi_with_credential_design.md:346

  • The token request in the PowerShell POC now always appends token_type=mtls_pop and always logs an "mTLS-PoP token". If attestation_endpoint is missing (non-attestable VM), this can send an unsupported token_type and produce a misleading log message. Make token_type conditional on having an attestation token (or fail fast).
    $regional = "$regionalTokenUrl/$tenantId/oauth2/v2.0/token"
    $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
}

Info "mTLS-PoP token acquired – expires_in = $($tokenJson.expires_in)s"

docs/msi_v2/msi_with_credential_design.md:61

  • The technical Mermaid diagram currently shows attestation as unconditional and the token as always mtls_pop, but the getPlatformMetadata response is described later as returning the MAA endpoint only for attestable VMs. The diagram should reflect the optional attestation branch (and token type) to avoid implying the flow works the same on non-attestable VMs.

This issue also appears on line 174 of the same file.

    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 (mtls_pop)

docs/msi_v2/msi_with_credential_design.md:317

  • In the PowerShell POC, $attToken stays $null when attestation_endpoint is not returned. The updated code still serializes attestation_token: null into the /issuecredential body, which can break the request if the service expects the property to be omitted when not present.

This issue also appears on line 339 of the same file.

    $bodyObj   = @{ csr = $csrBase64; attestation_token = $attToken }

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c958606f-3471-4310-8715-83d1081964f5
Copilot AI review requested due to automatic review settings August 15, 2026 20:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (4)

docs/msi_v2/msi_with_credential_design.md:73

  • This bullet implies MSAL always performs key attestation and always sends an attestation token. In the current implementation, attestation is only performed when .WithAttestationSupport() configures an attestation provider; otherwise the request proceeds without attestation and the attestation_token field is omitted.
- 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.

docs/msi_v2/msi_with_credential_design.md:177

  • The /issuecredential request example makes attestation_token look required. In MSAL, CertificateRequestBody has JsonIgnore(WhenWritingNull) for AttestationToken, and the non-attested flow omits the property entirely when WithAttestationSupport() is not used. The sample should document this optionality to match the implementation and avoid suggesting clients send null/empty values.
```http
POST /metadata/identity/issuecredential?cid={CUID}&uaid={client_id}&api-version=2025-05-01 HTTP/1.1
Content-Type: application/json

{
  "csr": "<Base64 CSR>",
  "attestation_token": "<jwt>"
}

docs/msi_v2/msi_with_credential_design.md:318

  • In the PowerShell sample, $attToken can remain $null (e.g., if $maaEp is empty/unavailable), but the request body always includes attestation_token = $attToken. ConvertTo-Json will serialize this as "attestation_token": null, which contradicts MSAL's behavior (it omits the property when null) and may cause the IMDS endpoint to reject the request. Build the JSON body to only include attestation_token when it has a value.
    $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; attestation_token = $attToken }
    $issueResp = Invoke-WebRequest -Uri $issueUri -Method POST -Headers $issueHdr -Body ($bodyObj | ConvertTo-Json -Compress) -ContentType 'application/json'

docs/msi_v2/msi_with_credential_design.md:57

  • The sequence diagram currently shows key attestation as unconditional, but MSAL supports a non-attested flow when .WithAttestationSupport() is not configured (see ImdsV2ManagedIdentitySource.GetAttestationJwtAsync which returns null and proceeds). The diagram should reflect attestation as optional and the attestation token as optional in the /issuecredential call.

This issue also appears in the following locations of the same file:

  • line 69
  • line 170
  • line 315
    MSAL ->> MAA: POST key attestation info
    MAA  -->> MSAL: attestation_token

    MSAL ->> IMDS: POST /metadata/identity/issuecredential (CSR + attestation_token)

Copilot AI review requested due to automatic review settings August 15, 2026 21:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (7)

docs/msi_v2/msi_with_credential_design.md:62

  • The diagram now states ESTS always returns an mtls_pop token. MSAL currently supports both mTLS PoP (token_type=mtls_pop) and mTLS bearer (token_type=bearer) depending on the requested authentication scheme, so the response here should not be mtls_pop-only.
    MSAL ->> ESTS: POST /oauth2/v2.0/token (mTLS)
    ESTS -->> MSAL: access_token (mtls_pop)
    MSAL -->> App : AuthenticationResult (access_token + mtls_certificate)

docs/msi_v2/msi_with_credential_design.md:177

  • This request body now makes attestation_token mandatory, but the client request model omits the property when null (non-attested flows). Marking this field as required may mislead readers and break the doc’s alignment with the implementation.
{
  "csr": "<Base64 CSR>",
  "attestation_token": "<jwt>"
}

docs/msi_v2/msi_with_credential_design.md:191

  • The token request example now hard-codes token_type=mtls_pop, but MSAL also supports requesting token_type=bearer for the mTLS-bearer flow. The example should either show both options or explain when each is used.
grant_type=client_credentials
client_id=<UAID>
scope=https://management.azure.com/.default
token_type=mtls_pop
**docs/msi_v2/msi_with_credential_design.md:342**
* The PowerShell sample now always requests token_type=mtls_pop. MSAL supports both mtls_pop and bearer (mTLS bearer) depending on the chosen authentication scheme, so hard-coding mtls_pop here is misleading unless this sample is explicitly scoped to PoP-only. Consider either reintroducing a switch/parameter for bearer vs mtls_pop or clarifying in the doc that the sample is PoP-only.
$regional = "$regionalTokenUrl/$tenantId/oauth2/v2.0/token"
$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'
**docs/msi_v2/msi_with_credential_design.md:57**
* The sequence diagram now shows MAA attestation as unconditional. In the implementation, attestation is only performed for certain key types (e.g., KeyGuard); other key types proceed without calling MAA and without an attestation JWT. Consider restoring a conditional (alt/else) block here and making the attestation token optional in the subsequent /issuecredential call.

This issue also appears in the following locations of the same file:
- line 60
- line 174
- line 187
- line 339
MSAL ->> MAA: POST key attestation info
MAA  -->> MSAL: attestation_token

MSAL ->> IMDS: POST /metadata/identity/issuecredential (CSR + attestation_token)
**docs/msi_v2/msi_with_credential_design.md:318**
* In the PowerShell sample, attestation_token is now always included in the /issuecredential request body. If $attToken is null/empty (e.g., when attestation is skipped), this sends a null token instead of omitting the property. Keeping the prior conditional addition better matches the request contract (omit when not present).
$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; attestation_token = $attToken }
$issueResp = Invoke-WebRequest -Uri $issueUri -Method POST -Headers $issueHdr -Body ($bodyObj | ConvertTo-Json -Compress) -ContentType 'application/json'
**docs/msi_v2/linux-attested-story.md:43**
* This doc describes a "current implementation" with `libkmpp.so` interop and enclave-backed signing, but there is no corresponding KMPP/KeyIso implementation in this repo snapshot (no references to kmpp/keyiso/libkmpp outside docs). Unless the code lives elsewhere, this should be phrased as planned/future work or should link to the implementing PR/branch to avoid implying the feature exists in MSAL.NET today.

Current proof-of-concept scope

The current implementation covers:

  • 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.
</details>

Copilot AI review requested due to automatic review settings August 19, 2026 12:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

docs/msi_v2/msi_with_credential_design.md:302

  • In the PowerShell sample, $attToken can remain $null in non-mock mode when attestation_endpoint is missing (or when MAA doesn’t return a token). The script then always sends attestation_token = $null and later always requests token_type=mtls_pop, which will likely fail and is hard to diagnose. Consider failing fast with a clear error when an attestation token is required but not available.
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 = '<bin>' } | ConvertTo-Json -Compress) -ContentType 'application/json'

This was referenced Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants