-
Notifications
You must be signed in to change notification settings - Fork 0
Authentication
AzureDevOpsDscNative supports multiple authentication methods for connecting to Azure DevOps.
Authentication is configured by calling New-AzDoAuthenticationProvider before running any DSC
resources. This guide covers all available options.
This environment variable must be set before calling New-AzDoAuthenticationProvider. The function
throws immediately if it is absent:
$ENV:AZDODSC_CACHE_DIRECTORY = 'C:\ProgramData\AzureDevOpsDsc' # Windows
$ENV:AZDODSC_CACHE_DIRECTORY = '/var/lib/azuredevopsdsc' # Linux / macOSThis directory is used to persist the module's credential cache (ModuleSettings.clixml) and security
descriptor cache (SecurityDescriptors.clixml). The directory must already exist and be writable by
the account running the DSC configuration.
When using the Dsc.PipelineRunner companion project, Invoke-DscPipelineRunner reads this variable and configures
it automatically — see Pipeline Runner Configuration for details.
- Personal Access Token (PAT) — Most common and flexible
- Managed Identity — Best for Azure-hosted resources
- Service Principal (Client Secret) — For service-to-service authentication
- Service Principal (Certificate) — More secure alternative to client secrets
-
Azure CLI Token — Use an existing
az loginsession - Workload Identity Federation — Keyless authentication for CI/CD pipelines
Personal Access Tokens are scoped credentials tied to a specific Azure DevOps user account.
- In Azure DevOps, click your profile icon (top right)
- Select Personal access tokens
- Click New Token
- Configure:
- Name: Give the token a meaningful name
- Organization: Select your organisation
- Expiration: Set an expiration (30, 60, or 90 days, or custom)
- Scopes: Select the required scopes (typically "Full access" for DSC operations)
- Click Create and copy the token immediately — you will not see it again
# Plain-text PAT (suitable for interactive or test scripts)
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -PersonalAccessToken 'my-pat-token-here'
# SecureString PAT (preferred for production — avoids storing the plain-text value in memory)
$SecureStringPAT = Read-Host -Prompt 'Enter your PAT' -AsSecureString
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -SecureStringPersonalAccessToken $SecureStringPAT
# Skip the initial connectivity verification check (useful in CI environments)
# Note: -NoVerify is only available with -PersonalAccessToken, not -SecureStringPersonalAccessToken
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -PersonalAccessToken 'my-pat-token-here' -NoVerifyNote: The
-NoVerifyswitch is not available when using-SecureStringPersonalAccessToken. The SecureString PAT path always skips connectivity verification.
- Store the PAT in a secure location (Azure Key Vault, Windows Credential Manager, PowerShell SecretStore)
- Use the minimum required scopes
- Set a reasonable expiration date (30–90 days) and rotate regularly
- Never commit a PAT to version control or hardcode it in a script
Managed Identity is the recommended approach when running DSC configurations on Azure resources (Virtual Machines, Azure Arc-enabled servers, Azure Automation, etc.). No credentials or secrets need to be stored — the identity is provided by the Azure platform.
- The hosting resource must have a System-assigned or User-assigned Managed Identity enabled
- The Managed Identity must be added to the Azure DevOps organisation with appropriate permissions
# Authenticate using the Managed Identity assigned to the current Azure resource
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -useManagedIdentity
# Skip the initial connectivity verification check
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -useManagedIdentity -NoVerify- Prefer System-assigned identity when only one resource needs access
- Apply the principle of least privilege — grant the minimum permissions required
- No token rotation is needed; tokens are issued and refreshed by the Azure platform
- Audit identity access regularly
Service Principals are ideal for non-Azure environments, CI/CD pipelines, and cross-tenant scenarios where Managed Identity is not available.
- An Azure AD App Registration with a Client Secret
- The Service Principal (Enterprise Application) must be added to the Azure DevOps organisation with appropriate permissions via Access Control
# Plain-text client secret
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-ClientSecret 'my-client-secret-value'
# SecureString client secret (preferred for production)
$SecureSecret = Read-Host -Prompt 'Enter client secret' -AsSecureString
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-SecureStringClientSecret $SecureSecret
# Skip the initial connectivity verification check
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-ClientSecret 'my-client-secret-value' `
-NoVerify- Store client secrets in Azure Key Vault or PowerShell SecretStore — never in code or config files
- Rotate secrets regularly
- Prefer certificate-based authentication (see below) for higher-security scenarios
- Grant minimal required permissions
Certificate-based authentication is more secure than client secrets because private keys never leave the machine and certificates can be stored in the Windows Certificate Store or as PFX files.
- An Azure AD App Registration with an uploaded certificate (public key)
- The private key must be available on the machine running DSC (certificate store or PFX file)
- The Service Principal must be added to the Azure DevOps organisation with appropriate permissions
# ── Windows certificate store (thumbprint) ──────────────────────────────────
# The certificate must be present in the local machine or current user certificate store.
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-CertificateThumbprint 'AABBCCDDEEFF00112233445566778899AABBCCDD'
# ── PFX file (cross-platform — Linux, macOS, and Windows) ───────────────────
$CertPassword = Read-Host -Prompt 'Enter PFX password' -AsSecureString
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-CertificatePath '/etc/azdo-dsc/auth.pfx' `
-CertificatePassword $CertPassword
# Skip the initial connectivity verification check (either mode)
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-CertificateThumbprint 'AABBCCDDEEFF00112233445566778899AABBCCDD' `
-NoVerify- Store the private key securely — Windows Certificate Store (LocalMachine\My) or a protected PFX file
- Monitor certificate expiration and rotate before it expires
- Use a unique certificate per environment (Dev/Staging/Production)
- Do not share certificates across service principals
Acquires a Bearer token from an existing az login session without requiring any additional
credentials. Particularly useful for local development and interactive sessions.
- The Azure CLI must be installed and available in
PATH - You must be signed in: run
az login(oraz login --use-device-codein headless environments) - The signed-in account must have access to the Azure DevOps organisation
- Run
az account showto verify the active context; useaz account set --subscription <id>to switch
# Authenticate using the active Azure CLI session
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -useAzureCLI
# Skip the initial connectivity verification check
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -useAzureCLI -NoVerify- Suitable for local development and interactive sessions
- Token is automatically refreshed by the CLI; no manual credential management required
- Not recommended for automated/unattended scenarios — use a Service Principal or Managed Identity instead
- Only works on machines with the Azure CLI installed
Keyless authentication for GitHub Actions, Kubernetes/AKS, Azure DevOps Pipelines, and any OIDC-compliant system. A short-lived JWT issued by the external identity provider is exchanged for an Azure AD access token — no client secret or certificate is required on the App Registration.
Three token sources are supported:
| Mode | Description |
|---|---|
| File-based | Token is read from a projected file path (Kubernetes/AKS Workload Identity) |
| GitHub Actions OIDC | Token is requested from the GitHub Actions runtime endpoint automatically |
| Manual token | Caller supplies a federated JWT obtained from another OIDC source |
- An Azure AD App Registration with a Federated Identity Credential configured for the appropriate issuer and subject
- The Service Principal must be added to the Azure DevOps organisation with required permissions
# ── 1. File-based token (Kubernetes / AKS Workload Identity) ─────────────────
# AKS projects the service-account token at the path in AZURE_FEDERATED_TOKEN_FILE.
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-FederatedTokenFile $ENV:AZURE_FEDERATED_TOKEN_FILE
# Hard-coded file path variant
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-FederatedTokenFile '/var/run/secrets/azure/tokens/azure-identity-token'
# ── 2. GitHub Actions OIDC ────────────────────────────────────────────────────
# The workflow must grant `id-token: write` permission.
# ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN are injected
# automatically by GitHub Actions when that permission is present.
#
# GitHub Actions workflow snippet:
# permissions:
# id-token: write
# contents: read
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-useGitHubActionsOIDC
# Custom audience (must match the federated identity credential audience in Azure AD)
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-useGitHubActionsOIDC `
-GitHubActionsAudience 'api://AzureADTokenExchange'
# ── 3. Manually-supplied federated token ─────────────────────────────────────
# Use when the OIDC token has already been acquired externally (e.g. Azure DevOps
# Pipelines OIDC service connection) and is available as a variable.
$FederatedJWT = $ENV:SYSTEM_OIDCTOKEN | ConvertTo-SecureString -AsPlainText -Force
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-FederatedToken $FederatedJWT
# ── Skip connectivity verification (any mode) ─────────────────────────────────
New-AzDoAuthenticationProvider `
-OrganizationName 'my-organization' `
-TenantId '00000000-0000-0000-0000-000000000000' `
-ClientId 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
-FederatedTokenFile '/var/run/secrets/azure/tokens/azure-identity-token' `
-NoVerify- No secrets stored in CI/CD — tokens are short-lived and issued on demand
- Recommended for modern CI/CD systems (GitHub Actions, Azure DevOps Pipelines, AKS)
- Manually-supplied tokens are not automatically refreshed; call
New-AzDoAuthenticationProvideragain with a fresh token when the current one expires
Before passing credentials to New-AzDoAuthenticationProvider, retrieve them from a secure store
rather than hardcoding them.
# Retrieve PAT from Key Vault
$token = (Get-AzKeyVaultSecret -VaultName 'MyKeyVault' -Name 'AzureDevOpsPAT').SecretValue
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -SecureStringPersonalAccessToken $token# Install SecretStore module
Install-Module Microsoft.PowerShell.SecretStore
# Store credential (one-time setup)
Set-Secret -Name AzureDevOpsPAT -Secret 'your-pat-token' -Vault SecretStore
# Retrieve in script
$token = Get-Secret -Name AzureDevOpsPAT -AsPlainText
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -PersonalAccessToken $token# Store PAT in Credential Manager (one-time setup)
$cred = New-Object System.Management.Automation.PSCredential(
'AzureDevOpsDsc',
(ConvertTo-SecureString 'your-pat-token' -AsPlainText -Force)
)
$cred | Export-Clixml -Path "$env:APPDATA\AzureDevOpsDsc\cred.xml"
# Retrieve in script
$cred = Import-Clixml -Path "$env:APPDATA\AzureDevOpsDsc\cred.xml"
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -SecureStringPersonalAccessToken $cred.Password| Method | Best For | Pros | Cons |
|---|---|---|---|
| PAT | Local dev, general use | Simple, no Azure AD required | Requires token management and rotation |
| Managed Identity | Azure VMs, Arc, Automation | No credentials to manage, secure | Azure-hosted resources only |
| Service Principal (secret) | CI/CD, on-premises automation | Works anywhere | Secret management required |
| Service Principal (cert) | High-security scenarios | More secure than secrets | More complex certificate lifecycle |
| Azure CLI | Local development | Automatic, uses existing login | Not suitable for automation |
| Workload Identity | GitHub Actions, AKS, ADO Pipelines | Keyless, short-lived tokens | Requires OIDC federation setup |
Verify the token or credentials are correct and have not expired. For PAT, check that the token still exists in Azure DevOps and has the required scopes.
The authenticated identity lacks the necessary permissions in Azure DevOps:
- Check group memberships and permission assignments for the identity
- For PAT, review the token scopes (Full access or specific scopes required)
- PAT: Create a new token in Azure DevOps
- Service Principal secret: Rotate the secret in Azure AD
-
Azure CLI: Re-run
az login - Workload Identity (manual): Acquire a fresh federated token
# Verify the module is installed
Get-Module -ListAvailable | Where-Object Name -eq AzureDevOpsDscNative
# Import explicitly if needed
Import-Module -Name AzureDevOpsDscNative- Use the minimum required permissions for the authenticated identity
- Store all credentials in a secure vault — never in code or config files
- Set expiration dates on PATs and rotate them regularly
- Rotate service principal secrets before they expire
- Monitor authentication logs and audit access regularly
- Revoke unused credentials and service principals
- Use MFA for personal accounts (PAT is tied to the user account)
- Prefer Managed Identity or Workload Identity over long-lived secrets where possible
- Assert-BoundParameter
- Assert-ElevatedUser
- Assert-IPAddress
- Assert-Module
- AzDoAPI_0_ProjectCache
- AzDoAPI_1_GroupCache
- AzDoAPI_2_UserCache
- AzDoAPI_3_GroupMemberCache
- AzDoAPI_4_GitRepositoryCache
- AzDoAPI_5_PermissionsCache
- AzDoAPI_6_ServicePrinciple
- AzDoAPI_7_IdentitySubjectDescriptors
- AzDoAPI_8_ProjectProcessTemplates
- AzDoAPI_9_DevOpsClassificationNodes
- Compare-DscParameterState
- Compare-ResourcePropertyState
- ConvertFrom-DscResourceInstance
- ConvertTo-Base64String
- ConvertTo-CimInstance
- ConvertTo-HashTable
- Find-Certificate
- Format-Path
- Get-AzDevOpsOperation
- Get-AzDevOpsServicesApiUri
- Get-AzDevOpsServicesUri
- AzDoAgentPool
- AzDoAgentPoolPermission
- AzDoAgentQueue
- AzDoAreaNodes
- AzDoAreaPermission
- AzDoArtifactFeed
- AzDoArtifactFeedPermission
- AzDoArtifactFeedSettings
- AzDoArtifactFeedView
- AzDoAuditStream
- AzDoBranchPolicy
- AzDoCheckConfiguration
- AzDoDeploymentGroup
- AzDoEnvironmentApproval
- AzDoEnvironmentPermission
- AzDoExtension
- AzDoGitPermission
- AzDoGitRepository
- AzDoGroupMember
- AzDoGroupPermission
- AzDoIterationNodes
- AzDoIterationPermission
- AzDoNotificationSubscription
- AzDoOrganizationGroup
- AzDoOrganizationSettings
- AzDoPipeline
- AzDoPipelineEnvironment
- AzDoPipelinePermission
- AzDoPipelineSettings
- AzDoProcess
- AzDoProcessPermission
- AzDoProject
- AzDoProjectGroup
- AzDoProjectPermission
- AzDoProjectServices
- AzDoRepositorySettings
- AzDoSecurityNamespacePermission
- AzDoServiceConnection
- AzDoServiceConnectionPermission
- AzDoServiceHook
- AzDoTaskGroup
- AzDoTeam
- AzDoTeamMember
- AzDoTeamSettings
- AzDoUserEntitlement
- AzDoVariableGroup
- AzDoVariableGroupPermission
- AzDoWiki
- AzDoWIPTags