Public/Initialize-iPilotSession.ps1

Function Initialize-iPilotSession {
    <#
        .Synopsis
        Prompts the user for iPilot credentials including APIKey and storing securely for later sessions

        .Description
        Helper function for iPilot module to retrieve api and credentials either from file, global or prompting the user

        .Parameter ApiUrl
        URL of iPilot API

        .Parameter Credential
        Credentials for iPilot API

        .Parameter APIKey
        iPilot API Key Provided by NuWave

        .Parameter Instance
        iPilot Synthesis Instance

        .Parameter Refresh
        Ask and store new credentials instead of using saved

        .Parameter SaveToFile
        Will save Credentials and ApiKey to iPilot Data Directory

        .Example
        # Get iPilot ApiKey and iPilot Credential and save to iPilot Data Directory
        Initialize-iPilotSession -ApiUrl https://api.nuwave.com -SaveToFile
    #>

    Param (
        [System.String]
            $ApiUrl = "https://api.nuwave.com",   
        [System.String]
            $ApiVersion = "v1",
        [System.String]
            $ApiKey, # if not specified, will prompt user
        [System.String]
            $iPilotDataDirectory = "${env:APPDATA}\NuWave",
        [System.String]
            $Instance,  
        [System.Management.Automation.PSCredential]
            $Credential, # if not specified, will prompt user
        [Switch] 
            $Refresh,
        [Switch] 
            $SaveToFile,
        [Switch]
            $Verbose,
        [Switch]
            $Debug
    )

    # Verbose Switch
    if($PSBoundParameters.containskey("Verbose")) {
        $PreviousVerbosePreference = $VerbosePreference
        $VerbosePreference = "continue"
    }

    # Debug Switch
    if($PSBoundParameters.containskey("Debug")) {
        $PreviousDebugPreference = $DebugPreference
        $DebugPreference = "continue"
    }

    # Set API URL
    $global:IP_ApiUrl = $ApiUrl
    Write-Debug "ApiUrl: $ApiUrl"

    # Set API Version
    $global:IP_ApiVersion = $ApiVersion
    Write-Debug "ApiVersion: $ApiVersion"

    # if oauth iPilotOAuthToken is valid and not expired, nothing for us to do unless explicitly told to refresh
    if ($global:IP_iPilotOAuthToken -and $global:IP_iPilotApiKey) {
        if (!$Refresh.IsPresent) {
            $now = Get-Date
            if ($global:IP_iPilotOAuthToken.OAuthTokenExpirationDateTime -ge ($now.ToUniversalTime())) {
                Write-Debug "iPilotOAuthToken not expired"
                # nothing to do
                return 
            } else {
                Write-Debug "iPilotOAuthToken expired, renewing token"
            }
        } else {
            Write-Debug "Refreshing iPilotOAuthToken"
            $global:IP_iPilotOAuthToken = $iPilotOAuthToken = $null
        }
    } else {
        Write-Debug "Missing iPilotOAuthToken token"
    }

    # make company directory in user profile to store files
    if ( !(Test-Path -Path "$iPilotDataDirectory") ) {
        New-Item -ItemType Directory -Force -Path $iPilotDataDirectory | Out-Null
    }

    if ($ApiKey -or $Credential) {
        Write-Debug "Using explicit credentials and/or ApiKey"
        if (!$ApiKey) {
            Write-Debug "Prompt for ApiKey"
            $ApiKeyCredential = Get-Credential -UserName "ApiKey" -Message "Enter API Key provided to you by NuWave Communications"

            # decrypt the apikey
            $ApiKey = $ApiKeyCredential.GetNetworkCredential().Password
        } else {
            $ApiKeyCredential = New-Object System.Management.Automation.PSCredential ("ApiKey", ($ApiKey | ConvertTo-SecureString -AsPlainText -Force))
        }
        if (!$Credential) {
            Write-Debug "Prompt user for NuWave iPilot credentials"
            $Credential = Get-Credential -Message "Enter NuWave iPilot username and password"
        } 

        # Save ApiKey and iPilot credential
        if ($SaveToFile -and $Instance) {
            Write-Debug "Saving NuWave iPilot credentials to $iPilotDataDirectory\iPilot.cred with instance specified ($Instance)"
            $ApiKeyCredential, $Credential, $Instance | Export-Clixml -Path "$iPilotDataDirectory\iPilot.cred" -Force
        } elseif ($SaveToFile -and !$Instance) {
            Write-Debug "Saving NuWave iPilot credentials to $iPilotDataDirectory\iPilot.cred without instance specified"
            $ApiKeyCredential, $Credential | Export-Clixml -Path "$iPilotDataDirectory\iPilot.cred" -Force
        }
    } else {
        Write-Debug "Prompt or retrieve from iPilot.cred"

        # They didnt specify credentials so either read or prompt the user for apikey and ipilot credentials
        if ( (!$Refresh.IsPresent) -and (Test-Path -Path "$iPilotDataDirectory\iPilot.cred")) {
            Write-Verbose "Reading ApiKey and Credential (and Instance if applicable) from iPilot.cred"
            
            # load credentials from file
            $Clixml = Import-Clixml -Path "$iPilotDataDirectory\iPilot.cred"
            
            # If Instance is saved in Clixml, import into $instance variable, otherwise only import ApiKeyCredential and Credential
            if ($Clixml.Count -eq 3) {
                $ApiKeyCredential, $Credential, $Instance = $Clixml
                Write-Debug "Importing ApiKeyCredential, Credential, & Instance from $iPilotDataDirectory\iPilot.cred"
            } else {
                Write-Debug "Importing ApiKeyCredential & Credential from $iPilotDataDirectory\iPilot.cred"
                $ApiKeyCredential, $Credential = $Clixml
            }

            $global:IP_iPilotApiKeyCredential = $ApiKeyCredential
            $global:IP_iPilotCredential = $Credential
        } else {
            Write-Debug "Asking for ApiKey and Credential"
            $ApiKeyCredential = Get-Credential -UserName "ApiKey" -Message "Enter API Key provided to you by NuWave Communications"
            $Credential = Get-Credential                          -Message "Enter NuWave iPilot username and password"

            # Save ApiKey and iPilot credential
            if ($SaveToFile -and $Instance) {
                Write-Debug "Saving ApiKeyCredential, Credential, & Instance to $iPilotDataDirectory\iPilot.cred"
                $ApiKeyCredential, $Credential, $Instance | Export-Clixml -Path "$iPilotDataDirectory\iPilot.cred" -Force
            } elseif ($SaveToFile -and !$Instance) {
                Write-Debug "Saving ApiKeyCredential, Credential, & Instance to $iPilotDataDirectory\iPilot.cred"
                $ApiKeyCredential, $Credential | Export-Clixml -Path "$iPilotDataDirectory\iPilot.cred" -Force
            }
        }
        # Decrypt the ApiKey
        $ApiKey = $ApiKeyCredential.GetNetworkCredential().Password
    }

    # Create printable version of ApiKey
    if ($ApiKey.length -gt 9) {
        $PrintableApiKey = "..." + $ApiKey.SubString($ApiKey.length - 6) # only grab last 6
    } else {
        $PrintableApiKey = $ApiKey  # not really an ApiKey so print all of it
    }

    # Attempt to log in and get iPilotOAuthToken
    Write-Debug "Logging in user $($Credential.UserName) with ApiKey ending in $PrintableApiKey"
    $GetiPilotOAuthTokenSplat = @{
        Credential = $Credential 
        ApiKey =     $ApiKey 
        ApiUrl =     $ApiUrl 
        ApiVersion = $ApiVersion
    }

    # Add Instance to splat if specified & set global variable
    if ($Instance) {
        Write-Debug "Adding Instance ($Instance) to GetiPilotOAuthTokenSplat"
        $GetiPilotOAuthTokenSplat += @{
            Instance = $Instance
        }

        Write-Verbose "Setting global Instance variable to $Instance"
        $global:IP_Instance = $Instance
    }
    $global:IP_iPilotOAuthToken = Get-iPilotOAuthToken @GetiPilotOAuthTokenSplat
    Write-Debug "GetiPilotOAuthTokenSplat(JSON):$($GetiPilotOAuthTokenSplat | ConvertTo-Json)"
    Write-Verbose "iPilot OAuth Token Expires on: $(Get-Date $global:IP_iPilotOAuthToken.OAuthTokenExpirationDateTime -Format g)"

    # and store the api key since commands need it to prevent user from having to type or specify everytime.
    $global:IP_iPilotApiKey = $ApiKey

    # Verbose Switch
    if($PSBoundParameters.containskey("Verbose")) {
        $VerbosePreference = $PreviousVerbosePreference
    }

    # Debug Switch
    if($PSBoundParameters.containskey("Debug")) {
        $DebugPreference = $PreviousDebugPreference
    }
}