Service Principal Setup¶
Register and configure the Service Principal for automated environment provisioning.
Overview¶
The provisioning flows use a Service Principal (app-only identity) to:
- Create Power Platform environments
- Enable Managed Environments
- Assign environments to groups
- Bind security groups
- Apply baseline configurations
Architecture¶
Azure Key Vault
|
| (Get Secret)
v
Power Automate Flow
|
| (Bearer Token)
v
Service Principal ──────────────────────────────────────────┐
| |
|── api.powerplatform.com (Power Platform API) |
|── *.crm.dynamics.com (Dataverse Web API) |
└── graph.microsoft.com (Microsoft Graph) |
|
Power Platform Management App Registration ◄─────────────┘
(admin.powerplatform.microsoft.com)
Prerequisites¶
- Entra ID Application Administrator role
- Power Platform Admin role
- Azure Key Vault Secrets Officer role
azure-identityandmsalPython packages installed
Automated Registration¶
Using the Script¶
# Install dependencies
pip install -r scripts/requirements.txt
# Dry run (validates without creating)
python scripts/register_service_principal.py \
--tenant-id <your-tenant-id> \
--app-name ELM-Provisioning-ServicePrincipal \
--key-vault-name <your-keyvault-name> \
--secret-name ELM-ServicePrincipal-Secret \
--expiry-days 90 \
--dry-run
# Execute registration
python scripts/register_service_principal.py \
--tenant-id <your-tenant-id> \
--app-name ELM-Provisioning-ServicePrincipal \
--key-vault-name <your-keyvault-name> \
--secret-name ELM-ServicePrincipal-Secret \
--expiry-days 90
# With verbose output (shows stack traces on error)
python scripts/register_service_principal.py \
--tenant-id <your-tenant-id> \
--app-name ELM-Provisioning-ServicePrincipal \
--key-vault-name <your-keyvault-name> \
--secret-name ELM-ServicePrincipal-Secret \
--expiry-days 90 \
--verbose
Script Output¶
ELM Service Principal Registration
==================================
[1/4] Creating Entra ID application...
Application ID: 12345678-1234-1234-1234-123456789012
Object ID: 87654321-4321-4321-4321-210987654321
[2/4] Creating client secret...
Secret ID: secret-id-guid
Expiry: 2026-04-29 (90 days)
[3/4] Storing secret in Key Vault...
Vault: your-keyvault-name
Secret: ELM-ServicePrincipal-Secret
Version: abc123...
[4/4] Summary
========
Application Name: ELM-Provisioning-ServicePrincipal
Application ID: 12345678-1234-1234-1234-123456789012
Tenant ID: <your-tenant-id>
Key Vault: your-keyvault-name
Secret Name: ELM-ServicePrincipal-Secret
NEXT STEP (MANUAL):
Register as Power Platform Management Application:
1. Go to admin.powerplatform.microsoft.com
2. Settings > Admin settings > Power Platform settings
3. Service principal > New service principal
4. Enter Application ID: 12345678-1234-1234-1234-123456789012
5. Click Create
6. Grant admin consent for Microsoft Graph Group.Read.All
Manual Registration Steps¶
If not using the script, follow these steps:
Step 1: Register Application in Entra ID¶
- Open Entra admin center
- Navigate to: Applications > App registrations > New registration
| Setting | Value |
|---|---|
| Name | ELM-Provisioning-ServicePrincipal |
| Supported account types | Accounts in this organizational directory only |
| Redirect URI | (leave blank) |
- Click Register
- Record these values:
- Application (client) ID:
________-____-____-____-____________ - Directory (tenant) ID:
________-____-____-____-____________
Step 2: Grant Microsoft Graph Permission¶
The provisioning flow validates Microsoft Entra security groups before binding them to environments. Grant the app registration the Microsoft Graph application permission Group.Read.All, then grant tenant-wide admin consent.
Step 3: Create Client Secret (legacy dev-only fallback)¶
- In the app registration, go to Certificates & secrets
- Click New client secret
| Setting | Value |
|---|---|
| Description | ELM Provisioning Secret |
| Expires | 90 days |
- Click Add
- Immediately copy the secret value - it won't display again
Production Recommendation: Prefer managed identity, workload identity federation, or certificate-backed authentication where the hosting surface or connector supports it. Client secrets are retained here only as a legacy development fallback; store them in Key Vault, restrict access, and rotate them at least quarterly. See Certificate Configuration below.
Step 4: Store Secret in Azure Key Vault¶
- Open Azure Portal
- Navigate to your Key Vault
- Go to Secrets > Generate/Import
| Setting | Value |
|---|---|
| Upload options | Manual |
| Name | ELM-ServicePrincipal-Secret |
| Value | (paste client secret; legacy dev-only fallback) |
| Content type | text/plain |
- Click Create
Step 5: Grant Key Vault Access to Power Automate¶
- In Key Vault, go to Access policies (or Access control (IAM) for RBAC)
- Add access policy:
| Setting | Value |
|---|---|
| Secret permissions | Get |
| Principal | (search for Power Automate connection identity) |
Note: The exact principal depends on how you configure the Power Automate Key Vault connection. You may need to grant access to a user-assigned managed identity or the flow creator's identity.
Step 6: Register as Power Platform Management Application¶
- Open Power Platform admin center
- Navigate to: Settings > Admin settings > Power Platform settings
- Select Service principal > New service principal
- Enter the Application (client) ID from Step 1
- Click Create
- Verify status shows Enabled
Permissions Granted Implicitly¶
When registered as a Management Application, the SP receives:
| Permission | Granted |
|---|---|
| Create environments | Yes |
| Read environment properties | Yes |
| Update environment settings | Yes |
| Enable Managed Environments | Yes |
| Add to Environment Groups | Yes |
| Delete environments | No |
| Modify DLP policies | No |
| Access environment data | No |
This follows the principle of least privilege.
Certificate Configuration (Production)¶
For production deployments, use managed identity or workload identity federation where supported. If the automation path requires an app credential, use certificates instead of client secrets:
Generate Certificate¶
$cert = New-SelfSignedCertificate `
-Subject "CN=ELM-Provisioning-ServicePrincipal" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-KeyExportPolicy Exportable `
-KeySpec Signature `
-KeyLength 2048 `
-KeyAlgorithm RSA `
-HashAlgorithm SHA256 `
-NotAfter (Get-Date).AddYears(1)
# Export public key (.cer) for upload to Entra
Export-Certificate -Cert $cert -FilePath "ELM-SP.cer"
# Export private key (.pfx) for Key Vault
$pwd = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath "ELM-SP.pfx" -Password $pwd
Upload to Entra ID¶
- App registration > Certificates & secrets > Certificates
- Upload certificate:
ELM-SP.cer
Store in Key Vault¶
- Key Vault > Certificates > Generate/Import
- Import
ELM-SP.pfxwith password - Update Power Automate connection to use certificate
Power Automate Connection Setup¶
Create Service Principal Connection¶
- Open Power Automate
- Go to Connections > New connection
- Search for Power Platform for Admins V2
- Select Connect with Service Principal
| Field | Value |
|---|---|
| Tenant ID | (your tenant ID) |
| Client ID | (application ID) |
| Client Secret | (legacy dev-only fallback from Key Vault; prefer certificate-backed authentication where supported) |
Retrieve Secret from Key Vault in Flow¶
Add this action before using the SP connection:
Action: Azure Key Vault - Get secret
| Parameter | Value |
|---|---|
| Vault name | your-keyvault-name |
| Secret name | ELM-ServicePrincipal-Secret |
Secure the output:
Credential Rotation¶
Rotation Schedule¶
| Credential Type | Rotation Period | Lead Time |
|---|---|---|
| Client Secret | 90 days | 14 days |
| Certificate | 1 year | 30 days |
Rotation Procedure¶
- Generate new credential in Entra ID (keep old active)
- Update Key Vault with new value
- Test provisioning flow with new credential
- Verify successful environment creation
- Revoke old credential in Entra ID
- Log rotation in ProvisioningLog (optional)
Automated Rotation Reminder¶
Set up a recurrence flow to remind administrators:
Trigger: Recurrence (daily at 9:00 AM)
Action: Calculate days until expiry
Condition: Days remaining < 14
Action: Send Teams/email notification
Troubleshooting¶
Common Issues¶
| Issue | Cause | Solution |
|---|---|---|
| 401 Unauthorized | Expired credential | Rotate credential, update Key Vault |
| 403 Forbidden | Not registered as Management App | Complete Step 6 in PPAC |
| Environment creation fails | Insufficient permissions | Verify Management App registration |
| Key Vault access denied | Missing access policy | Grant Get permission to correct principal |
Verify Registration¶
- Entra ID: App registrations > Search for app name
- PPAC: Settings > Service principal > Verify "Enabled" status
- Key Vault: Secrets/Certificates > Verify credential exists and is not expired
Test Script¶
python scripts/elm_client.py \
--tenant-id <tenant-id> \
--client-id <app-id> \
--environment-url https://<org>.crm.dynamics.com \
--test-connection
Expected output:
Testing Dataverse connection...
Token acquired: ✓
API accessible: ✓
Organization: Your Org Name
Connection test: PASSED
Security Considerations¶
Principle of Least Privilege¶
- SP cannot delete environments
- SP cannot modify DLP policies
- SP cannot access environment data beyond metadata
- SP actions logged in ProvisioningLog
Monitoring¶
Monitor for suspicious activity:
- Failed authentication attempts
- Unusual creation patterns
- Off-hours activity
Revocation¶
If SP is compromised:
- Immediately revoke credentials in Entra ID
- Disable Management App registration in PPAC
- Rotate Key Vault secret
- Audit ProvisioningLog for unauthorized actions
- Generate new SP with new credentials
Next Steps¶
After Service Principal setup: