cancel
Showing results for 
Search instead for 
Did you mean: 
Disclaimer
JUMPCLOUD EXPRESSLY DISCLAIMS ALL REPRESENTATIONS, WARRANTIES, CONDITIONS, AND LIABILITIES OF ANY KIND ARISING FROM OR RELATED TO THIRD-PARTY SOFTWARE, SCRIPTS, REPOSITORIES, AND APIS. JUMPCLOUD IS NOT REQUIRED TO SUPPORT ANY SUCH THIRD-PARTY MATERIALS AND ALL RISKS RELATED TO THIRD-PARTY MATERIALS ARE YOUR RESPONSIBILITY. PLEASE ALSO REVIEW THE JUMPCLOUD TOS.

[PowerShell] How to spice up Conditional Access Policies (CAP) with Device Posture Attributes

JuergenKlaassen
Rising Star III
Rising Star III

Hi Community Folks

I kept thinking about how I could make use of certain device attributes to enhance Conditional Access Policies. 
As of now your only device related condition is `Disk Encryption`:

SCR-20240216-ofww.png

But what if I want other attributes to be considered such as Policy Status, a specific OS Version or device-level MFA?

What is doable: 
- We can certainly acquire all kinds of attributes from a device by using Get-JCSystem (see screenshot below)
(I could also check for other attributes like applications or SystemInsights) 
- We can iterate through all systems and put them in buckets
- We can lookup the respective users on these systems and 'mark them' as compliant or non-compliant
- We can, based on this marker, put the users into a Dynamic Group
SCR-20240216-oiym.png

 

Currently I can use the 'Description' field of a user to put this marker. A custom attribute would be more elegant. 
In my script for demonstration purposes I came up with the following filters to declare a user as compliant:

SCR-20240216-odhz.png

  1. Device has zero failed policies
  2. Device has zero pending policies
  3. Device-level MFA is enabled
  4. Device is either macOS, Windows or Linux 
  5. Device has be active within the last 30 days
  6. Agent version is at 1.162.1 at least
  7. macOS version is 14.2.1 at least
  8. Device runs on Somona

As you can see, the combination of these attributes doesn't make too much sense, but I wanted to put a bunch of examples together and you can get really creative here.

Once you run this script, each user will get an entry into the description field with a timestamp:

SCR-20240216-okzw.png

Then I can create my Dynamic Group for Compliant users:

SCR-20240216-oltp.png

 Lastly I can utilise this group with a Conditional Access Policy (or for anything else like an SSO Application):

SCR-20240216-omph.png

 

Here is the complete script (and here on my Github):

# Import the JumpCloud Module
Import-Module JumpCloud -Force

# Get all systems
$systems = Get-JCSystem

# Get timestamp
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"

# Initialize dictionaries to hold compliant and non-compliant systems
$compliantSystems = @()
$nonCompliantSystems = @()

# Classify each system as compliant or non-compliant
foreach ($system in $systems) {
    $isCompliant = ($system.policyStats.failed -eq 0) -and
                   ($system.policyStats.pending -eq 0) -and
                   ($system.allowMultiFactorAuthentication -eq $true) -and
                   ((($system.os -eq "Mac OS X") -or ($system.os -eq "Windows") -or ($system.os -eq "Linux")) -and
                    ($system.lastContact -gt (Get-Date).AddDays(-30)) -and
                    ($system.agentVersion -gt "1.162.1") -and
                    ($system.version -gt "14.2.1") -and
                    ($system.osVersionDetail.releaseName -eq "Sonoma"))

    if ($isCompliant) {
        $compliantSystems += $system
    } else {
        $nonCompliantSystems += $system
    }
}

# Function to update user descriptions based on system compliance
function Update-UserDescriptions {
    param (
        $systems,
        $complianceStatus
    )
    foreach ($system in $systems) {
        # Query associated managed users for the current system
        $systemUsers = Get-JCSystemUser -SystemId $system.id

        # Loop through each user
        foreach ($user in $systemUsers) {
            # Extract the username from the user object
            $username = $user.username

            # Verifying we have a username before attempting to set the description
            if (-not [string]::IsNullOrWhiteSpace($username)) {
                $description = "device ${complianceStatus}: ${timestamp}"
                Write-Host "Adding description '$description' to user $username on system $($system.id)."
                Set-JCUser -UserName $username -Description $description
            }
            else {
                Write-Host "User $($user.id) does not have a valid username."
            }
        }
    }
}

# Update descriptions for users with compliant devices
Update-UserDescriptions -systems $compliantSystems -complianceStatus "compliant"

# Update descriptions for users with non-compliant devices
Update-UserDescriptions -systems $nonCompliantSystems -complianceStatus "not compliant"

...and: How about updates? How to ensure that this is frequently checked?

Depending on your specific use case, you can just run this locally on your admin machine, or you start hosting it on AWS Lambda, Azure Functions or you could even run it as a scheduled Command via JumpCloud itself on an administrative host. 

... and of course as usual, before throwing this onto your users: testing testing testing

My assumption here is also: one user has one computer/laptop (best case scenario)

Thanks for reading
-Juergen

 

1 REPLY 1

BrightRodger
JumpCloud Employee
JumpCloud Employee

This is great @JuergenKlaassen , what a great idea!