Files
Zack Meier 1d304511b8 update
2026-04-15 15:45:50 -05:00

814 lines
29 KiB
PowerShell

# . . . . . . . . . . . . . . . . . . .
# PowerShell Module for Cohesity API
# Version 2020.12.22 - Brian Seltzer
# . . . . . . . . . . . . . . . . . . .
#
# 2020.10.16 - added password parameter to storePasswordInFile function
# 2020.10.20 - code cleanup (moved old version history to end of file)
# 2020.12.22 - added v2 support for file download
#
# . . . . . . . . . . . . . . . . . . . . . . . .
$versionCohesityAPI = '2020.12.22'
# demand modern powershell version (must support TLSv1.2)
if($Host.Version.Major -le 5 -and $Host.Version.Minor -lt 1){
Write-Warning "PowerShell version must be upgraded to 5.1 or higher to connect to Cohesity!"
Pause
exit
}
$REPORTAPIERRORS = $true
$pwfile = $(Join-Path -Path $PSScriptRoot -ChildPath YWRtaW4)
$apilogfile = $(Join-Path -Path $PSScriptRoot -ChildPath cohesity-api-debug.log)
# platform detection ==========================================================================
if ($PSVersionTable.Platform -eq 'Unix') {
$CONFDIR = '~/.cohesity-api'
if ($(Test-Path $CONFDIR) -eq $false) { $null = New-Item -Type Directory -Path $CONFDIR}
}else{
$registryPath = 'HKCU:\Software\Cohesity-API'
$WEBCLI = New-Object System.Net.WebClient;
}
if($PSVersionTable.PSEdition -eq 'Desktop'){
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { return $true }
$ignoreCerts = @"
public class SSLHandler
{
public static System.Net.Security.RemoteCertificateValidationCallback GetSSLHandler()
{
return new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });
}
}
"@
if(!("SSLHandler" -as [type])){
Add-Type -TypeDefinition $ignoreCerts
}
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [SSLHandler]::GetSSLHandler()
}
function __writeLog($logmessage){
"$(Get-Date): $logmessage" | Out-File -FilePath $apilogfile -Append
}
# authentication functions ========================================================================
function apiauth($vip, $username='helios', $domain='local', $passwd=$null, $password = $null, $tenantId = $null, [switch] $quiet, [switch] $noprompt, [switch] $updatePassword, [switch] $helios, [switch] $useApiKey){
if(-not $vip){
if($helios){
$vip = 'helios.cohesity.com'
}else{
Write-Host 'vip is required' -foregroundcolor Yellow
break
}
}
# parse domain\username or username@domain
if($username.Contains('\')){
$domain, $username = $username.Split('\')
}
if($password){ $passwd = $password }
if($updatePassword){
$fpasswd = Get-CohesityAPIPasswordFromFile -vip $vip -username $username -domain $domain
if($fpasswd){
storePasswordInFile -vip $vip -username $username -domain $domain
}else{
Set-CohesityAPIPassword -vip $vip -username $username -domain $domain
}
}
# get password
if(!$passwd){
$passwd = Get-CohesityAPIPassword -vip $vip -username $username -domain $domain
if(!$passwd -and !$noprompt){
Set-CohesityAPIPassword -vip $vip -username $username -domain $domain
$passwd = Get-CohesityAPIPassword -vip $vip -username $username -domain $domain
}
if(!$passwd){
Write-Host "No password provided for $username at $vip" -ForegroundColor Yellow
$global:AUTHORIZED = $false
break
}
}
$body = ConvertTo-Json @{
'domain' = $domain;
'username' = $username;
'password' = $passwd
}
$global:APIROOT = 'https://' + $vip + '/irisservices/api/v1'
$global:APIROOTv2 = 'https://' + $vip + '/v2/'
$HEADER = @{'accept' = 'application/json'; 'content-type' = 'application/json'}
if($useApiKey){
$HEADER['apiKey'] = $passwd
$global:HEADER = $HEADER
$global:AUTHORIZED = $true
$global:CLUSTERSELECTED = $true
$cluster = api get cluster
if($cluster){
if(!$quiet){ Write-Host "Connected!" -foregroundcolor green }
}else{
$global:AUTHORIZED = $false
}
}elseif($vip -eq 'helios.cohesity.com' -or $helios){
# Authenticate Helios
$HEADER['apiKey'] = $passwd
$URL = 'https://helios.cohesity.com/mcm/clusters/connectionStatus'
try{
if($PSVersionTable.Edition -eq 'Core'){
$global:HELIOSALLCLUSTERS = Invoke-RestMethod -Method get -Uri $URL -Header $HEADER -SkipCertificateCheck
}else{
$global:HELIOSALLCLUSTERS = Invoke-RestMethod -Method get -Uri $URL -Header $HEADER
}
$global:HELIOSCONNECTEDCLUSTERS = $global:HELIOSALLCLUSTERS | Where-Object connectedToCluster -eq $true
$global:HEADER = $HEADER
$global:AUTHORIZED = $true
$global:CLUSTERSELECTED = $false
$global:CLUSTERREADONLY = $false
if(!$quiet){ Write-Host "Connected!" -foregroundcolor green }
}catch{
$global:AUTHORIZED = $false
__writeLog $_.ToString()
if($_.ToString().contains('"message":')){
Write-Host (ConvertFrom-Json $_.ToString()).message -foregroundcolor yellow
}else{
Write-Host $_.ToString() -foregroundcolor yellow
}
}
}else{
# Authenticate Cluster
$url = $APIROOT + '/public/accessTokens'
try {
# authenticate
if($PSVersionTable.PSEdition -eq 'Core'){
$auth = Invoke-RestMethod -Method Post -Uri $url -Header $HEADER -Body $body -SkipCertificateCheck
}else{
$auth = Invoke-RestMethod -Method Post -Uri $url -Header $HEADER -Body $body
}
# set file transfer details
if($PSVersionTable.Platform -eq 'Unix'){
$global:CURLHEADER = "authorization: $($auth.tokenType) $($auth.accessToken)"
}else{
$WEBCLI.Headers['authorization'] = $auth.tokenType + ' ' + $auth.accessToken;
}
# store token
$global:AUTHORIZED = $true
$global:CLUSTERSELECTED = $true
$global:CLUSTERREADONLY = $false
$global:HEADER = @{'accept' = 'application/json';
'content-type' = 'application/json';
'authorization' = $auth.tokenType + ' ' + $auth.accessToken
}
if($tenantId){
$global:HEADER['x-impersonate-tenant-id'] = "$tenantId/"
}
if(!$quiet){ Write-Host "Connected!" -foregroundcolor green }
}catch{
$global:AUTHORIZED = $false
__writeLog $_.ToString()
$global:AUTHORIZED = $false
if($REPORTAPIERRORS){
if($_.ToString().contains('"message":')){
Write-Host (ConvertFrom-Json $_.ToString()).message -foregroundcolor yellow
}else{
Write-Host $_.ToString() -foregroundcolor yellow
}
}
}
}
}
# select helios access cluster
function heliosCluster($clusterName, [switch] $verbose){
if($clusterName -and $HELIOSCONNECTEDCLUSTERS){
if(! ($clusterName -is [string])){
$clusterName = $clusterName.name
}
$cluster = $HELIOSCONNECTEDCLUSTERS | Where-Object name -eq $clusterName
if($cluster){
$global:HEADER.accessClusterId = $cluster.clusterId
$global:CLUSTERSELECTED = $true
$global:CLUSTERREADONLY = (api get /mcm/config).mcmReadOnly
if($verbose){
Write-Host "Connected ($($cluster.name))" -ForegroundColor Green
}
}else{
Write-Host "Cluster $clusterName not connected to Helios" -ForegroundColor Yellow
$global:CLUSTERSELECTED = $false
return $null
}
}else{
$HELIOSCONNECTEDCLUSTERS | Sort-Object -Property name | Select-Object -Property name, clusterId, softwareVersion
"`ntype heliosCluster <clustername> to connect to a cluster"
}
if (-not $global:AUTHORIZED){
if($REPORTAPIERRORS){
Write-Host 'Please use apiauth to connect to helios' -foregroundcolor yellow
}
}
}
function heliosClusters(){
return $HELIOSCONNECTEDCLUSTERS | Sort-Object -Property name
}
# terminate authentication
function apidrop([switch] $quiet){
$global:AUTHORIZED = $false
$global:HEADER = ''
$global:HELIOSALLCLUSTERS = $null
$global:HELIOSCONNECTEDCLUSTERS = $null
if(!$quiet){ Write-Host "Disonnected!" -foregroundcolor green }
}
# api call functions ==============================================================================
$methods = 'get', 'post', 'put', 'delete'
function api($method, $uri, $data, $version=1, [switch]$v2){
if (-not $global:AUTHORIZED){
if($REPORTAPIERRORS){
Write-Host 'Not authenticated to a cohesity cluster' -foregroundcolor yellow
if($MyInvocation.PSCommandPath){
exit 1
}
}
}else{
if($method -ne 'get' -and $global:CLUSTERREADONLY -eq $true){
Write-Host "Cluster connection is READ-ONLY" -ForegroundColor Yellow
break
}
if (-not $methods.Contains($method)){
if($REPORTAPIERRORS){
Write-Host "invalid api method: $method" -foregroundcolor yellow
}
break
}
try {
if($version -eq 2 -or $v2){
$url = $APIROOTv2 + $uri
}else{
if ($uri[0] -ne '/'){ $uri = '/public/' + $uri}
$url = $APIROOT + $uri
}
$body = ConvertTo-Json -Depth 100 $data
if ($PSVersionTable.PSEdition -eq 'Core'){
if($body){
$result = Invoke-RestMethod -Method $method -Uri $url -Body $body -Header $HEADER -SkipCertificateCheck
}else{
$result = Invoke-RestMethod -Method $method -Uri $url -Header $HEADER -SkipCertificateCheck
}
}else{
$result = Invoke-RestMethod -Method $method -Uri $url -Body $body -Header $HEADER
}
return $result
}catch{
__writeLog $_.ToString()
if($REPORTAPIERRORS){
if($_.ToString().contains('"message":')){
Write-Host (ConvertFrom-Json $_.ToString()).message -foregroundcolor yellow
}else{
Write-Host $_.ToString() -foregroundcolor yellow
}
}
}
}
}
# file download function
function fileDownload($uri, $fileName, $version=1, [switch]$v2){
if (-not $global:AUTHORIZED){ Write-Host 'Please use apiauth to connect to a cohesity cluster' -foregroundcolor yellow; break }
try {
if($version -eq 2 -or $v2){
$url = $APIROOTv2 + $uri
}else{
if ($uri[0] -ne '/'){ $uri = '/public/' + $uri}
$url = $APIROOT + $uri
}
if ($PSVersionTable.Platform -eq 'Unix'){
curl -k -s -H "$global:CURLHEADER" -o "$fileName" "$url"
}else{
if($fileName -notmatch '\\'){
$fileName = $(Join-Path -Path $PSScriptRoot -ChildPath $fileName)
}
$WEBCLI.DownloadFile($url, $fileName)
}
}catch{
__writeLog $_.ToString()
$_.ToString()
if($_.ToString().contains('"message":')){
Write-Host (ConvertFrom-Json $_.ToString()).message -foregroundcolor yellow
}else{
Write-Host $_.ToString() -foregroundcolor yellow
}
}
}
# date functions ==================================================================================
function timeAgo([int64] $age, [string] $units){
$currentTime = [int64](((get-date).ToUniversalTime())-([datetime]"1970-01-01 00:00:00")).TotalSeconds*1000000
$secs=@{'seconds'= 1; 'sec'= 1; 'secs' = 1;
'minutes' = 60; 'min' = 60; 'mins' = 60;
'hours' = 3600; 'hour' = 3600;
'days' = 86400; 'day' = 86400;
'weeks' = 604800; 'week' = 604800;
'months' = 2628000; 'month' = 2628000;
'years' = 31536000; 'year' = 31536000 }
$age = $age * $secs[$units.ToLower()] * 1000000
return [int64] ($currentTime - $age)
}
function usecsToDate($usecs){
$unixTime=$usecs/1000000
$origin = ([datetime]'1970-01-01 00:00:00')
return $origin.AddSeconds($unixTime).ToLocalTime()
}
function dateToUsecs($datestring){
if($datestring -isnot [datetime]){ $datestring = [datetime] $datestring }
$usecs = [int64](($datestring.ToUniversalTime())-([datetime]"1970-01-01 00:00:00")).TotalSeconds*1000000
$usecs
}
# password functions ==============================================================================
function Get-CohesityAPIPassword($vip, $username, $domain='local'){
# parse domain\username or username@domain
if($username.Contains('\')){
$domain, $username = $username.Split('\')
}
if($username.Contains('@')){
$username, $domain = $username.Split('@')
}
$passwd = Get-CohesityAPIPasswordFromFile -vip $vip -username $username -domain $domain
if($passwd){
return $passwd
}
$keyName = "$vip`:$domain`:$username"
if($PSVersionTable.Platform -eq 'Unix'){
# Unix
$keyFile = "$CONFDIR/$keyName"
if (Test-Path $keyFile) {
$key, $storedPassword = Get-Content $keyFile
return Unprotect-CohesityAPIPassword $key $storedPassword
}
}else{
# Windows
$storedPassword = Get-ItemProperty -Path "$registryPath" -Name "$keyName" -ErrorAction SilentlyContinue
If (($null -ne $storedPassword) -and ($storedPassword.Length -ne 0)) {
$securePassword = $storedPassword.$keyName | ConvertTo-SecureString
return [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $securePassword ))
}
}
}
function Get-CohesityAPIPasswordFromFile($vip, $username, $domain){
$pwlist = Get-Content -Path $pwfile -ErrorAction SilentlyContinue
foreach($pwitem in $pwlist){
$v, $d, $u, $cpwd = $pwitem.split(":", 4)
if($v -eq $vip -and $d -eq $domain -and $u -eq $username){
return [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($cpwd))
}
}
return $null
}
function storePasswordInFile($vip='helios.cohesity.com', $username='helios', $domain='local', [switch]$helios, $password=$null){
# parse domain\username or username@domain
if($username.Contains('\')){
$domain, $username = $username.Split('\')
}
if($username.Contains('@')){
$username, $domain = $username.Split('@')
}
if($vip -eq 'helios.cohesity.com' -and $username -eq 'helios' -and ! $helios){
# prompt for vip
__writeLog "Prompting for VIP, USERNAME, DOMAIN"
$newVip = Read-Host -Prompt "Enter VIP ($vip)"
if($newVip -ne ''){ $vip = $newVip }
# prompt for domain
$newDomain = Read-Host -Prompt "Enter domain ($domain)"
if($newDomain -ne ''){ $domain = $newDomain }
# prompt for username
$newUsername = Read-Host -Prompt "Enter username ($username)"
if($newUsername -ne ''){ $username = $newUsername }
}
# prompt for password
__writeLog "Prompting for Password"
if(!$password){
$secureString = Read-Host -Prompt "Enter password for $domain\$username at $vip" -AsSecureString
$passwd = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $secureString ))
}else{
$passwd = $password
}
$opwd = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($passwd))
$pwlist = Get-Content -Path $pwfile -ErrorAction SilentlyContinue
$updatedContent = ''
$foundPwd = $false
foreach($pwitem in $pwlist){
$v, $d, $u, $cpwd = $pwitem.split(":", 4)
# update existing
if($v -eq $vip -and $d -eq $domain -and $u -eq $username){
$foundPwd = $true
$updatedContent += "{0}:{1}:{2}:{3}`n" -f $vip, $domain, $username, $opwd
# other existing records
}else{
if($pwitem -ne ''){
$updatedContent += "{0}`n" -f $pwitem
}
}
}
# add new
if(!$foundPwd){
$updatedContent += "{0}:{1}:{2}:{3}`n" -f $vip, $domain, $username, $opwd
}
$updatedContent | out-file -FilePath $pwfile
Write-Host "Password stored!" -ForegroundColor Green
}
function Set-CohesityAPIPassword($vip, $username, $domain='local', $passwd=$null){
# prompt for vip
if(-not $vip){
__writeLog "Prompting for VIP"
Write-Host 'VIP: ' -foregroundcolor green -nonewline
$vip = Read-Host
if(-not $vip){Write-Host 'vip is required' -foregroundcolor red; break}
}
# prompt for username
if(-not $username){
__writeLog "Prompting for Username"
Write-Host 'Username: ' -foregroundcolor green -nonewline
$username = Read-Host
if(-not $username){Write-Host 'username is required' -foregroundcolor red; break}
}
# parse domain\username or username@domain
if($username.Contains('\')){
$domain, $username = $username.Split('\')
}
if($username.Contains('@')){
$username, $domain = $username.Split('@')
}
$keyName = "$vip`:$domain`:$username"
if(!$passwd){
__writeLog "Prompting for Password"
$secureString = Read-Host -Prompt "Enter password for $username at $vip" -AsSecureString
$passwd = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $secureString ))
}
if($PSVersionTable.Platform -eq 'Unix'){
# Unix
$keyFile = "$CONFDIR/$keyName"
$key = New-AesKey
$key | Out-File $keyFile
Protect-CohesityAPIPassword $key $passwd | Out-File $keyFile -Append
}else{
# Windows
$securePassword = ConvertTo-SecureString -String $passwd -AsPlainText -Force
$encryptedPasswordText = $securePassword | ConvertFrom-SecureString
if(!(Test-Path $registryPath)){
New-Item -Path $registryPath -Force | Out-Null
}
Set-ItemProperty -Path "$registryPath" -Name "$keyName" -Value "$encryptedPasswordText"
}
}
# security functions ==============================================================================
function New-AesManagedObject($key, $IV){
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
if($IV){
if($IV.getType().Name -eq "String"){
$aesManaged.IV = [System.Convert]::FromBase64String($IV)
}else{
$aesManaged.IV = $IV
}
}
if($key){
if($key.getType().Name -eq "String") {
$aesManaged.Key = [System.Convert]::FromBase64String($key)
}else{
$aesManaged.Key = $key
}
}
$aesManaged
}
function New-AesKey() {
$aesManaged = New-AesManagedObject
$aesManaged.GenerateKey()
[System.Convert]::ToBase64String($aesManaged.Key)
}
function Protect-CohesityAPIPassword($key, $unencryptedString) {
$bytes = [System.Text.Encoding]::UTF8.GetBytes($unencryptedString)
$aesManaged = New-AesManagedObject $key
$encryptor = $aesManaged.CreateEncryptor()
$encryptedData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length);
[byte[]] $fullData = $aesManaged.IV + $encryptedData
$aesManaged.Dispose()
[System.Convert]::ToBase64String($fullData)
}
function Unprotect-CohesityAPIPassword($key, $encryptedStringWithIV) {
$bytes = [System.Convert]::FromBase64String($encryptedStringWithIV)
$IV = $bytes[0..15]
$aesManaged = New-AesManagedObject $key $IV
$decryptor = $aesManaged.CreateDecryptor();
$unencryptedData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16);
$aesManaged.Dispose()
[System.Text.Encoding]::UTF8.GetString($unencryptedData).Trim([char]0)
}
# developer tools =================================================================================
function saveJson($object, $jsonFile = './debug.json'){
$object | ConvertTo-Json -Depth 99 | out-file -FilePath $jsonFile
}
function loadJson($jsonFile = './debug.json'){
return Get-Content $jsonFile | ConvertFrom-Json
}
function json2code($json = '', $jsonFile = '', $psFile = 'myObject.ps1'){
if($jsonFile -ne ''){
$json = (Get-Content $jsonFile) -join "`n"
}
$json = $json | ConvertFrom-Json | ConvertTo-Json -Depth 99
$pscode = ''
foreach ($line in $json.split("`n")) {
$line = $line.TrimEnd()
# preserve end of line character
$finalEntry = $true
if ($line[-1] -eq ',') {
$finalEntry = $false
$line = $line -replace ".$"
}
# key value delimiter :
$key, $value = $line.split(':', 2)
# line is braces only
$key = $key.Replace('{', '@{').Replace('[','@(').Replace(']', ')')
if ($value) {
$value = $value.trim()
# value is quoted text
if ($value[0] -eq '"') {
$line = "$key = $value"
}
# value is opening { brace
elseif ('{' -eq $value) {
$value = $value.Replace('{', '@{')
$line = "$key = $value"
}
# value is opening [ list
elseif ('[' -eq $value) {
$value = $value.Replace('[', '@(')
$line = "$key = $value"
}
# empty braces
elseif ('{}' -eq $value) {
$value = '@{}'
$line = "$key = $value"
}
# empty list
elseif ('[]' -eq $value) {
$value = '@()'
$line = "$key = $value"
}
# value is opening ( list
elseif ('[' -eq $value) {
$value = $value.Replace('[', '@(')
$line = "$key = $value"
}
# value is a boolean
elseif ($value -eq 'true') {
$line = "$key = " + '$true'
}
elseif ($value -eq 'false') {
$line = "$key = " + '$false'
}
# null
elseif ($value -eq 'null') {
$line = "$key = " + '$null'
}
else {
# value is numeric
if ($value -as [long] -or $value -eq '0') {
$line = "$($key) = $value"
}
else {
# delimeter : was inside of quotes
$line = "$($key):$($value)"
}
}
}
else {
# was no value on this line
$line = $key
}
# replace end of line character ;
if (! $finalEntry) {
$line = "$line;"
}
$pscode += "$line`n"
}
$pscode = '$myObject = ' + $pscode
$pscode | out-file $psFile
return $pscode
}
# add a property
function setApiProperty{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True)][string]$name,
[Parameter(Mandatory = $True)][System.Object]$value,
[Parameter(Mandatory = $True, ValueFromPipeline = $True)][System.Object]$object
)
if(! $object.PSObject.Properties[$name]){
$object | Add-Member -MemberType NoteProperty -Name $name -Value $value
}else{
$object.$name = $value
}
}
# delete a propery
function delApiProperty{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True)][string]$name,
[Parameter(Mandatory = $True, ValueFromPipeline = $True)][System.Object]$object
)
$object.PSObject.Members.Remove($name)
}
# show properties of an object
function showProps{
param (
[Parameter(Mandatory = $True)]$obj,
[Parameter()]$parent = 'myobject',
[Parameter()]$search = $null
)
if($obj.getType().Name -eq 'String' -or $obj.getType().Name -eq 'Int64'){
if($null -ne $search){
if($parent.ToLower().Contains($search) -or ($obj.getType().Name -eq 'String' -and $obj.ToLower().Contains($search))){
"$parent = $obj"
}
}else{
"$parent = $obj"
}
}else{
foreach($prop in $obj.PSObject.Properties | Sort-Object -Property Name){
if($($prop.Value.GetType().Name) -eq 'PSCustomObject'){
$thisObj = $prop.Value
showProps $thisObj "$parent.$($prop.Name)" $search
}elseif($($prop.Value.GetType().Name) -eq 'Object[]'){
$thisObj = $prop.Value
$x = 0
foreach($item in $thisObj){
showProps $thisObj[$x] "$parent.$($prop.Name)[$x]" $search
$x += 1
}
}else{
if($null -ne $search){
if($prop.Name.ToLower().Contains($search.ToLower()) -or ($prop.Value.getType().Name -eq 'String' -and $prop.Value.ToLower().Contains($search.ToLower()))){
"$parent.$($prop.Name) = $($prop.Value)"
}
}else{
"$parent.$($prop.Name) = $($prop.Value)"
}
}
}
}
}
# convert syntax to python
function py($p){
$py = $p.replace("$","").replace("].","]['").replace(".","']['")
if($py[-1] -ne ']'){
$py += "']"
}
$py
}
# self updater
function cohesityAPIversion([switch]$update){
if($update){
$repoURL = 'https://raw.githubusercontent.com/bseltz-cohesity/scripts/master/powershell'
(Invoke-WebRequest -Uri "$repoURL/cohesity-api/cohesity-api.ps1").content | Out-File -Force cohesity-api.ps1; (Get-Content cohesity-api.ps1) | Set-Content cohesity-api.ps1
Write-Host "Cohesity-API version updated! Please restart PowerShell"
}else{
Write-Host "Cohesity-API version $versionCohesityAPI" -ForegroundColor Green
}
}
# paged view list
function getViews([switch]$includeInactive){
$myViews = @()
$views = $null
while(! $views){
if($includeInactive){
$views = api get views?includeInactive=true
}else{
$views = api get views
}
}
$myViews += $views.views
$lastResult = $views.lastResult
while(! $lastResult){
$lastViewId = $views.views[-1].viewId
$views = $null
while(! $views){
if($includeInactive){
$views = api get "views?maxViewId=$lastViewId&includeInactive=true"
}else{
$views = api get views?maxViewId=$lastViewId
}
}
$lastResult = $views.lastResult
$myViews += $views.views
}
return $myViews
}
# old version history
# . . . . . . . . . . . . . . . . . . . . . . . .
# 0.06 - Consolidated Windows and Unix versions - June 2018
# 0.07 - Added saveJson, loadJson and json2code utility functions - Feb 2019
# 0.08 - added -prompt to prompt for password rather than save - Mar 2019
# 0.09 - added setApiProperty / delApiProperty - Apr 2019
# 0.10 - added $REPORTAPIERRORS constant - Apr 2019
# 0.11 - added storePassword function and username parsing - Aug 2019
# 0.12 - added -password to apiauth function - Oct 2019
# 0.13 - added showProps function - Nov 2019
# 0.14 - added storePasswordFromInput function - Dec 2019
# 0.15 - added support for PS Core on Windows - Dec 2019
# 0.16 - added ServicePoint connection workaround - Jan 2020
# 0.17 - fixed json2code line endings on Windows - Jan 2020
# 0.18 - added REINVOKE - Jan 2020
# 0.19 - fixed password encryption for PowerShell 7.0 - Mar 2020
# 0.20 - refactored, added apipwd, added helios access - Mar 2020
# 0.21 - helios changes - Mar 2020
# 0.22 - added password file storage - Apr 2020
# 0.23 - added self updater - Apr 2020
# 0.24 - added delete with body - Apr 2020
# 0.25 - added paged view list - Apr 2020
# 0.26 - added support for tenants - May 2020
# 0.27 - added support for Iris API Key - May 2020
# 0.28 - added reprompt for password, debug log - June 2020
# 0.29 - update storePasswordInFile - June 2020
# 2020.06.04 - updated version numbering - June 2020
# 2020.06.16 - improved REINVOKE - June 2020
# 2020-06.25 - added API v2 support (-version 2) or (-v2)
# 2020.07.08 - removed timout
# 2020.07.20 - fixed dateToUsecs for international date formats
# 2020.07.30 - quiet ssl handler
# 2020.08.08 - fixed timezone issue
# 2020.10.02 - set PROMPTFORPASSWORDCHANGE to false
# 2020.10.05 - retired REINVOKE
# 2020.10.06 - exit script when attempting unauthenticated api call
# 2020.10.13 - fixed timeAgo function for i14n
# . . . . . . . . . . . . . . . . . . . . . . . .