For the complete documentation index, see llms.txt. This page is also available as Markdown.

optional Step - Automatic Desktop Update - using Azure DevOps pipeline

After the initial SCA Win32 application has been created and successfully tested, you can use the supplied Azure DevOps pipeline to update the existing application.

Before You Begin: Access and Responsibilities

Use an Intune tenant with an active subscription, an existing SCA Windows app (Win32), and a successfully tested Windows pilot device. You also need an Azure DevOps project with Azure Repos and available Microsoft-hosted Windows pipeline capacity. Azure DevOps access alone does not grant access to Intune.

The administrator configuring the solution and the identity running the pipeline require different permissions:

Responsibility
Required access

Review and manage the SCA app in Intune

Use the Intune Intune Administrator role, or an approved custom role with the relevant app read, update, and assignment permissions. The role assignment must include the applicable scope groups and scope tags. Read access is sufficient for inspection; changing properties or assignments requires the corresponding write permissions.

Create and maintain the Entra App Registration

The setup administrator must be allowed to register applications and manage this registration, including its certificates. An owner of the registration can maintain its credentials. If application registration is restricted, ask your Entra administrator to create the registration and assign the approved owners.

Grant Microsoft Graph application consent

A Privileged Role Administrator or Global Administrator grants tenant-wide admin consent. Application Administrator, Cloud Application Administrator, and Intune Administrator alone do not grant this Microsoft Graph application consent. Activate the required role through PIM first if your organization uses eligible assignments.

Run the unattended Intune update

The pipeline service principal uses the Microsoft Graph Application permission DeviceManagementApps.ReadWrite.All, with admin consent, and a registered certificate. No interactive administrator sign-in occurs during the run.

Create and maintain the Azure DevOps pipeline

Use an account with access to Azure Repos, normally Basic access or higher, repository Read and Contribute permissions, and the pipeline permissions needed to create and edit build pipelines. Creating a new repository additionally requires Create repository permission.

Operate and review the pipeline

Operators need Queue builds to start runs and View builds / View build pipeline to review them. Maintaining its variables and definition requires Edit build pipeline. The selected agent pool and repository must be available to the pipeline.

Confirm access before creating credentials:

  • In Intune, open the SCA app and confirm that you can inspect its properties, assignments, and installation status. Ask your Intune role administrator to review the role assignment if the app is missing or an action is unavailable.

  • In Entra ID, agree who owns the automation registration and who will grant consent. The Intune administrator does not need permanent Global Administrator access to operate this solution.

  • In Azure DevOps, have the project administrator check repository and pipeline security if you cannot save or run the pipeline. The pipeline build identity needs repository read access for checkout; it does not need repository write access for this workflow.

  • For verification, ensure that you can inspect the pilot device. Triggering Sync from the Intune admin center requires the relevant remote-task permission; alternatively, initiate synchronization locally on the test device.

How the Pipeline Works

The Windows pipeline supports the following modes:

Mode
Description

Validation-only

Downloads and validates the selected SCA release and publishes audit artifacts. It does not connect to or modify Intune.

What-If

Compares the latest release with the existing Intune application and records the decision. It does not package, upload, or modify the application.

Publish

Updates the existing Intune application only when the selected GitHub release is newer. An equal or older version completes without an update.

What-If requires the existing Intune app and Microsoft Graph authentication because it compares the release with the current Intune application. Validation-only does not require Graph credentials.

1

Identify the Existing Intune Application

  • Open the Microsoft Intune admin center and go to Apps → All apps.

  • Open the SCA Windows app created in Step 3 and record its application ID. If the ID is not displayed in the application details, copy the GUID following appId/ in the browser address while the app is open.

  • Under Properties, verify that the app has exactly one MSI ProductCode detection rule.

  • Review Assignments and confirm which devices receive this application.

2

Create the Pipeline App Registration

Have a Privileged Role Administrator or Global Administrator

  • Open the Microsoft Entra admin center and navigate to App registrations → New registration.

  • Enter SCA Intune Update Pipeline as the name.

  • Select Accounts in this organizational directory only, leave the redirect URI empty, and select Register.

  • On the Overview page, record the Directory (tenant) ID and Application (client) ID. These become INTUNE_TENANT_ID and INTUNE_CLIENT_ID in the pipeline.

  • Open API permissions → Add a permission → Microsoft Graph → Application permissions.

  • Search for DeviceManagementApps.ReadWrite.All, select it, and choose Add permissions.

  • Open this registration and select Grant admin consent for your organization. If you do not hold that role, hand over the registration name, tenant ID, client ID, requested permission, and its purpose to your Entra administrator.

  • Confirm that DeviceManagementApps.ReadWrite.All appears with Type: Application and a granted status for the correct tenant. Adding the permission without granting consent is not sufficient. A delegated permission does not provide the unattended access used here.

Record the responsible application owners and certificate renewal contact. Do not assign Global Administrator or Intune Administrator to the service principal for this workflow; it uses the consented Graph application permission.

