Mar 18 2010

Réduire la taille de votre ntds.dit

Nous allons voir dans ce post comment effectuer un nettoyage de printemps sur votre base de données AD: Le fichier ntds.dit.
Dans un premier temps il vous faudra repérer les objets inutiles dans votre domaine, suite à ce premier audit, si peu d’objets sont détectés comme inutiles, n’espérez pas gagner beaucoup d’espace. Pour information un objet utilisateur prend une taille minimale de 4ko dans votre base, après tout dépend du nombre d’attributs édités. Voir cet article pour plus d’informations.

Nous allons via un script repérer les objets utilisateurs et ordinateurs inutiles. Ce script ne fonctionne que si le niveau fonctionnel minimal de votre domaine est Windows 2003 car l’attribut utilisé pour repérer les vieux objets utilisateurs est le LastLogonTimeStamp, attribut répliqué sur tous vos DCs, contrairement à LastLogon. Si cet attribut a une valeur vide alors l’utilisateur ne s’est jamais logué, sinon nous pouvons obtenir la dernière date d’accès au domaine, via l’algorithme utilisé dans le script. Pour les comptes ordinateurs nous nous basons sur l’attribut PwdLastSet qui correspond à la date de dernier renouvellement de mot de passe machine. Pour plus d’informations concernant l’identification des objets ordinateurs et utilisateurs non utilisés vous pouvez lire cet article.
Voici le script utilisé pour repérer les comptes ordinateurs et utilisateurs non utilisés:

 
On Error Resume Next
 
'Input domain's distinguishedname
DomainDN = "dc=ldap389,dc=info"
 
Const ForAppending = 8
Const ADS_SCOPE_SUBTREE = 2
 
'We search for objects stale since 6 months
dtmDateValue = DateAdd("m", -6, now)
 
Set objShell = CreateObject("Wscript.Shell")
lngBiasKey = objShell.RegRead("HKLMSystemCurrentControlSetControl" _
    & "TimeZoneInformationActiveTimeBias")
If (UCase(TypeName(lngBiasKey)) = "LONG") Then
    lngBias = lngBiasKey
ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then
    lngBias = 0
    For k = 0 To UBound(lngBiasKey)
        lngBias = lngBias + (lngBiasKey(k) * 256^k)
    Next
End If
 
' Convert datetime value to UTC.
dtmAdjusted = DateAdd("n", lngBias, dtmDateValue)
 
