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

optional Step - Automatic Desktop Update - using Azure DevOps pipeline

Before You Begin: Permissions and Responsibilities

You need an active Intune tenant, the existing macOS app ID, an Azure DevOps project and repository, and available Microsoft-hosted macOS pipeline capacity.

Responsibility
Required access

Manage the Intune application

Use Application Manager or an approved custom role with the required app read, update, and assignment permissions. Include the correct scope groups and tags. Configuration profile changes require separate profile-management permissions.

Maintain the App Registration

The administrator must be permitted to register applications and manage the selected registration and its certificates. If registration is restricted, have your Entra administrator create it and assign its approved owners.

Grant Graph application consent

A Privileged Role Administrator or Global Administrator grants consent. Intune Administrator, Application Administrator, and Cloud Application Administrator alone cannot grant this Microsoft Graph application permission. Activate the required role through PIM if applicable.

Run the unattended update

The pipeline service principal requires Microsoft Graph Application permission DeviceManagementApps.ReadWrite.All, admin consent, and a registered certificate.

Maintain Azure DevOps

Use repository access, normally Basic or higher, with Read and Contribute permissions, plus the required Create build pipeline and Edit build pipeline permissions. Creating a repository requires Create repository permission.

Run and inspect pipelines

Operators need Queue builds, View builds, and View build pipeline. Editing variables requires Edit build pipeline. The pipeline needs access to the repository, hosted agent pool, and deployment environment.

Manage the deployment environment

An environment Creator can create the environment; its Administrator can maintain access. Assign approved people to manage its checks and approve deployments.

Agree who maintains the registration, credentials, pipeline, and failed-run notifications before enabling scheduled updates. The administrator who operates the pipeline does not need permanent Global Administrator access. The build identity needs repository read access for checkout; this workflow does not require it to write to the repository.

How the Pipeline Works

Mode
Behavior

Validation-only

Downloads the PKG and matching checksum, validates the package, and publishes artifacts. No Graph authentication or Intune changes.

Review only (What-If)

Authenticates, reads the existing macOS PKG app, and compares its SCA bundle version with the selected release. Produces a decision manifest. No PKG download, package validation, or Intune writes.

Publish to Intune

Compares versions, downloads and validates a newer package, then passes that artifact to the Publish stage. The stage uses the configured deployment environment and updates the existing app.

1

Identify the Existing Intune Application

  • In Intune, open Apps → All apps and select the SCA macOS application created in Step 2.

  • Confirm its type is macOS app (PKG). Record its Intune app ID from the application address if necessary: the GUID following appId/.

  • Review Included apps. There must be exactly one entry matching de.provectus.SecureContactsDesktop, with the actual deployed numeric bundle version.

  • Confirm Ignore app version is No for this version-controlled rollout and review the app's assignments. Record the current package version and pilot scope.

2

Create the Pipeline App Registration

  • Open Microsoft Entra admin center → App registrations → New registration.

  • Enter SCA macOS Intune Update Pipeline, select Accounts in this organizational directory only, and leave the redirect URI empty. Select Register.

  • Record the Directory (tenant) ID and Application (client) ID.

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

Privileged Role Administrator or Global Administrator grant admin consent.

  • Confirm the permission is listed as Application and granted for your tenant.

INTUNE_CLIENT_ID identifies the pipeline App Registration: who performs the update. INTUNE_MACOS_APP_ID identifies the existing Intune PKG app: which app is updated. Neither variable contains the SCA Enterprise Application ID or the macOS bundle ID.

3

Prepare and Register the Certificate

  • Obtain an organization-approved certificate with a public certificate file and a matching password-protected PKCS#12 file (.p12 or .pfx) containing the private key.

  • Open Terminal and run:

Enter a strong private-key passphrase when prompted. During PKCS#12 export, supply that passphrase and choose a strong export password.

  • Store the export password in your approved password manager; this is the pipeline certificate password.

  • In the pipeline App Registration, select Certificates & secrets → Certificates → Upload certificate. Upload the public .cer file.

  • Confirm that the certificate is listed. Record its expiry date and responsible owner.

  • Copy the PKCS#12 file as a single Base64 value:

For an existing certificate, substitute its actual path. Paste the result into the secret variable in Configure Pipeline Variables below.

4

