PI Services

Le blog des collaborateurs de PI Services

Powershell 5.0 : découvertes de quelques nouveautés

Introduction

Powershell 5.0 est encore en beta mais de nombreuses nouveautés sont déjà présentes. Nous allons aborder dans cet article quelques unes d'entres elles. Elles peuvent concerner : Powershell, son éditeur (Powershell ISE) ou encore son paramétrage dans Windows. Certaines avaient déjà été évoquées dans l'article suivant lors de la première preview de Powershell 5.0 :
http://blog.piservices.fr/post/Powershell-V5-Preview-est-sorti-!-DSC-Switch-OneGet-et-du-chocolat.aspx

NB : Contrairement à la première beta, Powershell 5.0 est dorénavant disponible pour Windows 2012 et supérieur (qui n’était compatible qu’avec Windows 2012 R2 et supérieur). Le lien suivant vous mènera à la dernière beta sortie (Novembre 2014) :

http://www.microsoft.com/en-us/download/details.aspx?id=44987

Gestion des Archives

Un nouveau module permettant de gérer nativement les archives apparaît dans Powershell 5.0. Cette option n'était auparavant disponible qu'au travers de module réalisé par la communauté. Ce dernier permet de générer des archives (Compress-Archive) ou de les extraire (Expand-Archive). Seul le format Zip est actuellement géré. Un paramètre nommé “update” permet de mettre à jour une archive existante en ajoutant seulement les nouveaux fichiers et les changements sur les fichiers déjà présents dans l'archive. Le paramètre “path” peut définir un ou plusieurs fichiers ainsi qu'un dossier entier en utilisant le caractère “*” (wildcard). Enfin le paramètre “CompressionLevel” permet d'influencer le taux de compression et la taille finale de l'archive.

 

Zip module

Support des raccourcis claviers

La console Powershell supporte désormais certains raccourcis clavier : copier (CTRL+C), coller (CTRL+V), tout sélectionner (CTRL+A).

Gestion des liens symboliques

Il est dorénavant possible de créer/supprimer des raccourcis via Powershell. Cette fonctionnalité est incluse dans la commande New-Item en spécifiant le type “SymbolicLink”.

Création d'un raccourci vers un fichier

 

Création d'un raccourci vers un dossier

 

On peut aussi lister des fichier via la commande Get-ChildItem en passant par un raccourci !

Event Viewer

Un nouveau journal de log est apparu dans l'observateur d'événements. Par défaut, ce dernier enregistre les lancements de console Powershell et les erreurs générales comme un échec de chargement de module. Ce nouveau journal est situé dans Applications and Services Logs\Microsoft\Windows\PowerShell\Operational. Il peut aussi enregistrer les exécutions de code Powershell. Cette fonctionnalité s'active via GPO.

Attention : Activer l'utilisation de ce journal pour les exécutions de code est très verbeux. Néanmoins cela peut être très utile pour obtenir rapidement des traces d'actions effectuées sur des serveurs via Powershell.

Il est possible d'activer cette fonctionnalité via GPO (voir paragraphe ci-dessous).

GPO

