Audit Active Directory : Part 3 – les comptes utilisateurs

Sommaire

 

 

Introduction

Autant d’un point de vue sécurité qu’à titre informatif, il peut être intéressant d’auditer vos comptes utilisateurs Active Directory.

Pour cela, j’ai réalisé un script PowerShell qui va vous permettre de générer un rapport Excel tel que présenté ci-dessous.

{gallery}78-AUDITAD-USERS{/gallery}

 

 

 

 

 

Le script disponible depuis le lien suivant : http://gallery.technet.microsoft.com/scriptcenter/Generate-Excel-report-48c3f3b4

L’objectif de cet article est donc de vous expliquer la méthodologie appliquée pour la réalisation de ce script. Cela vous permettra de comprendre son fonctionnement et d’analyser les données présentées.

 

 

Collecter les informations nécessaires

La première étape est bien entendu de collecter tous les comptes utilisateurs depuis votre annuaire Active Directory. L’information collectée devra nous permettre de quantifier les objets utilisateurs, d’en définir l’état et d’énumérer les différentes configurations existantes.

Le but n’est pas de collecter toutes les propriétés de chaque utilisateur sachant que cela peut s’avérer très consommateur et par forcément très pertinent.

Nous allons simplement nous focaliser sur les propriétés standards nécessaires à l’identification de chaque compte utilisateur (distinguishedName, sAMAccountName…). Je m’appuie également sur certains attributs spécifiques me permettant donc de qualifier la configuration et l’état de chaque compte utilisateur :

  • pwdLastSet : indique la date du dernier changement du mot de passe. Cet attribut va permettre d’identifier les comptes ayant un mot de passe de plus de XX jours.
  • lastLogonTimestamp : une fois le niveau fonctionnel de domaine Windows Server 2003 activé au sein de votre infrastructure Active Directory, les contrôleurs de domaine utilisent cet attribut pour identifier la date de dernière ouverture de session. L’attribut n’est pas 100% fiable sachant que certains comptes utilisateurs sont exclusivement utilisés via des portails Web qui ne vont pas permettre de mettre à jour cet attribut. Toutefois, il reste le meilleur moyen pour identifier si un  compte utilisateur est inactif ou non.
  • accountexpires : cet attribut contient la date d’expiration d’un compte utilisateur. Il permettra donc d’identifier les comptes ayant expirés.
  • userAccountControl : cet attribut est particulièrement riche en information car il contient de nombreux indicateurs sur la configuration de chaque utilisateur (http://support.microsoft.com/kb/305144/fr).

 

Depuis Windows Server 2003, certains indicateurs de l’attribut userAccountControl ont été remplacé par l’attribut construit « msds-user-account-control-computed ». Nous trouverons entre autres les informations de verrouillage du compte te de l’expiration du mot de passe. Nous devrons donc également l’exploiter.

Le script génère donc un fichier CSV avec les informations suivantes :

  • displayName, distinguishedname, samaccountname, userPrincipalName : la valeur de chacun de ces attributs pour identifier le compte utilisateur. La liste n’est pas exhaustive. Il est possible que vous ayez besoin d’autres attributs…
  • useraccountcontrol: la valeur cet attribut est fournie uniquement à titre indicatif sachant que durant la collecte, l’attribut est déjà traité.
  • isPreAuthNotRequired: si l’option est activée, cela induit que le compte peut s’affranchir de la pré-authentification Kerberos et donc de mécanismes de sécurité supplémentaires.
  • isActive: indique que le compte est actif depuis une période spécifique (par défaut depuis 180 jours). La valeur de la période peut être changée grâce à paramètre « InactiveDays » du script.
  • isDESKeyOnly: permet d’utiliser la norme DES pour l’option de chiffrement qui est considéré comme obsolète.
  • isDisabled: spécifie si le compte est désactivé.
  • isExpired: informe que le compte est expiré.
  • isLocked: signale que le compte est verrouillé. Bien entendu, si vous avez une politique de déverrouillage de compte, l’information ne sera pertinente qu’au moment de la collecte.
  • isPwdNotRequired: indique si le compte peut utiliser un mot de passe vide. Cette option peut représenter un risque en termes de sécurité.
  • isPwdEncryptedTextAllowed: autorise le stockage de mots de passe par le biais d’un chiffrement réversible et donc n’assure nullement la protection du mot de passe.
  • isPwdOld: indique si le mot de passe est considéré comme étant obsolète (par défaut 120 jours). La durée d’obsolescence peut être modifiée via le paramètre « PasswordAge » du script.
  • isPwdNeverExpires: informe que le mot de passe n’a pas d’expiration. Un mot de passe qui n’expire jamais peut représenter une faille de sécurité.
  • isPwdExpired: permet de savoir si le mot de passe du compte utilisateur est expire.

Le rapport Excel s’appuie donc exclusivement sur la collecte de ces données. Afin de vous faciliter la vie, le script stocke ces données dans un fichier CSV afin de permettre soit de le traiter selon vos besoins ou tout simplement de pouvoir collecter les données et de générer les informations de manière séparée.

Le paramètre « CollectOnly » du script va permettre de collecter uniquement les données sans générer le fichier Excel. Le paramètre « ExistingData », quant à lui, va permettre de générer le  rapport Excel à partir d’un fichier de collecte existant.

 

 

Informations utiles sur le rapport Excel

Comme vous avez pu le voir en introduction, le rapport Excel contient trois graphiques différents :

Volumetry of user accounts : ce graphique permet d’avoir le nombre total d’objets utilisateur de votre domaine. Il permet également de voir le pourcentage de comptes actifs/inactifs. Plus le pourcentage de comptes inactifs est élevé plus cela indique qu’il faudra intégrer une stratégie de cycle de vie sur les comptes utilisateurs.

Status of user accounts : le deuxième tableau liste les différents états possibles de vos comptes utilisateurs actifs et inactifs. J’ai décidé de scinder l’information entre les utilisateurs actifs et inactifs sachant qu’elle n’est pas forcément très pertinente pour des comptes inactifs… Le graphique se focalise sur l’état des comptes actifs. Notez également qu’un compte peut être dans plusieurs états simultanément… hormis pour l’état dit « standard » qui est exclusif.

Configuration of user accounts : à la manière du deuxième tableau, il liste les différentes configurations de vos comptes utilisateurs actifs et inactifs et fourni un graphique uniquement sur les utilisateurs actifs. Un compte utilisateur peut avoir plusieurs paramètres associés.

 

 

Conclusion

Avec cette troisième partie sur l’audit d’Active Directory, je vous ai proposé une solution rapide et simple pour collecter et traiter les informations de l’ensemble de vos comptes utilisateurs. Le prochain article se focalisera plus spécifiquement sur les comptes disposant de privilèges.

Manipuler Excel avec PowerShell : Part 4 – Ajouter un graphique

Dans l’article précédent, je vous ai montré comment mettre en forme votre tableau sous Excel à l’aide de PowerShell.

Nous avions obtenu le résultat ci-dessous.

 

Dans cet article, je vais vous montrer comment ajouter un graphique.

 

On commence par instancier notre objet de type « Chart ».

{codecitation style= »brush: PowerShell »}

$Chart = $WorkSheet.Shapes.AddChart().Chart

{/codecitation}

 

On va maintenant définir le type de notre graphique. Pour cela, il faut choisir parmi la longue liste que propose Excel. Ils sont énumérés depuis le lien http://msdn.microsoft.com/en-us/library/office/bb241008(v=office.12).aspx avec la valeur correspondante. Je vais partir sur un « histogramme 3D groupé ».

{codecitation style= »brush: PowerShell »}

$Chart.ChartType = 54

{/codecitation}

 

On peut spécifier également un style à notre graphique via la propriété « ChartStyle ». Il est assez dur de les identifier et d’ailleurs la documentation Microsoft parle d’une valeur possible comprise entre 1 et 48 mais j’ai pu définir mon style à une valeur bien plus élevée… J’ai donc fait un petit try-catch au cas où…

{codecitation style= »brush: PowerShell »}

try

{

$Chart.ChartStyle = 288

}

catch

{

$chart.ChartStyle = 1

}

{/codecitation}

 

On va continuer sur la mise en forme. On va désactiver les légendes à l’aide de la propriété « HasLegend ». On va activer le titre avec les propriétés « HasTitle » et « Text ».

{codecitation style= »brush: PowerShell »}

$Chart.HasLegend = $false

$Chart.HasTitle = $true

$Chart.ChartTitle.Text = « Production de bananes (en tonnes) »

{/codecitation}

 

Nous en avons terminé avec la mise en forme… On va s’attaquer aux données. On va ajouter une nouvelle série avec les années en abscisse (propriété « XValues ») et les tonnes en ordonnée (propriété « Values »). Pour cela on va utiliser des étendues.

{codecitation style= »brush: PowerShell »}

$Chart.SeriesCollection(1).XValues = $WorkSheet.Range($WorkSheet.Cells.Item(4,1),$WorkSheet.Cells.Item(7,1))

$Chart.SeriesCollection(1).Values = $WorkSheet.Range($WorkSheet.Cells.Item(4,2),$WorkSheet.Cells.Item(7,2))

{/codecitation}

 

Il y a différentes solutions en fonction des données à traiter, le nombre de séries ou le type de graphique mais vous avez déjà un bon exemple à votre disposition.

La toute dernière étape est le positionnement du graphique… A ma connaissance, la meilleure solution est de s’appuyer sur une étendue pour définir le positionnement et la taille. Ça pourrait paraitre plus compliqué mais au final vous verrez que s’est nettement plus pratique, surtout si vous êtes maniaque…

On créée donc une nouvelle étendue.

{codecitation style= »brush: PowerShell »}

$RangePositionChart = $WorkSheet.Range($WorkSheet.Cells.Item(10,1),$WorkSheet.Cells.Item(25,4))

{/codecitation}

 

On va ensuite utiliser l’objet parent contenant le graphique et définir la taille et le positionnement par rapport à notre étendue définie préalablement.

{codecitation style= »brush: PowerShell »}

$ChartObj = $Chart.Parent

$ChartObj.Height = $RangePositionChart.Height

$ChartObj.Width = $RangePositionChart.Width

$ChartObj.Top = $RangePositionChart.Top

$ChartObj.Left = $RangePositionChart.Left

{/codecitation}

 

Et voila le résultat !

 

Et le script au complet:

{codecitation style= »brush: PowerShell »}

[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo] « en-US »

 

$Excel = New-Object -ComObject « Excel.Application »

 

$WorkBook = $Excel.Workbooks.Add()

 

$WorkSheet = $WorkBook.WorkSheets.Add()

$WorkSheet.Name = « Production de bananes »

$WorkSheet.Select()

 

$WorkSheet.Cells.Item(1,1) = « Production annuelle de bananes »

 

$ArrProduction = @((‘2010’,’4.5’),(‘2011’,’12’),(‘2012’,’11.5’),(‘2013’,’15’))

 

$WorkSheet.Cells.Item(3,1) = « Année »

$WorkSheet.Cells.Item(3,2) = « Production (en tonnes) »

 

$InitialRow = 4

 

for ( $i=0; $i -lt $ArrProduction.Count; $i++ )

{

$WorkSheet.Cells.Item($InitialRow,1) = $ArrProduction[$i][0]

$WorkSheet.Cells.Item($InitialRow,2) = [decimal] $ArrProduction[$i][1]

$InitialRow++

}

 

$RangeTitle = $WorkSheet.Range($WorkSheet.Cells.Item(1,1),$WorkSheet.Cells.Item(1,2))

$RangeTitle.MergeCells = $true

$RangeTitle.Style = ($WorkBook.Styles.Item(43)).Name

$RangeTitle.HorizontalAlignment = [Microsoft.Office.Interop.Excel.XlHAlign]::xlHAlignCenter

$RangeTitle.ColumnWidth = 20

 

$RangeTable = $WorkSheet.Range($WorkSheet.Cells.Item(3,1),$WorkSheet.Cells.Item(7,2))

$ListObject = $WorkSheet.ListObjects.Add(1,$RangeTable,$null,1,$null)

$ListObject.TableStyle = « TableStyleLight6 »

 

$ListObject.ShowTotals = $true

$ListObject.ShowHeaders = $true

$ListObject.ShowAutoFilterDropDown = $false

 

$RangeSort = $WorkSheet.Range($WorkSheet.Cells.Item(4,1).Address($False,$False))

$WorkSheet.Sort.SortFields.Add($RangeSort,0,1) | Out-Null

$WorkSheet.Sort.SetRange($RangeTable)

$WorkSheet.Sort.Header = 1

$WorkSheet.Sort.Apply()

 

$Chart = $WorkSheet.Shapes.AddChart().Chart

$Chart.ChartType = 54

 

try

{

$Chart.ChartStyle = 288

}

catch

{

$chart.ChartStyle = 1

}

 

$Chart.HasLegend = $false

$Chart.HasTitle = $true

$Chart.ChartTitle.Text = « Production de bananes (en tonnes) »

 

$Chart.SeriesCollection(1).XValues = $WorkSheet.Range($WorkSheet.Cells.Item(4,1),$WorkSheet.Cells.Item(7,1))

$Chart.SeriesCollection(1).Values = $WorkSheet.Range($WorkSheet.Cells.Item(4,2),$WorkSheet.Cells.Item(7,2))

 

$RangePositionChart = $WorkSheet.Range($WorkSheet.Cells.Item(10,1),$WorkSheet.Cells.Item(25,4))

$ChartObj = $Chart.Parent

$ChartObj.Height = $RangePositionChart.Height

$ChartObj.Width = $RangePositionChart.Width

$ChartObj.Top = $RangePositionChart.Top

$ChartObj.Left = $RangePositionChart.Left

 

$WorkBook.SaveAs(« c:\temp\MaProductionDeBananes.xlsx »)

$Excel.Visible = $true

{/codecitation}

 

Grâce à cette séries d’articles, v devriez avoir bonnes bases pour commencer à générer vos tableaux et graphiques sur Excel à l’aide de Powershell.

Si vous voulez un exemple plus complexe, vous pouvez également consulter le code d’un de mes scripts depuis le lien technet suivant : http://gallery.technet.microsoft.com/scriptcenter/Generate-Excel-report-48c3f3b4

Il y a également de très nombreux exemples en VBA sur Internet qui vous permettra de vous guider sur les différentes méthodes et propriétés à utiliser.

Enfin, vous avez également le site MSDN dont j’ai fait assez souvent référence et qui est plutôt bien documenté !

Pour les autres articles sur le sujet:

Manipuler Excel avec PowerShell : Part 3 – Mettre en forme un tableau

Dans l’article précédent, je vous ai montré comment appliquer un style à une cellule pour obtenir le fichier Excel suivant:

 

Maintenant, on va aller un peu plus loin et on va manipuler le tableau et lui appliquer un style.  On va définir l’étendue de notre tableau (dans notre exemple de A3 à B7) :

{codecitation style= »brush: PowerShell »}

$RangeTable = $WorkSheet.Range($WorkSheet.Cells.Item(3,1),$WorkSheet.Cells.Item(7,2))

{/codecitation}

 

On va définir notre tableau en un type « ListObjects » (http://msdn.microsoft.com/en-us/library/ff196851(v=office.14).aspx)  et en utilisant la méthode « add() » (http://msdn.microsoft.com/en-us/library/office/bb211863(v=office.12).aspx). Ceci va nous permettre de profiter de l’ensemble des fonctions.

{codecitation style= »brush: PowerShell »}

$ListObject = $WorkSheet.ListObjects.Add(1,$RangeTable,$null,1,$null)

{/codecitation}

Nous n’avons plus qu’à appliquer un style de tableau Excel existant. Pour obtenir la liste complète, vous pouvez utiliser la commande « $WorkBook.TableStyles | ft name ». Il s’agit de la liste disponible depuis « Mettre sous forme de tableau » sous Excel.

 

Je vais appliquer le style « TableStyleLight6 »:

{codecitation style= »brush: PowerShell »}

$ListObject.TableStyle = « TableStyleLight6 »

{/codecitation}

Comme c’était le cas pour les styles de cellules, on peut appeler un style de tableau par son nom ou par son index. Il semblerait toutefois que les noms des styles de tableau ne soient pas traduits dans la langue locale… Par contre, certains styles peuvent avoir le même nom et être différents entre les versions d’Excel. C’est le cas du style « TableStyleLight6 » qui n’est pas le même entre Excel 2007 et Excel 2013… Je n’ai pas de solution miracle sachant que la création d’un style de tableau est beaucoup complexe que la création d’un style de cellules.

 

On pourrait affiner la mise en forme en permettant, par exemple, l’affichage de la ligne des totaux :

{codecitation style= »brush: PowerShell »}

$ListObject.ShowTotals = $true

{/codecitation}

…ou en désactivant le filtrage automatique :

{codecitation style= »brush: PowerShell »}

$ListObject.ShowAutoFilterDropDown = $false

{/codecitation}

C’est un exemple parmi tant d’autres… mais voici ce que l’on peut déjà obtenir visuellement.

 

Pour conclure cet article, on va corser un peu tout cela et on va essayer de trier les données. L’objectif est de classer par ordre croissant la production de manière automatique. Je ne vous cache que j’ai eu pas mal de difficultés pour y arriver et qu’il y a peut-être plus simple…

Premièrement, je défini l’étendue sur laquelle portera le tri. Je désigne simplement la première cellule concernée soit la cellule B4.

{codecitation style= »brush: PowerShell »}

$RangeSort = $WorkSheet.Range(« B4 »)

{/codecitation}

J’aurai pu très bien utiliser la valeur numérique pour identifier la position de la cellule. Ça peut être très pratique lorsque l’on veut améliorer l’automatisation. Par contre, comme la fonction « Range » ne peut pas interpréter la position d’une cellule par sa valeur numérique seule, il faut la convertir.

{codecitation style= »brush: PowerShell »}

$RangeSort = $WorkSheet.Range($WorkSheet.Cells.Item(4,2).Address($False,$False))

{/codecitation}

On utilise ensuite la méthode SortFields.Add() pour la création de notre tri (http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.sortfields.add.aspx). La syntaxe est .Add(MonEtendue, SortOn, Order, CustomOrder, DataOption) (consulter les liens pour obtenir les différentes valeurs possibles).

{codecitation style= »brush: PowerShell »}

$WorkSheet.Sort.SortFields.Add($RangeSort,0,1) | Out-Null

{/codecitation}

On définit l’étendue affectée par le tri. En l’occurrence il s’agit de notre tableau.

{codecitation style= »brush: PowerShell »}

$WorkSheet.Sort.SetRange($RangeTable)

{/codecitation}

Il nous reste plus qu’à exclure l’entête du triage à l’aide la propriété « Header » de l’objet « Sort ». Pour la liste des valeurs possibles consulter le lien http://msdn.microsoft.com/fr-fr/library/office/ff838812.aspx.

{codecitation style= »brush: PowerShell »}

$WorkSheet.Sort.Header = 1

{/codecitation}

Nous achevons le tri via la méthode Apply().

{codecitation style= »brush: PowerShell »}

$WorkSheet.Sort.Apply()

{/codecitation}

Et voila le résultat!

 

Et le script au complet:

{codecitation style= »brush: PowerShell »}

[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo] « en-US »

 

$Excel = New-Object -ComObject « Excel.Application »

 

$WorkBook = $Excel.Workbooks.Add()

 

$WorkSheet = $WorkBook.WorkSheets.Add()

$WorkSheet.Name = « Production de bananes »

$WorkSheet.Select()

 

$WorkSheet.Cells.Item(1,1) = « Production annuelle de bananes »

 

$ArrProduction = @((‘2010’,’4.5’),(‘2011’,’12’),(‘2012’,’11.5’),(‘2013’,’15’))

 

$WorkSheet.Cells.Item(3,1) = « Année »

$WorkSheet.Cells.Item(3,2) = « Production (en tonnes) »

 

$InitialRow = 4

 

for ( $i=0; $i -lt $ArrProduction.Count; $i++ )

{

$WorkSheet.Cells.Item($InitialRow,1) = $ArrProduction[$i][0]

$WorkSheet.Cells.Item($InitialRow,2) = [decimal] $ArrProduction[$i][1]

$InitialRow++

}

 

$RangeTitle = $WorkSheet.Range($WorkSheet.Cells.Item(1,1),$WorkSheet.Cells.Item(1,2))

$RangeTitle.MergeCells = $true

$RangeTitle.Style = ($WorkBook.Styles.Item(43)).Name

$RangeTitle.HorizontalAlignment = [Microsoft.Office.Interop.Excel.XlHAlign]::xlHAlignCenter

$RangeTitle.ColumnWidth = 20

 

$RangeTable = $WorkSheet.Range($WorkSheet.Cells.Item(3,1),$WorkSheet.Cells.Item(7,2))

$ListObject = $WorkSheet.ListObjects.Add(1,$RangeTable,$null,1,$null)

$ListObject.TableStyle = « TableStyleLight6 »

 

$ListObject.ShowTotals = $true

$ListObject.ShowHeaders = $true

$ListObject.ShowAutoFilterDropDown = $false

 

$RangeSort = $WorkSheet.Range($WorkSheet.Cells.Item(4,2).Address($False,$False))

$WorkSheet.Sort.SortFields.Add($RangeSort,0,1) | Out-Null

$WorkSheet.Sort.SetRange($RangeTable)

$WorkSheet.Sort.Header = 1

$WorkSheet.Sort.Apply()

 

$WorkBook.SaveAs(« c:\temp\MaProductionDeBananes.xlsx »)

$Excel.Visible = $true

{/codecitation}

Nous avons donc vu dans cette troisième partie comme manipuler et mettre en forme notre tableau Excel. Dans la quatrième partie, on va s’attaquer à la création du graphique.

Pour les autres articles sur le sujet:

Manipuler Excel avec PowerShell : Part 2 – Appliquer un style à vos cellules

Dans le premier article, je vous ai montré comment créer votre premier fichier Excel et l’alimenter avec PowerShell pour obtenir le résultat suivant :

 

Dans cet article, on va s’attarder un peu plus sur la mise en forme.

On va commencer par fusionner les cellules A1 et B1. Pour cela, il va falloir définir une étendue ou un « Range » correspondant à ces deux cellules :

{codecitation style= »brush: PowerShell »}

$RangeTitle = $WorkSheet.Range($WorkSheet.Cells.Item(1,1),$WorkSheet.Cells.Item(1,2))

{/codecitation}

 

Une fois l’étendue définie, on va faire appel à la propriété « MergeCells » pour fusionner les deux cellules :

{codecitation style= »brush: PowerShell »}

$RangeTitle.MergeCells = $true

{/codecitation}

 

On peut également appliquer un style à une cellule ou à une étendue. Pour cela, il suffit simplement d’associer un style Excel existant à la propriété « Style » de notre étendue. Par contre, cela nécessite d’avoir la liste des styles existants dans Excel et de savoir à quoi ils correspondent…

Pour obtenir la liste des styles, il suffit simplement de saisir la commande « $WorkBook.Styles | ft name » qui nous retourne la liste des styles à disposition et qui est disponible également depuis « Styles de Cellules » dans Excel.

 

On va appliquer le style « Titre 2 ». Pour cela deux solutions :

{codecitation style= »brush: PowerShell »}

#Solution 1

$RangeTitle.Style = « Titre 2 »

#Solution 2

$RangeTitle.Style = ($WorkBook.Styles.Item(43)).Name

{/codecitation}

 

La première solution est la plus simple, par contre, vous aurez sans doute noté que le nom du style est en français dans mon exemple. En fait, le titre du style est traduit, il n’y a aucune solution pour y remédier (en tout cas je n’ai pas trouvé !).

La deuxième solution est donc plus adaptée sauf que les styles n’ont pas la même indexation entre les différentes versions d’Excel…

Troisième solution… Créer son propre style en s’appuyant sur un style existant. Si dessous, un nouveau style s’appuyant sur le style Excel « Titre 2 ».

{codecitation style= »brush: PowerShell »}

$Style = $WorkBook.Styles.Add(« MonTitre »)

$Style.IncludeAlignment = $false

$Style.IncludeNumber = $false

$Style.IncludePatterns = $false

$Style.IncludeProtection = $false

 

# Style de police

$Style.Font.Bold = $true

$Style.Font.Color = 6968388

$Style.Font.ColorIndex = 50

$Style.Font.Size = 11

$Style.Font.ThemeColor = 4

 

# style des bordures

$Style.Borders.item(4).Color = 15123099

$Style.Borders.item(4).ColorIndex = 37

$Style.Borders.item(4).ThemeColor = 5

$Style.Borders.item(4).LineStyle = 1

$Style.Borders.item(4).Weight = -4138

$Style.Borders.item(4).TintAndShade = +0.4

 

$Style.IncludeBorder = $true

{/codecitation}

 

Vous pouvez vous appuyer sur cet exemple de style personnalisé pour appliquer une police ou une bordure particulière directement à une cellule ou à une étendue. Les propriétés sont les mêmes.

 

On peut également centrer le titre (voir la liste des valeurs possibles depuis http://msdn.microsoft.com/en-us/library/office/bb241313(v=office.12).aspx) :

{codecitation style= »brush: PowerShell »}

$RangeTitle.HorizontalAlignment = -4108

{/codecitation}

 

Si vous avez consulté le lien ci-dessus, nous aurions pu également appeler la valeur par son nom pour un résultat équivalent.

{codecitation style= »brush: PowerShell »}

$RangeTitle.HorizontalAlignment = [Microsoft.Office.Interop.Excel.XlHAlign]::xlHAlignCenter

{/codecitation}

 

C’est un point intéressant car de nombreuses méthodes la classe Office Interop Excel s’appuie sur ce genre d’énumération. Vous en avez la liste complète depuis http://msdn.microsoft.com/en-us/library/office/bb259481(v=office.12).aspx.

 

Pour conclure, on va définir la taille de nos colonnes sur notre étendue, histoire que le titre ne soit pas trop écrasé.

{codecitation style= »brush: PowerShell »}

$RangeTitle.ColumnWidth = 20

{/codecitation}

 

Et voila le résultat!

 

Et le script au complet:

{codecitation style= »brush: PowerShell »}

[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo] « en-US »

 

$Excel = New-Object -ComObject « Excel.Application »

 

$WorkBook = $Excel.Workbooks.Add()

 

$WorkSheet = $WorkBook.WorkSheets.Add()

$WorkSheet.Name = « Production de bananes »

$WorkSheet.Select()

 

$WorkSheet.Cells.Item(1,1) = « Production annuelle de bananes »

 

$ArrProduction = @((‘2010’,’4.5’),(‘2011’,’12’),(‘2012’,’11.5’),(‘2013’,’15’))

 

$WorkSheet.Cells.Item(3,1) = « Année »

$WorkSheet.Cells.Item(3,2) = « Production (en tonnes) »

 

$InitialRow = 4

 

for ( $i=0; $i -lt $ArrProduction.Count; $i++ )

{

$WorkSheet.Cells.Item($InitialRow,1) = $ArrProduction[$i][0]

$WorkSheet.Cells.Item($InitialRow,2) = [decimal] $ArrProduction[$i][1]

$InitialRow++

}

 

$RangeTitle = $WorkSheet.Range($WorkSheet.Cells.Item(1,1),$WorkSheet.Cells.Item(1,2))

$RangeTitle.MergeCells = $true

$RangeTitle.Style = ($WorkBook.Styles.Item(43)).Name

$RangeTitle.HorizontalAlignment = [Microsoft.Office.Interop.Excel.XlHAlign]::xlHAlignCenter

$RangeTitle.ColumnWidth = 20

 

$WorkBook.SaveAs(« c:\temp\MaProductionDeBananes.xlsx »)

$Excel.Visible = $true

{/codecitation}

 

On a vu dans ce deuxième article comment appliquer un style Excel existant et même créer une étendue. On verra dans le prochain article comment mettre en forme un tableau.

 

Vous pouvez consulter également mes autres articles sur le sujet:

Manipuler Excel avec PowerShell : Part 1 – Créer un classeur, un feuillet et un tableau

Dans cette série d’articles, je vais vous montrer les bases pour générer un fichier Excel à l’aide de PowerShell.

Au préalable et surtout afin d’éviter d’obtenir une erreur de type « Old format or invalid type library » (http://support.microsoft.com/kb/320369), nous allons définir les informations culturelles sur l’anglais avant d’instancier Excel :

{codecitation style= »brush: PowerShell »}

[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo] « en-US »

{/codecitation}

 

Nous pouvons, dès-lors, instancier notre objet Excel :

{codecitation style= »brush: PowerShell »}

$Excel = New-Object -ComObject « Excel.Application »

{/codecitation}


Avec notre objet Excel, nous allons créer notre classeur:

{codecitation style= »brush: PowerShell »}

$WorkBook = $Excel.Workbooks.Add()

{/codecitation}


Un classeur étant constitué de feuillets, ajoutons maintenant un feuillet:

{codecitation style= »brush: PowerShell »}

$WorkSheet = $WorkBook.WorkSheets.Add()

{/codecitation}

 

Donnons-lui un nom :

{codecitation style= »brush: PowerShell »}

$WorkSheet.Name = « Production de bananes »

{/codecitation}

 

Définissons le titre de notre futur tableau en position A1 :

{codecitation style= »brush: PowerShell »}

$WorkSheet.Cells.Item(1,1) = « Production annuelle de bananes »

{/codecitation}

 

Remarque : Le premier chiffre correspond au numéro de ligne et le deuxième chiffre au numéro de colonne.

 

Maintenant, nous allons créer notre tableau Excel. Mais, pour cela, on va déjà commencer par stocker les éléments de notre tableau:

{codecitation style= »brush: PowerShell »}

$ArrProduction = @((‘2010’,’4.5’),(‘2011’,’12’),(‘2012’,’11.5’),(‘2013’,’15’))

{/codecitation}

 

Nous déclarons les entêtes de notre tableau :

{codecitation style= »brush: PowerShell »}

$WorkSheet.Cells.Item(3,1) = « Année »

$WorkSheet.Cells.Item(3,2) = « Production (en tonnes) »

{/codecitation}

 

… et les données :

{codecitation style= »brush: PowerShell »}

$WorkSheet.Cells.Item(4,1) = $ArrProduction[0][0]

$WorkSheet.Cells.Item(4,2) = [decimal] $ArrProduction[0][1]

$WorkSheet.Cells.Item(5,1) = $ArrProduction[1][0]

$WorkSheet.Cells.Item(5,2) = [decimal] $ArrProduction[1][1]

$WorkSheet.Cells.Item(6,1) = $ArrProduction[2][0]

$WorkSheet.Cells.Item(6,2) = [decimal] $ArrProduction[2][1]

$WorkSheet.Cells.Item(7,1) = $ArrProduction[3][0]

$WorkSheet.Cells.Item(7,2) = [decimal] $ArrProduction[3][1]

{/codecitation}


Un autre méthode pour alimenter les cellules plus efficacement, dirons-nous…

{codecitation style= »brush: PowerShell »}

$InitialRow = 4

for ( $i=0; $i -lt $ArrProduction.Count; $i++ )

{

$WorkSheet.Cells.Item($InitialRow,1) = $ArrProduction[$i][0]

$WorkSheet.Cells.Item($InitialRow,2) = [decimal] $ArrProduction[$i][1]

$InitialRow++

}

{/codecitation}

 

Pour visualiser le fichier Excel, il faut simplement saisir la commande suivante:

{codecitation style= »brush: PowerShell »}

$Excel.Visible = $true

{/codecitation}

 

Si vous voulez sauvegarder le classeur Excel :

{codecitation style= »brush: PowerShell »}

$WorkBook.SaveAs(« c:\temp\MaProductionDeBananes.xlsx »)

{/codecitation}


Et voila le résultat!

 

Et le script au complet:

{codecitation style= »brush: PowerShell »}

[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo] « en-US »

$Excel = New-Object -ComObject « Excel.Application »

$WorkBook = $Excel.Workbooks.Add()

$WorkSheet = $WorkBook.WorkSheets.Add()

$WorkSheet.Name = « Production de bananes »

$WorkSheet.Select()

$WorkSheet.Cells.Item(1,1) = « Production annuelle de bananes »

$ArrProduction = @((‘2010’,’4.5’),(‘2011’,’12’),(‘2012’,’11.5’),(‘2013’,’15’))

 

$WorkSheet.Cells.Item(3,1) = « Année »

$WorkSheet.Cells.Item(3,2) = « Production (en tonnes) »


$InitialRow = 4

for ( $i=0; $i -lt $ArrProduction.Count; $i++ )

{

$WorkSheet.Cells.Item($InitialRow,1) = $ArrProduction[$i][0]

$WorkSheet.Cells.Item($InitialRow,2) = [decimal] $ArrProduction[$i][1]

$InitialRow++

}


$WorkBook.SaveAs(« c:\temp\MaProductionDeBananes.xlsx »)

$Excel.Visible = $true

{/codecitation}

 

On a vu dans ce premier article comment créer notre premier classeur, un feuillet et comment l’alimenter. Dans l’article suivant, nous nous attarderons un peu plus longuement sur la mise en forme.

Ci-dessous, les autres articles sur le sujet:

Gérer automatiquement le mot de passe administrateur DSRM à partir de Windows Server 2008

Sommaire

 

 

Introduction

Nous allons voir dans cet article comment gérer de manière centralisée le mot de passe du mode DSRM sur l’ensemble de vos contrôleurs de domaine à partir de Windows Server 2008.

Cet article fait écho à l’article de l’équipe Ask the Directory Services Team suivant : http://blogs.technet.com/b/askds/archive/2009/03/11/ds-restore-mode-password-maintenance.aspx.

 


Qu’est-ce que le mot de passe administrateur DSRM ?

Le mode DSRM (Directory Services Restore Mode) est un mode de démarrage disponible sur vos contrôleurs de domaine afin de réaliser une restauration Active Directory. Il est accessible depuis les options de démarrage avancées (menu disponible au démarrage du serveur à l’aide de la touche « F8 »).

{gallery}71_DSRMPWD/01{/gallery}

 

 

 

 

 

 

 

Lorsque vous démarrez sur un contrôleur de domaine avec le « mode de restauration des services d’annuaire », l’état du contrôleur de domaine ne permet pas de se connecter avec un compte du domaine. Sachant qu’un contrôleur de domaine ne dispose pas d’une base locale de comptes, il faut donc passer par un compte spécifique, une sorte de compte administrateur local pour les contrôleurs de domaine. D’ailleurs, lors de la promotion d’un serveur en tant que nouveau contrôleur de domaine, l’assistant de promotion vous propose de définir le mot de passe DSRM.

{gallery}71_DSRMPWD/02{/gallery}

 

 

 

 

 

 


 

 

Il faut donc que les personnes responsables de la promotion de nouveaux contrôleurs de domaine aient connaissance du mot de passe à définir. Afin d’éviter cela, il est également possible de passer par un fichier de réponse mais là encore le mot de passe DSRM sera stocké en clair.

L’outil en ligne de commande NTDSUTIL permet également de modifier le mot de passe DSRM.

 

Du coup, vous pourriez définir facilement le mot de passe DSRM et à intervalle régulier grâce à un script sur tous les contrôleurs de domaine. Toutefois, là encore, le problème du stockage du mot de passe va poser problème.

 

 

 

Utilisation d’un compte de domaine pour définir le mot de passe administrateur DSRM

Dès Windows Server 2008 et avec l’application du hotfix KB961320 (http://support.microsoft.com/kb/961320), NTDSUTIL permet d’être défini à partir d’un compte utilisateur du domaine. Il suffit simplement de spécifié « SYNC FROM DOMAIN ACCOUNT <mon compte> » lorsque NTDSUTIL nous demande de redéfinir le mot de passe administrateur DSRM.

Par exemple, sur votre annuaire Active Directory, créez un compte utilisateur « Administrateur DSRM » avec comme nom d’ouverture de session « adminDSRM ».

{gallery}71_DSRMPWD/04{/gallery}

 

 

 

 


Ouvrez ensuite une invite de commandes et tapez les commandes suivantes :

  • ntdsutil
  • Set DSRM Password
  • Sync from domain account adminDSRM
  • q
  • q

 

Le mot de passe administrateur DSRM est désormais défini sans avoir à le connaitre en spécifiant tout simplement le compte de domaine vers lequel se synchroniser. Par contre, il ne s’agit que d’une synchronisation sur demande. Du coup, si vous changez le mot de passe du compte du domaine, le mot de passe administrateur DSRM ne sera pas synchroniser automatiquement.

 

 

Synchroniser automatiquement le mot de passe administrateur DSRM

Afin de garantir que le mot de passe administrateur DSRM sur chaque contrôleur de domaine et identique à votre compte utilisateur du domaine l’idéal sera de lancer de manière automatique et à intervalle régulier la commande NTDSUTIL « sync from domain account … ».

Pour cela, nous allons déployé une tâche planifiée via une stratégie de groupe.

Commençons par ouvrir la console « Gestion de stratégie de groupe » en lançant la commande « gpmc.msc » depuis « Démarrer | Exécuter ».

 

Nous allons créer la nouvelle stratégie de groupe « Synchronisation du mot de passe DSRM » et la lier directement au conteneur « Domain Controllers ». Pour cela fait un clic droit sur le conteneur et sélectionnez « Créer un objet GPO dans ce domaine, le lier ici… ».

{gallery}71_DSRMPWD/07{/gallery}

 

 

 

 

 

 

 

La GPO étant créée, faites un clic droit dessus et sélectionnez « Modifier… » pour accéder à la console « Editeur de gestion des stratégies de groupe ».

{gallery}71_DSRMPWD/08{/gallery}

 

 

 


 

 

Naviguez ensuite vers « Configuration ordinateur | Préférences | Tâches planifiées » et, l’aide d’un clic droit sur « Tâches planifiées », choisissez « Nouveau => Tâche planifiée ».

{gallery}71_DSRMPWD/09{/gallery}

 

 


 

 

 

 

 

Dans les propriétés de la tâche planifiée :

  • Choisissez l’action « Mettre à jour »
  • Donnez-lui un nom
  • Spécifiez le chemin d’accès « %systemRoot%\system32\ntdsutil.exe » dans le champ « Exécuter »
  • Ajouter les arguments suivant : « « SET DSRM PASSWORD » « SYNC FROM DOMAIN ACCOUNT adminDSRM » Q Q »

{gallery}71_DSRMPWD/10{/gallery}

 

 

 

 

 

 

 

 

 

Depuis l’onglet « Planifier », définissez l’intervalle d’exécution qui vous conviendra le mieux.

{gallery}71_DSRMPWD/11{/gallery}

 

 

 

 

 

 

 

 

 

 

Pour aller plus loin…

Pour les quelques idées à développer… vous avez, par exemple, la possibilité de dédier un compte de domaine pour les RODC et les RWDC ou empêcher l’ouverture de session interactive pour ces comptes de domaine.

Autre point intéressant sera de mettre un filtre WMI sur votre GPO ou activer le « ciblage au niveau de l’élément » au sein même de la GPP pour exclure les éventuels contrôleurs de domaine encore en version Windows Server 2003.

 

How to Find Active Directory Schema Update History by Using PowerShell