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

196
API/Deploy - Create.ps1 Normal file
View File

@@ -0,0 +1,196 @@
<#
.SYNOPSIS
Create a Tanium Deploy software package using the Deploy module cmdlets.
Strategy: clone an existing package to get the exact schema, then modify a few fields.
REQUIRES: Redden-TanREST (for the Deploy cmdlets your screenshot shows)
#>
# =============== Block 0 - Parameters to edit ===============
# New package name and install command
$NewPackageName = 'Demo - My Package (API)'
$InstallCommandLine = 'cmd /c echo Hello from Deploy > %TEMP%\hello.txt'
# Choose ONE mode: 'CommandOnly' | 'LocalFile' | 'RemoteURL'
$Mode = 'CommandOnly'
# If Mode = LocalFile
$LocalFilePath = 'C:\Temp\payload.msi'
# If Mode = RemoteURL
$RemoteFileUrl = 'https://example.com/payload.msi'
# An existing simple package to use as a schema template (must exist in your Deploy)
$TemplatePackageName = 'Notepad++ (Gallery)' # <-- mets ici un paquet simple qui existe chez toi
# Optional: content set ID (leave as-is to keep the template's)
$OverrideContentSetId = $null # ex: 0 (ou $null pour garder lID du template)
# =============== Block 1 - Import & Session ===============
$ErrorActionPreference = 'Stop'
Import-Module Redden-TanREST -Force
# Load config.json next to this script
$configPath = Join-Path $PSScriptRoot 'config.json'
if (-not (Test-Path $configPath)) { throw "Configuration file not found: $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 in config.json."
}
if ($TaniumUrl -match '^https?://') { $TaniumUrl = $TaniumUrl -replace '^https?://','' -replace '/+$','' }
# Create a short-lived CLIXML for Initialize-TaniumSession (same pattern as your other scripts)
$TempXml = Join-Path $env:TEMP 'tanium-session-tmp.apicred'
$ExportObject = @{
baseURI = $TaniumUrl
token = ($TaniumToken | ConvertTo-SecureString -AsPlainText -Force)
}
$ExportObject | Export-Clixml -Path $TempXml
Initialize-TaniumSession -PathToXML $TempXml
Write-Host "Tanium session initialized."
# =============== Block 2 - Helpers ===============
function DeepClone($obj) {
# round-trip through JSON for a deep copy
return ($obj | ConvertTo-Json -Depth 100 | ConvertFrom-Json)
}
function Remove-ReadOnlyProps {
param([Parameter(Mandatory)]$o)
# remove common read-only or server-managed fields wherever they appear
$remove = @('id','createdAt','createdBy','updatedAt','updatedBy','lastModified','created','modified','revision','status')
if ($o -is [System.Collections.IDictionary]) {
foreach ($k in @($o.Keys)) {
if ($remove -contains [string]$k) { $o.Remove($k) | Out-Null; continue }
$o[$k] = Remove-ReadOnlyProps $o[$k]
}
return $o
} elseif ($o -is [System.Collections.IEnumerable] -and -not ($o -is [string])) {
$new = @()
foreach ($item in $o) { $new += ,(Remove-ReadOnlyProps $item) }
return $new
} else {
return $o
}
}
function Replace-AllTempFileIds {
param(
[Parameter(Mandatory)]$o,
[Parameter(Mandatory)][string]$NewTempFileId
)
# replace any property named 'tempFileId' or 'fileId' with the new tempfile id (common API shapes)
$matchKeys = @('tempFileId','fileId')
if ($o -is [System.Collections.IDictionary]) {
foreach ($k in @($o.Keys)) {
if ($matchKeys -contains [string]$k) {
$o[$k] = $NewTempFileId
} else {
$o[$k] = Replace-AllTempFileIds -o $o[$k] -NewTempFileId $NewTempFileId
}
}
return $o
} elseif ($o -is [System.Collections.IEnumerable] -and -not ($o -is [string])) {
$new = @()
foreach ($item in $o) { $new += ,(Replace-AllTempFileIds -o $item -NewTempFileId $NewTempFileId) }
return $new
} else {
return $o
}
}
function Update-InstallCommand {
param(
[Parameter(Mandatory)]$o,
[Parameter(Mandatory)][string]$CommandLine
)
# best-effort: update common command fields if found
$cmdKeys = @('command','commandLine','installCommand','install_command','command_line')
if ($o -is [System.Collections.IDictionary]) {
foreach ($k in @($o.Keys)) {
if ($cmdKeys -contains [string]$k -and ($o[$k] -is [string])) {
$o[$k] = $CommandLine
} else {
$o[$k] = Update-InstallCommand -o $o[$k] -CommandLine $CommandLine
}
}
return $o
} elseif ($o -is [System.Collections.IEnumerable] -and -not ($o -is [string])) {
$new = @()
foreach ($item in $o) { $new += ,(Update-InstallCommand -o $item -CommandLine $CommandLine) }
return $new
} else {
return $o
}
}
# =============== Block 3 - Fetch template & prepare body ===============
Write-Host "Fetching template package: $TemplatePackageName"
$template = Get-DeploySoftwarePackage -Name $TemplatePackageName -IncludeHidden
if (-not $template) { throw "Template package '$TemplatePackageName' not found." }
# If multiple, take the first
if ($template -is [System.Array]) { $template = $template[0] }
# Deep clone and strip read-only fields
$bodyObj = DeepClone $template
$bodyObj = Remove-ReadOnlyProps $bodyObj
# Apply basic changes
$bodyObj.name = $NewPackageName
if ($OverrideContentSetId -ne $null) {
if ($bodyObj.contentSet -and $bodyObj.contentSet.id -ne $null) {
$bodyObj.contentSet.id = [int]$OverrideContentSetId
}
}
# Update command line everywhere it appears (best-effort)
$bodyObj = Update-InstallCommand -o $bodyObj -CommandLine $InstallCommandLine
# =============== Block 4 - Attach file if requested ===============
$tempFile = $null
switch ($Mode) {
'LocalFile' {
Write-Host "Uploading local file: $LocalFilePath"
if (-not (Test-Path $LocalFilePath)) { throw "Local file not found: $LocalFilePath" }
$tempFile = New-DeployTempFile -FilePath $LocalFilePath
if (-not $tempFile) { throw "Failed to upload local file." }
$bodyObj = Replace-AllTempFileIds -o $bodyObj -NewTempFileId ([string]$tempFile.id)
}
'RemoteURL' {
Write-Host "Registering remote file URL: $RemoteFileUrl"
$tempFile = New-DeployTempFile -RemoteURL $RemoteFileUrl
if (-not $tempFile) { throw "Failed to register remote URL." }
$bodyObj = Replace-AllTempFileIds -o $bodyObj -NewTempFileId ([string]$tempFile.id)
}
'CommandOnly' {
Write-Host "No file attachment (command-only mode)."
}
default { throw "Unknown Mode '$Mode' (use CommandOnly | LocalFile | RemoteURL)" }
}
# =============== Block 5 - Create software package ===============
# Convert to JSON for -Body
$bodyJson = $bodyObj | ConvertTo-Json -Depth 100
Write-Host "Creating Deploy software package: $NewPackageName"
$newPkg = New-DeploySoftwarePackage -Body ($bodyJson | ConvertFrom-Json)
# Certains modules attendent un objet PS, dautres une chaîne JSON ; si erreur, essaie directement -Body $bodyJson
if (-not $newPkg) {
Write-Warning "New-DeploySoftwarePackage returned no object. Verify in console if the package exists."
} else {
Write-Host "Created: ID=$($newPkg.id) Name=$($newPkg.name)"
}
# Optional: verify by name
$check = Get-DeploySoftwarePackage -Name $NewPackageName -IncludeHidden
if ($check) {
Write-Host "Verified package exists. Done."
} else {
Write-Warning "Package not found via Get-DeploySoftwarePackage; please check the console or API logs."
}
# Cleanup temp clixml (optional)
Remove-Item -Path $TempXml -Force -ErrorAction SilentlyContinue