Create the Pipeline and Deployment Environment

  • Open the release repository through Step 2, download the source ZIP, and locate .azure-pipelines.

  • Commit the complete folder to your administrator-owned Azure Repos repository using your normal reviewed Git workflow:

  • The checkout must contain exactly one Validate-SecureContactsPackage.sh, with Sync-SecureContactsToIntune.sh beside it.

  • In Pipelines → New pipeline, select Azure Repos Git, your repository, and Existing Azure Pipelines YAML file.

  • Select the reviewed branch and .azure-pipelines/azure-publish-sca-intune-macos.yml. Save the pipeline and name it SCA macOS - Update Intune.

  • Open Pipelines → Environments → Create environment. Create an empty environment named exactly intune-production, matching the supplied YAML.

  • Select None for resources.

Restrict environment pipeline access to the SCA macOS pipeline. If the environment already exists, have its administrator review the existing access and checks before using it.

  • Confirm that the pipeline can use the environment and that an approver is available for the first publication.

  • An environment name alone does not create an approval requirement.

Both stages use macOS-latest. Authentication uses Azure CLI with a certificate. This workflow does not need an Azure Resource Manager service connection or an Azure subscription role; Intune access comes from the consented Graph application permission.

5

Configure Pipeline Variables

  • Open the pipeline and select Edit → Variables → New variable.

  • Add these exact names as pipeline variables:

Variable
Value
Secret

INTUNE_TENANT_ID

Directory (tenant) ID.

No

INTUNE_CLIENT_ID

Application (client) ID of the pipeline registration.

No

INTUNE_MACOS_APP_ID

Intune app ID of the existing macOS PKG app.

No

INTUNE_CERTIFICATE_BASE64

Single-line Base64 content of the password-protected PKCS#12 file.

Yes

INTUNE_CERTIFICATE_PASSWORD

PKCS#12 export password.

Yes

SECURE_CONTACTS_GITHUB_TOKEN

Optional customer-owned token for release access or authenticated API limits.

Yes

  • Enable Keep this value secret for the certificate, password, and optional token. Use a read-only GitHub token with access to the release repository if required.

  • Save the variables. If you use a variable group instead, add its group reference to the YAML and authorize this pipeline to use it; creating a group alone does not make its values available.

The YAML maps INTUNE_MACOS_APP_ID to the script environment variable INTUNE_APP_ID. Configure the macOS-specific name in Azure DevOps. The supplied macOS YAML does not use the Windows MSI hash, signer-override, or certificate-thumbprint variables.

6

Run Validation-only

  • Select Run pipeline and choose the reviewed branch.

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

  • Select Run.

Watch Download and validate package in the Validate stage. It checks the checksum, installer signer, Gatekeeper assessment, bundle identity, version, and ARM64 executable.

Download secure-contacts-macos-intune-artifacts from the run summary. Review the PKG, its matching checksum file, and validation-manifest.json. Confirm ValidationResult is Validated and the package identity and version are expected.

7

Run a What-If Preview

Start another run with:

Azure DevOps option
Selection

Publish to Intune

Unchecked

Review only (What-If)

Checked

  • Review Compare GitHub and Intune versions and open decision-manifest.json in secure-contacts-macos-intune-artifacts.

  • Check IntuneAppId, BundleId, CandidateVersion, IntuneBundleVersion, and Decision. Confirm that the target is the intended macOS app.

Interpret the result:

  • UpdateExistingApp: the candidate version is newer.

  • NoUpdateRequired: the candidate is equal to or older than the existing included-app version.

macOS What-If is a metadata-only comparison. Even when an update is available, it does not download or validate the PKG. A successful result also does not prove upload permission or successful installation.

8

Publish the Update

  • Recheck the target app's assignments and confirm that the currently assigned devices may receive the update.

  • Start a run with:

Azure DevOps option
Selection

Publish to Intune

Checked

Review only (What-If)

Unchecked

  • The Validate stage compares versions. If no newer version is available, the Publish stage is skipped. Otherwise, it downloads and validates the package.

  • If approval is configured on intune-production, review the validation artifact from this run before approving the Publish stage. Confirm its package version, bundle ID, and validation result.

  • The Publish stage consumes that artifact, validates it again, authenticates, uploads the encrypted content, and commits the new version to Intune.

  • Review Publish validated package to Intune, the final run result, and secure-contacts-macos-intune-publish-artifacts. A validation manifest alone is not proof of successful publication.