Les modèles d'administration possède désormais un ADMX permettant de gérer quelques paramètres Powershell. Ce dernier est situé dans Administrative Templates / Windows Components / Windows PowerShell. Il serait compatible avec les systèmes d'exploitation de la famille Windows 7 / Windows 2008 et supérieur (je ne l'ai personnellement testé que sur Windows 10 Server Technical Preview). Cette nouveauté n'est donc pas totalement liée à Powershell 5.0 puisqu'elle sera fonctionnelle sur les anciennes versions de Powershell.

Administrative Template Powershell

Les paramètres configurables sont les suivants :

  • Activer les traces dans l'observateur d'événements pour tout exécution de script.
  • Activer les traces dans l'observateur d'événements pour les exécutions de module Powershell (il faut préciser les modules concernés).
  • Définir la politique d'exécution des scripts (Set-ExecutionPolicy). Il s'agit d'une très bonne nouvelle car il n'existait pas de solution pour généraliser ce paramètre sur un grand nombre de serveur hormis en passant par une ressource DSC (ce qui représente un déploiement beaucoup plus lourd).
  • Activer automatique du transcript : cela permet de ne pas avoir à lancer la commande “start-transcript”. Il est également possible de définir le chemin où doit être stocké le transcript. Par défaut le nom du fichier est horodaté, contient le nom de l'ordinateur et est stocké dans le répertoire “Mes documents” de l'utilisateur de la session Powershell.
  • Définir la source de l'aide Powershell. Depuis Powershell 3.0, l'aide des cmdlets n'est pas entièrement incluse avec le package d'installation Powershell. Il est nécessaire d'utiliser la commande “Update-Help” pour la mettre à jour (par défaut, elle est récupéré depuis internet). Cela permet entre autre de récupérer l'aide avec la langue qui nous intéresse. Grâce à ce paramètre, on peut dorénavant spécifier une source comme un partage de fichier. Néanmoins, l'utilisateur a toujours la possibilité de changer le comportement en indiquant lui même une valeur lors de l'exécution de la commande via le paramètre “SourcePath”.

Tous ces paramètres sont disponibles dans la configuration ordinateur et utilisateur de la GPO.

Transcript

La génération de transcript n'était jusqu'à présent fonctionnelle que dans la console Powershell. Grâce aux cmdlets “Start-Transcript” / “Stop-Transcript”, il est désormais possible de générer des fichiers de traces aussi via Powershell ISE.

Powershell ISE avec Powershell 4 :

Powershell ISE transcript v4

Powershell ISE avec Powershell 5 :

Powershell ISE transcript v5

PSEdit

Une nouveauté fait son apparition dans Powershell ISE et le PSRemoting : PSEdit. Cet outil existait déjà et permettait d'ouvrir script dans un nouvel onglet dans Powershell ISE lorsque l'on exécutait la commande suivante : PSEdit chemin_de_mon_script.

Cependant, dans cette nouvelle version de Powershell ISE, il est possible d'ouvrir des fichiers à distances. Il n'y a donc plus besoin d'ouvrir Powershell ISE sur la machine où se trouve le script pour l'éditer. Il suffit d'ouvrir une PSSession puis d'exécuter PSEdit.

Cette fonctionnalité est facilement testable même en local en simulant une session distante :

PSEdit Remote file

Il n'y a pas besoin de connaître le chemin exact du script puisque l'auto complétion est disponible pour le retrouver.

Enumérations

La dernière nouveauté expliquée dans cet article est plus orientée scripting. Les énumerations font leurs apparitions dans Powershell. Pour cela un nouveau mot clé est disponible : “enum”. Celles-ci vont nous permettre de réaliser plus rapidement de la validation de paramètres.

Prenons le cas du paramètre ErrorAction disponible sur toutes les commandes Powershell. Il n'est possible de fournir qu'un certain nombre de valeurs : Continue, Ignore, Inquire, SilentlyContinue, Stop, Suspend. Ceux-ci correspondent à une énumération.

La syntaxe d'une énumération est la suivante : Pour utiliser cette dernière dans une fonction :

Nous pouvons remarquer que les choix disponibles sont proposés par le système d'auto complétion.

EnumEnfin, si l'on souhaite récupérer les valeurs d'une énumération, il faut exécuter la commande suivante :

 

Conclusion

Powershell 5.0 et Windows 10 sont riches en nouveautés pour le langage de scripting de Microsoft. Certaines d'entre elles n'ont pas été abordées mais feront l'objet d'articles dédiées :

  • La création de classes d'objets personnalisés.
  • Les améliorations de Desired State Configuration comme la gestion des configurations partielles permettant de segmenter celles-ci en plusieurs fichiers (exemple : par fonctionnalité).
  • PowershellGet : à l'instar de OneGet qui permet de récupérer des packages, ce dernier offre la possibilité de récupérer des modules depuis internet ou depuis sa propre source. Ainsi, une société peut créer sa bibliothèque de modules Powershell.

Script Powershell–Scom: Surveillance consommation reguliere de fichiers dans un dossier

 

Le script ci-dessous surveille la consommation (création / suppression) régulière de fichiers dans un dossiers en excluant potentiellement des noms de fichiers et des heures de dernieres modification puis remonte l’état a SCOM.

Lien du script plus bas.

##################################################################################################### #SCRIPT DE SUPERVISION DU CHANGEMENT DE CONTENU DU DOSSIER ARRIVEE POUR L'APPLICATION INVENTAIRE #ETAT KO SI DES FICHIERS SONT PRESENT APRES 15 minutes (CES FICHIERS SONT CENSES ETRE RAPIDEMENT CONSOMMES) ##################################################################################################### #NB: L'INTERVALLE DE TEMPS DE COMPARAISON EST CELLE DE L'INTERVALLE D'EXECUTION DU SCRIPT #SONT EXCLUS DANS LES CRITERES DE RECHERCHE LES FICHIERS CREES ENTRE 22:00 ET 00:59 Param( [string]$computerName, [string]$DirPath, [regex]$excludedfiles="^(FILETOEXCLUDE)|(FILETOEXCLUDE)$", [regex]$filename="^.*(.*)$", [regex]$excludetime="^(22:).*|(23:).*|(00:).*$" ) $scriptname="CheckDirFileConso" #API Scom $api = new-Object -ComObject 'Mom.ScriptAPI' #Verification de l'existence d'une source ayant le nom du script dans l'eventlog operation manager pour loguer certains events Function NewEventSource { if(!(Test-Path "HKLM:\SYSTEM\CurrentControlSet\services\eventlog\Operations Manager\$scriptname")) { New-EventLog -LogName "Operations Manager" -Source $scriptname } } #Verification de l'existence du dossier $DirPath if (!(test-path -Path $DirPath)) { write-host "le dossier $DirPath est introuvable" NewEventSource Write-EventLog -LogName "Operations Manager" -Source $scriptname -EntryType Error -EventId 1004 -Message "le dossier $DirPath est introuvable" Exit } $Files=Get-ChildItem -Path $DirPath | Where-Object {$_.name -match $filename -AND $_.name -notmatch $excludedfiles -AND $_.lastwritetime -lt (get-date).AddMinutes(-15) -AND $_.LastWriteTime.ToLongTimeString() -notmatch $excludetime} | Select-Object -Property Name -ExpandProperty Name If ($Files) { write-host -ForegroundColor yellow -BackgroundColor black "Les fichiers suivants sont présent depuis 15 minutes dans le dossier $DirPath:" foreach ($file in $Files) { write-host $file } NewEventSource Write-EventLog -LogName "Operations Manager" -Source $scriptname -EntryType Warning -EventId 1005 -Message "Les fichiers suivants sont présent depuis 15 minutes dans le dossier $DirPath: $Files" $status="KO" write-host "" write-host -ForegroundColor yellow -BackgroundColor black "ETAT $status" } Else { write-host -ForegroundColor green "Tout les fichiers présents il y a 15 minutes dans le dossier $DirPath ont été consommés" NewEventSource Write-EventLog -LogName "Operations Manager" -Source $scriptname -EntryType Information -EventId 1000 -Message "Tout les fichiers présent il y a 15 minutes dans le dossier $DirPath ont été consommés" $status="OK" write-host "" write-host -ForegroundColor green "ETAT $status" } #Envoi de l'état a SCOM $bag = $API.CreatePropertyBag() If ($status -eq "KO") { $bag.AddValue("Status","Warning") } Else { $bag.AddValue("Status","Success") } $bag

 

 

Powershell / Active Directory : Intégration de la photo des utilisateurs

Introduction

Cet article a pour but d'expliquer la gestion des photos dans l'annuaire Active Directory via une intégration par un script Powershell. En effet, le référentiel photo d'une entreprise ne respecte pas forcément les préconisations Microsoft. Grâce à un script, nous allons voir comment les respecter et peupler un annuaire Active Directory. La solution proposée permettra d'automatiser le processus en s'affranchissant d'outils tiers qui peuvent réaliser cette opération.

Solution

L'attribut AD permettant de renseigner la photo est thumbnailPhoto. Il y a plusieurs restrictions sur une image de profil :

  • la résolution est limitée à 96x96 pixels
  • la taille ne doit pas éxéder 100Kb

La valeur stockée dans l'attribut thumbnailPhoto est un tableau de bytes.

La solution proposée utilise des classes .Net issue de System.Drawing. Ainsi, on va pouvoir redéfinir la taille d'une image, la centrer et éventuellement définir la qualité si la photo est trop lourde. Afin d'être le plus portable possible, le script interroge Active Directory via ADSI pour réaliser la modification de l'attribut thumbnailPhoto.

NB : Depuis la V15 des produits d'infrastructure Microsoft et grâce au couple Exchange 2013/Lync 2013, il est possible de stocker des photos d'une résolution de 648*648 pixels directement dans la boîte aux lettres de l'utilisateur. Cette dernière est accédée directement via les Exchange Web Services par Lync. Une copie d'une résolution de 48x48 est toujours stockée dans l'attribut thumbnailPhoto.

Script

Le script permet de rendre conforme la photo d'un utilisateur et de la placer sur l'objet Active Directory dans l'attribut thumbnailPhoto. Pour chaque utilisateur, il est nécessaire de renseigner les paramètres suivants :

  • le samaccountname de l'utilisateur
  • le dossier contenant la photo
  • le nom du fichier photo
  • l'extension du fichier photo
Le script possède deux fonctions. Set-ADUserPhoto, requête l'annuaire Active Directory pour obtenir l'utilisateur via son SamAccountName. L'attribut thumbnailPhoto est ensuite mis à jour avec la valeur qui est retournée par la fonction Resize-Photo. Cette dernière retourne l'image sous la forme d'un tableau de bytes. Elle insère l'image d'origine dans une nouvelle image Bitmap possédant les limites de dimensions spécifiées (dans notre cas 96x96 pixels). Tout surplus sur les côtés est donc supprimé. L'image d'origine est positionnée de façon à se situer au centre. Enfin cette image est enregistrée en mémoire. Sa taille est évaluée. Si sa taille est supérieure au poids maximal choisi (ici 100Kb) alors on génère une nouvelle image en faisant varier la qualité (il s'agit d'un pourcentage que l'on décrémente de 5% à chaque essai).

