PI Services

Le blog des collaborateurs de PI Services

Intune - Détecter l'installation et l'utilisation du New Teams

Avec l'arrivée du New Teams, les IT ont besoin d'inventorier les appareils Windows qui l'ont installé et qui l'utilisent.

Ceci est possible en utilisant un script de remédiation Intune, qui fera le check continu sur tous les appareils concernés.

Script de détection :

function Is-NewTeamsInstalled {
    return (Get-AppxPackage *MSTeams* -ErrorAction SilentlyContinue) -ne $null
}
 
# Function to check if Microsoft Teams is the default IM app
function Is-NewTeamsDefault {
    $registryPath = "HKCU:\Software\IM Providers"
    $registryKey = "DefaultIMApp"
    $defaultValue = Get-ItemProperty -Path $registryPath -Name $registryKey -ErrorAction SilentlyContinue
 
    return ($defaultValue -ne $null) -and ($defaultValue.DefaultIMApp -eq "MSTeams")
}
 
# Main script logic
$teamsInstalled = Is-NewTeamsInstalled
$teamsDefault = Is-NewTeamsDefault
 
if ($teamsInstalled -and $teamsDefault) {
    Write-Host "New Teams installed and is set Default!";Exit 0
} 
elseif ($teamsInstalled -or $teamsDefault) {
    Write-Host "New Teams installed but not set Default."
    Exit 1
}
else {
    Write-Host "New Teams not installed."
    Exit 1
}

 

Intune : Définir le fuseau horaire automatiquement dans Windows 10/11

Afin de détecter les appareils Windows où l'option "Définir le fuseau horaire automatiquement" est désactivée, il suffit d'utiliser un script de remédiation Intune.

Script de détection :

$registrySettings = @(
    @{ Path = "HKLM:\SYSTEM\CurrentControlSet\Services\tzautoupdate"; Name = "Start"; DesiredValue = 3 }
)


    # test if the registry path exists
    if ((Test-Path $registrySettings.Path)) {

        # get the current value of the registry key
      
        $currentValueTZauto = (Get-ItemProperty -Path $registrySettings.Path -ErrorAction SilentlyContinue).$($registrySettings.Name)
  

        # If the current value is not the desired value, update it
        if ($currentValueTZauto -ne $registrySettings.DesiredValue) {
            Write-Host "the current value is Start=$currentValueTZauto, and it is not the desired value"
			exit 1
        } else {
            # If the current value is already correct, do nothing
            Write-Host "the current value is Start=$currentValueTZauto, and it is the desired value"
			exit 0
        }

    } else {
        # If the registry path does not exist, log a warning
        Write-Warning "Registry path $($registrySettings.Path) does not exist."
		exit 1
    }

 

Intune : LAPS - Création du compte admin local

Afin de créer le compte admin local pour qui sera utilisé pour LAPS, nous pouvons utiliser un script de remédiation Intune.

Script de détection :

Start-Transcript -Path "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\LAPSLocalAdmin_Detect.log" -Append

$LAPSAdmin = "Laps"

$Query = Get-WmiObject -Class Win32_UserAccount -Filter "LocalAccount=True"

$Group = Get-WmiObject -Query "Select * From Win32_Group Where LocalAccount = TRUE And SID = 'S-1-5-32-544'"

$Members=$group.GetRelated("win32_useraccount")

If ($Query.Name -notcontains $LAPSAdmin) {

    Write-Output "User: $LAPSAdmin does not existing on the device"
        
    Exit 1

}
Elseif ($Members.Name -notcontains $LAPSAdmin) {

    Write-Output "User $LAPSAdmin created but not member of the group"

    Exit 1
       
    
}
Else {
    
    Write-Output "User $LAPSAdmin exists on the device and member of the group"

    Exit 0
}
Stop-Transcript

Script de remédiation :

Start-Transcript -Path "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\LAPSLocalAdmin_Remediate.log" -Append

$LAPSAdmin = "Laps"

$Query = Get-WmiObject -Class Win32_UserAccount -Filter "LocalAccount=True"

$Group = Get-WmiObject -Query "Select * From Win32_Group Where LocalAccount = TRUE And SID = 'S-1-5-32-544'"

$GroupName = $Group.Name

$Members=$group.GetRelated("win32_useraccount")

