Comme vu dans l'article Powershell - Chiffrer un mot de passe la santé de votre équipe de sécurité a été préservé car vos mots de passe sont désormais chiffrés dans vos scripts. Un mot de passe chiffré c'est bien mais comment le déchiffrer pour pouvoir l'utiliser ?
La fonction de déchiffrement
function Get-SecureStringFromEncryptedFile #Fonction qu'il faudra appeler pour déchiffrer le mot de passe
{
[CmdletBinding()] #Déclaration des paramètres qu'il faudra fournir à la fonction pour qu'elle puisse s'exécuter
Param
(
[Parameter(Mandatory=$true)] #Indique que ce paramètre est obligatoire
[ValidateNotNullOrEmpty()] #Indique que ce champ ne peut pas être vide ou null
[string]$Name, #Paramètre qui attend le nom de l'utilisateur, il est utilisé pour créer un credential object
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$PwdPath #Paramètre qui attend le chemin complet du fichier qui contient le mot de passe chiffré
)
Begin
{
$Return = @{} #Tableau de retour qui contient le mot de passe sous forme de secure string et le credential object généré à partir du nom du compte de service et de son mot de passe
}
Process
{
$PwdSecureString = Get-Content $PwdPath | ConvertTo-SecureString #Récupére le mot de passe chiffré depuis le fichier txt fourni et le convertit en secure string
$Return.pwdSecureString = $PwdSecureString #Attribution de la secure string générée dans la variable de sortie de la fonction
$Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Name, $PwdSecureString #Génére un credential object à partir de l'utilisateur et de son mot de passe
$Return.credentials = $Credentials #Attribution du credential object générée dans la variable de sortie de la fonction
Return $Return #Retourne le mot de passe ainsi que la secure string en sortie de la fonction
}
}
Exemple d'utilisation de la fonction de déchiffrement
. .\Get-SecureStringFromEncryptedFile_article.ps1 #Permet de déclarer (dot source) la fonction de chiffrement pour qu'elle puisse être utilisée
$Password = Get-SecureStringFromEncryptedFile -Name "Svc-test-01" -PwdPath "D:\A_folder\Svc-test-01_encrypted_password.txt" #Appelle de la fonction de déchiffrement et lui passe en paramètre le nom de l'utilisateur le chemin complet du fichier qui contient le mot de passe chiffré
#Le mot de passe sous forme de secure string est conservé dans la propriété pwdSecurestring, on peut y accéder comme ceci $Password.pwdSecureString
#Le credential object qui contient le jeu d'identifiant nom d'utilisateur et mot de passe est conservé sous forme de credential object dans la propriété credentials, on peut y accéder comme ceci $Password.credentials
$Credentials = $Password.Credentials #Attribution du credential object à la variable $Credentials
Get-ADUser -Identity "Toto" -Credential $Credentials #Utilisation de la cmdlet Get-ADUser avec le credential object précédemment généré
Remarque : lorsque le fichier est généré, une combinaison du compte utilisateur et du compte machine est utilisée. Cela implique que le mot de passe ne peut être déchiffré que par l'utilisateur qui l'a chiffré et sur la machine sur laquelle le chiffrement a eu lieu.
À moins que votre but ne soit d'essayer de causer une crise cardiaque à votre équipe sécurité et d'entre autres faciliter le travail des hackers, il est conseillé de conserver les mots de passe dans les scripts chiffrés.
La fonction de chiffrement
function New-EncryptedPasswordFile #Fonction qu'il faudra appeler pour générer un fichier txt qui contiendra le mot de passe chiffré
{
[CmdletBinding()] #Déclaration des paramètres qu'il faudra fournir à la fonction pour qu'elle puisse s'exécuter
Param
(
[Parameter(Mandatory=$true)] #Indique que ce paramètre est obligatoire
[ValidateNotNullOrEmpty()] #Indique que ce champ ne peut pas être vide ou null
[string]$User, #Paramètre qui attend le nom de l'utilisateur, il n'est utilisé que pour le nom du txt de sortie ainsi n'importe quelle valeur peut être renseigné
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[securestring]$Password #Paramètre qui attend une secure string,
)
Process
{
$EncryptedPasswordPath = $PSScriptRoot + "\" + $User + "_encrypted_password.txt" #Génére dynamiquement le chemin complet du txt qui contiendra le mot de passe chiffré
$Password | ConvertFrom-SecureString | Out-File $EncryptedPasswordPath #Génére le txt qui contient le mot de passe chiffré
}
}
Exemple d'utilisation de la fonction de chiffrement
Le script suivant appelle la fonction de chiffrement lorsque lui-même est appelé
. .\New-EncryptedPasswordFile_article.ps1 #Permet de déclarer (dot source) la fonction de chiffrement pour qu'elle puisse être utilisée
New-EncryptedPasswordFile -User "Svc-test-01" #Appelle de la fonction de chiffrement et lui fournit volontairement uniquement le nom de l'utilisateur
#Le mot de passe sera demandé sous forme de secure string
Appel du script précédent
PS D:\A_folder> .\Call_me_maybe.ps1 #Appel du script précédent qui contient l'appelle de la fonction de chiffrement
cmdlet New-EncryptedPasswordFile at command pipeline position 1
Supply values for the following parameters: #La saisie du mot de passe sous forme de secure string est demandé
Password: ****
Le résultat
Le mot de passe contenu dans le fichier txt généré est chiffré
Remarque : lorsque le fichier est généré, une combinaison du compte utilisateur et du compte machine est utilisée. Cela implique que le mot de passe ne peut être déchiffré que par l'utilisateur qui l'a chiffré et sur la machine sur laquelle le chiffrement a eu lieu.
La génération de mots de passe dans un script est un besoin fréquent lors de création de compte utilisateur. Au lieu d'appeler les cmdlets pour générer un mot de passe aléatoire à chaque besoin, il est plus esthétique de créer une fonction de génération de mots de passe dédiée et de l'utiliser quand le besoin se présente.
Le code suivant propose une fonction de génération de mots de passe qui essaye d'être simple, compréhensible et adaptative.
La fonction de génération de mots de passe
function New-RandomPassword #Fonction qu'il faudra appeler pour générer un mot de passe aléatoire
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$false)] #Indique que ce paramètre n'est pas obligatoire
[ValidateNotNullOrEmpty()] #Indique que ce champ ne peut pas être vide ou null
[int]$PasswordLength = 16, #Paramètre optionel qui spécifie la longueur du mot de passe, valeur par défaut 16
[Parameter(Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[int]$NumberOfAlphaNumericCharacters = 2, #Paramètre optionnel qui spécifie le nombre de caractères alphanumériques que le mot de passe doit contenir, valeur par défaut 2
[Parameter(Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[switch]$ConvertToSecureString #Paramètre qui si présent convertit le mot de passe en secure string pour pouvoir construire un PSCredential Object utile par exemple pour exécuter des cmdlets avec un compte de service
)
Begin
{
Add-Type -AssemblyName 'System.Web' # Ajout d'une classe .NET à la session PowerShell qui permet d'accéder aux fonctions nécessaires à la génération du mot de passe
$Return = @{} #Tableau de retour qui contient le mot de passe en clair et le mot de passe sous forme de secure string
}
Process
{
$Password = [System.Web.Security.Membership]::GeneratePassword($PasswordLength,$NumberOfAlphaNumericCharacters) #Génération du mot de passe en clair avec les paramètres fournis
$Return.passwordObject = $Password #Attribution du mot de passe généré dans la variable de sortie de la fonction
if ($ConvertToSecureString.IsPresent) #Si le paramètre ConvertToSecureString est présent, génère une secure string du mot de passe
{
$Password = ConvertTo-SecureString -String $Password -AsPlainText -Force #Génération de la secure string du mot de passe
$Return.passwordSecureObject = $Password #Attribution de la secure string du mot de passe dans la variable de sortie de la fonction
}
Return $Return #Retourne le mot de passe ainsi que la secure string en sortie de la fonction
}
}
Exemple d'utilisation de la fonction de génération de mots de passe
. .\New-RandomPassword_article.ps1 #Permet de déclarer (dot source) la fonction de génération de mots de passe pour qu'elle puisse être utilisée
$Password = New-RandomPassword -PasswordLength 20 -ConvertToSecureString #Appelle de la fonction de génération de mots de passe
#Avec génération d'une secure string du mot de passe et une longueur de mot de passe de 20 caractères
$Password.passwordObject #Le mot de passe en clair est dans l'attribut passwordObject de la variable de sortie définit ci-avant $Password
$Password.passwordSecureObject #Le mot de passe sous forme de secure string est dans l'attribut passwordSecureObject de la variable de sortie définit ci-avant $Password
Le résultat
Appel du script PowerShell Call_me_maybe.ps1 ci-avant
PS D:\Hey_Im_a_folder> .\Call_me_maybe.ps1
LmcfY>5O$-GZ^z/fvfB1 #Affichage du mot de passe en clair
System.Security.SecureString #Mot de passe sous forme de secure string
SSPR et MFA
Face aux nombreuses attaques informatique ces dernières années, les entreprises répondent en renforçant la sécurité de leur système d'information (SI).
SSPR (Self-Service Password Reset) et MFA (Multi-factor authentication) y contribuent.
SSPR permet à un utilisateur de réinitialiser son mot de passe dans Azure de façon autonome via des méthodes de récupération qu'il aura configuré préalablement, SMS, appel téléphonique, questions secrètes..
MFA demande à un utilisateur un deuxième moyen de prouver son identité, c'est par exemple parfois le cas suite à un achat en ligne, un code à usage unique (OTP) pour valider la transaction est envoyé par SMS à un téléphone dont le numéro a été communiqué au fournisseur de service en amont. D'autres méthodes existent tel que l'application Microsoft Authenticator ou l'appel d'un numéro de téléphone.
On observe donc que certaines méthodes d'authentification sont communes entre SSPR et MFA, les utilisateurs seront donc invités à renseigner plusieurs fois les mêmes informations ce qui détériore leurs expériences et par conséquent amoindris leurs adhésions à ces outils.
Combiner les informations de sécurité SSPR et MFA
Il existe dans Azure un paramètre qui permet de combiner les informations de sécurité SSPR et MFA.
Se connecter avec un compte administrateur global à portal.azure.com > User settings > Manage user feature settings
Choisir ensuite All dans User can use the combined security information registration experience
Selected permet d'activer ce paramètre pour des utilisateurs nominatif
Pour aller plus loin
Documentation officielle Microsoft sur la combinaison des informations de sécurité SSPR et MFA
Oh, la belle bleue (même si elle est verte) !
Modifier les paramètres Internet Explorer (IE) via GPO permet de simplifier grandement le déploiement d'un paramètre spécifique IE, si tenté que la GPO soit intuitive à configurer..
Rappelons dans un premier temps comment accèder aux settings IE, une fois la GPO ouverte pour modification : User Configuration > Preferences > Control Panel Settings > Internet Settings > New
La même fenêtre des options IE que sur une machine local s'affiche avec la particularité d'avoir des paramètres soulignés en vert d'un trait plein et d'autre souligné en rouge d'un trait en pointillé.
Signification et modification
Les codes couleurs fonctionnent comme ceci :
- Les traits verts correspondent aux paramètres qui sont activés et s'appliqueront sur les machines
- Les traits rouges correspondent aux paramètres non désactivés et qui ne s'appliqueront pas sur les machines
Comment faire pour basculer un paramètre activé à désactivé puisque les raccourcis habituels ne semblent pas fonctionner ?
C'est grâce aux touches F5, F6, F7 et F8 qu'il est possible de changer le statut d'un paramètre :
- F5 : active tous les paramètres de l'onglet
- F6 : active uniquement le paramètre qui a été modifié en dernier
- F7 : désactive uniquement le paramètre qui a été modifié en dernier
- F8 : désactive tous les paramètres de l'onglet
À l'image du chien qui est le meilleur ami de l'homme, le fichier de log est le meilleur ami de l'informaticien qui débug.
Générer des logs lorsqu'un code PowerShell s'exécute permet de savoir si une fonction a été correctement exécutée et si ce n'est pas le cas de savoir précisément à quel endroit un problème est survenu, ce qui va sans dire est d'une aide considérable lors d'un débug.
La fonction de log
function Get-CurrentLineNumber #Fonction qui permet de récupérer la ligne actuelle dans un script, elle sera utilisée par le script qui appelle la fonction de log
{
Return $MyInvocation.ScriptLineNumber
}
function Write-Log #Fonction qu'il faudra appeler lorsque l'on voudra faire du logging
{
[CmdletBinding()] #Déclaration des paramètres qu'il faudra fournir à la fonction pour qu'elle puisse s'exécuter
param
(
[Parameter(Mandatory=$true)] #Indique que ce paramètre est obligatoire
[ValidateNotNullOrEmpty()] #Indique que ce champ ne peut pas être vide ou null
[string]$LogFile, #Paramètre qui contient le chemin complet du script qui appelle la fonction de log
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$LogLine, #Paramètre qui contient la ligne à laquelle la fonction de log est appelée
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$LogMessage, #Paramètre qui contient le log
[Parameter(Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[string]$LogPath, #Paramètre qui contient le chemin complet du fichier de log
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[ValidateSet('Information','Warning','Error')] #Valeurs disponibles pour qualifier le log
[string]$LogSeverity #Paramètre qui va quantifier la nature du log parmi les valeurs disponibles
)
Begin
{
if (!$LogPath) #Code qui permet de générer un dossier de log ainsi que le fichier de log de façon dynamique si le paramètre LogPath est vide
{
$CurrentDateFormatForLog = Get-Date -Format "yyyy-MM-dd_HH" #Recupère la date du jour pour la mettre à la fin du nom de fichier de log
$LogFolderName = "Logs" #Nom du fichier de log
$LogFolderPath = $PSScriptRoot + "\" + $LogFolderName #Détermine dynamiquement la localisation du dossier de log qui doit se trouver dans le même dossier que le script PowerShell qui appelle la fonction de log
if (!(Test-Path -Path $LogFolderPath))#Vérifie l'existence d'un dossier de log dans le même dossier que le script qui appelle la fonction de log
{
New-Item -ItemType Directory -Path $LogFolderPath | Out-Null #Si le dossier de log n'existe pas, le créé
}
$LogPath = $LogFolderPath + "\" + "Log_" + $CurrentDateFormatForLog + ".csv" #Détermine le nom du chemin complet du fichier de log
}
}
Process
{
[pscustomobject]@{ #Génére un objet PowerShell dont chaque ligne représente une colonne du fichier de log
Date = Get-Date -Format "yyyy-MM-dd HH:mm:ss" #Première colonne qui contient la date à laquelle la fonction de log s'est exécuté
Severity = $LogSeverity #Deuxième colonne qui contient la nature du log
File = $LogFile #Troisième colonne qui contient le nom du script PowerShell qui appelle la fonction de log
Line = $LogLine #Quatrième colonne qui contient la ligne à laquelle la fonction de log a été appelée
Message = $LogMessage #Cinquième colonne qui contient le log
} | Export-Csv -Path $LogPath -Append -NoTypeInformation -Delimiter ";" -Encoding UTF8 #Code qui permet de transformer l'objet PowerShell en fichier de log (csv)
}
}
Exemple d'utilisation de la fonction de log
. .\Write-Log_article.ps1 #Permet de déclarer (dot source) la fonction de log pour qu'elle puisse être utilisée
try #Appelle de la fonction de log pour indique l'utilisateur a bien été trouvé
{
$User = Get-ADUser -Identity "maybe" #Cherche un utilisateur dont le samAccountName est maybe
Write-Log -LogSeverity "Information" -LogMessage "L'utilisateur a bien été récupéré" -LogFile $PSCommandPath -LogLine $(Get-CurrentLineNumber)
#$PSCommandPath permet de trouver le chemin complet du script qui est en train de s'exécuter
#Get-CurrentLineNumber fonction déclarée dans le script de log qui permet de récupérer la ligne courante du script qui appelle la fonction de log
}
catch #Appelle la fonction de log si l'utilisateur n'a pas été trouvé et envoie en tant que message de log l'erreur généré par la cmdlet Get-ADUser
{
Write-Log -LogSeverity "Error" -LogMessage $_.Exception.Message -LogFile $PSCommandPath -LogLine $(Get-CurrentLineNumber)
}
Le résultat
Une fois le script PowerShell Call_me_maybe.ps1 appelé, le dossier de log est généré
Le fichier de log est généré
Le log est généré
Marre de devoir attendre que le bureau Windows Server 2016/2019 se charge pour chercher votre console d'administration ou peur que le simple fait d'ouvrir la recherche Windows de Windows Server 2012 freeze votre session ?
Voici la liste des commandes les plus utiles pour accéder aux outils d'administration Windows :
Active Directory Domains & Trust |
DOMAIN.MSC |
Active Directory Sites & Services |
DSSITE.MSC |
Active Directory Users & Computers |
DSA.MSC |
Certificates snap-in |
ERTMGR.MSC |
Certification Services |
CERTSRV.MSC |
Command Prompt |
CMD.EXE |
Computer Management |
COMPMGMT.MSC |
Device Manager |
DEVMGMT.MSC |
DHCP Manager |
DHCPMGMT.MSC |
Disk Defragmenter |
DFRG.MSC |
Disk Management |
DISKMGMT.MSC |
Distributed File System |
DFSGUI.MSC |
DNS Manager |
DNSMGMT.MSC |
Domain Controller Security Policy |
DCPOL.MSC |
Domain Security Policy |
DOMPOL.MSC |
Event Viewer |
EVENTVWR.MSC |
Hardware and software configuration information |
MSINFO32.EXE |
Internet Authentication Service |
IAS.MSC |
Internet Information Service (\Windows\system32\inetsrv) |
INETMGR |
local Group Policy Editor |
GPEDIT.MSC |
Local Security Policy |
SECPOL.MSC |
Local Users and Groups |
LUSRMGR.MSC |
Microsoft Management Console |
MMC.EXE |
Performance Monitor |
PERFMON.MSC |
Remote Desktop |
MSTSC |
Resultant Set of Policy |
RSOP.MSC |
Routing and Remote Access |
RRASMGMT.MSC |
Run Registry Editor |
REGEDIT.EXE |
Service Configuration |
SERVICES.MSC |
Shared Folders |
FSMGMT.MSC |
Terminal Services |
TSCC.MSC |
À quoi cela sert-il ?
En réalité, il y a peu de cas pratiques ou trouver le mot de passe d'un réseau wifi précédemment utilisé est utile, car bien souvent, celui-ci étant sauvegardé, il n'y a pas besoin de l'entrer à nouveau.
Alors à quoi cela sert-il ? C'est avant tout pour mettre en relief que certaines cmdlets Windows sont peu sécurisées et révèlent beaucoup d'informations avec peu de privilèges, ce qui est bien évidemment le combo préféré des hackers.
Les commandes
Les commandes ci-après sont exécutés avec un utilisateur qui n'est ni administrateur de la machine ni en mode administrateur
La première commande permet d'afficher les profiles auquel la machine s'est déjà connecté
C:\WINDOWS\System32>netsh wlan show profiles
Profiles on interface Wi-Fi:
Group policy profiles (read only) #Dans le cas d'un PC dans un domaine Active Directory les profiles déployés par GPO sont affichés ci-après
---------------------------------
Profile_entreprise
Profile_entreprise2
User profiles #Les profiles sont affichés ci-après
-------------
All User Profile : MonWifi
All User Profile : Faux_reseau
All User Profile : Toto
Cette commande va afficher le mot de passe du profile appelé en clair
C:\WINDOWS\System32>netsh wlan show profiles MonWifi key=clear
Profile MonWifi on interface Wi-Fi:
=======================================================================
Applied: All User Profile
Profile information
-------------------
Version : 1
Type : Wireless LAN
Name : MonWifi
Control options :
Connection mode : Connect automatically
Network broadcast : Connect only if this network is broadcasting
AutoSwitch : Do not switch to other networks
MAC Randomization : Disabled
Connectivity settings
---------------------
Number of SSIDs : 1
SSID name : "MonWifi"
Network type : Infrastructure
Radio type : [ Any Radio Type ]
Vendor extension : Not present
Security settings
-----------------
Authentication : WPA2-Personal
Cipher : CCMP
Authentication : WPA2-Personal
Cipher : GCMP
Security key : Present
Key Content : MonMotDePasseEnClair #Le mot de passe est affiché en clair
Cost settings
-------------
Cost : Unrestricted
Congested : No
Approaching Data Limit : No
Over Data Limit : No
Roaming : No
Cost Source : Default
Quels sont alors les moyens de se prémunir de cette vulnérabilité ? Les méthodes sont diverses, telles que l'utilisation du 802.1X ou un changement régulier du mot de passe.
Pour aller plus loin
Vidéo youtube qui propose un script python pour automatiser la récupération des mots de passe de tous les profils d'un ordinateur
Ça pique les yeux
Vous avez peut être déjà eu recours à la commande (cmdlet) suivante pour créér un compte dans l'Active Directory (AD) :
New-ADUser -Name $Name -samAccountName $samAccountName -userPrincipalName $UserPrincipalName -Path $Path -AccountPassword $AccountPassword -DisplayName $DisplayName -GivenName $GivenName -sn $sn -Description $Description -Server $Server -ChangePasswordAtLogon -Enabled
Oui ca fait mal aux yeux, mais pourquoi ne pas utiliser le caractère backtick ` qui permet de scinder une cmdlet sur plusieurs lignes ?
New-ADUser -Name $Name -samAccountName $samAccountName
` -userPrincipalName $UserPrincipalName
` -Path $Path -AccountPassword $AccountPassword
` -DisplayName $DisplayName -GivenName $GivenName -sn $sn
` -Description $Description -Server $Server
` -ChangePasswordAtLogon -Enabled
Effectivement, c'est mieux, mais cela n'est toujours pas très esthétique, peut-on faire encore mieux ?
Le splatting
Le splatting permet de passer à une cmdlet un hash table (tableau associatif), array (tableau) ou une liste d'arguments qui va contenir la liste des paramètres voulus
$parameters = @{ #Ceci est un hash table qui va associer à gauche du signe égal le nom du paramètre avec à droite la valeur du dit paramètre
Name = $Name
samAccountName = $samAccountName
userPrincipalName = $userPrincipalName
Path = $Path
AccountPassword = $AccountPassword
DisplayName = $DisplayName
GivenName = $GivenName
sn = $sn
Description = $Description
Server = $Server
ChangePasswordAtLogon = $true
Enabled = $true
}
New-ADUser @parameters #Pour utiliser le splatting il faut passer en paramètre le hash table à l'aide du caractère @ et non $
En plus de rendre le code plus lisible, les méthodes associées aux hash table sont désormais accessibles, si par exemple on veut ajouter ou retirer des éléments plus loin dans le code :
$parameters.add('employeeID', $EmployeeID) #Ajout du paramètre à gauche du signe , employeeID et à droite la valeur du dit paramètre dans le hashtable $parameters
$parameters.remove('ChangePasswordAtLogon') #Suppression du paramètre ChangePasswordAtLogon du hash table $parameters
Pour aller plus loin
Documentation officielle de Microsoft sur le splatting
Les souscriptions, des ressources Azure aux permissions isolées
Le rôle Azure administrateur global (global administrateur) est le rôle absolu, il octroie le droit de vie ou de mort sur un tenant Azure, cependant, les irrésistibles souscriptions (subscriptions) n'en ont que faire et un global administrator se fera jeter comme un simple utilisateur s'il tente d'accéder à une ressource Azure auquel il n'a pas accès si tenté qu'il puisse déjà la voir, à moins que..
S'octroyer les permissions sur toutes les souscriptions
Il existe une fonctionnalité Azure qui permet à un Global admin de se conférer des droits sur toutes les subscriptions existantes et ceci en un clic, pour ce faire :
Connectez-vous à portal.azure.com avec votre compte Global admin et dans la liste déroulante de gauche, ouvrez Properties
En bas de la fenêtre dans la section Access management for Azure ressources basculez le bouton en Yes
Attention, ce rôle ne fournit pas le rôle Propriétaire (Owner) sur les subscriptons, il fournit le rôle User Access Administrator à la racine ce qui permet d'accéder au RBAC Azure de la subscription et de s'octroyer les droits voulus.
Pensez à retirer vos droits de la subscription avant de basculer à nouveau le bouton évoqué précédemment en No
Pour aller plus loin
Article officiel de Microsoft sur la délégation de permissions sur les souscriptions Azure en tant qu'administrateur global
Article officiel de Microsoft sur le RBAC Azure