|
################################################ |
|
# |
|
# NOTES |
|
# |
|
################################################ |
|
|
|
|
|
################################################ |
|
# |
|
# SCRIPT ROOT |
|
# |
|
################################################ |
|
|
|
# Load scriptpath |
|
if ($MyInvocation.MyCommand.CommandType -eq "ExternalScript") { |
|
$scriptPath = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition |
|
} else { |
|
$scriptPath = Split-Path -Parent -Path ([Environment]::GetCommandLineArgs()[0]) |
|
} |
|
Set-Location -Path $scriptPath |
|
|
|
|
|
################################################ |
|
# |
|
# SETTINGS |
|
# |
|
################################################ |
|
|
|
# General settings |
|
$settingsFilename = "ionos.json" |
|
|
|
# Request type for calling the api |
|
$requestType = [ordered]@{ |
|
"WebRequest"="(Default) Using WebRequest to get the status code back of last API call, requires Internet Explorer Engine installed (normally installed by default)." |
|
"RestMethod"="Using RestMethod as more modern way of API calls. This does not deliver the status code back, only from PowerShell Core 6 upwards." |
|
} |
|
|
|
################################################ |
|
# |
|
# LOAD FUNCTIONS |
|
# |
|
################################################ |
|
|
|
|
|
Function Get-PlaintextToSecure { |
|
|
|
param( |
|
[Parameter(Mandatory=$true)][String]$String |
|
) |
|
|
|
# generate salt |
|
Create-KeyFile -keyfilename "$( $scriptPath )\aes.key" -byteLength 32 |
|
$salt = Get-Content -Path "$( $scriptPath )\aes.key" -Encoding UTF8 |
|
|
|
# convert |
|
$stringSecure = ConvertTo-secureString -String $String -asplaintext -force |
|
$return = ConvertFrom-SecureString $stringSecure -Key $salt |
|
|
|
# return |
|
$return |
|
|
|
} |
|
|
|
Function Get-SecureToPlaintext { |
|
|
|
param( |
|
[Parameter(Mandatory=$true)][String]$String |
|
) |
|
|
|
# generate salt |
|
$salt = Get-Content -Path "$( $scriptPath )\aes.key" -Encoding UTF8 |
|
|
|
#convert |
|
$stringSecure = ConvertTo-SecureString -String $String -Key $salt |
|
$return = (New-Object PSCredential "dummy",$stringSecure).GetNetworkCredential().Password |
|
|
|
#return |
|
$return |
|
|
|
} |
|
|
|
Function Create-KeyFile { |
|
|
|
param( |
|
[Parameter(Mandatory=$false)][string]$keyfilename = "$( $scriptPath )\aes.key" |
|
,[Parameter(Mandatory=$false)][int]$byteLength = 32 |
|
) |
|
|
|
#$keyfile = ".\$( $keyfilename )" |
|
|
|
# file does not exist -> create one |
|
if ( (Test-Path -Path $keyfilename) -eq $false ) { |
|
$Key = New-Object Byte[] $byteLength # You can use 16, 24, or 32 for AES |
|
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key) |
|
$Key | Set-Content -Encoding UTF8 -Path $keyfilename |
|
} |
|
|
|
|
|
} |
|
|
|
Function Invoke-IONOS { |
|
|
|
param( |
|
[Parameter(Mandatory=$true)][string]$url |
|
,[Parameter(Mandatory=$true)][Hashtable]$headers |
|
,[Parameter(Mandatory=$false)][string]$method = "GET" # TODO [ ] maybe use the method type as an enum |
|
) |
|
|
|
# TODO [ ] maybe use the request type as an enum |
|
|
|
if ( $settings.requestTypeDefault -eq "RestMethod" ) { |
|
|
|
$res = Invoke-RestMethod -Headers $headers -Uri $url -Verbose -Method $method # In Powershell 6 we can directly use Invoke-Restmethod to get the headers |
|
$statusString = "Call is done: $( $res )" |
|
|
|
} else { |
|
|
|
$res = Invoke-WebRequest -Headers $headers -Uri $url -Verbose -Method $method # In Powershell 6 we can directly use Invoke-Restmethod to get the headers |
|
$statusString = "Status $( $res.StatusCode ) with url $( $res.Headers.Location )" |
|
|
|
} |
|
|
|
return $statusString |
|
|
|
} |
|
|
|
|
|
|
|
|
|
################################################ |
|
# |
|
# MANAGE CREDENTIALS |
|
# |
|
################################################ |
|
|
|
|
|
if ( (Test-Path -Path $settingsFilename) -eq $false ) { |
|
|
|
# Ask for default values |
|
$baseDefault = "https://api.ionos.com/cloudapi/v4/" |
|
$base = read-host "Using default API adress? Just press enter for [$( $baseDefault )]" |
|
if ( $null -eq $base ) { |
|
$base = $baseDefault |
|
} |
|
|
|
# Using WebRequest or RestMethod at last API call? |
|
$requestTypeDefault = $requestType | Out-GridView -PassThru |
|
|
|
# Ask for credentials |
|
$username = read-host "Please enter your username" |
|
$password = read-host "Please enter the password" -assecurestring |
|
|
|
# Create credentials object |
|
$cred = @{ |
|
username=$username |
|
password= ( Get-PlaintextToSecure ( $password | convertfrom-securestring )) |
|
} |
|
|
|
# Create settings |
|
$settings = @{ |
|
base = $base |
|
requestTypeDefault = $requestTypeDefault.Name |
|
credentials = $cred |
|
} |
|
|
|
# create json object |
|
$json = $settings | ConvertTo-Json -Depth 8 # -compress |
|
|
|
# print settings to console |
|
$json |
|
|
|
# save settings to file |
|
$json | Set-Content -path "$( $scriptPath )\$( $settingsFilename )" -Encoding UTF8 |
|
|
|
# destroy credentials cache |
|
$username = "" |
|
$password = "" |
|
|
|
} |
|
|
|
|
|
################################################ |
|
# |
|
# PREPARE API CALLS |
|
# |
|
################################################ |
|
|
|
|
|
#----------------------------------------------- |
|
# LOAD SETTINGS |
|
#----------------------------------------------- |
|
|
|
# Load settings |
|
$settings = Get-Content -Path "$( $scriptPath )\$( $settingsFilename )" -Encoding UTF8 -Raw | ConvertFrom-Json |
|
$base = $settings.base |
|
|
|
|
|
#----------------------------------------------- |
|
# LOAD CREDENTIALS |
|
#----------------------------------------------- |
|
|
|
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $settings.credentials.username,(( Get-SecureToPlaintext $settings.credentials.password ) | ConvertTo-SecureString) |
|
|
|
#----------------------------------------------- |
|
# PREPARE HEADER |
|
#----------------------------------------------- |
|
|
|
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f ( $credentials.GetNetworkCredential().Username ),($credentials.GetNetworkCredential().password)))) |
|
$headers = @{ |
|
Authorization=("Basic {0}" -f $base64AuthInfo) |
|
} |
|
|
|
|
|
|
|
################################################ |
|
# |
|
# HANDLE IONOS API |
|
# |
|
################################################ |
|
|
|
|
|
#----------------------------------------------- |
|
# WHAT TO DO? |
|
#----------------------------------------------- |
|
|
|
# operations |
|
$operations = [ordered]@{ |
|
"list"="list all servers" |
|
"start"="start a server" |
|
"stop"="stop a server / end provisioning" |
|
"reboot"="do a hard restart" |
|
"rdp"="remotedesktop" |
|
"nothing"="nothing" |
|
} |
|
|
|
$operation = $operations | Out-GridView -PassThru |
|
|
|
|
|
#----------------------------------------------- |
|
# LOAD DATACENTERS FIRST |
|
#----------------------------------------------- |
|
|
|
# get all datacenters |
|
$datacenters = Invoke-RestMethod -Headers $headers -Uri "$( $base )datacenters?pretty=true&depth=0" -Verbose -Method Get -ContentType "application/json" #| Select -expand companies |
|
|
|
# get details for all datacenters |
|
$datacentersDetail = @() |
|
$datacenters.items | ForEach { |
|
|
|
$url = $_.href |
|
$dc = Invoke-RestMethod -Headers $headers -Uri "$( $url )?pretty=true&depth=4" -Verbose -Method Get -ContentType "application/json" |
|
|
|
$datacentersDetail += $dc |
|
|
|
} |
|
|
|
|
|
#----------------------------------------------- |
|
# BUILD SERVER LIST |
|
#----------------------------------------------- |
|
|
|
# build custom list for all servers |
|
$servers = @() |
|
$nics = @() |
|
$datacentersDetail | ForEach { |
|
|
|
$dataCenterId = $_.id # = New-Object -TypeName PSCustomObject |
|
$dataCenterName = $_.properties.name |
|
|
|
$_.entities.servers.items | ForEach { |
|
|
|
$server = $_.properties.PSObject.Copy() |
|
|
|
$server | Add-Member -Type NoteProperty -Name "datacenterId" -Value $dataCenterId |
|
$server | Add-Member -Type NoteProperty -Name "datacenterName" -Value $dataCenterName |
|
$server | Add-Member -Type NoteProperty -Name "serverId" -Value $_.id |
|
$server | Add-Member -Type NoteProperty -Name "serverHref" -Value $_.href |
|
$server | Add-Member -Type NoteProperty -Name "serverState" -Value $_.metadata.state |
|
$servers += $server |
|
|
|
# build custom list for NICs |
|
$_.entities.nics.items | ForEach { |
|
|
|
$nic = $_.properties.PSObject.Copy() |
|
|
|
$nic | Add-Member -Type NoteProperty -Name "datacenterName" -Value $dataCenterName |
|
$nic | Add-Member -Type NoteProperty -Name "serverName" -Value $server.name |
|
|
|
$nics += $nic |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#----------------------------------------------- |
|
# DO THE OPERATION |
|
#----------------------------------------------- |
|
|
|
switch ( $operation.Name ) { |
|
|
|
"list" { |
|
|
|
$servers | Select datacenterName, name, cores, ram, vmState, serverState, cpuFamily, datacenterId, serverId, serverHref | Out-GridView |
|
|
|
} |
|
|
|
"start" { |
|
|
|
$servers | Select datacenterName, name, cores, ram, vmState, serverState, cpuFamily, datacenterId, serverId, serverHref | where { $_.serverState -eq "INACTIVE" } | Out-GridView -PassThru | ForEach { |
|
|
|
$url = "$( $_.serverHref )/$( $operation.Name )" |
|
|
|
$res = Invoke-IONOS -url $url -headers $headers -method "POST" |
|
"$( $res )" |
|
|
|
} |
|
|
|
} |
|
|
|
"reboot" { |
|
|
|
$servers | Select datacenterName, name, cores, ram, vmState, serverState, cpuFamily, datacenterId, serverId, serverHref | where { $_.serverState -eq "AVAILABLE" } | Out-GridView -PassThru | ForEach { |
|
|
|
$url = "$( $_.serverHref )/$( $operation.Name )" |
|
|
|
$res = Invoke-IONOS -url $url -headers $headers -method "POST" |
|
"$( $res )" |
|
|
|
} |
|
|
|
} |
|
|
|
"stop" { |
|
|
|
$servers | Select datacenterName, name, cores, ram, vmState, serverState, cpuFamily, datacenterId, serverId, serverHref | where { $_.serverState -eq "AVAILABLE" } | Out-GridView -PassThru | ForEach { |
|
|
|
$url = "$( $_.serverHref )/$( $operation.Name )" |
|
|
|
$res = Invoke-IONOS -url $url -headers $headers -method "POST" |
|
"$( $res )" |
|
|
|
} |
|
|
|
} |
|
|
|
"rdp" { |
|
|
|
$nics | Select datacenterName, serverName, name, mac, ips | where { $_.ips -ne "{}" } | Out-GridView -PassThru | ForEach { |
|
|
|
mstsc /v:$($_.ips) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
################################################ |
|
# |
|
# FINISHING |
|
# |
|
################################################ |
|
|
|
# Wait until key pressed |
|
Write-Host "Press any key to continue ..." |
|
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") |
|
|
|
|