-
-
Notifications
You must be signed in to change notification settings - Fork 39
Getting started
Before running IntuneCD create an app registration in Entra ID
After creating the App registration -> browse to API permissions -> Click Add Permission -> Click the Microsoft Graph -> Application permissions.
Select each of the following permissions:
- DeviceManagementApps.ReadWrite.All
- DeviceManagementConfiguration.ReadWrite.All
- DeviceManagementServiceConfig.ReadWrite.All
- DeviceManagementManagedDevices.ReadWrite.All
- DeviceManagementRBAC.ReadWrite.All
- Group.Read.All
- Policy.Read.All
- Policy.ReadWrite.ConditionalAccess
- Application.Read.All
- Domain.ReadWrite.All
- Policy.ReadAll
- Policy.ReadWrite.AuthenticationFlows
- Policy.ReadWrite.AuthenticationMethod
- Policy.ReadWrite.Authorization
- Policy.ReadWrite.DeviceConfiguration
- Policy.ReadWrite.ExternalIdentities
- Policy.ReadWrite.SecurityDefaults
- Group.ReadWrite.All
Make sure to perform all necessary security reviews within your organizations before deploying in production environments
IntuneCD is built using Python and requires Python version 3.9 or higher to be installed. To install Python on your device, head over to https://python.org
The tool can run on any platform, and does not require you to have any knowledge of Python.
IntuneCD is available on PyPi and can be installed using pip:
pip install IntuneCD
Updating IntuneCD is also done using pip:
pip install IntuneCD --upgrade
To see what parameters you must provide when using IntuneCD, run the following in your terminal:
IntuneCD-startbackup --help
IntuneCD-startupdate --help
IntuneCD-startdocumentation --help
# PIPELINE VARIABLES THAT NEEDS TO BE DEFINED FIRST FOR THIS PIPELINE TO WORK:
# CLIENT_ID (application ID), CLIENT_SECRET (application secret), TENANT_NAME, USER_EMAIL (email that will be used in the commit), USER_NAME (name that will be used in commit)
# based on https://github.com/aaronparker/intune-backup-template
trigger:
none
schedules:
- cron: '0 1 * * *'
displayName: "1am"
branches:
include:
- main
always: true
jobs:
- job: backup_document
displayName: Backup configuration and generate markdown
pool:
vmImage: ubuntu-latest
continueOnError: false
steps:
- checkout: self
persistCredentials: true
# Set git global settings
- task: Bash@3
displayName: Configure Git
inputs:
targetType: 'inline'
script: |
git config --global user.name $(USER_NAME)
git config --global user.email $(USER_EMAIL)
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: true
- task: Bash@3
displayName: Remove existing prod-backup directory
inputs:
targetType: 'inline'
script: |
rm -rfv "$(Build.SourcesDirectory)/prod-backup"
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: false
# Install IntuneCD
# https://github.com/almenscorner/IntuneCD
- task: Bash@3
displayName: Install IntuneCD
inputs:
targetType: 'inline'
script: |
pip3 install IntuneCD
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: true
# Backup the latest configuration, using the current directory
- task: Bash@3
displayName: IntuneCD backup
inputs:
targetType: 'inline'
script: |
mkdir -p "$(Build.SourcesDirectory)/prod-backup"
IntuneCD-startbackup \
--mode=1 \
--output=json \
--path="$(Build.SourcesDirectory)/prod-backup"
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: true
env:
TENANT_NAME: $(TENANT_NAME)
CLIENT_ID: $(CLIENT_ID)
CLIENT_SECRET: $(CLIENT_SECRET)
# Commit changes and push to repo
- task: Bash@3
displayName: Commit changes
name: commitAndsetVariable
inputs:
targetType: 'inline'
script: |
DATEF=`date +%Y.%m.%d`
git add --all
# modified files in folder prod-backup
var=$(git diff --name-only --staged -- prod-backup)
echo "##vso[task.setVariable variable=CHANGE_DETECTED;isOutput=true;]$var"
git commit -m "Intune config backup $DATEF"
git push origin HEAD:main
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: false
# Create markdown documentation
# Install IntuneCD
# https://github.com/almenscorner/IntuneCD
- task: Bash@3
displayName: Generate markdown document
inputs:
targetType: 'inline'
script: |
if [ ! -z "$(commitAndsetVariable.CHANGE_DETECTED)" ]
then
INTRO="Intune backup and documentation generated at $(Build.Repository.Uri) <img align=\"right\" width=\"96\" height=\"96\" src=\"./logo.png\">"
IntuneCD-startdocumentation \
--path="$(Build.SourcesDirectory)/prod-backup" \
--outpath="$(Build.SourcesDirectory)/prod-as-built.md" \
--tenantname=$TENANT_NAME \
--intro="$INTRO" \
#--split=Y
else
echo "no configuration backup change detected in the last commit, documentation will not be created"
fi
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: true
env:
TENANT_NAME: $(TENANT_NAME)
# Commit changes and push to repo
- task: Bash@3
displayName: Commit changes
inputs:
targetType: 'inline'
script: |
DATEF=`date +%Y.%m.%d`
git add --all
git commit -m "Intune config as-built $DATEF"
git push origin HEAD:main
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: false
- job: tag
displayName: Tag repo
dependsOn: backup_document
condition: and(succeeded(), ne(dependencies.backup_document.outputs['commitAndsetVariable.CHANGE_DETECTED'], ''))
pool:
vmImage: ubuntu-latest
continueOnError: false
steps:
- checkout: self
persistCredentials: true
# Set git global settings
- task: Bash@3
displayName: Configure Git
inputs:
targetType: 'inline'
script: |
git config --global user.name $(USER_NAME)
git config --global user.email $(USER_EMAIL)
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: true
- task: Bash@3
displayName: Pull origin
inputs:
targetType: 'inline'
script: |
git pull origin main
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: false
- task: PowerShell@2
displayName: Git tag
inputs:
targetType: 'inline'
script: |
# change in configuration backup folder detected, create TAG
$DATEF= Get-Date -format 'yyyy.MM.dd_HH.mm'
git tag -a "v$DATEF" -m "Microsoft Intune configuration snapshot $DATEF"
git push origin "v$DATEF" *> $null # even status information goes to stderr :(
failOnStderr: true
pwsh: false
workingDirectory: '$(Build.SourcesDirectory)'
- job: publish
displayName: Publish as-built artefacts
dependsOn: tag
condition: and(succeeded(), ne(dependencies.backup_document.outputs['commitAndsetVariable.CHANGE_DETECTED'], ''))
pool:
vmImage: ubuntu-latest
continueOnError: false
steps:
- checkout: self
persistCredentials: true
# Install md-to-pdf
# https://github.com/simonhaenisch/md-to-pdf
- task: Bash@3
displayName: Install md-to-pdf
inputs:
targetType: 'inline'
script: |
npm i --location=global md-to-pdf
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: true
# Convert markdown document to HTML
- task: Bash@3
displayName: Convert markdown to HTML
inputs:
targetType: 'inline'
script: |
cat "$(Build.SourcesDirectory)/prod-as-built.md" | md-to-pdf --config-file "$(Build.SourcesDirectory)/md2pdf/htmlconfig.json" --as-html > "$(Build.SourcesDirectory)/prod-as-built.html"
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: false
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: "$(Build.SourcesDirectory)/prod-as-built.html"
artifactName: "prod-as-built.html"
# Convert markdown document to PDF
- task: Bash@3
displayName: Convert markdown to PDF
inputs:
targetType: 'inline'
script: |
cat "$(Build.SourcesDirectory)/prod-as-built.md" | md-to-pdf --config-file "$(Build.SourcesDirectory)/md2pdf/pdfconfig.json" > "$(Build.SourcesDirectory)/prod-as-built.pdf"
workingDirectory: '$(Build.SourcesDirectory)'
failOnStderr: false
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: "$(Build.SourcesDirectory)/prod-as-built.pdf"
artifactName: "prod-as-built.pdf"