' Find number of seconds since 1/1/1601.
lngSeconds = DateDiff("s", #1/1/1601#, dtmAdjusted)
 
' Convert the number of seconds to a string
' and convert to 100-nanosecond intervals.
str64Bit = CStr(lngSeconds) & "0000000"
 
Set fso = CreateObject("Scripting.FileSystemObject")
 
CibleFileOU = "Resultsusers.csv"
CibleFileOU2 = "Resultscpu.csv"
 
Set df3 = fso.OpenTextFile(CibleFileOU,ForAppending,True)
Set df4 = fso.OpenTextFile(CibleFileOU2,ForAppending,True)
 
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
 
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
 
objCommand.CommandText =_
    "SELECT DistinguishedName,sAMAccountName,lastLogonTimestamp FROM 'LDAP://"&DomainDN&"' WHERE objectCategory='user' AND lastLogonTimestamp < '"&str64Bit&"'"
 
Set objRecordSet = objCommand.Execute
 
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
 
disting = objRecordSet.Fields("DistinguishedName").Value
SAM = objRecordSet.Fields("sAMAccountName").Value
Set StrFlagMCP = objRecordSet.Fields("lastLogonTimestamp").Value
 
           intLastLogonTime0 = StrFlagMCP.HighPart * (2^32) + StrFlagMCP.LowPart
           intLastLogonTime0 = intLastLogonTime0 / (60 * 10000000)
           intLastLogonTime0 = intLastLogonTime0 / 1440
           'Convert lastlogontimestamp in date format
           StrFlagPwd = intLastLogonTime0 + #1/1/1601#
 
df3.writeline(SAM&";"&StrFlagPwd&";"&disting)
 
objRecordSet.MoveNext
Loop
 
objCommand.CommandText =_
    "SELECT DistinguishedName,sAMAccountName,lastLogonTimestamp,WhenCreated FROM 'LDAP://"&DomainDN&"' WHERE objectCategory='user' AND NOT lastLogonTimestamp = '*'"
 
Set objRecordSet2 = objCommand.Execute
 
objRecordSet2.MoveFirst
Do Until objRecordSet2.EOF
 
disting = objRecordSet2.Fields("DistinguishedName").Value
SAM = objRecordSet2.Fields("sAMAccountName").Value
LastLOG = objRecordSet2.Fields("lastLogonTimestamp").Value
Whencreate = objRecordSet2.Fields("WhenCreated").Value
 
df3.writeline(SAM&";NEVER LOGGED;"&disting&";"&Whencreate)
 
objRecordSet2.MoveNext
Loop
 
objCommand.CommandText =_
    "SELECT DistinguishedName,sAMAccountName,lastLogonTimestamp FROM 'LDAP://"&DomainDN&"' WHERE objectCategory='computer' AND PwdLastSet < '"&str64Bit&"'"  
 
Set objRecordSet3 = objCommand.Execute
 
objRecordSet3.MoveFirst
Do Until objRecordSet3.EOF
 
disting = objRecordSet3.Fields("DistinguishedName").Value
SAM = objRecordSet3.Fields("sAMAccountName").Value
 
set StrFlagMCP = objRecordSet3.Fields("lastLogonTimestamp").Value
 
           intLastLogonTime0 = StrFlagMCP.HighPart * (2^32) + StrFlagMCP.LowPart
           intLastLogonTime0 = intLastLogonTime0 / (60 * 10000000)
           intLastLogonTime0 = intLastLogonTime0 / 1440
           StrFlagPwd = intLastLogonTime0 + #1/1/1601#
 
df4.writeline(SAM&";"&StrFlagPwd&";"&disting)
 
objRecordSet3.MoveNext
Loop
 
df3.close
df4.close
 
msgbox "done!

Pour télécharger le vbs c’est ici:

Changer la valeur de DomainDN en indiquant le DistinguishedName de votre domaine, ici on recherche les objets inactifs depuis 6 mois, changer la valeur dtmDateValue si vous désirez utiliser un autre seuil.

Les résultats concernant les comptes utilisateurs sont retournés dans le fichier Resultsusers.csv. Pour les comptes dont le LastLogonTimeStamp est nul, la date de création du compte est indiqué, car un utilisateur dont le compte a été créé il y a quelques jours peut ne s’être toujours pas logué. Une fois le tri fait vous pouvez désactiver les comptes avant de les supprimer, si il n’y a pas de retour de la part de votre hotline d’ici quelques semaines alors vous pourrez les supprimer.

Les résultats concernant les comptes ordinateurs sont retournés dans le fichier Resultscpu.csv , attention certains objets ordinateurs de votre AD dont l’OS n’est pas Windows (serveurs CIFS, OS X…) ainsi que les objets Microsoft Cluster Server Virtual Server peuvent ne pas mettre à jour leur attribut PwdLastSet, il faudra les exclure de votre liste.

Nous allons maintenant nous intéresser aux objets de stratégie de groupe inutiles dans votre domaine. Pour cela il vous suffit d’utiliser les scripts fournis avec la GPMC qui se trouvent dans %programfiles%gpmcscripts. Nous allons simplement lister les GPOs désactivées et non liées avec les scripts FindDisabledGPOs.wsf et FindUnlinkedGPOs.wsf. Si il s’avère que vous ne vous servez plus de ces GPOs vous pouvez les supprimer.

Bien maintenant vous avez supprimé tous ces objets et la taille votre ntds.dit n’a pas bougé et cela pour deux raisons:

Tout d’abord vos objets effacés sont tombstonés, ils ne sont pas encore supprimés del’AD et cela pour une période de 60 ou 180 jours (paramétrage par défaut), c’est le TombstoneLifeTime, ceci de façon à être réanimés facilement en cas de suppression accidentelle, une partie des attributs sont effacés mais pas tous. Pour plus d’informations sur le détail des attributs sauvegardés voir cet article. Par ailleurs pour les réanimation d’objets du Tombstone je vous conseille ADRestore.NET qui est la version graphique de ADrestore. Si vous avez activé la corbeille sous 2008, ces outils ne vous sont pas utiles.

Si vous etes une personne pressée vous pouvez réduire ce TombstoneLifeTime avec adsiedit.msc en changeant la valeur (exprimée en jours) de l’attribut tombstonelifetime dans la partition de configuration cn=directory service,cn=windows nt,cn=services,cn=configuration,dc=<forestDN>. Attention cette manipulation peut s’avérer dangereuse, le TombstoneLifeTime ne doit jamais être inférieur au délai de réplication d’un objet au sein de toute votre forêt. Une fois tous les objets réellement supprimés du Tombstone n’oubliez pas de remettre la valeur par défaut à votre attribut tombstonelifetime. Par ailleurs ci une suppression accidentelle a lieu pendant que vous avez réduit la valeur de cet attribut vous riquez de devoir restaurer les comptes avec un backup. Ce paragraphe est à titre informatif, ne pas utiliser cette méthode si vous considérez que c’est trop risqué.

La deuxième raison est qu’une fois tous les objets supprimés du Tombstone il faut défragmenter le fichier ntds.dit hors ligne. Nous allons avant cela activer un audit afin de voir quel gain de place nous pouvons espérer d’une telle défragmentation. Pour cela activer sur vos DCs le diagnostic de garbage collection, une fois la valeur 6 Garbage Collection de la clef HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesNTDSDiagnostics égale à un nous avons un événement d’ID 164 enregistré dans le journal d’évènements lors de chaque défragmentation en ligne de la base (toutes les 12heures).

Sur l’exemple donné, le gain est de 584Mo si nous effectuons une défragmentation hors ligne. Il s’agit d’un cas extrême, n’espérez pas gagner autant de place sur votre environnement, à moins d’avoir supprimé quelques dizaines de milliers d’objets. Ensuite il ne vous reste plus qu’à suivre la procédure fournie par Microsoft.

Cette procédure prend de 5 à 10 minutes, hors temps de reboot en mode DSRM sous Windows 2003, en 2008 il vous suffit de stopper le service AD. Vous devrez effectuer cette opération sur chacun des DCs car ce gain de place ne se réplique évidemment pas. Ce sont les changements sur les objets qui sont répliqués et non la base elle même.

This post is also available in: Anglais

No Comments

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

*

WordPress Themes

Blossom Icon Set

Software Top Blogs