Pour vérifier que l'opération s'est correctement exécutée, il suffit de vérifier dans la console Active Directory Users and Computers que l'utilisateur possède bien une valeur pour l'attribut thumbnailPhoto (via l'éditeur d'attribut). La photo peut ensuite être consultée via Outlook (pour les messageries Exchange) ou le client Lync. thumbnailPhoto

Ce script s'exécute utilisateur par utilisateur. Il est possible d'imaginer une logique de traitement "en masse".

Voici un script pour remplacer la région Main du script traitant l'intégralité des comptes utilisateurs Active Directory.
On suppose que toutes les photos sont stockées dans le même répertoire et portent comme nom de fichier le samaccountname de l'utilisateur. Bien entendu, cette partie reste adaptable en fonction des besoins. Il est par exemple possible de changer la racine de la recherche pour ne cibler qu'une unité d'organisation. Pour se faire, il faut remplacer $Root = [ADSI]'' par le distinguished name de l'unité d'organisation ciblée. Exemple :
A titre informatif, la fonction Resize-Photo peut être totalement décorrelée du processus de mis à jour de l'objet AD et être utilisée pour d'autre situation. Il est en effet possible de sauvegarder l'image générée dans un fichier plutôt qu'en mémoire en changeant un paramètre de la méthode Save :
Il faut remplacer la variable $Ms (représentant le buffer mémoire que l'on a instantié) par un chemin de fichier.

Exchange 2010 / SCOM : Erreur après la désactivation de l’agent de scripting

Introduction

Dans un précédent article, nous avons découvert l'agent de scripting dans Exchange (http://blog.piservices.fr/post/Exchange-Decouverte-de-lagent-de-scripting.aspx). Pour rappel, cela permet  les fonctionnalités de base des cmdlets Exchange. Ainsi, on peut par exemple ajouter automatiquement une boîte d'archive au moment de la création de sa boîte aux lettres. Pour que cette opération fonctionne, il faut activer l'agent de scripting via la cmdlet “Enable-CmdletExtensionAgent”.

Cependant, si vous êtes amenés à désactiver cet agent ultérieurement, vous pouvez rencontrer de nombreuses erreurs avec l'event ID “6” dans le journal “MSExchange Management”.

Event

Ces erreurs peuvent être normales, lorsqu’un administrateur Exchange s'est trompé dans la syntaxe d'une cmdlet Powershell.

Contexte

Dans certaines situations ces erreurs sont à l’origine du mauvais  fonctionnement d'un composant tiers. En l'occurrence, comme nous allons le voir ici, il s'agit de System Center Operations Manager (SCOM). En effet, le Management Pack SCOM d'Exchange lance de nombreuses cmdlets afin d'effectuer des tests de vérification d'intégrité de l'infrastructure Exchange. A cause, de cette erreur, la supervision de l'infrastructure Exchange peut ne plus être opérationnelle.

Explication

Si on affiche l'erreur au format XML dans l’observateur d’événements, on obtient plus de détails :

 

Il est indiqué qu'Exchange ne trouve pas le fichier de configuration de l'agent de scripting : “File is not found: 'D:\Program Files\Microsoft\Exchange Server\V14\Bin\CmdletExtensionAgents\ScriptingAgentConfig.xml'”.

Cependant, si l'agent de scripting a été désactivé, il n'y a aucune raison qu'il soit utilisé. Pour rappel, le fichier de configuration ne doit être présent que si l'agent de scripting est démarré. Il est à noter que même si ce fichier est présent, l'erreur continue d'apparaître. Le message indiqué dans l'erreur n'est donc pas pertinent. En réalité, il s'avère que le service “Exchange Monitoring” ne prend pas en compte le changement de configuration. Il est utilisé par le management pack SCOM et permet d'executer toutes les cmdlets de diagnostics comme “Test-PopConnectivity”, “Test-MRSHealth”, “Test-ReplicationHealth”, ...

Résolution

Pour résoudre cette erreur, il suffit de redémarrer le service "Exchange Monitoring". Ainsi, la configuration des cmdlets extensions agents sera correctement prise en compte. 

Exchange Monitoring Service

Pour information, ce service peut être redémarré sans incidence.

NB : Il faut redémarrer ce service sur tous les serveurs de l'organisation Exchange car l'opération d'activation/désactivation de l'agent de scripting se fait sur la totalité de ceux-ci.

Création d’un Virtual Switch Hyper-V de type réseaux convergé en Powershell

 

Ici, nous allons voir comment créer un Switch virtuel Hyper-V de type convergé.

Sur un unique Switch virtuel Hyper-V, nous allons ici créer plusieurs Management OS qui permettront de séparer de façon logique via différences vNICs, des réseaux de type Live Migration, Cluster, Management ou autres.

image

 

Dans notre exemple, nous créons tout d'abord le switch virtuel Hyper-V.

New-VMSwitch "SwitchVirtuel" -MinimumBandwidthMode weight -NetAdapterName "NICsTeam" –AllowManagement $false

image

Nous allons maintenant ajouter 3 vNICs.

vNIC LiveMigration
Add-VMNetworkAdapter -ManagementOS -Name "LiveMigration" -SwitchName "SwitchVirtuel"


vNIC Cluster
Add-VMNetworkAdapter -ManagementOS -Name "Cluster" -SwitchName "SwitchVirtuel"


vNIC Management
Add-VMNetworkAdapter -ManagementOS -Name "Management" -SwitchName "SwitchVirtuel"

Dans l’affichage des cartes réseaux, trois nouvelles interfaces virtuelles sont apparues :

image

 

Maintenant afin de contrôler les différents flux réseaux véhiculés par ces interfaces, nous pouvons appliquer à chacune d’entre elle une politique de QOS.

QOS vNIC LiveMigration
Set-VMNetworkAdapter -ManagementOS -Name "LiveMigration" -MinimumBandwidthWeight 20

QOS vNIC Cluster
Set-VMNetworkAdapter -ManagementOS -Name "Cluster" -MinimumBandwidthWeight 30

QOS vNIC Management
Set-VMNetworkAdapter -ManagementOS -Name "Management" -MinimumBandwidthWeight 50

Remarque : la somme des Weights ici appliqués est de 100. (Ceci est hautement recommandé mais non requis d’avoir une somme à 100).

A l’aide de la commande Get-VMNetworkAdapter –ManagementOS vous pouvez voir les différentes vNICs créés. (non visible depuis l’interface graphique Hyper-V).

image

Configuration du Live Migration Settings dans un cluster en Powershell

 

Depuis la console de gestion Failover Cluster Manager, il est facile de sélectionner les réseau devant être utilisé par le Live Migration.

Allez sur Network ==> clique droit Live Migration Settings

image

 

Et il ne vous reste plus qu’a sélectionner les interfaces réseaux souhaitées.

image

 

Maintenant pour effectuer la même opération en Powershell, veuillez taper:

Get-ClusterResourceType -Name "Virtual Machine" | Set-ClusterParameter -Name MigrationExcludeNetworks -Value ([String]::Join(";",(Get-ClusterNetwork | Where-Object {$_.Name -notmatch "LM" -and $_.Name -notmatch "VN -"}).ID))   

Dans le filtre de la commande:

Where-Object {$_.Name -notmatch "XXX" -and $_.Name -notmatch "XXX"}).ID))