If ($Query.Name -notcontains $LAPSAdmin) {

    Write-Output "User: $LAPSAdmin does not existing on the device, creating user"
    
    try {
       
        $password = "fO%B2vcr36+sj2v}<£]L"

        Net User /Add $LAPSAdmin $password /Y
        Write-Output "Added Local User $LAPSAdmin"


        net localgroup $GroupName $LAPSAdmin /add
        Write-Output "Added Local User $LAPSAdmin to Administrators"
        Exit 0

    }
    catch {
        Write-Error "Couldn't create user"
        Exit 1
    }

}
Elseif ($Members.Name -notcontains $LAPSAdmin) {

try {
       
        
        Write-Output "Added Local User $LAPSAdmin"

        net localgroup $GroupName $LAPSAdmin /add
        Write-Output "Added Local User $LAPSAdmin to Administrators"
        Exit 0

    }
    catch {
        Write-Error "Couldn't add user in the group"
        Exit 1
    }

}


Else {
    Write-Output "User $LAPSAdmin exists on the device"
    Exit 0
}

Stop-Transcript

 

Intune : Lister les version Adobe Acrobat Pro via un script de remédiation

Le script ci-dessous peut être utilisé comme un script de remédiation dans Intune.
Seule la partie "Script de détection" sera configurée afin d'avoir la liste des appareils qui ont une version Adobe Acrobat Pro installée.
 
$regkey64 = "HKLM:\SOFTWARE\Adobe\Adobe Acrobat\DC\Installer"
$regkey32 = "HKLM:\SOFTWARE\WOW6432Node\Adobe\Adobe Acrobat\DC\Installer"
$name64 = "ProductCode"
$name32 = "ENU_GUID"
    try
    {
        $exists64 = Get-ItemProperty $regkey64 $name64 -ErrorAction SilentlyContinue
        $exists32 = Get-ItemProperty $regkey32 $name32 -ErrorAction SilentlyContinue
        #Write-Host "Test-RegistryValue: $exists32"
        if ($exists64.ProductCode -eq "{AC76BA86-1033-FFFF-7760-BC15014EA700}")
        {
            Write-Host "Adobe Acrobat Pro 64"
            exit 1
        }
        elseif ($exists32.ENU_GUID -eq "{AC76BA86-1033-FFFF-7760-0C0F074E4100}")
        {
            Write-Host "Adobe Acrobat Pro 32"
            exit 1
        }
        else
        {
            Write-Host "Adobe Acrobat Reader"
            exit 0
        }
    }
    catch
    {
        return $false 
    }
Après l'exécution du script de détection sur tous les appareils Windows concernés, il suffit d'aller sur le "Devices status" :
- Ajouter la colonne "Pre-remediation detection output" pour afficher les version d'Adobe Pro
- Filtrer les appareils 'With issues' dans la colonne "Detection status"
 
 

Intune : Changer le port RDP par défaut sur les appareils Windows

Un de mes clients m'a demandé de changer le port RDP par défaut (3389) par un port personnalisé afin de renforcer la sécurité, sur tous les appareils Windows qui sont gérés par Intune.

Ma proposition était de créer un script de remédiation et le pousser sur tous le parc Windows.

N.B : je vais utiliser le port 6612 comme exemple de port RDP personnalisé.

Script de détection :

