Public/Connect-AtwsWebAPI.ps1
<# .COPYRIGHT Copyright (c) ECIT Solutions AS. All rights reserved. Licensed under the MIT license. See https://github.com/ecitsolutions/Autotask/blob/master/LICENSE.md for license information. #> Function Connect-AtwsWebAPI { <# .SYNOPSIS This function connects to the Autotask Web Services API, authenticates a user and creates a SOAP webservices proxy object. .DESCRIPTION The function takes a credential object and uses it to authenticate and connect to the Autotask Web Services API. This is done by creating a webservices proxy. The proxy object imports the SOAP WSDL definition file, creates all entity classes in PowerShell and exposes the basic methods (query(), create(), update(), remove(), GetEntityInfo(), GetFieldInfo() and a few more). .INPUTS A PSCredential object. Required. It will prompt for credentials if the object is not provided. .OUTPUTS A webserviceproxy object is created. .EXAMPLE Connect-AtwsWebAPI Prompts for a username and password and authenticates to Autotask .EXAMPLE Connect-AtwsWebAPI .NOTES NAME: Connect-AtwsWebAPI .LINK Get-AtwsData #> [cmdletbinding( SupportsShouldProcess = $true, ConfirmImpact = 'Low', DefaultParameterSetName = 'ConfigurationFile' )] Param ( [Parameter( Mandatory = $true, ParameterSetName = 'Parameters' )] [ValidateNotNullOrEmpty()] [pscredential] $Credential, [Parameter( Mandatory = $true, ParameterSetName = 'Parameters' )] [string] $ApiTrackingIdentifier, [Parameter( ParameterSetName = 'Parameters' )] [Alias('Picklist', 'UsePickListLabels')] [switch] $ConvertPicklistIdToLabel, [Parameter( ParameterSetName = 'Parameters' )] [ValidateScript( { # It can be empty, but if it isn't it should be max 8 characters and only letters and numbers if ($_.length -eq 0 -or ($_ -match '[a-zA-Z0-9]' -and $_.length -gt 0 -and $_.length -le 8)) { $true } else { $false } })] [string] $Prefix, [Parameter( ParameterSetName = 'Parameters' )] [switch] $RefreshCache, [Parameter( ParameterSetName = 'Parameters' )] [switch] $NoDiskCache, [Parameter( Mandatory = $true, ParameterSetName = 'ConfigurationObject' )] [ValidateScript( { $requiredProperties = @('Username', 'Securepassword', 'SecureTrackingIdentifier', 'ConvertPicklistIdToLabel', 'Prefix', 'RefreshCache', 'DebugPref', 'VerbosePref', 'ErrorLimit', 'DateConversion', 'PicklistExpansion', 'UdfExpansion') $members = Get-Member -InputObject $_ -MemberType NoteProperty $missingProperties = Compare-Object -ReferenceObject $requiredProperties -DifferenceObject $members.Name -PassThru -ErrorAction SilentlyContinue if (-not($missingProperties)) { $true } else { $missingProperties | ForEach-Object { Throw [System.Management.Automation.ValidationMetadataException] "Property: '$_' missing" } } })] [pscustomobject] [alias('Configuration', 'Profile')] $AtwsModuleConfiguration, [Parameter( ParameterSetName = 'ConfigurationFile' )] [ArgumentCompleter( { param($Cmd, $Param, $Word, $Ast, $FakeBound) $(Get-ChildItem -Path $Global:AtwsModuleConfigurationPath -Filter "*.clixml").FullName })] [ValidateScript( { Test-Path $_ })] [Alias('Path')] [IO.FileInfo] $ProfilePath = $(Join-Path -Path $Global:AtwsModuleConfigurationPath -ChildPath AtwsConfig.clixml), # Name of the Configuration inside the Config file. [Parameter( ParameterSetName = 'ConfigurationFile' )] [ArgumentCompleter( { param($Cmd, $Param, $Word, $Ast, $FakeBound) if (Test-Path $FakeBound.ProfilePath) { [IO.FileInfo]$filepath = $FakeBound.ProfilePath } else { [IO.FileInfo]$filepath = $(Join-Path -Path $Global:AtwsModuleConfigurationPath -ChildPath AtwsConfig.clixml) } $tempsettings = Import-Clixml -Path $filepath.Fullname if ($tempsettings -is [hashtable]) { $tempsettings.keys } })] [alias('Name')] [string] $ProfileName = 'Default' ) begin { # Enable modern -Debug behavior if ($PSCmdlet.MyInvocation.BoundParameters['Debug'].IsPresent) { $DebugPreference = 'Continue' } Write-Verbose ('{0}: Begin of function' -F $MyInvocation.MyCommand.Name) } process { # Make sure we have a valid configuration before we proceed # If we didn't get a prepared configuration object, create one from the parameters try { if ($PSCmdlet.ParameterSetName -eq 'Parameters') { $Parameters = @{ Credential = $Credential SecureTrackingIdentifier = ConvertTo-SecureString $ApiTrackingIdentifier -AsPlainText -Force ConvertPicklistIdToLabel = $ConvertPicklistIdToLabel.IsPresent Prefix = $Prefix RefreshCache = $RefreshCache.IsPresent DebugPref = $DebugPreference VerbosePref = $VerbosePreference } # We cannot reuse $configuration variable without triggering the validationscript # again Write-Verbose ('{0}: Calling New-AtwsModuleConfiguration with $parameters splatting' -F $MyInvocation.MyCommand.Name) $ConfigurationData = New-AtwsModuleConfiguration @Parameters } elseif ($ENV:FUNCTIONS_WORKER_RUNTIME) { # We are probably on Azure and in an azure function to boot. # Can be used locally, too, but that is a secret... try { $UserName = $ENV:AtwsUserName $PassWord = $ENV:AtwsPassword $SecurePass = $PassWord | ConvertTo-SecureString -AsPlainText -Force $Credential = [System.Management.Automation.PSCredential]::new($UserName, $SecurePass ) $TrackingIdentifier = $ENV:AtwsTrackingIdentifier $SecureTrackingIdentifier = $TrackingIdentifier | ConvertTo-SecureString -AsPlainText -Force } catch { $message = 'Unable to get needed variables and convert them from Azure Function Application Settings. Fix and try again.' throw (New-Object System.Configuration.Provider.ProviderException $message) } Write-Verbose ('{0}: Calling New-AtwsModuleConfiguration with variables from Azure Functions application settings.' -F $MyInvocation.MyCommand.Name) $ConfigurationData = New-AtwsModuleConfiguration -Credential $Credential -SecureTrackingIdentifier $SecureTrackingIdentifier } elseif ($env:AUTOMATION_ASSET_ACCOUNTID ) { # We are on Azure. Try to get credentials and api key try { $Credential = Get-AutomationPSCredential -Name 'AtwsDefaultCredential' } catch { $message = "Could not find credentials with name 'AtwsDefaultCredential'. Create and run again." throw (New-Object System.Configuration.Provider.ProviderException $message) return } # Now try for API key try { $SecureIdentifier = Get-AutomationVariable -Name 'AtwsDefaultSecureIdentifier' $SecureIdentifier = $SecureIdentifier | ConvertTo-SecureString -AsPlainText -Force } catch { $message = "Could not a variable with name 'AtwsDefaultSecureIdentifier'. Create and run again." throw (New-Object System.Configuration.Provider.ProviderException $message) return } Write-Verbose ('{0}: Calling New-AtwsModuleConfiguration with variables from Azure Automation resources.' -F $MyInvocation.MyCommand.Name) # There are no $DebugPreferences on Azure Automation. Set explicitly to SlientlyContinue to avoid validation error $ConfigurationData = New-AtwsModuleConfiguration -Credential $Credential -SecureTrackingIdentifier $SecureIdentifier -DebugPref SilentlyContinue } elseif ($PSCmdlet.ParameterSetName -eq 'ConfigurationFile') { Write-Verbose ('{0}: Calling Get-AtwsModuleConfiguration with profilename {1} and path {2}.' -F $MyInvocation.MyCommand.Name, $ProfileName, $ProfilePath) if (-not (Test-Path $ProfilePath)) { $message = "There are no saved connection profiles. Create one and try again." throw (New-Object System.Configuration.Provider.ProviderException $message) } $ConfigurationData = Get-AtwsModuleConfiguration -Name $ProfileName -Path $ProfilePath } elseif (Test-AtwsModuleConfiguration -Configuration $AtwsModuleConfiguration) { # We got a configuration object and it passed validation Write-Verbose ('{0}: Calling New-AtwsModuleConfiguration with a configuration object passed on the command line.' -F $MyInvocation.MyCommand.Name) $ConfigurationData = $AtwsModuleConfiguration } else { Write-Warning ('{0}: Tried to call New-AtwsModuleConfiguration with a configuration object passed on the command line, but the configuration did not validate properly.' -F $MyInvocation.MyCommand.Name) } } catch { # Write a debug message with detailed information to developers $reason = ("{0}: {1}" -f $_.CategoryInfo.Category, $_.CategoryInfo.Reason) $message = "{2}: {0}`r`n`r`nLine:{1}`r`n`r`nScript stacktrace:`r`n{3}" -f $_.Exception.Message, $_.InvocationInfo.Line, $reason, $_.ScriptStackTrace Write-Debug $message # Pass on the error $PSCmdlet.ThrowTerminatingError($_) return } ## Connect to the API # or die trying . Connect-AtwsWebServices -Configuration $ConfigurationData -Erroraction Stop } end { Write-Debug ('{0}: End of function' -F $MyInvocation.MyCommand.Name) } } |