help to create a script that adds a domain security group to the local administrator group
- Hello,
We need to make sure an AD security group is added to the Local Administrators group on all client machines. I know the Domain Admins group is in there by default but our Domain Admin security group is locked down and we can't add members of the IT team to this group.
So I had the idea of a computer startup script deployed via Group Policy. Unfortunately I have zero scripting skills, I realised I can put the "net localgroup administrators mis01 /add" line into a batch file and our AD security group "mis01" would be added to the local administrator group.
This net command works fine on English clients, however we have multiple language OS clients to support and some of these clients have a local administrators group with a different spelling - for example in France the local group is administrateurs. I identified 5 different groups - added the following below to my batch file - again it seems to work - BUT now computers take forever to bootup - sitting there applying startup policies - I'm guessing the clients try to apply each of the 5 net commands and fail / timeout on four, because a certain local group is not found.
Is there a cleaner method to run this script where the client only runs the necessary net command? Our computer accounts are grouped into different OU's BUT that doesn't always mean all French clients are running French OS's so five separate scripts against different OU's is not really possible - I need a blanket script that can cover all computer accounts...
net localgroup administrators mis01 /add
net localgroup administratoren mis01 /add
net localgroup administradores mis01 /add
net localgroup administratorer mis01 /add
net localgroup administrateurs mis01 /add
Regards
Mark
All Replies
You can use Restricted Groups to manage membership in local groups. This is better than startup scripts. Check this link:
http://technet.microsoft.com/en-us/library/cc785631(WS.10).aspx
Otherwise, VBScript code to add a domain group to the local Administrators group would be similar to:
=========
' Bind to the domain group.
Set objDomainGroup = GetObject("WinNT://MyDomain/MyAdm,group")
' Bind to local Administrators group.
Set objNetwork = CreateObject("Wscript.Network")
strComputer = objNetwork.ComputerName
Set LocalAdm = GetObject("WinNT://" & strComputer & "/Administrators,group")
' Check if domain group already a member of local Administrators group.
If (objLocalAdm.IsMember(objDomainGroup.ADsPath) = False) Then
' Add the domain group.
objLocalAdm.Add(objDomainGroup.ADsPath)
End If
=========Since the local Administrators group can be renamed, it would be best to use the well known SID for this group. I believe it is S-1-2-32-544. I have to research how to bind to this object using the SID.
MVP ADSI- Thanks Richard,
Yes ideally we should use the restricted groups to manage this - however with hundreds of clients out there; some are already set as local admins (for various reasons), I'm reluctant to use this as it would kick them out of the local admin group.
RE the VBScript you have posted above - I assume this would still need 5 different scripts because it is looking for either Administrators, OR Administratoren etc. using the SID is a good idea if it is common to all languages...
Mark Yes, the SID values are universal, independent of language or regional settings. They also remain the same if you rename the object.
I sometimes bind to objects by SID value using the LDAP provider. I investigated and this feature does not seem to be available with the WinNT provider. The local SAM account database is not LDAP compliant, so we must use the WinNT provider. However, the WinNT provider does expose the objectSID attribute of local objects, and I have developed some VBScript functions that convert these byte array values into string values. A script can bind to the local computer object and enumerate all local group objects. Then the script can retrieve the objectSID value of each group, convert into a string and compare with the well known SID value "S-1-2-32-544" to find the Administrators group. This doesn't look elegant, but it works. In this case, the code would be as follows:
=========
Option ExplicitDim objNetwork, strComputer, objComputer, objGroup
Dim strHexSID, strDecSID, objDomainGroup
' Bind to the domain group.
Set objDomainGroup = GetObject("WinNT://MyDomain/MyAdm,group")
' Enumerate all local groups.
Set objNetwork = CreateObject("Wscript.Network")
strComputer = objNetwork.ComputerName
Set objComputer = GetObject("WinNT://" & strComputer)
objComputer.Filter = Array("group")
For Each objGroup In objComputer
' Find local Administrators group by well known SID.
strHexSID = OctetToHexStr(objGroup.objectSID)
strDecSID = HexSIDToDec(strHexSID)
If (strDecSID = "S-1-2-32-544") Then
' Check if domain group already a member of local Administrators group.
If (objGroup.IsMember(objDomainGroup.ADsPath) = False) Then
' Add the domain group.
objGroup.Add(objDomainGroup.ADsPath)
End If
Exit For
End If
Next
Wscript.QuitFunction OctetToHexStr(ByVal arrbytOctet)
' Function to convert OctetString (Byte Array) to a hex string.Dim k
OctetToHexStr = ""
For k = 1 To Lenb(arrbytOctet)
OctetToHexStr = OctetToHexStr _
& Right("0" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)
NextEnd Function
Function HexSIDToDec(ByVal strSID)
' Function to convert most hex SID values to decimal format.Dim arrbytSID, lngTemp, j
ReDim arrbytSID(Len(strSID)/2 - 1)
For j = 0 To UBound(arrbytSID)
arrbytSID(j) = CInt("&H" & Mid(strSID, 2*j + 1, 2))
NextIf (UBound(arrbytSID) = 11) Then
HexSIDToDec = "S-" & arrbytSID(0) & "-" _
& arrbytSID(1) & "-" & arrbytSID(8)Exit Function
End IfIf (UBound(arrbytSID) = 15) Then
HexSIDToDec = "S-" & arrbytSID(0) & "-" _
& arrbytSID(1) & "-" & arrbytSID(8)lngTemp = arrbytSID(15)
lngTemp = lngTemp * 256 + arrbytSID(14)
lngTemp = lngTemp * 256 + arrbytSID(13)
lngTemp = lngTemp * 256 + arrbytSID(12)HexSIDToDec = HexSIDToDec & "-" & CStr(lngTemp)
Exit Function
End IfHexSIDToDec = "S-" & arrbytSID(0) & "-" _
& arrbytSID(1) & "-" & arrbytSID(8)lngTemp = arrbytSID(15)
lngTemp = lngTemp * 256 + arrbytSID(14)
lngTemp = lngTemp * 256 + arrbytSID(13)
lngTemp = lngTemp * 256 + arrbytSID(12)HexSIDToDec = HexSIDToDec & "-" & CStr(lngTemp)
lngTemp = arrbytSID(19)
lngTemp = lngTemp * 256 + arrbytSID(18)
lngTemp = lngTemp * 256 + arrbytSID(17)
lngTemp = lngTemp * 256 + arrbytSID(16)HexSIDToDec = HexSIDToDec & "-" & CStr(lngTemp)
lngTemp = arrbytSID(23)
lngTemp = lngTemp * 256 + arrbytSID(22)
lngTemp = lngTemp * 256 + arrbytSID(21)
lngTemp = lngTemp * 256 + arrbytSID(20)HexSIDToDec = HexSIDToDec & "-" & CStr(lngTemp)
If (UBound(arrbytSID) > 23) Then
lngTemp = arrbytSID(25)
lngTemp = lngTemp * 256 + arrbytSID(24)HexSIDToDec = HexSIDToDec & "-" & CStr(lngTemp)
End IfEnd Function
========
Richard Mueller
MVP ADSI