The pipeline App Registration is a separate automation identity. Do not use the SCA Enterprise Application ID or the MSI ProductCode as INTUNE_CLIENT_ID. INTUNE_APP_ID identifies the Windows app in Intune; INTUNE_CLIENT_ID identifies this new App Registration in Entra ID.

3

Create and Register the Certificate

  • Obtain a certificate according to your organization's certificate policy. You need a public .cer file and a matching password-protected .pfx file containing the private key.

For a pilot, you can create a self-signed certificate using the following example. If you already have the required files, continue with uploading the public certificate.

  • Open PowerShell on your Windows administrator workstation and run:

Record the PFX password in your approved password manager. Keep the PowerShell session open for the conversion step.

  • In the pipeline App Registration, open Certificates & secrets → Certificates → Upload certificate.

  • Select the public .cer file and choose Add. The public certificate goes into Entra ID; the PFX is used by the pipeline.

  • Confirm that the certificate is listed and record its expiration date.

  • Convert the PFX to Base64 and copy the result to your clipboard:

If you are using an existing PFX, set $scaPfxPath to its full path. Paste the copied value into the secret variable INTUNE_CERTIFICATE_BASE64 in the pipeline variables.

4

Create the Azure DevOps Pipeline

  • Open the release repository linked in Step 3. Select Code → Download ZIP, extract the archive, and locate .azure-pipelines.

  • In your Azure DevOps project, open Repos → Files and create or select an administrator-owned automation repository.

  • Add and commit the complete .azure-pipelines folder using your normal Git workflow. Keep this structure:

  • Open Pipelines → New pipeline and select Azure Repos Git.

  • Select your automation repository, then choose Existing Azure Pipelines YAML file.

  • Select the branch containing the files and the path .azure-pipelines/azure-publish-sca-intune-win.yml.

  • Continue to the YAML review and save the pipeline. Use Save rather than starting a publish run during setup.

  • Give the pipeline a recognizable name such as SCA Windows - Update Intune.

The supplied YAML authenticates directly through a certificate in its PowerShell steps. It does not require an Azure Resource Manager service connection. Your Azure DevOps organization must have access to a Microsoft-hosted Windows agent.

5

Configure Pipeline Variables

  • Open your saved pipeline and select Edit → Variables → New variable.

  • Add the following variables using the names exactly as shown. For this guide, use pipeline variables directly; a variable group additionally requires a YAML group reference and pipeline authorization.

Variable
Value
Secret

INTUNE_TENANT_ID

Microsoft Entra Directory (tenant) ID.

No

INTUNE_CLIENT_ID

Application (client) ID of the pipeline App Registration.

No

INTUNE_APP_ID

Intune application ID of the existing SCA Windows app created in Step 3.

No

INTUNE_CERTIFICATE_BASE64

Base64-encoded content of the password-protected PFX file.

Yes

INTUNE_CERTIFICATE_PASSWORD

Password of the PFX file.

Yes

SECURE_CONTACTS_GITHUB_TOKEN

Optional GitHub token for authenticated release access or to avoid anonymous API rate limits.

Yes

SECURE_CONTACTS_MSI_SHA256

Optional expected SHA-256 value for an explicitly controlled release.

No

SECURE_CONTACTS_EXPECTED_SIGNER

Optional expected MSI signer used during package validation.

No

The GitHub token is optional while the release repository is public and the anonymous API limit is sufficient. If a token is used, use a customer-owned fine-grained token with Contents: Read-only access and store it as a secret variable.

  • Enable Keep this value secret for INTUNE_CERTIFICATE_BASE64, INTUNE_CERTIFICATE_PASSWORD, and the GitHub token if used. Paste the Base64 PFX value copied during certificate setup and enter the password used for that PFX.

Leave the optional hash and signer override variables undefined unless your organization deliberately uses them. A fixed MSI hash must be updated when the release changes.

  • Save the variables and pipeline.

Do not enter a certificate thumbprint manually. The pipeline imports the PFX, derives its thumbprint, and uses it for authentication. Its cleanup step removes the temporary PFX and imported certificate.

6

Run Validation-only

  • Open the pipeline and select Run pipeline.

  • Select the configured branch. Leave both Publish to Intune and Review only (What-If) unchecked.

  • Select Run and watch the steps Locate Windows pipeline script, Install pinned IntuneWin32App module, and Validate or publish Secure Contacts.

When the run finishes, open its summary and download the published artifact secure-contacts-intune-artifacts. In the release-tag folder, review manifest.json and confirm that the generated .intunewin package is present. Validation-only also packages the MSI; it does not upload it to Intune.

7

Run a What-If Preview

  • Select Run pipeline again and set:

Azure DevOps option
Selection

Publish to Intune

Unchecked

Review only (What-If)

Checked

  • Start the run. The pipeline imports the certificate and connects to Microsoft Graph.

  • Open the run summary and download secure-contacts-intune-artifacts.

  • Open decision-manifest.json in the release-tag folder and confirm IntuneAppId, IntuneDisplayName, IntuneVersion, ReleaseTag, and Decision against your intended target.

If a newer release exists, the preview validates its MSI without creating or uploading an update package. If the candidate is equal to or older than the Intune version, NoUpdateRequired is a successful result.

