205 lines
7.1 KiB
PowerShell
205 lines
7.1 KiB
PowerShell
#requires -Version 7.0
|
||
<#
|
||
.SYNOPSIS
|
||
Liste les Computer Groups (Management Rights) effectifs par UTILISATEUR et par USER GROUP,
|
||
en affichant les NOMS (pas les mrgroup_*).
|
||
- Auth depuis config.json (TaniumUrl, TaniumApiToken) via CLIXML -> Initialize-TaniumSession
|
||
- Déplie .group.id avec Get-MRGroupsFromGroup et mappe ID->Nom via Get-ManagementRightsGroup (fallback REST)
|
||
#>
|
||
|
||
# =========================
|
||
# Block 1 - Prérequis
|
||
# =========================
|
||
$ErrorActionPreference = 'Stop'
|
||
try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {}
|
||
Import-Module Redden-TanREST -Force
|
||
|
||
# =========================
|
||
# Block 2 - Chargement config & init session
|
||
# =========================
|
||
$configPath = Join-Path $PSScriptRoot 'config.json'
|
||
$TempXml = Join-Path $env:TEMP 'tanium-session-tmp.apicred'
|
||
|
||
if (-not (Test-Path $configPath -PathType Leaf)) {
|
||
throw "Configuration file not found: $configPath (expected: TaniumUrl, TaniumApiToken)"
|
||
}
|
||
|
||
Write-Host "Reading configuration from: $configPath"
|
||
$config = Get-Content -Path $configPath -Raw | ConvertFrom-Json
|
||
$TaniumUrl = $config.TaniumUrl
|
||
$TaniumToken = $config.TaniumApiToken
|
||
|
||
if ([string]::IsNullOrWhiteSpace($TaniumUrl) -or [string]::IsNullOrWhiteSpace($TaniumToken)) {
|
||
throw "Both TaniumUrl and TaniumApiToken must be provided."
|
||
}
|
||
if ($TaniumUrl -match '^https?://') {
|
||
$TaniumUrl = $TaniumUrl -replace '^https?://','' -replace '/+$',''
|
||
Write-Host "Normalized TaniumUrl to host: $TaniumUrl"
|
||
}
|
||
|
||
$ExportObject = @{
|
||
baseURI = $TaniumUrl
|
||
token = ($TaniumToken | ConvertTo-SecureString -AsPlainText -Force)
|
||
}
|
||
$ExportObject | Export-Clixml -Path $TempXml
|
||
|
||
Write-Host "Initializing Tanium session..."
|
||
Initialize-TaniumSession -PathToXML $TempXml
|
||
Write-Host "Tanium session initialized."
|
||
|
||
# =========================
|
||
# Block 3 - Index MR id -> nom (module puis REST fallback)
|
||
# =========================
|
||
$Script:MRIndex = @{}
|
||
try {
|
||
$allMR = Get-ManagementRightsGroup -All
|
||
} catch { $allMR = @() }
|
||
|
||
if (-not $allMR -or $allMR.Count -eq 0) {
|
||
# fallback REST
|
||
$baseUri = $TaniumUrl; if ($baseUri -notmatch '^https?://') { $baseUri = "https://$baseUri" }
|
||
$headers = @{
|
||
'Accept' = 'application/json'
|
||
'Content-Type' = 'application/json'
|
||
'X-Api-Token' = $TaniumToken
|
||
'session' = $TaniumToken
|
||
}
|
||
try {
|
||
$resp = Invoke-RestMethod -Method GET -Uri "$baseUri/api/v2/management_rights_groups?limit=5000" -Headers $headers
|
||
$allMR = @($resp.items ?? $resp.data ?? $resp)
|
||
} catch {
|
||
Write-Warning "Could not fetch Management Rights groups via REST: $($_.Exception.Message)"
|
||
$allMR = @()
|
||
}
|
||
}
|
||
foreach ($g in $allMR) {
|
||
if ($null -ne $g.id) { $Script:MRIndex[[int]$g.id] = [string]$g.name }
|
||
}
|
||
|
||
# =========================
|
||
# Block 4 - Helpers
|
||
# =========================
|
||
function Expand-NamedMRGroups {
|
||
<#
|
||
.SYNOPSIS
|
||
A partir d'un ID de groupe fusionné (.group.id), retourne les Computer Groups *nommés* (id/name).
|
||
Utilise Get-MRGroupsFromGroup puis mappe ID->Nom via $Script:MRIndex et filtre mrgroup_*.
|
||
#>
|
||
param([Parameter(Mandatory)][int]$MergedGroupID)
|
||
|
||
if ($MergedGroupID -lt 0) { return @() }
|
||
|
||
$items = @()
|
||
try { $items = @( Get-MRGroupsFromGroup -ID $MergedGroupID ) } catch { $items = @() }
|
||
|
||
$mapped = @()
|
||
foreach ($i in $items) {
|
||
$id = [int]$i.id
|
||
$name = [string]$i.name
|
||
if (-not $name -or $name -like 'mrgroup_*') { $name = $Script:MRIndex[$id] }
|
||
if ($name) {
|
||
$mapped += [pscustomobject]@{ id = $id; name = $name }
|
||
}
|
||
}
|
||
if ($mapped.Count -gt 0) {
|
||
$mapped = $mapped | Sort-Object id -Unique
|
||
}
|
||
return $mapped
|
||
}
|
||
|
||
function Get-UsersWithComputerGroups {
|
||
<#
|
||
.SYNOPSIS Récupère Users + leurs Computer Groups effectifs (nommés).
|
||
#>
|
||
$users = @()
|
||
try { $users = @(Get-User -All) }
|
||
catch { $users = @(Get-User -Summary) }
|
||
|
||
$rows = @()
|
||
foreach ($u in $users) {
|
||
$uid = [int]($u.id)
|
||
$name = [string]($u.display_name ?? $u.displayName ?? $u.name ?? $u.username)
|
||
$login = [string]($u.username)
|
||
|
||
$mergedId = 0
|
||
try { if ($u.group -and $u.group.id -ne $null) { $mergedId = [int]$u.group.id } } catch {}
|
||
|
||
$cgNamed = if ($mergedId -ge 0) { Expand-NamedMRGroups -MergedGroupID $mergedId } else { @() }
|
||
$cgNames = $cgNamed.name | Sort-Object -Unique
|
||
$cgIds = $cgNamed.id | Sort-Object -Unique
|
||
|
||
$rows += [pscustomobject]@{
|
||
id = $uid
|
||
name = $name
|
||
username = $login
|
||
mergedGroup = $mergedId
|
||
groupsCount = @($cgNames).Count
|
||
groupNames = ($cgNames -join ', ')
|
||
groupIDs = ($cgIds -join ', ')
|
||
}
|
||
}
|
||
if ($rows.Count -gt 0) { $rows = $rows | Sort-Object name }
|
||
return $rows
|
||
}
|
||
|
||
function Get-UserGroupsWithComputerGroups {
|
||
<#
|
||
.SYNOPSIS Récupère User Groups + leurs Computer Groups effectifs (nommés).
|
||
#>
|
||
$ugs = @(Get-UserGroup -All)
|
||
|
||
$rows = @()
|
||
foreach ($g in $ugs) {
|
||
$gid = [int]($g.id)
|
||
$gname = [string]($g.name)
|
||
|
||
$mergedId = 0
|
||
try { if ($g.group -and $g.group.id -ne $null) { $mergedId = [int]$g.group.id } } catch {}
|
||
|
||
$cgNamed = if ($mergedId -ge 0) { Expand-NamedMRGroups -MergedGroupID $mergedId } else { @() }
|
||
$cgNames = $cgNamed.name | Sort-Object -Unique
|
||
$cgIds = $cgNamed.id | Sort-Object -Unique
|
||
|
||
$rows += [pscustomobject]@{
|
||
id = $gid
|
||
name = $gname
|
||
mergedGroup = $mergedId
|
||
groupsCount = @($cgNames).Count
|
||
groupNames = ($cgNames -join ', ')
|
||
groupIDs = ($cgIds -join ', ')
|
||
}
|
||
}
|
||
if ($rows.Count -gt 0) { $rows = $rows | Sort-Object name }
|
||
return $rows
|
||
}
|
||
|
||
# =========================
|
||
# Block 5 - Exécution + affichage
|
||
# =========================
|
||
Write-Host ">> Gathering Users + Effective Computer Groups..." -ForegroundColor Cyan
|
||
$UsersWithCG = Get-UsersWithComputerGroups
|
||
|
||
Write-Host ">> Gathering User Groups + Effective Computer Groups..." -ForegroundColor Cyan
|
||
$UGsWithCG = Get-UserGroupsWithComputerGroups
|
||
|
||
$hasOGV = $null -ne (Get-Command Out-GridView -ErrorAction SilentlyContinue)
|
||
if ($hasOGV) {
|
||
$UsersWithCG | Out-GridView -Title 'Tanium Users – Effective Computer Groups (by name)' -Wait
|
||
$UGsWithCG | Out-GridView -Title 'Tanium User Groups – Effective Computer Groups (by name)' -Wait
|
||
} else {
|
||
Write-Host "`n=== USERS – EFFECTIVE COMPUTER GROUPS ===" -ForegroundColor Green
|
||
$UsersWithCG | Format-Table id,name,username,groupsCount,groupNames -AutoSize
|
||
|
||
Write-Host "`n=== USER GROUPS – EFFECTIVE COMPUTER GROUPS ===" -ForegroundColor Green
|
||
$UGsWithCG | Format-Table id,name,groupsCount,groupNames -AutoSize
|
||
Write-Host "`n(Out-GridView not available; showing tables instead)" -ForegroundColor Yellow
|
||
}
|
||
|
||
# =========================
|
||
# Block 6 - Cleanup
|
||
# =========================
|
||
if (Test-Path $TempXml) {
|
||
Remove-Item $TempXml -Force -ErrorAction SilentlyContinue
|
||
Write-Host "Temporary CLIXML removed: $TempXml"
|
||
}
|