Interesting scheduled deployment challenge

Comments

5 comments

  • Christian Ullrich

    Your main problem seems to be to reliably detect when there is actually a user logged on. For that you could use a scheduled task triggered by user login that sends something to your deployment server, telling it to start the deployment via the PDQDeploy.exe command line.

    1
    Comment actions Permalink
  • Rob Oaks

    That's an interesting approach, but devising a secure way for the WorkSpace to run PDQDeploy.exe seems challenging--especially since they exists in different AWS accounts (necessary for security).

    If the paucity of responses is any measure, it really surprises me that more people have not encountered the issue of updating systems where a package must run as the logged in user. Surely that's not so unusual?

     

    1
    Comment actions Permalink
  • Christian Ullrich

    No, I'm not suggesting to run it on the Workspace, but to have the Workspace tell the server that a user just logged on. Just an HTTP request, for example, that somehow causes the server to run PDQDeploy.exe.

    1
    Comment actions Permalink
  • Rob Oaks

    I understand that and, in many contexts, such an HTTP request would be no problem. In our context, however, executing an HTTP request from the AWS WorkSpace account into the AWS admin account containing PDQ is non-trivial. 

    Your idea is a good one, it's just a question of whether it's feasible in our context.

    1
    Comment actions Permalink
  • Rob Oaks

    I have come up with a solution that seems to work reasonably well:

    1. When Deploy updates a WorkSpace, it runs a PowerShell step that creates a machine environment variable, `ItsLastUpdatePackageDeployedDate`, with the ISO date/time as a value
    2. I created the PowerShell scanner listed below, `ReadyForUpdate`, that is triggered via Heartbeat. This scanner determines that a WorkSpace is ready to be updated if a) it has been more than `WaitBetweenUpdatesDays` (set to 7) since the last update and b) the env var, `USERDOMAIN_ROAMINGPROFILE` exists. This env var seems to only exist when a WorkSpace user is actually logged on (of course other approaches could be easily employed). Detection of this env var is repeated in a loop for roughly `TimeoutSecs` (set to 60 to give the user a minute to login after the WorkSpace is online). 
    3. I have a dynamic Inventory collection, `Ready for Update`, that contains WorkSpaces that are ready for update
    4. I have a Deploy schedule for the update package that runs every 10 minutes against the `Ready for Update` collection

    BTW, the update package alerts the user (via message step) at the start and end of the update process but, I will shortly be implementing the ability for the user to cancel the update as per this: https://help.pdq.com/hc/en-us/community/posts/360000252611-Give-logged-on-user-a-choice

    Here is the PowerShell scanner (alas, the indentation was lost when I pasted it):

    [CmdletBinding()]
    param (
    # How long to wait before assuming system is not online or no user is logged on
    [UInt32]$TimeoutSecs = 60,
    # How many days to wait between updates
    [UInt32]$WaitBetweenUpdatesDays = 7
    )

    Write-Verbose "TimeoutSecs = [$TimeoutSecs], WaitBetweenUpdatesDays = [$WaitBetweenUpdatesDays]"

    $loggedOn = $false

    for($i = 1; $i -le $TimeoutSecs; $i++) {
    if ($env:USERDOMAIN_ROAMINGPROFILE -ne $null) {
    $loggedOn = $true
    Write-Verbose "Found `USERDOMAIN_ROAMINGPROFILE` on attempt #$i"
    break
    }
    Write-Verbose "Failed to find `USERDOMAIN_ROAMINGPROFILE` on attempt #$i"
    Start-Sleep -s 1
    }

    $updateRequired = $false

    if ($loggedOn -eq $true) {
    $daysSinceLastUpdate = 0
    $lastUpdateDt = $env:ItsLastUpdatePackageDeployedDate
    if ($lastUpdateDt -ne $null) {
    $lastUpdateDate = [datetime]::Parse($env:ItsLastUpdatePackageDeployedDate)
    Write-Verbose "lastUpdateDate = [$lastUpdateDate]"
    if ($lastUpdateDate -ne $null) {
    $nowIso = Get-Date -format s
    $nowDt = [datetime]::Parse($nowIso)
    $ts = New-TimeSpan -Start $lastUpdateDate -End $nowDt
    $daysSinceLastUpdate = $ts.Days
    }
    Write-Verbose "daysSinceLastUpdate = [$daysSinceLastUpdate]"
    if ($daysSinceLastUpdate -ge $WaitBetweenUpdatesDays) {
    $updateRequired = $true
    }
    }
    else {
    $updateRequired = $true
    }
    }

    $readyForUpdate = $loggedOn -and $updateRequired


    [PSCustomObject]@{
    "ReadyForUpdate" = $readyForUpdate
    }

    1
    Comment actions Permalink

Please sign in to leave a comment.