For a newer candidate, review the planned MSI ProductCode change in the decision and logs. A NoUpdateRequired run returns before downloading the MSI or checking its detection-rule compatibility. It confirms the version comparison, not a complete update rehearsal. What-If does not test write access, upload, or installation on a device.

8

Publish the Update

  • Return to the application in Intune and recheck its assignments. Confirm that the assigned devices may receive the update.

  • In Azure DevOps, select Run pipeline and set:

Azure DevOps option
Selection

Publish to Intune

Checked

Review only (What-If)

Unchecked

  • Start the run. The pipeline compares the release with the existing Intune application. If the release is newer, it downloads and validates the MSI, creates the IntuneWin package, and updates the application.

  • Review the Validate or publish Secure Contacts result and the published audit artifacts.

  • In Intune, review the application version, install command, uninstall command, and MSI detection rule.

  • If the MSI ProductCode changes, the pipeline replaces the existing MSI detection rule and preserves unrelated detection rules.

9

Validate the Update

  • Synchronize a Windows test device with Intune and allow the update to be processed.

  • Confirm that Intune reports the app as installed and that SCA starts with the new version.

  • Verify sign-in, licensing, App Configuration, contact synchronization, and the required desktop functions.

If the app was assigned only to pilot devices, expand its assignments after accepting the results. If production devices were already assigned, publishing has already made the update available to that scope.

10

Optional: Schedule Automatic Updates

The supplied YAML runs manually by default and includes a commented daily schedule example.

Complete a successful manual publish and pilot verification first.

  • Edit azure-publish-sca-intune-win.yml in your Azure DevOps repository.

  • In the existing parameters block, change the default for publish to true. Leave whatIf set to false:

  • Replace the existing block; do not add a second parameter block. Scheduled runs use these defaults, and they also become the defaults displayed for manual runs.

  • Uncomment the existing schedule or add this top-level block after trigger: none:

  • Replace main if your pipeline uses another branch. Keep the existing pool, variables, and steps.

  • Commit the changes to that branch. In Azure DevOps, check Scheduled runs to confirm the next execution. If you have configured a schedule in the pipeline UI, remove it before relying on the YAML schedule.

  • Review the first scheduled run and its artifacts.

Assign an operational owner to review failed runs and certificate expiry. Use your organization's Azure DevOps notification settings to notify the responsible team of build failures. To pause automatic publishing, remove or comment out the YAML schedule and commit the change; also check for schedules configured in the pipeline UI. Already running jobs must be handled separately.

The example runs daily at 06:00 UTC. always: true allows it to check for releases even when the automation repository has not changed. With publish defaulting to true, a newer release is automatically published to the selected Intune app and becomes available to its assigned devices.

Troubleshooting and Certificate Renewal

Result or error
Action

No hosted agent is available

Check your Azure DevOps hosted parallel-job entitlement and agent access.

Expected exactly one script

Check the full checkout for missing or duplicate Sync-SecureContactsToIntune.ps1 files.

Certificate import fails

Check the Base64 value, PFX password, and whether the PFX contains the private key.

Graph authentication fails

Check tenant ID, client ID, certificate expiry, and the public certificate registered on the pipeline App Registration.

Graph access is denied

Check the DeviceManagementApps.ReadWrite.All application permission and admin consent.

Target app cannot be found

Check the tenant and INTUNE_APP_ID. Use the Intune app ID, not an Entra ID or MSI ProductCode.

MSI rule validation fails

Check that the target Win32 app has exactly one MSI detection rule.

GitHub access or rate-limit error

Check release access and configure the optional read-only token if required.

NoUpdateRequired

No change is needed. The selected release is not newer than the version in Intune.

If a publish run fails after upload starts, inspect the app's content state, version, commands, and detection rules before retrying. The upload and metadata update are separate operations; a failed run does not guarantee that Intune is unchanged. The script does not automatically roll back. It also skips an equal or older release, so selecting an older release tag is not a rollback procedure.

Renew the Pipeline Certificate

1

Arrange the renewal

  • Arrange renewal before the recorded expiry date and obtain a new public certificate and matching password-protected PFX as described in section 3.

2

Upload the new certificate

  • Upload the new public certificate to the same App Registration. Keep the previous certificate registered during the transition.

3

Update pipeline credentials

  • When no publish run is active, replace both INTUNE_CERTIFICATE_BASE64 and INTUNE_CERTIFICATE_PASSWORD with the new matching values. Keep both marked as secret. The tenant ID, client ID, and Intune app ID stay the same.

4

Verify authentication

  • Save and start a Review only (What-If) run with Publish to Intune unchecked. Confirm successful certificate authentication and lookup of the expected Intune app. A NoUpdateRequired result is sufficient to verify this authentication step.

5

Remove the old certificate

  • After successful verification and confirmation that no other approved job uses the old credential, remove the old certificate from the App Registration. Record the new expiry date and renewal owner.

6

Handle the private-key files

  • Retain or dispose of the exported private-key files according to your organization's credential policy. Pipeline cleanup does not remove the PFX or certificate from the administrator workstation used to create them.

Last updated

Was this helpful?