Identity

Secure JumpCloud with cnspec

Scan JumpCloud users, systems, groups, SSO applications, policies, and RADIUS servers against security and compliance best practices with cnspec.

JumpCloud is both the directory that decides who your people are and the management plane that decides what their devices do, so one JumpCloud organization holds the identity posture and the device posture in the same place. cnspec reads a JumpCloud organization through its API and evaluates the user accounts and their multi-factor and lifecycle state, the enrolled systems and their SSH, multi-factor, and full disk encryption settings, the user and system groups that carry access, the SSO applications and the groups that reach them, and the policies, commands, RADIUS servers, and external directory integrations configured in the organization.

cnspec reads directory and device configuration only. It never reads user passwords, SSH private keys, or the contents of managed systems: it queries the JumpCloud API's directory endpoints.

If you're new to cnspec, start with the Quickstart. For an overview of every identity provider cnspec can scan, see the identity scanning overview.

Prerequisites

To scan JumpCloud with cnspec, you must have:

Authenticate

cnspec authenticates with a JumpCloud API key. To create one, sign in to the JumpCloud Admin Portal, open the account menu in the top right, and go to My API Key. The key inherits the permissions of the administrator who owns it, so create it under an account with read access to the resources you want to scan.

cnspec shell jumpcloud --api-key YOUR_API_KEY

Multi-tenant organizations

A multi-tenant (MSP) API key can act on more than one organization, so it can't infer which one you mean. Pass the organization ID alongside the key. You can find it in the Admin Portal under Settings > General.

cnspec shell jumpcloud --api-key YOUR_API_KEY --org-id YOUR_ORG_ID

A single-tenant key resolves its own organization, so --org-id is optional there.

Environment variables

JUMPCLOUD_API_KEY supplies the key, and JUMPCLOUD_ORG_ID supplies the organization ID for a multi-tenant key:

export JUMPCLOUD_API_KEY=YOUR_API_KEY
export JUMPCLOUD_ORG_ID=YOUR_ORG_ID

When these are set, you can omit the matching flags from the commands below.

Connection options

OptionDescription
--api-keyJumpCloud API key
--org-idOrganization ID, required for a multi-tenant (MSP) key

Verify with a quick JumpCloud check

Confirm that cnspec can reach your organization by opening a cnspec shell:

cnspec shell jumpcloud --api-key YOUR_API_KEY
cnspec> jumpcloud.users.length
jumpcloud.users.length: 187

If cnspec connects and reports a user count, you're ready to scan.

Scan JumpCloud

cnspec scan jumpcloud --api-key YOUR_API_KEY

The organization is a single asset. There are no child assets to discover.

When a scan completes, cnspec prints a summary of all the checks it ran, grouped by policy, along with a risk score from 0 (no risk) to 100 (highest risk). Failed checks include remediation guidance to help you fix issues. To learn more about reading scan results, read Understand cnspec Results.

Mondoo doesn't yet ship an out-of-the-box JumpCloud policy, so use the checks below as a starting point and create your own policies to meet your specific requirements.

Explore and test checks interactively

Open a cnspec shell to discover resources and try out checks:

cnspec shell jumpcloud --api-key YOUR_API_KEY

List users and their security posture

state carries the lifecycle stage, and the flags beside it carry the risk:

cnspec> jumpcloud.users { email state activated suspended accountLocked mfaConfigured totpEnabled }

Review who holds administrative rights on systems

sudo grants administrator rights on associated systems, and passwordlessSudo removes the password prompt that would otherwise confirm the person is still there:

cnspec> jumpcloud.users { email sudo passwordlessSudo ldapBindingUser }

List systems and their hardening settings

cnspec> jumpcloud.systems {
    hostname
    os
    version
    agentVersion
    active
    fdeActive
    allowSshRootLogin
    allowSshPasswordAuthentication
    allowMultiFactorAuthentication
  }

Find systems that stopped reporting

lastContact is the last time the agent checked in, so a stale value means the device is off, gone, or no longer managed:

cnspec> jumpcloud.systems { hostname active lastContact remoteIP }

Review the user groups and who's in them

