web-dev-qa-db-fra.com

De quelles autorisations / droits un utilisateur a-t-il besoin pour avoir un accès WMI sur des machines distantes?

J'écris un service de surveillance qui utilise WMI pour obtenir des informations à partir de machines distantes. Il n'est pas possible d'avoir des droits d'administrateur local sur toutes ces machines pour des raisons politiques.

Est-ce possible? De quelles autorisations/droits mon utilisateur a-t-il besoin pour cela?

34
jpoh

Les éléments suivants fonctionnent sur Windows 2003 R2 SP 2, Windows Server 2012 R2

  1. Ajoutez le ou les utilisateurs en question au groupe tilisateurs de l'Analyseur de performances
  2. Sous Services et applications, ouvrez la boîte de dialogue des propriétés du contrôle WMI (ou exécutez wmimgmt.msc). Dans l'onglet Sécurité, mettez en surbrillance Root/CIMV2, cliquez sur Sécurité; ajoutez tilisateurs de l'Analyseur de performances et activez les options: Enable Account et Remote Enable
  3. Exécutez dcomcnfg. Dans Services de composants> Ordinateurs> Poste de travail, dans l'onglet Sécurité COM de la boîte de dialogue Propriétés, cliquez sur "Modifier les limites" pour les deux Access Permissions et Launch and Activation Permissions. Ajoutez des utilisateurs de l'Analyseur de performances et autorisez l'accès à distance, le lancement à distance et l'activation à distance.
  4. Sélectionnez Windows Management Instrumentation sous Services de composants> Ordinateurs> Poste de travail> DCOM Config et donnez Remote Launch et Remote Activation privilèges pour tilisateurs de l'Analyseur de performances Groupe.

Remarques:

  • En alternative aux étapes 3 et 4, on peut affecter l'utilisateur au groupe tilisateurs COM distribués (Testé sur Windows Server 2012 R2)
  • Si l'utilisateur a besoin d'accéder à tous les espaces de noms, vous pouvez définir les paramètres dans 2. au niveau Root, et récupérer les autorisations des sous-espaces de noms via la fenêtre Advanced dans Security
32
jpoh

Tout ce que j'ai fait sur Windows 8 a été ajouté utilisateur au groupe "Utilisateurs de gestion à distance", et les requêtes WQL distantes ont fonctionné.

4
Bunyk

Par défaut, seul le groupe Administrateurs local dispose d'autorisations distantes sur WMI. Vous devrez personnaliser les autorisations WMI "Remote Enable".

1
ThatGraemeGuy

Vous devrez peut-être également accorder des "autorisations d'accès à distance DCOM" et/ou des "autorisations de lancement et d'activation à distance DCOM" en fonction de ce que vous essayez de faire. Cet article MSDN donne les procédures étape par étape.

1
KevinH

Les éléments suivants ont fonctionné pour moi dans un environnement de domaine 2012 r2, bien que je ne réussisse qu'à le faire par serveur et non par l'ensemble du domaine:

1) Ajouter un utilisateur au groupe d'utilisateurs du journal des performances. 2) Exécutez wmimgmt.msc, cliquez avec le bouton droit sur "Contrôle WMI (LOCAL), accédez à l'onglet Sécurité et accordez à l'utilisateur approprié" Activer le compte "et" Activer à distance "sur l'espace de noms souhaité (habituellement CIMV2).

Si je parviens à le faire pour l'ensemble du domaine, je reviendrai et mettrai à jour.

0
JustAGuy

Sur la base de la réponse choisie, j'ai modifié le script de Microsoft pour définir la sécurité WMI. Mon utilisateur de test était un utilisateur de domaine non administratif qui était membre des "utilisateurs de gestion à distance" sur le système local pour des raisons non liées à ce problème . Après avoir accordé à mon utilisateur les autorisations EnableAccount, RemoteEnable et ExecuteMethods sur l'espace de noms cible, j'ai pu accéder à WMI.

Donc, j'ai pas ajouté mon utilisateur aux tilisateurs de l'Analyseur de performances ou tilisateurs COM distribués local groupes.

Quelques notes concernant le script:

  1. Vous devez spécifier le chemin complet de l'espace de noms. Dans mon cas, l'espace de noms était Root/Microsoft/SqlServer
  2. L'héritage était faux. Parce qu'il n'y a aucun objet feuille que vous ne pouvez pas utiliser $OBJECT_INHERIT_ACE_FLAG
  3. Je me suis débarrassé de la fonction embarquée car elle était trop petite et n'a été utilisée qu'une seule fois.

Le script est ci-dessous. Je l'ai nommé Set-WMINamespaceSsecurity.ps1

Param ([Parameter(Mandatory=$true,Position=0)] [string]$Namespace,
       [Parameter(Mandatory=$true,Position=1)] [ValidateSet("Add","Remove")] [string]$Operation,
       [Parameter(Mandatory=$true,Position=2)] [string] $Account,
       [Parameter(Mandatory=$false,Position=3)] [ValidateSet("EnableAccount","ExecuteMethods","FullWrite","PartialWrite","ProviderWrite","RemoteEnable","ReadSecurity","WriteSecurity")] [string[]] $Permissions=$null,
       [Parameter(Mandatory=$false)] [switch]$AllowInherit,
       [Parameter(Mandatory=$false)] [switch]$Deny,
       [Parameter(Mandatory=$false)] [string]$ComputerName=".",
       [Parameter(Mandatory=$false)] [System.Management.Automation.PSCredential]$Credential=$null)