Veuiller taper comme valeurs pour les XXX une partie de la chaine de caractère du nom matchant vos interfaces réseaux afin de les identifier.

Modification des propriétés général du DHCP server clusterisé en Powershell

 

Vous souhaitez modifier les propriétés générale de la ressource cluster DHCP server en Powershell.

image

 

Récupérer dans 3 variables les Paths que vous voulez définir pour :

  • Database path
  • Audit file path
  • Backup path

$DatabasePath="j:\dhcp\db"
$AuditFilePath="j:\dhcp\logs"
$BackupPath="j:\dhcp\backup"

Récupérer maintenant votre ressource de type DHCP Service
$RessDHCP=get-ClusterResource "DHCP Server"

Nous allons maintenant manipuler des instances basées sur Microsoft.FailoverClusters.PowerShell.ClusterParameter qui va nous permettre de manipuler nos propriétés.

Modification du Database Path
$param1 = New-Object Microsoft.FailoverClusters.PowerShell.ClusterParameter $RessDHCP,DatabasePath,$DatabasePath

$param1 | Set-ClusterParameter

 

Modification de l'Audit File Path
$param2 = New-Object Microsoft.FailoverClusters.PowerShell.ClusterParameter $RessDHCP,LogFilePath,$AuditFilePath

$param2 | Set-ClusterParameter

 

