Si vous avez un parc avec des postes Windows, vous aimerez surement appliquer des GPO un jours ou l’autre en fonction des groupes. Voici comment j’ai réussi à émuler quelque chose de semblable.

J’ai suivi cette procédure premièrement pour monter le DC: http://www.howtoforge.com/openldap-samba-domain-controller-ubuntu7.10

Activer un logon script
Dans smb.conf, assurez vous d’avoir:

[global]
...
logon script = scripts\logon.bat
...
[netlogon]
comment = The domain logon service
path = /home/netlogon
public = no
writeable = no
browsable = no

Logon script

Dans /home/netlogon/scripts/logon.bat

@echo off

echo %time%  > C:\time.txt

REM Yaay! Let's print an ascii art
type \\<THIS_SERVER>\netlogon\scripts\ascii_arts\tux.txt

REM Things are easier in VBS
cscript \\<THIS_SERVER>\netlogon\scripts\logon.vbs
echo %time% >> C:\time.txt

Je me suis fait demander: “Pourquoi VBS?”. La réponse est que c’est la seule façon de travailler avec Microsoft Office sur le sens du monde… malheureusement.

Avec le script suivant, nous pouvons lancer des sous scripts dans l’order désiré (ordre alphabétique). Dans /home/netlogon/scripts/logon.vbs

'
' This script runs every scripts in folder_name sorted by name
'
'On Error Resume Next
Main
Sub Main()
  Dim fso, folder, files, sFolder
  Dim objFile, strScriptCode

  Set fso = CreateObject("Scripting.FileSystemObject")
  Set objShell = Wscript.CreateObject("Wscript.Shell")

  folder_name = "\\<THIS_SERVER>\netlogon\scripts\scripts.d\"

  set fold = fso.getFolder(folder_name)
  fileCount = fold.files.count
  dim fNames()
  redim fNames(fileCount)
  cFcount = 0
  for each file in fold.files
    cFcount = cFcount + 1
    fNames(cFcount) = lcase(file.name)
  next
  for tName = 1 to fileCount
    for nName = (tName + 1) to fileCount
      if strComp(fNames(tName),fNames(nName),0)=1 then
        buffer = fNames(nName)
          fNames(nName) = fNames(tName)
          fNames(tName) = buffer
      end if
    next
  next
  for i = 1 to fileCount
    script_name = folder_name & fNames(i)
    wscript.stdout.writeline script_name

    Set objFile = fso.OpenTextFile(script_name, 1)
    strScriptCode = objFile.ReadAll
    objFile.Close

    Execute strScriptCode
  next
End Sub

Le répertoire /home/netlogon/scripts/scripts.d contient les sous scripts. Un bon truc pour l’ordre alphabétique est de mettre des numéros devant les noms selon l’ordre dans lequel on veut qu’il soit exécuté (merci rc.d).

Émulation des GPO
Les GPO sont en fait des clé de registres appliqués sur une machine. Soit par utilisateur (HKEY_CURRENT_USER) ou pour toutes les machines (HKEY_LOCAL_MACHINE).

Donc pour appliquer les GPO, il suffit de faire un script qui applique des clés de registre. Encore une fois, le trie par ordre alphabétique est utile. Disons /home/netlogon/scripts/scripts.d/0001_update_registry.vbs

'
' This script runs every scripts in folder_name sorted by name
'
On Error Resume Next
update_registry
Sub update_registry()
  Dim fso, folder, files, sFolder

  Set fso = CreateObject("Scripting.FileSystemObject")
  Set objShell = Wscript.CreateObject("Wscript.Shell")

  folder_name = "\\<THIS_SERVER>\netlogon\scripts\registry_keys.d\"

  set fold = fso.getFolder(folder_name)
  fileCount = fold.files.count
  dim fNames()
  redim fNames(fileCount)
  cFcount = 0
  for each file in fold.files
      cFcount = cFcount + 1
      fNames(cFcount) = lcase(file.name)
  next
  for tName = 1 to fileCount
    for nName = (tName + 1) to fileCount
      if strComp(fNames(tName),fNames(nName),0)=1 then
        buffer = fNames(nName)
          fNames(nName) = fNames(tName)
          fNames(tName) = buffer
      end if
    next
  next
  for i = 1 to fileCount
    ' First param is the command to run
    ' Second param is window visibility (0 hidden, 1 visible)
    ' Third param is if we need to wait the return of the command to continue
    ' http://msdn.microsoft.com/en-us/library/d5fk67ky(VS.85).aspx
    objShell.Run "regedit.exe /S " & folder_name & fNames(i), 0, true
  next
End Sub

Pour trouver quelle clé de registre nous devons changer pour appliquer un certain paramètre, il suffit d’utiliser l’outil Process Monitor de Microsoft. Il permet de voir en temps réel quels sont les accèes en lecture et en écriture sur les registres. En “sniffant” et en cliquand sur la “bonne case à cocher” de n’importe quelle application ou outil de configuration Windows, on voit quelle clé se modifie. On peut donc l’exporter avec l’outil regedit et l’appliquer avec notre script. L’avantage de cette technique est que contrairement aux GPO Microsoft il est possible d’appliquer n’importe quel changement sur n’importe quel paramètre de n’importe quelle application.

Voici un exemple qui active la prise de contrôle à distance sur les postes clients. Dans /home/netlogon/scripts/registry_keys.d/ créer un fichier (0050_enable_remote_desktop).

