CM: Еще раз о членстве локальных групп

Давным-давно я (да и не только я) уже писал о том, как можно получить отчет по членам локальных групп. Сегодня, поковырявшись с WMI и оглядываясь назад, решил, что код выглядит достаточно некрасиво, да и сам по себе класс имеет некоторые недостатки. Так, например, если членом локальной группы будет локальный и доменный пользователь с одним и тем же именем, то объект создастся лишь для одной записи. В общем-то сам по себе скрипт поменялся не сильно, а вот класс Win32_LocalGroupMember, если вы уже его использовали, придется пересоздать, т.к. теперь ключевыми свойствами является SID группы и SID учетной записи, что даст абсолютную уникальность каждому объекту в WMI. Также по данному классу теперь можно узнать, является ли пользователь локальным или доменным (MemberLocalAccount), а также SID данного пользователя (MemberSID).

Собственно, сам скрипт:

Set oWMI = GetObject("winmgmts:root\cimv2")
iCimtypeString = 8
iCimtypeBoolean = 11

sClassName = "Win32_LocalGroupMember"
sLocalGroupQuery = "SELECT Domain, Name, SID FROM Win32_Group WHERE LocalAccount=TRUE"
sComputerSystemQuery = "SELECT DomainRole FROM Win32_ComputerSystem"

For Each oSubclass in oWMI.SubclassesOf()
    If oSubclass.Path_.Class = sClassName then oWMI.Get(sClassName).Delete_
Next

Set oClass = oWMI.Get()
oClass.Path_.Class = sClassName
Call oClass.Properties_.add("MemberName", iCimtypeString)
Call oClass.Properties_.add("MemberDomain", iCimtypeString)
Call oClass.Properties_.add("MemberType", iCimtypeString)
Call oClass.Properties_.add("MemberLocalAccount", iCimtypeBoolean)
Call oClass.Properties_.add("MemberSID", iCimtypeString)
Call oClass.Properties_.add("GroupName", iCimtypeString)
Call oClass.Properties_.add("GroupDomain", iCimtypeString)
Call oClass.Properties_.add("GroupSID", iCimtypeString)
Call oClass.Properties_("GroupSID").Qualifiers_.add("key", True)
Call oClass.Properties_("MemberSID").Qualifiers_.add("key", True)
Call oClass.Put_()

Set oClass = oWMI.Get(sClassName).SpawnInstance_

For Each oGroup in oWMI.ExecQuery(sLocalGroupQuery)
	sAssociatorsQuery = "ASSOCIATORS OF {Win32_Group.Domain='"&oGroup.Domain&"',Name='"&oGroup.Name&"'} WHERE Role=GroupComponent"
	For Each oAccount in oWMI.ExecQuery(sAssociatorsQuery)
		oClass.MemberName = oAccount.Name
		oClass.MemberDomain = oAccount.Domain
		oClass.MemberSID = oAccount.SID
		oClass.MemberType = Replace((oAccount.Path_.Class), "Win32_", "")
		oClass.MemberLocalAccount = oAccount.LocalAccount
		oClass.GroupName = oGroup.Name
		oClass.GroupDomain = oGroup.Domain
		oClass.GroupSID = oGroup.SID
		Call oClass.Put_()
	Next
Next

И сам MOF:

//**************************************************************************
//* Class: Win32_LocalGroupMember
//**************************************************************************
 
[ SMS_Report     (TRUE),
  SMS_Group_Name ("Local Group Member"),
  SMS_Class_ID   ("CUSTOM|LocalGroupMember|1.0") ]
class Win32_LocalGroupMember : SMS_Class_Template
{
    [SMS_Report (TRUE)      ] string MemberName;
    [SMS_Report (TRUE)      ] string MemberDomain;
    [SMS_Report (TRUE), key ] string MemberSID;
    [SMS_Report (TRUE)      ] string MemberType;
    [SMS_Report (TRUE)      ] boolean MemberLocalAccount;
    [SMS_Report (TRUE)      ] string GroupName;
    [SMS_Report (TRUE)      ] string GroupDomain;
    [SMS_Report (TRUE), key ] string GroupSID;
};

О том, как опубликовать и использовать в отчетах данный пример можно прочитать в предыдущей статье о членстве групп, все имена свойств класса остались прежними.
Во вложении к статье можно скачать сам скрипт и MOF файл. Не забудьте поменять расширение на .zip.

Реклама

CM: Visio Stensils для System Center 2012 Configuration Manager

Jean-Sébastien DUCHÊNE опубликовал, на мой взгляд, неплохие шаблоны Visio для System Center 2012 Configuration Manager.

ConfigMgr 2012 Stensils

Скачать можно по ссылке https://skydrive.live.com/?cid=5025055EB72B5CF8&id=5025055EB72B5CF8%21107

RS: Отчет по членству локальных групп

Скорее всего многим поступала задача от руководства — определить пользователей, которые входят в группу локальных администраторов и многие решали этот вопрос с помощью скриптов, которые есть в интернете. Но все скрипты, которые я видел, хороши до тех пор, пока не сталкиваешься с разноязычными операционными системами в одной компании. В таких случаях группа администраторов может называться «Администраторы», «Administrators», где-то еще как-то, а кому-то вообще нужен отчет по пользователям и группам, которые входят не в группу локальных администраторов, а в группу пользователей удаленного рабочего стола. В итоге я решил написать скрипт, взяв за основу скрипт Sherry Kissinger. Этот скрипт будет создавать собственный класс — Win32_LocalGroupMember. Данный класс обновляется с помощью адвертайзмента и распространяется на коллекцию «All Systems» (либо собственную), либо через Desired Configuration Management.

