Saturday, December 01, 2012

Backup - nur für Feiglinge oder auch für GPOs?

Hallo ins Netz ;-)

Um was geht es hier?


Ich will die Sicherung von GPOs und WMI-Filtern per Skript automatisieren.

Sicher macht Ihr auch alle jeden Tag ein Backup Eurer Server... Vermutlich als System State Sicherung, gerne per WBAdmin oder mit ArcServe oder TSM. Aber wie ist das mit den GPOs und WMI-Filtern?

Natürlich werden die dann mit gesichert. Allerdings kommt man an einzelne Objekte dieser Sicherung nur schlecht heran: GPOs liegen im Sysvol, WMI-Filter nur im AD. Über die GPMC kann man beides manuell sichern.

Backup mit der GPMC

GPOs sichern ist noch relativ einfach - da gibt es "Alle sichern...":


Bei WMI-Filtern ist es schon schwieriger - die gehen nur einzeln:


Das ist natürlich ärgerlich, wenn man nicht - wie hier - nur einen einzigen Filter hat, sondern einige Duzend. Und ohnehin gilt: "Manuell ist immer schlecht"...

Deshalb habe ich mich mal wieder mit dem Skripting-Interface der GPMC beschäftigt. Heraus kam ein Skript, das GPOs und WMI-Filter sichert. Es gibt zwar auch Sample Scripts von MS (BackupAllGPOs.wsf), aber die haben einige Nachteile:
  • Keine Sicherungslimits (Anzahl oder Alter)
  • Keine WMI-Filter
  • Keine Events, die wir überwachen können
Das können wir besser, oder? ;-))

GPO-Backup mit GPOBackup.VBS

Nachdem es für meine Belange nichts fertiges gab, musste ein eigenes Skript her. Das Skript habe ich so gebaut, dass es entweder als geplanter Task auf einem DC oder manuell von einem Member aus aufgerufen werden kann. Läuft es auf einem DC, dann verbindet es sich mit genau diesem DC - jeder DC erstellt also eine Sicherung der bei ihm lokal vorhandenen Repliken von GPOs und WMI-Filtern. Das kann wichtig sein bei Replikationsproblemen...

Ruft man es von einem Member auf, geht es zum PDC-Emulator.



Hier der vollständige Aufruf mit allen Parametern:

cscript GPOBackup.VBS [/CreateShare:0] [/BackupDirectory:] [/BackupShare:] [/ForceBackup] [/RetentionMethod:age|count] [/RetentionCount:] [/L:] [/EventLogName:] [/EventSource:]

Keiner der Parameter ist erforderlich, und Gross-/Kleinschreibung ist natürlich egal. Statt Parameter kann man auch das Skript selber bearbeiten und die dort definierten Defaultwerte einfach überschreiben.

Nach dem Aufruf passiert folgendes:
  1. Das Sicherungsverzeichnis %Public%\GPOBackup (oder /BackupDirectory:) wird erstellt und mit ACLs versehen. Die Rechte auf dem Verzeichnis: Vollzugriff für System, Administratoren, Domain Admins und Creator-Owner.
  2. Ist der Computer ein DC und nicht /CreateShare:0, wird das Verzeichnis freigegeben als GPOBackup (oder /BackupShare:). Die Rechte auf der Freigabe: Vollzugriff für Everyone.
  3. Alle GPOs werden gesichert, wenn sie geändert wurden. Mit /ForceBackup auch ohne Änderungen. Jede GPO bekommt unter "GPOBackup\GPOs" ihr eigenes Verzeichnis {GPO-GUID}.
  4. Die Anzahl der vorhandenen Backups pro GPO wird geprüft.
    1. Gibt es mehr als 10 (oder /RetentionCount:) Sicherung, werden die ältesten gelöscht.
    2. Wurde /RetentionMethod:age angegeben, werden alle gelöscht, die älter als 10 Tage (oder /RetentionCount:) sind, gelöscht.
  5. Alle WMI-Filter werden gesichert, wenn sie geändert wurden. Mit /ForceBackup auch ohne Änderungen. Alle Filter landen in "GPOBackup\WMI-Filter". Es gibt nur eine Sicherung pro Filter. Der Filter wird gesichert in {Filter-GUID}.mof.
  6. Für eine einfache Überwachung gibt es eine Handvoll Events im Application Event Log (oder /EventLogName:], Quelle "GPOBackup" (oder /EventSource:):
    •  I  1 - started
    •  I  2 - GPOs unchanged
    • I/W 3 - GPOs backed up (with error)
    • I/W 4 - GPOs backup deleted (with error)
    •  I  5 - WMI filters unchanged
    • I/W 6 - WMI filters backed up (with error)
    • I/W 9 - finished (with errors)
