Using service principals
Add a service principal to the authorizations. Learn how to configure Partner Admin Link for service principals.
Introduction
On this page:
- Create a service principal
- Use it in an Azure Lighthouse definition
- Link the service principal to your MPN ID with the Azure CLI
Create a service principal
-
Create the service principal
In this example I will create a service principal for Terraform deployments.
az ad sp create-for-rbac --name "http://terraform"
The cosmetic name is optional but recommended.
Example output:
{ "appId": "59611dd1-bfff-4fe0-b806-113262f43a3f", "displayName": "http://terraform", "password": "<redacted>", "tenant": "3c584bbd-915f-4c70-9f2e-7217983f22f6" }
⚠️ Store the output JSON as you’ll need the password later.
-
Display the object ID
You will reference the object id - not the app id - of the service principal in Azure Lighthouse definitions.
az ad sp show --id <appId> --query id --output tsv
You can also use the OData filters if you only have the display name, e.g.
az ad sp list --filter "displayname eq 'http://terraform'" --query [0].id --output tsv
The service principal’s object id is
e11d5c66-9c16-488a-afce-fd4da574296d
in the example below.
Lighthouse definition
Example service principal lighthouse definition:
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"variables": {
"name": "Basic Support Service + Terraform",
"roleDefinitionId": {
"Contributor": "b24988ac-6180-42a0-ab88-20f7382dd24c",
"ManagedServicesRegistrationAssignmentDeleteRole": "91c1777a-f3dc-4fae-b103-61d183457e46",
"Reader": "acdd72a7-3385-48ef-bd42-f606fba81ae7",
"SupportRequestContributor": "cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e"
},
"management": {
"objectId": "9d2b2ec1-a465-431f-91d3-546f97b8fb26",
"name": "Managed Service Management"
},
"consultants": {
"objectId": "30f86a83-b2a9-477a-90d6-23e51042839a",
"name": "Managed Service Consultants"
},
"terraform": {
"objectId": "e11d5c66-9c16-488a-afce-fd4da574296d",
"name": "Service principal - http://terraform"
}
},
"resources": [
{
"type": "Microsoft.ManagedServices/registrationDefinitions",
"apiVersion": "2019-06-01",
"name": "[guid(concat('Azure Citadel - ', variables('name')))]",
"properties": {
"registrationDefinitionName": "[variables('name')]",
"description": "Azure support services for call logging and call management (L0/L1). Terraform for CI/CD pipelines.",
"managedByTenantId": "3c584bbd-915f-4c70-9f2e-7217983f22f6",
"authorizations": [
{
"principalIdDisplayName": "[variables('management').name]",
"principalId": "[variables('management').objectId]",
"roleDefinitionId": "[variables('roleDefinitionId').ManagedServicesRegistrationAssignmentDeleteRole]"
},
{
"principalIdDisplayName": "[variables('consultants').name]",
"principalId": "[variables('consultants').objectId]",
"roleDefinitionId": "[variables('roleDefinitionId').Reader]"
},
{
"principalIdDisplayName": "[variables('consultants').name]",
"principalId": "[variables('consultants').objectId]",
"roleDefinitionId": "[variables('roleDefinitionId').SupportRequestContributor]"
},
{
"principalIdDisplayName": "[variables('terraform').name]",
"principalId": "[variables('terraform').objectId]",
"roleDefinitionId": "[variables('roleDefinitionId').Contributor]"
}
]
}
}
]
}
Note that this example makes greater use of variable objects. It is entirely up to you whether you follow the same approach or just hard code values in the resource section.
Using variable like this does make the authorization section easier to understand and ensures that the cosmetic strings will be consistent.
Here is how the role would look in the portal:
Linking service principals
Creating a PAL link for service principals make a lot of sense as they do not hand in their notice!
The partner will then be recognised for the ACR if the service principal has a PEC eligible role in the authorizations.
Azure CLI
-
Retrieve the appId and tenantId
az ad sp show --id <objectId> --query "{appId:appId, tenantId:appOwnerOrganizationId}" --output yamlc
Example output:
appId: 59611dd1-bfff-4fe0-b806-113262f43a3f tenantId: 3c584bbd-915f-4c70-9f2e-7217983f22f6
-
Authenticate as the service principal
The format of the
az login
command for service principals using a password (or client secret) is:az login --service-principal --user <appId> --password <password> --tenant <tenantId>
You will need the service principal’s password from earlier.
You can reset service principal credentials with
az ad sp credential reset
.Example output:
[ { "cloudName": "AzureCloud", "homeTenantId": "3c584bbd-915f-4c70-9f2e-7217983f22f6", "id": "9b7a166a-267f-45a5-b480-7a04cfc1edf6", "isDefault": true, "managedByTenants": [], "name": "Azure Citadel (Internal)", "state": "Enabled", "tenantId": "3c584bbd-915f-4c70-9f2e-7217983f22f6", "user": { "name": "59611dd1-bfff-4fe0-b806-113262f43a3f", "type": "servicePrincipal" } } ]
ℹ️ Using a system assigned managed identity? Just use
az login --identity
on the trusted compute to authenticate.
-
Create the partner admin link
You will need your location based MPN ID.
az managementpartner create --partner-id <mpnId>
Example output:
{ "objectId": "e11d5c66-9c16-488a-afce-fd4da574296d", "partnerId": "31415927", "partnerName": "Azure Citadel Ltd", "state": "Active", "tenantId": "3c584bbd-915f-4c70-9f2e-7217983f22f6" }
Note that PAL links the service principal (tenantId/objectId) to the partnerId.
REST API
Here is some additional information for those who don’t have the Azure CLI installed.
I was helping a partner with a Managed Application and shows how to use the undocumented REST API to create the Partner Admin Link to your MPN ID.
This example is for a system assigned managed identity on a RHEL linux server.
-
Install jq
sudo dnf install jq -y
-
Use the Instance Metadata Service to get a token
token=$(curl -sSL -H "Metadata:true" 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' | jq -r .access_token)
-
Define the REST API uri
mpnid=31415927
⚠️ Set the mpnid variable to your location based Microsoft Partner ID.
-
Create the PAL link
curl --silent \ --header "Authorization: Bearer ${token}" \ --header "Content-Type: application/json" \ --data '{"partnerId": "'${mpnid}'"}' \ --request PUT \ "https://management.azure.com/providers/microsoft.managementpartner/partners/${mpnid}?api-version=2018-02-01"
Using the example MPN ID, the JSON payload would be:
{"partnerId": "31415927"}
And the uri would be:
"https://management.azure.com/providers/microsoft.managementpartner/partners/31415927?api-version=2018-02-01"
Next
On the next page we will look at an example with Privileged Identity Management.
Help us improve
Azure Citadel is a community site built on GitHub, please contribute and send a pull request
Make a change