L'ajout d'utilisateurs dans des groupes de manière temporaire est un vrai casse tête.
Ces demandes correspondant en très grande majorité à un besoin d'accès à des ressources réservées à des groupes de sécurité, et bien souvent certains utilisateurs doivent se voir octroyés des droits afin de remplacer un collègue absent.
Autant il est un peu plus simple de gérer des demandes d'accès temporaires lorsque l'on est seul en charge de l'informatique d'une société, autant le fait d'avoir plusieurs personnes au sein du service support ou le fait d'être prestataire et d'avoir de multiples clients peut rendre la tâche compliquée...
Et inutile de dire que de laisser des accès à une personne qui ne devrait pas ou plus les avoir n'est pas quelque chose d'anodin. C'est une faille de sécurité importante, qui pourrait avoir des conséquences encore plus importantes! Partant de ce constat et du fait que mon ordinateur commençait à grouiller de post-it me rappelant que je devais retirer ou ajouter en date du X l'utilisateur Y au groupe W, je me suis mis en tête de créer quelque chose de "simple" et efficace pour permettre de programmer des ajouts et des suppressions d'utilisateurs à des groupes à des dates précises. Afin de permettre à tout un chacun du service informatique de se servir de mon nouveau jouet, j'ai également programmé une interface utilisateur intuitive. Ce script a été testé et est fonctionnel sur Windows Server 2008R2 et 2012, doit fonctionner sur des versions supérieures.
L'interface en elle même vous est présentée ci-dessous. Elle comporte 8 points importants que je vais décrire.
Lorsque le bouton OK est validé, un fichier XML est créé dans un répertoire défini en entête du script. Ce fichier XML contient l'intégralité des entrées de la Datagridview et est traité dans un second script qui tourne en tache planifiée, et qui ajoute ou retire l'appartenance d'un ou plusieurs groupes aux utilisateurs qui ont dépassé les dates de début ou de fin. Le nom de chaque label ou de colonne de la grille de données est changeable afin d'être adaptable au client, à la seule condition de ne pas modifier les noms de champs de la grille de données une fois le script en production.
Ce script doit tourner en tâche planifiée, et être executé une fois par jour. Il va récupérer les fichiers XML crées par le formulaire, ainsi que les anciens fichiers déjà partiellement traités (Par exemple un ajout dans un groupe qui attends une fin), vérifier chaque date et ajouter chaque entrée qui n'a pas déjà été faite, commençant par ajouter dans les groupes, puis supprimer (ainsi si le script n'a pas pu tourner pendant X jours et que des modifications se font, cela se terminera par des retraits de groupes, et évitera de laisser une autorisation permanente.)
Des lors qu'il exécute une action, il ajoute une notation à l'objet représentant les ajouts / suppression en attente permettant de savoir si oui ou non une action a déjà été faite.
Si une erreur ou une incohérence se présentent, les exceptions sont affichées dans deux fichiers error.txt et warning.txt, permettant de détecter tout problème.
Afin de pouvoir rajouter à tout cela une autre tracabilité, je vous propose de reprendre également mon article qui permet de lister les modifications faites sur les groupes Active Directory entre deux exécutions du script.
Et maintenant...
Vous pouvez télécharger les 2 scripts (gui et script en planification) sur mon espace git personnel.
#La variable $path représente le repertoire dans lequel les données seront sauvegardées. Changez le également dans le script de planification pour qu'il corresponde à celui renseigné ici
$path = "\\nas\ScriptPS\Workspaces\TemporaryUserToGroup"
#Le nom des colonnes. Changez le à votre guise, mais ne le changez plus une fois que le script est mis en production
$columnsnames = @("Util.","Groupe","De","Jusque")
#Labels que vous pouvez changer à votre guise
$labelusername = "Util."
$labelgroupname = "Groupe"
$labelfromname = "De"
$labeluntilincluded = "Jusque (inclus)"
$labelform = "Ajout de groupe temporaire by Nicolas LANG. lang.nicolas54 arobase gmail .com"
$popupmessage = "Choisissez un utilisateur et un ou plusieurs groupes"
#Différents messages d'erreur que vous pouvez modifier si besoin est
$aderror = "Impossible d'obtenir des informations de groupe ou d'utilisateur. Vérifiez que le module AD pour Powershell est activé ou que le controleur de domaine est joignable"
$nopathcreated = "Impossible de créer $path"
try
{
$users = Get-ADUser -filter 'enabled -eq $true'
$groups = Get-ADGroup -filter *
}
catch
{
Write-Output $aderror
Start-Sleep -Seconds 5
throw("AD Error")
}
$datestart = Get-Date -Format yyyy-MM-dd
$array = New-Object System.Collections.ArrayList
If (!(Test-Path $path))
{
Try
{
New-Item $path -ItemType Folder -Force
}
Catch
{
throw($nopathcreated)
}
}
#region Import the Assemblies
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
#endregion
#region Generated Form Objects
$bds = New-Object System.Windows.Forms.BindingSource
$form1 = New-Object System.Windows.Forms.Form
$groupBox_permatemp = New-Object System.Windows.Forms.GroupBox
$radioButton_temporary = New-Object System.Windows.Forms.RadioButton
$radioButton_permanent = New-Object System.Windows.Forms.RadioButton
$label4 = New-Object System.Windows.Forms.Label
$button_OK = New-Object System.Windows.Forms.Button
$button3 = New-Object System.Windows.Forms.Button
$button_remove = New-Object System.Windows.Forms.Button
$button_add = New-Object System.Windows.Forms.Button
$listBox_results = New-Object System.Windows.Forms.ListBox
$label_from = New-Object System.Windows.Forms.Label
$dateTimePicker2 = New-Object System.Windows.Forms.DateTimePicker
$dateTimePicker1 = New-Object System.Windows.Forms.DateTimePicker
$label_group = New-Object System.Windows.Forms.Label
$label_utilisateur = New-Object System.Windows.Forms.Label
$comboBox1 = New-Object System.Windows.Forms.ComboBox
$datagridview1 = New-Object System.Windows.Forms.datagridview
$checkedListBox1 = New-Object System.Windows.Forms.CheckedListBox
$button_uncheck = New-Object System.Windows.Forms.Button
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
#endregion Generated Form Objects
#region fonctions
function Check-Date{
if ([datetime]$dateTimePicker1.value -gt [datetime]$dateTimePicker2.Value)
{
$dateTimePicker2.value = $dateTimePicker1.Value
}
}
Function Show-popup([string]$message){
$popup = New-Object -ComObject Wscript.Shell
$popup.Popup($message,0,"Erreur",0x0)
}
Function Check-Array($row, $comparearray){
$return = $false
foreach ($line in $comparearray)
{
if (!(Compare-Object $row.psobject.properties $line.psobject.properties))
{
$return = $true
return $return
}
}
return $return
}
#endregion
#show_sidebar: false
visible: false
----------------------------------------------
#Generated Event Script Blocks
#show_sidebar: false
visible: false
----------------------------------------------
#Provide Custom Code for events specified in PrimalForms.
$handler_button_add_MouseClick=
{
}
$handler_dateTimePicker2_ValueChanged=
{
Check-Date
}
$button_OK_OnClick=
{
if ($array.Count -gt 0)
{
$dateTime = "$(Get-Date -Format yyyyMMdd_HHmmss).xml"
$array | Export-Clixml (Join-Path $path $dateTime)
$form1.Close()
}
}
$handler_button3_MouseClick=
{
}
$handler_dateTimePicker1_ValueChanged=
{
Check-Date
}
$handler_button_uncheck_Click=
{
foreach ($checked in $checkedListBox1.CheckedIndices)
{
$checkedListBox1.SetItemChecked($checked,$False)
}
}
$handler_radioButton_permanent_CheckedChanged=
{
if ($radioButton_permanent.Checked)
{
$dateTimePicker1.Enabled = $False
$dateTimePicker2.Enabled = $False
}
else
{
$dateTimePicker1.Enabled = $True
$dateTimePicker2.Enabled = $True
}
}
$button_remove_OnClick=
{
foreach ($selectedrow in $datagridview1.SelectedRows)
{
$index= $array.IndexOf(($array | Where-Object {$_ -eq $selectedrow.DataBoundItem}))
$array.RemoveAt($index)
}
$datagridview1.DataSource = $null
$bds.DataSource = $null
$bds.DataSource = $array
$datagridview1.DataSource = $bds
}
$handler_button_OK_MouseClick=
{
$array | Export-Clixml
}
$button3_OnClick=
{
$array.Clear()
$datagridview1.DataSource = $null
$bds.DataSource = $null
$bds.DataSource = $array
$datagridview1.DataSource = $bds
#TODO: Place custom script here
}
$handler_button_remove_MouseClick=
{
#TODO: Place custom script here
}
$button_add_OnClick=
{
if ($checkedListBox1.SelectedItems.Count -gt 0 -and $comboBox1.SelectedItem -ne $null)
{
Foreach ($item in $($checkedListBox1.CheckedItems))
{
$newline = [pscustomobject]@{$columnsnames[0]=$comboBox1.SelectedItem;$columnsnames[1]=$item;$columnsnames[2]=([datetime]$dateTimePicker1.Value).ToShortDateString();$columnsnames[3]=([datetime]$dateTimePicker2.Value).ToShortDateString()}
$result = (Check-Array -row $newline -comparearray $array)
if (!($result))
{
$array.add($newline)
}
}
$datagridview1.DataSource = $null
$bds.DataSource = $null
$bds.DataSource = $array
$datagridview1.DataSource = $bds
}
else
{
Show-Popup $popupmessage
}
#TODO: Place custom script here
}
$OnLoadForm_StateCorrection=
{#Correct the initial state of the form to prevent the .Net maximized form issue
$form1.WindowState = $InitialFormWindowState
$comboBox1.items.AddRange($($users | select-object -ExpandProperty samaccountname | sort-object))
$checkedListBox1.items.AddRange($($groups | select-object -ExpandProperty name | sort-object))
}
#show_sidebar: false
visible: false
----------------------------------------------
#region Generated Form Code
$form1.AcceptButton = $button_OK
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 261
$System_Drawing_Size.Width = 1033
$form1.ClientSize = $System_Drawing_Size
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$form1.MaximizeBox = $False
$form1.Name = "form1"
$form1.ShowIcon = $False
$form1.Text = $labelform
$button_uncheck.BackColor = [System.Drawing.Color]::FromArgb(255,255,255,255)
$button_uncheck.DataBindings.DefaultDataSourceUpdateMode = 0
$button_uncheck.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",6,0,3,0)
$button_uncheck.ForeColor = [System.Drawing.Color]::FromArgb(255,255,0,0)
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 444
$System_Drawing_Point.Y = 42
$button_uncheck.Location = $System_Drawing_Point
$button_uncheck.Name = "button_uncheck"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 17
$System_Drawing_Size.Width = 23
$button_uncheck.Size = $System_Drawing_Size
$button_uncheck.TabIndex = 13
$button_uncheck.Text = "X"
$button_uncheck.UseVisualStyleBackColor = $False
$button_uncheck.add_Click($handler_button_uncheck_Click)
$form1.Controls.Add($button_uncheck)
$dataGridView1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 520
$System_Drawing_Point.Y = 8
$dataGridView1.Location = $System_Drawing_Point
$dataGridView1.Name = "dataGridView1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 241
$System_Drawing_Size.Width = 449
$dataGridView1.Size = $System_Drawing_Size
$dataGridView1.TabIndex = 12
$dataGridView1.SelectionMode = 1
$dataGridView1.AllowUserToAddRows = $False
$dataGridView1.AllowUserToDeleteRows = $False
$bds.DataSource = $array
$datagridview1.DataSource = $bds
$form1.Controls.Add($dataGridView1)
$groupBox_permatemp.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 68
$groupBox_permatemp.Location = $System_Drawing_Point
$groupBox_permatemp.Name = "groupBox_permatemp"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 74
$System_Drawing_Size.Width = 200
$groupBox_permatemp.Size = $System_Drawing_Size
$groupBox_permatemp.TabIndex = 2
$groupBox_permatemp.TabStop = $False
$form1.Controls.Add($groupBox_permatemp)
$radioButton_temporary.Checked = $True
$radioButton_temporary.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 7
$System_Drawing_Point.Y = 38
$radioButton_temporary.Location = $System_Drawing_Point
$radioButton_temporary.Name = "radioButton_temporary"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 24
$System_Drawing_Size.Width = 104
$radioButton_temporary.Size = $System_Drawing_Size
$radioButton_temporary.TabIndex = 3
$radioButton_temporary.TabStop = $True
$radioButton_temporary.Text = "Temporaire"
$radioButton_temporary.UseVisualStyleBackColor = $True
$groupBox_permatemp.Controls.Add($radioButton_temporary)
$radioButton_permanent.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 7
$System_Drawing_Point.Y = 10
$radioButton_permanent.Location = $System_Drawing_Point
$radioButton_permanent.Name = "radioButton_permanent"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 24
$System_Drawing_Size.Width = 104
$radioButton_permanent.Size = $System_Drawing_Size
$radioButton_permanent.TabIndex = 2
$radioButton_permanent.TabStop = $True
$radioButton_permanent.Text = "Permanent"
$radioButton_permanent.UseVisualStyleBackColor = $True
$radioButton_permanent.add_CheckedChanged($handler_radioButton_permanent_CheckedChanged)
$groupBox_permatemp.Controls.Add($radioButton_permanent)
$groupBox_permatemp.Visible = $False
$label4.BorderStyle = 1
$label4.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 198
$label4.Location = $System_Drawing_Point
$label4.Name = "label4"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 200
$label4.Size = $System_Drawing_Size
$label4.TabIndex = 9
$label4.Text = $labeluntilincluded
$label4.TextAlign = 32
$form1.Controls.Add($label4)
$button_OK.DataBindings.DefaultDataSourceUpdateMode = 0
$button_OK.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8,0,3,0)
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 975
$System_Drawing_Point.Y = 8
$button_OK.Location = $System_Drawing_Point
$button_OK.Name = "button_OK"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 31
$System_Drawing_Size.Width = 55
$button_OK.Size = $System_Drawing_Size
$button_OK.TabIndex = 11
$button_OK.Text = "OK"
$button_OK.UseVisualStyleBackColor = $True
$button_OK.add_Click($button_OK_OnClick)
#$button_OK.add_MouseClick($handler_button_OK_MouseClick)
$form1.Controls.Add($button_OK)
$button3.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 472
$System_Drawing_Point.Y = 182
$button3.Location = $System_Drawing_Point
$button3.Name = "button3"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 39
$System_Drawing_Size.Width = 42
$button3.Size = $System_Drawing_Size
$button3.TabIndex = 9
$button3.Text = "<<"
$button3.UseVisualStyleBackColor = $True
$button3.add_Click($button3_OnClick)
$button3.add_MouseClick($handler_button3_MouseClick)
$form1.Controls.Add($button3)
$button_remove.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 472
$System_Drawing_Point.Y = 138
$button_remove.Location = $System_Drawing_Point
$button_remove.Name = "button_remove"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 38
$System_Drawing_Size.Width = 42
$button_remove.Size = $System_Drawing_Size
$button_remove.TabIndex = 8
$button_remove.Text = "<"
$button_remove.UseVisualStyleBackColor = $True
$button_remove.add_Click($button_remove_OnClick)
$button_remove.add_MouseClick($handler_button_remove_MouseClick)
$form1.Controls.Add($button_remove)
$button_add.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 472
$System_Drawing_Point.Y = 42
$button_add.Location = $System_Drawing_Point
$button_add.Name = "button_add"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 34
$System_Drawing_Size.Width = 42
$button_add.Size = $System_Drawing_Size
$button_add.TabIndex = 7
$button_add.Text = ">"
$button_add.UseVisualStyleBackColor = $True
$button_add.add_Click($button_add_OnClick)
$button_add.add_MouseClick($handler_button_add_MouseClick)
$form1.Controls.Add($button_add)
$listBox_results.DataBindings.DefaultDataSourceUpdateMode = 0
$listBox_results.FormattingEnabled = $True
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 543
$System_Drawing_Point.Y = 9
$listBox_results.Location = $System_Drawing_Point
$listBox_results.Name = "listBox_results"
$listBox_results.SelectionMode = 3
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 238
$System_Drawing_Size.Width = 238
$listBox_results.Size = $System_Drawing_Size
$listBox_results.TabIndex = 10
$form1.Controls.Add($listBox_results)
$label_from.BorderStyle = 1
$label_from.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 149
$label_from.Location = $System_Drawing_Point
$label_from.Name = "label_from"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 200
$label_from.Size = $System_Drawing_Size
$label_from.TabIndex = 6
$label_from.Text = $labelfromname
$label_from.TextAlign = 32
$form1.Controls.Add($label_from)
$dateTimePicker2.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 224
$dateTimePicker2.Location = $System_Drawing_Point
$dateTimePicker2.Name = "dateTimePicker2"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 200
$dateTimePicker2.Size = $System_Drawing_Size
$dateTimePicker2.TabIndex = 5
$dateTimePicker2.add_ValueChanged($handler_dateTimePicker2_ValueChanged)
$form1.Controls.Add($dateTimePicker2)
$dateTimePicker1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 175
$dateTimePicker1.Location = $System_Drawing_Point
$dateTimePicker1.MinDate = "2015-09-03"
$dateTimePicker1.Name = "dateTimePicker1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 200
$dateTimePicker1.Size = $System_Drawing_Size
$dateTimePicker1.TabIndex = 4
$dateTimePicker1.add_ValueChanged($handler_dateTimePicker1_ValueChanged)
$form1.Controls.Add($dateTimePicker1)
$label_group.BorderStyle = 1
$label_group.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 237
$System_Drawing_Point.Y = 9
$label_group.Location = $System_Drawing_Point
$label_group.Name = "label_group"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 228
$label_group.Size = $System_Drawing_Size
$label_group.TabIndex = 3
$label_group.Text = $labelgroupname
$label_group.TextAlign = 32
$form1.Controls.Add($label_group)
$label_utilisateur.BorderStyle = 1
$label_utilisateur.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 14
$System_Drawing_Point.Y = 9
$label_utilisateur.Location = $System_Drawing_Point
$label_utilisateur.Name = "label_utilisateur"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 200
$label_utilisateur.Size = $System_Drawing_Size
$label_utilisateur.TabIndex = 2
$label_utilisateur.Text = $labelusername
$label_utilisateur.TextAlign = 32
$form1.Controls.Add($label_utilisateur)
$comboBox1.DropDownStyle = 2
$comboBox1.DataBindings.DefaultDataSourceUpdateMode = 0
$comboBox1.FormattingEnabled = $True
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 13
$System_Drawing_Point.Y = 45
$comboBox1.Location = $System_Drawing_Point
$comboBox1.Name = "comboBox1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 21
$System_Drawing_Size.Width = 201
$comboBox1.Size = $System_Drawing_Size
$comboBox1.TabIndex = 1
$form1.Controls.Add($comboBox1)
$checkedListBox1.CheckOnClick = $True
$checkedListBox1.DataBindings.DefaultDataSourceUpdateMode = 0
$checkedListBox1.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",8,0,3,0)
$checkedListBox1.FormattingEnabled = $True
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 237
$System_Drawing_Point.Y = 59
$checkedListBox1.Location = $System_Drawing_Point
$checkedListBox1.Name = "checkedListBox1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 184
$System_Drawing_Size.Width = 228
$checkedListBox1.Size = $System_Drawing_Size
$checkedListBox1.TabIndex = 6
$form1.Controls.Add($checkedListBox1)
#endregion Generated Form Code
#Save the initial state of the form
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($OnLoadForm_StateCorrection)
$form1.ShowDialog()| Out-Null
$ErrorActionPreference = "Stop"
#Faites correspondre $path avec la même valeur que dans le script d'interface utilisateur
$path = "\\nas\ScriptPS\Workspaces\TemporaryUserToGroup"
$filelist = Get-ChildItem $path
#Les fichiers XML sont générés avec un identifiant numérique. La regex va filtrer selon ce critère
$totreat = $filelist | Where-Object {$_.Name -match "^\p{Nd}.+.xml$"}
#Les fichiers à moitié traités commencent par un A puis un identifiant numérique. La encore, la regex va filtrer.
$resultarrayimports = $filelist | Where-Object {$_.Name -match "^A\p{Nd}.+.xml$"}
$resultarray = New-Object System.Collections.ArrayList
$global:headers = $null
function Update-File
{
param($from = $null,$until = $null)
$result = $null
if ($from -ne $null)
{
$result = $resultarray.IndexOf($from)
if ($result -eq -1)
{
"$(get-date -format yyyyMMdd_HHmmss) : Update from FROM - $($line.$($global:headers[1])) / $($line.$($global:headers[2])) => $($Error[0].Exception.Message)" >> "$path\warning.txt"
throw("No result for FROM in the result array")
}
else
{
$resultarray[$result].$($global:headers[2]+"_checked") = "X"
}
}
elseif ($until -ne $null)
{
$result = $resultarray.IndexOf($until)
if ($result -eq -1)
{
"$(get-date -format yyyyMMdd_HHmmss) : Update from UNTIL - $($line.$($global:headers[1])) / $($line.$($global:headers[2])) => $($Error[0].Exception.Message)" >> "$path\warning.txt"
throw("No result for UNTIL in the result array")
}
else
{
$resultarray[$result].$($global:headers[3]+"_checked") = "X"
}
}
else
{
"$(get-date -format yyyyMMdd_HHmmss) : A Null value came to the function => $($Error[0].Exception.Message)" >> "$path\warning.txt"
throw("Null Value from function")
}
}
#Récupération des fichiers et ajout des colonnes de check date
foreach ($file in $totreat)
{
try
{
$array = Import-Clixml $file.FullName
}
catch
{
"$(get-date -format yyyyMMdd_HHmmss) : $($file.FullName) => $($Error[0].Exception.Message)" >> "$path\error.txt"
throw("Error while importing")
}
$global:headers = $array[0].psobject.Properties.name
$array | Add-Member -MemberType NoteProperty -Name $($global:headers[2]+"_checked") -Value $null
$array | Add-Member -MemberType NoteProperty -Name $($global:headers[3]+"_checked") -Value $null
$array | Add-Member -MemberType NoteProperty -Name "Original_file" -Value $file.Name
foreach ($entry in $array)
{
$resultarray.Add($entry) | Out-Null
}
}
#Récupère les headers si aucun fichier créé depuis la GUI n'existe.
if ($global:headers -eq $null)
{
#Tente depuis des fichiers déja importés
try
{
$array = Import-Clixml ($filelist | Where-Object {$_.Name -like "IMPORTED_*"} | Select-Object -First 1).fullname
$Global:headers = $array[0].psobject.Properties.name
}
catch
{
#Si rien, tente depuis un fichier Axxxxx.xml issu d'un $resultarray précedent
try
{
$array = Import-Clixml $($resultarrayimports | Select-Object -First 1).FullName
$global:headers = $array[0].psobject.Properties.name
}
catch
{
"$(get-date -format yyyyMMdd_HHmmss) : No file to import" >> "$path\warning.txt"
throw("Nothing to import!")
}
}
}
#Rajoute chaque enregistrement déja exporté auparavant
if ($resultarrayimports -ne $null)
{
$import = Import-Clixml $resultarrayimports.FullName
foreach ($result in $import)
{
$resultarray.Add($result)
}
foreach ($result in $resultarrayimports)
{
Move-Item $result.FullName (join-path $path $("IMPORTED_"+ $($result.Name)))
}
}
#Renomme chaque fichier totreat, considéré comme intégré, pour ne plus être pris en compte au prochain passage du script
foreach ($file in $totreat)
{
$newname = "IMPORTED_" + $file.Name
try
{
Move-Item $file.FullName (Join-Path $path $newname) -Force
}
catch
{
"$(get-date -format yyyyMMdd_HHmmss) : $($file.FullName) / $newname => $($Error[0].Exception.Message)" >> "$path\error.txt"
throw("Error while moving item")
}
}
#Checke de chaque entrée dans resultarray
$date = get-date
foreach ($line in $resultarray)
{
$line
if ((Get-Date $($line.$($global:headers[2]))).date -le $date.Date -and $line.$($global:headers[2]+"_checked") -eq $null)
{
try
{
Add-ADGroupMember $line.$($global:headers[1]) $line.$($global:headers[0])
Write-output "Adding $($line.$($global:headers[0])) to $($line.$($global:headers[1])) / $($line.$($global:headers[2])) to $($line.$($global:headers[3]))"
}
catch [Microsoft.ActiveDirectory.Management.ADException]
{
"$(get-date -format yyyyMMdd_HHmmss) : $($line.$($global:headers[1])) / $($line.$($global:headers[0])) => $($Error[0].Exception.Message)" >> "$path\warning.txt"
}
catch
{
"$(get-date -format yyyyMMdd_HHmmss) : $($line.$($global:headers[1])) / $($line.$($global:headers[0])) => $($Error[0].Exception.Message)" >> "$path\error.txt"
throw("Erreur!")
}
Update-File -from $line
}
if ((Get-Date $($line.$($global:headers[3]))).date -lt $date.Date -and $line.$($global:headers[3]+"_checked") -eq $null)
{
try
{
Write-output "Removing $($line.$($global:headers[0])) from $($line.$($global:headers[1])) / $($line.$($global:headers[2])) to $($line.$($global:headers[3]))"
Remove-ADGroupMember $line.$($global:headers[1]) $line.$($global:headers[0]) -Confirm:$false
}
catch [Microsoft.ActiveDirectory.Management.ADException]
{
"Account not member of the group "
"$(get-date -format yyyyMMdd_HHmmss) : $($line.$($global:headers[1])) / $($line.$($global:headers[0])) => $($Error[0].Exception.Message)" >> "$path\warning.txt"
}
catch
{
"$(get-date -format yyyyMMdd_HHmmss) : $($line.$($global:headers[1])) / $($line.$($global:headers[0])) => $($Error[0].Exception.Message)" >> "$path\error.txt"
throw("Erreur!")
}
Update-File -until $line
}
}
#Clean des entrées
$indexarray = @()
$index = 0
foreach ($line in $resultarray)
{
if ($line.$($global:headers[2]+"_checked") -eq "X" -and $line.$($global:headers[3]+"_checked") -eq "X")
{
$indexarray += $index
}
$index++
}
$indexarray = $indexarray | Sort-Object -Descending
foreach ($entry in $indexarray)
{
$resultarray.RemoveAt($entry)
}
$rafile = "A"+(Get-Date).Ticks+".xml"
if ($resultarray.Count -gt 0)
{
$resultarray | Export-Clixml (Join-Path $path $rafile)
}
Edit du 14/09/2015 : Visiblement mon travail a bien plu, puisque sur le forum communautaire de Spiceworks, mon travail a été promu par la communauté, et me voici en première page du site et en toute première position qui plus est! Joie!