Authentication Guide
This guide explains how to set up authentication for PPDS ALM pipelines.
Overview
PPDS ALM uses service principals (app registrations) to authenticate with Power Platform environments. This provides:
- Non-interactive authentication for CI/CD pipelines
- Scoped permissions without user credentials
- Audit trail of automated actions
- Secret rotation capability
Prerequisites
- Azure AD access (to create app registrations)
- Power Platform Admin Center access (to create application users)
- Repository admin access (to configure secrets)
Step 1: Create App Registration
Azure Portal
- Go to Azure Portal > Azure Active Directory
- Select App registrations > New registration
- Configure:
- Name:
Power Platform CI/CD(or your preferred name) - Supported account types: Single tenant
- Redirect URI: Leave blank
- Name:
- Click Register
- Note the Application (client) ID and Directory (tenant) ID
Create Client Secret
- In your app registration, go to Certificates & secrets
- Click New client secret
- Add a description:
CI/CD Pipeline - Choose expiration: 6 months, 12 months, or 24 months
- Click Add
- IMPORTANT: Copy the secret value immediately (it won't be shown again)
Azure CLI Alternative
# Create app registration
az ad app create --display-name "Power Platform CI/CD"
# Get app ID
APP_ID=$(az ad app list --display-name "Power Platform CI/CD" --query "[0].appId" -o tsv)
# Create service principal
az ad sp create --id $APP_ID
# Create client secret (expires in 1 year)
az ad app credential reset --id $APP_ID --years 1
Step 2: Create Application User in Power Platform
The app registration must be added as an application user in each target environment.
Power Platform Admin Center
- Go to Power Platform Admin Center
- Select Environments > Select your environment
- Go to Settings > Users + permissions > Application users
- Click + New app user
- Click + Add an app and search for your app registration
- Select your Business unit (usually the root)
- Under Security roles, select:
- System Administrator for full access, OR
- Custom role with required permissions
- Click Create
Repeat for Each Environment
Create application users in all environments:
- Dev environment
- QA environment
- Prod environment (when ready)
Step 3: Configure Repository Secrets
Using GitHub Environments (Recommended)
- Go to repository Settings > Environments
- Create environments:
Dev,QA,Prod - For each environment, add:
Variables:
| Name | Description | Example |
|---|---|---|
POWERPLATFORM_ENVIRONMENT_URL | Environment URL | https://myorg-qa.crm.dynamics.com/ |
POWERPLATFORM_TENANT_ID | Azure AD tenant ID | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
POWERPLATFORM_CLIENT_ID | App registration client ID | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
Secrets:
| Name | Description |
|---|---|
POWERPLATFORM_CLIENT_SECRET | App registration client secret |
Workflow Usage
jobs:
deploy:
environment: QA # Uses QA environment secrets
uses: joshsmithxrm/ppds-alm/.github/workflows/solution-deploy.yml@v1
with:
solution-name: MySolution
solution-folder: solutions/MySolution/src
secrets:
environment-url: ${{ vars.POWERPLATFORM_ENVIRONMENT_URL }}
tenant-id: ${{ vars.POWERPLATFORM_TENANT_ID }}
client-id: ${{ vars.POWERPLATFORM_CLIENT_ID }}
client-secret: ${{ secrets.POWERPLATFORM_CLIENT_SECRET }}
Security Best Practices
Principle of Least Privilege
| Environment | Recommended Role |
|---|---|
| Dev | System Administrator |
| QA | System Customizer + Solution import |
| Prod | Custom role (minimal permissions) |
Production Custom Role
For production, create a custom security role with only:
- Solution: Read, Write (import)
- Plugin Assembly: Create, Read, Write, Delete
- Plugin Step: Create, Read, Write, Delete
- Customization: Publish All
- System Job: Read (monitoring)
Secret Rotation
- Create new secret before old one expires
- Update GitHub secrets
- Verify pipelines still work
- Delete old secret
Recommended schedule: Every 6-12 months
Verification
Test authentication before using in pipelines:
PAC CLI
# Create auth profile
pac auth create \
--environment "https://myorg.crm.dynamics.com" \
--tenant "<tenant-id>" \
--applicationId "<client-id>" \
--clientSecret "<client-secret>"
# Test by listing solutions
pac solution list
PowerShell (PPDS.Tools)
# Install module
Install-Module PPDS.Tools -Force
# Connect
Connect-DataverseEnvironment `
-EnvironmentUrl "https://myorg.crm.dynamics.com" `
-TenantId "<tenant-id>" `
-ClientId "<client-id>" `
-ClientSecret "<client-secret>"
# Test connection
Get-DataversePluginAssembly | Select-Object Name -First 5
Troubleshooting
"AADSTS700016: Application not found"
- Verify Client ID is correct
- Ensure app registration is in the correct tenant
- Check for typos
"AADSTS7000215: Invalid client secret"
- Verify you're using the secret value, not ID
- Check if secret has expired
- Create a new secret and update configuration
"User is not a member of the organization"
- Application user doesn't exist in Dataverse
- Create application user in Power Platform Admin Center
- Ensure correct Business Unit
"Insufficient privileges"
- Check security roles assigned to application user
- Ensure solution import permissions are granted
- Consider using System Administrator for troubleshooting