Public/Start-LMSessionSyncServer.ps1

Function Start-LMSessionSyncServer {
    Param(
        [Switch]$EnableRequestLogging,
        [Switch]$EnableErrorLogging
    )
    Begin {
        #Ensure we have a vault to use for storing session details
        $VaultName = "Logic.Monitor"

        Try {
            Get-SecretVault -Name $VaultName -ErrorAction Stop | Out-Null
            Write-Host "Existing vault $VaultName already exists, skipping creation" -ForegroundColor Yellow
        }
        Catch {
            If($_.Exception.Message -like "*Vault $VaultName does not exist in registry*") {
                Write-Host "Credential vault for cached accounts does not currently exist, creating credential vault: $VaultName" -ForegroundColor Yellow
                Register-SecretVault -Name $VaultName -ModuleName Microsoft.PowerShell.SecretStore
                Get-SecretStoreConfiguration | Out-Null
            }
        }

    }
    Process{
        #Assuming we got here we can start our session server
        Start-PodeServer {
            #Ensure we have a vault to use for storing session details
            $VaultName = "Logic.Monitor"
            $VaultKeyPrefix = "LMSessionSync"

            #Capture creds so we can use them
            Try{
                Unlock-SecretVault -Name $VaultName -Password $(Read-Host "Enter vault credentials" -AsSecureString -OutVariable VaultCred) -ErrorAction Stop
                Set-PodeState -Name 'VaultUnlock' -Value $VaultCred | Out-Null
            }
            Catch {
                Write-Error "Unable to start SessionSync server without valid vault unlock credentials: $_"
                Return
            }

            #Rotate APIKey in vault
            $ApiKey = (1..64| ForEach-Object {[byte](Get-Random -Max 256)} | ForEach-Object ToString X2) -join ''
            Set-Secret -Name $VaultKeyPrefix-RESTAPIKey -Vault $VaultName -Secret $ApiKey -Metadata @{Modified="$(Get-Date)";Portal="SessionSync-ApiKey"}

            #Sete our web server state
            Set-PodeState -Name 'VaultName' -Value $VaultName | Out-Null
            Set-PodeState -Name 'VaultKeyPrefix' -Value $VaultKeyPrefix | Out-Null
            Set-PodeState -Name 'VaultApiKey' -Value $ApiKey | Out-Null

            Add-PodeEndpoint -Address 127.0.0.1 -Port 8072 -Protocol Http

            If($EnableRequestLogging){New-PodeLoggingMethod -Terminal | Enable-PodeRequestLogging}
            If($EnableErrorLogging){New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging}

            # setup apiKey authentication to validate a user
            New-PodeAuthScheme -ApiKey | Add-PodeAuth -Name 'Auth' -Sessionless -ScriptBlock {
                param($key)

                #Grab current key
                $ApiKey = Get-PodeState -Name 'VaultApiKey'
                
                #Check if user is authenticated
                if ($key.toString() -eq $ApiKey.toString()) {
                    return @{
                        User = @{'ID' ='1'}
                    }
                }

                # authentication failed
                return $null
            }
        
            # check the request on this route against the authentication
            Add-PodeRoute -Method Get -Path '/api/v1/portal/:AccountName' -Authentication 'Auth' -ScriptBlock {
                #Store Session Info in Secret Vault
                $VaultName = Get-PodeState -Name 'VaultName'
                $VaultKeyPrefix = Get-PodeState -Name 'VaultKeyPrefix'
                $VaultUnlock = Get-PodeState -Name 'VaultUnlock'

                Unlock-SecretVault -Name  $VaultName -Password $VaultUnlock

                #Get Session details in vault, return response data
                $AccountName = $WebEvent.Parameters['AccountName']
                Try{
                    $SecretData = Get-Secret -Name $VaultKeyPrefix-$AccountName -Vault  $VaultName -AsPlainText -ErrorAction Stop
                    Write-PodeJsonResponse -Value $SecretData
                }
                Catch{
                    Write-PodeTextResponse -Value "Unexpected error: $($_.Exception.Message)" -StatusCode 500
                    #Set-PodeResponseStatus -Code 500 -Exception "Unexpected error: $($_.Exception.Message)" -NoErrorPage
                }
            }
        
            # this route will not be validated against the authentication
            Add-PodeRoute -Method Post -Path '/api/v1/portal/:AccountName' -ScriptBlock {
                #Store Session Info in Secret Vault
                $VaultName = Get-PodeState -Name 'VaultName'
                $VaultKeyPrefix = Get-PodeState -Name 'VaultKeyPrefix'
                $VaultUnlock = Get-PodeState -Name 'VaultUnlock'

                #Convert request data into JSON and unlock vault
                $SecretData = $($WebEvent.Data | ConvertTo-Json)
                Unlock-SecretVault -Name  $VaultName -Password $VaultUnlock

                #Add/Update Session details in vault, return response data
                $AccountName = $WebEvent.Parameters['AccountName']
                Try{
                    Set-Secret -Name $VaultKeyPrefix-$AccountName -Vault  $VaultName -Secret $SecretData -Metadata @{Modified="$(Get-Date)";Type="SessionSync";Portal=$AccountName}
                    Write-PodeJsonResponse -Value $SecretData
                }
                Catch{
                    Write-PodeTextResponse -Value "Unexpected error: $($_.Exception.Message)" -StatusCode 500
                    #Set-PodeResponseStatus -Code 500 -Exception "Unexpected error: $($_.Exception.Message)" -NoErrorPage
                }
            }

            Register-PodeEvent -Type Terminate -Name 'CleanupSessions' -ScriptBlock {
                $VaultName = Get-PodeState -Name 'VaultName'
                $VaultKeyPrefix = Get-PodeState -Name 'VaultKeyPrefix'
                $VaultUnlock = Get-PodeState -Name 'VaultUnlock'

                Unlock-SecretVault -Name  $VaultName -Password $VaultUnlock
                $Sessions = Get-SecretInfo -Vault $VaultName | Where-Object {$_.Name -like "*$VaultKeyPrefix*"}
                Foreach ($Session in $Sessions){
                    Try{
                        Remove-Secret -Vault $VaultName -Name $Session.Name -ErrorAction Stop
                        Write-Host "Successfully cleared session details for $($Session.Metadata["Portal"])." -ForegroundColor Green
                    }
                    Catch{
                        Write-Error "Unable to clear session details for $($Session.Metadata["Portal"]): $_"
                    }
                }
                Disconnect-LMAccount
            }
        }
    }
    End{}
}