Modification du Backup path
$param3 = New-Object Microsoft.FailoverClusters.PowerShell.ClusterParameter $RessDHCP,BackupPath,$BackupPath

$param3 | Set-ClusterParameter

 

Les propriétés sont maintenant définis.

Exchange : Découverte de l'agent de scripting

Introduction

Depuis Exchange 2010, il existe les agents d'extension des Cmdlets. C'est une fonctionalité méconnue (car peu documentée) et pourtant très utile dans beaucoup d'entreprise.

Ces agents permettent d'étendre les fonctionnalités de base d'Exchange. Par exemple lors de la création d'une boîte aux lettres, si une base de données n'est pas renseignée alors un agent se charge d'en choisir une automatiquement. Quelque soit le mode d'administration (Powershell ou via la console graphique EMC), l'agent se lancera. Cela vient entre autre du fait que la console Exchange ne fait qu'exécuter du Powershell en tâche de fond. Il est possible d'obtenir la liste de ces agents en exécutant la Cmdlet suivante dans une session Powershell Exchange :

Voici le résultat obtenu sur une infrastructure sans paramétrage particulier de ces agents :

Exchange Extension Agent Listing

Il existe de nombreux agents ; notamment pour la gestion de l'OAB ou des boîtes aux lettres. Dans le résultat obtenu, 2 attributs vont nous intéresser : l'activation et la priorité. Le premier permet simplement de savoir si l'agent est actuellement utilisé ou non. Le second concerne l'ordre d'application. En effet, plusieurs agents peuvent agir sur la même chose (par exemple : le choix de la base de données pour une boîte aux lettres). La priorité permet de définir l'agent qui sera utilisé (celui qui a la priorité la plus basse, les autres ne seront pas utilisés). Pour changer la priorité d'un agent, il suffit d'utiliser la commande suivante :

L'agent qui nous intéresse dans cet article est le "Scripting Agent". Nous allons voir comment l'utiliser ainsi que quels exemples d'utilisation.

L'agent de script

A contrario des autres agents, l'agent de scripting est entièrement customisable par les administrateurs Exchange. Typiquement, il va nous permettre par exemple, de réaliser certaines actions au moment de la création d'une boîte aux lettres et donc de l'exécution de la commande New-Mailbox ou Enable-Mailbox (activer/désactiver POP3/Single item recovery etc, création d'une boîte d'archive, envoi d'un mail automatique à l'utilisateur). On peux aussi imaginer un export automatique de la boîte aux lettres au format PST lorsque la commande remove-mailbox sera lancée. D'autres types d'actions sont réalisables. Elles seront détaillées plus loin dans cet article. Tout type de script Powershell peux être intégré.

Par défaut l'agent de scripting n'est pas activé. C'est pourquoi, on utilise la commande :

Cette commande active l'agent de scripting sur tous les serveurs Exchange de l'organisation.

Attention : Le fichier de configuration doit être présent sur tous vos serveurs Exchange. En effet, si l'agent de scripting est activé et que l'un des serveurs ne possède pas le fichier alors des erreurs peuvent survenir lorsque l'on appelle une commande Powershell ou lorsqu’on lance la console Exchange (impossibilité de se connecter au serveur ne possédant pas le fichier de configuration).

L'agent de scripting ne possède aucune configuration par défaut. Il convient aux administrateurs Exchange de la créer. Celle-ci se fait au travers du fichier ScriptingAgentConfig.xml qui doit être positionné dans le dossier C:\Program Files\Microsoft\Exchange Server\V14\Bin\CmdletExtensionAgents (à moduler suivant le répertoire d'installation d'Exchange). Un exemple existe dans ce même répertoire nommé ScriptingAgentConfig.xml.sample).

Ce fichier contiendra tous nos scripts d'automatisation. Regardons maintenant la hiérarchie de ce fichier XML :

La balise Configuration contient l'ensemble des scripts qui seront utilisés par l'agent de scripting. C'est la balise racine.