# Get RDP information
$PortNumber = (Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp').PortNumber

# Check Custom Port number
if ($PortNumber -eq 6612)
{
    Write-host "Port Number is OK"
    exit 0
    }
else
{
    Write-host "Port Number should be changed from $PortNumber to 6612"
    exit 1
    }

Script de remédiation :

# Declare custom RDP Port value
$portvalue = 6612

Try {
    #Do the RDP port change
	Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -name "PortNumber" -Value $portvalue
	New-NetFirewallRule -DisplayName 'RDPPORTLatest-TCP-In' -Profile 'Public' -Direction Inbound -Action Allow -Protocol TCP -LocalPort $portvalue
    Write-Host "RDP port has changed to $portvalue"
	}
Catch
{
	# Output the Error and Log to a file
    Write-host "Encountered Error:"$_.Exception.Message
	}

 

Script - SCCM - Recuperation et export des Distribution points

Le script ci-dessous requete la base SQL de SCCM pour lister et exporter en CSV, les points de distribution SCCM

 

########################################################################################################
### REQUETE LA BASE SQL DE SCCM POUR OBTENIR LA LISTE DES POINTS DE DISTRIBUTION SCCM.
### EXPORT DES RESULTAT EN FICHIER CSV  #####
######################################################################################################## 

# AUTHOR: CJOURDAN

<# 

    .SYNOPSIS 
        REQUETE LA BASE SQL DE SCCM POUR OBTENIR LA LISTE DES POINTS DE DISTRIBUTION SCCM
        EXPORT DU RESULTAT EN FICHIER CSV.

    .PARAMETER  
        SQLInstance : Instance SQL
        SQLDB : Instance SQL
        SQLQuery : Requete SQL
        ExportFolder : Dossier d'export du fichier CSV
        LogFolder : Chemin du dossier où creer le log du script

 
    .EXAMPLE 
     .\SCCM_SCCM_Distribution_Points.ps1 -SQLInstance SQLSCCM\SCCM -SQLDB CM_BIM -ExportFolder C:\MyExport -LogFolder C:\MyLogs
#>


[CmdletBinding()]
param(
[Parameter(Mandatory=$true,HelpMessage="Instance SQL")]
[string]$SQLInstance,

[Parameter(Mandatory=$true,HelpMessage="Base SQL")]
[string]$SQLDB,

[Parameter(Mandatory=$false,HelpMessage="Requete SQL")] 
[string]$SQLQuery= $("/* --- ALL SCCM DISTRIBUTION POINTS --- */

Declare @UserSIDs As Varchar(25); 
Set @UserSIDs = 'Disabled'

SELECT DISTINCT                 
        dp.ServerName AS Distribution_Point 
        
from fn_rbac_SystemResourceList(@UserSIDs)  as sys 
join fn_rbac_DistributionPointInfo(@UserSIDs)  as dp 
on sys.NALPath = dp.NALPath 
where sys.RoleName = 'SMS Distribution Point'

"),


[Parameter(Mandatory=$true,HelpMessage="Dossier d'export du fichier CSV")]
[string]$ExportFolder,

[Parameter(Mandatory=$true,HelpMessage="Chemin du dossier où creer le log du script")] 
[string]$LogFolder

)


# SCRIPT NAME
$ScriptName = "SCCM_SCCM_Distribution_Points.ps1"


# LogName = ScriptName without extension
$Log = $ScriptName.Split('.')[0]


### FUNCTIONS

# Function Write-Log



function Write-Log 
{ 
    <# 
    .SYNOPSIS 
        This function creates or appends a line to a log file. 
 
    .PARAMETER  Message 
        The message parameter is the log message you'd like to record to the log file. 
 
    .EXAMPLE 
        PS C:\> Write-Log -Message 'Value1' 
        This example shows how to call the Write-Log function with named parameters. 
    #> 
    [CmdletBinding()] 
    param ( 
        [Parameter(Mandatory)] 
        [string]$Message,
        [Parameter(Mandatory)] 
        [string]$LogPath, 
        [Parameter(Mandatory)] 
        [string]$LogName
        
    ) 
     
    try 
    { 
        $DateTime = Get-Date -Format ‘MM-dd-yy HH:mm:ss’ 
        Add-Content -Value "$DateTime # $Message" -Path "$LogPath\$LogName.log" 
    } 
    catch 
    { 
        Write-Error $_.Exception.Message 
    } 
} 


Function GetSQLData {

<# 
    .SYNOPSIS 
        This function query SQL Database and get Data 
 
    .PARAMETER  
        SQLInstance: Instance SQL.
        SQLDB: Base SQL.
        SQLQuery: Requete SQL.

 
    .EXAMPLE 
        GetSQLData -SQLInstance "MyInstance" -SQLDB "MyDB" -SQLQuery "Select * from MyView"
    #> 


[CmdletBinding()] 
    Param( 
        [Parameter(Mandatory=$false)] 
        [string[]] 
        $SQLInstance,
        [Parameter(Mandatory=$false)] 
        [string[]] 
        $SQLDB,
        [Parameter(Mandatory=$false)] 
        [string[]] 
        $SQLQuery
        
        )

$connectionString = "Data Source=$SQLInstance;"+"Integrated Security=SSPI;"+"Initial Catalog=$SQLDB"

$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$command = new-object system.data.sqlclient.sqlcommand($SQLQuery,$connection)
$connection.Open()

$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataSet) | Out-Null

$connection.Close()
$dataSet.Tables

}






# EXECUTE Query ($SQLQuery)
    Write-Log -Message "Execution of GetSQLData on $SQLDB" -LogPath $LogFolder -LogName $Log
    $Result = 
    Try {
        GetSQLData -SQLInstance $SQLInstance -SQLDB $SQLDB -SQLQuery $SQLQuery
        }
    Catch
        {
        $Message = "ERROR DURING EXECUTION OF QUERY"
        Write-Host -F Red $Message
        Write-Log -Message "$Message - $($Error[0].Exception)" -LogPath $LogFolder -LogName $Log
        Exit 1
        }


########################################
# SOUS-REGROUPEMENTS
########################################


# All SCCM DP
$AllSCCMDP = $Result | ConvertTo-Csv -Delimiter ';' -NoTypeInformation | foreach {$_.replace('"','')}

$AllSCCMDP

# EXPORTS TO TXT FILES
$AllSCCMDP  |  Out-File -FilePath "$ExportFolder\All_SCCMDP.txt" -Force



# DISPLAY SUCCESS
$Message = "--- EXECUTION OK ---"
Write-Host -F Green $Message
Write-Log -Message $Message -LogPath $LogFolder -LogName $Log



 

Intune : Supprimer des devices Autopilot en masse en utilisant leurs numéros de série

Besoin :

Supprimer en masse des devices Autopilot d'un tenant source (Intune) pour pouvoir les migrer vers un tenant cible.

N.B : Un device Autopilot qu'on intègre dans Intune en utilisant son Hash ID ne peut pas co-exister dans deux tenants.

 

Solution :

1- Extraire les numéros de série des devices Autopilot à supprimer depuis Intune et les mettre dans un fichier texte nommé "Autopilot_Device_SN_list.txt" et le placer sous "c:\Windows\Temp".

2- Exécuter le script PowerShell ci-dessous afin de supprimer des devices Autopilot :

 

#STEP 1: Install WindowsAutopilotIntune Powershell module (if required, need ot run PowerShell as admin)
    Install-module WindowsAutopilotIntune -Force -AllowClobber

#STEP 2: Install WindowsAutopilotIntune Powershell module
    Import-module WindowsAutopilotIntune

#STEP 3: Connect to Microsoft Graph
    Connect-MgGraph -scopes "Group.ReadWrite.All, Device.ReadWrite.All, DeviceManagementManagedDevices.ReadWrite.All, DeviceManagementServiceConfig.ReadWrite.All, GroupMember.ReadWrite.All"

#STEP 4: Get the Autopilot devices Serial Numbers in a variable $DeviceSNs
    $DeviceSNs = Get-Content "C:\Windows\Temp\Autopilot_Device_SN_list.txt"
    $Counter = 0

#STEP 5: Delete the Autopilot devices based on serial number list
    foreach ($DeviceSN in $DeviceSNs)
    {
        $Counter++
        #Get Autopilot device ID
        $DeviceID = (Get-AutopilotDevice -serial $DeviceSN).id
        #Get current device information
        $CurrentDevice = Get-AutopilotDevice -id $DeviceID
        Write-host "Working on device $DeviceSN" -ForegroundColor Cyan
        #Delete device from Intune Windows Autopilot devices
        try
        {
            Remove-AutopilotDevice -id $DeviceID
            Write-host "- Device $DeviceSN is deleted" -ForegroundColor Green
        }
        catch{
            $ErrorMessage = $_.Exception.message; Write-Host $ErrorMessage -ForegroundColor Red
        }
        #Counter for PowerShell execution progress
        Write-Progress -Activity "Processing $($Counter) of $($DeviceSNs.count)" -CurrentOperation $DeviceSN -PercentComplete (($Counter / $DeviceSNs.count) * 100)
        Start-Sleep -Milliseconds 200
    }

N.B : le chemin vers le fichier texte qui contient les numéros de série des devices Autopilot "C:\Windows\Temp\Autopilot_Device_SN_list.txt" peut être modifié.

Azure AD : Convertir un SID Azure AD en GUID en utilisant PowerShell

Besoin :

On ne peut pas identifier simplement les noms de groupes qui sont membres du groupe local "Administrateurs" sur une machine joint à l'Azure AD.

Si on fait Windows+R et on tape "lusrmgr.msc" pour afficher les utilisateurs et groupes locaux d'une machine, on souhaite par exemple afficher les membres du groupe Administrateurs, on n'aura pas les noms des groupes membres mais plutôt leurs SID.

Ces SID doivent être convertis en GUID pour pouvoir chercher les noms des groupes dans Azure AD.

 

Solution :

J'ai utilisé ce script PowerShell pour convertir le SID en GUID :

function Convert-AzureAdSidToObjectId {
<#
.SYNOPSIS
Convert a Azure AD SID to Object ID
 
.DESCRIPTION
Converts an Azure AD SID to Object ID.
Author: Oliver Kieselbach (oliverkieselbach.com)
The script is provided "AS IS" with no warranties.
 
.PARAMETER ObjectID
The SID to convert
#>

    param([String] $Sid)

    $text = $sid.Replace('S-1-12-1-', '')
    $array = [UInt32[]]$text.Split('-')

    $bytes = New-Object 'Byte[]' 16
    [Buffer]::BlockCopy($array, 0, $bytes, 0, 16)
    [Guid]$guid = $bytes

    return $guid
}

$sid = "S-1-12-1-1943430372-1249052806-2496021943-3034400218"
$objectId = Convert-AzureAdSidToObjectId -Sid $sid
Write-Output $objectId


# Output:

# Guid
# ----
# 73d664e4-0886-4a73-b745-c694da45ddb4

N.B : Il faut renseigner le SID dans la variable $sid pour que le script retourne son GUID

O365 : Réaliser un hard match (Update)

Dans un précédent article j'expliquais comment réaliser un hard match (https://blog.piservices.fr/post/2021/04/01/o365-realiser-un-hard-match).

J'ai récemment eu à me servir de nouveau des cmdlets et ces dernières ne fonctionnaient pas correctement, il est possible de le faire via API Graph, mais les commande Azure AD permettent encore de le faire si besoin.

 

# Get GUID for User
$User = Get-ADUser jdupont | select ObjectGUID,UserPrincipalName
$Upn = $User.UserPrincipalName
$Guid = $User.ObjectGUID.Guid
 
# Convert GUID to ImmutableID
$ImmutableId = [System.Convert]::ToBase64String(([GUID]($User.ObjectGUID)).tobytearray())
 
# Connect Azure AD
Connect-AzureAD

# Retrieve my user
$User = Get-AzureADUser -SearchString "jdupont @mydomain.com"

# Set ImmutableID to user
Set-AzureADUser -ObjectId $User.ObjectID -ImmutableId $ImmutableId

 

[Exchange Online] Envoi de mails depuis un alias avec Outlook/OWA

Microsoft a ajouté la prise en charge de l'envoi à partir d'une adresse mail en alias dans Office 365/Microsoft 365. Toutefois, la fonctionnalité Envoyer en tant qu'alias ne fonctionnera que pour les boîtes aux lettres Exchange Online et ne fonctionnera pas pour les boîtes aux lettres Exchange Onpremise.

Cet article explique comment activer la fonctionnalité Envoyer depuis un alias dans un tenant Microsoft O365 et comment envoyer des e-mails en tant qu'alias dans Outlook et Outlook sur le Web. Le paramètre s’applique à l’ensemble du tenant. Il n’y a aucun moyen de restreindre la possibilité l'envoi des e-mails à partir d’alias vers certaines boîtes aux lettres.

Activer l'option SendFromAliasEnabled dans O365 

  1. Se connecter à Exchange Online PowerShell:

Import-Module ExchangeOnlineManagement

Connect-ExchangeOnline -UserPrincipalName 'UPNO365'

  1. Une fois connecté, exécuter la commande ci-dessous pour vérifier l'état actuel de l'option SendFromAliasEnabled 

Get-OrganizationConfig | Format-Table SendFromAliasEnabled

 Puis exécuter la commande:

Set-OrganizationConfig -SendFromAliasEnabled $True

 Activer l’envoi à partir d’un alias dans le centre d’administration Exchange

Vous pouvez également activer cette option à partir du Centre d’administration Exchange:

  1. Se connecter au centre d’administration Exchange.
  2. Cliquer sur Paramètres > Flux de messagerie.
  3. Cocher la case Activer l’envoi à partir d’alias.
  4. Cliquer sur Enregistrer.

Envoyer à partir d’un alias dans Outlook

Pour envoyer à partir d’une adresse d’alias dans Outlook:

  1. Démarrer l’application Outlook puis cliquer sur Nouvel e-mail.
  2. Cliquer sur Options > de Cela affichera le champ De dans Outlook.
  3. Cliquer sur À partir de > autre adresse e-mail....puis renseigner l’adresse de l’alias et cliquez sur OK.

Envoyer à partir d’un alias dans Outlook sur le web

Pour envoyer à partir d’un alias dans Outlook sur le web:

  1. Se connecter à Outlook sur le web.
  2. Cliquer sur Nouveau message > ... > montrer à partir de Cela affichera le champ De dans Outlook web
  3. Cliquer sur À partir de > autre adresse e-mail... et renseigner l’adresse de l’alias.