Mit /L kann noch ein Logfile angegeben werden, das den (spärlichen) Bildschirmoutput auch noch in eine Datei schreibt (mit automatischem Size Wrapper bei >100 kB natürlich - wir wollen ja nicht die Platte vollmüllen).

Zwei Tricks sind auch noch dabei:
  1. AD-intern sind GPOs und WMI-Filter nur GUIDs, und die Anzeigenamen müssen nicht eindeutig sein. Ich kann also nicht einfach den Anzeigenamen im Dateisystem der Sicherung verwenden. Also machen wir eine desktop.ini dazu, die jeweils im Explorer statt der GUID den Anzeigenamen darstellt. Das sieht dann für einen WMI-Filter z.B. so aus:
    Dateisystem


    01.12.2012 15:24 326 {76593C02-E9B2-414A-BB9E-A3BF3E51F519}.mof


    Explorer

     
  2. WMI-Filter kann man nicht direkt "sichern", man kann aber deren Eigenschaften auslesen. Daraus wird dann das mof neu zusammengesetzt.
Und wie einsetzen?

Ganz einfach - per GPO natürlich ;-)
  1. Skript auf Netlogon oder sonstwo im Netzwerk kopieren
  2. Per GPP "Dateien" oder per Startskript auf den DC bringen
  3. Geplanten Task einrichten per GPP, Ausführungstrigger nach Wunsch


Hier findet Ihr das Skript als ZIP:

Im Skript findet Ihr einige Kommentare zum "warum, wieso, weshalb".
Fragen, Feedback und Kommentare sind herzlich willkommen!

Und wenn sich jemand fragt "warum VBS und nicht Powershell" - ganz einfach: VBS spreche ich besser, und die Powershell-CMDlets für GPOs haben kein GPOBackup-Interface, wie es das COM-Objekt der GPMC kennt.

Have fun!!!

Links:

GPMC Scripting COM Interface
MOF-Dateieformat

8 comments:

  1. Tolles Skript, Danke :)
    Ich habe noch eine Frage zur Ausführung:
    Wenn man das Skript via Aufgabenplanung startet, erscheint der Windows Scripting Host, in diesem muss man jeden Eintrag (der in das Logfile geschrieben werden sollte) manuell bestätigen.
    Wie kann man diesen manuellen Eingriff umgehen?

    ReplyDelete
    Replies
    1. Da gibts 2 Möglichkeiten:
      a) CScript statt WScript als Standardhost setzen. Dazu in einer Admin-Commandline:
      cscript //h:cscript
      eingeben.
      b) Das VBS nicht in die Kommandozeile setzen, sondern in den Parameter-Eintrag. Als Kommandozeile dann "%systemroot%\system32\cscript.exe" verwenden.

      Delete
    2. Super, ich habe die Variante "b" gewählt, damit klappt es einwandfrei.

      Danke für den schnellen Support :)

      Delete
    3. Gern geschehen... Hab ich überhaupt nicht drangedacht, da wir generell die Verknüpfung von vbs/wsf/js/vbe etc. mit WScript löschen, so daß bei uns IMMER der Interpreter (cscript/wscript) angegeben werden muß ;-))

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. looks great article. is there an english version? :)

    ReplyDelete
    Replies
    1. Unfortunately - no, there's no english version. But in short: Download the zip, copy it to an appropriate folder on your DCs and start it through a scheduled task with the above mentioned command line.

      Delete
  4. Brilliant script, indeed.
    I'll link that on my page if it is OK for you.

    ReplyDelete