PSAtera.psm1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<#
  .Synopsis
  Generic command for making GET requests against the Atera API
   
  .Parameter Endpoint
  Endpoint to request, beginning with a /
   
  .Parameter Paginate
  Whether to paginate the request. If set to false, will only query the first page of results.
   
  .Example
  New-AteraGetRequest -Endpoint "/customers/3"
  # Get a customer
 
  .Example
  New-AteraGetRequest -Endpoint "/customvalues/ticketfield/2/Product%20Family" -Paginate $false
  # Get a custom value (which needs to not paginate)
#>

function New-AteraGetRequest {
  [CmdletBinding()]
  param (
    [Parameter(Mandatory)]
    [string] $Endpoint,
    [Parameter()]
    [bool] $Paginate=$true
  )
  $Headers = @{
    "accept" = "application/json"
    "X-API-KEY" = Get-AteraAPIKey
  }
  $ItemsInPage = 50
  $Uri = "https://app.atera.com/api/v3$($endpoint)?itemsInPage=$ItemsInPage"
  $items = @()
  $index = 0

  do {
    Write-Debug "[PSAtera] Request for $Uri"
    $data = Invoke-RestMethod -Uri $Uri -Method "GET" -Headers $Headers
    if (!$Paginate) { return $data }
    $items += $data.items
    $index += 1
    $Uri = $data.nextLink
  } while ($Uri -ne "" -and $index -lt [math]::ceiling($RecordLimit / $ItemsInPage))
  return $items
}

<#
  .Synopsis
  Generic command for making POST requests against the Atera API
   
  .Parameter Endpoint
  Endpoint to request, beginning with a /
 
  .Parameter Body
  Hashtable of data to send in POST request
 
  .Example
  New-AteraPostRequest -Endpoint "/contacts" -Body @{CustomerID=5; Email="john@example.com"}
  # Create a new Contact
#>

function New-AteraPostRequest {
  [CmdletBinding()]
  param (
    [Parameter(Mandatory)]
    [string] $Endpoint,
    [Parameter(Mandatory, ValueFromPipeline)]
    [Hashtable] $Body
  )
  $Headers = @{
    "accept" = "application/json"
    "X-API-KEY" = Get-AteraAPIKey
  }
  $Uri = "https://app.atera.com/api/v3$($endpoint)"
  Write-Debug "[PSAtera] Request for $Uri"
  $data = Invoke-RestMethod -Uri $Uri -Method "POST" -Headers $Headers -Body $body
  return $data
}

$AteraAPIKey = $env:ATERAAPIKEY
<#
  .Synopsis
  Set the Atera API Key used by the module. If none set, the ATERAAPIKEY environment variable will be used instead.
   
  .Parameter APIKey
  Atera API Key which can be found at https://app.atera.com/Admin#/admin/api
#>

function Set-AteraAPIKey {
  param(
    # Atera API Key
    [string]$APIKey
  )
  $script:AteraAPIKey = $APIKey
}

<#
  .Synopsis
  Get the Atera API Key in use by the module.
#>

function Get-AteraAPIKey {
  if (!$AteraAPIKey) { throw "`$AteraAPIKey not set. Set it with either Set-AteraAPIKey or `$env:ATERAAPIKEY" }
  return $AteraAPIKey
}

$RecordLimit = 1000
<#
  .Synopsis
  Set the maximum number of records returned by API calls. Default is set at 1,000.
 
  .Parameter Limit
  Number of total records returned by Get- command
#>

function Set-AteraRecordLimit {
  param(
    # Maximum records returned
    [Parameter(Mandatory=$true)]
    [int]$Limit
  )
  $script:RecordLimit = $Limit
}
<#
  .Synopsis
  Get the maximum number of records returned by API calls.
#>

function Get-AteraRecordLimit {
  $RecordLimit
}

<#
  .Synopsis
  Installs the Atera Agent for a device
 
  .Parameter Subdomain
  Atera instances subdomain (ex. for https://example.atera.com/GetAgent... the subdomain is 'example')
 
  .Parameter IntegratorLogin
  Your Atera username
 
  .Parameter CustomerID
  Customer ID to assign agent to. If not provided, assigned agent to the Unassigned customer in Atera
 
  .Example
  Install-AteraAgent -Subdomain example -IntegratorLogin john@example.com -CustomerID 2
  # Install agent
 
  .Example
  Get-AteraCustomers | Where CustomerName -eq "Contoso" | Install-AteraAgent -Subdomain example -IntegratorLogin john@example.com
  # Search for a customer to install the agent for
#>

function Install-AteraAgent {
  param (
    [Parameter(Mandatory)]
    [string] $Subdomain,
    [Parameter(Mandatory)]
    [string] $IntegratorLogin,
    [Parameter(ValueFromPipelineByPropertyName)]
    [int] $CustomerID = 0
  )
  if (Get-Service -Name "AteraAgent" -ErrorAction SilentlyContinue) {
    Write-Host "Atera Agent already installed."
    return
  }

  Write-Debug "Downloading Atera Installer"
  $TempFile = Join-Path -Path $env:TEMP -ChildPath "AteraAgent.msi"
  Invoke-WebRequest -Uri "http://$Subdomain.atera.com/GetAgent/Msi/?CustomerID=$CustomerID&IntegratorLogin=$IntegratorLogin" -OutFile $TempFile
  Write-Debug "Installing Atera"
  $proc = Start-Process (Join-Path -Path $env:SystemRoot -ChildPath "system32\msiexec.exe") -PassThru -Wait -ArgumentList "/I","$TempFile","/quiet"
  Write-Host "Exit code: $($proc.ExitCode)"
  if ($proc.ExitCode -eq 0) { Write-Host "Atera Agent installed" -ForegroundColor Green }
  else { Write-Error "Installation failed with exit code $($proc.ExitCode)" -Category InvalidResult }
}

Get-ChildItem -Path $PSScriptRoot/endpoints | ForEach-Object { . $_.PSPath }

Export-ModuleMember -Function Install-AteraAgent,Get-Atera*,Set-Atera*,New-Atera*