9

Verify in Intune

  • Confirm the new package and bundle version is updated in Intune.

  • The script updates the package content, file name, primary bundle version, SCA's version and the description to Secure Contacts Desktop - Release: <version>.

The bundle identity is preserved, and unrelated Included apps entries are retained. The script does update SCA's version metadata used by detection; it does not create a new detection model or change the app's assignments or configuration profile.

10

Verify the Updated Mac

  • Synchronize the pilot Mac and allow Intune to process the update.

  • Confirm Intune installation status and the actual installed version.

  • Verify that managed preferences, licensing, sign-in, and contact synchronization still work. Updating the package does not update the preference profile.

  • Expand assignments after pilot acceptance. If the app already had production assignments, publishing has already exposed the update to that scope.

11

Optional: Schedule Update Checks and Publishing

  • Complete a successful manual publication and pilot verification first.

  • In the existing YAML parameter block, set the default for publish to true and keep whatIf at false:

Uncomment the supplied schedule, or add this top-level block after trigger: none:

  • Replace main if necessary and commit to that branch. Remove any conflicting UI schedule, then commit a change so Azure DevOps reevaluates the YAML schedule. Inspect Scheduled runs.

  • Review the first scheduled run and assign an owner for failures and certificate expiry. Configure the team's Azure DevOps notifications according to your operating process.

The example checks daily at 06:00 UTC even without repository changes. Environment approval checks still apply. With an approval check, a newer package waits for approval; without one, it can publish automatically. These parameter defaults also appear in manual runs.

Operational Acceptance

Before enabling unattended operation, record:

  • The Azure DevOps pipeline, reviewed branch, and source revision.

  • The target tenant and macOS Intune app ID.

  • The environment approval policy and authorized approvers.

  • The registration owners, certificate expiry, and renewal contact.

  • The successful publish run and corresponding pilot-device results.

  • The team responsible for reviewing failed or approval-pending runs.

Keep the decision and validation artifacts with the release record. Review repository updates before replacing your pipeline bundle; copying the files once does not automatically keep the customer repository synchronized with upstream changes.

Troubleshooting and Certificate Renewal

Result or error
Action

No macOS agent available

Check hosted parallel-job capacity and agent-pool access.

Environment missing or unauthorized

Check the exact environment name, its existence, and pipeline permissions.

Waiting for approval

Review the current run's artifact and contact the configured environment approver.

Script lookup fails

Keep one validator in the checkout and the sync script beside it.

Certificate cannot be unlocked

Check the Base64 value, export password, and private key in the PKCS#12 file.

Graph authentication or access fails

Check tenant/client IDs, certificate registration and expiry, application permission, and admin consent.

Target is not a macOSPkgApp

Use the Intune ID of the macOS app (PKG), not a LOB app or the Windows app.

Included-app match or version fails

Check the exact SCA bundle ID and its single numeric version entry.

Package validation fails

Inspect the first validator error and the selected release assets. Do not bypass validation.

NoUpdateRequired

The included-app version is already equal or newer; the normal pipeline skips publication.

Publishing fails or times out

Inspect the app's content state and version before retrying. Publication uses several operations and is not automatically rolled back.

Do not run concurrent publications for the same app. A failed run can leave uncommitted content or partially completed changes. An older release is not an automatic rollback: the publisher rejects downgrades, and the normal preflight skips equal or older releases.

To renew the certificate:

1

Obtain the new certificate

  • Obtain the new certificate and matching password-protected PKCS#12 file before expiry.

2

Upload the public certificate

  • Upload the new public certificate to the same registration while keeping the old certificate during the transition.

3

Replace pipeline secrets

  • With no publish job active, replace both secret certificate variables with the new matching values.

4

Verify authentication

  • Run Review only (What-If) with Publish to Intune unchecked. Confirm authentication and lookup of the intended app; NoUpdateRequired is sufficient for this credential test.

5

Remove the old certificate

  • Once verification succeeds and no other approved job needs the old credential, remove the old certificate from the registration.

6

Record certificate lifecycle details

  • Record the new expiry date. Retain or dispose of workstation private-key files according to your credential policy.

The pipeline removes its temporary certificate files, and the script cleans up its temporary authentication files. That does not remove credentials exported on the administrator workstation.

Last updated

Was this helpful?