Auto-commit: 2025-10-31 08:59:02

This commit is contained in:
David Wuibaille
2025-10-31 08:59:02 +01:00
parent d3b18d8b45
commit 851c85ec3d
30 changed files with 3734 additions and 6 deletions

View File

@@ -0,0 +1,218 @@
<#
.SYNOPSIS
Create or delete a Tanium Computer Group via Gateway GraphQL.
.DESCRIPTION
- CREATE: filter "Computer Name STARTS_WITH <Prefix>" (usable as Computer Management Group; optional Content Set).
- DELETE: delete a Computer Group by its Tanium ID.
- Reads URL/token from config.json (same folder) unless -Url/-Token are provided.
- Optional TLS bypass for lab with -SkipCertCheck.
.USAGE (examples)
# Create a group (no defaults; you MUST pass -GroupName and -Prefix)
.\Create-ComputerGroup.ps1 -GroupName "LAB - starts with LAB" -Prefix "LAB" -MrEnabled:$true
.\Create-ComputerGroup.ps1 -GroupName "LAB - starts with LAB" -Prefix "LAB" -ContentSetName "My Content Set"
# Delete by ID
.\Create-ComputerGroup.ps1 -Delete -Id "12345"
# Override URL/token
.\Create-ComputerGroup.ps1 -Url tanium.pp.dktinfra.io -Token 'token-xxxx' -GroupName "LAB ..." -Prefix "LAB"
# Raw JSON (debug)
.\Create-ComputerGroup.ps1 -GroupName "LAB ..." -Prefix "LAB" -Raw
#>
param(
[string]$Url,
[string]$Token,
[switch]$SkipCertCheck,
# CREATE params (no defaults; both required for creation)
[string]$GroupName,
[string]$Prefix,
[bool] $MrEnabled = $true,
[string]$ContentSetName,
# DELETE params
[switch]$Delete,
[string]$Id,
[switch]$Raw
)
$ErrorActionPreference = 'Stop'
try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {}
function Show-ShortHelp {
Write-Host ""
Write-Host "Create mode (requires -GroupName and -Prefix):" -ForegroundColor Cyan
Write-Host " .\Create-ComputerGroup.ps1 -GroupName 'LAB - starts with LAB' -Prefix 'LAB' [-MrEnabled:`$true] [-ContentSetName 'My Content Set']" -ForegroundColor Gray
Write-Host ""
Write-Host "Delete mode (requires -Delete and -Id):" -ForegroundColor Cyan
Write-Host " .\Create-ComputerGroup.ps1 -Delete -Id '12345'" -ForegroundColor Gray
Write-Host ""
Write-Host "Common options: -Url <host> -Token <token> -SkipCertCheck -Raw" -ForegroundColor DarkGray
}
# ---------- Helpers ----------
function Get-GatewayUri {
param([Parameter(Mandatory)][string]$HostLike)
$h = $HostLike.Trim()
if ($h -match '^https?://') { $h = $h -replace '^https?://','' }
$h = $h.TrimEnd('/')
if ([string]::IsNullOrWhiteSpace($h)) { throw 'TaniumUrl empty after normalization.' }
"https://$h/plugin/products/gateway/graphql"
}
# TLS bypass for Windows PowerShell 5.1 (temporary, restored after call)
$script:__oldCb = $null
function Enter-InsecureTls {
param([switch]$Enable)
if (-not $Enable) { return }
$script:__oldCb = [System.Net.ServicePointManager]::ServerCertificateValidationCallback
$cb = [System.Net.Security.RemoteCertificateValidationCallback]{ param($s,$c,$ch,$e) $true }
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $cb
}
function Exit-InsecureTls {
if ($script:__oldCb -ne $null) {
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $script:__oldCb
$script:__oldCb = $null
}
}
# ---------- Load config if needed ----------
$BaseDir = if ($PSScriptRoot) { $PSScriptRoot } else { $pwd.Path }
$configPath = Join-Path $BaseDir 'config.json'
if (-not $Url -or -not $Token) {
if (-not (Test-Path $configPath)) {
throw "Missing -Url/-Token and config.json not found: $configPath"
}
$cfg = Get-Content -Path $configPath -Raw | ConvertFrom-Json
if (-not $Url) { $Url = [string]$cfg.TaniumUrl }
if (-not $Token) { $Token = [string]$cfg.TaniumApiToken }
if (-not $PSBoundParameters.ContainsKey('SkipCertCheck')) { $SkipCertCheck = [bool]$cfg.SkipCertificateCheck }
}
# ---------- Endpoint & headers ----------
$gateway = Get-GatewayUri -HostLike $Url
$headers = @{ 'Content-Type' = 'application/json'; session = $Token }
# ---------- GraphQL mutations ----------
$Create_WithContentSet = @'
mutation createGroup($name: String!, $mrEnabled: Boolean!, $prefix: String!, $contentSetName: String!) {
computerGroupCreate(
input: {
name: $name
managementRightsEnabled: $mrEnabled
contentSetRef: { name: $contentSetName }
filter: {
sensor: { name: "Computer Name" }
op: STARTS_WITH
value: $prefix
}
}
) {
group { id name }
error { message }
}
}
'@
$Create_NoContentSet = @'
mutation createGroup($name: String!, $mrEnabled: Boolean!, $prefix: String!) {
computerGroupCreate(
input: {
name: $name
managementRightsEnabled: $mrEnabled
filter: {
sensor: { name: "Computer Name" }
op: STARTS_WITH
value: $prefix
}
}
) {
group { id name }
error { message }
}
}
'@
$Delete_ById = @'
mutation deleteComputerGroup($id: ID!) {
computerGroupDelete(ref: { id: $id }) {
id
error { message }
}
}
'@
# ---------- Mode selection & validation ----------
if ($Delete) {
if ([string]::IsNullOrWhiteSpace($Id)) {
Write-Warning "Missing -Id for deletion."
Show-ShortHelp
return
}
$Query = $Delete_ById
$Variables = @{ id = $Id }
$OpName = 'deleteComputerGroup'
}
else {
if ([string]::IsNullOrWhiteSpace($GroupName) -or [string]::IsNullOrWhiteSpace($Prefix)) {
Write-Warning "Missing -GroupName and/or -Prefix for creation."
Show-ShortHelp
return
}
$useCS = -not [string]::IsNullOrWhiteSpace($ContentSetName)
$Query = if ($useCS) { $Create_WithContentSet } else { $Create_NoContentSet }
$Variables = @{ name = $GroupName; mrEnabled = $MrEnabled; prefix = $Prefix }
if ($useCS) { $Variables.contentSetName = $ContentSetName }
$OpName = 'createGroup'
}
# ---------- Execute ----------
$bodyObj = @{ query = $Query; variables = $Variables; operationName = $OpName }
$bodyJson = $bodyObj | ConvertTo-Json -Depth 10
$resp = $null
$ps7 = ($PSVersionTable.PSVersion.Major -ge 7)
if ($ps7 -and $SkipCertCheck) {
$resp = Invoke-RestMethod -SkipCertificateCheck -Method Post -Uri $gateway -Headers $headers -ContentType 'application/json' -Body $bodyJson
}
else {
try {
Enter-InsecureTls -Enable:$SkipCertCheck
$resp = Invoke-RestMethod -Method Post -Uri $gateway -Headers $headers -ContentType 'application/json' -Body $bodyJson
}
finally { Exit-InsecureTls }
}
# ---------- Output ----------
if ($Raw) { $resp | ConvertTo-Json -Depth 12; return }
if ($resp.errors) {
Write-Error ("GraphQL errors: " + (($resp.errors | ForEach-Object { $_.message }) -join '; '))
return
}
if ($Delete) {
$del = $resp.data.computerGroupDelete
if ($del.error -and $del.error.message) {
Write-Error ("Delete failed: {0}" -f $del.error.message)
} elseif ($del.id) {
Write-Host ("Deleted group ID: {0}" -f $del.id) -ForegroundColor Green
} else {
Write-Warning "No confirmation returned. Use -Raw to inspect the full response."
}
}
else {
$crt = $resp.data.computerGroupCreate
if ($crt.error -and $crt.error.message) {
Write-Error ("Create failed: {0}" -f $crt.error.message)
} elseif ($crt.group) {
Write-Host ("Created group: {0} (ID: {1})" -f $crt.group.name, $crt.group.id) -ForegroundColor Green
} else {
Write-Warning "No group returned. Use -Raw to inspect the full response."
}
}