Les balises Feature contiennent chaque fonctionnalité que l'on souhaite ajouter. Il peut y en envoir plusieurs au sein d'une balise Configuration. Elle possède chacune 2 attributs :

  • Name : pour le nom que l'on souhaite donner à notre fonctionnalité)
  • Cmdlets : permet de spécifier les Cmdlets Powershell Exchange qui vont déclencher la fonctionnalité. S'il y en a plusieurs, elles doivent être séparées par des virgules (Exemple : "New-Mailbox,Enable-Mailbox").

La balise API Call précice à quel moment la fonctionnalité se déclenche. Elle contient aussi le script qui sera lancé au déclenchement. Il peux y en envoir plusieurs au sein d'une balise Feature. Elle possède un attribut Name qui peut avoir 4 valeurs possibles :

  • OnComplete : Le script fourni sera exécuté lorsque la commande appelé aura déjà été exécuté. Exemple : Après la création d'une boîte aux lettres, on souhaite envoyer un mail de bienvenu à l'utilisateur et activer le Single Item Recovery.
  • Validate : Utile lorsque l'on souhaite valider des attributs. Le script se déclenchera avant l'exécution de la commande. Exemple : On souhaite être sur que les attributs Location et Phone ont été renseignés ou qu'ils respectent une certaine nomenclature pendant la création d'une boîte aux lettres. Ainsi l'administrateur recevra une erreur lors de l'exécution de la commande comme si ces attributs étaient obligatoire. Lorsque le retour est $null alors l'étape de validation est un succès.
  • ProvisionDefaultProperties : Cela permet de définir des valeurs par défaut pour les propriétés d'un objet. Exemple : Lorsque l'on crée une boîte aux lettres Exchange, on peux imaginer une règle qui choisit automatiquement la base de données en fonction de la première lettre du nom de la personne. Attention, dans cet exemple, il est nécessaire de désactiver l'agent Mailbox Resources Management ou de baisser sa priorité en dessous de celle de l'agent de scripting. En effet, l'agent Mailbox Resources Management est en charge de l'attribution automatique d'une base de données si aucune n'est renseignée.
  • UpdateAffectedIConfigurable : Cette API offre la possibilité de définir des propriétés juste avant l'opération de validation.

L'ordre d'exécution des différentes API lorsque l'on exécute une commande Exchange est le suivant  :

ProvisionDefaultProperties - UpdateAffectedIConfigurable - Validate – OnComplete

L'exécution de la commande Powershell Exchange a lieu entre les étapes Validate et OnComplete.

Enfin la balise Common permet de définir des fonctions Powershell pouvant être utilisées dans les scripts des balises ApiCall (A utiliser comme une librairie). On peut aussi charger ses propres scripts Powershell.

La mise en forme du fichier ScriptingAgentConfig.xml est importante. En effet, il apparait que lorsque des espaces inutiles sont présents, Exchange génère une erreur similaire à celle ci-dessous :

ScriptingAgent Error

De plus, un événement est généré :

ScriptingAgent Error Event 

Pour ma part, afin d'éviter tout problème, je me suis rendu compte qu’il ne fallait mieux pas commenter les scripts présents dans le fichier xml.

NB : Une fois l'agent de scripting activé, les modifications du fichier ScriptingAgentConfig.xml sont prises en compte automatiquement.

Exemple d'utilisation avec l'événement OnComplete :

Lorsqu'on utilise l'API OnComplete, la variable $succeeded existe si la commande a réussi. Cela permet de gérer les cas d'échecs (il serait impossible d'effectuer un traitement sur une boîte aux lettres qui n'existerait pas).

L’exemple ci-dessous est un fichier ScriptingAgentConfig.xml permettant d’activer la boîte d’archive et le single item recovery lorsqu’une nouvelle boîte aux lettres Exchange est créée (Commande New-Mailbox et Enable-Mailbox). On remarque que l’on accède aux paramètres définis par l’utilisateur via la variable $provisioningHandler qui contient un hastable nommé UserSpecifiedParameters.

Exemple d'utilisation avec l'événement Validate : 

Ce nouvel exemple montre cette fois-ci l'usage de l'API Validate. Ici, lorsqu'une boîte aux lettres de salle est créée, on vérifie que son nom est bien du type : Salle, XX où XX est un nombre. Si le test échoue alors une erreur est retourné avec un message qui sera affiché pour l’administrateur (que l’action soit réalisée via EMS ou l’EMC).

Desired State Configuration (Partie 5) : Création d’une ressource personnalisée

Introduction

Cet article fait partie d’une série de 5 billets sur Desired State Configuration :

Desired State Configuration est disponible comme Powershell 4.0 sur Windows 2012 R2/8.1, Windows 2012/8 et Windows 2008 R2/7.

Lors du précédent article nous avons vu l'implémentation du mode Pull via un web service.

Desired State Configuration est fourni avec un certain nombre de ressources. Malgré qu'il y en ai peu, et comme évoqué dans le précédent article, Microsoft et la communauté se sont employés à créer des nouvelles ressources. Dans cette cinquième et dernière partie, nous évoquerons la création d’une ressource personnalisée. Cette dernière permettra de prendre en charge un scénario non présent dans les ressources existantes : la présence d'un partage NFS.

Fonctionnement

Une ressource est constituée de plusieurs fichiers :

  • Un fichier .SCHEMA.MOF contenant sa définition et plus particulièrement toutes les propriétés que l'on pourra renseigner.
  • Un module Powershell contenant quelques fonctions obligatoires (.PSM1)
  • Un fichier .PSD1 représentant le manifest du module Powershell. Ce dernier contiendra les fonctions a exporter de notre module. Ce dernier est principalement utilisé pour versionner le module et avoir quelques informations dessus.

