none
listar los grupos y miebros de los grupos de AD RRS feed

  • Pregunta

  • Hola a todos,

    quiero sacar un listado de los grupos y de los miembros de los grupos desde power Shell.

    New-variable -Name ArrayGrupos -Value @() -Force
    $ArrayGrupos= Get-ADGroup -Filter {name -like "1*"} | select-Object name
    #$ArrayGrupos
    $posicion=$ArrayGrupos.Length
    Write-Host "Número de miembros del array:" $posicion
    Write-Host
    Write-Host "Todos los elementos del array:"
    $ArrayGrupos
    Write-Host "Elemento 3 del array:"
    $ArrayGrupos[3]
    Write-Host
    Get-ADGroupMember $ArrayGrupos[3] -Recursive | Select-Object name
    For($i = 0;$i -lt $ArrayGrupos.Length;$i++){Get-ADGroupMember ""$ArrayGrupos""[$i]"" -Recursive | Select-Object name}
    
    Esta es la salida que tengo en pantalla:
    
    New-variable -Name ArrayGrupos -Value @() -Force
    $ArrayGrupos= Get-ADGroup -Filter {name -like "1*"} | select-Object name
    #$ArrayGrupos
    $posicion=$ArrayGrupos.Length
    Write-Host "Número de miembros del array:" $posicion
    Write-Host
    Write-Host "Todos los elementos del array:"
    $ArrayGrupos
    Write-Host "Elemento 3 del array:"
    $ArrayGrupos[3]
    Write-Host
    Get-ADGroupMember $ArrayGrupos[3] -Recursive | Select-Object name
    For($i = 0;$i -lt $ArrayGrupos.Length;$i++){Get-ADGroupMember ""$ArrayGrupos""[$i]"" -Recursive | Select-Object name}
    
    #$ArrayGrupos para probar que cargo el contenido
    # Prueba que no va foreach(For($i = 0;$i -lt $ArrayGrupos.Length;$i++)$i) In $ArrayGrupos) {Get-ADGroupMember '$ArrayGrupos' -recursive | Select-Object name}
    
    #Prueba For($i = 0;$i -lt $ArrayGrupos.Length;$i++){$ArrayGrupos[$i]}(Get-ADGroupMember $ArrayGrupos -recursive | Select-Object name)
    
    Número de miembros del array: 5
    
    Todos los elementos del array:
    
    Elemento 3 del array:
    
    name                               
    ----                               
    140916 - Grupo1 RW
    150821 - Grupo2 RW             
    151145 - Grupo3 RW               
    151544 - Grupo4 RW            
    151672 - Grupo5 RW 
    151544 - Grupo4 RW            
    Get-ADGroupMember : No se puede enlazar el parámetro 'Identity'. No se puede crear el objeto de tipo "Microsoft.ActiveDirectory.Management.ADGroup". El adaptador no puede establecer el valor de la propiedad "name".
    En línea: 41 Carácter: 19
    + Get-ADGroupMember $ArrayGrupos[3] -Recursive | Select-Object name
    +                   ~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [Get-ADGroupMember], ParameterBindingException
        + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
     
    Get-ADGroupMember : No se puede validar el argumento del parámetro 'Identity'. La propiedad Identity en el argumento es nula o está vacía.
    En línea: 42 Carácter: 63
    + ... ($i = 0;$i -lt $ArrayGrupos.Length;$i++){Get-ADGroupMember ""$ArrayGr ...
    +                                                                ~~
        + CategoryInfo          : InvalidData: (:) [Get-ADGroupMember], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
     
    Get-ADGroupMember : No se puede validar el argumento del parámetro 'Identity'. La propiedad Identity en el argumento es nula o está vacía.
    En línea: 42 Carácter: 63
    + ... ($i = 0;$i -lt $ArrayGrupos.Length;$i++){Get-ADGroupMember ""$ArrayGr ...
    +                                                                ~~
        + CategoryInfo          : InvalidData: (:) [Get-ADGroupMember], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
     
    Get-ADGroupMember : No se puede validar el argumento del parámetro 'Identity'. La propiedad Identity en el argumento es nula o está vacía.
    En línea: 42 Carácter: 63
    + ... ($i = 0;$i -lt $ArrayGrupos.Length;$i++){Get-ADGroupMember ""$ArrayGr ...
    +                                                                ~~
        + CategoryInfo          : InvalidData: (:) [Get-ADGroupMember], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
     
    Get-ADGroupMember : No se puede validar el argumento del parámetro 'Identity'. La propiedad Identity en el argumento es nula o está vacía.
    En línea: 42 Carácter: 63
    + ... ($i = 0;$i -lt $ArrayGrupos.Length;$i++){Get-ADGroupMember ""$ArrayGr ...
    +                                                                ~~
        + CategoryInfo          : InvalidData: (:) [Get-ADGroupMember], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
     
    Get-ADGroupMember : No se puede validar el argumento del parámetro 'Identity'. La propiedad Identity en el argumento es nula o está vacía.
    En línea: 42 Carácter: 63
    + ... ($i = 0;$i -lt $ArrayGrupos.Length;$i++){Get-ADGroupMember ""$ArrayGr ...
    +                                                                ~~
        + CategoryInfo          : InvalidData: (:) [Get-ADGroupMember], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
     

    Como se puede ver el array tiene cosas a las que se puede acceder,  pero no sé como hacer que recorra el array con los nombres de los grupos usando estos como variable dentro del comando Get-ADGroupMember y así recorrer todos los grupos y sus miembros.

    Que se os ocurre que hago mal, por donde puedo tirar?

    PD. Para nota sería poder sacar solo los grupos de usuarios que se hayan creado a partir de una fecha, eso sería ya de 10.

    Gracias por toda la ayuda.


    Carlos Del Prado

    jueves, 11 de agosto de 2016 9:41

Respuestas

  • Hola Carlos,

    El error que te da al intentar exportar a CSV es porque estás ejecutando "exporta a fichero.csv" pero sin decirle que es lo que quieres exportar. Te falta poner primero la variable con los datos a exportar:

    $Members | Export-Csv tufichero.csv -NoTypeInformation etc...


    Teniendo mas datos sobre lo que quieres, te he adaptado un poco el script de ayer para generar el CSV de modo que sea sencillo sacar un informe agrupando por grupo:

    #Requires -Module ActiveDirectory
    $Error.Clear();
    Clear-Host;
    #OU donde quieres buscar los grupos. Si quieres el dominio completo quita la parte OU=
    $SearchOU = "OU=TuOU,DC=dominio,DC=com"
    #Fecha para filtrar que los grupos sean igual o mas recientes.
    [datetime]$GroupDate = '2015/12/01'
    $CSVFile = "C:\Temp\Prueba.csv"
    Try
    {
    	$Modules = "ActiveDirectory"
    	ForEach ($Module in $Modules)
    	{
    		If ((Get-Module | ForEach-Object {$_.Name}) -notcontains $Module)
    		{
    			Import-Module $Module
    		}
    	}
    	If (Test-Path $CSVFile)	
    	{
    		Remove-Item $CSVFile
    	}
    	$Groups = Get-ADGroup -Filter {(whenCreated -ge $GroupDate)} -SearchBase $SearchOU -Properties whenCreated 
    	ForEach ($Group in $Groups)
    	{
    		$GroupMembers = $null
    		$Members = Get-ADGroupMember $Group -Recursive
    		ForEach ($User in $Members)
    		{
    			$GroupMembers = New-Object PSCustomObject -Property @{
    				GroupName = $Group.Name
    				GroupDate = (Get-Date $Group.whenCreated -UFormat "%d-%m-%Y")
    				Login = $User.SamAccountName
    				UserName = $User.name
    			}
    			$GroupMembers | Select GroupName, GroupDate, Login, Username | Export-Csv $CSVFile -NoTypeInformation -Append
    		}
    	}
    }
    Catch
    {
    	$Error
    }

    Sobre lo que haces en tu script, yo lo haría de forma un poco diferente, aunque tampoco soy ningún experto en powershell, de modo que a lo mejor no es la mas óptima.

    Debido a que en un rato empiezo vacaciones y tengo que dejar terminado todo mi trabajo no puedo hacerte el script, pero la idea sería:

    $Carpetas_a_revisar = "c:\carpeta1","c:\carpeta2","c:\carpeta3" $CSVFile = "Ruta_para_el_CSV" ForEach ($carpeta in $Carpetas_a_revisar) { #Obtengo los grupos que acceden a la carpeta $Acceso = "Tu_comando_de_obtener_los_ACL" # Mira el módulo Powershell NTFSSecurity, puede ayudarte mucho para mejorar este comando. ForEach ($Grupo in $Acceso) { $Miembros = Get-ADGroupMember $Grupo -Recursive ForEach ($Usuario in $Miembros) { $GroupMembers = New-Object PSCustomObject -Property @{ Carpeta = $Carpeta

    GroupName = $Grupo.Name GroupDate = (Get-Date $Grupo.whenCreated -UFormat "%d-%m-%Y") Login = $Usuario.SamAccountName UserName = $Usuario.name } $GroupMembers | Select Carpeta, GroupName, GroupDate, Login, Username | Export-Csv $CSVFile -NoTypeInformation -Append } } }

    De este modo, en lugar de leer "todos" los grupos de AD, únicamente leo los que corresponden a cada carpeta, y el CSV te incluye para cada carpeta sus grupos con sus miembros. Ten en cuenta que es solo un guión, si lo ejecutas lógicamente no funcionará, es para guiarte.

    Espero que entre el script y este último guión puedas solucionarlo, porque hasta final de mes ya no podré ayudarte.

    Un saludo.

    Diego

    PD. Si te ha servido de ayuda, por favor marcalo como respuesta y vota. Gracias.


    viernes, 12 de agosto de 2016 10:27

Todas las respuestas

  • Hola,

    A ver si esto es lo que necesitas:

    #Requires -Module ActiveDirectory
    $Error.Clear();
    Clear-Host;
    #OU donde quieres buscar los grupos. Si quieres el dominio completo quita la parte OU=
    $SearchOU = "OU=TuOU,DC=dominio,DC=com"
    #Fecha para filtrar que los grupos sean igual o mas recientes.
    [datetime]$GroupDate = '2015/12/01' 
    Try
    {
    	$Modules = "ActiveDirectory"
    	ForEach ($Module in $Modules)
    	{
    		If ((Get-Module | ForEach-Object {$_.Name}) -notcontains $Module)
    		{
    			Import-Module $Module
    		}
    	}
    	
    	$Groups = Get-ADGroup -Filter {(whenCreated -ge $GroupDate)} -SearchBase $SearchOU -Properties whenCreated 
    	ForEach ($Group in $Groups)
    	{
    		#Si no quieres que sea recursivo quita el parámetro -Recursive. Si en lugar del "login" quieres el nombre cambia el SamAccountName por Name
    		$Members = Get-ADGroupMember $Group -Recursive | Select-Object @{Name='Miembros';Expression={$_.SamAccountName}}
    		#Aquí pon lo que quieras hacer con la salida. Export-CSV, etc...
    		Write-Host -ForegroundColor DarkRed $Group.Name "-"$Members.Count" miembros - Creado:" $Group.whenCreated
    		Write-OutPut $Members
    		Write-Host "`n"
    	}
    }
    Catch
    {
    	$Error
    }

    Lleva el filtrado por fecha de creación del grupo que pedías.

    En realidad se puede hacer en una línea, pero te lo pongo así para que sea mas legible y puedas adaptarlo a tus necesidades fácilmente.

    Espero que te sirva.

    Un saludo.

    Diego

    jueves, 11 de agosto de 2016 11:28
  • Hola y un millón de gracias por lo que has hecho.

    pero cuando le digo que me saque todo a un csv e indica:

    cmdlet Export-Csv en la posición 1 de la canalización de comandos
    Proporcione valores para los parámetros siguientes:
    InputObject:

    #Requires -Module ActiveDirectory
    #remove-item -path \\172.17.0.123\e$\GruposyMiembros.txt
    $destino = "\\172.17.0.123\e$\GruposyMiembros.txt"
    $Error.Clear();
    Clear-Host;
    #OU donde quieres buscar los grupos. Si quieres el dominio completo quita la parte OU= que sean necesaria, ahora coge solo los grupos dentro de la OU Grupos
    $SearchOU = "OU=Grupos,OU=Div_Seguridad,DC=ctag-idiada,DC=local"
    #Fecha para filtrar que los grupos sean igual o mas recientes.
    [datetime]$GroupDate = '2016/04/01' 
    Try
    {
    	$Modules = "ActiveDirectory"
    	ForEach ($Module in $Modules)
    	{
    		If ((Get-Module | ForEach-Object {$_.Name}) -notcontains $Module)
    		{
    			Import-Module $Module
    		}
    	}
    	
    	$Groups = Get-ADGroup -Filter {(whenCreated -ge $GroupDate)} -SearchBase $SearchOU -Properties whenCreated 
    	ForEach ($Group in $Groups)
    	{
    		#Si no quieres que sea recursivo quita el parámetro -Recursive. Si en lugar del "login" quieres el nombre cambia el SamAccountName por Name
    		$Members = Get-ADGroupMember $Group -Recursive | Select-Object @{Name='Miembros';Expression={$_.Name}}
            Export-Csv $destino
            Write-Host -ForegroundColor Green  $Group.Name "-"$Members.Count" miembros  - Creado:" $Group.whenCreated 
    		Write-OutPut $Members 
    		Write-Host "`n"        
    	}   
    }
    Catch
    {
    	$Error
    }
    Todo esto viene a que tengo que sacar un informe de quien accede a que carpetas por petición del cliente, un informe que diga; a estas carpetas accede estas personas, pero como el acceso lo hago por grupos necesito los miembros de los grupos.

    Para sacar quien accede hago esto a ver que te parece:

    Tengo varios problemas, primero que no se usar power shell el segundo y por culpa de esto primero, que tengo seguro errores de concepto graves.

    remove-item -path E:\Compartido-CTAG.txt
    remove-item -path E:\Direccion.txt
    remove-item -path E:\Gestion.txt
    remove-item -path E:\Nas.txt
    remove-item -path E:\Proyectos.txt
    Remove-Item -Path E:\InformesACL.zip
    
    $fecha = get-date -uformat "%d-%m-%Y"
    $var1= pwd
    
    
    Get-Childitem -path "e:\Seguridad\Direccion" | Where-Object {$_.PSIsContainer} | Get-ACL| Select-Object Path -ExpandProperty Access | Export-CSV "e:\Direccion.txt" -NoTypeInformation
    #Get-ChildItem e:\Seguridad\direccion | get-acl | format-list Path, owner, group, Accesstostring > e:\Direccion.txt
    Get-ChildItem e:\Direccion.txt | Compress-Archive -DestinationPath e:\InformesACL.zip -CompressionLevel Optimal
    
    Get-Childitem -path "e:\Seguridad\Gestion" | Where-Object {$_.PSIsContainer} | Get-ACL| Select-Object Path -ExpandProperty Access | Export-CSV "e:\Gestion.txt" -NoTypeInformation
    #Get-ChildItem e:\Seguridad\gestion | get-acl | format-list Path, owner, group, Accesstostring > e:\Gestion.txt
    Get-ChildItem e:\Gestion.txt | Compress-Archive -DestinationPath e:\InformesACL.zip -CompressionLevel Optimal -Update
    
    Get-Childitem -path "e:\Seguridad\Proyectos" | Where-Object {$_.PSIsContainer} | Get-ACL| Select-Object Path -ExpandProperty Access | Export-CSV "e:\Proyectos.txt" -NoTypeInformation
    #Get-ChildItem e:\Seguridad\Proyectos | get-acl | format-list Path, owner, group, Accesstostring > e:\Proyectos.txt
    Get-ChildItem e:\Proyectos.txt | Compress-Archive -DestinationPath e:\InformesACL.zip -CompressionLevel Optimal -Update
    
    Get-Childitem -path "e:\ctag" -Recurse | Where-Object {$_.PSIsContainer} | Get-ACL| Select-Object Path -ExpandProperty Access | Export-CSV "e:\Compartido-CTAG.txt" -NoTypeInformation
    #Get-ChildItem e:\ctag -recurse | get-acl | format-list Path, owner, group, Accesstostring > e:\Compartido-CTAG.txt
    Get-ChildItem e:\Compartido-CTAG.txt | Compress-Archive -DestinationPath e:\InformesACL.zip -CompressionLevel Optimal -Update
    
    Get-Childitem -path "e:\Nas" | Where-Object {$_.PSIsContainer} | Get-ACL| Select-Object Path -ExpandProperty Access | Export-CSV "e:\Nas.txt" -NoTypeInformation
    #Get-ChildItem e:\nas | get-acl | format-list Path, owner, group, Accesstostring > e:\Nas.txt
    Get-ChildItem e:\Nas.txt | Compress-Archive -DestinationPath e:\InformesACL.zip -CompressionLevel Optimal -Update
    
    #------------------------------------------------------------------------------------------------------------------------------------
    # Esto envía correo pero pide credenciales al usario.
    #Send-MailMessage -From carlos.fernandez@ctag.com -Subject "Informe ACL´s CTAG-IDIADA" -To carlos.fernandez@ctag.com -Attachments e:\InformesACL.zip -Bcc carlos.fernandez@ctag.com -Body "Se adjunta a este  correo informe trimestral de lista de accesos a carpetas. Para cualquier consulta pongase en contacto con el Administrador del Sistema." -Credential carlos_fernandez -Port 587 -Priority High -SmtpServer smtp.ctag.com
    #------------------------------------------------------------------------------------------------------------------------------------
    
    $EmailTo = "correo@mail.com"
    $EmailFrom = "correoremite@mail.com"
    $Subject = "Informe Acceso a Datos a $fecha" 
    $Body = "A este correo se adjunta informe con la lista de usuarios que acceden a las carpetas marcadas con información sensible" 
    $SMTPServer = "smtp.mail.com" 
    $filenameAndPath = "e:\InformesACL.zip"
    $SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
    $attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
    $SMTPMessage.Attachments.Add($attachment)
    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) 
    $SMTPClient.EnableSsl = $true 
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential("correo@mail.com","password_1"); 
    $SMTPClient.Send($SMTPMessage)

    Muchas gracias por todo.



    Carlos Del Prado

    viernes, 12 de agosto de 2016 7:25
  • Hola Carlos,

    El error que te da al intentar exportar a CSV es porque estás ejecutando "exporta a fichero.csv" pero sin decirle que es lo que quieres exportar. Te falta poner primero la variable con los datos a exportar:

    $Members | Export-Csv tufichero.csv -NoTypeInformation etc...


    Teniendo mas datos sobre lo que quieres, te he adaptado un poco el script de ayer para generar el CSV de modo que sea sencillo sacar un informe agrupando por grupo:

    #Requires -Module ActiveDirectory
    $Error.Clear();
    Clear-Host;
    #OU donde quieres buscar los grupos. Si quieres el dominio completo quita la parte OU=
    $SearchOU = "OU=TuOU,DC=dominio,DC=com"
    #Fecha para filtrar que los grupos sean igual o mas recientes.
    [datetime]$GroupDate = '2015/12/01'
    $CSVFile = "C:\Temp\Prueba.csv"
    Try
    {
    	$Modules = "ActiveDirectory"
    	ForEach ($Module in $Modules)
    	{
    		If ((Get-Module | ForEach-Object {$_.Name}) -notcontains $Module)
    		{
    			Import-Module $Module
    		}
    	}
    	If (Test-Path $CSVFile)	
    	{
    		Remove-Item $CSVFile
    	}
    	$Groups = Get-ADGroup -Filter {(whenCreated -ge $GroupDate)} -SearchBase $SearchOU -Properties whenCreated 
    	ForEach ($Group in $Groups)
    	{
    		$GroupMembers = $null
    		$Members = Get-ADGroupMember $Group -Recursive
    		ForEach ($User in $Members)
    		{
    			$GroupMembers = New-Object PSCustomObject -Property @{
    				GroupName = $Group.Name
    				GroupDate = (Get-Date $Group.whenCreated -UFormat "%d-%m-%Y")
    				Login = $User.SamAccountName
    				UserName = $User.name
    			}
    			$GroupMembers | Select GroupName, GroupDate, Login, Username | Export-Csv $CSVFile -NoTypeInformation -Append
    		}
    	}
    }
    Catch
    {
    	$Error
    }

    Sobre lo que haces en tu script, yo lo haría de forma un poco diferente, aunque tampoco soy ningún experto en powershell, de modo que a lo mejor no es la mas óptima.

    Debido a que en un rato empiezo vacaciones y tengo que dejar terminado todo mi trabajo no puedo hacerte el script, pero la idea sería:

    $Carpetas_a_revisar = "c:\carpeta1","c:\carpeta2","c:\carpeta3" $CSVFile = "Ruta_para_el_CSV" ForEach ($carpeta in $Carpetas_a_revisar) { #Obtengo los grupos que acceden a la carpeta $Acceso = "Tu_comando_de_obtener_los_ACL" # Mira el módulo Powershell NTFSSecurity, puede ayudarte mucho para mejorar este comando. ForEach ($Grupo in $Acceso) { $Miembros = Get-ADGroupMember $Grupo -Recursive ForEach ($Usuario in $Miembros) { $GroupMembers = New-Object PSCustomObject -Property @{ Carpeta = $Carpeta

    GroupName = $Grupo.Name GroupDate = (Get-Date $Grupo.whenCreated -UFormat "%d-%m-%Y") Login = $Usuario.SamAccountName UserName = $Usuario.name } $GroupMembers | Select Carpeta, GroupName, GroupDate, Login, Username | Export-Csv $CSVFile -NoTypeInformation -Append } } }

    De este modo, en lugar de leer "todos" los grupos de AD, únicamente leo los que corresponden a cada carpeta, y el CSV te incluye para cada carpeta sus grupos con sus miembros. Ten en cuenta que es solo un guión, si lo ejecutas lógicamente no funcionará, es para guiarte.

    Espero que entre el script y este último guión puedas solucionarlo, porque hasta final de mes ya no podré ayudarte.

    Un saludo.

    Diego

    PD. Si te ha servido de ayuda, por favor marcalo como respuesta y vota. Gracias.


    viernes, 12 de agosto de 2016 10:27
  • Mil gracias por todo y muy bunas vacaciones.

    Carlos Del Prado

    viernes, 12 de agosto de 2016 10:36