' Set variables

Set oWMI = GetObject("winmgmts:root\cimv2")
cDQT = Chr(34)
cSQT = Chr(39)
iCimtypeString = 8
sClassName = "Win32_LocalGroupMember"

' Exit script if computer is a Domain Controller

For Each oComputer in oWMI.ExecQuery("Select DomainRole from Win32_ComputerSystem")
	if (oComputer.DomainRole >= 4) then Wscript.Quit
Next

' Clear class if exists

For Each oSubclass in oWMI.SubclassesOf()
	if oSubclass.Path_.Class = sClassName then oWMI.Get(sClassName).Delete_
Next

' Create class

Set oClass = oWMI.Get()
oClass.Path_.Class = sClassName
oClass.Properties_.add "MemberName" , iCimtypeString
oClass.Properties_.add "MemberDomain" , iCimtypeString
oClass.Properties_.add "MemberType" , iCimtypeString
oClass.Properties_.add "GroupName" , iCimtypeString
oClass.Properties_.add "GroupSID" , iCimtypeString
oClass.Properties_("GroupName").Qualifiers_.add "key" , True
oClass.Properties_("MemberName").Qualifiers_.add "key" , True
oClass.Put_

' Return data to class

Set oClass = oWMI.Get(sClassName).SpawnInstance_
For Each oGroup in oWMI.ExecQuery("Select * From Win32_Group Where LocalAccount = 1")
	For Each oGroupUser in oWMI.ExecQuery("Select PartComponent From Win32_GroupUser Where GroupComponent = "_
	&cSQT&"\\\\"&oGroup.Domain&"\\root\\cimv2:Win32_Group.Domain="_
	&cDQT&oGroup.Domain&cDQT&",Name="&cDQT&oGroup.Name&cDQT&cSQT)
		aSplit = split(oGroupUser.PartComponent,cDQT)
		Select Case lcase(split(aSplit(0),":")(1))
			Case "win32_systemaccount.domain="
				oClass.MemberType = "SystemAccount"
			Case "win32_useraccount.domain="
				oClass.MemberType = "UserAccount"
			Case "win32_group.domain="
				oClass.MemberType = "Group"
			Case Else
				oClass.MemberType = "Unknown"
		End Select
		oClass.MemberName = aSplit(3)
		oClass.MemberDomain = aSplit(1)
		oClass.GroupName = oGroup.Name
		oClass.GroupSID = oGroup.SID
		oClass.Put_
	Next
Next

Далее нам потребуется изменить файл sms_def.mof и добавить в него следующие строки:

//**************************************************************************
//* Class: Win32_LocalGroupMember
//**************************************************************************

[ SMS_Report     (TRUE),
  SMS_Group_Name ("Local Group Member"),
  SMS_Class_ID   ("CUSTOM|LocalGroupMember|1.0") ]
class Win32_LocalGroupMember : SMS_Class_Template
{
	[SMS_Report (TRUE), key ] string MemberName;
	[SMS_Report (TRUE)      ] string MemberDomain;
	[SMS_Report (TRUE)      ] string MemberType;
	[SMS_Report (TRUE), key ] string GroupName;
	[SMS_Report (TRUE)      ] string GroupSID;
};

Следующим этапом требуется запустить данный скрипт на клиентах, причем делать это следует регулярно. Желательно скрипт запускать с той же частотой, что и аппаратная инвентаризация. Т.е. если у вас инвентаризация проходит раз в три дня, то и скрипт запускать следует раз в три дня. После этого можно уже построить отчет по группам, указывая не имя, а SID группы. Список SID встроенных групп можно найти здесь — http://support.microsoft.com/kb/243330. Вот самый простой отчет по доменным пользователям, которые входят в группу локальных администраторов:

SELECT SYS.Name0, GroupName0[Local Group Name], MemberDomain0[Member Domain], MemberName0[Member Name], MemberType0[Type]
FROM v_GS_LocalGroupMember0 LGM
INNER JOIN v_R_System SYS on SYS.ResourceID = LGM.ResourceID
WHERE LGM.GroupSID0 = 'S-1-5-32-544' and LGM.MemberDomain0 != SYS.Name0 and LGM.MemberType0 = 'UserAccount'
ORDER by SYS.Name0

UPDATE 27.06.2014: В ConfigMgr 2012 R2 создается таблица в виде v_GS_CUSTOM_LocalGroupMember0, соответственно запрос будет выглядеть так:

SELECT SYS.Name0, GroupName0[Local Group Name], MemberDomain0[Member Domain], MemberName0[Member Name], MemberType0[Type]
FROM v_GS_CUSTOM_LocalGroupMember0 LGM
INNER JOIN v_R_System SYS on SYS.ResourceID = LGM.ResourceID
WHERE LGM.GroupSID0 = 'S-1-5-32-544' and LGM.MemberDomain0 != SYS.Name0 and LGM.MemberType0 = 'UserAccount'
ORDER by SYS.Name0