Le module Powershell doit obligatoirement comporter trois fonctions. Elles seront appelées lorsqu'un fichier de configuration contiendra une ressource du type que l'on aura créé. “Get-TargetResource” permet de récupérer la configuration telle qu'elle a été définie. “Set-TargetResource” applique une configuration (création, modification et suppression) et “Test-TargetResource” effectue le test de validité (elle retourne un booléen).

Il convient à la personne créant le module de développer le corps de ces fonctions (le squelette étant toujours identique), c'est à dire les paramètres et les process effectués.

Pré-requis

Au lancement de Powershell 4.0, il pouvait être fastidieux de développer ses propres ressources car il fallait respecter une certaine syntaxe. Cependant, Microsoft a développé un module permettant de faciliter la création de ressource à destination de DSC : xDscResourceDesigner. Ce dernier va nous permettre de générer nos fichiers automatiquement. Il est disponible en suivant le lien ci-dessous : http://gallery.technet.microsoft.com/scriptcenter/xDscResourceDesigne-Module-22eddb29

Il suffit ensuite de placer ce module dans le dossier :
C:\Program Files\WindowsPowerShell\Modules”.

DSC xDscResourceDesigner

Création de la ressource

Pour créer la ressource, on commence par définir ses propriétés avec la cmdlet “New-xDscResourceProperty”. Celles-ci possèdent à minima un nom, un type et des attributs. Ces derniers permettent de définir l'accessibilité (lecture, écriture,...). Lorsque l'on définit une nouvelle ressource, au moins une de ses propriétés devra posséder l'attribut “Key” et ne pourra être un tableau. Cet attribut permet d'indiquer la propriété utilisée lors de la recherche d'une ressource.

Dans l'exemple ci-dessous, on définit 3 propriétés :

  • le nom du partage
  • le chemin vers lequel le partage pointe
  • la présence ou l'abscence du partage
Ensuite, il est nécessaire de créer la ressource via la cmdlet “New-xDscResource”. Il faut spécifier toutes les propriétés utilisées dans cette ressource, le nom de la ressource et éventuellement le chemin où l'on va la stocker (sinon il sera placé dans un répertoire “DSCResources” à l’intérieur du répertoire dans lequel on se trouve).
Nous nous retrouvons avec le fichier .MOF ci-dessous :

Un module Powershell qui ne comprend pour l'instant que le fichier .PSM1 a aussi été généré. Il faut maintenant définir la logique de nos 3 fonctions à l'intérieur de ce module.

Get-TargetResource

Le code intégré à la fonction “Get-TargetResource” récupère le partage NFS s'il existe et retourne le chemin vers lequel il pointe. S'il n'y a pas de partage NFS avec ce nom, alors un message est écrit dans l'invite de commande Powershell.

Set-TargetRessource

Dans le code ci-dessous, on récupère un éventuel partage avec le nom défini en paramètre. Si ce dernier existe, alors on le met à jour avec le bon chemin (obligation de supprimer puis de recréer le partage NFS) sinon le partage NFS est créé. Si le partage est présent alors que la propriété “Ensure” a pour valeur “Absent” alors le partage NFS est supprimé. Il est à noter que cette fonction n'est appelée que lors de la modification d'un fichier de configuration d'un serveur ou lorsqu’une configuration est incorrecte.

NB : Lors de la génération du template de module à remplir, il est indiqué dans le corps de la fonction qu'il faut positionné la variable globale “$global:DSCMachineStatus” avec la valeur 1 si une configuration nécessite un reboot après son application.

Test-TargetResource

Cette dernière fonction valide qu'une configuration est bien appliquée. Elle vérifie l'existence du partage ainsi que le chemin vers lequel il pointe si le paramètre “Ensure” a pour valeur “Present”. Si “Ensure” vaut “Absent” alors il est vérifié que le partage NFS n'existe pas. Les différents tests retournent la valeur “$true” si la configuration est bonne et “$false” dans le cas contraire. 

A noter, qu'à la fin de notre module, la cmdlet “Export-ModuleMember” est présente et obligatoire afin que Powershell découvre correctement les méthodes de la ressource.

Génération du manifest

Enfin, il faut générer le fichier de manifest du module. Afin de réaliser cette opération, il faut utiliser la commance New-ModuleManifest en spécifiant les paramètres “FunctionsToExport”, “RequiredModules” et “Path”. Attention, le chemin indiqué doit être la racine de la ressource créée (Au même niveau que le dossier DSCResources), sinon il vous sera impossible d'importer la ressource. De même, le nom du manifest doit être le même que le nom du module.