Windows Registry Editor Version 5.00</code>

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server]
"fDenyTSConnections"=dword:00000000

*On note ici que ce n’est pas activate, mais deny… WTF?

Scripts par groupes
Parfois, il est utile de “connecter un lecteur réseau” sur une machine en fonction de son groupe ou d’appliquer tel paramètre sur une application que seul tel groupe pourrait avoir. Voici un script qui fait une requête dans l’arbre LDAP pour trouver tous les groupes de l’utilisateur courant pour ensuite lancer tous les sous scripts de ce groupe (encore avec l’orde alphabétique)

Dans /home/netlogon/scripts/scripts.d créer un nouveau script (0089_group_logon.vbs)

group_logon
Sub group_logon()
  Set objShell = wscript.createObject("wscript.shell")
  Set fso = CreateObject("Scripting.FileSystemObject")
  username =  objShell.ExpandEnvironmentStrings("%USERNAME%")

  sUser = "logon_scripts"
  sPassword = "PASSWORD"
  sDN = "cn=" & sUser & ",dc=example,dc=com"
  sRoot = "LDAP://<LDAP_SERVER>/dc=example,dc=com"

  Dim oDS: Set oDS = GetObject("LDAP:")
  Dim oAuth: Set oAuth = oDS.OpenDSObject(sRoot, sDN, sPassword, &H0200)

  Dim oConn: Set oConn = CreateObject("ADODB.Connection")
  oConn.Provider = "ADSDSOObject"
  oConn.Open "Ads Provider", sDN, sPassword

  dim fNames()

  Dim rs
  Set rs = oConn.Execute("<" & sRoot & ">;(&(objectClass=sambaGroupMapping)(memberUid="&username&"));cn;subtree")

  Do while not rs.EOF
    For Each vValue in RS.Fields(0).value
      folder_name = "\\<THIS_SERVER>\netlogon\scripts\groups\"&vValue&".d\"
      If fso.FolderExists(folder_name) Then
        set fold = fso.getFolder(folder_name)
        fileCount = fold.files.count
        redim fNames(fileCount)
        cFcount = 0
        for each file in fold.files
          cFcount = cFcount + 1
          fNames(cFcount) = lcase(file.name)
        next
        for tName = 1 to fileCount
          for nName = (tName + 1) to fileCount
            if strComp(fNames(tName),fNames(nName),0)=1 then
              buffer = fNames(nName)
                fNames(nName) = fNames(tName)
                fNames(tName) = buffer
            end if
          next
        next
        for i = 1 to fileCount
          script_name = folder_name & fNames(i)
          wscript.stdout.writeline script_name

          Set objFile = fso.OpenTextFile(script_name, 1)
          strScriptCode = objFile.ReadAll
          objFile.Close

          Execute strScriptCode
        next
      End if
    next
  rs.moveNext
  Loop
End Sub

Ensuite on créer les répertoires en fonction des groupes. Si on ne veut pas de logon script pour un groupe, on ne crée pas de répertoire. Aussi simple que ça. Tout ça grâce à la ligne: If fso.FolderExists(folder_name) Then

Exemple de connexion de deux lecteurs réseau (le home et un autre) pour le groupe DouchEbag. Dans /home/netlogon/scripts/groups/DouchEbag.d (Un peu de respect pour la casse. On est sous Linux):

mount_netdrives
Sub mount_netdrives()
  ' Verifiy if drives are mounted, unmount them and remount them.
  Dim objShell, objNet, checkDrive, objUser, CurrentUser, strGroup

  Set objShell = WScript.CreateObject("WScript.Shell")
  Set objNet = WScript.CreateObject("WScript.Network")
  Set checkDrive = objNet.EnumNetworkDrives()

  'Declare static drives letters here
  Dim vecDriveLetter(2)
  vecDriveLetter(0) = "J:"
  vecDriveLetter(1) = "Z:"

  'Declare static drives paths here
  Dim vecRemotePath(2)
  vecRemotePath(0) = "\\<FILE_SERVER>\"&objShell.ExpandEnvironmentStrings("%USERNAME%")
  vecRemotePath(1) = "\\<MAYBE_ANOTHER_SERVER>\<SHARE>"

  'Mount every drive (persistent mode)
  For i = 0 To ubound(vecDriveLetter) - 1
    ' See http://msdn.microsoft.com/en-us/library/8kst88h6(VS.85).aspx
    objNet.MapNetworkDrive vecDriveLetter(i), vecRemotePath(i), true
  Next
End Sub

Il serait aussi possible d’appliquer le script de registres pour les groupes.

Déploiement de logiciels
Je vous conseille fortement WPKG.

Personellement je n’utilise pas leur agent (car il faut le déployer pour déployer…), mais j’utilise un script. Je le lance en dernier pour être certain que l’installation ne nuit pas trop au temps de login.

wpkg_command = "cscript \\<THIS_SERVER>\netlogon\wpkg\wpkg.js /synchronize /quiet /nonotify"
Set objShell = wscript.createObject("wscript.shell")
objShell.Run wpkg_command, 0, FALSE

Il ne resterait qu’à coder un GUI pour atteindre beaucoup de petites entreprises. Personnellement je trouve cette solution assez charmante, mais elle ne fera pas l’unanimité au niveau des sysadmins.