cnspec> jumpcloud.userGroups { name type members { email state } }

Review the system groups and what they contain

System groups are the unit policies and commands bind to, so a group's membership decides which devices a policy actually reaches:

cnspec> jumpcloud.systemGroups { name members { hostname os } }

Review the SSO applications and who reaches them

cnspec> jumpcloud.applications { displayName ssoUrl active userGroups { name } }

Review the policies and whether they're active

cnspec> jumpcloud.policies { name templateName active }

Review the commands and the privileges they run with

A command is remote code execution by design, so the ones that run with sudo on a schedule deserve the most scrutiny:

cnspec> jumpcloud.commands { name commandType launchType sudo timeout }

Review RADIUS authentication

cnspec> jumpcloud.radiusServers { name networkSourceIp mfa }

Review external directory integrations

An integration synchronizes identities from another directory, so it's an inbound path into the organization:

cnspec> jumpcloud.directories { name type }

Walk from a resource to its neighbors

Users, systems, and groups reference each other, so a query can start from any of them and walk in either direction:

cnspec> jumpcloud.users { email userGroups { name } systems { hostname } }
cnspec> jumpcloud.systems { hostname users { email } systemGroups { name } }
cnspec> jumpcloud.userGroups { name members { email } }

Example security checks

Ensure every active user has multi-factor authentication configured

cnspec> jumpcloud.users.where(state == "ACTIVATED").all(mfaConfigured == true)
[ok] value: true

Ensure administrators use multi-factor authentication

An account with sudo on managed systems is the one worth protecting most:

cnspec> jumpcloud.users.where(sudo == true).all(mfaConfigured == true)
[ok] value: true

Ensure no account is granted passwordless sudo

cnspec> jumpcloud.users.none(passwordlessSudo == true)
[ok] value: true

Ensure sudo rights stay rare

cnspec> jumpcloud.users.where(sudo == true).length <= 5
[ok] value: true

Ensure no account is left locked out

A locked account is an unresolved incident or an offboarding nobody finished:

cnspec> jumpcloud.users.none(accountLocked == true)
[ok] value: true

Ensure staged accounts don't linger

A staged account was created but never activated, so it's a seat nobody watches:

cnspec> jumpcloud.users.none(state == "STAGED")
[ok] value: true

Ensure suspended accounts hold no group membership

Suspending an account stops the sign-in. It doesn't remove the access that was granted through groups:

cnspec> jumpcloud.users.where(suspended == true).all(userGroups.length == 0)
[ok] value: true

Ensure no user's password has expired unnoticed

cnspec> jumpcloud.users.where(state == "ACTIVATED").none(passwordExpired == true)
[ok] value: true

Ensure every active system encrypts its disk

Full disk encryption is what makes a lost laptop a lost laptop rather than a breach:

cnspec> jumpcloud.systems.where(active == true).all(fdeActive == true)
[ok] value: true

Ensure no system permits SSH login as root

cnspec> jumpcloud.systems.none(allowSshRootLogin == true)
[ok] value: true

Ensure systems require SSH keys rather than passwords

cnspec> jumpcloud.systems.all(allowSshPasswordAuthentication == false)
[ok] value: true

Ensure systems require multi-factor authentication at the login screen

cnspec> jumpcloud.systems.where(active == true).all(allowMultiFactorAuthentication == true)
[ok] value: true

Ensure RADIUS authentication requires a second factor

RADIUS often fronts the network itself, so a password alone there reaches further than a password elsewhere:

cnspec> jumpcloud.radiusServers.all(mfa == "REQUIRED")
[ok] value: true

Ensure no SSO application is left active without a group behind it

An application no group reaches is either unused or reachable some other way, and both are worth knowing:

cnspec> jumpcloud.applications.where(active == true).all(userGroups.length > 0)
[ok] value: true

Ensure every policy that exists is actually enforced

An inactive policy is a control someone wrote and nobody applied:

cnspec> jumpcloud.policies.all(active == true)
[ok] value: true

Review systems that haven't reported recently

cnspec> jumpcloud.systems.where(active == false) { hostname os lastContact }

Learn more

On this page