Les autres champs du fichier .PSD1 généré peuvent aussi être spécifiés via la cmdlet précédente ou en remplissant manuellement le fichier (via un éditeur de texte). Certaines propriétés seront même automatiquement remplies (exemple : auteur avec le samaccountname de l'utilisateur ayant lancé la commande).

Voici un lien menant vers le manifest généré pour cette ressource : Manifest

Import de la ressource et utilisation

Il suffit de placer notre ressource (Répertoire C:\NFSShare dans notre exemple) dans “C:\Program Files\WindowsPowerShell\Modules\

En utilisant la commande “Get-DSCResource”, on remarque que notre ressource NFSShare est disponible. On s'aperçoit aussi que la propriété DependsOn est automatiquement rajouté sur cette ressource. Il s'agit d'une propriété par défaut disponible sur toutes les ressources DSC. Pour rappel elle permet de lier des configurations entre elles en spécifiant qu’une configuration dépend de la réussite d’une autre.
 DSC List Resources
Il est ensuite possible de générer un fichier de configuration pour un serveur. Il est nécessaire d'ajouter la commande “Import-DscResource” en renseignant le paramètre “ModuleName” dans le bloc de configuration lorsque l'on utilise des ressources personnalisées.
Enfin, on applique la configuration via la ligne de commande ci-dessous et on obtient bien la création du partage NFS :

DSC Result

Conclusion

Lors de cet article, nous avons vu la création d'une ressource permettant de gérer des partages NFS. Il est possible de l'améliorer en gérant d'autres propriétés de ce type de partage comme les permissions. 

Customiser ses pages ADFS / Ajout du suffixe UPN automatique dans l'identifiant

Préambule

L'ensemble des manipulations ont été réalisées sur une infrastructure Windows 2012 R2 / ADFS 3.0.

Problématique

Avec quelques connaissances en développement web (CSS et Javascript), il est possible de customiser les pages de logon ADFS. On peut positionner un logo qui remplacera le nom de la federation ou encore changer l'illustration par défaut. De plus, Microsoft offre aussi la possibilité de changer une partie du code Javascript et CSS. Nous verrons donc comment gérer ses templates ADFS puis je détaillerai un script Javascript permettant d'ajouter automatiquement le suffixe UPN de l'utilisateur. Ainsi toute personne souhaitant se connecter n'aura qu'à entrer son samAccountName. Attention, cette méthode n'est fonctionnelle que dans le cas où tous les utilisateurs possèdent le même suffixe UPN.

Gestion des templates ADFS

Microsoft fourni quelques indications pour customiser les pages ADFS sur le lien suivant :
http://technet.microsoft.com/en-us/library/dn280950.aspx . On retrouve notamment les modifications les plus basiques comme les changements d'images ou de messages (erreur, aide,...).

Aussi, dans ADFS 3.0, il est possible de gérer plusieurs templates via les Cmdlets Powershell adéquates. Le template de base se nomme "default". On peut d'ailleurs récupérer la liste des thèmes avec la Cmdlet Get-ADFSWebTheme. On remarque qu'il s'agit bien du template de base grâce à l'attribut IsBuiltinTheme.

Les étapes de customisation d'un thème sont les suivantes :

  • création d'un nouveau thème 
  • export des fichiers du thème 
  • modification des fichiers 
  • import des fichiers modifiés dans le thème créé

Pour ajouter un nouveau thème il suffit d'utiliser la commande New-AdfsWebTheme en spécifiant le nom du thème ainsi que les sources du nouveau thème. En général, on se basera sur le thème par défaut que l'on customisera ultérieurement.

 

Il nous faut ensuite exporter les fichiers de ce thème (vers le dossier C:\ADFSTheme par exemple) :

 

Attention le dossier d'export doit exister (il ne sera pas généré automatiquement).

On remarque que l'on a accès à un certain nombre de fichiers mais pas à tous. En général, ceux que l'on voudra customiser sont le fichier onload.js et le fichier style.css.

2014-04-18 11_53_36-SRV01673 - Remote Desktop Connection Manager v2.2

Une fois modifiée, il ne reste plus qu'à importer le fichier dans le thème nommé custom. Un exemple avec le fichier onload.js :

 

Enfin pour définir le thème custom comme actif il faut utiliser la Cmdlet ci-dessous :

 

Ajout automatique du suffixe UPN

Afin de faciliter l'expérience utilisateur lors d'un usage en situation de mobilité ou via un navigateur ne supportant pas ADFS, il peut être utile d"ajouter automatiquement le suffixe UPN lorsque ce dernier a été omis dans le formulaire d'authentification. Pour les utilisateurs ne connaissant pas les notions de nom de domain Netbios ou d'UPN, cette customisation peut être interessante. Celle-ci nécessite du code Javascript.

ADFS se base sur la valeur entrée dans le champ “UserName” avec l’ID “userNameInput” du fomulaire. Il faut donc modifier cette valeur. Une autre solution (utilisée ici), consiste à changer l’ID et le nom du champ original. Puis, on ajoute un nouveau champ, invisible à l’utilisateur et contenant la bonne valeur ainsi que l’ID et le nom mentionné précédemment. Cette seconde solution est esthétiquement plus réussi (l’utilisateur ne voit pas le changement)

Ci-dessous, se trouve le script a ajouté à la fin du fichier onload.js est à intégrer dans le thème ADFS via la méthode vu précédemment :

 

Voici les opérations réalisées par le script lorsque le formulaire est valider (via la touche “Entrée” ou un clic sur le bouton de connexion) :

  • Récupération du champ contenant l’identifiant utilisateur
  • Vérification de la présence d’un suffixe UPN

Si le suffixe est manquant :

  • On renomme le champ contenant l’identifiant utilisateur (UserName) et on change son ID (userNameInput).
  • On ajoute un nouveau champ non visible portant les valeurs initiales (Id et nom). Il contiendra la valeur entrée par l’utilisateur avec le suffixe UPN. Celles-ci seront transmises à ADFS.

Une amélioration pourrait être d'ajouter une balise “select” contenant une liste de tous les suffixes UPN possibles. Cela permettrait de gérer les infrastructures utilisant de multiples suffixes UPN.