$OBJECT_INHERIT_ACE_FLAG    = 0x1
$CONTAINER_INHERIT_ACE_FLAG = 0x2
$ACCESS_ALLOWED_ACE_TYPE    = 0x0
$ACCESS_DENIED_ACE_TYPE     = 0x1

$WBEM_ENABLE            = 0x01
$WBEM_METHOD_EXECUTE    = 0x02
$WBEM_FULL_WRITE_REP    = 0x04
$WBEM_PARTIAL_WRITE_REP = 0x08
$WBEM_WRITE_PROVIDER    = 0x10
$WBEM_REMOTE_ACCESS     = 0x20
$WBEM_RIGHT_SUBSCRIBE   = 0x40
$WBEM_RIGHT_PUBLISH     = 0x80
$READ_CONTROL           = 0x20000
$WRITE_DAC              = 0x40000
$WBEM_S_SUBJECT_TO_SDS  = 0x43003

$ErrorActionPreference = "Stop"

$InvokeParams=@{Namespace=$Namespace;Path="__systemsecurity=@";ComputerName=$ComputerName}
if ($PSBoundParameters.ContainsKey("Credential")) { $InvokeParams+= @{Credential=$Credential}}

$output = Invoke-WmiMethod @InvokeParams -Name "GetSecurityDescriptor"
if ($output.ReturnValue -ne 0) { throw "GetSecurityDescriptor failed:  $($output.ReturnValue)" }

$ACL = $output.Descriptor

if ($Account.Contains('\')) {
  $Domain=$Account.Split('\')[0]
  if (($Domain -eq ".") -or ($Domain -eq "BUILTIN")) { $Domain = $ComputerName }
  $AccountName=$Account.Split('\')[1]
}
elseif ($Account.Contains('@')) {
  $Somain=$Account.Split('@')[1].Split('.')[0]
  $AccountName=$Account.Split('@')[0]
}
else {
  $Domain = $ComputerName
  $AccountName = $Account
}

$GetParams = @{Class="Win32_Account" ;Filter="Domain='$Domain' and Name='$AccountName'"}
$Win32Account = Get-WmiObject @GetParams
if ($Win32Account -eq $null) { throw "Account was not found: $Account" }

# Add Operation
if ($Operation -eq "Add") {
  if ($Permissions -eq $null) { throw "Permissions must be specified for an add operation" }

  # Construct AccessMask
  $AccessMask=0
  $WBEM_RIGHTS_FLAGS=$WBEM_ENABLE,$WBEM_METHOD_EXECUTE,$WBEM_FULL_WRITE_REP,$WBEM_PARTIAL_WRITE_REP,$WBEM_WRITE_PROVIDER,$WBEM_REMOTE_ACCESS,$READ_CONTROL,$WRITE_DAC
  $WBEM_RIGHTS_STRINGS="EnableAccount","ExecuteMethods","FullWrite","PartialWrite","ProviderWrite","RemoteEnable","ReadSecurity","WriteSecurity"
  $PermissionTable=@{}
  for ($i=0; $i -lt $WBEM_RIGHTS_FLAGS.Count; $i++) { $PermissionTable.Add($WBEM_RIGHTS_STRINGS[$i].ToLower(), $WBEM_RIGHTS_FLAGS[$i]) }
  foreach ($Permission in $Permissions) { $AccessMask+=$PermissionTable[$Permission.ToLower()] }

  $ACE=(New-Object System.Management.ManagementClass("Win32_Ace")).CreateInstance()
  $ACE.AccessMask=$AccessMask
  # Do not use $OBJECT_INHERIT_ACE_FLAG.  There are no leaf objects here.
  if ($AllowInherit.IsPresent) { $ACE.AceFlags=$CONTAINER_INHERIT_ACE_FLAG }
  else { $ACE.AceFlags=0 }

  $Trustee=(New-Object System.Management.ManagementClass("Win32_Trustee")).CreateInstance()
  $Trustee.SidString = $Win32Account.SID
  $ACE.Trustee=$Trustee

  if ($Deny.IsPresent) { $ACE.AceType = $ACCESS_DENIED_ACE_TYPE } else { $ACE.AceType = $ACCESS_ALLOWED_ACE_TYPE }
  $ACL.DACL+=$ACE
}
#Remove Operation
else {
  if ($Permissions -ne $null) { Write-Warning "Permissions are ignored for a remove operation" }
  [System.Management.ManagementBaseObject[]]$newDACL = @()
  foreach ($ACE in $ACL.DACL) {
    if ($ACE.Trustee.SidString -ne $Win32Account.SID) { $newDACL+=$ACE }
  }
  $ACL.DACL = $newDACL
}

$SetParams=@{Name="SetSecurityDescriptor"; ArgumentList=$ACL}+$InvokeParams

$output = Invoke-WmiMethod @SetParams
if ($output.ReturnValue -ne 0) { throw "SetSecurityDescriptor failed: $($output.ReturnValue)" }