cookbook.geuer-pollmann.de
  • Introduction
  • Command line utilities
    • bash scripting
    • cURL command line utility
    • ffmpeg - Processing Media
    • JOSE from the command line
    • jq
    • Misc. command line tools
    • Zettelkasten / Markdown
  • Azure
    • Logging in to Azure
    • Working with the REST API
    • Tracing HTTP requests with Fiddler
    • Upload a file from bash
    • Azure CLI
    • terraform
    • Azure Logic Apps
    • Azure Web Apps
    • Azure Python code snippets
    • SSH keys in ARM
    • Minimal "Azure AD Workload identity federation"
    • Federated credentials from GitHub and GitLab pipelines to Azure
    • Azure Marketplace Metered Billing- Picking the correct ID when submitting usage events
    • Manually submitting values to the Azure Metering API
    • How can a publisher/ISV access the data plane of an Azure managed application?
    • The checkZonePeers API: Is your availability zone "1" equal to my "1"?
    • Token authentication with "Azure Verizon Premium CDN"
    • Getting the right storage container name in a Bicep template
    • Event-sourcing into working memory to improve data access latency
    • Postgrex on Azure - Connecting to Azure PostgreSQL from Elixir
  • Productivity
    • Excel
    • Desktop Setup
    • Time handling and Scheduling
    • Elgato from the shell
    • Typora
Powered by GitBook
On this page
  • Control plane versus Data plane
  • How to get a access token from the customer's Entra ID tenant?
  • Option 1 (highly recommended): Use the ARM control plane to list an access token
  • Option 2 (for the adventurous): Workload identity federation
  • Option 3 (legacy, bad): Managed identity attached to a VM
Edit on GitHub
  1. Azure

How can a publisher/ISV access the data plane of an Azure managed application?

PreviousManually submitting values to the Azure Metering APINextThe checkZonePeers API: Is your availability zone "1" equal to my "1"?

Last updated 4 months ago

ISVs can package and sell their solution as a managed application via Azure Marketplace, i.e. the ISV solution gets provisioned (via an ARM template) into the customer's environment. It's called 'managed' application because the publisher/ISV can indicate which identities from the publisher's Entra ID tenant are authorized to manage resources in the managed application.

Authorized employees (or applications) in the publisher's tenant can 'see' the customer's resources in their own Azure portal (and ARM REST API). One way is to configure (in partner center) a group in the publisher's Entra ID tenant to be an Owner on managed resource groups. As a result, if the managed resource group for example contains a virtual machine, members of that group can turn the VM on or off.

Control plane versus Data plane

The Owner privileges configured in Azure partner center only apply to control plane operation, that is, to calls against managed resource group resource via the ARM API. For example, if the managed resource group contains a storage account, and the storage account allows access via storage account access keys, then authorized members at the publisher side can reveal the storage account's access keys (technically a POST call against the ARM API).

Please note that the access tokens used by publisher employees to hit the ARM API are issued by the publisher's Entra ID tenant. For managed apps, the ARM API 'knows' that even if the token is not coming from the customer's Entra ID tenant, the access is still OK if it comes from the publisher.

If the service access should happen using Entra ID authentication (a Bearer / access token), or the service only supports Enta ID authN, then the previously mentioned 'access key' mechanism doesn't work, so Entra ID it is.

However, for data plane operations (like updating a secret in KeyVault or uploading a blob to blob storage), the access token must be issued by the customer's Entra ID tenant. And the publisher has no accounts in the customer's tenant.

During the provisioning of the managed application, you also cannot create a service principal with client_id and client_secret in the customer's tenant.

How to get a access token from the customer's Entra ID tenant?

There are 3 ways how this can be solved:

Option 1 (highly recommended): Use the ARM control plane to list an access token

In Azure Marketplace managed applications, you must distinguish between the "managed application" object, and the "managed resource group" that belongs to the managed application: The managed application object if of ARM resource type Microsoft.Solutions/applications. This is the object that is fully customer-manageable; while the customer might not be allowed to delete resources within the managed resource group, they can delete the managed application object itself (which results in deletion of the corresponding resource group).

POST https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Solutions/applications/{applicationName}/listTokens?api-version=2018-09-01-preview HTTP/1.1
Authorization: Bearer {{token issued by the publisher tenant, to hit the ARM API, audience https://management.azure.com/}}

{
  "authorizationAudience": "https://vault.azure.net/"
}

On the ISV side, an authorized identity first fetches a token for the ARM control plane (audience https://management.azure.com/), and then POSTs against the Microsoft.Solutions/applications resource at the customer side, with the listTokens operation, to fetch a token of the managed app.

Alternatively, if there is a user-assigned managed identity in the managed resource group that is authorized to do whatever you want, you can also supply the "userAssignedIdentities": [...] identity for which you'd like a token.

Option 2 (for the adventurous): Workload identity federation

In this example, the UAMI is configured to allow federated sign-in from an identity provider. So one first has to get an access token from that trusted IdP, and then do a client credentials grant against the customer's Entra tenant, with a "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer".

curl \
  --silent \
  --request POST \
  --url "https://login.microsoftonline.com/{customer tenant}/oauth2/token" \
  --data-urlencode "resource=20e940b3-4c77-4b0b-9a53-9e16a1b010a7"         \
  --data-urlencode "response_type=token" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
  --data-urlencode "client_id={client id of the UAMI}" \
  --data-urlencode "client_assertion={access token from the IdP}"

Option 3 (legacy, bad): Managed identity attached to a VM

In the past, publishers attached an authorized managed identity in the managed resource group to a virtual machine in the managed resource group. They then remotely signed in the the VM (via SSH), and fetched a token for the managed identity by talking the the VM's instance metadata service' endpoint (IMDS), on IP 169.254.169.254.

However, this is very inflexible (having to have a running VM), hard to automate, expensive and cumbersome (need a running VM), and certainly created security issues (remote connections to a VM might not give cozy feelings).

A 'managed application object' can have a managed identity (). In the ARM template, the ISV can create an RBAC assignment to make the managed application a Secrets Officer on the Key Vault resource. This managed identity lives in the right tenant (the customer tenant), and is authorized to access Key Vault (or other data planes). But how to get a token?

The show the necessary API call:

In addition to previously described approach of POSTing to the ARM API to list an access token (e.g. for a user-assigned managed identity), you can use workload identity federation to sign-in directly to the UAMI from a trusted IdP. I have a small demo for this approach in my GitHub repo .

Up until December 2024, you could not configure the publisher's Entra ID tenant to be a trusted issuer for a federated credential in the customer's Entra ID tenant. That would've resulted in an AADSTS700222 error. That's why in my sample I created a 'fake' IdP by storing the IdP metadata in a storage account.

However, since 18. December 2024, there is a public preview of "", in which one can specify another Entra ID tenant as trusted issuer for workload identity.

see the docs
docs
chgeuer/metering_cloudshell
chgeuer/metering_cloudshell
Public Preview of Managed Identities as Federated Identity Credentials for Microsoft Entra